[amazonechoontrol] fix announcement without speak (#9213)
* fix announcement without speak * improve code Signed-off-by: Jan N. Klug <jan.n.klug@rub.de>
This commit is contained in:
parent
33faa51d7c
commit
b27ddbe9fc
|
@ -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<Integer, Announcement> announcements = Collections.synchronizedMap(new LinkedHashMap<>());
|
||||
private Map<Integer, AnnouncementWrapper> announcements = Collections.synchronizedMap(new LinkedHashMap<>());
|
||||
private Map<Integer, TextToSpeech> textToSpeeches = Collections.synchronizedMap(new LinkedHashMap<>());
|
||||
private Map<Integer, Volume> volumes = Collections.synchronizedMap(new LinkedHashMap<>());
|
||||
private Map<String, LinkedBlockingQueue<QueueObject>> 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<Announcement> iterator = announcements.values().iterator();
|
||||
Iterator<AnnouncementWrapper> iterator = announcements.values().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Announcement announcement = iterator.next();
|
||||
AnnouncementWrapper announcement = iterator.next();
|
||||
try {
|
||||
List<Device> devices = announcement.devices;
|
||||
if (!devices.isEmpty()) {
|
||||
String speak = announcement.speak;
|
||||
String bodyText = announcement.bodyText;
|
||||
String title = announcement.title;
|
||||
JsonAnnouncementContent content = new JsonAnnouncementContent(announcement);
|
||||
|
||||
Map<String, Object> 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>") && speak.endsWith("</speak>")) {
|
||||
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<Device> 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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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<String, Device> 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> 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<Device> updateDeviceList() {
|
||||
|
@ -636,15 +628,8 @@ public class AccountHandler extends BaseBridgeHandler implements IWebSocketComma
|
|||
}
|
||||
if (devices != null) {
|
||||
// create new device map
|
||||
Map<String, Device> 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();
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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("<speak>") && speakText.endsWith("</speak>")) ? "ssml" : "text";
|
||||
value = speakText;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<TargetDevice> devices;
|
||||
|
||||
public JsonAnnouncementTarget(List<JsonDevices.Device> deviceList) {
|
||||
customerId = deviceList.get(0).deviceOwnerCustomerId;
|
||||
devices = deviceList.stream().map(TargetDevice::new).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public static class TargetDevice {
|
||||
public @Nullable String deviceSerialNumber;
|
||||
|
|
Loading…
Reference in New Issue