From b27ddbe9fc86f6de76d818fd95306e8cae38eb4d Mon Sep 17 00:00:00 2001 From: J-N-K Date: Fri, 4 Dec 2020 02:24:56 +0100 Subject: [PATCH] [amazonechoontrol] fix announcement without speak (#9213) * fix announcement without speak * improve code Signed-off-by: Jan N. Klug --- .../internal/Connection.java | 49 ++++++------------- .../ChannelHandlerAnnouncement.java | 2 +- .../channelhandler/IAmazonThingHandler.java | 2 +- .../channelhandler/IEchoThingHandler.java | 2 +- .../internal/handler/AccountHandler.java | 35 ++++--------- .../internal/handler/EchoHandler.java | 2 +- .../jsons/JsonAnnouncementContent.java | 31 +++++++++--- .../jsons/JsonAnnouncementTarget.java | 10 +++- 8 files changed, 62 insertions(+), 71 deletions(-) diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/Connection.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/Connection.java index 14f8607ee..dcc16059f 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/Connection.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/Connection.java @@ -45,7 +45,6 @@ import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import java.util.regex.Matcher; import java.util.regex.Pattern; -import java.util.stream.Collectors; import java.util.zip.GZIPInputStream; import javax.net.ssl.HttpsURLConnection; @@ -56,7 +55,6 @@ import org.openhab.binding.amazonechocontrol.internal.jsons.JsonActivities; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonActivities.Activity; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonAnnouncementContent; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonAnnouncementTarget; -import org.openhab.binding.amazonechocontrol.internal.jsons.JsonAnnouncementTarget.TargetDevice; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonAscendingAlarm; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonAscendingAlarm.AscendingAlarmModel; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonAutomation; @@ -147,7 +145,7 @@ public class Connection { private @Nullable String accountCustomerId; private @Nullable String customerName; - private Map announcements = Collections.synchronizedMap(new LinkedHashMap<>()); + private Map announcements = Collections.synchronizedMap(new LinkedHashMap<>()); private Map textToSpeeches = Collections.synchronizedMap(new LinkedHashMap<>()); private Map volumes = Collections.synchronizedMap(new LinkedHashMap<>()); private Map> devices = Collections.synchronizedMap(new LinkedHashMap<>()); @@ -1313,16 +1311,20 @@ public class Connection { public void announcement(Device device, String speak, String bodyText, @Nullable String title, @Nullable Integer ttsVolume, @Nullable Integer standardVolume) { - if (speak.replaceAll("<.+?>", " ").replaceAll("\\s+", " ").trim().isEmpty()) { + String plainSpeak = speak.replaceAll("<.+?>", " ").replaceAll("\\s+", " ").trim(); + String plainBody = bodyText.replaceAll("<.+?>", " ").replaceAll("\\s+", " ").trim(); + + if (plainSpeak.isEmpty() && plainBody.isEmpty()) { + // if there is neither a bodytext nor (except tags) a speaktext, we have nothing to announce return; } // we lock announcements until we have finished adding this one - Lock lock = locks.computeIfAbsent(TimerType.ANNOUNCEMENT, k -> new ReentrantLock()); + Lock lock = Objects.requireNonNull(locks.computeIfAbsent(TimerType.ANNOUNCEMENT, k -> new ReentrantLock())); lock.lock(); try { - Announcement announcement = Objects.requireNonNull(announcements.computeIfAbsent( - Objects.hash(speak, bodyText, title), k -> new Announcement(speak, bodyText, title))); + AnnouncementWrapper announcement = Objects.requireNonNull(announcements.computeIfAbsent( + Objects.hash(speak, plainBody, title), k -> new AnnouncementWrapper(speak, plainBody, title))); announcement.devices.add(device); announcement.ttsVolumes.add(ttsVolume); announcement.standardVolumes.add(standardVolume); @@ -1340,37 +1342,18 @@ public class Connection { Lock lock = locks.computeIfAbsent(TimerType.ANNOUNCEMENT, k -> new ReentrantLock()); lock.lock(); try { - Iterator iterator = announcements.values().iterator(); + Iterator iterator = announcements.values().iterator(); while (iterator.hasNext()) { - Announcement announcement = iterator.next(); + AnnouncementWrapper announcement = iterator.next(); try { List devices = announcement.devices; if (!devices.isEmpty()) { - String speak = announcement.speak; - String bodyText = announcement.bodyText; - String title = announcement.title; + JsonAnnouncementContent content = new JsonAnnouncementContent(announcement); Map parameters = new HashMap<>(); parameters.put("expireAfter", "PT5S"); - JsonAnnouncementContent[] contentArray = new JsonAnnouncementContent[1]; - JsonAnnouncementContent content = new JsonAnnouncementContent(); - content.display.title = title == null || title.isEmpty() ? "openHAB" : title; - content.display.body = bodyText.replaceAll("<.+?>", " ").replaceAll("\\s+", " ").trim(); - if (speak.startsWith("") && speak.endsWith("")) { - content.speak.type = "ssml"; - } - content.speak.value = speak; - - contentArray[0] = content; - - parameters.put("content", contentArray); - - JsonAnnouncementTarget target = new JsonAnnouncementTarget(); - target.customerId = devices.get(0).deviceOwnerCustomerId; - TargetDevice[] targetDevices = devices.stream().map(TargetDevice::new) - .collect(Collectors.toList()).toArray(new TargetDevice[0]); - target.devices = targetDevices; - parameters.put("target", target); + parameters.put("content", new JsonAnnouncementContent[] { content }); + parameters.put("target", new JsonAnnouncementTarget(devices)); String customerId = getCustomerId(devices.get(0).deviceOwnerCustomerId); if (customerId != null) { @@ -2023,7 +2006,7 @@ public class Connection { true, true, null, 0); } - private static class Announcement { + public static class AnnouncementWrapper { public List devices = new ArrayList<>(); public String speak; public String bodyText; @@ -2031,7 +2014,7 @@ public class Connection { public List<@Nullable Integer> ttsVolumes = new ArrayList<>(); public List<@Nullable Integer> standardVolumes = new ArrayList<>(); - public Announcement(String speak, String bodyText, @Nullable String title) { + public AnnouncementWrapper(String speak, String bodyText, @Nullable String title) { this.speak = speak; this.bodyText = bodyText; this.title = title; diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/channelhandler/ChannelHandlerAnnouncement.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/channelhandler/ChannelHandlerAnnouncement.java index d6bac7712..b063df865 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/channelhandler/ChannelHandlerAnnouncement.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/channelhandler/ChannelHandlerAnnouncement.java @@ -92,7 +92,7 @@ public class ChannelHandlerAnnouncement extends ChannelHandler { body = e.getLocalizedMessage(); } } - thingHandler.startAnnouncment(device, speak, Objects.requireNonNullElse(body, ""), title, volume); + thingHandler.startAnnouncement(device, speak, Objects.requireNonNullElse(body, ""), title, volume); } refreshChannel(); } diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/channelhandler/IAmazonThingHandler.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/channelhandler/IAmazonThingHandler.java index 4a32b6f33..2e910ef45 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/channelhandler/IAmazonThingHandler.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/channelhandler/IAmazonThingHandler.java @@ -31,6 +31,6 @@ public interface IAmazonThingHandler { void updateChannelState(String channelId, State state); - void startAnnouncment(Device device, String speak, String bodyText, @Nullable String title, + void startAnnouncement(Device device, String speak, String bodyText, @Nullable String title, @Nullable Integer volume) throws IOException, URISyntaxException; } diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/channelhandler/IEchoThingHandler.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/channelhandler/IEchoThingHandler.java index 967926ccb..f532c619d 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/channelhandler/IEchoThingHandler.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/channelhandler/IEchoThingHandler.java @@ -26,6 +26,6 @@ import org.openhab.binding.amazonechocontrol.internal.jsons.JsonDevices.Device; */ @NonNullByDefault public interface IEchoThingHandler extends IAmazonThingHandler { - void startAnnouncment(Device device, String speak, String bodyText, @Nullable String title, + void startAnnouncement(Device device, String speak, String bodyText, @Nullable String title, @Nullable Integer volume) throws IOException, URISyntaxException; } diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/handler/AccountHandler.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/handler/AccountHandler.java index 09713617f..20a45423c 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/handler/AccountHandler.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/handler/AccountHandler.java @@ -25,12 +25,12 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.Optional; import java.util.Set; import java.util.concurrent.CopyOnWriteArraySet; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; @@ -198,11 +198,11 @@ public class AccountHandler extends BaseBridgeHandler implements IWebSocketComma } @Override - public void startAnnouncment(Device device, String speak, String bodyText, @Nullable String title, + public void startAnnouncement(Device device, String speak, String bodyText, @Nullable String title, @Nullable Integer volume) throws IOException, URISyntaxException { EchoHandler echoHandler = findEchoHandlerBySerialNumber(device.serialNumber); if (echoHandler != null) { - echoHandler.startAnnouncment(device, speak, bodyText, title, volume); + echoHandler.startAnnouncement(device, speak, bodyText, title, volume); } } @@ -596,12 +596,10 @@ public class AccountHandler extends BaseBridgeHandler implements IWebSocketComma } public @Nullable Device findDeviceJson(@Nullable String serialNumber) { - Device result = null; - if (serialNumber != null && !serialNumber.isEmpty()) { - Map jsonSerialNumberDeviceMapping = this.jsonSerialNumberDeviceMapping; - result = jsonSerialNumberDeviceMapping.get(serialNumber); + if (serialNumber == null || serialNumber.isEmpty()) { + return null; } - return result; + return this.jsonSerialNumberDeviceMapping.get(serialNumber); } public @Nullable Device findDeviceJsonBySerialOrName(@Nullable String serialOrName) { @@ -609,15 +607,9 @@ public class AccountHandler extends BaseBridgeHandler implements IWebSocketComma return null; } - Optional device = this.jsonSerialNumberDeviceMapping.values().stream().filter( + return this.jsonSerialNumberDeviceMapping.values().stream().filter( d -> serialOrName.equalsIgnoreCase(d.serialNumber) || serialOrName.equalsIgnoreCase(d.accountName)) - .findFirst(); - - if (device.isPresent()) { - return device.get(); - } else { - return null; - } + .findFirst().orElse(null); } public List updateDeviceList() { @@ -636,15 +628,8 @@ public class AccountHandler extends BaseBridgeHandler implements IWebSocketComma } if (devices != null) { // create new device map - Map newJsonSerialDeviceMapping = new HashMap<>(); - for (Device device : devices) { - String serialNumber = device.serialNumber; - if (serialNumber != null) { - newJsonSerialDeviceMapping.put(serialNumber, device); - } - - } - jsonSerialNumberDeviceMapping = newJsonSerialDeviceMapping; + jsonSerialNumberDeviceMapping = devices.stream().filter(device -> device.serialNumber != null) + .collect(Collectors.toMap(d -> Objects.requireNonNull(d.serialNumber), d -> d)); } WakeWord[] wakeWords = currentConnection.getWakeWords(); diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/handler/EchoHandler.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/handler/EchoHandler.java index 25c74419c..89deefaaf 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/handler/EchoHandler.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/handler/EchoHandler.java @@ -713,7 +713,7 @@ public class EchoHandler extends BaseThingHandler implements IEchoThingHandler { } @Override - public void startAnnouncment(Device device, String speak, String bodyText, @Nullable String title, + public void startAnnouncement(Device device, String speak, String bodyText, @Nullable String title, @Nullable Integer volume) throws IOException, URISyntaxException { Connection connection = this.findConnection(); if (connection == null) { diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonAnnouncementContent.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonAnnouncementContent.java index c5a0386ea..bc3048e7c 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonAnnouncementContent.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonAnnouncementContent.java @@ -14,27 +14,42 @@ package org.openhab.binding.amazonechocontrol.internal.jsons; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; +import org.openhab.binding.amazonechocontrol.internal.Connection; /** - * The {@link JsonActivity} encapsulate the GSON data of the sequence command AlexaAnnouncement for sending + * The {@link JsonAnnouncementContent} encapsulate the GSON data of the sequence command AlexaAnnouncement for sending * announcements * * @author Michael Geramb - Initial contribution */ @NonNullByDefault public class JsonAnnouncementContent { - public String locale = ""; - public final Display display = new Display(); - public final Speak speak = new Speak(); + public Display display; + public Speak speak; + + public JsonAnnouncementContent(Connection.AnnouncementWrapper announcement) { + display = new Display(announcement.bodyText, announcement.title); + speak = new Speak(announcement.speak); + } public static class Display { - public @Nullable String title; - public @Nullable String body; + public String title; + public String body; + + public Display(String body, @Nullable String title) { + this.body = body; + this.title = (title == null || title.isEmpty() ? "openHAB" : title); + } } public static class Speak { - public String type = "text"; - public @Nullable String value; + public String type; + public String value; + + public Speak(String speakText) { + type = (speakText.startsWith("") && speakText.endsWith("")) ? "ssml" : "text"; + value = speakText; + } } } diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonAnnouncementTarget.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonAnnouncementTarget.java index be0c8c82e..31c7350ee 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonAnnouncementTarget.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonAnnouncementTarget.java @@ -12,6 +12,9 @@ */ package org.openhab.binding.amazonechocontrol.internal.jsons; +import java.util.List; +import java.util.stream.Collectors; + import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; @@ -25,7 +28,12 @@ import org.eclipse.jdt.annotation.Nullable; public class JsonAnnouncementTarget { public @Nullable String customerId; - public @Nullable TargetDevice @Nullable [] devices; + public List devices; + + public JsonAnnouncementTarget(List deviceList) { + customerId = deviceList.get(0).deviceOwnerCustomerId; + devices = deviceList.stream().map(TargetDevice::new).collect(Collectors.toList()); + } public static class TargetDevice { public @Nullable String deviceSerialNumber;