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;
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;
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<>());
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);
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) {
true, true, null, 0);
}
- private static class Announcement {
+ public static class AnnouncementWrapper {
public List<Device> devices = new ArrayList<>();
public String speak;
public String bodyText;
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;
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;
}
@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);
}
}
}
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) {
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() {
}
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();
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;
+ }
}
}