2 * Copyright (c) 2010-2023 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
7 * This program and the accompanying materials are made available under the
8 * terms of the Eclipse Public License 2.0 which is available at
9 * http://www.eclipse.org/legal/epl-2.0
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.amazonechocontrol.internal.channelhandler;
15 import java.io.IOException;
16 import java.net.URISyntaxException;
17 import java.util.Objects;
19 import org.eclipse.jdt.annotation.NonNullByDefault;
20 import org.eclipse.jdt.annotation.Nullable;
21 import org.openhab.binding.amazonechocontrol.internal.Connection;
22 import org.openhab.binding.amazonechocontrol.internal.jsons.JsonDevices.Device;
23 import org.openhab.core.library.types.StringType;
24 import org.openhab.core.types.Command;
25 import org.unbescape.xml.XmlEscape;
27 import com.google.gson.Gson;
28 import com.google.gson.JsonSyntaxException;
31 * The {@link ChannelHandlerAnnouncement} is responsible for the announcement
34 * @author Michael Geramb - Initial contribution
37 public class ChannelHandlerAnnouncement extends ChannelHandler {
39 private static final String CHANNEL_NAME = "announcement";
41 protected final IEchoThingHandler thingHandler;
43 public ChannelHandlerAnnouncement(IEchoThingHandler thingHandler, Gson gson) {
44 super(thingHandler, gson);
45 this.thingHandler = thingHandler;
49 public boolean tryHandleCommand(Device device, Connection connection, String channelId, Command command)
50 throws IOException, URISyntaxException {
51 if (channelId.equals(CHANNEL_NAME)) {
52 if (command instanceof StringType stringCommand) {
53 String commandValue = stringCommand.toFullString();
54 String body = commandValue;
56 String speak = commandValue;
57 Integer volume = null;
58 if (commandValue.startsWith("{") && commandValue.endsWith("}")) {
60 AnnouncementRequestJson request = parseJson(commandValue, AnnouncementRequestJson.class);
61 if (request != null) {
62 speak = request.speak;
63 if (speak == null || speak.length() == 0) {
64 speak = " "; // blank generates a beep
66 volume = request.volume;
67 title = request.title;
72 Boolean sound = request.sound;
74 if (!sound && !speak.startsWith("<speak>")) {
75 speak = "<speak>" + XmlEscape.escapeXml10(speak) + "</speak>";
77 if (sound && speak.startsWith("<speak>")) {
78 body = "Error: The combination of sound and speak in SSML syntax is not allowed";
80 speak = "<speak><lang xml:lang=\"en-UK\">Error: The combination of sound and speak in <prosody rate=\"x-slow\"><say-as interpret-as=\"characters\">SSML</say-as></prosody> syntax is not allowed</lang></speak>";
83 if ("<speak> </speak>".equals(speak)) {
84 volume = -1; // Do not change volume
87 } catch (JsonSyntaxException e) {
88 body = "Invalid Json." + e.getLocalizedMessage();
90 speak = "<speak><lang xml:lang=\"en-US\">" + XmlEscape.escapeXml10(body) + "</lang></speak>";
91 body = e.getLocalizedMessage();
94 thingHandler.startAnnouncement(device, speak, Objects.requireNonNullElse(body, ""), title, volume);
101 private void refreshChannel() {
102 thingHandler.updateChannelState(CHANNEL_NAME, new StringType(""));
105 private static class AnnouncementRequestJson {
106 public @Nullable Boolean sound;
107 public @Nullable String title;
108 public @Nullable String body;
109 public @Nullable String speak;
110 public @Nullable Integer volume;