From 7c839a7c1a25e13fbe5ae926861eb9360e8c8052 Mon Sep 17 00:00:00 2001 From: Michael Geramb Date: Sat, 11 May 2019 13:12:52 +0200 Subject: [PATCH 01/56] [amazonechocontrol] Fix json parsing Signed-off-by: Michael Geramb (github: mgeramb) --- .../amazonechocontrol/internal/Connection.java | 2 +- .../internal/handler/AccountHandler.java | 2 +- .../internal/jsons/JsonActivities.java | 6 +++--- .../jsons/JsonAnnouncementContent.java | 4 ++-- .../internal/jsons/JsonAnnouncementTarget.java | 2 +- .../internal/jsons/JsonAscendingAlarm.java | 2 +- .../internal/jsons/JsonAutomation.java | 4 ++-- .../internal/jsons/JsonBluetoothStates.java | 4 ++-- .../jsons/JsonCommandPayloadPushActivity.java | 2 +- .../jsons/JsonCommandPayloadPushDevice.java | 2 +- .../jsons/JsonDeviceNotificationState.java | 2 +- .../internal/jsons/JsonDevices.java | 2 +- .../jsons/JsonExchangeTokenResponse.java | 6 +++--- .../internal/jsons/JsonMediaState.java | 2 +- .../internal/jsons/JsonPlayerState.java | 12 ++++++------ .../internal/jsons/JsonPlaylists.java | 2 +- .../internal/jsons/JsonRegisterAppRequest.java | 8 ++++---- .../jsons/JsonRegisterAppResponse.java | 18 ++++++++++-------- .../internal/jsons/JsonWakeWords.java | 2 +- 19 files changed, 43 insertions(+), 41 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 052f1b0430cc6..166aecf8276b8 100755 --- 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 @@ -1051,7 +1051,7 @@ public void sendAnnouncement(Device device, String text, @Nullable String title, JsonAnnouncementTarget target = new JsonAnnouncementTarget(); target.customerId = device.deviceOwnerCustomerId; TargetDevice[] devices = new TargetDevice[1]; - TargetDevice deviceTarget = target.new TargetDevice(); + TargetDevice deviceTarget = new TargetDevice(); deviceTarget.deviceSerialNumber = device.serialNumber; deviceTarget.deviceTypeId = device.deviceType; devices[0] = deviceTarget; 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 bc9b622ea1e33..3a3db9cd87cc5 100755 --- 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 @@ -185,7 +185,7 @@ public void addFlashBriefingProfileHandler(FlashBriefingProfileHandler flashBrie flashBriefingProfileHandlers.add(flashBriefingProfileHandler); } Connection connection = this.connection; - if (connection != null) { + if (connection != null && connection.getIsLoggedIn()) { if (currentFlashBriefingJson.isEmpty()) { updateFlashBriefingProfiles(connection); } diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonActivities.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonActivities.java index 910b1f347cf54..b09660af70a1e 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonActivities.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonActivities.java @@ -29,7 +29,7 @@ public class JsonActivities { public @Nullable Activity @Nullable [] activities; - public class Activity { + public static class Activity { public @Nullable String activityStatus; public @Nullable Long creationTimestamp; public @Nullable String description; @@ -45,14 +45,14 @@ public class Activity { public @Nullable String utteranceId; public @Nullable Long version; - public class SourceDeviceId { + public static class SourceDeviceId { public @Nullable String deviceAccountId; public @Nullable String deviceType; public @Nullable String serialNumber; } - public class Description { + public static class Description { public @Nullable String summary; public @Nullable String firstUtteranceId; 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 c33aaa6323d42..ce2296773e417 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 @@ -28,13 +28,13 @@ public class JsonAnnouncementContent { public final Display display = new Display(); public final Speak speak = new Speak(); - public class Display { + public static class Display { public @Nullable String title; public @Nullable String body; } - public class Speak { + public static class Speak { public String type = "text"; public @Nullable String value; 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 fcb8e884541f2..6e99bec84f1c6 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 @@ -26,7 +26,7 @@ public class JsonAnnouncementTarget { public @Nullable String customerId; public @Nullable TargetDevice @Nullable [] devices; - public class TargetDevice { + public static class TargetDevice { public @Nullable String deviceSerialNumber; public @Nullable String deviceTypeId; } diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonAscendingAlarm.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonAscendingAlarm.java index 68ebe7d70d936..95c4d6c81a8a5 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonAscendingAlarm.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonAscendingAlarm.java @@ -25,7 +25,7 @@ public class JsonAscendingAlarm { public @Nullable AscendingAlarmModel @Nullable [] ascendingAlarmModelList; - public class AscendingAlarmModel { + public static class AscendingAlarmModel { public @Nullable Boolean ascendingAlarmEnabled; public @Nullable String deviceSerialNumber; public @Nullable String deviceType; diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonAutomation.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonAutomation.java index 9f9b7cf99faf3..d3be585e7c7f4 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonAutomation.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonAutomation.java @@ -32,13 +32,13 @@ public class JsonAutomation { public long creationTimeEpochMillis; public long lastUpdatedTimeEpochMillis; - public class Trigger { + public static class Trigger { public @Nullable Payload payload; public @Nullable String id; public @Nullable String type; } - public class Payload { + public static class Payload { public @Nullable String customerId; public @Nullable String utterance; public @Nullable String locale; diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonBluetoothStates.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonBluetoothStates.java index 5361887d5afb2..4d2ba0adb07cc 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonBluetoothStates.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonBluetoothStates.java @@ -44,7 +44,7 @@ public class JsonBluetoothStates { public @Nullable BluetoothState @Nullable [] bluetoothStates; - public class PairedDevice { + public static class PairedDevice { public @Nullable String address; public boolean connected; public @Nullable String deviceClass; @@ -53,7 +53,7 @@ public class PairedDevice { } - public class BluetoothState { + public static class BluetoothState { public @Nullable String deviceSerialNumber; public @Nullable String deviceType; public @Nullable String friendlyName; diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonCommandPayloadPushActivity.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonCommandPayloadPushActivity.java index 9fc7800324326..c53128cf0966a 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonCommandPayloadPushActivity.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonCommandPayloadPushActivity.java @@ -28,7 +28,7 @@ public class JsonCommandPayloadPushActivity { public @Nullable Key key; - public class Key { + public static class Key { public @Nullable String entryId; public @Nullable String registeredUserId; } diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonCommandPayloadPushDevice.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonCommandPayloadPushDevice.java index f606635ab5e22..c7b42709229ec 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonCommandPayloadPushDevice.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonCommandPayloadPushDevice.java @@ -25,7 +25,7 @@ public class JsonCommandPayloadPushDevice { public @Nullable DopplerId dopplerId; - public class DopplerId { + public static class DopplerId { public @Nullable String deviceSerialNumber; public @Nullable String deviceType; } diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonDeviceNotificationState.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonDeviceNotificationState.java index 2f0a6ccb7701b..596c172a2048b 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonDeviceNotificationState.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonDeviceNotificationState.java @@ -25,7 +25,7 @@ public class JsonDeviceNotificationState { public @Nullable DeviceNotificationState @Nullable [] deviceNotificationStates; - public class DeviceNotificationState { + public static class DeviceNotificationState { public @Nullable String deviceSerialNumber; public @Nullable String deviceType; public @Nullable String softwareVersion; diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonDevices.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonDevices.java index 16f00449aac06..2ff3a02ad65d1 100755 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonDevices.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonDevices.java @@ -23,7 +23,7 @@ @NonNullByDefault public class JsonDevices { - public class Device { + public static class Device { public @Nullable String accountName; public @Nullable String serialNumber; public @Nullable String deviceOwnerCustomerId; diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonExchangeTokenResponse.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonExchangeTokenResponse.java index e95a1df7a873e..48807bea68910 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonExchangeTokenResponse.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonExchangeTokenResponse.java @@ -26,15 +26,15 @@ public class JsonExchangeTokenResponse { public @Nullable Response response; - public class Response { + public static class Response { public @Nullable Tokens tokens; } - public class Tokens { + public static class Tokens { public @Nullable Map cookies; } - public class Cookie { + public static class Cookie { public @Nullable String Path; public @Nullable Boolean Secure; public @Nullable String Value; diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonMediaState.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonMediaState.java index 69033b938c5e5..0d23fb92d1995 100755 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonMediaState.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonMediaState.java @@ -47,7 +47,7 @@ public class JsonMediaState { // public long timeLastShuffled; parsing fails with some values, so do not use it public int volume; - public class QueueEntry { + public static class QueueEntry { public @Nullable String album; public @Nullable String albumAsin; diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonPlayerState.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonPlayerState.java index 79e4f508b6c97..f3013b518cc13 100755 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonPlayerState.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonPlayerState.java @@ -24,7 +24,7 @@ public class JsonPlayerState { public @Nullable PlayerInfo playerInfo; - public class PlayerInfo { + public static class PlayerInfo { public @Nullable String state; public @Nullable InfoText infoText; public @Nullable InfoText miniInfoText; @@ -37,7 +37,7 @@ public class PlayerInfo { public @Nullable Progress progress; - public class InfoText { + public static class InfoText { public boolean multiLineMode; public @Nullable String subText1; public @Nullable String subText2; @@ -45,24 +45,24 @@ public class InfoText { } - public class Provider { + public static class Provider { public @Nullable String providerDisplayName; public @Nullable String providerName; } - public class Volume { + public static class Volume { public boolean muted; public int volume; } - public class MainArt { + public static class MainArt { public @Nullable String altText; public @Nullable String artType; public @Nullable String contentType; public @Nullable String url; } - public class Progress { + public static class Progress { public @Nullable Boolean allowScrubbing; public @Nullable Object locationInfo; public @Nullable Long mediaLength; diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonPlaylists.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonPlaylists.java index 1e8b8bcdcdeee..d079c686df8c5 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonPlaylists.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonPlaylists.java @@ -27,7 +27,7 @@ public class JsonPlaylists { public @Nullable Map playlists; - public class PlayList { + public static class PlayList { public @Nullable String playlistId; public @Nullable String title; public int trackCount; diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonRegisterAppRequest.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonRegisterAppRequest.java index 54b242a0cf0f1..8b2e2762a22d5 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonRegisterAppRequest.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonRegisterAppRequest.java @@ -38,7 +38,7 @@ public JsonRegisterAppRequest(String serial, String access_token, String frc, Js public UserContextMap user_context_map = new UserContextMap(); public String[] requested_token_type = { "bearer", "mac_dms", "website_cookies" }; - public class Cookies { + public static class Cookies { @Nullable public JsonWebSiteCookie @Nullable [] website_cookies; @Nullable @@ -46,7 +46,7 @@ public class Cookies { } - public class RegistrationData { + public static class RegistrationData { public String domain = "Device"; public String app_version = "2.2.223830.0"; public String device_type = "A2IVLV5VM2W81"; @@ -59,12 +59,12 @@ public class RegistrationData { public String software_version = "1"; } - public class AuthData { + public static class AuthData { @Nullable public String access_token; } - public class UserContextMap { + public static class UserContextMap { public String frc = ""; } } diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonRegisterAppResponse.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonRegisterAppResponse.java index 9c6539c066aca..b2a22649f54ea 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonRegisterAppResponse.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonRegisterAppResponse.java @@ -29,19 +29,21 @@ public class JsonRegisterAppResponse { @Nullable public String request_id; - public class Response { + public static class Response { @Nullable public Success success; } - public class Success { + public static class Success { @Nullable public Extensions extensions; @Nullable public Tokens tokens; + @Nullable + public String customer_id; } - public class Extensions { + public static class Extensions { @Nullable public DeviceInfo device_info; @Nullable @@ -50,7 +52,7 @@ public class Extensions { public String customer_id; } - public class DeviceInfo { + public static class DeviceInfo { @Nullable public String device_name; @Nullable @@ -60,7 +62,7 @@ public class DeviceInfo { } - public class CustomerInfo { + public static class CustomerInfo { @Nullable public String account_pool; @Nullable @@ -73,7 +75,7 @@ public class CustomerInfo { public String given_name; } - public class Tokens { + public static class Tokens { @Nullable public Object website_cookies; @Nullable @@ -82,14 +84,14 @@ public class Tokens { public Bearer bearer; } - public class MacDms { + public static class MacDms { @Nullable public String device_private_key; @Nullable public String adp_token; } - public class Bearer { + public static class Bearer { @Nullable public String access_token; @Nullable diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonWakeWords.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonWakeWords.java index c8af33b41867c..c59a5bca171ab 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonWakeWords.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonWakeWords.java @@ -24,7 +24,7 @@ public class JsonWakeWords { public @Nullable WakeWord @Nullable [] wakeWords; - public class WakeWord { + public static class WakeWord { public @Nullable Boolean active; public @Nullable String deviceSerialNumber; public @Nullable String deviceType; From 35154c11a43fd0d49630d86f34bc36e1442b2559 Mon Sep 17 00:00:00 2001 From: Michael Geramb Date: Sun, 12 May 2019 08:19:52 +0200 Subject: [PATCH 02/56] [amazonechocontrol] Improve error handling Signed-off-by: Michael Geramb (github: mgeramb) --- .../openhab/binding/amazonechocontrol/internal/Connection.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 166aecf8276b8..cf60c7d83c646 100755 --- 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 @@ -809,7 +809,7 @@ public void logout() { private T parseJson(String json, Class type) throws JsonSyntaxException { try { return gson.fromJson(json, type); - } catch (JsonSyntaxException e) { + } catch (JsonSyntaxException | JsonParseException | IllegalStateException e) { logger.warn("Parsing json failed {}", e); logger.warn("Illegal json: {}", json); throw e; From 94494da65440dbe8ee1a48e3edfca2af736f63de Mon Sep 17 00:00:00 2001 From: Michael Geramb Date: Sun, 12 May 2019 10:25:38 +0200 Subject: [PATCH 03/56] [amazonechocontrol] Remove unused Exception Signed-off-by: Michael Geramb (github: mgeramb) Signed-off-by: Michael Geramb --- .../openhab/binding/amazonechocontrol/internal/Connection.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 cf60c7d83c646..37a4c3eda30cf 100755 --- 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 @@ -99,6 +99,7 @@ import com.google.gson.GsonBuilder; import com.google.gson.JsonArray; import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; import com.google.gson.JsonSyntaxException; /** @@ -809,7 +810,7 @@ public void logout() { private T parseJson(String json, Class type) throws JsonSyntaxException { try { return gson.fromJson(json, type); - } catch (JsonSyntaxException | JsonParseException | IllegalStateException e) { + } catch (JsonParseException | IllegalStateException e) { logger.warn("Parsing json failed {}", e); logger.warn("Illegal json: {}", json); throw e; From 611b9fd6ba39a4583ae3018502dd300ba62e0e89 Mon Sep 17 00:00:00 2001 From: Lkn94 Date: Sun, 9 Jun 2019 19:29:50 +0200 Subject: [PATCH 04/56] Original --- .../.classpath | 12 +- .../.project | 18 +- .../README.md | 140 +++--- .../internal/AccountServlet.java | 2 +- .../AmazonEchoControlBindingConstants.java | 29 +- .../AmazonEchoControlHandlerFactory.java | 12 - .../internal/Connection.java | 426 +++--------------- .../internal/WebSocketConnection.java | 13 +- .../internal/handler/AccountHandler.java | 96 ++-- .../internal/handler/EchoHandler.java | 192 +++++++- .../internal/jsons/JsonActivities.java | 6 +- .../jsons/JsonAnnouncementContent.java | 6 +- .../jsons/JsonAnnouncementTarget.java | 2 +- .../internal/jsons/JsonAscendingAlarm.java | 2 +- .../internal/jsons/JsonAutomation.java | 4 +- .../internal/jsons/JsonBluetoothStates.java | 4 +- .../jsons/JsonCommandPayloadPushActivity.java | 2 +- .../jsons/JsonCommandPayloadPushDevice.java | 2 +- .../jsons/JsonDeviceNotificationState.java | 2 +- .../internal/jsons/JsonDevices.java | 2 +- .../jsons/JsonExchangeTokenResponse.java | 6 +- .../internal/jsons/JsonMediaState.java | 2 +- .../jsons/JsonNotificationResponse.java | 4 + .../internal/jsons/JsonPlayerState.java | 12 +- .../internal/jsons/JsonPlaylists.java | 2 +- .../jsons/JsonRegisterAppRequest.java | 8 +- .../jsons/JsonRegisterAppResponse.java | 18 +- .../internal/jsons/JsonWakeWords.java | 2 +- ...onEchoDynamicStateDescriptionProvider.java | 9 +- 29 files changed, 442 insertions(+), 593 deletions(-) diff --git a/bundles/org.openhab.binding.amazonechocontrol/.classpath b/bundles/org.openhab.binding.amazonechocontrol/.classpath index 084e4c97f76f2..a5d95095ccaaf 100755 --- a/bundles/org.openhab.binding.amazonechocontrol/.classpath +++ b/bundles/org.openhab.binding.amazonechocontrol/.classpath @@ -1,14 +1,13 @@ - + + - - + - @@ -19,6 +18,11 @@ + + + + + diff --git a/bundles/org.openhab.binding.amazonechocontrol/.project b/bundles/org.openhab.binding.amazonechocontrol/.project index 29779e20d1765..875f2ada3f4f4 100755 --- a/bundles/org.openhab.binding.amazonechocontrol/.project +++ b/bundles/org.openhab.binding.amazonechocontrol/.project @@ -10,21 +10,6 @@ - - org.eclipse.pde.ManifestBuilder - - - - - org.eclipse.pde.SchemaBuilder - - - - - org.eclipse.pde.ds.core.builder - - - org.eclipse.m2e.core.maven2Builder @@ -32,8 +17,7 @@ - org.eclipse.m2e.core.maven2Nature - org.eclipse.pde.PluginNature org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature diff --git a/bundles/org.openhab.binding.amazonechocontrol/README.md b/bundles/org.openhab.binding.amazonechocontrol/README.md index f4a85122bdda7..9608894b142a5 100755 --- a/bundles/org.openhab.binding.amazonechocontrol/README.md +++ b/bundles/org.openhab.binding.amazonechocontrol/README.md @@ -1,6 +1,6 @@ # Amazon Echo Control Binding -This binding can control Amazon Echo devices (Alexa) and their smart bulbs. +This binding can control Amazon Echo devices (Alexa). It provides features to control and view the current state of echo devices: @@ -23,19 +23,8 @@ It provides features to control and view the current state of echo devices: - start playing music by providing the voice command as text (Works with all music providers) - get last spoken voice command - change the volume of the alarm - -Also this binding includes the features to control your lights connected to your Echo devices: - -- turn on/off your lights -- change the color -- control groups of lights or just single bulbs -- receive the current state of the lights - -Restrictions: - -- groups can't receive their current color (multiple colors are possible) -- lights can only receive their state every 30 seconds -- turning on/off (or switch color, change brightness) will send a request for every single bulb in a group +- change the equalizer settings +- get information about the next alarm, reminder and timer Some ideas what you can do in your home by using rules and other openHAB controlled devices: @@ -50,14 +39,8 @@ Some ideas what you can do in your home by using rules and other openHAB control - Have different flash briefing in the morning and evening - Let alexa say 'welcome' to you if you open the door - Implement own handling for voice commands in a rule - -With the possibility to control your lights you could do: - -- a scene-based configuration of your rooms -- connect single bulbs to functions of openhab -- simulate your presence at home -- automaticly turn on your lights at the evening -- integrate your smart bulbs with rules +- Change the equalizer settings depending on the bluetooth connection +- Turn on a light on your alexa alarm time ## Note @@ -77,8 +60,6 @@ The binding is tested with amazon.de, amazon.fr, amazon.it, amazon.com and amazo | echoshow | Amazon Echo Show Device | | wha | Amazon Echo Whole House Audio Control | | flashbriefingprofile | Flash briefing profile | -| light | Smart bulbs connected to the Echo | -| lightGroup | Groups of lights | ## First Steps @@ -93,9 +74,6 @@ If the device type is not known by the binding, the device will not be discovere But you can define any device listed in your alexa app with the best matching existing device (e.g. echo). You will find the required serial number in settings of the device in the alexa app. -Also you will see your lights in the inbox of openhab. They will automatically be discoverd by openhab based on your amazon login. -If you configured any groups of lights in your amazon alexa app they will be discovered by openhab too. - ## Binding Configuration The binding does not have any configuration. @@ -122,44 +100,48 @@ It will be configured at runtime by using the save channel to store the current ## Channels -| Channel Type ID | Item Type | Access Mode | Thing Type | Description -|-----------------------|-------------|-----------|-------------------------------|----------------------------------------------------------------------- -| player | Player | R/W | echo, echoshow, echospot, wha | Control the music player e.g. pause/continue/next track/previous track -| volume | Dimmer | R/W | echo, echoshow, echospot | Control the volume -| shuffle | Switch | R/W | echo, echoshow, echospot, wha | Shuffle play if applicable, e.g. playing a playlist -| imageUrl | String | R | echo, echoshow, echospot, wha | Url of the album image or radio station logo -| title | String | R | echo, echoshow, echospot, wha | Title of the current media -| subtitle1 | String | R | echo, echoshow, echospot, wha | Subtitle of the current media -| subtitle2 | String | R | echo, echoshow, echospot, wha | Additional subtitle of the current media -| providerDisplayName | String | R | echo, echoshow, echospot, wha | Name of the music provider -| bluetoothMAC | String | R/W | echo, echoshow, echospot | Bluetooth device MAC. Used to connect to a specific device or disconnect if a empty string was provided -| bluetooth | Switch | R/W | echo, echoshow, echospot | Connect/Disconnect to the last used bluetooth device (works after a bluetooth connection was established after the openHAB start) -| bluetoothDeviceName | String | R | echo, echoshow, echospot | User friendly name of the connected bluetooth device -| radioStationId | String | R/W | echo, echoshow, echospot, wha | Start playing of a TuneIn radio station by specifying it's id or stops playing if a empty string was provided -| radio | Switch | R/W | echo, echoshow, echospot, wha | Start playing of the last used TuneIn radio station (works after the radio station started after the openhab start) -| amazonMusicTrackId | String | R/W | echo, echoshow, echospot, wha | Start playing of a Amazon Music track by it's id od stops playing if a empty string was provided +| Channel Type ID | Item Type | Access Mode | Thing Type | Description +|-----------------------|-------------|-------------|------------|------------------------------------------------------------------------------------------ +| player | Player | R/W | echo, echoshow, echospot, wha | Control the music player (Supported commands: PLAY or ON, PAUSE or OFF, NEXT, PREVIOUS, REWIND, FASTFORWARD) +| volume | Dimmer | R/W | echo, echoshow, echospot | Control the volume +| equalizerTreble | Number | R/W | echo, echoshow, echospot | Control the treble (value from -6 to 6) +| equalizerMidrange | Number | R/W | echo, echoshow, echospot | Control the midrange (value from -6 to 6) +| equalizerBass | Number | R/W | echo, echoshow, echospot | Control the bass (value from -6 to 6) +| shuffle | Switch | R/W | echo, echoshow, echospot, wha | Shuffle play if applicable, e.g. playing a playlist +| imageUrl | String | R | echo, echoshow, echospot, wha | Url of the album image or radio station logo +| title | String | R | echo, echoshow, echospot, wha | Title of the current media +| subtitle1 | String | R | echo, echoshow, echospot, wha | Subtitle of the current media +| subtitle2 | String | R | echo, echoshow, echospot, wha | Additional subtitle of the current media +| providerDisplayName | String | R | echo, echoshow, echospot, wha | Name of the music provider +| bluetoothMAC | String | R/W | echo, echoshow, echospot | Bluetooth device MAC. Used to connect to a specific device or disconnect if a empty string was provided +| bluetooth | Switch | R/W | echo, echoshow, echospot | Connect/Disconnect to the last used bluetooth device (works after a bluetooth connection was established after the openHAB start) +| bluetoothDeviceName | String | R | echo, echoshow, echospot | User friendly name of the connected bluetooth device +| radioStationId | String | R/W | echo, echoshow, echospot, wha | Start playing of a TuneIn radio station by specifying it's id or stops playing if a empty string was provided +| radio | Switch | R/W | echo, echoshow, echospot, wha | Start playing of the last used TuneIn radio station (works after the radio station started after the openhab start) +| amazonMusicTrackId | String | R/W | echo, echoshow, echospot, wha | Start playing of a Amazon Music track by it's id od stops playing if a empty string was provided | amazonMusicPlayListId | String | W | echo, echoshow, echospot, wha | Write Only! Start playing of a Amazon Music playlist by specifying it's id od stops playing if a empty string was provided. Selection will only work in PaperUI -| amazonMusic | Switch | R/W | echo, echoshow, echospot, wha | Start playing of the last used Amazon Music song (works after at least one song was started after the openhab start) -| remind | String | R/W | echo, echoshow, echospot | Write Only! Speak the reminder and sends a notification to the Alexa app (Currently the reminder is played and notified two times, this seems to be a bug in the amazon software) -| startRoutine | String | W | echo, echoshow, echospot | Write Only! Type in what you normally say to Alexa without the preceding "Alexa," -| musicProviderId | String | R/W | echo, echoshow, echospot | Current Music provider +| amazonMusic | Switch | R/W | echo, echoshow, echospot, wha | Start playing of the last used Amazon Music song (works after at least one song was started after the openhab start) +| remind | String | R/W | echo, echoshow, echospot | Write Only! Speak the reminder and sends a notification to the Alexa app (Currently the reminder is played and notified two times, this seems to be a bug in the amazon software) +| nextReminder | DateTime | R | echo, echoshow, echospot | Next reminder on the device +| playAlarmSound | String | W | echo, echoshow, echospot | Write Only! Plays ans Alarm sound +| nextAlarm | DateTime | R | echo, echoshow, echospot | Next alarm on the device +| nextMusicAlarm | DateTime | R | echo, echoshow, echospot | Next music alarm on the device +| nextTimer | DateTime | R | echo, echoshow, echospot | Next timer on the device +| startRoutine | String | W | echo, echoshow, echospot | Write Only! Type in what you normally say to Alexa without the preceding "Alexa," +| musicProviderId | String | R/W | echo, echoshow, echospot | Current Music provider | playMusicVoiceCommand | String | W | echo, echoshow, echospot | Write Only! Voice command as text. E.g. 'Yesterday from the Beatles' | startCommand | String | W | echo, echoshow, echospot | Write Only! Used to start anything. Available options: Weather, Traffic, GoodMorning, SingASong, TellStory, FlashBriefing and FlashBriefing. (Note: The options are case sensitive) -| textToSpeech | String | W | echo, echoshow, echospot | Write Only! Write some text to this channel and alexa will speak it +| textToSpeech | String | W | echo, echoshow, echospot | Write Only! Write some text to this channel and alexa will speak it. It is possible to use plain text or SSML: e.g. `I want to tell you a secret.I am not a real human.` | textToSpeechVolume | Dimmer | R/W | echo, echoshow, echospot | Volume of the textToSpeech channel, if 0 the current volume will be used -| lastVoiceCommand | String | R/W | echo, echoshow, echospot | Last voice command spoken to the device. Writing to the channel starts voice output. -| mediaProgress | Dimmer | R/W | echo, echoshow, echospot | Media progress in percent -| mediaProgressTime | Number:Time | R/W | echo, echoshow, echospot | Media play time -| mediaLength | Number:Time | R | echo, echoshow, echospot | Media length -| notificationVolume | Dimmer | R | echo, echoshow, echospot | Notification volume -| ascendingAlarm | Switch | R/W | echo, echoshow, echospot | Ascending alarm up to the configured volume -| save | Switch | W | flashbriefingprofile | Write Only! Stores the current configuration of flash briefings within the thing -| active | Switch | R/W | flashbriefingprofile | Active the profile -| playOnDevice | String | W | flashbriefingprofile | Specify the echo serial number or name to start the flash briefing. -| lightState | Switch | R/W | light, lightGroup | Shows and changes the state (ON/OFF) of your light or lightgroup -| lightBrightness | Dimmer | R/W | light, lightGroup | Shows and changes the brightness of your light or lightgroup -| lightColor | String | R/W | light, lightGroup | Shows and changes the color of your light (groups are not able to show their color!) -| whiteTemperature | String | R/W | light, lightGroup | White temperatures of your lights +| lastVoiceCommand | String | R/W | echo, echoshow, echospot | Last voice command spoken to the device. Writing to the channel starts voice output. +| mediaProgress | Dimmer | R/W | echo, echoshow, echospot | Media progress in percent +| mediaProgressTime | Number:Time | R/W | echo, echoshow, echospot | Media play time +| mediaLength | Number:Time | R | echo, echoshow, echospot | Media length +| notificationVolume | Dimmer | R | echo, echoshow, echospot | Notification volume +| ascendingAlarm | Switch | R/W | echo, echoshow, echospot | Ascending alarm up to the configured volume +| save | Switch | W | flashbriefingprofile | Write Only! Stores the current configuration of flash briefings within the thing +| active | Switch | R/W | flashbriefingprofile | Active the profile +| playOnDevice | String | W | flashbriefingprofile | Specify the echo serial number or name to start the flash briefing. ## Advanced Feature Technically Experienced Users @@ -199,6 +181,9 @@ Group Alexa_Living_Room // Player control Player Echo_Living_Room_Player "Player" (Alexa_Living_Room) {channel="amazonechocontrol:echo:account1:echo1:player"} Dimmer Echo_Living_Room_Volume "Volume [%.0f %%]" (Alexa_Living_Room) {channel="amazonechocontrol:echo:account1:echo1:volume"} +Number Echo_Living_Room_Treble "Treble" (Alexa_Living_Room) {channel="amazonechocontrol:echo:account1:echo1:equalizerTreble"} +Number Echo_Living_Room_Midrange "Midrange" (Alexa_Living_Room) {channel="amazonechocontrol:echo:account1:echo1:equalizerMidrange"} +Number Echo_Living_Room_Bass "Bass" (Alexa_Living_Room) {channel="amazonechocontrol:echo:account1:echo1:equalizerBass"} Switch Echo_Living_Room_Shuffle "Shuffle" (Alexa_Living_Room) {channel="amazonechocontrol:echo:account1:echo1:shuffle"} // Media channels @@ -243,6 +228,11 @@ Switch Echo_Living_Room_AscendingAlarm "Ascending alarm" // Feedbacks String Echo_Living_Room_LastVoiceCommand "Last voice command" (Alexa_Living_Room) {channel="amazonechocontrol:echo:account1:echo1:lastVoiceCommand"} +DateTime Echo_Living_Room_NextReminder "Next reminder" (Alexa_Living_Room) {channel="amazonechocontrol:echo:account1:echo1:nextReminder"} +DateTime Echo_Living_Room_NextAlarm "Next alarm" (Alexa_Living_Room) {channel="amazonechocontrol:echo:account1:echo1:nextAlarm"} +DateTime Echo_Living_Room_NextMusicAlarm "Next music alarm" (Alexa_Living_Room) {channel="amazonechocontrol:echo:account1:echo1:nextMusicAlarm"} +DateTime Echo_Living_Room_NextTimer "Next timer" (Alexa_Living_Room) {channel="amazonechocontrol:echo:account1:echo1:nextTimer"} + // Flashbriefings Switch FlashBriefing_Technical_Save "Save (Write only)" { channel="amazonechocontrol:flashbriefingprofile:account1:flashbriefing1:save"} @@ -252,12 +242,6 @@ String FlashBriefing_Technical_Play "Play (Write only)" { channel="amazonechoc Switch FlashBriefing_LifeStyle_Save "Save (Write only)" { channel="amazonechocontrol:flashbriefingprofile:account1:flashbriefing2:save"} Switch FlashBriefing_LifeStyle_Active "Active" { channel="amazonechocontrol:flashbriefingprofile:account1:flashbriefing2:active"} String FlashBriefing_LifeStyle_Play "Play (Write only)" { channel="amazonechocontrol:flashbriefingprofile:account1:flashbriefing2:playOnDevice"} - -// Lights and lightgroups - you will find the applianceId in the properties of your light or lightgroup! -Switch Light_State "On/Off" { channel="amazonechocontrol:lightGroup:account1:applianceId:lightState" } -Dimmer Light_Brightness "Brightness" { channel="amazonechocontrol:lightGroup:account1:applianceId:lightBrightness" } -String Light_Color "Color" { channel="amazonechocontrol:lightGroup:account1:applianceId:lightColor" } -String Light_White "White temperature" { channel="amazonechocontrol:lightGroup:account1:applianceId:whiteTemperature" } ``` ### amazonechocontrol.sitemap: @@ -268,6 +252,10 @@ sitemap amazonechocontrol label="Echo Devices" Frame label="Alexa" { Default item=Echo_Living_Room_Player Slider item=Echo_Living_Room_Volume + Setpoint item=Echo_Living_Room_Volume minValue=0 maxValue=100 step=5 + Setpoint item=Echo_Living_Room_Treble minValue=-6 maxValue=6 step=1 + Setpoint item=Echo_Living_Room_Midrange minValue=-6 maxValue=6 step=1 + Setpoint item=Echo_Living_Room_Bass minValue=-6 maxValue=6 step=1 Slider item=Echo_Living_Room_MediaProgress Text item=Echo_Living_Room_MediaProgressTime Text item=Echo_Living_Room_MediaLength @@ -318,13 +306,6 @@ sitemap amazonechocontrol label="Echo Devices" Switch item=FlashBriefing_LifeStyle_Active Text item=FlashBriefing_LifeStyle_Play } - - Frame label="Lights and light groups" { - Switch item=Light_State - Slider item=Light_Brightness - Selection item=Light_Color mappings=[ ''='', 'red'='Red', 'crimson'='Crimson', 'salmon'='Salmon', 'orange'='Orange', 'gold'='Gold', 'yellow'='Yellow', 'green'='Green', 'turquoise'='Turquoise', 'cyan'='Cyan', 'sky_blue'='Sky Blue', 'blue'='Blue', 'purple'='Purple', 'magenta'='Magenta', 'pink'='Pink', 'lavender'='Lavender' ] - Selection item=Light_White mappings=[ ''='', 'warm_white'='Warm white', 'soft_white'='Soft white', 'white'='White', 'daylight_white'='Daylight white', 'cool_white'='Cool white' ] - } } ``` @@ -350,6 +331,17 @@ then end ``` +You can also use [SSML](https://docs.aws.amazon.com/polly/latest/dg/supported-ssml.html) to provide a better voice experience + +```php +rule "Say welcome if the door opens" +when + Item Door_Contact changed to OPEN +then + Echo_Living_Room_TTS.sendCommand('I want to tell you a secret.I am not a real human..Can you believe it?') +end +``` + ## Playing an alarm sound for 15 seconds with an openHAB rule if an door contact was opened: 1) Do get the ID of your sound, follow the steps in "How To Get IDs" diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/AccountServlet.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/AccountServlet.java index e977ef38aa323..ad3ef7b7396f9 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/AccountServlet.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/AccountServlet.java @@ -393,7 +393,7 @@ private void handleDefaultPageResult(HttpServletResponse resp, String message, C // device list html.append( - ""); + "
DeviceSerial NumberStateThingTypeFamily
"); for (Device device : this.account.getLastKnownDevices()) { html.append("
DeviceSerial NumberStateThingFamilyType
"); diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/AmazonEchoControlBindingConstants.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/AmazonEchoControlBindingConstants.java index 3aca19e0b336d..258e7ba07ba59 100755 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/AmazonEchoControlBindingConstants.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/AmazonEchoControlBindingConstants.java @@ -42,16 +42,16 @@ public class AmazonEchoControlBindingConstants { public static final ThingTypeUID THING_TYPE_FLASH_BRIEFING_PROFILE = new ThingTypeUID(BINDING_ID, "flashbriefingprofile"); - public static final ThingTypeUID THING_TYPE_LIGHT = new ThingTypeUID(BINDING_ID, "light"); - public static final ThingTypeUID THING_TYPE_LIGHT_GROUP = new ThingTypeUID(BINDING_ID, "lightGroup"); - public static final Set SUPPORTED_THING_TYPES_UIDS = new HashSet( Arrays.asList(THING_TYPE_ACCOUNT, THING_TYPE_ECHO, THING_TYPE_ECHO_SPOT, THING_TYPE_ECHO_SHOW, - THING_TYPE_ECHO_WHA, THING_TYPE_FLASH_BRIEFING_PROFILE, THING_TYPE_LIGHT, THING_TYPE_LIGHT_GROUP)); + THING_TYPE_ECHO_WHA, THING_TYPE_FLASH_BRIEFING_PROFILE)); // List of all Channel ids public static final String CHANNEL_PLAYER = "player"; public static final String CHANNEL_VOLUME = "volume"; + public static final String CHANNEL_EQUALIZER_TREBLE = "equalizerTreble"; + public static final String CHANNEL_EQUALIZER_MIDRANGE = "equalizerMidrange"; + public static final String CHANNEL_EQUALIZER_BASS = "equalizerBass"; public static final String CHANNEL_ERROR = "error"; public static final String CHANNEL_SHUFFLE = "shuffle"; public static final String CHANNEL_LOOP = "loop"; @@ -82,10 +82,10 @@ public class AmazonEchoControlBindingConstants { public static final String CHANNEL_MEDIA_PROGRESS_TIME = "mediaProgressTime"; public static final String CHANNEL_ASCENDING_ALARM = "ascendingAlarm"; public static final String CHANNEL_NOTIFICATION_VOLUME = "notificationVolume"; - public static final String CHANNEL_LIGHT_STATE = "lightState"; - public static final String CHANNEL_LIGHT_COLOR = "lightColor"; - public static final String CHANNEL_LIGHT_WHITE_TEMPERATURE = "whiteTemperature"; - public static final String CHANNEL_LIGHT_BRIGHTNESS = "lightBrightness"; + public static final String CHANNEL_NEXT_REMINDER = "nextReminder"; + public static final String CHANNEL_NEXT_ALARM = "nextAlarm"; + public static final String CHANNEL_NEXT_MUSIC_ALARM = "nextMusicAlarm"; + public static final String CHANNEL_NEXT_TIMER = "nextTimer"; public static final String CHANNEL_SAVE = "save"; public static final String CHANNEL_ACTIVE = "active"; @@ -101,25 +101,12 @@ public class AmazonEchoControlBindingConstants { public static final ChannelTypeUID CHANNEL_TYPE_MUSIC_PROVIDER_ID = new ChannelTypeUID(BINDING_ID, "musicProviderId"); public static final ChannelTypeUID CHANNEL_TYPE_START_COMMAND = new ChannelTypeUID(BINDING_ID, "startCommand"); - public static final ChannelTypeUID CHANNEL_TYPE_LIGHT_COLOR = new ChannelTypeUID(BINDING_ID, "lightColor"); // List of all Properties public static final String DEVICE_PROPERTY_SERIAL_NUMBER = "serialNumber"; public static final String DEVICE_PROPERTY_FAMILY = "deviceFamily"; public static final String DEVICE_PROPERTY_FLASH_BRIEFING_PROFILE = "configurationJson"; - public static final String DEVICE_PROPERTY_APPLIANCE_ID = "applianceId"; - public static final String DEVICE_PROPERTY_LIGHT_ENTITY_ID = "entityId"; - public static final String DEVICE_PROPERTY_LIGHT_SUBDEVICE = "subDevice"; // Other public static final String FLASH_BRIEFING_COMMAND_PREFIX = "FlashBriefing."; - - // List of all smart bulb actions - public static final String DEVICE_TURN_ON = "turnOn"; - public static final String DEVICE_TURN_OFF = "turnOff"; - - // List of Alexa interfaces - public static final String INTERFACE_BRIGHTNESS = "Alexa.BrightnessController"; - public static final String INTERFACE_COLOR_TEMPERATURE = "Alexa.ColorTemperatureController"; - public static final String INTERFACE_COLOR = "Alexa.ColorController"; } diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/AmazonEchoControlHandlerFactory.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/AmazonEchoControlHandlerFactory.java index b454dfaafdfdb..4b7722e52ae07 100755 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/AmazonEchoControlHandlerFactory.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/AmazonEchoControlHandlerFactory.java @@ -31,11 +31,9 @@ import org.eclipse.smarthome.core.thing.binding.ThingHandler; import org.eclipse.smarthome.core.thing.binding.ThingHandlerFactory; import org.openhab.binding.amazonechocontrol.internal.discovery.AmazonEchoDiscovery; -import org.openhab.binding.amazonechocontrol.internal.discovery.SmartHomeDevicesDiscovery; import org.openhab.binding.amazonechocontrol.internal.handler.AccountHandler; import org.openhab.binding.amazonechocontrol.internal.handler.EchoHandler; import org.openhab.binding.amazonechocontrol.internal.handler.FlashBriefingProfileHandler; -import org.openhab.binding.amazonechocontrol.internal.handler.SmartHomeDeviceHandler; import org.osgi.framework.ServiceRegistration; import org.osgi.service.component.ComponentContext; import org.osgi.service.component.annotations.Component; @@ -116,11 +114,6 @@ protected void deactivate(ComponentContext componentContext) { String.class.getClassLoader()); return new FlashBriefingProfileHandler(thing, storage); } - if (thingTypeUID.equals(THING_TYPE_LIGHT) || thingTypeUID.equals(THING_TYPE_LIGHT_GROUP)) { - Storage storage = storageService.getStorage(thing.getUID().toString(), - String.class.getClassLoader()); - return new SmartHomeDeviceHandler(thing, storage); - } if (SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID)) { return new EchoHandler(thing); } @@ -128,11 +121,6 @@ protected void deactivate(ComponentContext componentContext) { } private synchronized void registerDiscoveryService(AccountHandler bridgeHandler) { - SmartHomeDevicesDiscovery smartHomeDevicesDiscovery = new SmartHomeDevicesDiscovery(bridgeHandler); - smartHomeDevicesDiscovery.activate(); - this.discoveryServiceRegistrations.put(bridgeHandler.getThing().getUID(), bundleContext.registerService( - DiscoveryService.class.getName(), smartHomeDevicesDiscovery, new Hashtable())); - AmazonEchoDiscovery discoveryService = new AmazonEchoDiscovery(bridgeHandler); discoveryService.activate(); this.discoveryServiceRegistrations.put(bridgeHandler.getThing().getUID(), bundleContext 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 5fd3ace4fe898..37a4c3eda30cf 100755 --- 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 @@ -12,8 +12,6 @@ */ package org.openhab.binding.amazonechocontrol.internal; -import static org.openhab.binding.amazonechocontrol.internal.AmazonEchoControlBindingConstants.*; - import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -31,7 +29,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Base64; -import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.Hashtable; @@ -40,20 +37,16 @@ import java.util.Map; import java.util.Random; import java.util.Scanner; -import java.util.Set; -import java.util.UUID; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.zip.GZIPInputStream; import javax.net.ssl.HttpsURLConnection; -import javax.xml.bind.DatatypeConverter; import org.apache.commons.lang.StringUtils; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; -import org.eclipse.jetty.util.StringUtil; -import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.util.HexUtils; 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; @@ -65,13 +58,12 @@ import org.openhab.binding.amazonechocontrol.internal.jsons.JsonAutomation.Payload; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonAutomation.Trigger; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonBluetoothStates; -import org.openhab.binding.amazonechocontrol.internal.jsons.JsonColorTemperature; -import org.openhab.binding.amazonechocontrol.internal.jsons.JsonColors; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonDeviceNotificationState; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonDeviceNotificationState.DeviceNotificationState; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonDevices; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonDevices.Device; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonEnabledFeeds; +import org.openhab.binding.amazonechocontrol.internal.jsons.JsonEqualizer; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonExchangeTokenResponse; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonExchangeTokenResponse.Cookie; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonFeed; @@ -81,6 +73,7 @@ import org.openhab.binding.amazonechocontrol.internal.jsons.JsonNotificationResponse; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonNotificationSound; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonNotificationSounds; +import org.openhab.binding.amazonechocontrol.internal.jsons.JsonNotificationsResponse; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonPlaySearchPhraseOperationPayload; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonPlayValidationResult; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonPlayerState; @@ -94,10 +87,6 @@ import org.openhab.binding.amazonechocontrol.internal.jsons.JsonRegisterAppResponse.Success; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonRegisterAppResponse.Tokens; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonRenewTokenResponse; -import org.openhab.binding.amazonechocontrol.internal.jsons.JsonSmartHomeDeviceAlias; -import org.openhab.binding.amazonechocontrol.internal.jsons.JsonSmartHomeDevices; -import org.openhab.binding.amazonechocontrol.internal.jsons.JsonSmartHomeDevices.SmartHomeDevice; -import org.openhab.binding.amazonechocontrol.internal.jsons.JsonSmartHomeGroups.SmartHomeGroup; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonStartRoutineRequest; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonUsersMeResponse; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonWakeWords; @@ -109,9 +98,8 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonArray; -import com.google.gson.JsonElement; import com.google.gson.JsonObject; -import com.google.gson.JsonParser; +import com.google.gson.JsonParseException; import com.google.gson.JsonSyntaxException; /** @@ -170,7 +158,7 @@ public Connection(@Nullable Connection oldConnection) { // generate serial byte[] serialBinary = new byte[16]; rand.nextBytes(serialBinary); - this.serial = DatatypeConverter.printHexBinary(serialBinary); + this.serial = HexUtils.bytesToHex(serialBinary); } if (deviceId != null) { this.deviceId = deviceId; @@ -481,7 +469,7 @@ public HttpsURLConnection makeRequest(String verb, String url, @Nullable String if (customHeaders != null) { for (String key : customHeaders.keySet()) { String value = customHeaders.get(key); - if (!StringUtil.isBlank(value)) { + if (StringUtils.isNotEmpty(value)) { connection.setRequestProperty(key, value); } } @@ -822,7 +810,7 @@ public void logout() { private T parseJson(String json, Class type) throws JsonSyntaxException { try { return gson.fromJson(json, type); - } catch (JsonSyntaxException e) { + } catch (JsonParseException | IllegalStateException e) { logger.warn("Parsing json failed {}", e); logger.warn("Illegal json: {}", json); throw e; @@ -846,126 +834,6 @@ public WakeWord[] getWakeWords() { return new WakeWord[0]; } - public List getSmarthomeDeviceList() throws IOException, URISyntaxException { - JsonObject json = new JsonParser().parse(getSmarthomeDeviceListJson()).getAsJsonObject(); - JsonObject smartHomeDevices = json.get("networkDetail").getAsJsonObject().get("locationDetails") - .getAsJsonObject().get("locationDetails").getAsJsonObject().get("Default_Location").getAsJsonObject() - .get("amazonBridgeDetails").getAsJsonObject().get("amazonBridgeDetails").getAsJsonObject() - .get("LambdaBridge_AAA/SonarCloudService").getAsJsonObject().get("applianceDetails").getAsJsonObject() - .get("applianceDetails").getAsJsonObject(); - ArrayList smartHomeDeviceArray = new ArrayList<>(); - Set keys = smartHomeDevices.keySet(); - for (String key : keys) { - JsonObject keyObject = smartHomeDevices.get(key).getAsJsonObject(); - SmartHomeDevice shd = parseJson(keyObject.toString(), SmartHomeDevice.class); - if (keyObject.get("aliases").getAsJsonArray().size() > 0) { - shd.alias = new JsonSmartHomeDeviceAlias[1]; - shd.alias[0] = new JsonSmartHomeDeviceAlias( - keyObject.get("aliases").getAsJsonArray().get(0).getAsJsonObject().get("friendlyName") - .getAsString(), - keyObject.get("aliases").getAsJsonArray().get(0).getAsJsonObject().get("enabled") - .getAsBoolean()); - } - if (keyObject.get("tags").getAsJsonObject().get("tagNameToValueSetMap").getAsJsonObject().size() > 0) { - shd.groupIdentity = keyObject.get("tags").getAsJsonObject().get("tagNameToValueSetMap") - .getAsJsonObject().get("groupIdentity").getAsJsonArray().get(0).getAsString(); - } - if (keyObject.get("capabilities").getAsJsonArray().size() > 0) { - for (JsonElement obj : keyObject.get("capabilities").getAsJsonArray()) { - String interfaceName = ((JsonObject) obj).get("interfaceName").getAsString(); - if (interfaceName.equals(INTERFACE_BRIGHTNESS)) { - shd.brightness = true; - } else if (interfaceName.equals(INTERFACE_COLOR_TEMPERATURE)) { - shd.colorTemperature = true; - } else if (interfaceName.equals(INTERFACE_COLOR)) { - shd.color = true; - } - } - } - smartHomeDeviceArray.add(shd); - } - - List groups = this.getSmarthomeDeviceGroups(); - - for (SmartHomeGroup group : groups) { - String uuid = UUID.randomUUID().toString(); - JsonSmartHomeDeviceAlias[] alias = new JsonSmartHomeDeviceAlias[1]; - ArrayList smartDevices = new ArrayList<>(); - - for (int i = 0; i < smartHomeDeviceArray.size(); ++i) { - if (smartHomeDeviceArray.get(i).groupIdentity != null && group.applianceGroupIdentifier.value != null) { - if (smartHomeDeviceArray.get(i).groupIdentity.equals(group.applianceGroupIdentifier.value)) { - smartDevices.add(smartHomeDeviceArray.get(i)); - if (group.applianceGroupName != null) { - alias[0] = new JsonSmartHomeDeviceAlias(group.applianceGroupName, true); - } - } - } - } - - SmartHomeDevice[] smartDevicesArray = new SmartHomeDevice[smartDevices.size()]; - smartDevices.toArray(smartDevicesArray); - - if (group.applianceGroupName != null) { - SmartHomeDevice shdGroup = new JsonSmartHomeDevices().new SmartHomeDevice(uuid, "Amazon", - "Amazon Light Group", group.applianceGroupName, "reachable", uuid, alias, smartDevicesArray); - - smartHomeDeviceArray.add(shdGroup); - } - - } - - if (smartHomeDeviceArray.isEmpty()) { - return new ArrayList<>(); - } - - return smartHomeDeviceArray; - } - - public List getSmarthomeDeviceGroups() throws IOException, URISyntaxException { - JsonObject json = new JsonParser().parse(getSmarthomeDeviceListJson()).getAsJsonObject(); - JsonObject smartHomeGroups = json.get("networkDetail").getAsJsonObject().get("locationDetails") - .getAsJsonObject().get("locationDetails").getAsJsonObject().get("Default_Location").getAsJsonObject() - .get("applianceGroups").getAsJsonObject().get("applianceGroups").getAsJsonObject(); - ArrayList smartHomeGroupArray = new ArrayList<>(); - Set keys = smartHomeGroups.keySet(); - for (String key : keys) { - JsonObject keyObject = smartHomeGroups.get(key).getAsJsonObject(); - SmartHomeGroup shg = parseJson(keyObject.toString(), SmartHomeGroup.class); - - smartHomeGroupArray.add(shg); - } - - if (smartHomeGroupArray.isEmpty()) { - return new ArrayList<>(); - } - - return smartHomeGroupArray; - } - - // Placeholder for an api-request - public List getEchoLightColors() { - ArrayList colors = new ArrayList<>(); - String[] stringColors = { "red", "crimson", "salmon", "orange", "gold", "yellow", "green", "turquoise", "cyan", - "sky_blue", "blue", "purple", "magenta", "pink", "lavender" }; - for (String color : stringColors) { - colors.add(new JsonColors(color)); - } - - return colors; - } - - // Placeholder for an api-request - public List getEchoLightTemperatures() { - ArrayList temperatures = new ArrayList<>(); - String[] stringTemperatures = { "warm_white", "soft_white", "white", "daylight_white", "cool_white" }; - for (String temperature : stringTemperatures) { - temperatures.add(new JsonColorTemperature(temperature)); - } - - return temperatures; - } - public List getDeviceList() throws IOException, URISyntaxException { String json = getDeviceListJson(); JsonDevices devices = parseJson(json, JsonDevices.class); @@ -976,189 +844,11 @@ public List getDeviceList() throws IOException, URISyntaxException { return new ArrayList<>(Arrays.asList(result)); } - public String getSmarthomeDeviceListJson() throws IOException, URISyntaxException { - String json = makeRequestAndReturnString(alexaServer + "/api/phoenix?includeRelationships=true"); - json = json.replace("\\", ""); - json = json.replace("\"{", "{"); - json = json.replace("}\"", "}"); - return json; - } - public String getDeviceListJson() throws IOException, URISyntaxException { String json = makeRequestAndReturnString(alexaServer + "/api/devices-v2/device?cached=false"); return json; } - public int getLightGroupBrightness(Thing device) throws IOException, URISyntaxException { - Map props = device.getProperties(); - List states = new ArrayList<>(); - if (props.containsKey(DEVICE_PROPERTY_APPLIANCE_ID + "0")) { - int counter = 0; - for (String key : props.keySet()) { - if (key.contains(DEVICE_PROPERTY_APPLIANCE_ID + counter)) { - JsonArray capabilities = this.getBulbCapabilities(props.get(key)); - - Float state = null; - for (JsonElement capability : capabilities) { - JsonObject capabilityObject = capability.getAsJsonObject(); - if (capabilityObject.get("namespace").getAsString().equals("Alexa.BrightnessController")) { - state = capabilityObject.get("value").getAsFloat(); - states.add(state); - } - } - ++counter; - } - } - - if (states.size() > 0) { - return Collections.max(states).intValue(); - } - } - - return -1; - } - - public String getBulbColor(Thing device) throws IOException, URISyntaxException { - Map props = device.getProperties(); - String applianceId = props.get(DEVICE_PROPERTY_APPLIANCE_ID); - - String color = null; - if (device.getThingTypeUID().equals(THING_TYPE_LIGHT)) { - JsonArray capabilities = this.getBulbCapabilities(applianceId); - - for (JsonElement capability : capabilities) { - JsonObject capabilityObject = capability.getAsJsonObject(); - if (capabilityObject.get("namespace").getAsString().equals("Alexa.ColorPropertiesController")) { - try { - color = capabilityObject.getAsJsonObject().get("value").getAsJsonObject().get("name") - .getAsString(); - } catch (Exception e) { - logger.error("getting bulb color failed {}", e); - } - } - } - } - - if (color != null) { - return color; - } else { - throw new IOException(); - } - } - - public int getBulbBrightness(Thing device) throws IOException, URISyntaxException { - Map props = device.getProperties(); - String applianceId = props.get(DEVICE_PROPERTY_APPLIANCE_ID); - JsonArray capabilities = this.getBulbCapabilities(applianceId); - - int brightness = -1; - if (device.getThingTypeUID().equals(THING_TYPE_LIGHT) - || device.getThingTypeUID().equals(THING_TYPE_LIGHT_GROUP)) { - for (JsonElement capability : capabilities) { - JsonObject capabilityObject = capability.getAsJsonObject(); - if (capabilityObject.get("namespace").getAsString().equals("Alexa.BrightnessController")) { - brightness = capabilityObject.get("value").getAsInt(); - } - } - - if (brightness == -1) { - return 100; - } - - return brightness; - } - return -1; - } - - public String getLightGroupState(Thing device) throws IOException, URISyntaxException { - Map props = device.getProperties(); - List states = new ArrayList<>(); - if (props.containsKey(DEVICE_PROPERTY_APPLIANCE_ID + "0")) { - int counter = 0; - for (String key : props.keySet()) { - if (key.contains(DEVICE_PROPERTY_APPLIANCE_ID + counter)) { - JsonArray capabilities = this.getBulbCapabilities(props.get(key)); - String state = null; - for (JsonElement capability : capabilities) { - JsonObject capabilityObject = capability.getAsJsonObject(); - if (capabilityObject.get("namespace").getAsString().equals("Alexa.PowerController")) { - state = capabilityObject.get("value").getAsString(); - states.add(state); - } - } - ++counter; - } - } - if (states.contains("ON")) { - return "ON"; - } else { - return "OFF"; - } - } - - throw new IOException(); - } - - public String getBulbState(Thing device) throws IOException, URISyntaxException { - Map props = device.getProperties(); - String applianceId = props.get(DEVICE_PROPERTY_APPLIANCE_ID); - - String state = null; - if (device.getThingTypeUID().equals(THING_TYPE_LIGHT) - || device.getThingTypeUID().equals(THING_TYPE_LIGHT_GROUP)) { - JsonArray capabilities = this.getBulbCapabilities(applianceId); - - for (JsonElement capability : capabilities) { - JsonObject capabilityObject = capability.getAsJsonObject(); - if (capabilityObject.get("namespace").getAsString().equals("Alexa.PowerController")) { - try { - state = capabilityObject.get("value").getAsString(); - } catch (Exception e) { - logger.error("getting bulb state failed {}", e); - } - } - } - } - - if (state == null) { - throw new IOException(); - } - - return state; - } - - public JsonArray getBulbCapabilities(String applianceId) throws IOException, URISyntaxException { - String json = this.getBulbStateJson(applianceId); - JsonElement jobject = new JsonParser().parse(json); - JsonArray capabilities = null; - - try { - capabilities = jobject.getAsJsonObject().get("deviceStates").getAsJsonArray().get(0).getAsJsonObject() - .get("capabilityStates").getAsJsonArray(); - } catch (Exception e) { - logger.error("getting capabilities failed {}", e); - } - - if (capabilities != null) { - return capabilities; - } - - throw new IOException(); - } - - public String getBulbStateJson(String applianceId) throws IOException, URISyntaxException { - String command = "{ \"stateRequests\": [{ \"entityId\": \"" + applianceId - + "\", \"entityType\": \"APPLIANCE\" }] }"; - String json = makeRequestAndReturnString("POST", alexaServer + "/api/phoenix/state", command, true, null); - json = json.replace("\\", ""); - json = json.replace("\"{", "{"); - json = json.replace("}\"", "}"); - if (!json.isEmpty()) { - return json; - } - throw new IOException(); - } - public JsonPlayerState getPlayer(Device device) throws IOException, URISyntaxException { String json = makeRequestAndReturnString(alexaServer + "/api/np/player?deviceSerialNumber=" + device.serialNumber + "&deviceType=" + device.deviceType + "&screenWidth=1440"); @@ -1216,30 +906,6 @@ public void command(Device device, String command) throws IOException, URISyntax makeRequest("POST", url, command, true, true, null); } - public void smartHomeCommand(String entityId, String action, @Nullable String color, double brightness) - throws IOException, URISyntaxException { - String url = alexaServer + "/api/phoenix/state"; - String requestBody = null; - if (action == "turnOn" || action == "turnOff") { - requestBody = "{\"controlRequests\": [{\"entityId\": " + "\"" + entityId + "\"" - + ", \"entityType\": \"APPLIANCE\", \"parameters\": { \"action\": " + "\"" + action + "\"" - + " }}]}"; - } else if (action == "setColorTemperature") { - requestBody = "{\"controlRequests\": [{\"entityId\": " + "\"" + entityId + "\"" - + ", \"entityType\": \"APPLIANCE\", \"parameters\": { \"action\": " + "\"" + action + "\"" - + ", \"colorTemperatureName\": \"" + color + "\" }}]}"; - } else if (action == "setColor") { - requestBody = "{\"controlRequests\": [{\"entityId\": " + "\"" + entityId + "\"" - + ", \"entityType\": \"APPLIANCE\", \"parameters\": { \"action\": " + "\"" + action + "\"" - + ", \"colorName\": \"" + color + "\" }}]}"; - } else if (action == "setBrightness") { - requestBody = "{\"controlRequests\": [{\"entityId\": " + "\"" + entityId + "\"" - + ", \"entityType\": \"APPLIANCE\", \"parameters\": { \"action\": " + "\"" + action + "\"" - + ", \"brightness\": \"" + brightness + "\" }}]}"; - } - makeRequest("PUT", url, requestBody, true, true, null); - } - public void notificationVolume(Device device, int volume) throws IOException, URISyntaxException { String url = alexaServer + "/api/device-notification-state/" + device.deviceType + "/" + device.softwareVersion + "/" + device.serialNumber; @@ -1358,7 +1024,7 @@ public void sendNotificationToMobileApp(String customerId, String text, @Nullabl executeSequenceCommand(null, "Alexa.Notifications.SendMobilePush", parameters); } - public void sendAnnouncement(Device device, String text, @Nullable String title) + public void sendAnnouncement(Device device, String text, @Nullable String title, int ttsVolume, int standardVolume) throws IOException, URISyntaxException { Map parameters = new Hashtable(); parameters.put("expireAfter", "PT5S"); @@ -1370,6 +1036,13 @@ public void sendAnnouncement(Device device, String text, @Nullable String title) content.display.title = title; } content.display.body = text; + if (text.startsWith("") && text.endsWith("")) { + content.speak.type = "ssml"; + String plainText = text.replaceAll("<[^>]+>", ""); + content.display.body = plainText; + } else { + content.display.body = text; + } content.speak.value = text; contentArray[0] = content; @@ -1379,48 +1052,54 @@ public void sendAnnouncement(Device device, String text, @Nullable String title) JsonAnnouncementTarget target = new JsonAnnouncementTarget(); target.customerId = device.deviceOwnerCustomerId; TargetDevice[] devices = new TargetDevice[1]; - TargetDevice deviceTarget = target.new TargetDevice(); + TargetDevice deviceTarget = new TargetDevice(); + deviceTarget.deviceSerialNumber = device.serialNumber; + deviceTarget.deviceTypeId = device.deviceType; devices[0] = deviceTarget; target.devices = devices; parameters.put("target", target); - String customerId = device.deviceOwnerCustomerId; + String accountCustomerId = this.accountCustomerId; + String customerId = StringUtils.isEmpty(accountCustomerId) ? device.deviceOwnerCustomerId : accountCustomerId; + if (customerId != null) { parameters.put("customerId", customerId); } - executeSequenceCommand(null, "AlexaAnnouncement", parameters); + executeSequenceCommandWithVolume(device, "AlexaAnnouncement", parameters, ttsVolume, standardVolume); } public void textToSpeech(Device device, String text, int ttsVolume, int standardVolume) throws IOException, URISyntaxException { + Map parameters = new Hashtable<>(); + parameters.put("textToSpeak", text); + executeSequenceCommandWithVolume(device, "Alexa.Speak", parameters, ttsVolume, standardVolume); + } + private void executeSequenceCommandWithVolume(@Nullable Device device, String command, + @Nullable Map parameters, int ttsVolume, int standardVolume) + throws IOException, URISyntaxException { if (ttsVolume != 0) { JsonArray nodesToExecute = new JsonArray(); - Map parameters = new Hashtable(); - + Map volumeParameters = new Hashtable<>(); // add tts volume - parameters.clear(); - parameters.put("value", ttsVolume); - nodesToExecute.add(createExecutionNode(device, "Alexa.DeviceControls.Volume", parameters)); + volumeParameters.clear(); + volumeParameters.put("value", ttsVolume); + nodesToExecute.add(createExecutionNode(device, "Alexa.DeviceControls.Volume", volumeParameters)); - // add tts - parameters.clear(); - parameters.put("textToSpeak", text); - nodesToExecute.add(createExecutionNode(device, "Alexa.Speak", parameters)); + // add command + nodesToExecute.add(createExecutionNode(device, command, parameters)); // add volume - parameters.clear(); - parameters.put("value", standardVolume); - nodesToExecute.add(createExecutionNode(device, "Alexa.DeviceControls.Volume", parameters)); + volumeParameters.clear(); + volumeParameters.put("value", standardVolume); + nodesToExecute.add(createExecutionNode(device, "Alexa.DeviceControls.Volume", volumeParameters)); executeSequenceNodes(nodesToExecute); } else { - Map parameters = new Hashtable(); - parameters.put("textToSpeak", text); - executeSequenceCommand(device, "Alexa.Speak", parameters); + executeSequenceCommand(device, command, parameters); } } @@ -1559,7 +1238,7 @@ public void startRoutine(Device device, String utterance) throws IOException, UR } public JsonAutomation[] getRoutines() throws IOException, URISyntaxException { - String json = makeRequestAndReturnString(alexaServer + "/api/behaviors/automations"); + String json = makeRequestAndReturnString(alexaServer + "/api/behaviors/automations?limit=2000"); JsonAutomation[] result = parseJson(json, JsonAutomation[].class); return result; } @@ -1593,6 +1272,16 @@ public JsonNotificationSound[] getNotificationSounds(Device device) throws IOExc return new JsonNotificationSound[0]; } + public JsonNotificationResponse[] notifications() throws IOException, URISyntaxException { + String response = makeRequestAndReturnString(alexaServer + "/api/notifications"); + JsonNotificationsResponse result = parseJson(response, JsonNotificationsResponse.class); + JsonNotificationResponse[] notifications = result.notifications; + if (notifications == null) { + return new JsonNotificationResponse[0]; + } + return notifications; + } + public JsonNotificationResponse notification(Device device, String type, @Nullable String label, @Nullable JsonNotificationSound sound) throws IOException, URISyntaxException { Date date = new Date(new Date().getTime()); @@ -1654,7 +1343,8 @@ public List getMusicProviders() { public void playMusicVoiceCommand(Device device, String providerId, String voiceCommand) throws IOException, URISyntaxException { JsonPlaySearchPhraseOperationPayload payload = new JsonPlaySearchPhraseOperationPayload(); - payload.customerId = device.deviceOwnerCustomerId; + payload.customerId = (StringUtils.isEmpty(this.accountCustomerId) ? device.deviceOwnerCustomerId + : this.accountCustomerId); payload.locale = "ALEXA_CURRENT_LOCALE"; payload.musicProviderId = providerId; payload.searchPhrase = voiceCommand; @@ -1699,4 +1389,16 @@ public void playMusicVoiceCommand(Device device, String providerId, String voice String postData = gson.toJson(startRoutineRequest); makeRequest("POST", alexaServer + "/api/behaviors/preview", postData, true, true, null); } + + public JsonEqualizer getEqualizer(Device device) throws IOException, URISyntaxException { + String json = makeRequestAndReturnString( + alexaServer + "/api/equalizer/" + device.serialNumber + "/" + device.deviceType); + return parseJson(json, JsonEqualizer.class); + } + + public void SetEqualizer(Device device, JsonEqualizer settings) throws IOException, URISyntaxException { + String postData = gson.toJson(settings); + makeRequest("POST", alexaServer + "/api/equalizer/" + device.serialNumber + "/" + device.deviceType, postData, + true, true, null); + } } diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/WebSocketConnection.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/WebSocketConnection.java index 949cfde646b55..76656d246ea5d 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/WebSocketConnection.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/WebSocketConnection.java @@ -149,7 +149,18 @@ public void close() { Session session = this.session; this.session = null; if (session != null) { - session.close(); + try { + session.close(); + } catch (Exception e) { + logger.debug("Closing sessing failed {}", e); + } + } + try { + webSocketClient.stop(); + } catch (InterruptedException e) { + // Just ignore + } catch (Exception e) { + logger.debug("Stopping websocket failed {}", e); } webSocketClient.destroy(); } 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 8ceef6b571503..3a3db9cd87cc5 100755 --- 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 @@ -16,6 +16,7 @@ import java.net.URISyntaxException; import java.net.URLEncoder; import java.net.UnknownHostException; +import java.time.ZonedDateTime; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; @@ -54,14 +55,15 @@ import org.openhab.binding.amazonechocontrol.internal.jsons.JsonCommandPayloadPushActivity.Key; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonCommandPayloadPushDevice; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonCommandPayloadPushDevice.DopplerId; +import org.openhab.binding.amazonechocontrol.internal.jsons.JsonCommandPayloadPushNotificationChange; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonDeviceNotificationState.DeviceNotificationState; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonDevices.Device; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonFeed; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonMusicProvider; +import org.openhab.binding.amazonechocontrol.internal.jsons.JsonNotificationResponse; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonNotificationSound; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonPlaylists; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonPushCommand; -import org.openhab.binding.amazonechocontrol.internal.jsons.JsonSmartHomeDevices.SmartHomeDevice; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonWakeWords.WakeWord; import org.osgi.service.http.HttpService; import org.slf4j.Logger; @@ -83,7 +85,6 @@ public class AccountHandler extends BaseBridgeHandler implements IWebSocketComma private @Nullable Connection connection; private @Nullable WebSocketConnection webSocketConnection; private final Set echoHandlers = new HashSet<>(); - private final Set smartHomeDeviceHandlers = new HashSet<>(); private final Set flashBriefingProfileHandlers = new HashSet<>(); private final Object synchronizeConnection = new Object(); private Map jsonSerialNumberDeviceMapping = new HashMap<>(); @@ -141,10 +142,6 @@ public List getLastKnownDevices() { return new ArrayList<>(jsonSerialNumberDeviceMapping.values()); } - public List getSmartHomeDeviceHandlers() { - return new ArrayList<>(this.smartHomeDeviceHandlers); - } - public void addEchoHandler(EchoHandler echoHandler) { synchronized (echoHandlers) { if (!echoHandlers.add(echoHandler)) { @@ -154,16 +151,7 @@ public void addEchoHandler(EchoHandler echoHandler) { forceCheckData(); } - public void addSmartHomeDeviceHandler(SmartHomeDeviceHandler smartHomeDeviceHandler) { - synchronized (smartHomeDeviceHandler) { - if (!smartHomeDeviceHandlers.add(smartHomeDeviceHandler)) { - return; - } - } - forceCheckData(); - } - - void forceCheckData() { + public void forceCheckData() { if (foceCheckDataJob == null) { foceCheckDataJob = scheduler.schedule(this::forceCheckDataHandler, 1000, TimeUnit.MILLISECONDS); } @@ -197,7 +185,7 @@ public void addFlashBriefingProfileHandler(FlashBriefingProfileHandler flashBrie flashBriefingProfileHandlers.add(flashBriefingProfileHandler); } Connection connection = this.connection; - if (connection != null) { + if (connection != null && connection.getIsLoggedIn()) { if (currentFlashBriefingJson.isEmpty()) { updateFlashBriefingProfiles(connection); } @@ -205,6 +193,16 @@ public void addFlashBriefingProfileHandler(FlashBriefingProfileHandler flashBrie } } + private void scheduleUpdate() { + checkDataCounter = 999; + } + + @Override + public void childHandlerInitialized(ThingHandler childHandler, Thing childThing) { + super.childHandlerInitialized(childHandler, childThing); + scheduleUpdate(); + } + @Override public void handleRemoval() { cleanup(); @@ -338,7 +336,7 @@ public void setConnection(@Nullable Connection connection) { updateDeviceList(); updateFlashBriefingHandlers(); updateStatus(ThingStatus.ONLINE); - checkDataCounter = 0; + scheduleUpdate(); checkData(); } } @@ -391,6 +389,30 @@ private void checkData() { } } + private void refreshNotifications(@Nullable JsonCommandPayloadPushNotificationChange pushPayload) { + Connection currentConnection = this.connection; + if (currentConnection == null) { + return; + } + if (!currentConnection.getIsLoggedIn()) { + return; + } + JsonNotificationResponse[] notifications; + ZonedDateTime timeStamp = ZonedDateTime.now(); + try { + notifications = currentConnection.notifications(); + } catch (IOException | URISyntaxException e) { + logger.debug("refreshNotifications failed {}", e); + return; + } + ZonedDateTime timeStampNow = ZonedDateTime.now(); + + for (EchoHandler child : echoHandlers) { + child.updateNotifications(timeStamp, timeStampNow, pushPayload, notifications); + } + + } + private void refreshData() { synchronized (synchronizeConnection) { try { @@ -486,6 +508,9 @@ private void refreshData() { notificationSounds, musicProviders); } + // refresh notifications + refreshNotifications(null); + // update account state updateStatus(ThingStatus.ONLINE); @@ -529,37 +554,6 @@ private void refreshData() { return null; } - public List updateSmartHomeDeviceList() { - - Connection currentConnection = connection; - if (currentConnection == null) { - return new ArrayList(); - } - - List smartHomeDevices = null; - try { - if (currentConnection.getIsLoggedIn()) { - smartHomeDevices = currentConnection.getSmarthomeDeviceList(); - } - } catch (IOException | URISyntaxException e) { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getLocalizedMessage()); - } - if (smartHomeDevices != null) { - Map newJsonSerialDeviceMapping = new HashMap<>(); - for (SmartHomeDevice smartDevice : smartHomeDevices) { - String entityId = smartDevice.entityId; - if (entityId != null) { - newJsonSerialDeviceMapping.put(entityId, smartDevice); - } - } - } - if (smartHomeDevices != null) { - return smartHomeDevices; - } - - return new ArrayList(); - } - public List updateDeviceList() { Connection currentConnection = connection; @@ -712,7 +706,9 @@ void handleWebsocketCommand(JsonPushCommand pushCommand) { TimeUnit.MILLISECONDS); break; case "PUSH_NOTIFICATION_CHANGE": - // Currently ignored + JsonCommandPayloadPushNotificationChange pushPayload = gson.fromJson(pushCommand.payload, + JsonCommandPayloadPushNotificationChange.class); + refreshNotifications(pushPayload); break; default: String payload = pushCommand.payload; 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 e9eed8bf1a418..2bb4e8fb3ad03 100755 --- 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 @@ -16,17 +16,27 @@ import java.io.IOException; import java.net.URISyntaxException; +import java.time.Instant; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.time.temporal.ChronoUnit; +import java.util.HashSet; import java.util.Hashtable; import java.util.List; import java.util.Map; +import java.util.Objects; +import java.util.Set; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; +import java.util.stream.Stream; import javax.measure.quantity.Time; import org.apache.commons.lang.StringUtils; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.library.types.DateTimeType; import org.eclipse.smarthome.core.library.types.DecimalType; import org.eclipse.smarthome.core.library.types.IncreaseDecreaseType; import org.eclipse.smarthome.core.library.types.NextPreviousType; @@ -47,6 +57,7 @@ import org.eclipse.smarthome.core.types.RefreshType; import org.eclipse.smarthome.core.types.UnDefType; import org.openhab.binding.amazonechocontrol.internal.Connection; +import org.openhab.binding.amazonechocontrol.internal.ConnectionException; import org.openhab.binding.amazonechocontrol.internal.HttpException; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonActivities.Activity; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonActivities.Activity.Description; @@ -54,9 +65,11 @@ import org.openhab.binding.amazonechocontrol.internal.jsons.JsonBluetoothStates; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonBluetoothStates.BluetoothState; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonBluetoothStates.PairedDevice; +import org.openhab.binding.amazonechocontrol.internal.jsons.JsonCommandPayloadPushNotificationChange; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonCommandPayloadPushVolumeChange; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonDeviceNotificationState.DeviceNotificationState; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonDevices.Device; +import org.openhab.binding.amazonechocontrol.internal.jsons.JsonEqualizer; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonMediaState; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonMediaState.QueueEntry; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonMusicProvider; @@ -86,6 +99,7 @@ public class EchoHandler extends BaseThingHandler { private final Logger logger = LoggerFactory.getLogger(EchoHandler.class); private Gson gson = new Gson(); private @Nullable Device device; + private Set capabilities = new HashSet<>(); private @Nullable AccountHandler account; private @Nullable ScheduledFuture updateStateJob; private @Nullable ScheduledFuture ignoreVolumeChange; @@ -100,6 +114,7 @@ public class EchoHandler extends BaseThingHandler { private boolean isPaused = false; private int lastKnownVolume = 25; private int textToSpeechVolume = 0; + private @Nullable JsonEqualizer lastKnownEqualizer = null; private @Nullable BluetoothState bluetoothState; private boolean disableUpdate = false; private boolean updateRemind = true; @@ -149,6 +164,10 @@ public boolean setDeviceAndUpdateThingState(AccountHandler accountHandler, @Null return false; } this.device = device; + String[] capabilities = device.capabilities; + if (capabilities != null) { + this.capabilities = Stream.of(capabilities).filter(Objects::nonNull).collect(Collectors.toSet()); + } if (!device.online) { updateStatus(ThingStatus.OFFLINE); return false; @@ -366,6 +385,14 @@ public void handleCommand(ChannelUID channelUID, Command command) { } } + // equalizer commands + if (channelId.equals(CHANNEL_EQUALIZER_BASS) || channelId.equals(CHANNEL_EQUALIZER_MIDRANGE) + || channelId.equals(CHANNEL_EQUALIZER_TREBLE)) { + if (handleEqualizerCommands(channelId, command, connection, device)) { + waitForUpdate = -1; + } + } + // shuffle command if (channelId.equals(CHANNEL_SHUFFLE)) { if (command instanceof OnOffType) { @@ -638,6 +665,7 @@ public void handleCommand(ChannelUID channelUID, Command command) { }; if (command instanceof RefreshType) { waitForUpdate = 0; + account.forceCheckData(); } if (waitForUpdate == 0) { doRefresh.run(); @@ -651,6 +679,41 @@ public void handleCommand(ChannelUID channelUID, Command command) { } } + private boolean handleEqualizerCommands(String channelId, Command command, Connection connection, Device device) + throws URISyntaxException { + if (command instanceof RefreshType) { + this.lastKnownEqualizer = null; + } + if (command instanceof DecimalType) { + DecimalType value = (DecimalType) command; + if (this.lastKnownEqualizer == null) { + updateEqualizerState(); + } + JsonEqualizer lastKnownEqualizer = this.lastKnownEqualizer; + if (lastKnownEqualizer != null) { + JsonEqualizer newEqualizerSetting = lastKnownEqualizer.createClone(); + if (channelId.equals(CHANNEL_EQUALIZER_BASS)) { + newEqualizerSetting.bass = value.intValue(); + } + if (channelId.equals(CHANNEL_EQUALIZER_MIDRANGE)) { + newEqualizerSetting.mid = value.intValue(); + } + if (channelId.equals(CHANNEL_EQUALIZER_TREBLE)) { + newEqualizerSetting.treble = value.intValue(); + } + try { + connection.SetEqualizer(device, newEqualizerSetting); + return true; + } catch (HttpException | IOException | ConnectionException e) { + logger.debug("Update equalizer failed {}", e); + this.lastKnownEqualizer = null; + } + + } + } + return false; + } + private void startTextToSpeech(Connection connection, Device device, String text) throws IOException, URISyntaxException { if (textToSpeechVolume != 0) { @@ -661,7 +724,11 @@ private void startTextToSpeech(Connection connection, Device device, String text } this.ignoreVolumeChange = scheduler.schedule(this::stopIgnoreVolumeChange, 2000, TimeUnit.MILLISECONDS); } - connection.textToSpeech(device, text, textToSpeechVolume, lastKnownVolume); + if (text.startsWith("") && text.endsWith("")) { + connection.sendAnnouncement(device, text, null, textToSpeechVolume, lastKnownVolume); + } else { + connection.textToSpeech(device, text, textToSpeechVolume, lastKnownVolume); + } } private void stopCurrentNotification() { @@ -724,7 +791,7 @@ public void updateState(AccountHandler accountHandler, @Nullable Device device, @Nullable JsonNotificationSound @Nullable [] alarmSounds, @Nullable List musicProviders) { try { - this.logger.debug("Handle updateState {}", this.getThing().getUID().getAsString()); + this.logger.debug("Handle updateState {}", this.getThing().getUID()); if (deviceNotificationState != null) { noticationVolumeLevel = deviceNotificationState.volumeLevel; @@ -742,16 +809,16 @@ public void updateState(AccountHandler accountHandler, @Nullable Device device, this.musicProviders = musicProviders; } if (!setDeviceAndUpdateThingState(accountHandler, device, null)) { - this.logger.debug("Handle updateState {} aborted: Not online", this.getThing().getUID().getAsString()); + this.logger.debug("Handle updateState {} aborted: Not online", this.getThing().getUID()); return; } if (device == null) { - this.logger.debug("Handle updateState {} aborted: No device", this.getThing().getUID().getAsString()); + this.logger.debug("Handle updateState {} aborted: No device", this.getThing().getUID()); return; } if (this.disableUpdate) { - this.logger.debug("Handle updateState {} aborted: Disabled", this.getThing().getUID().getAsString()); + this.logger.debug("Handle updateState {} aborted: Disabled", this.getThing().getUID()); return; } Connection connection = this.findConnection(); @@ -759,6 +826,10 @@ public void updateState(AccountHandler accountHandler, @Nullable Device device, return; } + if (this.lastKnownEqualizer == null) { + updateEqualizerState(); + } + PlayerInfo playerInfo = null; Provider provider = null; InfoText infoText = null; @@ -1052,13 +1123,51 @@ public void updateState(AccountHandler accountHandler, @Nullable Device device, } } catch (Exception e) { - this.logger.debug("Handle updateState {} failed: {}", this.getThing().getUID().getAsString(), e); + this.logger.debug("Handle updateState {} failed: {}", this.getThing().getUID(), e); disableUpdate = false; throw e; // Rethrow same exception } } + private void updateEqualizerState() { + if (!this.capabilities.contains("SOUND_SETTINGS")) { + return; + } + + Connection connection = findConnection(); + if (connection == null) { + return; + } + Device device = findDevice(); + if (device == null) { + return; + } + Integer bass; + Integer midrange; + Integer treble; + try { + JsonEqualizer equalizer = connection.getEqualizer(device); + bass = equalizer.bass; + midrange = equalizer.mid; + treble = equalizer.treble; + this.lastKnownEqualizer = equalizer; + } catch (IOException | URISyntaxException | HttpException | ConnectionException e) { + logger.debug("Get equalizer failes {}", e); + return; + } + if (bass != null) { + updateState(CHANNEL_EQUALIZER_BASS, new DecimalType(bass)); + } + if (midrange != null) { + updateState(CHANNEL_EQUALIZER_MIDRANGE, new DecimalType(midrange)); + } + if (treble != null) { + updateState(CHANNEL_EQUALIZER_TREBLE, new DecimalType(treble)); + } + + } + private void updateMediaProgress() { updateMediaProgress(false); } @@ -1092,11 +1201,17 @@ private void updateMediaProgress(boolean updateMediaLength) { } public void handlePushActivity(Activity pushActivity) { + if ("DISCARDED_NON_DEVICE_DIRECTED_INTENT".equals(pushActivity.activityStatus)) { + return; + } Description description = pushActivity.ParseDescription(); if (StringUtils.isEmpty(description.firstUtteranceId) || StringUtils.startsWithIgnoreCase(description.firstUtteranceId, "TextClient:")) { return; } + if (StringUtils.isEmpty(description.firstStreamId)) { + return; + } String spokenText = description.summary; if (spokenText != null && StringUtils.isNotEmpty(spokenText)) { // remove wake word @@ -1141,7 +1256,7 @@ public void handlePushCommand(String command, String payload) { } break; case "PUSH_EQUALIZER_STATE_CHANGE": - // Currently ignored + updateEqualizerState(); break; default: AccountHandler account = this.account; @@ -1152,4 +1267,67 @@ public void handlePushCommand(String command, String payload) { } } } + + public void updateNotifications(ZonedDateTime currentTime, ZonedDateTime now, + @Nullable JsonCommandPayloadPushNotificationChange pushPayload, JsonNotificationResponse[] notifications) { + Device device = this.device; + if (device == null) { + return; + } + + ZonedDateTime nextReminder = null; + ZonedDateTime nextAlarm = null; + ZonedDateTime nextMusicAlarm = null; + ZonedDateTime nextTimer = null; + for (JsonNotificationResponse notification : notifications) { + if (StringUtils.equals(notification.deviceSerialNumber, device.serialNumber)) { + // notification for this device + if (StringUtils.equals(notification.status, "ON")) { + if ("Reminder".equals(notification.type)) { + String offset = ZoneId.systemDefault().getRules().getOffset(Instant.now()).toString(); + ZonedDateTime alarmTime = ZonedDateTime + .parse(notification.originalDate + "T" + notification.originalTime + offset); + if (StringUtils.isNotBlank(notification.recurringPattern) && alarmTime.isBefore(now)) { + continue; // Ignore recurring entry if alarm time is before now + } + if (nextReminder == null || alarmTime.isBefore(nextReminder)) { + nextReminder = alarmTime; + } + } else if ("Timer".equals(notification.type)) { + // use remaining time + ZonedDateTime alarmTime = currentTime.plus(notification.remainingTime, ChronoUnit.MILLIS); + if (nextTimer == null || alarmTime.isBefore(nextTimer)) { + nextTimer = alarmTime; + } + } else if ("Alarm".equals(notification.type)) { + String offset = ZoneId.systemDefault().getRules().getOffset(Instant.now()).toString(); + ZonedDateTime alarmTime = ZonedDateTime + .parse(notification.originalDate + "T" + notification.originalTime + offset); + if (StringUtils.isNotBlank(notification.recurringPattern) && alarmTime.isBefore(now)) { + continue; // Ignore recurring entry if alarm time is before now + } + if (nextAlarm == null || alarmTime.isBefore(nextAlarm)) { + nextAlarm = alarmTime; + } + } else if ("MusicAlarm".equals(notification.type)) { + String offset = ZoneId.systemDefault().getRules().getOffset(Instant.now()).toString(); + ZonedDateTime alarmTime = ZonedDateTime + .parse(notification.originalDate + "T" + notification.originalTime + offset); + if (StringUtils.isNotBlank(notification.recurringPattern) && alarmTime.isBefore(now)) { + continue; // Ignore recurring entry if alarm time is before now + } + if (nextMusicAlarm == null || alarmTime.isBefore(nextMusicAlarm)) { + nextMusicAlarm = alarmTime; + } + } + } + } + } + + updateState(CHANNEL_NEXT_REMINDER, nextReminder == null ? UnDefType.UNDEF : new DateTimeType(nextReminder)); + updateState(CHANNEL_NEXT_ALARM, nextAlarm == null ? UnDefType.UNDEF : new DateTimeType(nextAlarm)); + updateState(CHANNEL_NEXT_MUSIC_ALARM, + nextMusicAlarm == null ? UnDefType.UNDEF : new DateTimeType(nextMusicAlarm)); + updateState(CHANNEL_NEXT_TIMER, nextTimer == null ? UnDefType.UNDEF : new DateTimeType(nextTimer)); + } } diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonActivities.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonActivities.java index 910b1f347cf54..b09660af70a1e 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonActivities.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonActivities.java @@ -29,7 +29,7 @@ public class JsonActivities { public @Nullable Activity @Nullable [] activities; - public class Activity { + public static class Activity { public @Nullable String activityStatus; public @Nullable Long creationTimestamp; public @Nullable String description; @@ -45,14 +45,14 @@ public class Activity { public @Nullable String utteranceId; public @Nullable Long version; - public class SourceDeviceId { + public static class SourceDeviceId { public @Nullable String deviceAccountId; public @Nullable String deviceType; public @Nullable String serialNumber; } - public class Description { + public static class Description { public @Nullable String summary; public @Nullable String firstUtteranceId; 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 1ce05d0cbfa52..ce2296773e417 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 @@ -24,17 +24,17 @@ @NonNullByDefault public class JsonAnnouncementContent { - public @Nullable String locale; + public String locale = ""; public final Display display = new Display(); public final Speak speak = new Speak(); - public class Display { + public static class Display { public @Nullable String title; public @Nullable String body; } - public class Speak { + public static class Speak { public String type = "text"; public @Nullable String value; 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 fcb8e884541f2..6e99bec84f1c6 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 @@ -26,7 +26,7 @@ public class JsonAnnouncementTarget { public @Nullable String customerId; public @Nullable TargetDevice @Nullable [] devices; - public class TargetDevice { + public static class TargetDevice { public @Nullable String deviceSerialNumber; public @Nullable String deviceTypeId; } diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonAscendingAlarm.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonAscendingAlarm.java index 68ebe7d70d936..95c4d6c81a8a5 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonAscendingAlarm.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonAscendingAlarm.java @@ -25,7 +25,7 @@ public class JsonAscendingAlarm { public @Nullable AscendingAlarmModel @Nullable [] ascendingAlarmModelList; - public class AscendingAlarmModel { + public static class AscendingAlarmModel { public @Nullable Boolean ascendingAlarmEnabled; public @Nullable String deviceSerialNumber; public @Nullable String deviceType; diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonAutomation.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonAutomation.java index 9f9b7cf99faf3..d3be585e7c7f4 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonAutomation.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonAutomation.java @@ -32,13 +32,13 @@ public class JsonAutomation { public long creationTimeEpochMillis; public long lastUpdatedTimeEpochMillis; - public class Trigger { + public static class Trigger { public @Nullable Payload payload; public @Nullable String id; public @Nullable String type; } - public class Payload { + public static class Payload { public @Nullable String customerId; public @Nullable String utterance; public @Nullable String locale; diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonBluetoothStates.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonBluetoothStates.java index 5361887d5afb2..4d2ba0adb07cc 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonBluetoothStates.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonBluetoothStates.java @@ -44,7 +44,7 @@ public class JsonBluetoothStates { public @Nullable BluetoothState @Nullable [] bluetoothStates; - public class PairedDevice { + public static class PairedDevice { public @Nullable String address; public boolean connected; public @Nullable String deviceClass; @@ -53,7 +53,7 @@ public class PairedDevice { } - public class BluetoothState { + public static class BluetoothState { public @Nullable String deviceSerialNumber; public @Nullable String deviceType; public @Nullable String friendlyName; diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonCommandPayloadPushActivity.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonCommandPayloadPushActivity.java index 9fc7800324326..c53128cf0966a 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonCommandPayloadPushActivity.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonCommandPayloadPushActivity.java @@ -28,7 +28,7 @@ public class JsonCommandPayloadPushActivity { public @Nullable Key key; - public class Key { + public static class Key { public @Nullable String entryId; public @Nullable String registeredUserId; } diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonCommandPayloadPushDevice.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonCommandPayloadPushDevice.java index f606635ab5e22..c7b42709229ec 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonCommandPayloadPushDevice.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonCommandPayloadPushDevice.java @@ -25,7 +25,7 @@ public class JsonCommandPayloadPushDevice { public @Nullable DopplerId dopplerId; - public class DopplerId { + public static class DopplerId { public @Nullable String deviceSerialNumber; public @Nullable String deviceType; } diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonDeviceNotificationState.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonDeviceNotificationState.java index 2f0a6ccb7701b..596c172a2048b 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonDeviceNotificationState.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonDeviceNotificationState.java @@ -25,7 +25,7 @@ public class JsonDeviceNotificationState { public @Nullable DeviceNotificationState @Nullable [] deviceNotificationStates; - public class DeviceNotificationState { + public static class DeviceNotificationState { public @Nullable String deviceSerialNumber; public @Nullable String deviceType; public @Nullable String softwareVersion; diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonDevices.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonDevices.java index 16f00449aac06..2ff3a02ad65d1 100755 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonDevices.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonDevices.java @@ -23,7 +23,7 @@ @NonNullByDefault public class JsonDevices { - public class Device { + public static class Device { public @Nullable String accountName; public @Nullable String serialNumber; public @Nullable String deviceOwnerCustomerId; diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonExchangeTokenResponse.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonExchangeTokenResponse.java index e95a1df7a873e..48807bea68910 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonExchangeTokenResponse.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonExchangeTokenResponse.java @@ -26,15 +26,15 @@ public class JsonExchangeTokenResponse { public @Nullable Response response; - public class Response { + public static class Response { public @Nullable Tokens tokens; } - public class Tokens { + public static class Tokens { public @Nullable Map cookies; } - public class Cookie { + public static class Cookie { public @Nullable String Path; public @Nullable Boolean Secure; public @Nullable String Value; diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonMediaState.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonMediaState.java index 69033b938c5e5..0d23fb92d1995 100755 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonMediaState.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonMediaState.java @@ -47,7 +47,7 @@ public class JsonMediaState { // public long timeLastShuffled; parsing fails with some values, so do not use it public int volume; - public class QueueEntry { + public static class QueueEntry { public @Nullable String album; public @Nullable String albumAsin; diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonNotificationResponse.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonNotificationResponse.java index 48f1c1915e91c..e339d176c5bad 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonNotificationResponse.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonNotificationResponse.java @@ -30,6 +30,10 @@ public class JsonNotificationResponse { public @Nullable String id; public @Nullable String status; public @Nullable String type; + public long remainingTime; + public @Nullable String recurringPattern; + public @Nullable String originalDate; + public @Nullable String originalTime; } /* diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonPlayerState.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonPlayerState.java index 79e4f508b6c97..f3013b518cc13 100755 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonPlayerState.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonPlayerState.java @@ -24,7 +24,7 @@ public class JsonPlayerState { public @Nullable PlayerInfo playerInfo; - public class PlayerInfo { + public static class PlayerInfo { public @Nullable String state; public @Nullable InfoText infoText; public @Nullable InfoText miniInfoText; @@ -37,7 +37,7 @@ public class PlayerInfo { public @Nullable Progress progress; - public class InfoText { + public static class InfoText { public boolean multiLineMode; public @Nullable String subText1; public @Nullable String subText2; @@ -45,24 +45,24 @@ public class InfoText { } - public class Provider { + public static class Provider { public @Nullable String providerDisplayName; public @Nullable String providerName; } - public class Volume { + public static class Volume { public boolean muted; public int volume; } - public class MainArt { + public static class MainArt { public @Nullable String altText; public @Nullable String artType; public @Nullable String contentType; public @Nullable String url; } - public class Progress { + public static class Progress { public @Nullable Boolean allowScrubbing; public @Nullable Object locationInfo; public @Nullable Long mediaLength; diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonPlaylists.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonPlaylists.java index 1e8b8bcdcdeee..d079c686df8c5 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonPlaylists.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonPlaylists.java @@ -27,7 +27,7 @@ public class JsonPlaylists { public @Nullable Map playlists; - public class PlayList { + public static class PlayList { public @Nullable String playlistId; public @Nullable String title; public int trackCount; diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonRegisterAppRequest.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonRegisterAppRequest.java index 54b242a0cf0f1..8b2e2762a22d5 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonRegisterAppRequest.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonRegisterAppRequest.java @@ -38,7 +38,7 @@ public JsonRegisterAppRequest(String serial, String access_token, String frc, Js public UserContextMap user_context_map = new UserContextMap(); public String[] requested_token_type = { "bearer", "mac_dms", "website_cookies" }; - public class Cookies { + public static class Cookies { @Nullable public JsonWebSiteCookie @Nullable [] website_cookies; @Nullable @@ -46,7 +46,7 @@ public class Cookies { } - public class RegistrationData { + public static class RegistrationData { public String domain = "Device"; public String app_version = "2.2.223830.0"; public String device_type = "A2IVLV5VM2W81"; @@ -59,12 +59,12 @@ public class RegistrationData { public String software_version = "1"; } - public class AuthData { + public static class AuthData { @Nullable public String access_token; } - public class UserContextMap { + public static class UserContextMap { public String frc = ""; } } diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonRegisterAppResponse.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonRegisterAppResponse.java index 9c6539c066aca..b2a22649f54ea 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonRegisterAppResponse.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonRegisterAppResponse.java @@ -29,19 +29,21 @@ public class JsonRegisterAppResponse { @Nullable public String request_id; - public class Response { + public static class Response { @Nullable public Success success; } - public class Success { + public static class Success { @Nullable public Extensions extensions; @Nullable public Tokens tokens; + @Nullable + public String customer_id; } - public class Extensions { + public static class Extensions { @Nullable public DeviceInfo device_info; @Nullable @@ -50,7 +52,7 @@ public class Extensions { public String customer_id; } - public class DeviceInfo { + public static class DeviceInfo { @Nullable public String device_name; @Nullable @@ -60,7 +62,7 @@ public class DeviceInfo { } - public class CustomerInfo { + public static class CustomerInfo { @Nullable public String account_pool; @Nullable @@ -73,7 +75,7 @@ public class CustomerInfo { public String given_name; } - public class Tokens { + public static class Tokens { @Nullable public Object website_cookies; @Nullable @@ -82,14 +84,14 @@ public class Tokens { public Bearer bearer; } - public class MacDms { + public static class MacDms { @Nullable public String device_private_key; @Nullable public String adp_token; } - public class Bearer { + public static class Bearer { @Nullable public String access_token; @Nullable diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonWakeWords.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonWakeWords.java index c8af33b41867c..c59a5bca171ab 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonWakeWords.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonWakeWords.java @@ -24,7 +24,7 @@ public class JsonWakeWords { public @Nullable WakeWord @Nullable [] wakeWords; - public class WakeWord { + public static class WakeWord { public @Nullable Boolean active; public @Nullable String deviceSerialNumber; public @Nullable String deviceType; diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/statedescription/AmazonEchoDynamicStateDescriptionProvider.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/statedescription/AmazonEchoDynamicStateDescriptionProvider.java index dcd9c3acc966d..bf0b21394e49e 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/statedescription/AmazonEchoDynamicStateDescriptionProvider.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/statedescription/AmazonEchoDynamicStateDescriptionProvider.java @@ -123,8 +123,9 @@ protected void unsetThingRegistry(ThingRegistry thingRegistry) { if (device == null) { continue; } - if (device.address != null && device.friendlyName != null) { - options.add(new StateOption(device.address, device.friendlyName)); + final String value = device.address; + if (value != null && device.friendlyName != null) { + options.add(new StateOption(value, device.friendlyName)); } } StateDescription result = new StateDescription(originalStateDescription.getMinimum(), @@ -151,8 +152,8 @@ protected void unsetThingRegistry(ThingRegistry thingRegistry) { for (PlayList[] innerLists : playlistMap.values()) { if (innerLists != null && innerLists.length > 0) { PlayList playList = innerLists[0]; - if (playList.playlistId != null && playList.title != null) { - final String value = playList.playlistId; + final String value = playList.playlistId; + if (value != null && playList.title != null) { options.add(new StateOption(value, String.format("%s (%d)", playList.title, playList.trackCount))); } From bbdcbf8c5586f7ae2f973e84eb54087b02b2c17c Mon Sep 17 00:00:00 2001 From: Lkn94 Date: Sun, 9 Jun 2019 21:35:14 +0200 Subject: [PATCH 05/56] Bugfixed for new version and merge request --- .../AmazonEchoControlBindingConstants.java | 22 +- .../AmazonEchoControlHandlerFactory.java | 12 + .../internal/Connection.java | 340 ++++++++++++++++++ .../discovery/SmartHomeDevicesDiscovery.java | 12 + .../internal/handler/AccountHandler.java | 46 +++ .../jsons/JsonSmartHomeDeviceAlias.java | 3 + .../internal/jsons/JsonSmartHomeDevices.java | 7 +- .../jsons/JsonSmartHomeGroupIdentifiers.java | 2 +- .../internal/jsons/JsonSmartHomeGroups.java | 2 +- .../resources/ESH-INF/thing/thing-types.xml | 78 +++- 10 files changed, 517 insertions(+), 7 deletions(-) diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/AmazonEchoControlBindingConstants.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/AmazonEchoControlBindingConstants.java index 258e7ba07ba59..ba2a7960ec609 100755 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/AmazonEchoControlBindingConstants.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/AmazonEchoControlBindingConstants.java @@ -42,9 +42,12 @@ public class AmazonEchoControlBindingConstants { public static final ThingTypeUID THING_TYPE_FLASH_BRIEFING_PROFILE = new ThingTypeUID(BINDING_ID, "flashbriefingprofile"); + public static final ThingTypeUID THING_TYPE_LIGHT = new ThingTypeUID(BINDING_ID, "light"); + public static final ThingTypeUID THING_TYPE_LIGHT_GROUP = new ThingTypeUID(BINDING_ID, "lightGroup"); + public static final Set SUPPORTED_THING_TYPES_UIDS = new HashSet( Arrays.asList(THING_TYPE_ACCOUNT, THING_TYPE_ECHO, THING_TYPE_ECHO_SPOT, THING_TYPE_ECHO_SHOW, - THING_TYPE_ECHO_WHA, THING_TYPE_FLASH_BRIEFING_PROFILE)); + THING_TYPE_ECHO_WHA, THING_TYPE_FLASH_BRIEFING_PROFILE, THING_TYPE_LIGHT, THING_TYPE_LIGHT_GROUP)); // List of all Channel ids public static final String CHANNEL_PLAYER = "player"; @@ -82,6 +85,10 @@ public class AmazonEchoControlBindingConstants { public static final String CHANNEL_MEDIA_PROGRESS_TIME = "mediaProgressTime"; public static final String CHANNEL_ASCENDING_ALARM = "ascendingAlarm"; public static final String CHANNEL_NOTIFICATION_VOLUME = "notificationVolume"; + public static final String CHANNEL_LIGHT_STATE = "lightState"; + public static final String CHANNEL_LIGHT_COLOR = "lightColor"; + public static final String CHANNEL_LIGHT_WHITE_TEMPERATURE = "whiteTemperature"; + public static final String CHANNEL_LIGHT_BRIGHTNESS = "lightBrightness"; public static final String CHANNEL_NEXT_REMINDER = "nextReminder"; public static final String CHANNEL_NEXT_ALARM = "nextAlarm"; public static final String CHANNEL_NEXT_MUSIC_ALARM = "nextMusicAlarm"; @@ -101,12 +108,25 @@ public class AmazonEchoControlBindingConstants { public static final ChannelTypeUID CHANNEL_TYPE_MUSIC_PROVIDER_ID = new ChannelTypeUID(BINDING_ID, "musicProviderId"); public static final ChannelTypeUID CHANNEL_TYPE_START_COMMAND = new ChannelTypeUID(BINDING_ID, "startCommand"); + public static final ChannelTypeUID CHANNEL_TYPE_LIGHT_COLOR = new ChannelTypeUID(BINDING_ID, "lightColor"); // List of all Properties public static final String DEVICE_PROPERTY_SERIAL_NUMBER = "serialNumber"; public static final String DEVICE_PROPERTY_FAMILY = "deviceFamily"; public static final String DEVICE_PROPERTY_FLASH_BRIEFING_PROFILE = "configurationJson"; + public static final String DEVICE_PROPERTY_APPLIANCE_ID = "applianceId"; + public static final String DEVICE_PROPERTY_LIGHT_ENTITY_ID = "entityId"; + public static final String DEVICE_PROPERTY_LIGHT_SUBDEVICE = "subDevice"; // Other public static final String FLASH_BRIEFING_COMMAND_PREFIX = "FlashBriefing."; + + // List of all smart bulb actions + public static final String DEVICE_TURN_ON = "turnOn"; + public static final String DEVICE_TURN_OFF = "turnOff"; + + // List of Alexa interfaces + public static final String INTERFACE_BRIGHTNESS = "Alexa.BrightnessController"; + public static final String INTERFACE_COLOR_TEMPERATURE = "Alexa.ColorTemperatureController"; + public static final String INTERFACE_COLOR = "Alexa.ColorController"; } diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/AmazonEchoControlHandlerFactory.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/AmazonEchoControlHandlerFactory.java index 4b7722e52ae07..b454dfaafdfdb 100755 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/AmazonEchoControlHandlerFactory.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/AmazonEchoControlHandlerFactory.java @@ -31,9 +31,11 @@ import org.eclipse.smarthome.core.thing.binding.ThingHandler; import org.eclipse.smarthome.core.thing.binding.ThingHandlerFactory; import org.openhab.binding.amazonechocontrol.internal.discovery.AmazonEchoDiscovery; +import org.openhab.binding.amazonechocontrol.internal.discovery.SmartHomeDevicesDiscovery; import org.openhab.binding.amazonechocontrol.internal.handler.AccountHandler; import org.openhab.binding.amazonechocontrol.internal.handler.EchoHandler; import org.openhab.binding.amazonechocontrol.internal.handler.FlashBriefingProfileHandler; +import org.openhab.binding.amazonechocontrol.internal.handler.SmartHomeDeviceHandler; import org.osgi.framework.ServiceRegistration; import org.osgi.service.component.ComponentContext; import org.osgi.service.component.annotations.Component; @@ -114,6 +116,11 @@ protected void deactivate(ComponentContext componentContext) { String.class.getClassLoader()); return new FlashBriefingProfileHandler(thing, storage); } + if (thingTypeUID.equals(THING_TYPE_LIGHT) || thingTypeUID.equals(THING_TYPE_LIGHT_GROUP)) { + Storage storage = storageService.getStorage(thing.getUID().toString(), + String.class.getClassLoader()); + return new SmartHomeDeviceHandler(thing, storage); + } if (SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID)) { return new EchoHandler(thing); } @@ -121,6 +128,11 @@ protected void deactivate(ComponentContext componentContext) { } private synchronized void registerDiscoveryService(AccountHandler bridgeHandler) { + SmartHomeDevicesDiscovery smartHomeDevicesDiscovery = new SmartHomeDevicesDiscovery(bridgeHandler); + smartHomeDevicesDiscovery.activate(); + this.discoveryServiceRegistrations.put(bridgeHandler.getThing().getUID(), bundleContext.registerService( + DiscoveryService.class.getName(), smartHomeDevicesDiscovery, new Hashtable())); + AmazonEchoDiscovery discoveryService = new AmazonEchoDiscovery(bridgeHandler); discoveryService.activate(); this.discoveryServiceRegistrations.put(bridgeHandler.getThing().getUID(), bundleContext 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 37a4c3eda30cf..12649a6d73d73 100755 --- 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 @@ -12,6 +12,8 @@ */ package org.openhab.binding.amazonechocontrol.internal; +import static org.openhab.binding.amazonechocontrol.internal.AmazonEchoControlBindingConstants.*; + import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -29,6 +31,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Base64; +import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.Hashtable; @@ -37,6 +40,8 @@ import java.util.Map; import java.util.Random; import java.util.Scanner; +import java.util.Set; +import java.util.UUID; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.zip.GZIPInputStream; @@ -46,6 +51,7 @@ import org.apache.commons.lang.StringUtils; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.thing.Thing; import org.eclipse.smarthome.core.util.HexUtils; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonActivities; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonActivities.Activity; @@ -58,6 +64,8 @@ import org.openhab.binding.amazonechocontrol.internal.jsons.JsonAutomation.Payload; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonAutomation.Trigger; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonBluetoothStates; +import org.openhab.binding.amazonechocontrol.internal.jsons.JsonColorTemperature; +import org.openhab.binding.amazonechocontrol.internal.jsons.JsonColors; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonDeviceNotificationState; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonDeviceNotificationState.DeviceNotificationState; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonDevices; @@ -87,6 +95,9 @@ import org.openhab.binding.amazonechocontrol.internal.jsons.JsonRegisterAppResponse.Success; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonRegisterAppResponse.Tokens; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonRenewTokenResponse; +import org.openhab.binding.amazonechocontrol.internal.jsons.JsonSmartHomeDeviceAlias; +import org.openhab.binding.amazonechocontrol.internal.jsons.JsonSmartHomeDevices.SmartHomeDevice; +import org.openhab.binding.amazonechocontrol.internal.jsons.JsonSmartHomeGroups.SmartHomeGroup; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonStartRoutineRequest; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonUsersMeResponse; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonWakeWords; @@ -98,8 +109,10 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonArray; +import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParseException; +import com.google.gson.JsonParser; import com.google.gson.JsonSyntaxException; /** @@ -834,6 +847,131 @@ public WakeWord[] getWakeWords() { return new WakeWord[0]; } + public List getSmarthomeDeviceList() throws IOException, URISyntaxException { + JsonObject json = new JsonParser().parse(getSmarthomeDeviceListJson()).getAsJsonObject(); + JsonObject smartHomeDevices = json.get("networkDetail").getAsJsonObject().get("locationDetails") + .getAsJsonObject().get("locationDetails").getAsJsonObject().get("Default_Location").getAsJsonObject() + .get("amazonBridgeDetails").getAsJsonObject().get("amazonBridgeDetails").getAsJsonObject() + .get("LambdaBridge_AAA/SonarCloudService").getAsJsonObject().get("applianceDetails").getAsJsonObject() + .get("applianceDetails").getAsJsonObject(); + ArrayList smartHomeDeviceArray = new ArrayList<>(); + Set keys = smartHomeDevices.keySet(); + for (String key : keys) { + JsonObject keyObject = smartHomeDevices.get(key).getAsJsonObject(); + // TODO + logger.error(keyObject.toString()); + SmartHomeDevice shd = parseJson(keyObject.toString(), SmartHomeDevice.class); + if (keyObject.get("aliases").getAsJsonArray().size() > 0) { + shd.alias = new JsonSmartHomeDeviceAlias[1]; + shd.alias[0] = new JsonSmartHomeDeviceAlias( + keyObject.get("aliases").getAsJsonArray().get(0).getAsJsonObject().get("friendlyName") + .getAsString(), + keyObject.get("aliases").getAsJsonArray().get(0).getAsJsonObject().get("enabled") + .getAsBoolean()); + } + if (keyObject.get("tags").getAsJsonObject().get("tagNameToValueSetMap").getAsJsonObject().size() > 0) { + shd.groupIdentity = keyObject.get("tags").getAsJsonObject().get("tagNameToValueSetMap") + .getAsJsonObject().get("groupIdentity").getAsJsonArray().get(0).getAsString(); + } + if (keyObject.get("capabilities").getAsJsonArray().size() > 0) { + for (JsonElement obj : keyObject.get("capabilities").getAsJsonArray()) { + String interfaceName = ((JsonObject) obj).get("interfaceName").getAsString(); + if (interfaceName.equals(INTERFACE_BRIGHTNESS)) { + shd.brightness = true; + } else if (interfaceName.equals(INTERFACE_COLOR_TEMPERATURE)) { + shd.colorTemperature = true; + } else if (interfaceName.equals(INTERFACE_COLOR)) { + shd.color = true; + } + } + } + smartHomeDeviceArray.add(shd); + } + + List groups = this.getSmarthomeDeviceGroups(); + + for (SmartHomeGroup group : groups) { + String uuid = UUID.randomUUID().toString(); + JsonSmartHomeDeviceAlias[] alias = new JsonSmartHomeDeviceAlias[1]; + ArrayList smartDevices = new ArrayList<>(); + + for (int i = 0; i < smartHomeDeviceArray.size(); ++i) { + if (smartHomeDeviceArray.get(i).groupIdentity != null && group.applianceGroupIdentifier != null) { + String groupIdentity = smartHomeDeviceArray.get(i).groupIdentity; + @SuppressWarnings("null") + String applianceGroupIdentifier = group.applianceGroupIdentifier.value; + if (groupIdentity != null && groupIdentity.equals(applianceGroupIdentifier)) { + smartDevices.add(smartHomeDeviceArray.get(i)); + if (group.applianceGroupName != null) { + alias[0] = new JsonSmartHomeDeviceAlias(group.applianceGroupName, true); + } + } + } + } + + SmartHomeDevice[] smartDevicesArray = new SmartHomeDevice[smartDevices.size()]; + smartDevices.toArray(smartDevicesArray); + + if (group.applianceGroupName != null) { + SmartHomeDevice shdGroup = new SmartHomeDevice(uuid, "Amazon", "Amazon Light Group", + group.applianceGroupName, "reachable", uuid, alias, smartDevicesArray); + + smartHomeDeviceArray.add(shdGroup); + } + + } + + if (smartHomeDeviceArray.isEmpty()) { + return new ArrayList<>(); + } + + return smartHomeDeviceArray; + } + + public List getSmarthomeDeviceGroups() throws IOException, URISyntaxException { + JsonObject json = new JsonParser().parse(getSmarthomeDeviceListJson()).getAsJsonObject(); + JsonObject smartHomeGroups = json.get("networkDetail").getAsJsonObject().get("locationDetails") + .getAsJsonObject().get("locationDetails").getAsJsonObject().get("Default_Location").getAsJsonObject() + .get("applianceGroups").getAsJsonObject().get("applianceGroups").getAsJsonObject(); + ArrayList smartHomeGroupArray = new ArrayList<>(); + Set keys = smartHomeGroups.keySet(); + for (String key : keys) { + JsonObject keyObject = smartHomeGroups.get(key).getAsJsonObject(); + SmartHomeGroup shg = parseJson(keyObject.toString(), SmartHomeGroup.class); + + smartHomeGroupArray.add(shg); + } + + if (smartHomeGroupArray.isEmpty()) { + return new ArrayList<>(); + } + + return smartHomeGroupArray; + } + + // Placeholder for an api-request + public List getEchoLightColors() { + ArrayList colors = new ArrayList<>(); + String[] stringColors = { "red", "crimson", "salmon", "orange", "gold", "yellow", "green", "turquoise", "cyan", + "sky_blue", "blue", "purple", "magenta", "pink", "lavender" }; + for (String color : stringColors) { + colors.add(new JsonColors(color)); + } + + return colors; + } + + // Placeholder for an api-request + public List getEchoLightTemperatures() { + ArrayList temperatures = new ArrayList<>(); + String[] stringTemperatures = { "warm_white", "soft_white", "white", "daylight_white", "cool_white" }; + for (String temperature : stringTemperatures) { + temperatures.add(new JsonColorTemperature(temperature)); + } + + return temperatures; + } + public List getDeviceList() throws IOException, URISyntaxException { String json = getDeviceListJson(); JsonDevices devices = parseJson(json, JsonDevices.class); @@ -844,11 +982,189 @@ public List getDeviceList() throws IOException, URISyntaxException { return new ArrayList<>(Arrays.asList(result)); } + public String getSmarthomeDeviceListJson() throws IOException, URISyntaxException { + String json = makeRequestAndReturnString(alexaServer + "/api/phoenix?includeRelationships=true"); + json = json.replace("\\", ""); + json = json.replace("\"{", "{"); + json = json.replace("}\"", "}"); + return json; + } + public String getDeviceListJson() throws IOException, URISyntaxException { String json = makeRequestAndReturnString(alexaServer + "/api/devices-v2/device?cached=false"); return json; } + public int getLightGroupBrightness(Thing device) throws IOException, URISyntaxException { + Map props = device.getProperties(); + List states = new ArrayList<>(); + if (props.containsKey(DEVICE_PROPERTY_APPLIANCE_ID + "0")) { + int counter = 0; + for (String key : props.keySet()) { + if (key.contains(DEVICE_PROPERTY_APPLIANCE_ID + counter)) { + JsonArray capabilities = this.getBulbCapabilities(props.get(key)); + + Float state = null; + for (JsonElement capability : capabilities) { + JsonObject capabilityObject = capability.getAsJsonObject(); + if (capabilityObject.get("namespace").getAsString().equals("Alexa.BrightnessController")) { + state = capabilityObject.get("value").getAsFloat(); + states.add(state); + } + } + ++counter; + } + } + + if (states.size() > 0) { + return Collections.max(states).intValue(); + } + } + + return -1; + } + + public String getBulbColor(Thing device) throws IOException, URISyntaxException { + Map props = device.getProperties(); + String applianceId = props.get(DEVICE_PROPERTY_APPLIANCE_ID); + + String color = null; + if (device.getThingTypeUID().equals(THING_TYPE_LIGHT)) { + JsonArray capabilities = this.getBulbCapabilities(applianceId); + + for (JsonElement capability : capabilities) { + JsonObject capabilityObject = capability.getAsJsonObject(); + if (capabilityObject.get("namespace").getAsString().equals("Alexa.ColorPropertiesController")) { + try { + color = capabilityObject.getAsJsonObject().get("value").getAsJsonObject().get("name") + .getAsString(); + } catch (Exception e) { + logger.error("getting bulb color failed {}", e); + } + } + } + } + + if (color != null) { + return color; + } else { + throw new IOException(); + } + } + + public int getBulbBrightness(Thing device) throws IOException, URISyntaxException { + Map props = device.getProperties(); + String applianceId = props.get(DEVICE_PROPERTY_APPLIANCE_ID); + JsonArray capabilities = this.getBulbCapabilities(applianceId); + + int brightness = -1; + if (device.getThingTypeUID().equals(THING_TYPE_LIGHT) + || device.getThingTypeUID().equals(THING_TYPE_LIGHT_GROUP)) { + for (JsonElement capability : capabilities) { + JsonObject capabilityObject = capability.getAsJsonObject(); + if (capabilityObject.get("namespace").getAsString().equals("Alexa.BrightnessController")) { + brightness = capabilityObject.get("value").getAsInt(); + } + } + + if (brightness == -1) { + return 100; + } + + return brightness; + } + return -1; + } + + public String getLightGroupState(Thing device) throws IOException, URISyntaxException { + Map props = device.getProperties(); + List states = new ArrayList<>(); + if (props.containsKey(DEVICE_PROPERTY_APPLIANCE_ID + "0")) { + int counter = 0; + for (String key : props.keySet()) { + if (key.contains(DEVICE_PROPERTY_APPLIANCE_ID + counter)) { + JsonArray capabilities = this.getBulbCapabilities(props.get(key)); + String state = null; + for (JsonElement capability : capabilities) { + JsonObject capabilityObject = capability.getAsJsonObject(); + if (capabilityObject.get("namespace").getAsString().equals("Alexa.PowerController")) { + state = capabilityObject.get("value").getAsString(); + states.add(state); + } + } + ++counter; + } + } + if (states.contains("ON")) { + return "ON"; + } else { + return "OFF"; + } + } + + throw new IOException(); + } + + public String getBulbState(Thing device) throws IOException, URISyntaxException { + Map props = device.getProperties(); + String applianceId = props.get(DEVICE_PROPERTY_APPLIANCE_ID); + + String state = null; + if (device.getThingTypeUID().equals(THING_TYPE_LIGHT) + || device.getThingTypeUID().equals(THING_TYPE_LIGHT_GROUP)) { + JsonArray capabilities = this.getBulbCapabilities(applianceId); + + for (JsonElement capability : capabilities) { + JsonObject capabilityObject = capability.getAsJsonObject(); + if (capabilityObject.get("namespace").getAsString().equals("Alexa.PowerController")) { + try { + state = capabilityObject.get("value").getAsString(); + } catch (Exception e) { + logger.error("getting bulb state failed {}", e); + } + } + } + } + + if (state == null) { + throw new IOException(); + } + + return state; + } + + public JsonArray getBulbCapabilities(String applianceId) throws IOException, URISyntaxException { + String json = this.getBulbStateJson(applianceId); + JsonElement jobject = new JsonParser().parse(json); + JsonArray capabilities = null; + + try { + capabilities = jobject.getAsJsonObject().get("deviceStates").getAsJsonArray().get(0).getAsJsonObject() + .get("capabilityStates").getAsJsonArray(); + } catch (Exception e) { + logger.error("getting capabilities failed {}", e); + } + + if (capabilities != null) { + return capabilities; + } + + throw new IOException(); + } + + public String getBulbStateJson(String applianceId) throws IOException, URISyntaxException { + String command = "{ \"stateRequests\": [{ \"entityId\": \"" + applianceId + + "\", \"entityType\": \"APPLIANCE\" }] }"; + String json = makeRequestAndReturnString("POST", alexaServer + "/api/phoenix/state", command, true, null); + json = json.replace("\\", ""); + json = json.replace("\"{", "{"); + json = json.replace("}\"", "}"); + if (!json.isEmpty()) { + return json; + } + throw new IOException(); + } + public JsonPlayerState getPlayer(Device device) throws IOException, URISyntaxException { String json = makeRequestAndReturnString(alexaServer + "/api/np/player?deviceSerialNumber=" + device.serialNumber + "&deviceType=" + device.deviceType + "&screenWidth=1440"); @@ -906,6 +1222,30 @@ public void command(Device device, String command) throws IOException, URISyntax makeRequest("POST", url, command, true, true, null); } + public void smartHomeCommand(String entityId, String action, @Nullable String color, double brightness) + throws IOException, URISyntaxException { + String url = alexaServer + "/api/phoenix/state"; + String requestBody = null; + if (action == "turnOn" || action == "turnOff") { + requestBody = "{\"controlRequests\": [{\"entityId\": " + "\"" + entityId + "\"" + + ", \"entityType\": \"APPLIANCE\", \"parameters\": { \"action\": " + "\"" + action + "\"" + + " }}]}"; + } else if (action == "setColorTemperature") { + requestBody = "{\"controlRequests\": [{\"entityId\": " + "\"" + entityId + "\"" + + ", \"entityType\": \"APPLIANCE\", \"parameters\": { \"action\": " + "\"" + action + "\"" + + ", \"colorTemperatureName\": \"" + color + "\" }}]}"; + } else if (action == "setColor") { + requestBody = "{\"controlRequests\": [{\"entityId\": " + "\"" + entityId + "\"" + + ", \"entityType\": \"APPLIANCE\", \"parameters\": { \"action\": " + "\"" + action + "\"" + + ", \"colorName\": \"" + color + "\" }}]}"; + } else if (action == "setBrightness") { + requestBody = "{\"controlRequests\": [{\"entityId\": " + "\"" + entityId + "\"" + + ", \"entityType\": \"APPLIANCE\", \"parameters\": { \"action\": " + "\"" + action + "\"" + + ", \"brightness\": \"" + brightness + "\" }}]}"; + } + makeRequest("PUT", url, requestBody, true, true, null); + } + public void notificationVolume(Device device, int volume) throws IOException, URISyntaxException { String url = alexaServer + "/api/device-notification-state/" + device.deviceType + "/" + device.softwareVersion + "/" + device.serialNumber; diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/discovery/SmartHomeDevicesDiscovery.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/discovery/SmartHomeDevicesDiscovery.java index 1840da3783f82..040fcbfd65cf5 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/discovery/SmartHomeDevicesDiscovery.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/discovery/SmartHomeDevicesDiscovery.java @@ -1,3 +1,15 @@ +/** + * Copyright (c) 2010-2019 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ package org.openhab.binding.amazonechocontrol.internal.discovery; import static org.openhab.binding.amazonechocontrol.internal.AmazonEchoControlBindingConstants.*; 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 3a3db9cd87cc5..eb7aed9ee95f3 100755 --- 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 @@ -64,6 +64,7 @@ import org.openhab.binding.amazonechocontrol.internal.jsons.JsonNotificationSound; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonPlaylists; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonPushCommand; +import org.openhab.binding.amazonechocontrol.internal.jsons.JsonSmartHomeDevices.SmartHomeDevice; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonWakeWords.WakeWord; import org.osgi.service.http.HttpService; import org.slf4j.Logger; @@ -85,6 +86,7 @@ public class AccountHandler extends BaseBridgeHandler implements IWebSocketComma private @Nullable Connection connection; private @Nullable WebSocketConnection webSocketConnection; private final Set echoHandlers = new HashSet<>(); + private final Set smartHomeDeviceHandlers = new HashSet<>(); private final Set flashBriefingProfileHandlers = new HashSet<>(); private final Object synchronizeConnection = new Object(); private Map jsonSerialNumberDeviceMapping = new HashMap<>(); @@ -142,6 +144,10 @@ public List getLastKnownDevices() { return new ArrayList<>(jsonSerialNumberDeviceMapping.values()); } + public List getSmartHomeDeviceHandlers() { + return new ArrayList<>(this.smartHomeDeviceHandlers); + } + public void addEchoHandler(EchoHandler echoHandler) { synchronized (echoHandlers) { if (!echoHandlers.add(echoHandler)) { @@ -151,6 +157,15 @@ public void addEchoHandler(EchoHandler echoHandler) { forceCheckData(); } + public void addSmartHomeDeviceHandler(SmartHomeDeviceHandler smartHomeDeviceHandler) { + synchronized (smartHomeDeviceHandler) { + if (!smartHomeDeviceHandlers.add(smartHomeDeviceHandler)) { + return; + } + } + forceCheckData(); + } + public void forceCheckData() { if (foceCheckDataJob == null) { foceCheckDataJob = scheduler.schedule(this::forceCheckDataHandler, 1000, TimeUnit.MILLISECONDS); @@ -554,6 +569,37 @@ private void refreshData() { return null; } + public List updateSmartHomeDeviceList() { + + Connection currentConnection = connection; + if (currentConnection == null) { + return new ArrayList(); + } + + List smartHomeDevices = null; + try { + if (currentConnection.getIsLoggedIn()) { + smartHomeDevices = currentConnection.getSmarthomeDeviceList(); + } + } catch (IOException | URISyntaxException e) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getLocalizedMessage()); + } + if (smartHomeDevices != null) { + Map newJsonSerialDeviceMapping = new HashMap<>(); + for (SmartHomeDevice smartDevice : smartHomeDevices) { + String entityId = smartDevice.entityId; + if (entityId != null) { + newJsonSerialDeviceMapping.put(entityId, smartDevice); + } + } + } + if (smartHomeDevices != null) { + return smartHomeDevices; + } + + return new ArrayList(); + } + public List updateDeviceList() { Connection currentConnection = connection; diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonSmartHomeDeviceAlias.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonSmartHomeDeviceAlias.java index 65cafc30fb12b..0b66996b48b6c 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonSmartHomeDeviceAlias.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonSmartHomeDeviceAlias.java @@ -15,4 +15,7 @@ public JsonSmartHomeDeviceAlias(String friendlyName, Boolean enabled) { this.friendlyName = friendlyName; this.enabled = enabled; } + + public JsonSmartHomeDeviceAlias() { + } } diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonSmartHomeDevices.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonSmartHomeDevices.java index d34f891edc678..1ac0d40d2cf41 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonSmartHomeDevices.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonSmartHomeDevices.java @@ -21,7 +21,7 @@ @NonNullByDefault public class JsonSmartHomeDevices { - public class SmartHomeDevice { + public static class SmartHomeDevice { public @Nullable String applianceId; public @Nullable String manufacturerName; public @Nullable String friendlyDescription; @@ -36,7 +36,7 @@ public class SmartHomeDevice { public boolean colorTemperature = false; public SmartHomeDevice(String applianceId, String manufacturerName, String friendlyDescription, - String friendlyName, String reachability, String entityId, JsonSmartHomeDeviceAlias[] alias, + @Nullable String friendlyName, String reachability, String entityId, JsonSmartHomeDeviceAlias[] alias, SmartHomeDevice[] groupDevices) { this.applianceId = applianceId; this.manufacturerName = manufacturerName; @@ -47,6 +47,9 @@ public SmartHomeDevice(String applianceId, String manufacturerName, String frien this.alias = alias; this.groupDevices = groupDevices; } + + public SmartHomeDevice() { + } } public @Nullable SmartHomeDevice @Nullable [] smarthomeDevices; diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonSmartHomeGroupIdentifiers.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonSmartHomeGroupIdentifiers.java index a20d85355bbae..c789e7ffb018f 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonSmartHomeGroupIdentifiers.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonSmartHomeGroupIdentifiers.java @@ -6,7 +6,7 @@ @NonNullByDefault public class JsonSmartHomeGroupIdentifiers { - public class SmartHomeGroupIdentifier { + public static class SmartHomeGroupIdentifier { public @Nullable String value; } diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonSmartHomeGroups.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonSmartHomeGroups.java index ade1d91152892..3ab977df9edca 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonSmartHomeGroups.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonSmartHomeGroups.java @@ -7,7 +7,7 @@ @NonNullByDefault public class JsonSmartHomeGroups { - public class SmartHomeGroup { + public static class SmartHomeGroup { public @Nullable String applianceGroupName; public @Nullable Boolean isSpace; public @Nullable Boolean space; diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.amazonechocontrol/src/main/resources/ESH-INF/thing/thing-types.xml index 54b7acb0f7a42..51623497cc959 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/resources/ESH-INF/thing/thing-types.xml @@ -1,6 +1,5 @@ - @@ -210,6 +209,32 @@ + + + + + + Represents a light in your amazon account + + + + + + + + + + + + + Group of light bulbs in your amazon account + + + + + + + Switch @@ -426,6 +451,7 @@ Ascending alarm up to the configured volume + DateTime @@ -450,4 +476,52 @@ Next timer + + Switch + + State (ON/OFF) of a light + + + String + + The color of a smart bulb + + + + + + + + + + + + + + + + + + + + + + String + + The temperature of white + + + + + + + + + + + + Dimmer + + The brightness of the light + From 987d8ebe73d35694ba8d1bfe1b5084e806f61cee Mon Sep 17 00:00:00 2001 From: Lkn94 Date: Sun, 9 Jun 2019 21:39:48 +0200 Subject: [PATCH 06/56] Added license information and author --- .../internal/handler/DeviceHandler.java | 2 -- .../internal/handler/SmartHomeDeviceHandler.java | 2 -- .../internal/jsons/JsonColorTemperature.java | 15 +++++++++++++++ .../internal/jsons/JsonColors.java | 15 +++++++++++++++ .../internal/jsons/JsonSmartHomeDeviceAlias.java | 14 +++++++++++++- .../internal/jsons/JsonSmartHomeDevices.java | 2 +- .../jsons/JsonSmartHomeGroupIdentifiers.java | 15 +++++++++++++++ .../internal/jsons/JsonSmartHomeGroups.java | 15 +++++++++++++++ ...mazonEchoDynamicStateDescriptionSmartHome.java | 12 ++++++++++++ 9 files changed, 86 insertions(+), 6 deletions(-) diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/handler/DeviceHandler.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/handler/DeviceHandler.java index 1bd2ff07b9720..c43ab975c00b4 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/handler/DeviceHandler.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/handler/DeviceHandler.java @@ -33,9 +33,7 @@ import org.slf4j.LoggerFactory; /** - * * @author Lukas Knoeller - * */ public class DeviceHandler extends BaseThingHandler { diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/handler/SmartHomeDeviceHandler.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/handler/SmartHomeDeviceHandler.java index 4bb024a5bbda3..42f707bde2789 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/handler/SmartHomeDeviceHandler.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/handler/SmartHomeDeviceHandler.java @@ -42,9 +42,7 @@ import org.slf4j.LoggerFactory; /** - * * @author Lukas Knoeller - * */ public class SmartHomeDeviceHandler extends BaseThingHandler { diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonColorTemperature.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonColorTemperature.java index 65ac12e075889..bdf8f94f004dd 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonColorTemperature.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonColorTemperature.java @@ -1,8 +1,23 @@ +/** + * Copyright (c) 2010-2019 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ package org.openhab.binding.amazonechocontrol.internal.jsons; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; +/** + * @author Lukas Knoeller + */ @NonNullByDefault public class JsonColorTemperature { public @Nullable String temperatureName; diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonColors.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonColors.java index 96d606174758f..129fe2988f37f 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonColors.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonColors.java @@ -1,8 +1,23 @@ +/** + * Copyright (c) 2010-2019 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ package org.openhab.binding.amazonechocontrol.internal.jsons; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; +/** + * @author Lukas Knoeller + */ @NonNullByDefault public class JsonColors { public @Nullable String colorName; diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonSmartHomeDeviceAlias.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonSmartHomeDeviceAlias.java index 0b66996b48b6c..81d62666ea991 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonSmartHomeDeviceAlias.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonSmartHomeDeviceAlias.java @@ -1,10 +1,22 @@ +/** + * Copyright (c) 2010-2019 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ package org.openhab.binding.amazonechocontrol.internal.jsons; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; /** - * @author Lukas Knoeller - Initial contribution + * @author Lukas Knoeller */ @NonNullByDefault public class JsonSmartHomeDeviceAlias { diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonSmartHomeDevices.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonSmartHomeDevices.java index 1ac0d40d2cf41..441c4deaeb121 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonSmartHomeDevices.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonSmartHomeDevices.java @@ -16,7 +16,7 @@ import org.eclipse.jdt.annotation.Nullable; /** - * @author Lukas Knoeller - Contributor + * @author Lukas Knoeller */ @NonNullByDefault public class JsonSmartHomeDevices { diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonSmartHomeGroupIdentifiers.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonSmartHomeGroupIdentifiers.java index c789e7ffb018f..bd766a06c3b0a 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonSmartHomeGroupIdentifiers.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonSmartHomeGroupIdentifiers.java @@ -1,8 +1,23 @@ +/** + * Copyright (c) 2010-2019 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ package org.openhab.binding.amazonechocontrol.internal.jsons; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; +/** + * @author Lukas Knoeller + */ @NonNullByDefault public class JsonSmartHomeGroupIdentifiers { diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonSmartHomeGroups.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonSmartHomeGroups.java index 3ab977df9edca..3f54db9051ecf 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonSmartHomeGroups.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonSmartHomeGroups.java @@ -1,9 +1,24 @@ +/** + * Copyright (c) 2010-2019 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ 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.jsons.JsonSmartHomeGroupIdentifiers.SmartHomeGroupIdentifier; +/** + * @author Lukas Knoeller + */ @NonNullByDefault public class JsonSmartHomeGroups { diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/statedescription/AmazonEchoDynamicStateDescriptionSmartHome.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/statedescription/AmazonEchoDynamicStateDescriptionSmartHome.java index a9e6d9d450cde..63cd4b88cd3b8 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/statedescription/AmazonEchoDynamicStateDescriptionSmartHome.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/statedescription/AmazonEchoDynamicStateDescriptionSmartHome.java @@ -1,3 +1,15 @@ +/** + * Copyright (c) 2010-2019 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ package org.openhab.binding.amazonechocontrol.internal.statedescription; import static org.openhab.binding.amazonechocontrol.internal.AmazonEchoControlBindingConstants.CHANNEL_TYPE_LIGHT_COLOR; From ecd8095590883e318cece37f0d87593bca6b1a5e Mon Sep 17 00:00:00 2001 From: Daniel Weber <25605184+fruggy83@users.noreply.github.com> Date: Mon, 10 Jun 2019 09:18:32 +0200 Subject: [PATCH 07/56] [enocean] Fixes EEP definition for A5_07_03 message handling class (#5705) Fixes #5704 Signed-off-by: Daniel Weber --- .../java/org/openhab/binding/enocean/internal/eep/EEPType.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/EEPType.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/EEPType.java index 3ea9ba2ce78ad..e36fc16cd1d16 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/EEPType.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/EEPType.java @@ -257,7 +257,7 @@ public enum EEPType { CHANNEL_MOTIONDETECTION, CHANNEL_BATTERY_VOLTAGE), OCCUPANCYSENSOR_A5_07_02(RORG._4BS, 0x07, 0x02, false, A5_07_02.class, THING_TYPE_OCCUPANCYSENSOR, CHANNEL_MOTIONDETECTION, CHANNEL_BATTERY_VOLTAGE), - OCCUPANCYSENSOR_A5_07_03(RORG._4BS, 0x07, 0x02, false, A5_07_03.class, THING_TYPE_OCCUPANCYSENSOR, + OCCUPANCYSENSOR_A5_07_03(RORG._4BS, 0x07, 0x03, false, A5_07_03.class, THING_TYPE_OCCUPANCYSENSOR, CHANNEL_ILLUMINATION, CHANNEL_MOTIONDETECTION, CHANNEL_BATTERY_VOLTAGE), LightTemperatureOccupancySensor_A5_08_01(RORG._4BS, 0x08, 0x01, false, A5_08_01.class, From b2d9d0f5e74d93c39dff5fcd834e9d40e344838e Mon Sep 17 00:00:00 2001 From: Lkn94 Date: Mon, 10 Jun 2019 09:52:00 +0200 Subject: [PATCH 08/56] Added contributor and readme information --- .../README.md | 40 +++++++++++++++++++ .../resources/ESH-INF/binding/binding.xml | 2 +- 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/bundles/org.openhab.binding.amazonechocontrol/README.md b/bundles/org.openhab.binding.amazonechocontrol/README.md index 9608894b142a5..6c788b07af8f0 100755 --- a/bundles/org.openhab.binding.amazonechocontrol/README.md +++ b/bundles/org.openhab.binding.amazonechocontrol/README.md @@ -26,6 +26,19 @@ It provides features to control and view the current state of echo devices: - change the equalizer settings - get information about the next alarm, reminder and timer +Also this binding includes the features to control your lights connected to your Echo devices: + +- turn on/off your lights +- change the color +- control groups of lights or just single bulbs +- receive the current state of the lights + +Restrictions: + +- groups can't receive their current color (multiple colors are possible) +- lights can only receive their state every 30 seconds +- turning on/off (or switch color, change brightness) will send a request for every single bulb in a group + Some ideas what you can do in your home by using rules and other openHAB controlled devices: - Automatic turn on your amplifier and connect echo with bluetooth if the echo plays music @@ -42,6 +55,14 @@ Some ideas what you can do in your home by using rules and other openHAB control - Change the equalizer settings depending on the bluetooth connection - Turn on a light on your alexa alarm time +With the possibility to control your lights you could do: + +- a scene-based configuration of your rooms +- connect single bulbs to functions of openhab +- simulate your presence at home +- automaticly turn on your lights at the evening +- integrate your smart bulbs with rules + ## Note This binding uses the same API as the Web-Browser-Based Alexa site (alexa.amazon.de). @@ -60,6 +81,8 @@ The binding is tested with amazon.de, amazon.fr, amazon.it, amazon.com and amazo | echoshow | Amazon Echo Show Device | | wha | Amazon Echo Whole House Audio Control | | flashbriefingprofile | Flash briefing profile | +| light | Smart bulbs connected to the Echo | +| lightGroup | Groups of lights | ## First Steps @@ -142,6 +165,10 @@ It will be configured at runtime by using the save channel to store the current | save | Switch | W | flashbriefingprofile | Write Only! Stores the current configuration of flash briefings within the thing | active | Switch | R/W | flashbriefingprofile | Active the profile | playOnDevice | String | W | flashbriefingprofile | Specify the echo serial number or name to start the flash briefing. +| lightState | Switch | R/W | light, lightGroup | Shows and changes the state (ON/OFF) of your light or lightgroup +| lightBrightness | Dimmer | R/W | light, lightGroup | Shows and changes the brightness of your light or lightgroup +| lightColor | String | R/W | light, lightGroup | Shows and changes the color of your light (groups are not able to show their color!) +| whiteTemperature | String | R/W | light, lightGroup | White temperatures of your lights ## Advanced Feature Technically Experienced Users @@ -242,6 +269,13 @@ String FlashBriefing_Technical_Play "Play (Write only)" { channel="amazonechoc Switch FlashBriefing_LifeStyle_Save "Save (Write only)" { channel="amazonechocontrol:flashbriefingprofile:account1:flashbriefing2:save"} Switch FlashBriefing_LifeStyle_Active "Active" { channel="amazonechocontrol:flashbriefingprofile:account1:flashbriefing2:active"} String FlashBriefing_LifeStyle_Play "Play (Write only)" { channel="amazonechocontrol:flashbriefingprofile:account1:flashbriefing2:playOnDevice"} + + +// Lights and lightgroups - you will find the applianceId in the properties of your light or lightgroup! +Switch Light_State "On/Off" { channel="amazonechocontrol:lightGroup:account1:applianceId:lightState" } +Dimmer Light_Brightness "Brightness" { channel="amazonechocontrol:lightGroup:account1:applianceId:lightBrightness" } +String Light_Color "Color" { channel="amazonechocontrol:lightGroup:account1:applianceId:lightColor" } +String Light_White "White temperature" { channel="amazonechocontrol:lightGroup:account1:applianceId:whiteTemperature" } ``` ### amazonechocontrol.sitemap: @@ -306,6 +340,12 @@ sitemap amazonechocontrol label="Echo Devices" Switch item=FlashBriefing_LifeStyle_Active Text item=FlashBriefing_LifeStyle_Play } + Frame label="Lights and light groups" { + Switch item=Light_State + Slider item=Light_Brightness + Selection item=Light_Color mappings=[ ''='', 'red'='Red', 'crimson'='Crimson', 'salmon'='Salmon', 'orange'='Orange', 'gold'='Gold', 'yellow'='Yellow', 'green'='Green', 'turquoise'='Turquoise', 'cyan'='Cyan', 'sky_blue'='Sky Blue', 'blue'='Blue', 'purple'='Purple', 'magenta'='Magenta', 'pink'='Pink', 'lavender'='Lavender' ] + Selection item=Light_White mappings=[ ''='', 'warm_white'='Warm white', 'soft_white'='Soft white', 'white'='White', 'daylight_white'='Daylight white', 'cool_white'='Cool white' ] + } } ``` diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.amazonechocontrol/src/main/resources/ESH-INF/binding/binding.xml index b6c76c2bd9f9a..27d95905a731b 100755 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/resources/ESH-INF/binding/binding.xml @@ -4,6 +4,6 @@ Amazon Echo Control Binding Binding to control Amazon Echo devices (Alexa). This binding enables openHAB to control the volume, playing state, bluetooth connection of your amazon echo devices or allow to use it as TTS device. - Michael Geramb + Michael Geramb, Lukas Knoeller From 51873b55641322548bd99811aa09361d48e40479 Mon Sep 17 00:00:00 2001 From: Wouter Born Date: Mon, 10 Jun 2019 10:11:15 +0200 Subject: [PATCH 09/56] [hueemulation] Fix warnings/stacktraces at startup (#5709) * Properly annotates optional references with nullable to fix NPEs * Reworked HueEmulationConfigWithRuntime.startNow to prevent IllegalStateException Fixes #5622 Signed-off-by: Wouter Born --- .../internal/HueEmulationService.java | 9 ++++--- .../internal/rest/LightsAndGroups.java | 14 +++++++---- .../internal/rest/StatusResource.java | 25 +++++++++++-------- .../upnp/HueEmulationConfigWithRuntime.java | 8 +++++- .../internal/upnp/UpnpServer.java | 2 +- 5 files changed, 36 insertions(+), 22 deletions(-) diff --git a/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/HueEmulationService.java b/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/HueEmulationService.java index dce7b2bc1bb92..680c9eda7c562 100644 --- a/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/HueEmulationService.java +++ b/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/HueEmulationService.java @@ -117,7 +117,7 @@ public void filter(ContainerRequestContext requestContext, ContainerResponseCont // Don't fail the service if the upnp server does not come up // That part is required for discovery only but does not affect already configured hue applications @Reference(cardinality = ReferenceCardinality.OPTIONAL, policyOption = ReferencePolicyOption.GREEDY) - protected @NonNullByDefault({}) UpnpServer discovery; + protected @Nullable UpnpServer discovery; @Reference protected @NonNullByDefault({}) ConfigStore cs; @Reference @@ -201,10 +201,11 @@ public void handleEvent(@Nullable Event event) { initParams.put("com.sun.jersey.api.json.POJOMappingFeature", "false"); initParams.put(ServletProperties.PROVIDER_WEB_APP, "false"); httpService.registerServlet(RESTAPI_PATH, new ServletContainer(resourceConfig), initParams, null); - if (discovery == null) { + UpnpServer localDiscovery = discovery; + if (localDiscovery == null) { logger.warn("The UPnP Server service has not been started!"); - } else if (!discovery.upnpAnnouncementThreadRunning()) { - discovery.handleEvent(null); + } else if (!localDiscovery.upnpAnnouncementThreadRunning()) { + localDiscovery.handleEvent(null); } statusResource.startUpnpSelfTest(); logger.info("Hue Emulation service available under {}", RESTAPI_PATH); diff --git a/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/rest/LightsAndGroups.java b/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/rest/LightsAndGroups.java index e66d62fb92759..f4e5c5fa10563 100644 --- a/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/rest/LightsAndGroups.java +++ b/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/rest/LightsAndGroups.java @@ -32,6 +32,7 @@ import javax.ws.rs.core.UriInfo; import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.core.common.registry.RegistryChangeListener; import org.eclipse.smarthome.core.events.EventPublisher; import org.eclipse.smarthome.core.items.GenericItem; @@ -111,7 +112,7 @@ public class LightsAndGroups implements RegistryChangeListener { @Reference protected @NonNullByDefault({}) ItemRegistry itemRegistry; @Reference(policy = ReferencePolicy.DYNAMIC, cardinality = ReferenceCardinality.OPTIONAL) - protected volatile @NonNullByDefault({}) EventPublisher eventPublisher; + protected volatile @Nullable EventPublisher eventPublisher; /** * Registers to the {@link ItemRegistry} and enumerates currently existing items. @@ -373,9 +374,10 @@ public Response setLightStateApi(@Context UriInfo uri, // // If a command could be created, post it to the framework now if (command != null) { - if (eventPublisher != null) { + EventPublisher localEventPublisher = eventPublisher; + if (localEventPublisher != null) { logger.debug("sending {} to {}", command, itemUID); - eventPublisher.post(ItemEventFactory.createCommandEvent(itemUID, command, "hueemulation")); + localEventPublisher.post(ItemEventFactory.createCommandEvent(itemUID, command, "hueemulation")); } else { logger.warn("No event publisher. Cannot post item '{}' command!", itemUID); } @@ -418,8 +420,10 @@ public Response setGroupActionApi(@Context UriInfo uri, // // If a command could be created, post it to the framework now if (command != null) { logger.debug("sending {} to {}", command, id); - if (eventPublisher != null) { - eventPublisher.post(ItemEventFactory.createCommandEvent(groupItem.getUID(), command, "hueemulation")); + EventPublisher localEventPublisher = eventPublisher; + if (localEventPublisher != null) { + localEventPublisher + .post(ItemEventFactory.createCommandEvent(groupItem.getUID(), command, "hueemulation")); } else { logger.warn("No event publisher. Cannot post item '{}' command!", groupItem.getUID()); } diff --git a/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/rest/StatusResource.java b/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/rest/StatusResource.java index a8157d0ab918d..b7cdc3dcd76d8 100644 --- a/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/rest/StatusResource.java +++ b/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/rest/StatusResource.java @@ -54,7 +54,7 @@ @NonNullByDefault public class StatusResource implements RegistryListener { @Reference(cardinality = ReferenceCardinality.OPTIONAL, policyOption = ReferencePolicyOption.GREEDY) - protected @NonNullByDefault({}) UpnpServer discovery; + protected @Nullable UpnpServer discovery; @Reference protected @NonNullByDefault({}) ConfigStore cs; @Reference @@ -125,12 +125,11 @@ private static String TR(String s) { @Path("status") @Produces("text/html") public String getStatus() { - if (discovery == null) { // Optional service wiring + UpnpServer localDiscovery = discovery; + if (localDiscovery == null) { // Optional service wiring return "UPnP Server service not started!"; } - int httpPort = discovery.getDefaultport(); - String format = "

Self test

" + // "

To access any links you need be in pairing mode!

" + // "

Pairing mode: %s (%s) Enable | Enable with bridge V1 emulation

" @@ -145,18 +144,18 @@ public String getStatus() { + // "

Users

    %s
"; - final String users = cs.ds.config.whitelist.entrySet().stream().map(user -> "
  • " + user.getKey() + " " + String users = cs.ds.config.whitelist.entrySet().stream().map(user -> "
  • " + user.getKey() + " " + user.getValue().name + " " + user.getValue().lastUseDate + "") .collect(Collectors.joining("\n")); - final String url = "http://" + cs.ds.config.ipaddress + ":" + String.valueOf(httpPort); + String url = "http://" + cs.ds.config.ipaddress + ":" + String.valueOf(localDiscovery.getDefaultport()); - final String reachable = discovery.selfTests().stream() + String reachable = localDiscovery.selfTests().stream() .map(entry -> TR(TD(entry.address) + TD(toYesNo(entry.reachable)) + TD(toYesNo(entry.isOurs)))) .collect(Collectors.joining("\n")); Registry registry = upnpService.getRegistry(); - final String upnps; + String upnps; if (registry != null) { upnps = registry.getRemoteDevices().stream().map(device -> getDetails(device)) .map(details -> TR(TD(details.getSerialNumber()) + TD(details.getFriendlyName()))) @@ -165,7 +164,7 @@ public String getStatus() { upnps = TR(TD("service not available") + TD("")); } - if (!discovery.upnpAnnouncementThreadRunning()) { + if (!localDiscovery.upnpAnnouncementThreadRunning()) { selfTestUpnpFound = upnpStatus.upnp_announcement_thread_not_running; } @@ -224,7 +223,9 @@ public void remoteDeviceUpdated(Registry registry, RemoteDevice device) { @NonNullByDefault({}) @Override public void remoteDeviceRemoved(Registry registry, RemoteDevice device) { - if (selfTestUpnpFound != upnpStatus.success || discovery.upnpAnnouncementThreadRunning()) { + UpnpServer localDiscovery = discovery; + if (selfTestUpnpFound != upnpStatus.success || localDiscovery == null + || localDiscovery.upnpAnnouncementThreadRunning()) { return; } DeviceDetails details = getDetails(device); @@ -237,7 +238,9 @@ public void remoteDeviceRemoved(Registry registry, RemoteDevice device) { @NonNullByDefault({}) @Override public void localDeviceAdded(Registry registry, LocalDevice device) { - if (selfTestUpnpFound == upnpStatus.success || discovery.upnpAnnouncementThreadRunning()) { + UpnpServer localDiscovery = discovery; + if (selfTestUpnpFound == upnpStatus.success || localDiscovery == null + || localDiscovery.upnpAnnouncementThreadRunning()) { return; } checkForDevice(getDetails(device)); diff --git a/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/upnp/HueEmulationConfigWithRuntime.java b/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/upnp/HueEmulationConfigWithRuntime.java index 98c127f65aa91..a2de10d0d0c6e 100644 --- a/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/upnp/HueEmulationConfigWithRuntime.java +++ b/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/upnp/HueEmulationConfigWithRuntime.java @@ -23,6 +23,8 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.openhab.io.hueemulation.internal.HueEmulationConfig; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * The upnp server runtime configuration. Based on a {@link HueEmulationConfig} and determined ip address and port. @@ -33,6 +35,9 @@ */ @NonNullByDefault class HueEmulationConfigWithRuntime extends Thread implements Runnable { + + private final Logger logger = LoggerFactory.getLogger(HueEmulationConfigWithRuntime.class); + final @NonNullByDefault({}) HueEmulationConfig config; final InetAddress address; final String addressString; @@ -93,7 +98,8 @@ String getMulticastAddress() { public synchronized CompletableFuture<@Nullable HueEmulationConfigWithRuntime> startNow( @Nullable HueEmulationConfigWithRuntime ignored) { if (hasAlreadyBeenStarted) { - throw new IllegalStateException("Cannot restart thread"); + logger.debug("Cannot restart thread"); + return future; } hasAlreadyBeenStarted = true; super.start(); diff --git a/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/upnp/UpnpServer.java b/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/upnp/UpnpServer.java index 0c277a0940a6a..11d5de2faffc1 100644 --- a/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/upnp/UpnpServer.java +++ b/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/upnp/UpnpServer.java @@ -339,7 +339,7 @@ private void useAddressPort(HueEmulationConfigWithRuntime r) { * configuration ready event and depending on service start order we are also called by our own activate() method * when the configuration is already ready at that time. *

    - * Therefore this method is "synchronized" and chains a completeable future for each call to re-evaluate the config + * Therefore this method is "synchronized" and chains a completable future for each call to re-evaluate the config * after the former future has finished. */ @Override From d96d2d59e18285b7f5f6d05148030130225b1e29 Mon Sep 17 00:00:00 2001 From: Daniel Weber <25605184+fruggy83@users.noreply.github.com> Date: Mon, 10 Jun 2019 16:24:37 +0200 Subject: [PATCH 10/56] [enocean] Improve incoming message handling for Eltako rollershutters (#5703) Fixes #5702 Signed-off-by: Daniel Weber --- .../EnOceanChannelRollershutterConfig.java | 2 +- .../eep/A5_3F/A5_3F_7F_EltakoFSB.java | 20 +++++++++++++------ .../handler/EnOceanBaseSensorHandler.java | 2 +- .../resources/ESH-INF/thing/Rollershutter.xml | 1 + 4 files changed, 17 insertions(+), 8 deletions(-) diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/config/EnOceanChannelRollershutterConfig.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/config/EnOceanChannelRollershutterConfig.java index 8d2eb503fb781..9e2291b8028e1 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/config/EnOceanChannelRollershutterConfig.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/config/EnOceanChannelRollershutterConfig.java @@ -18,7 +18,7 @@ */ public class EnOceanChannelRollershutterConfig { - public Integer shutTime; + public int shutTime; public EnOceanChannelRollershutterConfig() { shutTime = 255; diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_3F/A5_3F_7F_EltakoFSB.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_3F/A5_3F_7F_EltakoFSB.java index 39173b6620bec..0da5eb17c2132 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_3F/A5_3F_7F_EltakoFSB.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_3F/A5_3F_7F_EltakoFSB.java @@ -96,16 +96,24 @@ protected State convertToStateImpl(String channelId, String channelTypeId, State currentState = getCurrentStateFunc.apply(channelId); if (currentState != null) { - int direction = getDB_1() == MoveUp ? -1 : 1; int duration = ((getDB_3Value() << 8) + getDB_2Value()) / 10; // => Time in DB3 and DB2 is given // in ms - PercentType current = currentState.as(PercentType.class); - if (config != null && current != null) { + if (config != null) { EnOceanChannelRollershutterConfig c = config.as(EnOceanChannelRollershutterConfig.class); - if (c.shutTime != -1 && c.shutTime != 0) { - return new PercentType(Math.min(100, (Math.max(0, current.intValue() - + direction * ((duration * PercentType.HUNDRED.intValue()) / c.shutTime))))); + if (duration == c.shutTime) { + return getDB_1() == MoveUp ? PercentType.ZERO : PercentType.HUNDRED; + } else { + PercentType current = PercentType.ZERO; + if (currentState instanceof PercentType) { + current = currentState.as(PercentType.class); + } + + int direction = getDB_1() == MoveUp ? -1 : 1; + if (c.shutTime != -1 && c.shutTime != 0) { + return new PercentType(Math.min(100, (Math.max(0, current.intValue() + + direction * ((duration * PercentType.HUNDRED.intValue()) / c.shutTime))))); + } } } } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/handler/EnOceanBaseSensorHandler.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/handler/EnOceanBaseSensorHandler.java index 2cddf477f78a1..542dd1780a6b1 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/handler/EnOceanBaseSensorHandler.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/handler/EnOceanBaseSensorHandler.java @@ -154,7 +154,7 @@ public void espPacketReceived(ESP3Packet packet) { EEP eep = EEPFactory.buildEEP(receivingEEPType, (ERP1Message) packet); logger.debug("ESP Packet payload {} for {} received", HexUtils.bytesToHex(packet.getPayload()), - config.enoceanId); + HexUtils.bytesToHex(msg.getSenderId())); if (eep.isValid()) { byte[] senderId = msg.getSenderId(); diff --git a/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/Rollershutter.xml b/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/Rollershutter.xml index 541d58f82ded1..89aae59187e69 100644 --- a/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/Rollershutter.xml +++ b/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/Rollershutter.xml @@ -48,6 +48,7 @@ + 4 true From 906776ccae8ac6bf7b5a00dd47522bfb1b1b6ecc Mon Sep 17 00:00:00 2001 From: Wouter Born Date: Mon, 10 Jun 2019 19:16:18 +0200 Subject: [PATCH 11/56] Upgrade Karaf to 4.2.6 (#5708) For Karaf 4.2.5 release notes, see: https://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12311140&version=12345153 For Karaf 4.2.6 release notes, see: https://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12311140&version=12345365 Signed-off-by: Wouter Born --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index b623483697f7b..0263483969c42 100644 --- a/pom.xml +++ b/pom.xml @@ -67,7 +67,7 @@ ${oh.java.version} 4.2.0 - 4.2.4 + 4.2.6 0.6.1 1.7.21 From ca773f7dfe56538706044ca1f3e3c52e639fd260 Mon Sep 17 00:00:00 2001 From: tmrobert8 Date: Mon, 10 Jun 2019 14:25:05 -0400 Subject: [PATCH 12/56] Added VSCode ignores to gitignore (#5712) Signed-off-by: Tim Roberts --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index ebbad56526f89..e283419c70d51 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,6 @@ xtend-gen/ bundles/**/src/main/history features/**/src/main/history features/**/src/main/feature + +.vscode +.factorypath From d2dc38fe603f9e38bb52fd9e0a3c294521e1b39f Mon Sep 17 00:00:00 2001 From: Helmut Lehmeyer Date: Tue, 11 Jun 2019 08:24:51 +0200 Subject: [PATCH 13/56] [knx] Docu: simplify Bridge and Thing configuration (#5713) [knx] Documentation: simplify Bridge and Thing configuration Simplification and more concrete information on Bridge and Thing configuration. https://github.com/openhab/openhab2-addons/issues/5281#issuecomment-498284324 Signed-off-by: lewie helmut.lehmeyer@gmail.com --- bundles/org.openhab.binding.knx/README.md | 57 +++++++++++++++++++---- 1 file changed, 49 insertions(+), 8 deletions(-) diff --git a/bundles/org.openhab.binding.knx/README.md b/bundles/org.openhab.binding.knx/README.md index 1f963dd5fa890..fd2ec6128d57a 100644 --- a/bundles/org.openhab.binding.knx/README.md +++ b/bundles/org.openhab.binding.knx/README.md @@ -183,22 +183,50 @@ Each configuration parameter has a `mainGA` where commands are written to and op The `dpt` element is optional. If ommitted, the corresponding default value will be used (see the channel descriptions above). -## Examples - -### Full Example +## Examples +The following two templates are sufficient for almost all purposes. Only add parameters to the Bridge and Thing configuration if you know exactly what functionality it is needed for. +### Type ROUTER mode configuration Template +knx.things: +```xtend +Bridge knx:ip:bridge [ + type="ROUTER", + autoReconnectPeriod=60 //optional, do not set <30 sec. +] { + Thing device knx_device "knx_device_name" @ "knx_device_group_in_paperui" [ + //readInterval=3600 //optional, only used if reading values are present + ] { + //Items configurations + } +} +``` +### Type TUNNEL mode configuration Template knx.things: - ```xtend Bridge knx:ip:bridge [ + type="TUNNEL", + ipAddress="192.168.0.111", + autoReconnectPeriod=60 //optional, do not set <30 sec. +] { + Thing device knx_device "knx_device_name" @ "knx_device_group_in_paperui" [ + //readInterval=3600 //optional, only used if reading values are present + ] { + //Items configurations + } +} +``` +### Full Example +```xtend +//TUNNEL +Bridge knx:ip:bridge [ + type="TUNNEL", ipAddress="192.168.0.10", portNumber=3671, - localIp="192.168.0.11", - type="TUNNEL", + localIp="192.168.0.11", readingPause=50, responseTimeout=10, readRetriesLimit=3, - autoReconnectPeriod=1, + autoReconnectPeriod=60, localSourceAddr="0.0.0" ] { Thing device generic [ @@ -216,6 +244,19 @@ Bridge knx:ip:bridge [ Type datetime : demoDatetime "Alarm" [ ga="5/5/42" ] } } + +//ROUTER +Bridge knx:ip:bridge [ + type="ROUTER", + ipAddress="224.0.23.12", + portNumber=3671, + localIp="192.168.0.11", + readingPause=50, + responseTimeout=10, + readRetriesLimit=3, + autoReconnectPeriod=60, + localSourceAddr="0.0.0" +] {} ``` knx.items: @@ -258,7 +299,7 @@ Bridge knx:serial:bridge [ readingPause=50, responseTimeout=10, readRetriesLimit=3, - autoReconnectPeriod=1 + autoReconnectPeriod=60 ] { Thing device generic { Type switch-control : controlSwitch "Control Switch" [ ga="3/3/10+<3/3/11" ] // '<' signs are allowed but will be ignored for control Channels From 504b52a9a8e7206e8c429587945a3291bedda97a Mon Sep 17 00:00:00 2001 From: J-N-K Date: Wed, 12 Jun 2019 21:52:18 +0200 Subject: [PATCH 14/56] remove wrapping and force dependency install (#5707) Signed-off-by: Jan N. Klug --- .../src/main/feature/feature.xml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/bundles/org.openhab.binding.xmppclient/src/main/feature/feature.xml b/bundles/org.openhab.binding.xmppclient/src/main/feature/feature.xml index fb23e4f4b80cd..d6fc0ab5158a7 100644 --- a/bundles/org.openhab.binding.xmppclient/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.xmppclient/src/main/feature/feature.xml @@ -4,8 +4,7 @@ openhab-runtime-base - wrap - mvn:org.igniterealtime.smack/smack-java7/4.3.3 + mvn:org.igniterealtime.smack/smack-extensions/4.3.3 mvn:org.igniterealtime.smack/smack-im/4.3.3 mvn:org.igniterealtime.smack/smack-tcp/4.3.3 @@ -14,9 +13,11 @@ mvn:org.jxmpp/jxmpp-util-cache/0.6.3 mvn:org.minidns/minidns-core/0.3.3 mvn:org.igniterealtime.smack/smack-core/4.3.3 - mvn:org.igniterealtime.smack/smack-resolver-javax/4.3.3 mvn:org.igniterealtime.smack/smack-sasl-javax/4.3.3 - wrap:mvn:xpp3/xpp3/1.1.4c$Bundle-Name=XPP3%20Library&Bundle-SymbolicName=xpp3-xpp3&Bundle-Version=1.1.4 + mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.xpp3/1.1.4c_7 + + mvn:org.igniterealtime.smack/smack-resolver-javax/4.3.3 + mvn:org.igniterealtime.smack/smack-java7/4.3.3 mvn:org.openhab.addons.bundles/org.openhab.binding.xmppclient/${project.version} From 95f8cb11cdda9b90b761697f992523846d264daa Mon Sep 17 00:00:00 2001 From: vbier Date: Wed, 12 Jun 2019 21:53:28 +0200 Subject: [PATCH 15/56] Fix jeelink serial connection broken by #5497. (#5717) Signed-off-by: Volker Bier --- .../connection/JeeLinkSerialConnection.java | 34 +++++++++---------- 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/bundles/org.openhab.binding.jeelink/src/main/java/org/openhab/binding/jeelink/internal/connection/JeeLinkSerialConnection.java b/bundles/org.openhab.binding.jeelink/src/main/java/org/openhab/binding/jeelink/internal/connection/JeeLinkSerialConnection.java index b94a0c42b39b6..cbd393731f4f4 100644 --- a/bundles/org.openhab.binding.jeelink/src/main/java/org/openhab/binding/jeelink/internal/connection/JeeLinkSerialConnection.java +++ b/bundles/org.openhab.binding.jeelink/src/main/java/org/openhab/binding/jeelink/internal/connection/JeeLinkSerialConnection.java @@ -16,7 +16,6 @@ import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStream; -import java.io.Reader; import java.util.TooManyListenersException; import org.slf4j.Logger; @@ -79,26 +78,25 @@ public synchronized void openConnection() { serialPort.setSerialPortParams(baudRate, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); - try (Reader isr = new InputStreamReader(serialPort.getInputStream()); - BufferedReader input = new BufferedReader(isr)) { - serialPort.addEventListener(new SerialPortEventListener() { - @Override - public void serialEvent(SerialPortEvent event) { - try { - if (event.getEventType() == SerialPortEvent.DATA_AVAILABLE) { - propagateLine(input.readLine()); - } - } catch (IOException ex) { - logger.debug("Error reading from serial port!", ex); - closeConnection(); - notifyAbort("propagate: " + ex.getMessage()); + final BufferedReader input = new BufferedReader(new InputStreamReader(serialPort.getInputStream())); + + serialPort.addEventListener(new SerialPortEventListener() { + @Override + public void serialEvent(SerialPortEvent event) { + try { + if (event.getEventType() == SerialPortEvent.DATA_AVAILABLE) { + propagateLine(input.readLine()); } + } catch (IOException ex) { + logger.debug("Error reading from serial port!", ex); + closeConnection(); + notifyAbort("propagate: " + ex.getMessage()); } - }); + } + }); - serialPort.notifyOnDataAvailable(true); - notifyOpen(); - } + serialPort.notifyOnDataAvailable(true); + notifyOpen(); } } catch (UnsupportedCommOperationException | IOException | TooManyListenersException ex) { closeConnection(); From 3b47874a0fa503f699a1edbc80c38389c5848876 Mon Sep 17 00:00:00 2001 From: funkstille <13382630+funkstille@users.noreply.github.com> Date: Wed, 12 Jun 2019 22:35:48 +0200 Subject: [PATCH 16/56] [dmx] fix documentation typo (#5686) --- bundles/org.openhab.binding.dmx/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundles/org.openhab.binding.dmx/README.md b/bundles/org.openhab.binding.dmx/README.md index daa0deeee8eda..5c60b9774c6b9 100644 --- a/bundles/org.openhab.binding.dmx/README.md +++ b/bundles/org.openhab.binding.dmx/README.md @@ -194,7 +194,7 @@ The next `ON` command uses these values instead of the default (or configuration |-----------------|---------------------|----------------------|----------------------------------------------------| |brightness |dimmer, tunablewhite |Switch, Dimmer | controls the brightness | |color |color |Switch, Dimmer, Color | allows to set the color and brightness | -|colortemperature |tunablewhite |Number | allows to set the color temperature | +|color_temperature|tunablewhite |Number | allows to set the color temperature | |brightness_r |color |Switch, Dimmer | controls the brightness of the red channel | |brightness_g |color |Switch, Dimmer | controls the brightness of the green channel | |brightness_b |color |Switch, Dimmer | controls the brightness of the blue channel | From 1c5ce817d50af23222f8710e506736ce47552058 Mon Sep 17 00:00:00 2001 From: Juergen Benz Date: Fri, 14 Jun 2019 12:10:41 +0200 Subject: [PATCH 17/56] [keba] Add setenergy command (#5595) * introduce setenergylimit command (for openhab#4417) this is adding read and write item setenergylimit to set a charging limit in Wh Signed-off-by: tiptick --- bundles/org.openhab.binding.keba/README.md | 3 +++ .../keba/internal/KebaBindingConstants.java | 1 + .../keba/internal/handler/KeContactHandler.java | 14 ++++++++++++++ .../src/main/resources/ESH-INF/thing/kecontact.xml | 7 +++++++ 4 files changed, 25 insertions(+) diff --git a/bundles/org.openhab.binding.keba/README.md b/bundles/org.openhab.binding.keba/README.md index 9d91b67597578..84c623b2d0f9d 100644 --- a/bundles/org.openhab.binding.keba/README.md +++ b/bundles/org.openhab.binding.keba/README.md @@ -42,6 +42,7 @@ All devices support the following channels: | sessionrfidtag | String | yes | RFID tag used for the last charging session | | sessionrfidclass | String | yes | RFID tag class used for the last charging session | | sessionid | Number | yes | session ID of the last charging session | +| setenergylimit | Number | no | set an energy limit for an already running or the next charging session| ## Example @@ -76,6 +77,7 @@ Number KebaSessionEnergy {channel="keba:kecontact:1:sessionconsumption"} Number KebaTotalEnergy {channel="keba:kecontact:1:totalconsumption"} Switch KebaInputSwitch {channel="keba:kecontact:1:input"} Switch KebaOutputSwitch {channel="keba:kecontact:1:output"} +Number KebaSetEnergyLimit {channel="keba:kecontact:1:setenergylimit"} ``` demo.sitemap: @@ -96,6 +98,7 @@ sitemap demo label="Main Menu" Text item=KebaFailSafeCurrent label="Failsafe supply current [%.0f mA]" Text item=KebaSessionEnergy label="Energy during current session [%.0f Wh]" Text item=KebaTotalEnergy label="Energy during all sessions [%.0f Wh]" + Switch item=KebaSetEnergyLimit label="Set charge energy limit" mappings=[0="off", 20000="20kWh"] } } ``` diff --git a/bundles/org.openhab.binding.keba/src/main/java/org/openhab/binding/keba/internal/KebaBindingConstants.java b/bundles/org.openhab.binding.keba/src/main/java/org/openhab/binding/keba/internal/KebaBindingConstants.java index 68d663bb77310..c10fe983e9a43 100644 --- a/bundles/org.openhab.binding.keba/src/main/java/org/openhab/binding/keba/internal/KebaBindingConstants.java +++ b/bundles/org.openhab.binding.keba/src/main/java/org/openhab/binding/keba/internal/KebaBindingConstants.java @@ -69,6 +69,7 @@ public class KebaBindingConstants { public static final String CHANNEL_SESSION_RFID_TAG = "sessionrfidtag"; public static final String CHANNEL_SESSION_RFID_CLASS = "sessionrfidclass"; public static final String CHANNEL_SESSION_SESSION_ID = "sessionid"; + public static final String CHANNEL_SETENERGY = "setenergylimit"; public enum KebaType { P20, diff --git a/bundles/org.openhab.binding.keba/src/main/java/org/openhab/binding/keba/internal/handler/KeContactHandler.java b/bundles/org.openhab.binding.keba/src/main/java/org/openhab/binding/keba/internal/handler/KeContactHandler.java index bcf684c616042..123db4d738dde 100644 --- a/bundles/org.openhab.binding.keba/src/main/java/org/openhab/binding/keba/internal/handler/KeContactHandler.java +++ b/bundles/org.openhab.binding.keba/src/main/java/org/openhab/binding/keba/internal/handler/KeContactHandler.java @@ -467,6 +467,12 @@ protected void onData(ByteBuffer byteBuffer) { updateState(CHANNEL_SESSION_SESSION_ID, newState); break; } + case "Setenergy": { + int state = entry.getValue().getAsInt() / 10; + State newState = new DecimalType(state); + updateState(CHANNEL_SETENERGY, newState); + break; + } } } } catch (JsonParseException e) { @@ -548,6 +554,14 @@ public void handleCommand(ChannelUID channelUID, Command command) { } break; } + case CHANNEL_SETENERGY: { + if (command instanceof DecimalType) { + transceiver.send( + "setenergy " + String.valueOf( + Math.min(Math.max(0, ((DecimalType) command).intValue()*10), 999999999)), this); + } + break; + } } } } diff --git a/bundles/org.openhab.binding.keba/src/main/resources/ESH-INF/thing/kecontact.xml b/bundles/org.openhab.binding.keba/src/main/resources/ESH-INF/thing/kecontact.xml index dea303d475a7e..2d8c5f3919f5f 100644 --- a/bundles/org.openhab.binding.keba/src/main/resources/ESH-INF/thing/kecontact.xml +++ b/bundles/org.openhab.binding.keba/src/main/resources/ESH-INF/thing/kecontact.xml @@ -53,6 +53,7 @@ + @@ -245,4 +246,10 @@ Session ID of the last charging session + + Number + + An energy limit for an already running or the next charging session. + + From 47b7c8fdf9aaada9963b8cbd79bc340a3c3db7d3 Mon Sep 17 00:00:00 2001 From: Martin van Wingerden Date: Fri, 14 Jun 2019 14:28:31 +0200 Subject: [PATCH 18/56] [network] DHCPTest.java (#5726) In maven the tests tends to fail, so by using an assume we can disable it automaticly if the precondition does not hold. Signed-off-by: Martin van Wingerden --- .../org/openhab/binding/network/internal/dhcp/DHCPTest.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/bundles/org.openhab.binding.network/src/test/java/org/openhab/binding/network/internal/dhcp/DHCPTest.java b/bundles/org.openhab.binding.network/src/test/java/org/openhab/binding/network/internal/dhcp/DHCPTest.java index 64ae230462a34..19b4d802e61fb 100644 --- a/bundles/org.openhab.binding.network/src/test/java/org/openhab/binding/network/internal/dhcp/DHCPTest.java +++ b/bundles/org.openhab.binding.network/src/test/java/org/openhab/binding/network/internal/dhcp/DHCPTest.java @@ -14,6 +14,7 @@ import static org.hamcrest.CoreMatchers.*; import static org.junit.Assert.assertThat; +import static org.junit.Assume.assumeTrue; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.*; @@ -34,7 +35,9 @@ public class DHCPTest { public void testService() throws SocketException { String testIP = "10.1.2.3"; IPRequestReceivedCallback dhcpListener = mock(IPRequestReceivedCallback.class); - assertThat(DHCPListenService.instance, is(nullValue())); + + // if this is not the case this test is not very useful, we don't always have the static field under control. + assumeTrue(DHCPListenService.instance == null); DHCPListenService.register(testIP, dhcpListener); assertThat(DHCPListenService.instance, is(notNullValue())); DHCPListenService.unregister(testIP); From 894028b2dcd1cd1b064e2f1262af356410e1d010 Mon Sep 17 00:00:00 2001 From: Nick Hill <42085028+knikhilwiz@users.noreply.github.com> Date: Fri, 14 Jun 2019 06:38:56 -0700 Subject: [PATCH 19/56] [globalcache] Update the Item type for Contact Closures to "Switch" (#5721) * Update the Item type for Contact Closures to Switch The "Contact" item type cannot actually accept commands, so move it to a Switch. The documentation (https://www.openhab.org/addons/bindings/globalcache/) refers to defining these as both Contact and Switch types, but a Contact type is not very useful if you want to change the state of a relay. --- bundles/org.openhab.binding.globalcache/README.md | 2 +- .../src/main/resources/ESH-INF/thing/channel-types.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bundles/org.openhab.binding.globalcache/README.md b/bundles/org.openhab.binding.globalcache/README.md index b2d905edd7ce4..4004bc3e05228 100644 --- a/bundles/org.openhab.binding.globalcache/README.md +++ b/bundles/org.openhab.binding.globalcache/README.md @@ -135,7 +135,7 @@ A *Contact Closure channel* activates the contact closure (relay) on the iTach o For example, the following item links to the module 1, connector 1 channel on an iTach CC device. ``` -Contact MyRelay "My Relay [%s]" (gRelays) { channel="globalcache:itachCC:000C1E039BCF:cc-m1#c1" } +Switch MyRelay "My Relay [%s]" (gRelays) { channel="globalcache:itachCC:000C1E039BCF:cc-m1#c1" } ``` The item definition for an iTach Flex WiFi device would look like this. diff --git a/bundles/org.openhab.binding.globalcache/src/main/resources/ESH-INF/thing/channel-types.xml b/bundles/org.openhab.binding.globalcache/src/main/resources/ESH-INF/thing/channel-types.xml index 103e1eac1b866..9bbe57a5bf5a3 100644 --- a/bundles/org.openhab.binding.globalcache/src/main/resources/ESH-INF/thing/channel-types.xml +++ b/bundles/org.openhab.binding.globalcache/src/main/resources/ESH-INF/thing/channel-types.xml @@ -12,7 +12,7 @@ - Contact + Switch Transmits contact closure command on module:connector From f3219acfba52c08a41b1dd8cd6a339d40eaef767 Mon Sep 17 00:00:00 2001 From: Martin van Wingerden Date: Fri, 14 Jun 2019 18:55:02 +0200 Subject: [PATCH 20/56] [hueemulation] seperate ipv4 / ipv6 (#5727) Resolves exception of combining ipv4 / ipv6 by getting to separate channels Closes #5589 Exception in thread "HueEmulation UPNP Server" java.lang.IllegalArgumentException: IPv6 socket cannot join IPv4 multicast group at sun.nio.ch.DatagramChannelImpl.innerJoin(DatagramChannelImpl.java:808) at sun.nio.ch.DatagramChannelImpl.join(DatagramChannelImpl.java:894) at org.openhab.io.hueemulation.internal.upnp.UpnpServer.accept(UpnpServer.java:439) at org.openhab.io.hueemulation.internal.upnp.UpnpServer.accept(UpnpServer.java:1) at org.openhab.io.hueemulation.internal.upnp.HueEmulationConfigWithRuntime.run(HueEmulationConfigWithRuntime.java:105) Signed-off-by: Martin van Wingerden --- .../JerseyServletContainerInitializer.java | 2 +- .../internal/HueEmulationService.java | 3 +- .../automation/TimerTriggerHandler.java | 2 +- .../internal/rest/ConfigurationAccess.java | 6 +-- .../io/hueemulation/internal/rest/Rules.java | 2 +- .../io/hueemulation/internal/rest/Scenes.java | 2 +- .../hueemulation/internal/rest/Schedules.java | 2 +- .../internal/upnp/UpnpServer.java | 51 +++++++++---------- .../automation/RuleConditionHandlerTests.java | 2 +- .../internal/rest/LightsAndGroupsTests.java | 31 ++++++----- .../internal/rest/SensorTests.java | 4 +- .../internal/rest/UsersAndConfigTests.java | 11 ++-- .../rest/mocks/DummyItemRegistry.java | 4 +- 13 files changed, 59 insertions(+), 63 deletions(-) diff --git a/bundles/org.openhab.io.hueemulation/src/main/java/org/glassfish/jersey/servlet/init/JerseyServletContainerInitializer.java b/bundles/org.openhab.io.hueemulation/src/main/java/org/glassfish/jersey/servlet/init/JerseyServletContainerInitializer.java index 26e16582dde2a..344ec0588a77f 100644 --- a/bundles/org.openhab.io.hueemulation/src/main/java/org/glassfish/jersey/servlet/init/JerseyServletContainerInitializer.java +++ b/bundles/org.openhab.io.hueemulation/src/main/java/org/glassfish/jersey/servlet/init/JerseyServletContainerInitializer.java @@ -25,7 +25,7 @@ */ public class JerseyServletContainerInitializer implements ServletContainerInitializer { @Override - public void onStartup(Set> c, ServletContext ctx) throws ServletException { + public void onStartup(Set> c, ServletContext ctx) { } } diff --git a/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/HueEmulationService.java b/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/HueEmulationService.java index 680c9eda7c562..d7133f31adbd2 100644 --- a/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/HueEmulationService.java +++ b/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/HueEmulationService.java @@ -91,8 +91,7 @@ public static class JerseyApplication extends Application { public class LogAccessInterceptor implements ContainerResponseFilter { @NonNullByDefault({}) @Override - public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) - throws IOException { + public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) { if (!logger.isDebugEnabled()) { return; diff --git a/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/automation/TimerTriggerHandler.java b/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/automation/TimerTriggerHandler.java index a6e0cbec60ba9..4d56fb1e4f116 100644 --- a/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/automation/TimerTriggerHandler.java +++ b/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/automation/TimerTriggerHandler.java @@ -113,7 +113,7 @@ public synchronized void dispose() { } @Override - public Duration call() throws Exception { + public Duration call() { ((TriggerHandlerCallback) callback).triggered(module, null); config.repeat -= 1; if (config.repeat == 0) { diff --git a/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/rest/ConfigurationAccess.java b/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/rest/ConfigurationAccess.java index 09ba6045c7959..53ef26ffa613f 100644 --- a/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/rest/ConfigurationAccess.java +++ b/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/rest/ConfigurationAccess.java @@ -78,7 +78,7 @@ public Response getReducedConfigApi() { @ApiOperation(value = "Return the full data store") @ApiResponses(value = { @ApiResponse(code = 200, message = "OK") }) public Response getAllApi(@Context UriInfo uri, - @PathParam("username") @ApiParam(value = "username") String username) throws IOException { + @PathParam("username") @ApiParam(value = "username") String username) { if (!userManagement.authorizeUser(username)) { return NetworkUtils.singleError(cs.gson, uri, HueResponse.UNAUTHORIZED, "Not Authorized"); } @@ -91,7 +91,7 @@ public Response getAllApi(@Context UriInfo uri, @ApiOperation(value = "Return the configuration") @ApiResponses(value = { @ApiResponse(code = 200, message = "OK") }) public Response getFullConfigApi(@Context UriInfo uri, - @PathParam("username") @ApiParam(value = "username") String username) throws IOException { + @PathParam("username") @ApiParam(value = "username") String username) { if (!userManagement.authorizeUser(username)) { return NetworkUtils.singleError(cs.gson, uri, HueResponse.UNAUTHORIZED, "Not Authorized"); } @@ -104,7 +104,7 @@ public Response getFullConfigApi(@Context UriInfo uri, @ApiOperation(value = "Return the reduced configuration") @ApiResponses(value = { @ApiResponse(code = 200, message = "OK") }) public Response putFullConfigApi(@Context UriInfo uri, - @PathParam("username") @ApiParam(value = "username") String username, String body) throws IOException { + @PathParam("username") @ApiParam(value = "username") String username, String body) { if (!userManagement.authorizeUser(username)) { return NetworkUtils.singleError(cs.gson, uri, HueResponse.UNAUTHORIZED, "Not Authorized"); } diff --git a/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/rest/Rules.java b/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/rest/Rules.java index 56b30bc5544fc..7f16240bc0419 100644 --- a/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/rest/Rules.java +++ b/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/rest/Rules.java @@ -239,7 +239,7 @@ protected static List createActions(String uid, List hueActi @ApiOperation(value = "Return all rules") @ApiResponses(value = { @ApiResponse(code = 200, message = "OK") }) public Response getRulesApi(@Context UriInfo uri, - @PathParam("username") @ApiParam(value = "username") String username) throws IOException { + @PathParam("username") @ApiParam(value = "username") String username) { if (!userManagement.authorizeUser(username)) { return NetworkUtils.singleError(cs.gson, uri, HueResponse.UNAUTHORIZED, "Not Authorized"); } diff --git a/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/rest/Scenes.java b/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/rest/Scenes.java index 64d6529efcbe6..7ee44ba57b102 100644 --- a/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/rest/Scenes.java +++ b/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/rest/Scenes.java @@ -169,7 +169,7 @@ public void updated(Rule oldElement, Rule element) { @ApiOperation(value = "Return all scenes") @ApiResponses(value = { @ApiResponse(code = 200, message = "OK") }) public Response getScenesApi(@Context UriInfo uri, - @PathParam("username") @ApiParam(value = "username") String username) throws IOException { + @PathParam("username") @ApiParam(value = "username") String username) { if (!userManagement.authorizeUser(username)) { return NetworkUtils.singleError(cs.gson, uri, HueResponse.UNAUTHORIZED, "Not Authorized"); } diff --git a/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/rest/Schedules.java b/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/rest/Schedules.java index 29e749e31ec9a..80472599edca8 100644 --- a/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/rest/Schedules.java +++ b/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/rest/Schedules.java @@ -232,7 +232,7 @@ protected static Rule createRule(String uid, RuleBuilder builder, List o @ApiOperation(value = "Return all schedules") @ApiResponses(value = { @ApiResponse(code = 200, message = "OK") }) public Response getSchedulesApi(@Context UriInfo uri, - @PathParam("username") @ApiParam(value = "username") String username) throws IOException { + @PathParam("username") @ApiParam(value = "username") String username) { if (!userManagement.authorizeUser(username)) { return NetworkUtils.singleError(cs.gson, uri, HueResponse.UNAUTHORIZED, "Not Authorized"); } diff --git a/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/upnp/UpnpServer.java b/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/upnp/UpnpServer.java index 11d5de2faffc1..e43b62c3678b3 100644 --- a/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/upnp/UpnpServer.java +++ b/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/upnp/UpnpServer.java @@ -17,16 +17,7 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.io.PrintWriter; -import java.net.DatagramPacket; -import java.net.DatagramSocket; -import java.net.Inet4Address; -import java.net.Inet6Address; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.NetworkInterface; -import java.net.SocketAddress; -import java.net.StandardSocketOptions; -import java.net.UnknownHostException; +import java.net.*; import java.nio.ByteBuffer; import java.nio.channels.ClosedSelectorException; import java.nio.channels.DatagramChannel; @@ -37,7 +28,6 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; -import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; import java.util.concurrent.ForkJoinPool; @@ -155,7 +145,7 @@ public UpnpServer(Executor executor) { */ @NonNullByDefault({}) @Override - protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + protected void service(HttpServletRequest req, HttpServletResponse resp) throws IOException { if (xmlDocWithAddress == null || xmlDocWithAddress.isEmpty()) { resp.sendError(HttpServletResponse.SC_NOT_FOUND); return; @@ -208,7 +198,7 @@ protected void activate() { } private void useAddressPort(HueEmulationConfigWithRuntime r) { - final String urlBase = "http://" + r.addressString + ":" + String.valueOf(r.port); + final String urlBase = "http://" + r.addressString + ":" + r.port; this.baseurl = urlBase + DISCOVERY_FILE; final String[] stVersions = { "upnp:rootdevice", "urn:schemas-upnp-org:device:basic:1", @@ -271,7 +261,7 @@ private void useAddressPort(HueEmulationConfigWithRuntime r) { ip = "[" + ip.split("%")[0] + "]"; } try { - url = "http://" + ip + ":" + String.valueOf(config.port) + DISCOVERY_FILE; + url = "http://" + ip + ":" + config.port + DISCOVERY_FILE; response = client.target(url).request().get(); boolean isOurs = response.readEntity(String.class).contains(cs.ds.config.bridgeid); selfTests.add(new SelfTestReport(url, response.getStatus() == 200, isOurs)); @@ -308,7 +298,7 @@ private void useAddressPort(HueEmulationConfigWithRuntime r) { r = new HueEmulationConfigWithRuntime(this, cs.getConfig(), cs.ds.config.ipaddress, MULTI_ADDR_IPV4, MULTI_ADDR_IPV6); } catch (UnknownHostException e) { - logger.warn("The picked default IP address is not valid: ", e.getMessage()); + logger.warn("The picked default IP address is not valid: {}", e.getMessage()); throw new IllegalStateException(e); } return r; @@ -363,8 +353,6 @@ public synchronized void handleEvent(@Nullable Event event) { /** * Stops the upnp server from running - * - * @throws InterruptedException */ @Deactivate public void deactivate() { @@ -375,7 +363,7 @@ public void deactivate() { } } - private void handleRead(SelectionKey key, Set addresses) throws IOException { + private void handleRead(SelectionKey key) throws IOException { logger.trace("upnp thread handle received message"); DatagramChannel channel = (DatagramChannel) key.channel(); ClientRecord clntRec = (ClientRecord) key.attachment(); @@ -424,22 +412,25 @@ public void accept(HueEmulationConfigWithRuntime threadContext) { boolean hasIPv4 = false; boolean hasIPv6 = false; - try (DatagramChannel channel = DatagramChannel.open(); Selector selector = Selector.open()) { + try ( + DatagramChannel channelV4 = DatagramChannel.open(StandardProtocolFamily.INET); + DatagramChannel channelV6 = DatagramChannel.open(StandardProtocolFamily.INET6); + Selector selector = Selector.open()) { threadContext.asyncIOselector = selector; - channel.setOption(StandardSocketOptions.SO_REUSEADDR, true) - .setOption(StandardSocketOptions.IP_MULTICAST_LOOP, true).bind(new InetSocketAddress(UPNP_PORT)); + bind(channelV4); + bind(channelV6); for (InetAddress address : cs.getDiscoveryIps()) { NetworkInterface networkInterface = NetworkInterface.getByInetAddress(address); if (networkInterface == null) { continue; } if (address instanceof Inet4Address) { - channel.join(MULTI_ADDR_IPV4, networkInterface); + channelV4.join(MULTI_ADDR_IPV4, networkInterface); hasIPv4 = true; } else { - channel.join(MULTI_ADDR_IPV6, networkInterface); + channelV6.join(MULTI_ADDR_IPV6, networkInterface); hasIPv6 = true; } } @@ -450,16 +441,18 @@ public void accept(HueEmulationConfigWithRuntime threadContext) { return; } - channel.configureBlocking(false); - channel.register(selector, SelectionKey.OP_READ, new ClientRecord()); if (hasIPv4) { + channelV4.configureBlocking(false); + channelV4.register(selector, SelectionKey.OP_READ, new ClientRecord()); try (DatagramSocket sendSocket = new DatagramSocket(new InetSocketAddress(config.address, 0))) { sendUPNPDatagrams(sendSocket, MULTI_ADDR_IPV4, UPNP_PORT); } } if (hasIPv6) { + channelV6.configureBlocking(false); + channelV6.register(selector, SelectionKey.OP_READ, new ClientRecord()); try (DatagramSocket sendSocket = new DatagramSocket()) { sendUPNPDatagrams(sendSocket, MULTI_ADDR_IPV6, UPNP_PORT); } @@ -475,7 +468,7 @@ public void accept(HueEmulationConfigWithRuntime threadContext) { while (keyIter.hasNext()) { SelectionKey key = keyIter.next(); if (key.isReadable()) { - handleRead(key, cs.getDiscoveryIps()); + handleRead(key); } keyIter.remove(); } @@ -504,6 +497,12 @@ public void accept(HueEmulationConfigWithRuntime threadContext) { } } + private void bind(DatagramChannel channel) throws IOException { + channel.setOption(StandardSocketOptions.SO_REUSEADDR, true) + .setOption(StandardSocketOptions.IP_MULTICAST_LOOP, true) + .bind(new InetSocketAddress(UPNP_PORT)); + } + /** * The upnp server performs some self-tests * diff --git a/bundles/org.openhab.io.hueemulation/src/test/java/org/openhab/io/hueemulation/internal/automation/RuleConditionHandlerTests.java b/bundles/org.openhab.io.hueemulation/src/test/java/org/openhab/io/hueemulation/internal/automation/RuleConditionHandlerTests.java index d972fbfb128ca..738cc9be11f80 100644 --- a/bundles/org.openhab.io.hueemulation/src/test/java/org/openhab/io/hueemulation/internal/automation/RuleConditionHandlerTests.java +++ b/bundles/org.openhab.io.hueemulation/src/test/java/org/openhab/io/hueemulation/internal/automation/RuleConditionHandlerTests.java @@ -67,7 +67,7 @@ protected LocalDateTime getNow() { } @Before - public void setUp() throws IOException { + public void setUp() { ds = new HueDataStore(); ds.lights.put("1", new HueLightEntry(new SwitchItem("switch"), "switch", DeviceType.SwitchType)); diff --git a/bundles/org.openhab.io.hueemulation/src/test/java/org/openhab/io/hueemulation/internal/rest/LightsAndGroupsTests.java b/bundles/org.openhab.io.hueemulation/src/test/java/org/openhab/io/hueemulation/internal/rest/LightsAndGroupsTests.java index cf99574e590a9..796c3b8cfd9b0 100644 --- a/bundles/org.openhab.io.hueemulation/src/test/java/org/openhab/io/hueemulation/internal/rest/LightsAndGroupsTests.java +++ b/bundles/org.openhab.io.hueemulation/src/test/java/org/openhab/io/hueemulation/internal/rest/LightsAndGroupsTests.java @@ -89,7 +89,7 @@ public void tearDown() { } @Test - public void addSwitchableByCategory() throws IOException { + public void addSwitchableByCategory() { SwitchItem item = new SwitchItem("switch1"); item.setCategory("Light"); itemRegistry.add(item); @@ -100,7 +100,7 @@ public void addSwitchableByCategory() throws IOException { } @Test - public void addSwitchableByTag() throws IOException { + public void addSwitchableByTag() { SwitchItem item = new SwitchItem("switch1"); item.addTag("Switchable"); itemRegistry.add(item); @@ -110,7 +110,7 @@ public void addSwitchableByTag() throws IOException { } @Test - public void ignoreByTag() throws IOException { + public void ignoreByTag() { SwitchItem item = new SwitchItem("switch1"); item.addTags("Switchable", "internal"); // The ignore tag will win itemRegistry.add(item); @@ -119,7 +119,7 @@ public void ignoreByTag() throws IOException { } @Test - public void addGroupSwitchableByTag() throws IOException { + public void addGroupSwitchableByTag() { GroupItem item = new GroupItem("group1", new SwitchItem("switch1")); item.addTag("Switchable"); itemRegistry.add(item); @@ -129,7 +129,7 @@ public void addGroupSwitchableByTag() throws IOException { } @Test - public void addGroupWithoutTypeByTag() throws IOException { + public void addGroupWithoutTypeByTag() { GroupItem item = new GroupItem("group1", null); item.addTag("Switchable"); @@ -142,7 +142,7 @@ public void addGroupWithoutTypeByTag() throws IOException { } @Test - public void removeGroupWithoutTypeAndTag() throws IOException { + public void removeGroupWithoutTypeAndTag() { String groupName = "group1"; GroupItem item = new GroupItem(groupName, null); item.addTag("Switchable"); @@ -157,7 +157,7 @@ public void removeGroupWithoutTypeAndTag() throws IOException { } @Test - public void updateSwitchable() throws IOException { + public void updateSwitchable() { SwitchItem item = new SwitchItem("switch1"); item.setLabel("labelOld"); item.addTag("Switchable"); @@ -187,7 +187,7 @@ public void updateSwitchable() throws IOException { } @Test - public void changeSwitchState() throws IOException { + public void changeSwitchState() { assertThat(((HueStatePlug) cs.ds.lights.get("1").state).on, is(false)); @@ -204,7 +204,7 @@ public void changeSwitchState() throws IOException { } @Test - public void changeGroupItemSwitchState() throws IOException { + public void changeGroupItemSwitchState() { assertThat(((HueStatePlug) cs.ds.groups.get("10").action).on, is(false)); @@ -221,7 +221,7 @@ public void changeGroupItemSwitchState() throws IOException { } @Test - public void changeOnValue() throws IOException { + public void changeOnValue() { assertThat(((HueStateColorBulb) cs.ds.lights.get("2").state).on, is(false)); @@ -235,7 +235,7 @@ public void changeOnValue() throws IOException { } @Test - public void changeOnAndBriValues() throws IOException { + public void changeOnAndBriValues() { assertThat(((HueStateColorBulb) cs.ds.lights.get("2").state).on, is(false)); assertThat(((HueStateColorBulb) cs.ds.lights.get("2").state).bri, is(0)); @@ -250,7 +250,7 @@ public void changeOnAndBriValues() throws IOException { } @Test - public void changeHueSatValues() throws IOException { + public void changeHueSatValues() { HueLightEntry hueDevice = cs.ds.lights.get("2"); hueDevice.item.setState(OnOffType.ON); hueDevice.state.as(HueStateColorBulb.class).on = true; @@ -271,7 +271,7 @@ public void changeHueSatValues() throws IOException { * Amazon echos are setting ct only, if commanded to turn a light white. */ @Test - public void changeCtValue() throws IOException { + public void changeCtValue() { HueLightEntry hueDevice = cs.ds.lights.get("2"); hueDevice.item.setState(OnOffType.ON); hueDevice.state.as(HueStateColorBulb.class).on = true; @@ -292,7 +292,7 @@ public void changeCtValue() throws IOException { } @Test - public void switchOnWithXY() throws IOException { + public void switchOnWithXY() { assertThat(((HueStateColorBulb) cs.ds.lights.get("2").state).on, is(false)); assertThat(((HueStateColorBulb) cs.ds.lights.get("2").state).bri, is(0)); @@ -313,8 +313,7 @@ public void switchOnWithXY() throws IOException { } @Test - public void allLightsAndSingleLight() - throws InterruptedException, ExecutionException, TimeoutException, IOException { + public void allLightsAndSingleLight() { Response response = commonSetup.client.target(commonSetup.basePath + "/testuser/lights").request().get(); assertEquals(200, response.getStatus()); diff --git a/bundles/org.openhab.io.hueemulation/src/test/java/org/openhab/io/hueemulation/internal/rest/SensorTests.java b/bundles/org.openhab.io.hueemulation/src/test/java/org/openhab/io/hueemulation/internal/rest/SensorTests.java index 4418ecaf0838b..a6e5583f2423f 100644 --- a/bundles/org.openhab.io.hueemulation/src/test/java/org/openhab/io/hueemulation/internal/rest/SensorTests.java +++ b/bundles/org.openhab.io.hueemulation/src/test/java/org/openhab/io/hueemulation/internal/rest/SensorTests.java @@ -92,7 +92,7 @@ public void tearDown() { } @Test - public void renameSensor() throws IOException { + public void renameSensor() { assertThat(cs.ds.sensors.get("switch1").name, is("name1")); @@ -107,7 +107,7 @@ public void renameSensor() throws IOException { } @Test - public void allAndSingleSensor() throws InterruptedException, ExecutionException, TimeoutException, IOException { + public void allAndSingleSensor() { Response response = commonSetup.client.target(commonSetup.basePath + "/testuser/sensors").request().get(); assertEquals(200, response.getStatus()); diff --git a/bundles/org.openhab.io.hueemulation/src/test/java/org/openhab/io/hueemulation/internal/rest/UsersAndConfigTests.java b/bundles/org.openhab.io.hueemulation/src/test/java/org/openhab/io/hueemulation/internal/rest/UsersAndConfigTests.java index 12727fb1045a0..1c6dd124e796f 100644 --- a/bundles/org.openhab.io.hueemulation/src/test/java/org/openhab/io/hueemulation/internal/rest/UsersAndConfigTests.java +++ b/bundles/org.openhab.io.hueemulation/src/test/java/org/openhab/io/hueemulation/internal/rest/UsersAndConfigTests.java @@ -68,17 +68,17 @@ public void tearDown() { } @Test - public void invalidUser() throws IOException { + public void invalidUser() { assertFalse(commonSetup.userManagement.authorizeUser("blub")); } @Test - public void validUser() throws IOException { + public void validUser() { assertTrue(commonSetup.userManagement.authorizeUser("testuser")); } @Test - public void configStoreRestartOnNoUUID() throws IOException { + public void configStoreRestartOnNoUUID() { ConfigStore configStore = new ConfigStoreWithoutMetadata(commonSetup.networkAddressService, commonSetup.configAdmin, commonSetup.scheduler); @@ -95,7 +95,7 @@ public void configStoreRestartOnNoUUID() throws IOException { } @Test - public void addUser() throws IOException { + public void addUser() { // GET should fail assertEquals(405, commonSetup.client.target(commonSetup.basePath).request().get().getStatus()); @@ -123,8 +123,7 @@ public void addUser() throws IOException { } @Test - public void UnauthorizedAccessTest() - throws InterruptedException, ExecutionException, TimeoutException, IOException { + public void UnauthorizedAccessTest() { // Unauthorized config Response response; diff --git a/bundles/org.openhab.io.hueemulation/src/test/java/org/openhab/io/hueemulation/internal/rest/mocks/DummyItemRegistry.java b/bundles/org.openhab.io.hueemulation/src/test/java/org/openhab/io/hueemulation/internal/rest/mocks/DummyItemRegistry.java index aa7c366b49648..200a4d6f109c7 100644 --- a/bundles/org.openhab.io.hueemulation/src/test/java/org/openhab/io/hueemulation/internal/rest/mocks/DummyItemRegistry.java +++ b/bundles/org.openhab.io.hueemulation/src/test/java/org/openhab/io/hueemulation/internal/rest/mocks/DummyItemRegistry.java @@ -90,12 +90,12 @@ public Item add(Item element) { } @Override - public Item getItem(@Nullable String name) throws ItemNotFoundException { + public Item getItem(@Nullable String name) { return items.get(name); } @Override - public Item getItemByPattern(String name) throws ItemNotFoundException, ItemNotUniqueException { + public Item getItemByPattern(String name) { return items.get(name); } From 3cf0803382858ae7cb86917b3a617751d1f458e2 Mon Sep 17 00:00:00 2001 From: Wouter Born Date: Sat, 15 Jun 2019 07:03:44 +0200 Subject: [PATCH 21/56] Fix missing feature bundles (#5731) Adapt regular expression so it also matches the bundles of the openhab-io-webaudio and openhab-misc-market features. Signed-off-by: Wouter Born --- features/openhab-addons/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/openhab-addons/pom.xml b/features/openhab-addons/pom.xml index 7235214003a90..2be013a8b2d48 100644 --- a/features/openhab-addons/pom.xml +++ b/features/openhab-addons/pom.xml @@ -50,7 +50,7 @@ - +