From 3a1be875551e1db4f1252ef1864963a0c95283a2 Mon Sep 17 00:00:00 2001 From: "Jan N. Klug" Date: Mon, 28 Aug 2023 21:21:49 +0200 Subject: [PATCH] [amazonechocontrol] Fix lastVoiceCommand channel After an API change the lastVoiceCommand channel was no longer working. This introduces manual polling after a voice command was detected. Unfortunately this results in a delay of about 10-15s (compared to the old solution). Signed-off-by: Jan N. Klug --- .../internal/connection/Connection.java | 6 +- .../internal/handler/AccountHandler.java | 59 ++++++++----------- .../internal/handler/EchoHandler.java | 11 +++- .../jsons/JsonCustomerHistoryRecords.java | 5 ++ .../internal/jsons/JsonPushCommand.java | 1 + 5 files changed, 44 insertions(+), 38 deletions(-) diff --git a/bundles/org.smarthomej.binding.amazonechocontrol/src/main/java/org/smarthomej/binding/amazonechocontrol/internal/connection/Connection.java b/bundles/org.smarthomej.binding.amazonechocontrol/src/main/java/org/smarthomej/binding/amazonechocontrol/internal/connection/Connection.java index db8664317b..8a4901b379 100644 --- a/bundles/org.smarthomej.binding.amazonechocontrol/src/main/java/org/smarthomej/binding/amazonechocontrol/internal/connection/Connection.java +++ b/bundles/org.smarthomej.binding.amazonechocontrol/src/main/java/org/smarthomej/binding/amazonechocontrol/internal/connection/Connection.java @@ -29,6 +29,7 @@ import java.util.Arrays; import java.util.Base64; import java.util.Collections; +import java.util.Comparator; import java.util.Date; import java.util.HashMap; import java.util.Iterator; @@ -942,10 +943,11 @@ public List getActivities(@Nullable Long startTime, @Null + (startTime != null ? startTime : "") + "&endTime=" + (endTime != null ? endTime : "") + "&maxRecordSize=1"); JsonCustomerHistoryRecords customerHistoryRecords = parseJson(json, JsonCustomerHistoryRecords.class); - if (customerHistoryRecords == null) { + if (customerHistoryRecords == null || customerHistoryRecords.customerHistoryRecords == null) { return List.of(); } - return Objects.requireNonNullElse(customerHistoryRecords.customerHistoryRecords, List.of()); + return Objects.requireNonNull(customerHistoryRecords.customerHistoryRecords).stream() + .sorted(Comparator.comparing(CustomerHistoryRecord::getTimestamp)).collect(Collectors.toList()); } catch (ConnectionException e) { logger.info("getting activities failed", e); } diff --git a/bundles/org.smarthomej.binding.amazonechocontrol/src/main/java/org/smarthomej/binding/amazonechocontrol/internal/handler/AccountHandler.java b/bundles/org.smarthomej.binding.amazonechocontrol/src/main/java/org/smarthomej/binding/amazonechocontrol/internal/handler/AccountHandler.java index 17f77c0ca9..464c9cff31 100644 --- a/bundles/org.smarthomej.binding.amazonechocontrol/src/main/java/org/smarthomej/binding/amazonechocontrol/internal/handler/AccountHandler.java +++ b/bundles/org.smarthomej.binding.amazonechocontrol/src/main/java/org/smarthomej/binding/amazonechocontrol/internal/handler/AccountHandler.java @@ -65,8 +65,6 @@ import org.smarthomej.binding.amazonechocontrol.internal.jsons.JsonAscendingAlarm.AscendingAlarmModel; import org.smarthomej.binding.amazonechocontrol.internal.jsons.JsonBluetoothStates; import org.smarthomej.binding.amazonechocontrol.internal.jsons.JsonBluetoothStates.BluetoothState; -import org.smarthomej.binding.amazonechocontrol.internal.jsons.JsonCommandPayloadPushActivity; -import org.smarthomej.binding.amazonechocontrol.internal.jsons.JsonCommandPayloadPushActivity.Key; import org.smarthomej.binding.amazonechocontrol.internal.jsons.JsonCommandPayloadPushDevice; import org.smarthomej.binding.amazonechocontrol.internal.jsons.JsonCommandPayloadPushDevice.DopplerId; import org.smarthomej.binding.amazonechocontrol.internal.jsons.JsonCommandPayloadPushNotificationChange; @@ -117,6 +115,7 @@ public class AccountHandler extends BaseBridgeHandler implements WebSocketComman private @Nullable ScheduledFuture checkLoginJob; private @Nullable ScheduledFuture updateSmartHomeStateJob; private @Nullable ScheduledFuture refreshAfterCommandJob; + private @Nullable ScheduledFuture refreshActivityJob; private @Nullable ScheduledFuture refreshSmartHomeAfterCommandJob; private final Object synchronizeSmartHomeJobScheduler = new Object(); private @Nullable ScheduledFuture forceCheckDataJob; @@ -495,8 +494,8 @@ private void refreshNotifications(@Nullable JsonCommandPayloadPushNotificationCh try { List notifications = currentConnection.notifications(); ZonedDateTime timeStampNow = ZonedDateTime.now(); - echoHandlers.forEach(echoHandler -> echoHandler.updateNotifications(timeStamp, timeStampNow, pushPayload, - notifications)); + echoHandlers + .forEach(echoHandler -> echoHandler.updateNotifications(timeStamp, timeStampNow, notifications)); } catch (ConnectionException e) { logger.debug("refreshNotifications failed", e); } @@ -744,9 +743,6 @@ void handleWebsocketCommand(JsonPushCommand pushCommand) { if (command != null) { ScheduledFuture refreshDataDelayed = this.refreshAfterCommandJob; switch (command) { - case "PUSH_ACTIVITY": - handlePushActivity(pushCommand.payload); - break; case "PUSH_DOPPLER_CONNECTION_CHANGE": case "PUSH_BLUETOOTH_STATE_CHANGE": if (refreshDataDelayed != null) { @@ -768,6 +764,15 @@ void handleWebsocketCommand(JsonPushCommand pushCommand) { DopplerId dopplerId = devicePayload.dopplerId; if (dopplerId != null) { handlePushDeviceCommand(dopplerId, command, payload); + if ("PUSH_EQUALIZER_STATE_CHANGE".equals(command)) { + ScheduledFuture refreshActivityJob = this.refreshActivityJob; + if (refreshActivityJob != null) { + refreshActivityJob.cancel(false); + } + this.refreshActivityJob = scheduler.schedule( + () -> handlePushActivity(dopplerId, pushCommand.timeStamp), 10, + TimeUnit.SECONDS); + } } } break; @@ -782,15 +787,8 @@ private void handlePushDeviceCommand(DopplerId dopplerId, String command, String } } - private void handlePushActivity(@Nullable String payload) { - if (payload == null) { - return; - } - JsonCommandPayloadPushActivity pushActivity = Objects - .requireNonNull(gson.fromJson(payload, JsonCommandPayloadPushActivity.class)); - - Key key = pushActivity.key; - if (key == null) { + private void handlePushActivity(@Nullable DopplerId dopplerId, @Nullable Long timestamp) { + if (dopplerId == null) { return; } @@ -799,23 +797,18 @@ private void handlePushActivity(@Nullable String payload) { return; } - Long timestamp = pushActivity.timestamp; - if (timestamp != null) { - long startTimestamp = timestamp - 30000; - long endTimestamp = timestamp + 30000; - List customerHistoryRecords = connection.getActivities(startTimestamp, endTimestamp); - for (CustomerHistoryRecord customerHistoryRecord : customerHistoryRecords) { - String recordKey = customerHistoryRecord.recordKey; - String search = key.registeredUserId + "#" + key.entryId; - if (recordKey != null && search.equals(recordKey)) { - String[] splitRecordKey = recordKey.split("#"); - if (splitRecordKey.length >= 2) { - EchoHandler echoHandler = findEchoHandlerBySerialNumber(splitRecordKey[3]); - if (echoHandler != null) { - echoHandler.handlePushActivity(customerHistoryRecord); - break; - } - } + long real_timestamp = Objects.requireNonNullElse(timestamp, System.currentTimeMillis()); + long startTimestamp = real_timestamp - 120000; + long endTimestamp = real_timestamp + 30000; + + String deviceKey = dopplerId.deviceType + "#" + dopplerId.deviceSerialNumber; + List customerHistoryRecords = connection.getActivities(startTimestamp, endTimestamp); + for (CustomerHistoryRecord customerHistoryRecord : customerHistoryRecords) { + String recordKey = customerHistoryRecord.recordKey; + if (recordKey != null && recordKey.endsWith(deviceKey)) { + EchoHandler echoHandler = findEchoHandlerBySerialNumber(dopplerId.deviceSerialNumber); + if (echoHandler != null) { + echoHandler.handlePushActivity(customerHistoryRecord); } } } diff --git a/bundles/org.smarthomej.binding.amazonechocontrol/src/main/java/org/smarthomej/binding/amazonechocontrol/internal/handler/EchoHandler.java b/bundles/org.smarthomej.binding.amazonechocontrol/src/main/java/org/smarthomej/binding/amazonechocontrol/internal/handler/EchoHandler.java index 32b1ec536b..23cc718d31 100644 --- a/bundles/org.smarthomej.binding.amazonechocontrol/src/main/java/org/smarthomej/binding/amazonechocontrol/internal/handler/EchoHandler.java +++ b/bundles/org.smarthomej.binding.amazonechocontrol/src/main/java/org/smarthomej/binding/amazonechocontrol/internal/handler/EchoHandler.java @@ -67,7 +67,6 @@ import org.smarthomej.binding.amazonechocontrol.internal.jsons.JsonAscendingAlarm.AscendingAlarmModel; import org.smarthomej.binding.amazonechocontrol.internal.jsons.JsonBluetoothStates.BluetoothState; import org.smarthomej.binding.amazonechocontrol.internal.jsons.JsonBluetoothStates.PairedDevice; -import org.smarthomej.binding.amazonechocontrol.internal.jsons.JsonCommandPayloadPushNotificationChange; import org.smarthomej.binding.amazonechocontrol.internal.jsons.JsonCommandPayloadPushVolumeChange; import org.smarthomej.binding.amazonechocontrol.internal.jsons.JsonCustomerHistoryRecords.CustomerHistoryRecord; import org.smarthomej.binding.amazonechocontrol.internal.jsons.JsonCustomerHistoryRecords.CustomerHistoryRecord.VoiceHistoryRecordItem; @@ -116,6 +115,7 @@ public class EchoHandler extends UpdatingBaseThingHandler implements AmazonHandl private @Nullable String lastKnownRadioStationId; private @Nullable String lastKnownBluetoothMAC; private @Nullable String lastKnownAmazonMusicId; + private long lastCustomerHistoryRecordTimestamp = System.currentTimeMillis(); private String musicProviderId = "TUNEIN"; private boolean isPlaying = false; private boolean isPaused = false; @@ -1259,7 +1259,12 @@ private void updateMediaProgress(boolean updateMediaLength) { } } - public void handlePushActivity(CustomerHistoryRecord customerHistoryRecord) { + public synchronized void handlePushActivity(CustomerHistoryRecord customerHistoryRecord) { + long recordTimestamp = customerHistoryRecord.getTimestamp(); + if (recordTimestamp <= lastCustomerHistoryRecordTimestamp) { + return; + } + lastCustomerHistoryRecordTimestamp = recordTimestamp; List voiceHistoryRecordItems = customerHistoryRecord.voiceHistoryRecordItems; if (voiceHistoryRecordItems != null) { for (VoiceHistoryRecordItem voiceHistoryRecordItem : voiceHistoryRecordItems) { @@ -1312,6 +1317,7 @@ public void handlePushCommand(String command, String payload) { default: AccountHandler account = this.account; Device device = this.device; + if (account != null && device != null) { this.disableUpdate = false; updateState(account, device, null, null, null, null, null, null, null); @@ -1320,7 +1326,6 @@ public void handlePushCommand(String command, String payload) { } public void updateNotifications(ZonedDateTime currentTime, ZonedDateTime now, - @Nullable JsonCommandPayloadPushNotificationChange pushPayload, List notifications) { Device device = this.device; if (device == null) { diff --git a/bundles/org.smarthomej.binding.amazonechocontrol/src/main/java/org/smarthomej/binding/amazonechocontrol/internal/jsons/JsonCustomerHistoryRecords.java b/bundles/org.smarthomej.binding.amazonechocontrol/src/main/java/org/smarthomej/binding/amazonechocontrol/internal/jsons/JsonCustomerHistoryRecords.java index 1e99c9c511..ffe04e8f97 100644 --- a/bundles/org.smarthomej.binding.amazonechocontrol/src/main/java/org/smarthomej/binding/amazonechocontrol/internal/jsons/JsonCustomerHistoryRecords.java +++ b/bundles/org.smarthomej.binding.amazonechocontrol/src/main/java/org/smarthomej/binding/amazonechocontrol/internal/jsons/JsonCustomerHistoryRecords.java @@ -13,6 +13,7 @@ package org.smarthomej.binding.amazonechocontrol.internal.jsons; import java.util.List; +import java.util.Objects; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; @@ -51,5 +52,9 @@ public static class VoiceHistoryRecordItem { public @Nullable String agentVisualName; public @Nullable List personsInfo; } + + public long getTimestamp() { + return Objects.requireNonNullElse(timestamp, 0L); + } } } diff --git a/bundles/org.smarthomej.binding.amazonechocontrol/src/main/java/org/smarthomej/binding/amazonechocontrol/internal/jsons/JsonPushCommand.java b/bundles/org.smarthomej.binding.amazonechocontrol/src/main/java/org/smarthomej/binding/amazonechocontrol/internal/jsons/JsonPushCommand.java index ff80d871f7..84cfdc7ef5 100644 --- a/bundles/org.smarthomej.binding.amazonechocontrol/src/main/java/org/smarthomej/binding/amazonechocontrol/internal/jsons/JsonPushCommand.java +++ b/bundles/org.smarthomej.binding.amazonechocontrol/src/main/java/org/smarthomej/binding/amazonechocontrol/internal/jsons/JsonPushCommand.java @@ -25,4 +25,5 @@ public class JsonPushCommand { public @Nullable String command; public @Nullable String payload; + public @Nullable Long timeStamp; }