From 4d169fc2d7c7ba4bffcd027a2ad7961b06f01f99 Mon Sep 17 00:00:00 2001 From: Michael Geramb Date: Thu, 24 May 2018 14:04:04 +0200 Subject: [PATCH] [amazonechocontrol] Initial contribution for the Amazon Echo Control Binding (#3083) (#3087) Signed-off-by: Michael Geramb (github: mgeramb) --- .../.classpath | 12 + .../.project | 33 + .../ESH-INF/binding/binding.xml | 9 + .../i18n/amazonechocontrol_de.properties | 135 +++ .../ESH-INF/thing/thing-types.xml | 355 +++++++ .../META-INF/MANIFEST.MF | 38 + .../OSGI-INF/.gitignore | 1 + .../README.md | 384 +++++++ .../about.html | 32 + .../build.properties | 8 + .../lib/jsoup-1.10.1.jar | Bin 0 -> 345536 bytes .../pom.xml | 19 + .../AmazonEchoControlBindingConstants.java | 94 ++ .../handler/AccountHandler.java | 559 +++++++++++ .../handler/EchoHandler.java | 800 +++++++++++++++ .../handler/FlashBriefingProfileHandler.java | 200 ++++ .../internal/AccountConfiguration.java | 30 + .../internal/AccountServlet.java | 511 ++++++++++ .../AmazonEchoControlHandlerFactory.java | 165 ++++ .../internal/BindingServlet.java | 126 +++ .../internal/Connection.java | 935 ++++++++++++++++++ .../internal/ConnectionException.java | 26 + .../internal/HttpException.java | 32 + .../internal/StateStorage.java | 113 +++ .../discovery/AmazonEchoDiscovery.java | 225 +++++ .../internal/jsons/JsonAutomation.java | 43 + .../internal/jsons/JsonBluetoothStates.java | 61 ++ .../internal/jsons/JsonDevices.java | 36 + .../internal/jsons/JsonEnabledFeeds.java | 23 + .../internal/jsons/JsonFeed.java | 25 + .../internal/jsons/JsonMediaState.java | 80 ++ .../internal/jsons/JsonMusicProvider.java | 30 + .../jsons/JsonNotificationRequest.java | 37 + .../jsons/JsonNotificationResponse.java | 65 ++ .../internal/jsons/JsonNotificationSound.java | 26 + .../jsons/JsonNotificationSounds.java | 22 + .../JsonPlaySearchPhraseOperationPayload.java | 28 + .../jsons/JsonPlayValidationResult.java | 22 + .../internal/jsons/JsonPlayerState.java | 61 ++ .../internal/jsons/JsonPlaylists.java | 32 + .../jsons/JsonStartRoutineRequest.java | 24 + ...onEchoDynamicStateDescriptionProvider.java | 286 ++++++ addons/binding/pom.xml | 1 + .../src/main/feature/feature.xml | 5 + 44 files changed, 5749 insertions(+) create mode 100755 addons/binding/org.openhab.binding.amazonechocontrol/.classpath create mode 100755 addons/binding/org.openhab.binding.amazonechocontrol/.project create mode 100755 addons/binding/org.openhab.binding.amazonechocontrol/ESH-INF/binding/binding.xml create mode 100755 addons/binding/org.openhab.binding.amazonechocontrol/ESH-INF/i18n/amazonechocontrol_de.properties create mode 100644 addons/binding/org.openhab.binding.amazonechocontrol/ESH-INF/thing/thing-types.xml create mode 100755 addons/binding/org.openhab.binding.amazonechocontrol/META-INF/MANIFEST.MF create mode 100755 addons/binding/org.openhab.binding.amazonechocontrol/OSGI-INF/.gitignore create mode 100755 addons/binding/org.openhab.binding.amazonechocontrol/README.md create mode 100755 addons/binding/org.openhab.binding.amazonechocontrol/about.html create mode 100755 addons/binding/org.openhab.binding.amazonechocontrol/build.properties create mode 100644 addons/binding/org.openhab.binding.amazonechocontrol/lib/jsoup-1.10.1.jar create mode 100755 addons/binding/org.openhab.binding.amazonechocontrol/pom.xml create mode 100755 addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/AmazonEchoControlBindingConstants.java create mode 100755 addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/handler/AccountHandler.java create mode 100755 addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/handler/EchoHandler.java create mode 100644 addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/handler/FlashBriefingProfileHandler.java create mode 100755 addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/AccountConfiguration.java create mode 100644 addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/AccountServlet.java create mode 100755 addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/AmazonEchoControlHandlerFactory.java create mode 100644 addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/BindingServlet.java create mode 100755 addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/Connection.java create mode 100644 addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/ConnectionException.java create mode 100755 addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/HttpException.java create mode 100644 addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/StateStorage.java create mode 100755 addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/discovery/AmazonEchoDiscovery.java create mode 100644 addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonAutomation.java create mode 100644 addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonBluetoothStates.java create mode 100755 addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonDevices.java create mode 100644 addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonEnabledFeeds.java create mode 100644 addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonFeed.java create mode 100755 addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonMediaState.java create mode 100644 addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonMusicProvider.java create mode 100644 addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonNotificationRequest.java create mode 100644 addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonNotificationResponse.java create mode 100644 addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonNotificationSound.java create mode 100644 addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonNotificationSounds.java create mode 100644 addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonPlaySearchPhraseOperationPayload.java create mode 100644 addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonPlayValidationResult.java create mode 100755 addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonPlayerState.java create mode 100644 addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonPlaylists.java create mode 100644 addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonStartRoutineRequest.java create mode 100644 addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/statedescription/AmazonEchoDynamicStateDescriptionProvider.java diff --git a/addons/binding/org.openhab.binding.amazonechocontrol/.classpath b/addons/binding/org.openhab.binding.amazonechocontrol/.classpath new file mode 100755 index 0000000000000..d0631ba8106d7 --- /dev/null +++ b/addons/binding/org.openhab.binding.amazonechocontrol/.classpath @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/addons/binding/org.openhab.binding.amazonechocontrol/.project b/addons/binding/org.openhab.binding.amazonechocontrol/.project new file mode 100755 index 0000000000000..3f4c8692d661a --- /dev/null +++ b/addons/binding/org.openhab.binding.amazonechocontrol/.project @@ -0,0 +1,33 @@ + + + org.openhab.binding.amazonechocontrol + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + org.eclipse.pde.ds.core.builder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/addons/binding/org.openhab.binding.amazonechocontrol/ESH-INF/binding/binding.xml b/addons/binding/org.openhab.binding.amazonechocontrol/ESH-INF/binding/binding.xml new file mode 100755 index 0000000000000..81910f326e731 --- /dev/null +++ b/addons/binding/org.openhab.binding.amazonechocontrol/ESH-INF/binding/binding.xml @@ -0,0 +1,9 @@ + + + + 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 + + diff --git a/addons/binding/org.openhab.binding.amazonechocontrol/ESH-INF/i18n/amazonechocontrol_de.properties b/addons/binding/org.openhab.binding.amazonechocontrol/ESH-INF/i18n/amazonechocontrol_de.properties new file mode 100755 index 0000000000000..0093a1e94138f --- /dev/null +++ b/addons/binding/org.openhab.binding.amazonechocontrol/ESH-INF/i18n/amazonechocontrol_de.properties @@ -0,0 +1,135 @@ +# binding +binding.amazonechocontrol.name = Amazon Echo Steuerung Binding +binding.amazonechocontrol.description = Binding zum Steuern von Amazon Echo (Alexa). Dieses Binding ermöglicht openHAB die Lautstärke, den Wiedergabe Status und die Bluetooth-Verbindung des Amazon Echo Gerätes zu steuern oder als TTS Gerät zu benutzen. + +# thing types + +thing-type.amazonechocontrol.account.label = Amazon Konto +thing-type.amazonechocontrol.account.description = Amazon Konto bei dem die Amazon Echo Geräte registriert sind. Hinweis: 2 Faktor Authentifizierung ist nicht unterstützt. + +thing-type.config.amazonechocontrol.account.amazonSite.label = Amazon Seite +thing-type.config.amazonechocontrol.account.amazonSite.description = Amazon Seite bei der das Amazon Konto erstellt wurde. Hinweis: 2 Faktor Authentifizierung ist nicht unterstützt. + +thing-type.config.amazonechocontrol.account.email.label = Amazon Konto E-Mail +thing-type.config.amazonechocontrol.account.email.description = E-Mail des Amazon Konto welches für die Amazon Echo Geräte verwendet wurde. + +thing-type.config.amazonechocontrol.account.password.label = Amazon Konto Kennwort +thing-type.config.amazonechocontrol.account.password.description = Kennwort des Amazon Konto welches für die Amazon Echo Geräte verwendet wurde. WICHTIG: Sollte das Account-Thing nicht Online gehen und einen Login-Fehler melden, die URL YOUR_OPENHAP/amazonechocontrol/ID_OF_THIS_THING im Browser (Z.B.: http://openhab:8080/amazonechocontrol/account) öffnen und anmelden versuchen. + +thing-type.config.amazonechocontrol.account.pollingIntervalInSeconds.label = Status-Aktualisierungs-Intervall +thing-type.config.amazonechocontrol.account.pollingIntervalInSeconds.description = Aktualtisierungs-Intervall für den Status in Sekunden. Kleinere Zeiten verursachen höheren Netzwerkverkehr. + +thing-type.amazonechocontrol.echo.label = Amazon Echo +thing-type.amazonechocontrol.echo.description = Amazon Echo Gerät (Amazon Echo, Amazon Echo Dot, Amazon Echo Plus...) + +thing-type.config.amazonechocontrol.echo.serialNumber.label = Seriennummer +thing-type.config.amazonechocontrol.echo.serialNumber.description = Die Seriennummer des Geräts aus der Alexa App + +thing-type.amazonechocontrol.echospot.label = Amazon Echo Spot +thing-type.amazonechocontrol.echospot.description = Amazon Echo Spot Gerät + +thing-type.config.amazonechocontrol.echospot.serialNumber.label = Seriennummer +thing-type.config.amazonechocontrol.echospot.serialNumber.description = Die Seriennummer des Geräts aus der Alexa App + +thing-type.amazonechocontrol.echoshow.label = Amazon Echo Show +thing-type.amazonechocontrol.echoshow.description = Amazon Echo Show Gerät + +thing-type.config.amazonechocontrol.echoshow.serialNumber.label = Seriennummer +thing-type.config.amazonechocontrol.echoshow.serialNumber.description = Die Seriennummer des Geräts aus der Alexa App + +thing-type.amazonechocontrol.wha.label = Amazon Multi-Raum Musik +thing-type.amazonechocontrol.wha.description = Multi-Raum Musik Steuerung + +thing-type.config.wha.echoshow.serialNumber.label = Seriennummer +thing-type.config.wha.echoshow.serialNumber.description = Die Seriennummer des Geräts aus der Alexa App + +thing-type.amazonechocontrol.flashbriefingprofile.label = Tägliche Zusammenfassungsprofile +thing-type.amazonechocontrol.flashbriefingprofile.description = Speichert und läd eine Tägliches Zusammenfassungskonfiguration + +# channel types +channel-type.amazonechocontrol.bluetoothDeviceName.label = Bluetooth Gerät +channel-type.amazonechocontrol.bluetoothDeviceName.description = Verbundenes Bluetoothgerät + +channel-type.amazonechocontrol.radioStationId.label = TuneIn Radio Stations ID +channel-type.amazonechocontrol.radioStationId.description = ID der Radio Station + +channel-type.amazonechocontrol.amazonMusicTrackId.label = Amazon Music Lied ID +channel-type.amazonechocontrol.amazonMusicTrackId.description = ID des Liedes auf Amazon Music + +channel-type.amazonechocontrol.amazonMusic.label = Amazon Music +channel-type.amazonechocontrol.amazonMusic.description = Amazon Music eingeschaltet + +channel-type.amazonechocontrol.amazonMusicPlayListId.label = Amazon Music Playlist ID +channel-type.amazonechocontrol.amazonMusicPlayListId.description = ID der Playlist auf Amazon Music (Nur schreiben, kein aktueller Status). + +channel-type.amazonechocontrol.providerDisplayName.label = Anbieter Name +channel-type.amazonechocontrol.providerDisplayName.description = Name des Musikanbieters + +channel-type.amazonechocontrol.bluetoothMAC.label = Bluetooth Verbindung +channel-type.amazonechocontrol.bluetoothMAC.description = MAC-Adresse des verbundenen Bluetoothgerätes + +channel-type.amazonechocontrol.textToSpeech.label = Sprich +channel-type.amazonechocontrol.textToSpeech.description = Spricht den Text (Nur schreiben) + +channel-type.amazonechocontrol.remind.label = Erinnere +channel-type.amazonechocontrol.remind.description = Spricht die Erinnerung und sendet eine Benachrichtigung an die Alexa-APP (Nur schreiben) + +channel-type.amazonechocontrol.playAlarmSound.label = Spielt Alarm Sound +channel-type.amazonechocontrol.playAlarmSound.description = Spielt Alarm Sound ab (Nur schreiben) + +channel-type.amazonechocontrol.startRoutine.label = Started eine Routine +channel-type.amazonechocontrol.startRoutine.description = Befehl der zu Alexa gesprochen werden muss um eine Routine zu starten, ohne "Alexa" vorangestellt (Nur schreiben) + +channel-type.amazonechocontrol.musicProviderId.label = Musikanbieter +channel-type.amazonechocontrol.musicProviderId.description = Musikanbieter + +channel-type.amazonechocontrol.playMusicVoiceCommand.label = Musik Sprachbefehl +channel-type.amazonechocontrol.playMusicVoiceCommand.description = Sprachbefehl als Text. Z.B. Yesterday von Beatles (Nur schreiben) + +channel-type.amazonechocontrol.imageUrl.label = Bild URL +channel-type.amazonechocontrol.imageUrl.description = URL des Album Covers oder des Radiostations Logos + +channel-type.amazonechocontrol.title.label = Titel +channel-type.amazonechocontrol.title.description = Titel + +channel-type.amazonechocontrol.subtitle1.label = Untertitel 1 +channel-type.amazonechocontrol.subtitle1.description = Untertitel 1 + +channel-type.amazonechocontrol.subtitle2.label = Untertitel 2 +channel-type.amazonechocontrol.subtitle2.description = Untertitel 2 + +channel-type.amazonechocontrol.radio.label = TuneIn Radio +channel-type.amazonechocontrol.radio.description = Radio eingeschaltet + +channel-type.amazonechocontrol.bluetooth.label = Bluetooth Verbindung +channel-type.amazonechocontrol.bluetooth.description = Verbindet zum letzten benutzten Bluetooth Gerätes + +channel-type.amazonechocontrol.loop.label = Wiederholung +channel-type.amazonechocontrol.loop.description = Wiederholung + +channel-type.amazonechocontrol.shuffle.label = Zufall +channel-type.amazonechocontrol.shuffle.description = Zufallswiedergabe + +channel-type.amazonechocontrol.player.label = Musikwiedergabe +channel-type.amazonechocontrol.player.description = Musikwiedergabe + +channel-type.amazonechocontrol.volume.label = Lautstärke +channel-type.amazonechocontrol.volume.description = Wiedergabelautstärke + +channel-type.amazonechocontrol.save.label = Speichern +channel-type.amazonechocontrol.save.description = Speichert die aktuelle tägliche Zusammenfassung Konfiguration (Nur schreiben) + +channel-type.amazonechocontrol.active.label = Aktiv +channel-type.amazonechocontrol.active.description = Aktiviert diese tägliche Zusammenfassung Konfiguration + +channel-type.amazonechocontrol.playOnDevice.label = Wiedergabe am Gerät +channel-type.amazonechocontrol.playOnDevice.description = Started die Wiedergabe am Gerät (Seriennummer oder Name, nur schreiben) + +channel-type.amazonechocontrol.playCommand.label = Started +channel-type.amazonechocontrol.playCommand.description = Started Information (Nur schreiben) +channel-type.amazonechocontrol.playCommand.option.Weather = Wetter +channel-type.amazonechocontrol.playCommand.option.Traffic = Verkehr +channel-type.amazonechocontrol.playCommand.option.GoodMorning = Guten Morgen +channel-type.amazonechocontrol.playCommand.option.SingASong = Lied +channel-type.amazonechocontrol.playCommand.option.TellStory = Geschichte +channel-type.amazonechocontrol.playCommand.option.TellStory = Zusammenfassung diff --git a/addons/binding/org.openhab.binding.amazonechocontrol/ESH-INF/thing/thing-types.xml b/addons/binding/org.openhab.binding.amazonechocontrol/ESH-INF/thing/thing-types.xml new file mode 100644 index 0000000000000..b6757b89b0133 --- /dev/null +++ b/addons/binding/org.openhab.binding.amazonechocontrol/ESH-INF/thing/thing-types.xml @@ -0,0 +1,355 @@ + + + + + Amazon Account where the amazon echo devices are registered. + + + + + false + + + + + + + + + + Site where the amazon account is created. + + + + Email address of the amazon account which is used for the amazon echo devices. Hint: 2 factor authentication is not supported! + + + password + + Password of the amazon account which is used for the amazon echo devices. IMPORTANT: If the account thing does not go online and reports and login error, open the url YOUR_OPENHAP/amazonechocontrol/ID_OF_THIS_THING in your browser (e.g. http://openhab:8080/amazonechocontrol/account) and try to login. + + + 30 + + Refresh state interval in seconds. Lower time causes more network traffic. + Seconds + + + + + + + + + Amazon Echo device (Amazon Echo, Amazon Echo Dot, Amazon Echo Plus...) + + + + + + + + + + + + + + + + + + + + + + + + + + serialNumber + + + + The serial number of the device from the Alexa app + + + + + + + + + Amazon Echo Spot device + + + + + + + + + + + + + + + + + + + + + + + + + + serialNumber + + + + The serial number of the device from the Alexa app + + + + + + + + + Amazon Echo Show device + + + + + + + + + + + + + + + + + + + + + + + + + + serialNumber + + + + The serial number of the device from the Alexa app + + + + + + + + + Amazon Multiroom Music + + + + + + + + + + + + + + + serialNumber + + + + The serial number of the device from the Alexa app + + + + + + + + + + Store and load a flash briefing configuration + + + + + + + + Switch + + Save the current flash briefing configuration (Write only) + + + Switch + + Activate this flash briefing configuration + + + String + + Plays the briefing on the device (serial number or name, write only) + + + String + + Connected bluetooth device + + + + String + + Id of the radio station + + + String + + Speak the reminder and send a notification to the Alexa app + + + String + + The command which must be spoken to active the routing without the preceding "Alexa," (Write Only) + + + String + + Plays an alarm sound + + + String + + Id of the amazon music track + + + Switch + + Amazon Music turned on + + + String + + Amazon Music play list id (Write only, no current state) + + + String + + Id of the playlist which was started with openHAB + + + String + + Name of music provider + + + + String + + MAC-Address of the bluetooth connected device + + + String + + Url of the album image or radio station logo + + + + String + + Title + + + + String + + Subtitle 1 + + + + String + + Subtitle 2 + + + + Switch + + Radio turned on + + + Switch + + Connect to last used device + + + Switch + + Loop + + + Switch + + Shuffle play + + + Player + + Music Player + + + Dimmer + + Volume of the sound + + + String + + Music provider + + + String + + Voice command as text. E.g. 'Yesterday from the Beatles' (Write only) + + + String + + Speak the text (Write only) + + + String + + Start information (Write only) + + + + + + + + + + + + diff --git a/addons/binding/org.openhab.binding.amazonechocontrol/META-INF/MANIFEST.MF b/addons/binding/org.openhab.binding.amazonechocontrol/META-INF/MANIFEST.MF new file mode 100755 index 0000000000000..d2190d145686a --- /dev/null +++ b/addons/binding/org.openhab.binding.amazonechocontrol/META-INF/MANIFEST.MF @@ -0,0 +1,38 @@ +Manifest-Version: 1.0 +Bundle-ActivationPolicy: lazy +Bundle-ClassPath: .,lib/jsoup-1.10.1.jar +Bundle-ManifestVersion: 2 +Bundle-Name: Amazon Echo Control Binding +Bundle-SymbolicName: org.openhab.binding.amazonechocontrol;singleton:=true +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Bundle-Vendor: openHAB +Bundle-Version: 2.3.0.qualifier +Import-Package: com.google.gson, + javax.servlet, + javax.servlet.http, + javax.ws.rs.core, + org.apache.commons.lang, + org.eclipse.jdt.annotation;resolution:=optional, + org.eclipse.smarthome.config.core, + org.eclipse.smarthome.config.discovery, + org.eclipse.smarthome.core.cache, + org.eclipse.smarthome.core.i18n, + org.eclipse.smarthome.core.library.types, + org.eclipse.smarthome.core.storage, + org.eclipse.smarthome.core.thing, + org.eclipse.smarthome.core.thing.binding, + org.eclipse.smarthome.core.thing.binding.builder, + org.eclipse.smarthome.core.thing.type, + org.eclipse.smarthome.core.types, + org.openhab.binding.amazonechocontrol, + org.openhab.binding.amazonechocontrol.handler, + org.osgi.framework, + org.osgi.service.component, + org.osgi.service.http, + org.slf4j +Service-Component: OSGI-INF/*.xml +Export-Package: + org.openhab.binding.amazonechocontrol, + org.openhab.binding.amazonechocontrol.handler + + diff --git a/addons/binding/org.openhab.binding.amazonechocontrol/OSGI-INF/.gitignore b/addons/binding/org.openhab.binding.amazonechocontrol/OSGI-INF/.gitignore new file mode 100755 index 0000000000000..6722cd96e785a --- /dev/null +++ b/addons/binding/org.openhab.binding.amazonechocontrol/OSGI-INF/.gitignore @@ -0,0 +1 @@ +*.xml diff --git a/addons/binding/org.openhab.binding.amazonechocontrol/README.md b/addons/binding/org.openhab.binding.amazonechocontrol/README.md new file mode 100755 index 0000000000000..9154a0f8a8c7d --- /dev/null +++ b/addons/binding/org.openhab.binding.amazonechocontrol/README.md @@ -0,0 +1,384 @@ +# Amazon Echo Control Binding + +This binding can control Amazon Echo devices (Alexa). + +It provides features to control and view the current state of echo devices: + +- use echo device as text to speech from a rule +- volume +- pause/continue/next track/previous track +- connect/disconnect bluetooth devices +- start playing tuneIn radio +- start playing Amazon Music +- control of multi room music +- show album art image in sitemap +- speak a reminder message +- plays an alarm sound +- start traffic news +- start daily briefing +- start weather report +- start good morning report +- start automation routine +- activate multiple configurations of flash briefings +- start playing music by providing the voice command as text (Works with all music providers) + +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 +- If the amplifier was turned of, the echo stop playing and disconnect the bluetooth +- The echo starts playing radio if the light was turned on +- The echo starts playing radio at specified time +- Remind you with a voice message, that a window is open for a long time and it is winter +- Start a routine which welcome you, if you come home +- Start a routine which switch a smart home device connected to alexa +- Start your briefing if you turn on the light first time in the morning +- Have different flash briefing in the morning and evening +- Let alexa say 'welcome' to you if you open the door + +## Note + +This binding uses the same API as the Web-Browser-Based Alexa site (alexa.amazon.de). +In other words, it simulates a user which is using the web page. +Unfortunately, the binding can get broken if Amazon change the web site. + +The binding is tested with amazon.de, amazon.com and amazon.co.uk accounts, but should also work with all others. + +## Warning + +For the connection to the Amazon server, your password of the Amazon account is required, this will be stored in your openHAB thing device configuration. +So you should be sure, that nobody other has access to your configuration! + +## What Else You Should Know + +All the display options are updated by polling the amazon server. +The polling time can be configured, but a minimum of 10 seconds is required. +The default is 60 seconds, which means the it can take up to 60 seconds to see the correct state. +It's not know, if there is a limit implemented in the amazon server if the polling is too fast and maybe amazon will lock your account. 30 seconds seems to be safe. + +## Supported Things + +| Thing type id | Name | +|----------------------|---------------------------------------| +| account | Amazon Account | +| echo | Amazon Echo Device | +| echospot | Amazon Echo Spot Device | +| echoshow | Amazon Echo Show Device | +| wha | Amazon Echo Whole House Audio Control | +| flashbriefingprofile | Flash briefing profile | + +## First Steps + +1) Create an 'Amazon Account' thing +2) Configure your credentials in the account thing (2 factor authentication is not supported!) +3) After confirmation: +a) the 'Account Thing' goes Online -> continue with 4) +b) the 'Account Thing' stays offline: +open the url YOUR_OPENHAB/amazonechocontrol in your browser (e.g. http://openhab:8080/amazonechocontrol/), click the link for your account thing and try to login. +4) The echo device things get automatically discovered and can be accepted + +## Discovery + +After configuration of the account thing with the login data, the echo devices registered in the amazon account, get discovered. +If the device type is not known by the binding, the device will not be discovered. +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. + +## Binding Configuration + +The binding does not have any configuration. +The configuration of your amazon account must be done in the 'Amazon Account' device. + +## Thing Configuration + +The Amazon Account thing needs the following configurations: + +| Configuration name | Description | +|--------------------------|---------------------------------------------------------------------------| +| amazonSite | The amazon site where the echos are registered. e.g. amazon.de | +| email | Email of your amazon account | +| password | Password of your amazon account | +| pollingIntervalInSeconds | Polling interval for the device state in seconds. Default 30, minimum 10 | + +IMPORTANT: If the Account thing does not go online and reports a login error, read the instructions in "First Steps" above. + +### Amazon Devices + +All Amazon devices (echo, echospot, echoshow, wha) needs the following configurations: + +| Configuration name | Description | +|--------------------------|----------------------------------------------------| +| serialNumber | Serial number of the amazon echo in the Alexa app | + +You will find the serial number in the alexa app. + +### Flash Briefing Profile + +The flashbriefingprofile thing has no configuration parameters. +It will be configured at runtime by using the save channel to store the current flash briefing configuration in the thing. + +## 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 +| 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 | Switch | 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 +| 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. + +## Full Example + +### amazonechocontrol.things + +``` +Bridge amazonechocontrol:account:account1 "Amazon Account" @ "Accounts" [amazonSite="amazon.de", email="myaccountemail@myprovider.com", password="secure", pollingIntervalInSeconds=60] +{ + Thing echo echo1 "Alexa" @ "Living Room" [serialNumber="SERIAL_NUMBER"] + Thing echoshow echoshow1 "Alexa" @ "Kitchen" [serialNumber="SERIAL_NUMBER"] + Thing echospot echospot1 "Alexa" @ "Sleeping Room" [serialNumber="SERIAL_NUMBER"] + Thing wha wha1 "Ground Floor Music Group" @ "Music Groups" [serialNumber="SERIAL_NUMBER"] + Thing flashbriefingprofile flashbriefing1 "Flash Briefing Technical" @ "Flash Briefings" + Thing flashbriefingprofile flashbriefing2 "Flash Briefing Life Style" @ "Flash Briefings" +} +``` + +You will find the serial number in the Alexa app. + +### amazonechocontrol.items: + +Sample for the Thing echo1 only. But it will work in the same way for the other things, only replace the thing name in the channel link. +Take a look in the channel description above to know, which channels are supported by your thing type. + +``` +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"} +Switch Echo_Living_Room_Shuffle "Shuffle" (Alexa_Living_Room) {channel="amazonechocontrol:echo:account1:echo1:shuffle"} + +// Player Information +String Echo_Living_Room_ImageUrl "Image URL" (Alexa_Living_Room) {channel="amazonechocontrol:echo:account1:echo1:imageUrl"} +String Echo_Living_Room_Title "Title" (Alexa_Living_Room) {channel="amazonechocontrol:echo:account1:echo1:title"} +String Echo_Living_Room_Subtitle1 "Subtitle 1" (Alexa_Living_Room) {channel="amazonechocontrol:echo:account1:echo1:subtitle1"} +String Echo_Living_Room_Subtitle2 "Subtitle 2" (Alexa_Living_Room) {channel="amazonechocontrol:echo:account1:echo1:subtitle2"} +String Echo_Living_Room_ProviderDisplayName "Provider" (Alexa_Living_Room) {channel="amazonechocontrol:echo:account1:echo1:providerDisplayName"} + +// Music provider and start command +String Echo_Living_Room_MusicProviderId "Music Provider Id" (Alexa_Living_Room) {channel="amazonechocontrol:echo:account1:echo1:musicProviderId"} +String Echo_Living_Room_PlayMusicCommand "Play music voice command (Write Only)" (Alexa_Living_Room) {channel="amazonechocontrol:echo:account1:echo1:playMusicVoiceCommand"} +String Echo_Living_Room_StartCommand "Start Information" (Alexa_Living_Room) {channel="amazonechocontrol:echo:account1:echo1:startCommand"} + +// TuneIn Radio +String Echo_Living_Room_RadioStationId "TuneIn Radio Station Id" (Alexa_Living_Room) {channel="amazonechocontrol:echo:account1:echo1:radioStationId"} +Switch Echo_Living_Room_Radio "TuneIn Radio" (Alexa_Living_Room) {channel="amazonechocontrol:echo:account1:echo1:radio"} + +// Amazon Music +String Echo_Living_Room_AmazonMusicTrackId "Amazon Music Track Id" (Alexa_Living_Room) {channel="amazonechocontrol:echo:account1:echo1:amazonMusicTrackId"} +String Echo_Living_Room_AmazonMusicPlayListId "Amazon Music Playlist Id" (Alexa_Living_Room) {channel="amazonechocontrol:echo:account1:echo1:amazonMusicPlayListId"} +Switch Echo_Living_Room_AmazonMusic "Amazon Music" (Alexa_Living_Room) {channel="amazonechocontrol:echo:account1:echo1:amazonMusic"} + +// Bluetooth +String Echo_Living_Room_BluetoothMAC "Bluetooth MAC Address" (Alexa_Living_Room) {channel="amazonechocontrol:echo:account1:echo1:bluetoothMAC"} +Switch Echo_Living_Room_Bluetooth "Bluetooth" (Alexa_Living_Room) {channel="amazonechocontrol:echo:account1:echo1:bluetooth"} +String Echo_Living_Room_BluetoothDeviceName "Bluetooth Device" (Alexa_Living_Room) {channel="amazonechocontrol:echo:account1:echo1:bluetoothDeviceName"} + +// Commands +String Echo_Living_Room_TTS "Text to Speech" (Alexa_Living_Room) {channel="amazonechocontrol:echo:account1:echo1:textToSpeech"} +String Echo_Living_Room_Remind "Remind" (Alexa_Living_Room) {channel="amazonechocontrol:echo:account1:echo1:remind"} +String Echo_Living_Room_PlayAlarmSound "Play Alarm Sound" (Alexa_Living_Room) {channel="amazonechocontrol:echo:account1:echo1:playAlarmSound"} +String Echo_Living_Room_StartRoutine "Start Routine" (Alexa_Living_Room) {channel="amazonechocontrol:echo:account1:echo1:startRoutine"} + +// Flashbriefings +Switch FlashBriefing_Technical_Save "Save (Write only)" { channel="amazonechocontrol:flashbriefingprofile:account1:flashbriefing1:save"} +Switch FlashBriefing_Technical_Active "Active" { channel="amazonechocontrol:flashbriefingprofile:account1:flashbriefing1:active"} +String FlashBriefing_Technical_Play "Play (Write only)" { channel="amazonechocontrol:flashbriefingprofile:account1:flashbriefing1:playOnDevice"} + +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"} +``` + +### amazonechocontrol.sitemap: + +``` +sitemap amzonechocontrol label="Echo Devices" +{ + Frame label="Alexa" { + Default item=Echo_Living_Room_Player + Slider item=Echo_Living_Room_Volume + Switch item=Echo_Living_Room_Shuffle + Image item=Echo_Living_Room_ImageUrl label="" + Text item=Echo_Living_Room_Title + Text item=Echo_Living_Room_Subtitle1 + Text item=Echo_Living_Room_Subtitle2 + Text item=Echo_Living_Room_ProviderDisplayName + + // The listed providers are only samples, you could have more + Selection item=Echo_Living_Room_MusicProviderId mappings=[ 'TUNEIN'='Radio', 'SPOTIFY'='Spotify', 'AMAZON_MUSIC'='Amazon Music', 'CLOUDPLAYER'='Amazon'] + Text item=Echo_Living_Room_MusicProviderId + + // To start one of your flashbriefings use Flashbriefing. + Selection item=Echo_Living_Room_StartCommand mappings=[ 'Weather'='Weather', 'Traffic'='Traffic', 'GoodMorning'='Good Morning', 'SingASong'='Song', 'TellStory'='Story', 'FlashBriefing'='Flash Briefing', 'FlashBriefing.flashbriefing1'='Technical', 'FlashBriefing.flashbriefing2'='Life Style' ] + + Selection item=Echo_Living_Room_RadioStationId mappings=[ ''='Off', 's1139'='Antenne Steiermark', 's8007'='Hitradio Ö3', 's16793'='Radio 10', 's8235'='FM4' ] + Text item=Echo_Living_Room_RadioStationId + Switch item=Echo_Living_Room_Radio + + Text item=Echo_Living_Room_AmazonMusicTrackId + Text item=Echo_Living_Room_AmazonMusicPlayListId + Switch item=Echo_Living_Room_AmazonMusic + + Text item=Echo_Living_Room_BluetoothMAC + // Change the Place holder with the MAC address shown, if alexa is connected to the device + Selection item=Echo_Living_Room_BluetoothMAC mappings=[ ''='Disconnected', ''='Bluetooth Device 1', ''='Bluetooth Device 2'] + + // These are only view of the possible options. Enable ShowIDsInGUI in the binding configuration and look in drop-down-box of this channel in the Paper UI Control section + Selection item=Echo_Living_Room_PlayAlarmSound mappings=[ ''='None', 'ECHO:system_alerts_soothing_01'='Adrift', 'ECHO:system_alerts_atonal_02'='Clangy'] + + Switch item=Echo_Living_Room_Bluetooth + Text item=Echo_Living_Room_BluetoothDeviceName + } + + Frame label="Flash Briefing Technical" { + Switch item=FlashBriefing_Technical_Save + Switch item=FlashBriefing_Technical_Active + Text item=FlashBriefing_Technical_Play + } + + Frame label="Flash Briefing Life Style" { + Switch item=FlashBriefing_LifeStyle_Save + Switch item=FlashBriefing_LifeStyle_Active + Text item=FlashBriefing_LifeStyle_Play + } +} +``` + +## How To Get IDs + +1) Open the url YOUR_OPENHAB/amazonechocontrol in your browser (e.g. http://openhab:8080/amazonechocontrol/) +2) Click on the name of the account thing +3) Click on the name of the echo thing +4) Scroll to the channel and copy the required ID + +## Tutorials + +### Let alexa speak a text from a rule: + +1) Create a rule with a trigger of your choice + +```php +rule "Say welcome if the door opens" +when + Item Door_Contact changed to OPEN +then + Echo_Living_Room_TTS.sendCommand('Hello World') +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" +2) Write down the text in the square brackets. e.g. ECHO:system_alerts_repetitive01 for the nightstand sound +3) Create a rule for start playing the sound: + +```php +var Timer stopAlarmTimer = null + +rule "Turn on alarm sound for 15 seconds if door opens" +when + Item Door_Contact changed to OPEN +then + Echo_Living_Room_PlayAlarmSound.sendCommand('ECHO:system_alerts_repetitive01') + if (stopAlarmTimer === null) + { + stopAlarmTimer = createTimer(now.plusSeconds(15)) [| + stopAlarmTimer.cancel() + stopAlarmTimer = null + Echo_Living_Room_PlayAlarmSound.sendCommand('') + ] + } +end +``` + +Note 1: Do not use a to short time for playing the sound, because alexa needs some time to start playing the sound. +It's not recommended to use a time below 10 seconds. + +Note 2: The rule have no effect for your default alarm sound used in the alexa app. + +### Play a spotify playlist if a switch was changed to on: + +1) Do get the ID of your sound, follow the steps in "How To Get IDs" +2) Write down the text in the square brackets. e.g. SPOTIFY for the spotify music provider +3) Create a rule for start playing a song or playlist: + +```php +rule "Play a playlist on spotify if a switch was changed" +when + Item Spotify_Playlist_Switch changed to ON +then + Echo_Living_Room_PlayMusicProvider.sendCommand('SPOTIFY') + Echo_Living_Room_PlayMusicCommand.sendCommand('Playlist Party') +end +``` + +Note: It's recommended to test the command send to play music command first with the voice and the real alexa device. E.g. say 'Alexa, Playlist Party' + +### Start playing weather/traffic/etc: + +1) Pick up one of the available commands: Weather, Traffic, GoodMorning, SingASong, TellStory, FlashBriefing +2) Create a rule for start playing the information where you provide the command as string: + +```php +rule "Start wheater info" +when + Item Spotify_Start_Wheater_Switch changed to ON +then + Echo_Living_Room_StartCommand.sendCommand('Weather') +end +``` + +### Start playing a custom flashbriefing on a device: + +1) Do get the ID of your sound, follow the steps in "How To Get IDs" +2) Write down the text in the square brackets. e.g. flashbriefing.flashbriefing1 +2) Create a rule for start playing the information where you provide the command as string: + +```php +rule "Start wheater info" +when + Item Spotify_Start_Wheater_Switch changed to ON +then + Echo_Living_Room_StartCommand.sendCommand('FlashBriefing.flashbriefing1') +end +``` + +## Credits + +The idea for writing this binding came from this blog: http://blog.loetzimmer.de/2017/10/amazon-alexa-hort-auf-die-shell-echo.html (German). +Thank you Alex! + +## Trademark Disclaimer + +TuneIn, Amazon Echo, Amazon Echo Spot, Amazon Echo Show, Amazon Music, Amazon Prime, Alexa and all other products and Amazon, TuneIn and other companies are trademarksâ„¢ or registered® trademarks of their respective holders. +Use of them does not imply any affiliation with or endorsement by them. diff --git a/addons/binding/org.openhab.binding.amazonechocontrol/about.html b/addons/binding/org.openhab.binding.amazonechocontrol/about.html new file mode 100755 index 0000000000000..089907bd268e0 --- /dev/null +++ b/addons/binding/org.openhab.binding.amazonechocontrol/about.html @@ -0,0 +1,32 @@ + + + + + About + + +

About This Content

+ +

March 30, 2017

+

License

+ +

+ The openHAB community makes available all content in this plug-in ("Content"). Unless otherwise + indicated below, the Content is provided to you under the terms and conditions of the + Eclipse Public License Version 1.0 ("EPL"). A copy of the EPL is available + at http://www.eclipse.org/legal/epl-v10.html. + For purposes of the EPL, "Program" will mean the Content. +

+ +

+ If you did not receive this Content directly from the openHAB community, the Content is + being redistributed by another party ("Redistributor") and different terms and conditions may + apply to your use of any object code in the Content. Check the Redistributor's license that was + provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise + indicated below, the terms and conditions of the EPL still apply to any source code in the Content + and such source code may be obtained at openhab.org. +

+ + + diff --git a/addons/binding/org.openhab.binding.amazonechocontrol/build.properties b/addons/binding/org.openhab.binding.amazonechocontrol/build.properties new file mode 100755 index 0000000000000..2b0da48f6f493 --- /dev/null +++ b/addons/binding/org.openhab.binding.amazonechocontrol/build.properties @@ -0,0 +1,8 @@ +source..=src/main/java/ +output..=target/classes +bin.includes=META-INF/,\ + .,\ + OSGI-INF/,\ + ESH-INF/,\ + lib/,\ + about.html diff --git a/addons/binding/org.openhab.binding.amazonechocontrol/lib/jsoup-1.10.1.jar b/addons/binding/org.openhab.binding.amazonechocontrol/lib/jsoup-1.10.1.jar new file mode 100644 index 0000000000000000000000000000000000000000..6415d0c030e31ce4a0e563912fc3687b309bc10b GIT binary patch literal 345536 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�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

p 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

2M=SQ& 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 + + + 4.0.0 + + + org.openhab.binding + pom + 2.3.0-SNAPSHOT + + + org.openhab.binding.amazonechocontrol + 2.3.0-SNAPSHOT + + Amazon Echo Control Binding + eclipse-plugin + + diff --git a/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/AmazonEchoControlBindingConstants.java b/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/AmazonEchoControlBindingConstants.java new file mode 100755 index 0000000000000..2fddadc81bfc2 --- /dev/null +++ b/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/AmazonEchoControlBindingConstants.java @@ -0,0 +1,94 @@ +/** + * Copyright (c) 2010-2018 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.amazonechocontrol; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.smarthome.core.thing.ThingTypeUID; +import org.eclipse.smarthome.core.thing.type.ChannelTypeUID; + +/** + * The {@link AmazonEchoControlBindingConstants} class defines common constants, which are + * used across the whole binding. + * + * @author Michael Geramb - Initial contribution + */ +@NonNullByDefault +public class AmazonEchoControlBindingConstants { + + public static final String BINDING_ID = "amazonechocontrol"; + public static final String BINDING_NAME = "Amazon Echo Control"; + + // List of all Thing Type UIDs + public static final ThingTypeUID THING_TYPE_ACCOUNT = new ThingTypeUID(BINDING_ID, "account"); + public static final ThingTypeUID THING_TYPE_ECHO = new ThingTypeUID(BINDING_ID, "echo"); + public static final ThingTypeUID THING_TYPE_ECHO_SPOT = new ThingTypeUID(BINDING_ID, "echospot"); + public static final ThingTypeUID THING_TYPE_ECHO_SHOW = new ThingTypeUID(BINDING_ID, "echoshow"); + public static final ThingTypeUID THING_TYPE_ECHO_WHA = new ThingTypeUID(BINDING_ID, "wha"); + + public static final ThingTypeUID THING_TYPE_FLASH_BRIEFING_PROFILE = new ThingTypeUID(BINDING_ID, + "flashbriefingprofile"); + + 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)); + + // List of all Channel ids + public static final String CHANNEL_PLAYER = "player"; + public static final String CHANNEL_VOLUME = "volume"; + public static final String CHANNEL_ERROR = "error"; + public static final String CHANNEL_SHUFFLE = "shuffle"; + public static final String CHANNEL_LOOP = "loop"; + public static final String CHANNEL_IMAGE_URL = "imageUrl"; + public static final String CHANNEL_TITLE = "title"; + public static final String CHANNEL_SUBTITLE1 = "subtitle1"; + public static final String CHANNEL_SUBTITLE2 = "subtitle2"; + public static final String CHANNEL_PROVIDER_DISPLAY_NAME = "providerDisplayName"; + public static final String CHANNEL_BLUETOOTH_MAC = "bluetoothMAC"; + public static final String CHANNEL_BLUETOOTH = "bluetooth"; + public static final String CHANNEL_BLUETOOTH_DEVICE_NAME = "bluetoothDeviceName"; + public static final String CHANNEL_RADIO_STATION_ID = "radioStationId"; + public static final String CHANNEL_RADIO = "radio"; + public static final String CHANNEL_AMAZON_MUSIC_TRACK_ID = "amazonMusicTrackId"; + public static final String CHANNEL_AMAZON_MUSIC = "amazonMusic"; + public static final String CHANNEL_AMAZON_MUSIC_PLAY_LIST_ID = "amazonMusicPlayListId"; + public static final String CHANNEL_TEXT_TO_SPEECH = "textToSpeech"; + public static final String CHANNEL_REMIND = "remind"; + public static final String CHANNEL_PLAY_ALARM_SOUND = "playAlarmSound"; + public static final String CHANNEL_START_ROUTINE = "startRoutine"; + public static final String CHANNEL_MUSIC_PROVIDER_ID = "musicProviderId"; + public static final String CHANNEL_PLAY_MUSIC_VOICE_COMMAND = "playMusicVoiceCommand"; + public static final String CHANNEL_START_COMMAND = "startCommand"; + + public static final String CHANNEL_SAVE = "save"; + public static final String CHANNEL_ACTIVE = "active"; + public static final String CHANNEL_PLAY_ON_DEVICE = "playOnDevice"; + + // List of channel Type UIDs + public static final ChannelTypeUID CHANNEL_TYPE_BLUETHOOTH_MAC = new ChannelTypeUID(BINDING_ID, "bluetoothMAC"); + public static final ChannelTypeUID CHANNEL_TYPE_AMAZON_MUSIC_PLAY_LIST_ID = new ChannelTypeUID(BINDING_ID, + "amazonMusicPlayListId"); + public static final ChannelTypeUID CHANNEL_TYPE_PLAY_ALARM_SOUND = new ChannelTypeUID(BINDING_ID, "playAlarmSound"); + public static final ChannelTypeUID CHANNEL_TYPE_CHANNEL_PLAY_ON_DEVICE = new ChannelTypeUID(BINDING_ID, + "playOnDevice"); + 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"); + + // 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"; + + // Other + public static final String FLASH_BRIEFING_COMMAND_PREFIX = "FlashBriefing."; +} diff --git a/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/handler/AccountHandler.java b/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/handler/AccountHandler.java new file mode 100755 index 0000000000000..394500036e123 --- /dev/null +++ b/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/handler/AccountHandler.java @@ -0,0 +1,559 @@ +/** + * Copyright (c) 2010-2018 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.amazonechocontrol.handler; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +import org.apache.commons.lang.StringUtils; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.storage.Storage; +import org.eclipse.smarthome.core.thing.Bridge; +import org.eclipse.smarthome.core.thing.ChannelUID; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.ThingStatus; +import org.eclipse.smarthome.core.thing.ThingStatusDetail; +import org.eclipse.smarthome.core.thing.binding.BaseBridgeHandler; +import org.eclipse.smarthome.core.thing.binding.ThingHandler; +import org.eclipse.smarthome.core.types.Command; +import org.eclipse.smarthome.core.types.RefreshType; +import org.openhab.binding.amazonechocontrol.internal.AccountConfiguration; +import org.openhab.binding.amazonechocontrol.internal.AccountServlet; +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.JsonBluetoothStates; +import org.openhab.binding.amazonechocontrol.internal.jsons.JsonBluetoothStates.BluetoothState; +import org.openhab.binding.amazonechocontrol.internal.jsons.JsonDevices.Device; +import org.openhab.binding.amazonechocontrol.internal.jsons.JsonFeed; +import org.osgi.service.http.HttpService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.Gson; +import com.google.gson.JsonSyntaxException; + +/** + * Handles the connection to the amazon server. + * + * @author Michael Geramb - Initial Contribution + */ +@NonNullByDefault +public class AccountHandler extends BaseBridgeHandler { + + private final Logger logger = LoggerFactory.getLogger(AccountHandler.class); + private Storage stateStorage; + private @Nullable Connection connection; + private final Set echoHandlers = new HashSet<>(); + private final Set flashBriefingProfileHandlers = new HashSet<>(); + private final Object synchronizeConnection = new Object(); + private Map jsonSerialNumberDeviceMapping = new HashMap<>(); + private @Nullable ScheduledFuture refreshJob; + private @Nullable ScheduledFuture refreshLogin; + private String currentFlashBriefingJson = ""; + private final HttpService httpService; + private @Nullable AccountServlet accountServlet; + private final Gson gson = new Gson(); + + public AccountHandler(Bridge bridge, HttpService httpService, Storage stateStorage) { + super(bridge); + this.httpService = httpService; + this.stateStorage = stateStorage; + } + + @Override + public void initialize() { + logger.debug("amazon account bridge starting..."); + + AccountConfiguration config = getConfigAs(AccountConfiguration.class); + + String amazonSite = config.amazonSite; + if (StringUtils.isEmpty(amazonSite)) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Amazon site not configured"); + return; + } + String email = config.email; + if (StringUtils.isEmpty(email)) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Account email not configured"); + return; + } + String password = config.password; + if (StringUtils.isEmpty(password)) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Account password not configured"); + return; + } + Integer pollingIntervalInSeconds = config.pollingIntervalInSeconds; + if (pollingIntervalInSeconds == null) { + pollingIntervalInSeconds = 30; + } + if (pollingIntervalInSeconds < 10) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, + "Polling interval less than 10 seconds not allowed"); + return; + } + synchronized (synchronizeConnection) { + Connection connection = this.connection; + if (connection == null || !connection.getEmail().equals(email) || !connection.getPassword().equals(password) + || !connection.getAmazonSite().equals(amazonSite)) { + this.connection = new Connection(email, password, amazonSite, this.getThing().getUID().getId()); + } + } + if (this.accountServlet == null) { + this.accountServlet = new AccountServlet(httpService, this.getThing().getUID().getId(), this, config); + } + + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_PENDING, "Wait for login"); + + refreshLogin = scheduler.scheduleWithFixedDelay(this::checkLogin, 0, 60, TimeUnit.SECONDS); + refreshJob = scheduler.scheduleWithFixedDelay(this::refreshData, 4, pollingIntervalInSeconds, TimeUnit.SECONDS); + + logger.debug("amazon account bridge handler started."); + } + + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + logger.trace("Command '{}' received for channel '{}'", command, channelUID); + if (command instanceof RefreshType) { + refreshData(); + } + } + + public List getFlashBriefingProfileHandlers() { + return new ArrayList<>(this.flashBriefingProfileHandlers); + } + + public List getLastKnownDevices() { + return new ArrayList<>(jsonSerialNumberDeviceMapping.values()); + } + + public void addEchoHandler(EchoHandler echoHandler) { + synchronized (echoHandlers) { + echoHandlers.add(echoHandler); + } + Connection connection = this.connection; + if (connection != null) { + initializeEchoHandler(echoHandler, connection); + } + } + + public @Nullable Thing findThingBySerialNumber(@Nullable String deviceSerialNumber) { + synchronized (echoHandlers) { + for (EchoHandler echoHandler : echoHandlers) { + if (StringUtils.equals(echoHandler.findSerialNumber(), deviceSerialNumber)) { + return echoHandler.getThing(); + } + } + } + return null; + } + + public void addFlashBriefingProfileHandler(FlashBriefingProfileHandler flashBriefingProfileHandler) { + synchronized (flashBriefingProfileHandlers) { + flashBriefingProfileHandlers.add(flashBriefingProfileHandler); + } + Connection connection = this.connection; + if (connection != null) { + if (currentFlashBriefingJson.isEmpty()) { + updateFlashBriefingProfiles(connection); + } + flashBriefingProfileHandler.initialize(this, currentFlashBriefingJson); + } + } + + private void initializeEchoHandler(EchoHandler echoHandler, Connection connection) { + intializeChildDevice(connection, echoHandler); + + @Nullable + Device device = findDeviceJson(echoHandler); + + JsonBluetoothStates states = null; + if (connection.getIsLoggedIn()) { + states = connection.getBluetoothConnectionStates(); + } + + BluetoothState state = null; + if (states != null) { + state = states.findStateByDevice(device); + } + echoHandler.updateState(device, state); + } + + private void intializeChildDevice(Connection connection, EchoHandler child) { + Device deviceJson = this.findDeviceJson(child); + if (deviceJson != null) { + child.intialize(connection, deviceJson); + } + } + + @Override + public void handleRemoval() { + cleanup(); + super.handleRemoval(); + } + + @Override + public void childHandlerDisposed(ThingHandler childHandler, Thing childThing) { + // check for echo handler + if (childHandler instanceof EchoHandler) { + synchronized (echoHandlers) { + echoHandlers.remove(childHandler); + } + } + // check for flash briefing profile handler + if (childHandler instanceof FlashBriefingProfileHandler) { + synchronized (flashBriefingProfileHandlers) { + flashBriefingProfileHandlers.remove(childHandler); + } + } + super.childHandlerDisposed(childHandler, childThing); + } + + @Override + public void dispose() { + AccountServlet accountServlet = this.accountServlet; + if (accountServlet != null) { + accountServlet.dispose(); + } + this.accountServlet = null; + cleanup(); + super.dispose(); + } + + private void cleanup() { + logger.debug("cleanup {}", getThing().getUID().getAsString()); + @Nullable + ScheduledFuture refreshJob = this.refreshJob; + if (refreshJob != null) { + refreshJob.cancel(true); + this.refreshJob = null; + } + @Nullable + ScheduledFuture refreshLogin = this.refreshLogin; + if (refreshLogin != null) { + refreshLogin.cancel(true); + this.refreshLogin = null; + } + Connection connection = this.connection; + if (connection != null) { + connection.logout(); + this.connection = null; + } + } + + private void checkLogin() { + try { + logger.debug("check login {}", getThing().getUID().getAsString()); + + synchronized (synchronizeConnection) { + Connection currentConnection = this.connection; + if (currentConnection == null) { + return; + } + Date verifyTime = currentConnection.tryGetVerifyTime(); + Date currentDate = new Date(); + long currentTime = currentDate.getTime(); + if (verifyTime != null && currentTime - verifyTime.getTime() > 3600000) // Every one hour + { + try { + if (!currentConnection.verifyLogin()) { + currentConnection.logout(); + } + } catch (IOException | URISyntaxException e) { + logger.info("logout failed: {}", e.getMessage()); + currentConnection.logout(); + } + } + Date loginTime = currentConnection.tryGetLoginTime(); + if (loginTime != null && currentTime - loginTime.getTime() > 86400000 * 5) // 5 days + { + // Recreate session + this.stateStorage.put("sessionStorage", ""); + currentConnection = new Connection(currentConnection.getEmail(), currentConnection.getPassword(), + currentConnection.getAmazonSite(), this.getThing().getUID().getId()); + } + boolean loginIsValid = true; + if (!currentConnection.getIsLoggedIn()) { + try { + + // read session data from property + String sessionStore = this.stateStorage.get("sessionStorage"); + + // try use the session data + if (!currentConnection.tryRestoreLogin(sessionStore)) { + // session data not valid -> login + int retry = 0; + while (true) { + try { + currentConnection.makeLogin(); + break; + } catch (ConnectionException e) { + // Up to 2 retries for login + retry++; + if (retry >= 2) { + currentConnection.logout(); + throw e; + } + // give amazon some time + try { + Thread.sleep(2000); + } catch (InterruptedException exception) { + // throw the original exception + throw e; + } + } + } + // store session data in property + String serializedStorage = currentConnection.serializeLoginData(); + this.stateStorage.put("sessionStorage", serializedStorage); + } + this.connection = currentConnection; + } catch (ConnectionException e) { + loginIsValid = false; + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, e.getMessage()); + } catch (UnknownHostException e) { + loginIsValid = false; + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Unknown host name '" + + e.getMessage() + "'. Maybe your internet connection is offline"); + } catch (IOException e) { + loginIsValid = false; + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, + e.getLocalizedMessage()); + } catch (URISyntaxException e) { + loginIsValid = false; + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, + e.getLocalizedMessage()); + } + if (loginIsValid) { + handleValidLogin(); + } + } + } + } catch (HttpException | JsonSyntaxException | ConnectionException e) { + logger.debug("check login fails {}", e); + } catch (Exception e) { // this handler can be removed later, if we know that nothing else can fail. + logger.error("check login fails with unexpected error {}", e); + } + } + + private void handleValidLogin() { + updateDeviceList(); + updateFlashBriefingHandlers(); + updateStatus(ThingStatus.ONLINE); + } + + // used to set a valid connection from the web proxy login + public void setConnection(Connection connection) { + this.connection = connection; + String serializedStorage = connection.serializeLoginData(); + this.stateStorage.put("sessionStorage", serializedStorage); + handleValidLogin(); + } + + private void refreshData() { + try { + logger.debug("refreshing data {}", getThing().getUID().getAsString()); + + // check if logged in + Connection currentConnection = null; + synchronized (synchronizeConnection) { + currentConnection = connection; + if (currentConnection != null) { + if (!currentConnection.getIsLoggedIn()) { + return; + } + } + } + if (currentConnection == null) { + return; + } + + // get all devices registered in the account + updateDeviceList(); + updateFlashBriefingHandlers(); + + // update bluetooth states + JsonBluetoothStates states = null; + if (currentConnection.getIsLoggedIn()) { + states = currentConnection.getBluetoothConnectionStates(); + } + + // forward device information to echo handler + for (EchoHandler child : echoHandlers) { + Device device = findDeviceJson(child); + BluetoothState state = null; + if (states != null) { + state = states.findStateByDevice(device); + } + child.updateState(device, state); + } + + // update account state + updateStatus(ThingStatus.ONLINE); + + logger.debug("refresh data {} finished", getThing().getUID().getAsString()); + } catch (HttpException | JsonSyntaxException | ConnectionException e) { + logger.debug("refresh data fails {}", e); + } catch (Exception e) { // this handler can be removed later, if we know that nothing else can fail. + logger.error("refresh data fails with unexpected error {}", e); + } + } + + public @Nullable Device findDeviceJson(EchoHandler echoHandler) { + String serialNumber = echoHandler.findSerialNumber(); + return findDeviceJson(serialNumber); + } + + public @Nullable Device findDeviceJson(@Nullable String serialNumber) { + Device result = null; + if (StringUtils.isNotEmpty(serialNumber)) { + Map jsonSerialNumberDeviceMapping = this.jsonSerialNumberDeviceMapping; + result = jsonSerialNumberDeviceMapping.get(serialNumber); + } + return result; + } + + public @Nullable Device findDeviceJsonBySerialOrName(@Nullable String serialOrName) { + if (StringUtils.isNotEmpty(serialOrName)) { + Map currentJsonSerialNumberDeviceMapping = this.jsonSerialNumberDeviceMapping; + for (Device device : currentJsonSerialNumberDeviceMapping.values()) { + if (StringUtils.equalsIgnoreCase(device.serialNumber, serialOrName)) { + return device; + } + } + for (Device device : currentJsonSerialNumberDeviceMapping.values()) { + if (StringUtils.equalsIgnoreCase(device.accountName, serialOrName)) { + return device; + } + } + } + return null; + } + + public List updateDeviceList() { + + Connection currentConnection = connection; + if (currentConnection == null) { + return new ArrayList(); + } + + List devices = null; + try { + if (currentConnection.getIsLoggedIn()) { + devices = currentConnection.getDeviceList(); + } + } catch (IOException | URISyntaxException e) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getLocalizedMessage()); + } + if (devices != null) { + Map newJsonSerialDeviceMapping = new HashMap<>(); + for (Device device : devices) { + String serialNumber = device.serialNumber; + if (serialNumber != null) { + newJsonSerialDeviceMapping.put(serialNumber, device); + } + } + jsonSerialNumberDeviceMapping = newJsonSerialDeviceMapping; + } + synchronized (echoHandlers) { + for (EchoHandler child : echoHandlers) { + initializeEchoHandler(child, currentConnection); + } + } + if (devices != null) { + return devices; + } + return new ArrayList(); + } + + public void setEnabledFlashBriefingsJson(String flashBriefingJson) { + Connection currentConnection = connection; + JsonFeed[] feeds = gson.fromJson(flashBriefingJson, JsonFeed[].class); + if (currentConnection != null) { + try { + currentConnection.setEnabledFlashBriefings(feeds); + } catch (IOException | URISyntaxException e) { + logger.warn("Set flashbriefing profile failed {}", e); + } + } + updateFlashBriefingHandlers(); + } + + public String getNewCurrentFlashbriefingConfiguration() { + return updateFlashBriefingHandlers(); + } + + public String updateFlashBriefingHandlers() { + Connection currentConnection = connection; + if (currentConnection != null) { + return updateFlashBriefingHandlers(currentConnection); + } + return ""; + } + + private String updateFlashBriefingHandlers(Connection currentConnection) { + synchronized (flashBriefingProfileHandlers) { + if (!flashBriefingProfileHandlers.isEmpty() || currentFlashBriefingJson.isEmpty()) { + updateFlashBriefingProfiles(currentConnection); + } + boolean flashBriefingProfileFound = false; + for (FlashBriefingProfileHandler child : flashBriefingProfileHandlers) { + flashBriefingProfileFound |= child.initialize(this, currentFlashBriefingJson); + } + if (flashBriefingProfileFound) { + return ""; + } + return this.currentFlashBriefingJson; + } + } + + public @Nullable Connection findConnection() { + return this.connection; + } + + public String getEnabledFlashBriefingsJson() { + Connection currentConnection = this.connection; + if (currentConnection == null) { + return ""; + } + updateFlashBriefingProfiles(currentConnection); + return this.currentFlashBriefingJson; + } + + private void updateFlashBriefingProfiles(Connection currentConnection) { + try { + JsonFeed[] feeds = currentConnection.getEnabledFlashBriefings(); + // Make a copy and remove changeable parts + JsonFeed[] forSerializer = new JsonFeed[feeds.length]; + for (int i = 0; i < feeds.length; i++) { + JsonFeed source = feeds[i]; + JsonFeed copy = new JsonFeed(); + copy.feedId = source.feedId; + copy.skillId = source.skillId; + // Do not copy imageUrl here, because it will change + forSerializer[i] = copy; + } + this.currentFlashBriefingJson = gson.toJson(forSerializer); + } catch (HttpException | JsonSyntaxException | IOException | URISyntaxException | ConnectionException e) { + logger.warn("get flash briefing profiles fails {}", e); + } + + } + +} diff --git a/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/handler/EchoHandler.java b/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/handler/EchoHandler.java new file mode 100755 index 0000000000000..74e2b2f873d95 --- /dev/null +++ b/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/handler/EchoHandler.java @@ -0,0 +1,800 @@ +/** + * Copyright (c) 2010-2018 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.amazonechocontrol.handler; + +import static org.openhab.binding.amazonechocontrol.AmazonEchoControlBindingConstants.*; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +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.IncreaseDecreaseType; +import org.eclipse.smarthome.core.library.types.NextPreviousType; +import org.eclipse.smarthome.core.library.types.OnOffType; +import org.eclipse.smarthome.core.library.types.PercentType; +import org.eclipse.smarthome.core.library.types.PlayPauseType; +import org.eclipse.smarthome.core.library.types.RewindFastforwardType; +import org.eclipse.smarthome.core.library.types.StringType; +import org.eclipse.smarthome.core.thing.Bridge; +import org.eclipse.smarthome.core.thing.ChannelUID; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.ThingStatus; +import org.eclipse.smarthome.core.thing.ThingUID; +import org.eclipse.smarthome.core.thing.binding.BaseThingHandler; +import org.eclipse.smarthome.core.types.Command; +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.HttpException; +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.JsonDevices.Device; +import org.openhab.binding.amazonechocontrol.internal.jsons.JsonMediaState; +import org.openhab.binding.amazonechocontrol.internal.jsons.JsonMediaState.QueueEntry; +import org.openhab.binding.amazonechocontrol.internal.jsons.JsonNotificationResponse; +import org.openhab.binding.amazonechocontrol.internal.jsons.JsonNotificationSound; +import org.openhab.binding.amazonechocontrol.internal.jsons.JsonPlayerState; +import org.openhab.binding.amazonechocontrol.internal.jsons.JsonPlayerState.PlayerInfo; +import org.openhab.binding.amazonechocontrol.internal.jsons.JsonPlayerState.PlayerInfo.InfoText; +import org.openhab.binding.amazonechocontrol.internal.jsons.JsonPlayerState.PlayerInfo.MainArt; +import org.openhab.binding.amazonechocontrol.internal.jsons.JsonPlayerState.PlayerInfo.Provider; +import org.openhab.binding.amazonechocontrol.internal.jsons.JsonPlayerState.PlayerInfo.Volume; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link EchoHandler} is responsible for the handling of the echo device + * + * @author Michael Geramb - Initial contribution + */ +@NonNullByDefault +public class EchoHandler extends BaseThingHandler { + + private final Logger logger = LoggerFactory.getLogger(EchoHandler.class); + + private @Nullable Device device; + private @Nullable Connection connection; + private @Nullable AccountHandler account; + private @Nullable ScheduledFuture updateStateJob; + private @Nullable String lastKnownRadioStationId; + private @Nullable String lastKnownBluetoothMAC; + private @Nullable String lastKnownAmazonMusicId; + private String musicProviderId = "TUNEIN"; + private boolean isPlaying = false; + private boolean isPaused = false; + private int lastKnownVolume = 25; + private @Nullable BluetoothState bluetoothState; + private boolean disableUpdate = false; + private boolean updateRemind = true; + private boolean updateTextToSpeech = true; + private boolean updateAlarm = true; + private boolean updateRoutine = true; + private boolean updatePlayMusicVoiceCommand = true; + private boolean updateStartCommand = true; + private @Nullable JsonNotificationResponse currentNotification; + private @Nullable ScheduledFuture currentNotifcationUpdateTimer; + + public EchoHandler(Thing thing) { + super(thing); + } + + @Override + public void initialize() { + logger.debug("Amazon Echo Control Binding initialized"); + + if (this.connection != null) { + setDeviceAndUpdateThingState(this.device); + } else { + updateStatus(ThingStatus.UNKNOWN); + Bridge bridge = this.getBridge(); + if (bridge != null) { + AccountHandler account = (AccountHandler) bridge.getHandler(); + if (account != null) { + this.account = account; + account.addEchoHandler(this); + } + } + } + } + + public void intialize(Connection connection, @Nullable Device deviceJson) { + this.connection = connection; + setDeviceAndUpdateThingState(deviceJson); + } + + boolean setDeviceAndUpdateThingState(@Nullable Device device) { + if (device == null) { + updateStatus(ThingStatus.UNKNOWN); + return false; + } + this.device = device; + if (!device.online) { + updateStatus(ThingStatus.OFFLINE); + return false; + } + updateStatus(ThingStatus.ONLINE); + return true; + } + + @Override + public void dispose() { + stopCurrentNotification(); + ScheduledFuture updateStateJob = this.updateStateJob; + this.updateStateJob = null; + if (updateStateJob != null) { + updateStateJob.cancel(false); + } + super.dispose(); + } + + public @Nullable BluetoothState findBluetoothState() { + return this.bluetoothState; + } + + public @Nullable Connection findConnection() { + return this.connection; + } + + public @Nullable AccountHandler findAccount() { + return this.account; + } + + public @Nullable Device findDevice() { + return this.device; + } + + public String findSerialNumber() { + String id = (String) getConfig().get(DEVICE_PROPERTY_SERIAL_NUMBER); + if (id == null) { + return ""; + } + return id; + } + + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + try { + int waitForUpdate = 1000; + boolean needBluetoothRefresh = false; + String lastKnownBluetoothMAC = this.lastKnownBluetoothMAC; + + ScheduledFuture updateStateJob = this.updateStateJob; + this.updateStateJob = null; + if (updateStateJob != null) { + updateStateJob.cancel(false); + } + + Connection connection = this.connection; + if (connection == null) { + return; + } + Device device = this.device; + if (device == null) { + return; + } + + // Player commands + String channelId = channelUID.getId(); + if (channelId.equals(CHANNEL_PLAYER)) { + if (command == PlayPauseType.PAUSE || command == OnOffType.OFF) { + connection.command(device, "{\"type\":\"PauseCommand\"}"); + } else if (command == PlayPauseType.PLAY || command == OnOffType.ON) { + if (isPaused) { + connection.command(device, "{\"type\":\"PlayCommand\"}"); + } else { + connection.playMusicVoiceCommand(device, this.musicProviderId, "!"); + waitForUpdate = 3000; + } + } else if (command == NextPreviousType.NEXT) { + connection.command(device, "{\"type\":\"NextCommand\"}"); + } else if (command == NextPreviousType.PREVIOUS) { + connection.command(device, "{\"type\":\"PreviousCommand\"}"); + } else if (command == RewindFastforwardType.FASTFORWARD) { + connection.command(device, "{\"type\":\"ForwardCommand\"}"); + } else if (command == RewindFastforwardType.REWIND) { + connection.command(device, "{\"type\":\"RewindCommand\"}"); + } + } + // Volume commands + if (channelId.equals(CHANNEL_VOLUME)) { + if (command instanceof PercentType) { + PercentType value = (PercentType) command; + int volume = value.intValue(); + connection.command(device, "{\"type\":\"VolumeLevelCommand\",\"volumeLevel\":" + volume + + ",\"contentFocusClientId\":\"Default\"}"); + } else if (command == OnOffType.OFF) { + connection.command(device, "{\"type\":\"VolumeLevelCommand\",\"volumeLevel\":" + 0 + + ",\"contentFocusClientId\":\"Default\"}"); + } else if (command == OnOffType.ON) { + connection.command(device, "{\"type\":\"VolumeLevelCommand\",\"volumeLevel\":" + lastKnownVolume + + ",\"contentFocusClientId\":\"Default\"}"); + } else if (command == IncreaseDecreaseType.INCREASE) { + if (lastKnownVolume < 100) { + lastKnownVolume++; + updateState(CHANNEL_VOLUME, new PercentType(lastKnownVolume)); + connection.command(device, "{\"type\":\"VolumeLevelCommand\",\"volumeLevel\":" + lastKnownVolume + + ",\"contentFocusClientId\":\"Default\"}"); + } + } else if (command == IncreaseDecreaseType.DECREASE) { + if (lastKnownVolume > 0) { + lastKnownVolume--; + updateState(CHANNEL_VOLUME, new PercentType(lastKnownVolume)); + connection.command(device, "{\"type\":\"VolumeLevelCommand\",\"volumeLevel\":" + lastKnownVolume + + ",\"contentFocusClientId\":\"Default\"}"); + } + } + } + // shuffle command + if (channelId.equals(CHANNEL_SHUFFLE)) { + if (command instanceof OnOffType) { + OnOffType value = (OnOffType) command; + + connection.command(device, "{\"type\":\"ShuffleCommand\",\"shuffle\":\"" + + (value == OnOffType.ON ? "true" : "false") + "\"}"); + } + } + + // play music command + if (channelId.equals(CHANNEL_MUSIC_PROVIDER_ID)) { + if (command instanceof StringType) { + waitForUpdate = 0; + String musicProviderId = ((StringType) command).toFullString(); + if (!StringUtils.equals(musicProviderId, this.musicProviderId)) { + this.musicProviderId = musicProviderId; + if (this.isPlaying) { + connection.playMusicVoiceCommand(device, this.musicProviderId, "!"); + waitForUpdate = 3000; + } + } + + } + } + if (channelId.equals(CHANNEL_PLAY_MUSIC_VOICE_COMMAND)) { + if (command instanceof StringType) { + String voiceCommand = ((StringType) command).toFullString(); + if (!this.musicProviderId.isEmpty()) { + connection.playMusicVoiceCommand(device, this.musicProviderId, voiceCommand); + waitForUpdate = 3000; + updatePlayMusicVoiceCommand = true; + } + } + } + + // bluetooth commands + if (channelId.equals(CHANNEL_BLUETOOTH_MAC)) { + needBluetoothRefresh = true; + if (command instanceof StringType) { + String address = ((StringType) command).toFullString(); + if (!address.isEmpty()) { + waitForUpdate = 4000; + } + connection.bluetooth(device, address); + } + } + if (channelId.equals(CHANNEL_BLUETOOTH)) { + needBluetoothRefresh = true; + if (command == OnOffType.ON) { + waitForUpdate = 4000; + String bluetoothId = lastKnownBluetoothMAC; + BluetoothState state = bluetoothState; + if (state != null && (StringUtils.isEmpty(bluetoothId))) { + PairedDevice[] pairedDeviceList = state.pairedDeviceList; + if (pairedDeviceList != null) { + for (PairedDevice paired : pairedDeviceList) { + if (paired == null) { + continue; + } + if (StringUtils.isNotEmpty(paired.address)) { + lastKnownBluetoothMAC = paired.address; + break; + } + } + } + } + if (StringUtils.isNotEmpty(lastKnownBluetoothMAC)) { + connection.bluetooth(device, lastKnownBluetoothMAC); + } + } else if (command == OnOffType.OFF) { + connection.bluetooth(device, null); + } + } + if (channelId.equals(CHANNEL_BLUETOOTH_DEVICE_NAME)) { + needBluetoothRefresh = true; + } + // amazon music commands + if (channelId.equals(CHANNEL_AMAZON_MUSIC_TRACK_ID)) { + if (command instanceof StringType) { + + String trackId = ((StringType) command).toFullString(); + if (StringUtils.isNotEmpty(trackId)) { + waitForUpdate = 3000; + } + connection.playAmazonMusicTrack(device, trackId); + + } + } + if (channelId.equals(CHANNEL_AMAZON_MUSIC_PLAY_LIST_ID)) { + if (command instanceof StringType) { + + String playListId = ((StringType) command).toFullString(); + if (StringUtils.isNotEmpty(playListId)) { + waitForUpdate = 3000; + } + connection.playAmazonMusicPlayList(device, playListId); + + } + } + if (channelId.equals(CHANNEL_AMAZON_MUSIC)) { + + if (command == OnOffType.ON) { + String lastKnownAmazonMusicId = this.lastKnownAmazonMusicId; + if (StringUtils.isNotEmpty(lastKnownAmazonMusicId)) { + waitForUpdate = 3000; + } + connection.playAmazonMusicTrack(device, lastKnownAmazonMusicId); + } else if (command == OnOffType.OFF) { + connection.playAmazonMusicTrack(device, ""); + } + } + + // radio commands + if (channelId.equals(CHANNEL_RADIO_STATION_ID)) { + if (command instanceof StringType) { + String stationId = ((StringType) command).toFullString(); + if (StringUtils.isNotEmpty(stationId)) { + waitForUpdate = 3000; + } + connection.playRadio(device, stationId); + } + } + if (channelId.equals(CHANNEL_RADIO)) { + if (command == OnOffType.ON) { + String lastKnownRadioStationId = this.lastKnownRadioStationId; + if (StringUtils.isNotEmpty(lastKnownRadioStationId)) { + waitForUpdate = 3000; + } + connection.playRadio(device, lastKnownRadioStationId); + } else if (command == OnOffType.OFF) { + connection.playRadio(device, ""); + } + } + + // notification + if (channelId.equals(CHANNEL_REMIND)) { + if (command instanceof StringType) { + stopCurrentNotification(); + String reminder = ((StringType) command).toFullString(); + if (StringUtils.isNotEmpty(reminder)) { + waitForUpdate = 3000; + updateRemind = true; + currentNotification = connection.notification(device, "Reminder", reminder, null); + currentNotifcationUpdateTimer = scheduler.scheduleWithFixedDelay(() -> { + updateNotificationTimerState(); + }, 1, 1, TimeUnit.SECONDS); + } + } + } + if (channelId.equals(CHANNEL_PLAY_ALARM_SOUND)) { + if (command instanceof StringType) { + stopCurrentNotification(); + String alarmSound = ((StringType) command).toFullString(); + if (StringUtils.isNotEmpty(alarmSound)) { + waitForUpdate = 3000; + updateAlarm = true; + String[] parts = alarmSound.split(":", 2); + JsonNotificationSound sound = new JsonNotificationSound(); + if (parts.length == 2) { + sound.providerId = parts[0]; + sound.id = parts[1]; + } else { + sound.providerId = "ECHO"; + sound.id = alarmSound; + } + currentNotification = connection.notification(device, "Alarm", null, sound); + currentNotifcationUpdateTimer = scheduler.scheduleWithFixedDelay(() -> { + updateNotificationTimerState(); + }, 1, 1, TimeUnit.SECONDS); + + } + } + } + + // routine commands + if (channelId.equals(CHANNEL_TEXT_TO_SPEECH)) { + if (command instanceof StringType) { + String text = ((StringType) command).toFullString(); + if (StringUtils.isNotEmpty(text)) { + waitForUpdate = 1000; + updateTextToSpeech = true; + connection.textToSpeech(device, text); + } + } + } + if (channelId.equals(CHANNEL_START_COMMAND)) { + if (command instanceof StringType) { + String commandText = ((StringType) command).toFullString(); + if (StringUtils.isNotEmpty(commandText)) { + updateStartCommand = true; + if (commandText.startsWith(FLASH_BRIEFING_COMMAND_PREFIX)) { + // Handle custom flashbriefings commands + String flashbriefing = commandText.substring(FLASH_BRIEFING_COMMAND_PREFIX.length()); + + AccountHandler account = this.account; + if (account != null) { + for (FlashBriefingProfileHandler flashBriefing : account + .getFlashBriefingProfileHandlers()) { + ThingUID flashBriefingId = flashBriefing.getThing().getUID(); + if (StringUtils.equals(flashBriefing.getThing().getUID().getId(), flashbriefing)) { + flashBriefing.handleCommand( + new ChannelUID(flashBriefingId, CHANNEL_PLAY_ON_DEVICE), + new StringType(device.serialNumber)); + break; + } + } + } + } else { + // Handle standard commands + if (!commandText.startsWith("Alexa.")) { + commandText = "Alexa." + commandText + ".Play"; + } + waitForUpdate = 1000; + connection.executeSequenceCommand(device, commandText, null); + } + } + } + } + if (channelId.equals(CHANNEL_START_ROUTINE)) { + if (command instanceof StringType) { + String utterance = ((StringType) command).toFullString(); + if (StringUtils.isNotEmpty(utterance)) { + waitForUpdate = 1000; + updateRoutine = true; + connection.startRoutine(device, utterance); + } + } + } + + // force update of the state + this.disableUpdate = true; + final boolean bluetoothRefresh = needBluetoothRefresh; + Runnable doRefresh = () -> { + BluetoothState state = null; + if (bluetoothRefresh) { + JsonBluetoothStates states; + states = connection.getBluetoothConnectionStates(); + state = states.findStateByDevice(device); + + } + this.disableUpdate = false; + updateState(device, state); + }; + if (command instanceof RefreshType) { + waitForUpdate = 0; + } + if (waitForUpdate == 0) { + doRefresh.run(); + } else { + this.updateStateJob = scheduler.schedule(doRefresh, waitForUpdate, TimeUnit.MILLISECONDS); + } + } catch (IOException | URISyntaxException e) { + logger.info("handleCommand fails: {}", e); + } + } + + private void stopCurrentNotification() { + ScheduledFuture currentNotifcationUpdateTimer = this.currentNotifcationUpdateTimer; + if (currentNotifcationUpdateTimer != null) { + this.currentNotifcationUpdateTimer = null; + currentNotifcationUpdateTimer.cancel(true); + } + JsonNotificationResponse currentNotification = this.currentNotification; + if (currentNotification != null) { + this.currentNotification = null; + Connection currentConnection = this.connection; + if (currentConnection != null) { + try { + currentConnection.stopNotification(currentNotification); + } catch (IOException | URISyntaxException e) { + logger.warn("Stop notification failed: {}", e); + } + } + } + } + + private void updateNotificationTimerState() { + boolean stopCurrentNotifcation = true; + JsonNotificationResponse currentNotification = this.currentNotification; + try { + if (currentNotification != null) { + Connection currentConnection = connection; + if (currentConnection != null) { + JsonNotificationResponse newState = currentConnection.getNotificationState(currentNotification); + if (StringUtils.equals(newState.status, "ON")) { + stopCurrentNotifcation = false; + } + } + } + } catch (IOException | URISyntaxException e) { + logger.warn("update notification state fails: {}", e); + } + if (stopCurrentNotifcation) { + if (currentNotification != null) { + String type = currentNotification.type; + if (type != null) { + if (type.equals("Reminder")) { + updateState(CHANNEL_REMIND, new StringType("")); + updateRemind = false; + } + if (type.equals("Alarm")) { + updateState(CHANNEL_PLAY_ALARM_SOUND, new StringType("")); + updateAlarm = false; + } + } + } + stopCurrentNotification(); + } + } + + public void updateState(@Nullable Device device, @Nullable BluetoothState bluetoothState) { + if (this.disableUpdate) { + return; + } + if (!setDeviceAndUpdateThingState(device)) { + return; + } + if (device == null) { + return; + } + + Connection connection = this.connection; + if (connection == null) { + return; + } + + PlayerInfo playerInfo = null; + Provider provider = null; + InfoText infoText = null; + MainArt mainArt = null; + try { + JsonPlayerState playerState = connection.getPlayer(device); + playerInfo = playerState.playerInfo; + if (playerInfo != null) { + infoText = playerInfo.infoText; + if (infoText == null) { + infoText = playerInfo.miniInfoText; + } + mainArt = playerInfo.mainArt; + provider = playerInfo.provider; + } + } catch (HttpException e) { + if (e.getCode() == 400) { + // Ignore + } else { + logger.info("getPlayer fails: {}", e); + } + } catch (IOException | URISyntaxException e) { + logger.info("getPlayer fails: {}", e); + } + JsonMediaState mediaState = null; + try { + mediaState = connection.getMediaState(device); + + } catch (HttpException e) { + if (e.getCode() == 400) { + + updateState(CHANNEL_RADIO_STATION_ID, new StringType("")); + + } else { + logger.info("getMediaState fails: {}", e); + } + } catch (IOException | URISyntaxException e) { + logger.info("getMediaState fails: {}", e); + } + // check playing + isPlaying = (playerInfo != null && StringUtils.equals(playerInfo.state, "PLAYING")) + || (mediaState != null && StringUtils.equals(mediaState.currentState, "PLAYING")); + + isPaused = (playerInfo != null && StringUtils.equals(playerInfo.state, "PAUSED")) + || (mediaState != null && StringUtils.equals(mediaState.currentState, "PAUSED")); + // handle music provider id + + if (provider != null && isPlaying) { + String musicProviderId; + if (mediaState != null && StringUtils.equals(mediaState.currentState, "PLAYING")) { + musicProviderId = mediaState.providerId; + } else { + musicProviderId = provider.providerName; + } + // Map the music provider id to the one used for starting music with voice command + if (musicProviderId != null) { + musicProviderId = musicProviderId.toUpperCase(); + } + if (StringUtils.equals(musicProviderId, "CLOUD_PLAYER")) { + musicProviderId = "AMAZON_MUSIC"; + } + if (StringUtils.equals(musicProviderId, "TUNE_IN")) { + musicProviderId = "TUNEIN"; + } + if (musicProviderId != null) { + this.musicProviderId = musicProviderId; + } + } + + // handle amazon music + String amazonMusicTrackId = ""; + String amazonMusicPlayListId = ""; + boolean amazonMusic = false; + if (mediaState != null && isPlaying && StringUtils.equals(mediaState.providerId, "CLOUD_PLAYER") + && StringUtils.isNotEmpty(mediaState.contentId)) { + amazonMusicTrackId = mediaState.contentId; + lastKnownAmazonMusicId = amazonMusicTrackId; + amazonMusic = true; + } + + // handle bluetooth + String bluetoothMAC = ""; + String bluetoothDeviceName = ""; + boolean bluetoothIsConnected = false; + if (bluetoothState != null) { + this.bluetoothState = bluetoothState; + PairedDevice[] pairedDeviceList = bluetoothState.pairedDeviceList; + if (pairedDeviceList != null) { + for (PairedDevice paired : pairedDeviceList) { + if (paired == null) { + continue; + } + if (paired.connected && paired.address != null) { + bluetoothIsConnected = true; + bluetoothMAC = paired.address; + bluetoothDeviceName = paired.friendlyName; + if (StringUtils.isEmpty(bluetoothDeviceName)) { + bluetoothDeviceName = paired.address; + } + break; + } + } + } + } + if (StringUtils.isNotEmpty(bluetoothMAC)) { + lastKnownBluetoothMAC = bluetoothMAC; + } + + // handle radio + boolean isRadio = false; + if (mediaState != null && StringUtils.isNotEmpty(mediaState.radioStationId)) { + lastKnownRadioStationId = mediaState.radioStationId; + if (provider != null && StringUtils.equalsIgnoreCase(provider.providerName, "TuneIn Live-Radio")) { + isRadio = true; + } + } + String radioStationId = ""; + if (isRadio && mediaState != null && StringUtils.equals(mediaState.currentState, "PLAYING") + && mediaState.radioStationId != null) { + radioStationId = mediaState.radioStationId; + } + + // handle title, subtitle, imageUrl + String title = ""; + String subTitle1 = ""; + String subTitle2 = ""; + String imageUrl = ""; + if (infoText != null) { + if (infoText.title != null) { + title = infoText.title; + } + if (infoText.subText1 != null) { + subTitle1 = infoText.subText1; + } + + if (infoText.subText2 != null) { + subTitle2 = infoText.subText2; + } + } + if (mainArt != null) { + if (mainArt.url != null) { + imageUrl = mainArt.url; + } + } + if (mediaState != null) { + QueueEntry[] queueEntries = mediaState.queue; + if (queueEntries != null && queueEntries.length > 0) { + QueueEntry entry = queueEntries[0]; + if (entry != null) { + + if (isRadio) { + if (StringUtils.isEmpty(imageUrl) && entry.imageURL != null) { + imageUrl = entry.imageURL; + } + if (StringUtils.isEmpty(subTitle1) && entry.radioStationSlogan != null) { + subTitle1 = entry.radioStationSlogan; + } + if (StringUtils.isEmpty(subTitle2) && entry.radioStationLocation != null) { + subTitle2 = entry.radioStationLocation; + } + } + } + } + } + + // handle provider + String providerDisplayName = ""; + if (provider != null) { + if (provider.providerDisplayName != null) { + providerDisplayName = provider.providerDisplayName; + } + if (StringUtils.isNotEmpty(provider.providerName) && StringUtils.isEmpty(providerDisplayName)) { + providerDisplayName = provider.providerName; + } + } + + // handle volume + Integer volume = null; + if (mediaState != null) { + volume = mediaState.volume; + } else if (playerInfo != null) { + + Volume volumnInfo = playerInfo.volume; + if (volumnInfo != null) { + volume = volumnInfo.volume; + } + } + if (volume != null && volume > 0) { + lastKnownVolume = volume; + } + + // Update states + if (updateRemind && currentNotifcationUpdateTimer == null) { + updateRemind = false; + updateState(CHANNEL_REMIND, new StringType("")); + } + if (updateAlarm && currentNotifcationUpdateTimer == null) { + updateAlarm = false; + updateState(CHANNEL_PLAY_ALARM_SOUND, new StringType("")); + } + if (updateRoutine) { + updateRoutine = false; + updateState(CHANNEL_START_ROUTINE, new StringType("")); + } + if (updateTextToSpeech) { + updateTextToSpeech = false; + updateState(CHANNEL_TEXT_TO_SPEECH, new StringType("")); + } + if (updatePlayMusicVoiceCommand) { + updatePlayMusicVoiceCommand = false; + updateState(CHANNEL_PLAY_MUSIC_VOICE_COMMAND, new StringType("")); + } + if (updateStartCommand) { + updateStartCommand = false; + updateState(CHANNEL_START_COMMAND, new StringType("")); + } + updateState(CHANNEL_MUSIC_PROVIDER_ID, new StringType(musicProviderId)); + updateState(CHANNEL_AMAZON_MUSIC_TRACK_ID, new StringType(amazonMusicTrackId)); + updateState(CHANNEL_AMAZON_MUSIC, isPlaying && amazonMusic ? OnOffType.ON : OnOffType.OFF); + updateState(CHANNEL_AMAZON_MUSIC_PLAY_LIST_ID, new StringType(amazonMusicPlayListId)); + updateState(CHANNEL_RADIO_STATION_ID, new StringType(radioStationId)); + updateState(CHANNEL_RADIO, isPlaying && isRadio ? OnOffType.ON : OnOffType.OFF); + updateState(CHANNEL_VOLUME, volume != null ? new PercentType(volume) : UnDefType.UNDEF); + updateState(CHANNEL_PROVIDER_DISPLAY_NAME, new StringType(providerDisplayName)); + updateState(CHANNEL_PLAYER, isPlaying ? PlayPauseType.PLAY : PlayPauseType.PAUSE); + updateState(CHANNEL_IMAGE_URL, new StringType(imageUrl)); + updateState(CHANNEL_TITLE, new StringType(title)); + updateState(CHANNEL_SUBTITLE1, new StringType(subTitle1)); + updateState(CHANNEL_SUBTITLE2, new StringType(subTitle2)); + if (bluetoothState != null) { + updateState(CHANNEL_BLUETOOTH, bluetoothIsConnected ? OnOffType.ON : OnOffType.OFF); + updateState(CHANNEL_BLUETOOTH_MAC, new StringType(bluetoothMAC)); + updateState(CHANNEL_BLUETOOTH_DEVICE_NAME, new StringType(bluetoothDeviceName)); + } + } +} diff --git a/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/handler/FlashBriefingProfileHandler.java b/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/handler/FlashBriefingProfileHandler.java new file mode 100644 index 0000000000000..e842dcd721c76 --- /dev/null +++ b/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/handler/FlashBriefingProfileHandler.java @@ -0,0 +1,200 @@ +/** + * Copyright (c) 2010-2018 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.amazonechocontrol.handler; + +import static org.openhab.binding.amazonechocontrol.AmazonEchoControlBindingConstants.*; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +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.OnOffType; +import org.eclipse.smarthome.core.library.types.StringType; +import org.eclipse.smarthome.core.storage.Storage; +import org.eclipse.smarthome.core.thing.Bridge; +import org.eclipse.smarthome.core.thing.ChannelUID; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.ThingStatus; +import org.eclipse.smarthome.core.thing.binding.BaseThingHandler; +import org.eclipse.smarthome.core.types.Command; +import org.eclipse.smarthome.core.types.RefreshType; +import org.openhab.binding.amazonechocontrol.internal.Connection; +import org.openhab.binding.amazonechocontrol.internal.jsons.JsonDevices.Device; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link FlashBriefingProfileHandler} is responsible for storing and loading of a flash briefing configuration + * + * @author Michael Geramb - Initial contribution + */ +@NonNullByDefault +public class FlashBriefingProfileHandler extends BaseThingHandler { + + private final Logger logger = LoggerFactory.getLogger(FlashBriefingProfileHandler.class); + + @Nullable + AccountHandler accountHandler; + Storage stateStorage; + boolean updatePlayOnDevice = true; + String currentConfigurationJson = ""; + private @Nullable ScheduledFuture updateStateJob; + + public FlashBriefingProfileHandler(Thing thing, Storage storage) { + super(thing); + this.stateStorage = storage; + } + + public @Nullable AccountHandler findAccountHandler() { + return this.accountHandler; + } + + @Override + public void initialize() { + updatePlayOnDevice = true; + logger.info("{} initialized", getClass().getSimpleName()); + if (!this.currentConfigurationJson.isEmpty()) { + updateStatus(ThingStatus.ONLINE); + } else { + updateStatus(ThingStatus.UNKNOWN); + Bridge bridge = this.getBridge(); + if (bridge != null) { + AccountHandler account = (AccountHandler) bridge.getHandler(); + if (account != null) { + account.addFlashBriefingProfileHandler(this); + } + } + } + } + + @Override + public void dispose() { + ScheduledFuture updateStateJob = this.updateStateJob; + this.updateStateJob = null; + if (updateStateJob != null) { + updateStateJob.cancel(false); + } + super.dispose(); + } + + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + AccountHandler accountHandler = this.accountHandler; + if (accountHandler == null) { + return; + } + int waitForUpdate = -1; + + ScheduledFuture updateStateJob = this.updateStateJob; + this.updateStateJob = null; + if (updateStateJob != null) { + updateStateJob.cancel(false); + } + try { + String channelId = channelUID.getId(); + if (command instanceof RefreshType) { + waitForUpdate = 0; + } + if (channelId.equals(CHANNEL_SAVE)) { + if (command.equals(OnOffType.ON)) { + saveCurrentProfile(accountHandler); + waitForUpdate = 500; + } + } + if (channelId.equals(CHANNEL_ACTIVE)) { + if (command.equals(OnOffType.ON)) { + String currentConfigurationJson = this.currentConfigurationJson; + if (!currentConfigurationJson.isEmpty()) { + accountHandler.setEnabledFlashBriefingsJson(currentConfigurationJson); + updateState(CHANNEL_ACTIVE, OnOffType.ON); + waitForUpdate = 500; + } + } + } + if (channelId.equals(CHANNEL_PLAY_ON_DEVICE)) { + if (command instanceof StringType) { + String deviceSerialOrName = ((StringType) command).toFullString(); + String currentConfigurationJson = this.currentConfigurationJson; + if (!currentConfigurationJson.isEmpty()) { + String old = accountHandler.getEnabledFlashBriefingsJson(); + accountHandler.setEnabledFlashBriefingsJson(currentConfigurationJson); + Device device = accountHandler.findDeviceJsonBySerialOrName(deviceSerialOrName); + if (device == null) { + logger.warn("Device '{}' not found", deviceSerialOrName); + } else { + @Nullable + Connection connection = accountHandler.findConnection(); + if (connection == null) { + logger.warn("Connection for '{}' not found", + accountHandler.getThing().getUID().getId()); + } else { + connection.executeSequenceCommand(device, "Alexa.FlashBriefing.Play", null); + + scheduler.schedule(() -> accountHandler.setEnabledFlashBriefingsJson(old), 1000, + TimeUnit.MILLISECONDS); + + updateState(CHANNEL_ACTIVE, OnOffType.ON); + } + } + updatePlayOnDevice = true; + waitForUpdate = 1000; + } + } + } + } catch (IOException | URISyntaxException e) { + logger.warn("Handle command failed {}", e); + } + if (waitForUpdate >= 0) { + this.updateStateJob = scheduler.schedule(() -> accountHandler.updateFlashBriefingHandlers(), waitForUpdate, + TimeUnit.MILLISECONDS); + } + } + + public boolean initialize(AccountHandler handler, String currentConfigurationJson) { + updateState(CHANNEL_SAVE, OnOffType.OFF); + if (updatePlayOnDevice) { + updateState(CHANNEL_PLAY_ON_DEVICE, new StringType("")); + } + if (this.accountHandler != handler) { + this.accountHandler = handler; + String configurationJson = this.stateStorage.get("configurationJson"); + if (configurationJson == null || configurationJson.isEmpty()) { + this.currentConfigurationJson = saveCurrentProfile(handler); + } else { + this.currentConfigurationJson = configurationJson; + } + if (!this.currentConfigurationJson.isEmpty()) { + updateStatus(ThingStatus.ONLINE); + + } else { + updateStatus(ThingStatus.UNKNOWN); + } + } + if (this.currentConfigurationJson.equals(currentConfigurationJson)) { + updateState(CHANNEL_ACTIVE, OnOffType.ON); + } else { + updateState(CHANNEL_ACTIVE, OnOffType.OFF); + } + return StringUtils.equals(this.currentConfigurationJson, currentConfigurationJson); + } + + private String saveCurrentProfile(AccountHandler connection) { + String configurationJson = ""; + configurationJson = connection.getEnabledFlashBriefingsJson(); + this.currentConfigurationJson = configurationJson; + if (!configurationJson.isEmpty()) { + this.stateStorage.put("configurationJson", configurationJson); + } + return configurationJson; + } +} diff --git a/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/AccountConfiguration.java b/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/AccountConfiguration.java new file mode 100755 index 0000000000000..433d0f8e492c2 --- /dev/null +++ b/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/AccountConfiguration.java @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2010-2018 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ + +package org.openhab.binding.amazonechocontrol.internal; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + +/** + * Account Thing configuration + * + * @author Michael Geramb - Initial Contribution + */ +@NonNullByDefault +public class AccountConfiguration { + @Nullable + public String email; + @Nullable + public String password; + @Nullable + public String amazonSite; + @Nullable + public Integer pollingIntervalInSeconds; +} diff --git a/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/AccountServlet.java b/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/AccountServlet.java new file mode 100644 index 0000000000000..232105ad8b60e --- /dev/null +++ b/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/AccountServlet.java @@ -0,0 +1,511 @@ +/** + * Copyright (c) 2010-2018 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.amazonechocontrol.internal; + +import static org.openhab.binding.amazonechocontrol.AmazonEchoControlBindingConstants.*; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URISyntaxException; +import java.net.URLDecoder; +import java.net.URLEncoder; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.net.ssl.HttpsURLConnection; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang.StringEscapeUtils; +import org.apache.commons.lang.StringUtils; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.thing.Thing; +import org.openhab.binding.amazonechocontrol.handler.AccountHandler; +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.JsonDevices.Device; +import org.openhab.binding.amazonechocontrol.internal.jsons.JsonMusicProvider; +import org.openhab.binding.amazonechocontrol.internal.jsons.JsonNotificationSound; +import org.openhab.binding.amazonechocontrol.internal.jsons.JsonPlaylists; +import org.openhab.binding.amazonechocontrol.internal.jsons.JsonPlaylists.PlayList; +import org.osgi.service.http.HttpService; +import org.osgi.service.http.NamespaceException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.JsonSyntaxException; + +/** + * + * Provides the following functions + * --- Login --- + * Simple http proxy to forward the login dialog from amazon to the user through the binding + * so the user can enter a captcha or other extended login information + * --- List of devices --- + * Used to get the device information of new devices which are currently not known + * --- List of IDs --- + * Simple possibility for a user to get the ids needed for writing rules + * + * @author Michael Geramb - Initial Contribution + */ +@NonNullByDefault +public class AccountServlet extends HttpServlet { + + private static final long serialVersionUID = -1453738923337413163L; + private static final String FORWARD_URI_PART = "/FORWARD/"; + + private final Logger logger = LoggerFactory.getLogger(AccountServlet.class); + + HttpService httpService; + String servletUrlWithoutRoot; + String servletUrl; + AccountHandler account; + AccountConfiguration configuration; + String id; + Connection connection; + + public AccountServlet(HttpService httpService, String id, AccountHandler account, + AccountConfiguration configuration) { + this.httpService = httpService; + this.account = account; + this.id = id; + this.configuration = configuration; + this.connection = reCreateConnection(); + try { + servletUrlWithoutRoot = "amazonechocontrol/" + URLEncoder.encode(id, "UTF8"); + } catch (UnsupportedEncodingException e) { + servletUrlWithoutRoot = ""; + servletUrl = ""; + logger.warn("Register servlet fails {}", e); + return; + } + servletUrl = "/" + servletUrlWithoutRoot; + try { + httpService.registerServlet(servletUrl, this, null, httpService.createDefaultHttpContext()); + } catch (ServletException e) { + logger.warn("Register servlet fails {}", e); + } catch (NamespaceException e) { + logger.warn("Register servlet fails {}", e); + } + } + + private Connection reCreateConnection() { + return new Connection(configuration.email, configuration.password, configuration.amazonSite, this.id); + } + + public void dispose() { + httpService.unregister(servletUrl); + } + + @Override + protected void doPost(@Nullable HttpServletRequest req, @Nullable HttpServletResponse resp) + throws ServletException, IOException { + if (req == null) { + return; + } + if (resp == null) { + return; + } + resp.addHeader("content-type", "text/html;charset=UTF-8"); + + Map map = req.getParameterMap(); + StringBuilder postDataBuilder = new StringBuilder(); + for (String name : map.keySet()) { + if (postDataBuilder.length() > 0) { + postDataBuilder.append('&'); + } + postDataBuilder.append(name); + postDataBuilder.append('='); + String value = map.get(name)[0]; + postDataBuilder.append(URLEncoder.encode(value, "UTF-8")); + if (name.equals("email") && !value.equalsIgnoreCase(configuration.email)) { + returnError(resp, + "Email must match the configured email of your thing. Change your configuration or retype your email."); + return; + } + + if (name.equals("password") && !value.equals(configuration.password)) { + returnError(resp, + "Password must match the configured password of your thing. Change your configuration or retype your password."); + return; + } + } + + String uri = req.getRequestURI(); + if (!uri.startsWith(servletUrl)) { + returnError(resp, "Invalid request uri '" + uri + "'"); + return; + } + String relativeUrl = uri.substring(servletUrl.length()).replace(FORWARD_URI_PART, "/"); + + String postUrl = "https://www." + connection.getAmazonSite() + relativeUrl; + String queryString = req.getQueryString(); + if (queryString != null && queryString.length() > 0) { + postUrl += "?" + queryString; + } + String referer = "https://www." + connection.getAmazonSite(); + String postData = postDataBuilder.toString(); + HandleProxyRequest(resp, "POST", postUrl, referer, postData); + } + + @Override + protected void doGet(@Nullable HttpServletRequest req, @Nullable HttpServletResponse resp) + throws ServletException, IOException { + if (req == null) { + return; + } + if (resp == null) { + return; + } + String baseUrl = req.getRequestURI().substring(servletUrl.length()); + String uri = baseUrl; + String queryString = req.getQueryString(); + if (queryString != null && queryString.length() > 0) { + uri += "?" + queryString; + } + logger.debug("doGet {}", uri); + try { + if (uri.startsWith(FORWARD_URI_PART)) { + + String getUrl = "https://www." + connection.getAmazonSite() + "/" + + uri.substring(FORWARD_URI_PART.length()); + + this.HandleProxyRequest(resp, "GET", getUrl, null, null); + return; + } + + Connection connection = this.account.findConnection(); + if (connection != null && connection.verifyLogin()) { + + // handle diagnostic commands + if (baseUrl.equals("/devices") || baseUrl.equals("/devices/")) { + handleDevices(resp, connection); + return; + } + if (baseUrl.equals("/ids") || baseUrl.equals("/ids/")) { + String serialNumber = getQueryMap(queryString).get("serialNumber"); + Device device = account.findDeviceJson(serialNumber); + if (device != null) { + Thing thing = account.findThingBySerialNumber(device.serialNumber); + if (thing != null) { + handleIds(resp, connection, device, thing); + } + return; + } + } + // return hint that everything is ok + handleDefaultPageResult(resp, "The Account is already logged in."); + return; + } + + if (!uri.equals("/")) { + String newUri = req.getServletPath() + "/"; + resp.sendRedirect(newUri); + return; + } + + String html = this.connection.getLoginPage(); + returnHtml(resp, html); + } catch (URISyntaxException e) { + logger.warn("get failed with uri syntax error {}", e); + } + } + + public Map getQueryMap(@Nullable String query) { + Map map = new HashMap(); + if (query != null) { + String[] params = query.split("&"); + for (String param : params) { + String[] elements = param.split("="); + if (elements.length == 2) { + String name = elements[0]; + String value = ""; + try { + value = URLDecoder.decode(elements[1], "UTF8"); + } catch (UnsupportedEncodingException e) { + logger.info("Unsupported encoding {}", e); + } + map.put(name, value); + } + } + } + return map; + } + + private void handleDefaultPageResult(HttpServletResponse resp, String message) throws IOException { + StringBuilder html = createPageStart("Index"); + html.append(StringEscapeUtils.escapeHtml(message + " The account thing should be online.")); + html.append("
"); + html.append(StringEscapeUtils.escapeHtml("Check Thing in Paper UI")); + html.append("

"); + + html.append( + ""); + for (Device device : this.account.getLastKnownDevices()) { + + html.append(""); + } + html.append("
DeviceSerial NumberStateThingTypeFamily
"); + html.append(StringEscapeUtils.escapeHtml(nullReplacement(device.accountName))); + html.append(""); + html.append(StringEscapeUtils.escapeHtml(nullReplacement(device.serialNumber))); + html.append(""); + html.append(StringEscapeUtils.escapeHtml(device.online ? "Online" : "Offline")); + html.append(""); + Thing accountHandler = account.findThingBySerialNumber(device.serialNumber); + if (accountHandler != null) { + html.append("" + + StringEscapeUtils.escapeHtml(accountHandler.getLabel()) + ""); + } else { + html.append("Not defined"); + } + html.append(""); + html.append(StringEscapeUtils.escapeHtml(nullReplacement(device.deviceFamily))); + html.append(""); + html.append(StringEscapeUtils.escapeHtml(nullReplacement(device.deviceType))); + html.append(""); + html.append("
"); + createPageEndAndSent(resp, html); + } + + private void handleDevices(HttpServletResponse resp, Connection connection) throws IOException, URISyntaxException { + returnHtml(resp, "" + StringEscapeUtils.escapeHtml(connection.getDeviceListJson()) + ""); + } + + private String nullReplacement(@Nullable String text) { + if (text == null) { + return ""; + } + return text; + } + + StringBuilder createPageStart(String title) { + StringBuilder html = new StringBuilder(); + html.append("" + + StringEscapeUtils + .escapeHtml(BINDING_NAME + " - " + this.account.getThing().getLabel() + " - " + title) + + ""); + html.append("

" + StringEscapeUtils + .escapeHtml(BINDING_NAME + " - " + this.account.getThing().getLabel() + " - " + title) + "

"); + return html; + } + + private void createPageEndAndSent(HttpServletResponse resp, StringBuilder html) { + html.append(""); + resp.addHeader("content-type", "text/html;charset=UTF-8"); + try { + resp.getWriter().write(html.toString()); + } catch (IOException e) { + logger.warn("return html failed with IO error {}", e); + } + } + + private void handleIds(HttpServletResponse resp, Connection connection, Device device, Thing thing) + throws IOException, URISyntaxException { + StringBuilder html = createPageStart("Channel Options - " + thing.getLabel()); + + renderBluetoothMacChannel(connection, device, html); + renderAmazonMusicPlaylistIdChannel(connection, device, html); + renderPlayAlarmSoundChannel(connection, device, html); + renderMusicProviderIdChannel(connection, html); + + createPageEndAndSent(resp, html); + } + + private void renderMusicProviderIdChannel(Connection connection, StringBuilder html) { + html.append("

" + StringEscapeUtils.escapeHtml("Channel " + CHANNEL_MUSIC_PROVIDER_ID) + "

"); + html.append(""); + List musicProviders = connection.getMusicProviders(); + for (JsonMusicProvider musicProvider : musicProviders) { + @Nullable + List<@Nullable String> properties = musicProvider.supportedProperties; + String providerId = musicProvider.id; + String displayName = musicProvider.displayName; + if (properties != null && properties.contains("Alexa.Music.PlaySearchPhrase") + && StringUtils.isNotEmpty(providerId) && StringUtils.equals(musicProvider.availability, "AVAILABLE") + && StringUtils.isNotEmpty(displayName)) { + html.append(""); + } + } + html.append("
NameValue
"); + html.append(StringEscapeUtils.escapeHtml(displayName)); + html.append(""); + html.append(StringEscapeUtils.escapeHtml(providerId)); + html.append("
"); + } + + private void renderPlayAlarmSoundChannel(Connection connection, Device device, StringBuilder html) { + html.append("

" + StringEscapeUtils.escapeHtml("Channel " + CHANNEL_PLAY_ALARM_SOUND) + "

"); + JsonNotificationSound[] notificationSounds = null; + String errorMessage = "No notifications sounds found"; + try { + notificationSounds = connection.getNotificationSounds(device); + } catch (IOException | HttpException | URISyntaxException | JsonSyntaxException | ConnectionException e) { + errorMessage = e.getLocalizedMessage(); + } + if (notificationSounds != null) { + html.append(""); + for (JsonNotificationSound notificationSound : notificationSounds) { + if (notificationSound.folder == null && notificationSound.providerId != null + && notificationSound.id != null && notificationSound.displayName != null) { + String providerSoundId = notificationSound.providerId + ":" + notificationSound.id; + + html.append(""); + } + } + html.append("
NameValue
"); + html.append(StringEscapeUtils.escapeHtml(notificationSound.displayName)); + html.append(""); + html.append(StringEscapeUtils.escapeHtml(providerSoundId)); + html.append("
"); + } else { + html.append(StringEscapeUtils.escapeHtml(errorMessage)); + } + } + + private void renderAmazonMusicPlaylistIdChannel(Connection connection, Device device, StringBuilder html) { + html.append("

" + StringEscapeUtils.escapeHtml("Channel " + CHANNEL_AMAZON_MUSIC_PLAY_LIST_ID) + "

"); + + JsonPlaylists playLists = null; + String errorMessage = "No playlists found"; + try { + playLists = connection.getPlaylists(device); + } catch (IOException | HttpException | URISyntaxException | JsonSyntaxException | ConnectionException e) { + errorMessage = e.getLocalizedMessage(); + } + + if (playLists != null) { + Map<@NonNull String, @Nullable PlayList @Nullable []> playlistMap = playLists.playlists; + if (playlistMap != null && !playlistMap.isEmpty()) { + html.append(""); + + for (PlayList[] innerLists : playlistMap.values()) { + { + if (innerLists != null && innerLists.length > 0) { + PlayList playList = innerLists[0]; + if (playList.playlistId != null && playList.title != null) { + html.append(""); + } + } + } + } + html.append("
NameValue
"); + html.append(StringEscapeUtils.escapeHtml(nullReplacement(playList.title))); + html.append(""); + html.append(StringEscapeUtils.escapeHtml(nullReplacement(playList.playlistId))); + html.append("
"); + } else { + html.append(StringEscapeUtils.escapeHtml(errorMessage)); + } + } + } + + private void renderBluetoothMacChannel(Connection connection, Device device, StringBuilder html) { + html.append("

" + StringEscapeUtils.escapeHtml("Channel " + CHANNEL_BLUETOOTH_MAC) + "

"); + JsonBluetoothStates bluetoothStates = connection.getBluetoothConnectionStates(); + BluetoothState[] innerStates = bluetoothStates.bluetoothStates; + if (innerStates != null) { + for (BluetoothState state : innerStates) { + if (StringUtils.equals(state.deviceSerialNumber, device.serialNumber)) { + PairedDevice[] pairedDeviceList = state.pairedDeviceList; + if (pairedDeviceList != null && pairedDeviceList.length > 0) { + html.append(""); + for (PairedDevice pairedDevice : pairedDeviceList) { + html.append(""); + } + html.append("
NameValue
"); + html.append(StringEscapeUtils.escapeHtml(nullReplacement(pairedDevice.friendlyName))); + html.append(""); + html.append(StringEscapeUtils.escapeHtml(nullReplacement(pairedDevice.address))); + html.append("
"); + } else { + html.append(StringEscapeUtils.escapeHtml("No bluetooth devices paired")); + } + } + } + } + } + + void HandleProxyRequest(HttpServletResponse resp, String verb, String url, @Nullable String referer, + @Nullable String postData) throws IOException { + HttpsURLConnection urlConnection; + try { + Map headers = null; + if (referer != null) { + headers = new HashMap(); + headers.put("Referer", referer); + } + + urlConnection = connection.makeRequest(verb, url, postData, false, false, headers); + if (urlConnection.getResponseCode() == 302) { + { + String location = urlConnection.getHeaderField("location"); + if (location.contains("//alexa.")) { + if (connection.verifyLogin()) { + handleDefaultPageResult(resp, "Login succeeded"); + account.setConnection(this.connection); + this.connection = reCreateConnection(); + return; + } + } + String startString = "https://www." + connection.getAmazonSite() + "/"; + String newLocation = null; + if (location.startsWith(startString)) { + newLocation = servletUrl + FORWARD_URI_PART + location.substring(startString.length()); + } else { + startString = "/"; + if (location.startsWith(startString)) { + newLocation = servletUrl + FORWARD_URI_PART + location.substring(startString.length()); + } + } + if (newLocation != null) { + logger.debug("Redirect mapped from {} to {}", location, newLocation); + resp.addHeader("location", newLocation); + resp.sendError(302); + return; + } + returnError(resp, "Invalid redirect to '" + location + "'"); + return; + } + } + } catch (URISyntaxException e) { + returnError(resp, e.getLocalizedMessage()); + return; + } + String response = connection.convertStream(urlConnection.getInputStream()); + returnHtml(resp, response); + } + + private void returnHtml(HttpServletResponse resp, String html) { + String resultHtml = html.replace("https://www." + connection.getAmazonSite() + "/", servletUrl + "/"); + resp.addHeader("content-type", "text/html;charset=UTF-8"); + try { + resp.getWriter().write(resultHtml); + } catch (IOException e) { + logger.warn("return html failed with IO error {}", e); + } + } + + void returnError(HttpServletResponse resp, String errorMessage) { + try { + resp.getWriter().write("" + StringEscapeUtils.escapeHtml(errorMessage) + "
Try again"); + } catch (IOException e) { + logger.info("Returning error message failed {}", e); + } + } +} diff --git a/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/AmazonEchoControlHandlerFactory.java b/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/AmazonEchoControlHandlerFactory.java new file mode 100755 index 0000000000000..824f912fe48b1 --- /dev/null +++ b/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/AmazonEchoControlHandlerFactory.java @@ -0,0 +1,165 @@ +/** + * Copyright (c) 2010-2018 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.amazonechocontrol.internal; + +import static org.openhab.binding.amazonechocontrol.AmazonEchoControlBindingConstants.*; + +import java.util.HashMap; +import java.util.Hashtable; +import java.util.Map; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.config.discovery.DiscoveryService; +import org.eclipse.smarthome.core.storage.Storage; +import org.eclipse.smarthome.core.storage.StorageService; +import org.eclipse.smarthome.core.thing.Bridge; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.ThingTypeUID; +import org.eclipse.smarthome.core.thing.ThingUID; +import org.eclipse.smarthome.core.thing.binding.BaseThingHandlerFactory; +import org.eclipse.smarthome.core.thing.binding.ThingHandler; +import org.eclipse.smarthome.core.thing.binding.ThingHandlerFactory; +import org.openhab.binding.amazonechocontrol.handler.AccountHandler; +import org.openhab.binding.amazonechocontrol.handler.EchoHandler; +import org.openhab.binding.amazonechocontrol.handler.FlashBriefingProfileHandler; +import org.openhab.binding.amazonechocontrol.internal.discovery.AmazonEchoDiscovery; +import org.osgi.framework.ServiceRegistration; +import org.osgi.service.component.ComponentContext; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; +import org.osgi.service.component.annotations.ReferenceCardinality; +import org.osgi.service.component.annotations.ReferencePolicy; +import org.osgi.service.http.HttpService; + +/** + * The {@link AmazonEchoControlHandlerFactory} is responsible for creating things and thing + * handlers. + * + * @author Michael Geramb - Initial contribution + */ +@Component(service = ThingHandlerFactory.class, immediate = true, configurationPid = "binding.amazonechocontrol") +@NonNullByDefault +public class AmazonEchoControlHandlerFactory extends BaseThingHandlerFactory { + + private final Map> discoveryServiceRegistrations = new HashMap<>(); + + @Nullable + HttpService httpService; + @Nullable + StorageService storageService; + @Nullable + BindingServlet bindingServlet; + + @Override + public boolean supportsThingType(ThingTypeUID thingTypeUID) { + return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID); + } + + @Override + protected void activate(ComponentContext componentContext) { + super.activate(componentContext); + HttpService httpService = this.httpService; + if (bindingServlet == null && httpService != null) { + bindingServlet = new BindingServlet(httpService); + } + } + + @Override + protected void deactivate(ComponentContext componentContext) { + BindingServlet bindingServlet = this.bindingServlet; + this.bindingServlet = null; + if (bindingServlet != null) { + bindingServlet.dispose(); + } + super.deactivate(componentContext); + } + + @Override + protected @Nullable ThingHandler createHandler(Thing thing) { + ThingTypeUID thingTypeUID = thing.getThingTypeUID(); + + HttpService httpService = this.httpService; + if (httpService == null) { + return null; + } + StorageService storageService = this.storageService; + if (storageService == null) { + return null; + } + + if (thingTypeUID.equals(THING_TYPE_ACCOUNT)) { + Storage storage = storageService.getStorage(thing.getUID().toString(), + String.class.getClassLoader()); + AccountHandler bridgeHandler = new AccountHandler((Bridge) thing, httpService, storage); + registerDiscoveryService(bridgeHandler); + BindingServlet bindingServlet = this.bindingServlet; + if (bindingServlet != null) { + bindingServlet.addAccountThing(thing); + } + return bridgeHandler; + } + if (thingTypeUID.equals(THING_TYPE_FLASH_BRIEFING_PROFILE)) { + Storage storage = storageService.getStorage(thing.getUID().toString(), + String.class.getClassLoader()); + return new FlashBriefingProfileHandler(thing, storage); + } + if (SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID)) { + return new EchoHandler(thing); + } + return null; + } + + private synchronized void registerDiscoveryService(AccountHandler bridgeHandler) { + AmazonEchoDiscovery discoveryService = new AmazonEchoDiscovery(bridgeHandler); + discoveryService.activate(); + this.discoveryServiceRegistrations.put(bridgeHandler.getThing().getUID(), bundleContext + .registerService(DiscoveryService.class.getName(), discoveryService, new Hashtable())); + } + + @Override + protected synchronized void removeHandler(ThingHandler thingHandler) { + if (thingHandler instanceof AccountHandler) { + BindingServlet bindingServlet = this.bindingServlet; + if (bindingServlet != null) { + bindingServlet.removeAccountThing(thingHandler.getThing()); + } + + ServiceRegistration serviceReg = this.discoveryServiceRegistrations + .get(thingHandler.getThing().getUID()); + if (serviceReg != null) { + // remove discovery service, if bridge handler is removed + AmazonEchoDiscovery service = (AmazonEchoDiscovery) bundleContext.getService(serviceReg.getReference()); + if (service != null) { + service.deactivate(); + } + serviceReg.unregister(); + discoveryServiceRegistrations.remove(thingHandler.getThing().getUID()); + } + } + } + + @Reference(cardinality = ReferenceCardinality.MANDATORY, policy = ReferencePolicy.DYNAMIC) + protected void setHttpService(HttpService httpService) { + this.httpService = httpService; + } + + protected void unsetHttpService(HttpService httpService) { + this.httpService = null; + } + + @Reference + protected void setStorageService(StorageService storageService) { + this.storageService = storageService; + } + + protected void unsetStorageService(StorageService storageService) { + this.storageService = null; + } +} diff --git a/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/BindingServlet.java b/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/BindingServlet.java new file mode 100644 index 0000000000000..ad5db34ed80c6 --- /dev/null +++ b/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/BindingServlet.java @@ -0,0 +1,126 @@ +/** + * Copyright (c) 2010-2018 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.amazonechocontrol.internal; + +import static org.openhab.binding.amazonechocontrol.AmazonEchoControlBindingConstants.BINDING_NAME; + +import java.io.IOException; +import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.List; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang.StringEscapeUtils; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.thing.Thing; +import org.osgi.service.http.HttpService; +import org.osgi.service.http.NamespaceException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * This servlet provides the base navigation page, with hyperlinks for the defined account things + * + * @author Michael Geramb - Initial Contribution + */ +@NonNullByDefault +public class BindingServlet extends HttpServlet { + + private static final long serialVersionUID = -1453738923337413163L; + + private final Logger logger = LoggerFactory.getLogger(AccountServlet.class); + + String servletUrlWithoutRoot; + String servletUrl; + HttpService httpService; + + List accountHandlers = new ArrayList(); + + public BindingServlet(HttpService httpService) { + this.httpService = httpService; + servletUrlWithoutRoot = "amazonechocontrol"; + servletUrl = "/" + servletUrlWithoutRoot; + try { + httpService.registerServlet(servletUrl, this, null, httpService.createDefaultHttpContext()); + } catch (ServletException e) { + logger.warn("Register servlet fails {}", e); + } catch (NamespaceException e) { + logger.warn("Register servlet fails {}", e); + } + } + + public void addAccountThing(Thing accountThing) { + synchronized (accountHandlers) { + accountHandlers.add(accountThing); + } + } + + public void removeAccountThing(Thing accountThing) { + synchronized (accountHandlers) { + accountHandlers.remove(accountThing); + } + } + + public void dispose() { + httpService.unregister(servletUrl); + } + + @Override + protected void doGet(@Nullable HttpServletRequest req, @Nullable HttpServletResponse resp) + throws ServletException, IOException { + if (req == null) { + return; + } + if (resp == null) { + return; + } + String uri = req.getRequestURI().substring(servletUrl.length()); + String queryString = req.getQueryString(); + if (queryString != null && queryString.length() > 0) { + uri += "?" + queryString; + } + logger.debug("doGet {}", uri); + + if (!uri.equals("/")) { + String newUri = req.getServletPath() + "/"; + resp.sendRedirect(newUri); + return; + } + + StringBuilder html = new StringBuilder(); + html.append("" + StringEscapeUtils.escapeHtml(BINDING_NAME) + ""); + html.append("

" + StringEscapeUtils.escapeHtml(BINDING_NAME) + "

"); + + synchronized (accountHandlers) { + if (accountHandlers.isEmpty()) { + html.append("No Account thing created."); + } else { + for (Thing accountHandler : accountHandlers) { + String url = URLEncoder.encode(accountHandler.getUID().getId(), "UTF8"); + html.append("" + StringEscapeUtils.escapeHtml(accountHandler.getLabel()) + + "
"); + } + } + } + html.append(""); + + resp.addHeader("content-type", "text/html;charset=UTF-8"); + try { + resp.getWriter().write(html.toString()); + } catch (IOException e) { + logger.warn("return html failed with uri syntax error {}", e); + } + } + +} diff --git a/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/Connection.java b/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/Connection.java new file mode 100755 index 0000000000000..c419c407efc62 --- /dev/null +++ b/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/Connection.java @@ -0,0 +1,935 @@ +/** + * Copyright (c) 2010-2018 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ + +package org.openhab.binding.amazonechocontrol.internal; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.CookieManager; +import java.net.CookieStore; +import java.net.HttpCookie; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.net.URLConnection; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.List; +import java.util.Map; +import java.util.Scanner; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.net.ssl.HttpsURLConnection; + +import org.apache.commons.lang.StringUtils; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.openhab.binding.amazonechocontrol.internal.jsons.JsonAutomation; +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.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.JsonFeed; +import org.openhab.binding.amazonechocontrol.internal.jsons.JsonMediaState; +import org.openhab.binding.amazonechocontrol.internal.jsons.JsonMusicProvider; +import org.openhab.binding.amazonechocontrol.internal.jsons.JsonNotificationRequest; +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.JsonPlaySearchPhraseOperationPayload; +import org.openhab.binding.amazonechocontrol.internal.jsons.JsonPlayValidationResult; +import org.openhab.binding.amazonechocontrol.internal.jsons.JsonPlayerState; +import org.openhab.binding.amazonechocontrol.internal.jsons.JsonPlaylists; +import org.openhab.binding.amazonechocontrol.internal.jsons.JsonStartRoutineRequest; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonObject; +import com.google.gson.JsonSyntaxException; + +/** + * The {@link Connection} is responsible for the connection to the amazon server and + * handling of the commands + * + * @author Michael Geramb - Initial contribution + */ +@NonNullByDefault +public class Connection { + private final Logger logger = LoggerFactory.getLogger(Connection.class); + + private final CookieManager cookieManager = new CookieManager(); + private final String email; + private final String password; + private final String amazonSite; + private final String alexaServer; + private final String accountThingId; + + private @Nullable String sessionId; + private @Nullable Date loginTime; + private @Nullable Date verifyTime; + + private final Gson gson = new Gson(); + private final Gson gsonWithNullSerialization; + + public Connection(@Nullable String email, @Nullable String password, @Nullable String amazonSite, + @Nullable String accountThingId) { + this.accountThingId = accountThingId != null ? accountThingId : ""; + this.email = email != null ? email : ""; + this.password = password != null ? password : ""; + + String correctedAmazonSite = amazonSite != null ? amazonSite : ""; + if (correctedAmazonSite.toLowerCase().startsWith("http://")) { + correctedAmazonSite = correctedAmazonSite.substring(7); + } + if (correctedAmazonSite.toLowerCase().startsWith("https://")) { + correctedAmazonSite = correctedAmazonSite.substring(8); + } + if (correctedAmazonSite.toLowerCase().startsWith("www.")) { + correctedAmazonSite = correctedAmazonSite.substring(4); + } + if (correctedAmazonSite.toLowerCase().startsWith("alexa.")) { + correctedAmazonSite = correctedAmazonSite.substring(6); + } + this.amazonSite = correctedAmazonSite; + alexaServer = "https://alexa." + this.amazonSite; + + GsonBuilder gsonBuilder = new GsonBuilder(); + gsonWithNullSerialization = gsonBuilder.create(); + } + + public @Nullable Date tryGetLoginTime() { + return loginTime; + } + + public @Nullable Date tryGetVerifyTime() { + return verifyTime; + } + + public String getEmail() { + return email; + } + + public String getPassword() { + return password; + } + + public String getAmazonSite() { + return amazonSite; + } + + public String serializeLoginData() { + Date loginTime = this.loginTime; + if (sessionId == null || loginTime == null) { + return ""; + } + StringBuilder builder = new StringBuilder(); + builder.append("4\n"); // version + builder.append(email); + builder.append("\n"); + builder.append(password.hashCode()); + builder.append("\n"); + builder.append(sessionId); + builder.append("\n"); + builder.append(loginTime.getTime()); + builder.append("\n"); + List cookies = cookieManager.getCookieStore().getCookies(); + builder.append(cookies.size()); + builder.append("\n"); + for (HttpCookie cookie : cookies) { + writeValue(builder, cookie.getName()); + writeValue(builder, cookie.getValue()); + writeValue(builder, cookie.getComment()); + writeValue(builder, cookie.getCommentURL()); + writeValue(builder, cookie.getDomain()); + writeValue(builder, cookie.getMaxAge()); + writeValue(builder, cookie.getPath()); + writeValue(builder, cookie.getPortlist()); + writeValue(builder, cookie.getVersion()); + writeValue(builder, cookie.getSecure()); + writeValue(builder, cookie.getDiscard()); + } + return builder.toString(); + } + + private void writeValue(StringBuilder builder, @Nullable Object value) { + if (value == null) { + builder.append('0'); + } else { + builder.append('1'); + builder.append("\n"); + builder.append(value.toString()); + } + builder.append("\n"); + } + + private String readValue(Scanner scanner) { + if (scanner.nextLine().equals("1")) { + String result = scanner.nextLine(); + if (result != null) { + return result; + } + } + return ""; + } + + public boolean tryRestoreLogin(@Nullable String data) { + // verify store data + if (StringUtils.isEmpty(data)) { + return false; + } + Scanner scanner = new Scanner(data); + String version = scanner.nextLine(); + if (!version.equals("4")) { + scanner.close(); + return false; + } + + // check if email or password was changed in the mean time + String email = scanner.nextLine(); + if (!email.equals(this.email)) { + scanner.close(); + return false; + } + int passwordHash = Integer.parseInt(scanner.nextLine()); + if (passwordHash != this.password.hashCode()) { + scanner.close(); + return false; + } + + // Recreate session and cookies + sessionId = scanner.nextLine(); + Date loginTime = new Date(Long.parseLong(scanner.nextLine())); + CookieStore cookieStore = cookieManager.getCookieStore(); + cookieStore.removeAll(); + + Integer numberOfCookies = Integer.parseInt(scanner.nextLine()); + for (Integer i = 0; i < numberOfCookies; i++) { + String name = readValue(scanner); + String value = readValue(scanner); + + HttpCookie clientCookie = new HttpCookie(name, value); + clientCookie.setComment(readValue(scanner)); + clientCookie.setCommentURL(readValue(scanner)); + clientCookie.setDomain(readValue(scanner)); + clientCookie.setMaxAge(Long.parseLong(readValue(scanner))); + clientCookie.setPath(readValue(scanner)); + clientCookie.setPortlist(readValue(scanner)); + clientCookie.setVersion(Integer.parseInt(readValue(scanner))); + clientCookie.setSecure(Boolean.parseBoolean(readValue(scanner))); + clientCookie.setDiscard(Boolean.parseBoolean(readValue(scanner))); + + cookieStore.add(null, clientCookie); + } + + scanner.close(); + try { + if (verifyLogin()) { + this.loginTime = loginTime; + return true; + } + } catch (IOException e) { + logger.info("verify login fails with io exception: {}", e); + } catch (URISyntaxException e) { + logger.warn("verify login fails with uri syntax exception: {}", e); + } + // anything goes wrong, remove session data + cookieStore.removeAll(); + this.sessionId = null; + this.loginTime = null; + this.verifyTime = null; + return false; + } + + public String convertStream(@Nullable InputStream input) throws IOException { + if (input == null) { + return ""; + } + Scanner inputScanner = new Scanner(input); + Scanner scannerWithoutDelimiter = inputScanner.useDelimiter("\\A"); + String result = scannerWithoutDelimiter.hasNext() ? scannerWithoutDelimiter.next() : null; + inputScanner.close(); + scannerWithoutDelimiter.close(); + input.close(); + if (result == null) { + result = ""; + } + return result; + } + + public String makeRequestAndReturnString(String url) throws IOException, URISyntaxException { + return makeRequestAndReturnString("GET", url, null, false, null); + } + + private String makeRequestAndReturnString(String verb, String url, @Nullable String postData, boolean json, + @Nullable Map customHeaders) throws IOException, URISyntaxException { + HttpsURLConnection connection = makeRequest(verb, url, postData, json, true, customHeaders); + return convertStream(connection.getInputStream()); + } + + public HttpsURLConnection makeRequest(String verb, String url, @Nullable String postData, boolean json, + boolean autoredirect, @Nullable Map customHeaders) throws IOException, URISyntaxException { + String currentUrl = url; + for (int i = 0; i < 30; i++) // loop for handling redirect, using automatic redirect is not possible, because + // all response headers must be catched + { + int code; + HttpsURLConnection connection; + try { + logger.debug("Make request to {}", url); + connection = (HttpsURLConnection) new URL(currentUrl).openConnection(); + connection.setRequestMethod(verb); + connection.setRequestProperty("Accept-Language", "en-US"); + connection.setRequestProperty("User-Agent", "Mozilla/5.0 openHAB/1.0.0.0"); + connection.setRequestProperty("DNT", "1"); + connection.setRequestProperty("Upgrade-Insecure-Requests", "1"); + if (customHeaders != null) { + for (String key : customHeaders.keySet()) { + String value = customHeaders.get(key); + connection.setRequestProperty(key, value); + } + } + connection.setInstanceFollowRedirects(false); + + // add cookies + URI uri = connection.getURL().toURI(); + + StringBuilder cookieHeaderBuilder = new StringBuilder(); + for (HttpCookie cookie : cookieManager.getCookieStore().get(uri)) { + if (cookieHeaderBuilder.length() > 0) { + cookieHeaderBuilder.insert(0, "; "); + } + cookieHeaderBuilder.insert(0, cookie); + if (cookie.getName().equals("csrf")) { + connection.setRequestProperty("csrf", cookie.getValue()); + } + + } + if (cookieHeaderBuilder.length() > 0) { + connection.setRequestProperty("Cookie", cookieHeaderBuilder.toString()); + } + if (postData != null) { + + // post data + byte[] postDataBytes = postData.getBytes(StandardCharsets.UTF_8); + int postDataLength = postDataBytes.length; + + connection.setFixedLengthStreamingMode(postDataLength); + + if (json) { + connection.setRequestProperty("Content-Type", "application/json; charset=UTF-8"); + } else { + connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); + } + connection.setRequestProperty("Content-Length", Integer.toString(postDataLength)); + if (verb == "POST") { + connection.setRequestProperty("Expect", "100-continue"); + } + + connection.setDoOutput(true); + OutputStream outputStream = connection.getOutputStream(); + outputStream.write(postDataBytes); + outputStream.close(); + } + // handle result + code = connection.getResponseCode(); + String location = null; + + // handle response headers + Map> headerFields = connection.getHeaderFields(); + for (Map.Entry> header : headerFields.entrySet()) { + String key = header.getKey(); + if (StringUtils.isNotEmpty(key)) { + if (key.equalsIgnoreCase("Set-Cookie")) { + // store cookie + for (String cookieHeader : header.getValue()) { + List cookies = HttpCookie.parse(cookieHeader); + for (HttpCookie cookie : cookies) { + cookieManager.getCookieStore().add(uri, cookie); + } + } + } + if (key.equalsIgnoreCase("Location")) { + // get redirect location + location = header.getValue().get(0); + if (StringUtils.isNotEmpty(location)) { + location = uri.resolve(location).toString(); + // check for https + if (location.toLowerCase().startsWith("http://")) { + // always use https + location = "https://" + location.substring(7); + logger.debug("Redirect corrected to {}", location); + } + } + } + } + } + if (code == 200) { + logger.debug("Call to {} succeeded", url); + return connection; + } + if (code == 302 && location != null) { + logger.debug("Redirected to {}", location); + currentUrl = location; + if (autoredirect) { + continue; + } + return connection; + } + } catch (IOException e) { + logger.warn("Request to url '{}' fails with unkown error", url, e); + throw e; + } + if (code != 200) { + throw new HttpException(code, verb + " url '" + url + "' failed: " + connection.getResponseMessage()); + } + } + throw new ConnectionException("Too many redirects"); + } + + public boolean getIsLoggedIn() { + return loginTime != null; + } + + public String getLoginPage() throws IOException, URISyntaxException { + // clear session data + cookieManager.getCookieStore().removeAll(); + sessionId = null; + loginTime = null; + verifyTime = null; + + logger.debug("Start Login to {}", alexaServer); + // get login form + String loginFormHtml = makeRequestAndReturnString(alexaServer); + + logger.debug("Received login form {}", loginFormHtml); + + // get session id from cookies + for (HttpCookie cookie : cookieManager.getCookieStore().getCookies()) { + if (cookie.getName().equalsIgnoreCase("session-id")) { + sessionId = cookie.getValue(); + break; + } + } + if (sessionId == null) { + throw new ConnectionException("No session id received"); + } + cookieManager.getCookieStore().add(new URL("https://www." + amazonSite).toURI(), + HttpCookie.parse("session-id=" + sessionId).get(0)); + return loginFormHtml; + } + + public void makeLogin() throws IOException, URISyntaxException { + try { + String loginFormHtml = getLoginPage(); + // read hidden form inputs, the will be used later in the url and for posting + Pattern inputPattern = Pattern + .compile("[^\"]+)\"\\s+value=\"(?[^\"]*)\""); + Matcher matcher = inputPattern.matcher(loginFormHtml); + + StringBuilder postDataBuilder = new StringBuilder(); + while (matcher.find()) { + + postDataBuilder.append(URLEncoder.encode(matcher.group("name"), "UTF-8")); + postDataBuilder.append('='); + postDataBuilder.append(URLEncoder.encode(matcher.group("value"), "UTF-8")); + postDataBuilder.append('&'); + } + + String queryParameters = postDataBuilder.toString() + "session-id=" + URLEncoder.encode(sessionId, "UTF-8"); + logger.debug("Login query String: {}", queryParameters); + + postDataBuilder.append("email"); + postDataBuilder.append('='); + postDataBuilder.append(URLEncoder.encode(email, "UTF-8")); + postDataBuilder.append('&'); + postDataBuilder.append("password"); + postDataBuilder.append('='); + postDataBuilder.append(URLEncoder.encode(password, "UTF-8")); + + String postData = postDataBuilder.toString(); + + String response = postLoginData(queryParameters, postData); + if (response != null) { + Document htmlDocument = Jsoup.parse(response); + Element authWarningBoxElement = htmlDocument.getElementById("auth-warning-message-box"); + String error = null; + if (authWarningBoxElement != null) { + error = authWarningBoxElement.text(); + } + if (StringUtils.isNotEmpty(error)) { + throw new ConnectionException( + "Login fails. Check your credentials and try to login with your webbrowser to http(s):///amazonechocontrol/" + + accountThingId + System.lineSeparator() + "" + error); + } else { + throw new ConnectionException( + "Login fails. Check your credentials and try to login with your webbrowser to http(s):///amazonechocontrol/" + + accountThingId); + } + } + + } catch (Exception e) { + // clear session data + cookieManager.getCookieStore().removeAll(); + sessionId = null; + loginTime = null; + verifyTime = null; + logger.info("Login failed: {}", e.getLocalizedMessage()); + // rethrow + throw e; + } + } + + public @Nullable String postLoginData(@Nullable String optionalQueryParameters, @Nullable String postData) + throws IOException, URISyntaxException { + // build query parameters + @Nullable + String queryParameters = optionalQueryParameters; + if (queryParameters == null) { + queryParameters = "session-id=" + URLEncoder.encode(sessionId, "UTF-8"); + } + + // build referer link + String referer = "https://www." + amazonSite + "/ap/signin?" + queryParameters; + Map headers = new HashMap(); + headers.put("Referer", referer); + + // make the request + URLConnection request = makeRequest("POST", "https://www." + amazonSite + "/ap/signin", postData, false, true, + headers); + + String response = convertStream(request.getInputStream()); + logger.debug("Received content after login {}", response); + + String host = request.getURL().getHost(); + if (!host.equalsIgnoreCase(new URI(alexaServer).getHost())) { + return response; + } + if (response.contains("Amazon Alexa")) { + logger.debug("Response seems to be alexa app"); + } else { + + logger.info("Response maybe not valid"); + } + + // verify login + if (!verifyLogin()) { + return response; + } + logger.debug("Login succeeded"); + return null; + } + + public boolean verifyLogin() throws IOException, URISyntaxException { + String response = makeRequestAndReturnString(alexaServer + "/api/bootstrap?version=0"); + Boolean result = response.contains("\"authenticated\":true"); + if (result) { + verifyTime = new Date(); + if (loginTime == null) { + loginTime = verifyTime; + } + } + return result; + } + + public void logout() { + cookieManager.getCookieStore().removeAll(); + sessionId = null; + loginTime = null; + verifyTime = null; + } + + // parser + private T parseJson(String json, Class type) throws JsonSyntaxException { + try { + return gson.fromJson(json, type); + } catch (JsonSyntaxException e) { + logger.warn("Parsing json failed {}", e); + logger.warn("Illegal json: {}", json); + throw e; + } + } + + // commands and states + + public List getDeviceList() throws IOException, URISyntaxException { + String json = getDeviceListJson(); + JsonDevices devices = parseJson(json, JsonDevices.class); + Device[] result = devices.devices; + if (result == null) { + return new ArrayList<>(); + } + return new ArrayList<>(Arrays.asList(result)); + } + + public String getDeviceListJson() throws IOException, URISyntaxException { + String json = makeRequestAndReturnString(alexaServer + "/api/devices-v2/device?cached=false"); + return json; + } + + public JsonPlayerState getPlayer(Device device) throws IOException, URISyntaxException { + String json = makeRequestAndReturnString(alexaServer + "/api/np/player?deviceSerialNumber=" + + device.serialNumber + "&deviceType=" + device.deviceType + "&screenWidth=1440"); + JsonPlayerState playerState = parseJson(json, JsonPlayerState.class); + return playerState; + } + + public JsonMediaState getMediaState(Device device) throws IOException, URISyntaxException { + String json = makeRequestAndReturnString(alexaServer + "/api/media/state?deviceSerialNumber=" + + device.serialNumber + "&deviceType=" + device.deviceType); + JsonMediaState mediaState = parseJson(json, JsonMediaState.class); + return mediaState; + } + + public JsonBluetoothStates getBluetoothConnectionStates() { + String json; + try { + json = makeRequestAndReturnString(alexaServer + "/api/bluetooth?cached=true"); + } catch (IOException | URISyntaxException e) { + logger.debug("failed to get bluetooth state: {}", e.getMessage()); + return new JsonBluetoothStates(); + } + JsonBluetoothStates bluetoothStates = parseJson(json, JsonBluetoothStates.class); + return bluetoothStates; + } + + public JsonPlaylists getPlaylists(Device device) throws IOException, URISyntaxException { + String json = makeRequestAndReturnString( + alexaServer + "/api/cloudplayer/playlists?deviceSerialNumber=" + device.serialNumber + "&deviceType=" + + device.deviceType + "&mediaOwnerCustomerId=" + device.deviceOwnerCustomerId); + JsonPlaylists playlists = parseJson(json, JsonPlaylists.class); + return playlists; + } + + public void command(Device device, String command) throws IOException, URISyntaxException { + String url = alexaServer + "/api/np/command?deviceSerialNumber=" + device.serialNumber + "&deviceType=" + + device.deviceType; + makeRequest("POST", url, command, true, true, null); + } + + public void bluetooth(Device device, @Nullable String address) throws IOException, URISyntaxException { + if (StringUtils.isEmpty(address)) { + // disconnect + makeRequest("POST", + alexaServer + "/api/bluetooth/disconnect-sink/" + device.deviceType + "/" + device.serialNumber, "", + true, true, null); + } else { + makeRequest("POST", + alexaServer + "/api/bluetooth/pair-sink/" + device.deviceType + "/" + device.serialNumber, + "{\"bluetoothDeviceAddress\":\"" + address + "\"}", true, true, null); + } + } + + public void playRadio(Device device, @Nullable String stationId) throws IOException, URISyntaxException { + if (StringUtils.isEmpty(stationId)) { + command(device, "{\"type\":\"PauseCommand\"}"); + } else { + makeRequest("POST", + alexaServer + "/api/tunein/queue-and-play?deviceSerialNumber=" + device.serialNumber + + "&deviceType=" + device.deviceType + "&guideId=" + stationId + + "&contentType=station&callSign=&mediaOwnerCustomerId=" + device.deviceOwnerCustomerId, + "", true, true, null); + } + } + + public void playAmazonMusicTrack(Device device, @Nullable String trackId) throws IOException, URISyntaxException { + if (StringUtils.isEmpty(trackId)) { + command(device, "{\"type\":\"PauseCommand\"}"); + } else { + String command = "{\"trackId\":\"" + trackId + "\",\"playQueuePrime\":true}"; + makeRequest("POST", + alexaServer + "/api/cloudplayer/queue-and-play?deviceSerialNumber=" + device.serialNumber + + "&deviceType=" + device.deviceType + "&mediaOwnerCustomerId=" + + device.deviceOwnerCustomerId + "&shuffle=false", + command, true, true, null); + } + } + + public void playAmazonMusicPlayList(Device device, @Nullable String playListId) + throws IOException, URISyntaxException { + if (StringUtils.isEmpty(playListId)) { + command(device, "{\"type\":\"PauseCommand\"}"); + } else { + String command = "{\"playlistId\":\"" + playListId + "\",\"playQueuePrime\":true}"; + makeRequest("POST", + alexaServer + "/api/cloudplayer/queue-and-play?deviceSerialNumber=" + device.serialNumber + + "&deviceType=" + device.deviceType + "&mediaOwnerCustomerId=" + + device.deviceOwnerCustomerId + "&shuffle=false", + command, true, true, null); + } + } + + public void textToSpeech(Device device, String text) throws IOException, URISyntaxException { + Map parameters = new Hashtable(); + parameters.put("textToSpeak", text); + executeSequenceCommand(device, "Alexa.Speak", parameters); + } + + // commands: Alexa.Weather.Play, Alexa.Traffic.Play, Alexa.FlashBriefing.Play, Alexa.GoodMorning.Play, + // Alexa.SingASong.Play, Alexa.TellStory.Play, Alexa.Speak (textToSpeach) + public void executeSequenceCommand(Device device, String command, @Nullable Map parameters) + throws IOException, URISyntaxException { + JsonObject operationPayload = new JsonObject(); + operationPayload.addProperty("deviceType", device.deviceType); + operationPayload.addProperty("deviceSerialNumber", device.serialNumber); + operationPayload.addProperty("locale", ""); + operationPayload.addProperty("customerId", device.deviceOwnerCustomerId); + if (parameters != null) { + for (String key : parameters.keySet()) { + Object value = parameters.get(key); + if (value instanceof String) { + operationPayload.addProperty(key, (String) value); + } else if (value instanceof Number) { + operationPayload.addProperty(key, (Number) value); + } else if (value instanceof Boolean) { + operationPayload.addProperty(key, (Boolean) value); + } else if (value instanceof Character) { + operationPayload.addProperty(key, (Character) value); + } else { + operationPayload.add(key, gson.toJsonTree(value)); + } + } + } + + JsonObject startNode = new JsonObject(); + startNode.addProperty("@type", "com.amazon.alexa.behaviors.model.OpaquePayloadOperationNode"); + startNode.addProperty("type", command); + startNode.add("operationPayload", operationPayload); + + JsonObject sequenceJson = new JsonObject(); + sequenceJson.addProperty("@type", "com.amazon.alexa.behaviors.model.Sequence"); + sequenceJson.add("startNode", startNode); + + JsonStartRoutineRequest request = new JsonStartRoutineRequest(); + request.sequenceJson = gson.toJson(sequenceJson); + String json = gson.toJson(request); + + makeRequest("POST", alexaServer + "/api/behaviors/preview", json, true, true, null); + } + + public void startRoutine(Device device, String utterance) throws IOException, URISyntaxException { + JsonAutomation found = null; + String deviceLocale = ""; + for (JsonAutomation routine : getRoutines()) { + Trigger[] triggers = routine.triggers; + if (triggers != null && routine.sequence != null) { + for (JsonAutomation.Trigger trigger : triggers) { + if (trigger == null) { + continue; + } + Payload payload = trigger.payload; + if (payload == null) { + continue; + } + if (StringUtils.equalsIgnoreCase(payload.utterance, utterance)) { + found = routine; + deviceLocale = payload.locale; + break; + } + } + } + } + if (found != null) { + String sequenceJson = gson.toJson(found.sequence); + + JsonStartRoutineRequest request = new JsonStartRoutineRequest(); + request.behaviorId = found.automationId; + + // replace tokens + + // "deviceType":"ALEXA_CURRENT_DEVICE_TYPE" + String deviceType = "\"deviceType\":\"ALEXA_CURRENT_DEVICE_TYPE\""; + String newDeviceType = "\"deviceType\":\"" + device.deviceType + "\""; + sequenceJson = sequenceJson.replace(deviceType.subSequence(0, deviceType.length()), + newDeviceType.subSequence(0, newDeviceType.length())); + + // "deviceSerialNumber":"ALEXA_CURRENT_DSN" + String deviceSerial = "\"deviceSerialNumber\":\"ALEXA_CURRENT_DSN\""; + String newDeviceSerial = "\"deviceSerialNumber\":\"" + device.serialNumber + "\""; + sequenceJson = sequenceJson.replace(deviceSerial.subSequence(0, deviceSerial.length()), + newDeviceSerial.subSequence(0, newDeviceSerial.length())); + + // "customerId": "ALEXA_CUSTOMER_ID" + String customerId = "\"customerId\":\"ALEXA_CUSTOMER_ID\""; + String newCustomerId = "\"customerId\":\"" + device.deviceOwnerCustomerId + "\""; + sequenceJson = sequenceJson.replace(customerId.subSequence(0, customerId.length()), + newCustomerId.subSequence(0, newCustomerId.length())); + + // "locale": "ALEXA_CURRENT_LOCALE" + String locale = "\"locale\":\"ALEXA_CURRENT_LOCALE\""; + String newlocale = StringUtils.isNotEmpty(deviceLocale) ? "\"locale\":\"" + deviceLocale + "\"" + : "\"locale\":null"; + sequenceJson = sequenceJson.replace(locale.subSequence(0, locale.length()), + newlocale.subSequence(0, newlocale.length())); + + request.sequenceJson = sequenceJson; + + String requestJson = gson.toJson(request); + makeRequest("POST", alexaServer + "/api/behaviors/preview", requestJson, true, true, null); + } else { + logger.warn("Routine {} not found", utterance); + } + } + + public JsonAutomation[] getRoutines() throws IOException, URISyntaxException { + String json = makeRequestAndReturnString(alexaServer + "/api/behaviors/automations"); + JsonAutomation[] result = parseJson(json, JsonAutomation[].class); + return result; + } + + public JsonFeed[] getEnabledFlashBriefings() throws IOException, URISyntaxException { + String json = makeRequestAndReturnString(alexaServer + "/api/content-skills/enabled-feeds"); + JsonEnabledFeeds result = parseJson(json, JsonEnabledFeeds.class); + JsonFeed[] enabledFeeds = result.enabledFeeds; + if (enabledFeeds != null) { + return enabledFeeds; + } + return new JsonFeed[0]; + } + + public void setEnabledFlashBriefings(JsonFeed[] enabledFlashBriefing) throws IOException, URISyntaxException { + JsonEnabledFeeds enabled = new JsonEnabledFeeds(); + enabled.enabledFeeds = enabledFlashBriefing; + String json = gsonWithNullSerialization.toJson(enabled); + makeRequest("POST", alexaServer + "/api/content-skills/enabled-feeds", json, true, true, null); + } + + public JsonNotificationSound[] getNotificationSounds(Device device) throws IOException, URISyntaxException { + String json = makeRequestAndReturnString( + alexaServer + "/api/notification/sounds?deviceSerialNumber=" + device.serialNumber + "&deviceType=" + + device.deviceType + "&softwareVersion=" + device.softwareVersion); + JsonNotificationSounds result = parseJson(json, JsonNotificationSounds.class); + JsonNotificationSound[] notificationSounds = result.notificationSounds; + if (notificationSounds != null) { + return notificationSounds; + } + return new JsonNotificationSound[0]; + } + + public JsonNotificationResponse notification(Device device, String type, @Nullable String label, + @Nullable JsonNotificationSound sound) throws IOException, URISyntaxException { + Date date = new Date(new Date().getTime()); + long createdDate = date.getTime(); + Date alarm = new Date(createdDate + 5000); // add 5 seconds, because amazon does not except calls for times in + // the past (compared with the server time) + long alarmTime = alarm.getTime(); + + JsonNotificationRequest request = new JsonNotificationRequest(); + request.type = type; + request.deviceSerialNumber = device.serialNumber; + request.deviceType = device.deviceType; + request.createdDate = createdDate; + request.alarmTime = alarmTime; + request.reminderLabel = label; + request.sound = sound; + request.originalDate = new SimpleDateFormat("yyyy-MM-dd").format(alarm); + request.originalTime = new SimpleDateFormat("HH:mm:ss.SSSS").format(alarm); + request.type = type; + request.id = "create" + type; + + String data = gsonWithNullSerialization.toJson(request); + String response = makeRequestAndReturnString("PUT", alexaServer + "/api/notifications/createReminder", data, + true, null); + JsonNotificationResponse result = parseJson(response, JsonNotificationResponse.class); + return result; + } + + public void stopNotification(JsonNotificationResponse notification) throws IOException, URISyntaxException { + makeRequestAndReturnString("DELETE", alexaServer + "/api/notifications/" + notification.id, null, true, null); + } + + public JsonNotificationResponse getNotificationState(JsonNotificationResponse notification) + throws IOException, URISyntaxException { + String response = makeRequestAndReturnString("GET", alexaServer + "/api/notifications/" + notification.id, null, + true, null); + JsonNotificationResponse result = parseJson(response, JsonNotificationResponse.class); + return result; + } + + public List getMusicProviders() { + String response; + try { + Map headers = new HashMap(); + headers.put("Routines-Version", "1.1.201102"); + response = makeRequestAndReturnString("GET", + alexaServer + "/api/behaviors/entities?skillId=amzn1.ask.1p.music", null, true, headers); + } catch (IOException | URISyntaxException e) { + logger.warn("getMusicProviders fails: {}", e.getMessage()); + return new ArrayList<>(); + } + if (StringUtils.isEmpty(response)) { + return new ArrayList<>(); + } + JsonMusicProvider[] result = parseJson(response, JsonMusicProvider[].class); + return Arrays.asList(result); + } + + public void playMusicVoiceCommand(Device device, String providerId, String voiceCommand) + throws IOException, URISyntaxException { + JsonPlaySearchPhraseOperationPayload payload = new JsonPlaySearchPhraseOperationPayload(); + payload.customerId = device.deviceOwnerCustomerId; + payload.locale = "ALEXA_CURRENT_LOCALE"; + payload.musicProviderId = providerId; + payload.searchPhrase = voiceCommand; + + String playloadString = gson.toJson(payload); + + JsonObject postValidataionJson = new JsonObject(); + + postValidataionJson.addProperty("type", "Alexa.Music.PlaySearchPhrase"); + postValidataionJson.addProperty("operationPayload", playloadString); + + String postDataValidate = postValidataionJson.toString(); + + String validateResultJson = makeRequestAndReturnString("POST", + alexaServer + "/api/behaviors/operation/validate", postDataValidate, true, null); + + if (StringUtils.isNotEmpty(validateResultJson)) { + JsonPlayValidationResult validationResult = parseJson(validateResultJson, JsonPlayValidationResult.class); + JsonPlaySearchPhraseOperationPayload validatedOperationPayload = validationResult.operationPayload; + if (validatedOperationPayload != null) { + payload.sanitizedSearchPhrase = validatedOperationPayload.sanitizedSearchPhrase; + payload.searchPhrase = validatedOperationPayload.searchPhrase; + } + } + + payload.locale = null; + payload.deviceSerialNumber = device.serialNumber; + payload.deviceType = device.deviceType; + + JsonObject sequenceJson = new JsonObject(); + sequenceJson.addProperty("@type", "com.amazon.alexa.behaviors.model.Sequence"); + JsonObject startNodeJson = new JsonObject(); + startNodeJson.addProperty("@type", "com.amazon.alexa.behaviors.model.OpaquePayloadOperationNode"); + startNodeJson.addProperty("type", "Alexa.Music.PlaySearchPhrase"); + startNodeJson.add("operationPayload", gson.toJsonTree(payload)); + sequenceJson.add("startNode", startNodeJson); + + JsonStartRoutineRequest startRoutineRequest = new JsonStartRoutineRequest(); + startRoutineRequest.sequenceJson = sequenceJson.toString(); + startRoutineRequest.status = null; + + String postData = gson.toJson(startRoutineRequest); + makeRequest("POST", alexaServer + "/api/behaviors/preview", postData, true, true, null); + } +} diff --git a/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/ConnectionException.java b/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/ConnectionException.java new file mode 100644 index 0000000000000..3d7240c050f7a --- /dev/null +++ b/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/ConnectionException.java @@ -0,0 +1,26 @@ +/** + * Copyright (c) 2010-2018 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.amazonechocontrol.internal; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * The {@link ConnectionException} is used for errors in the connection to the amazon server + * + * @author Michael Geramb - Initial contribution + */ +@NonNullByDefault +public class ConnectionException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + public ConnectionException(String message) { + super(message); + } +} diff --git a/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/HttpException.java b/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/HttpException.java new file mode 100755 index 0000000000000..59323f9a47271 --- /dev/null +++ b/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/HttpException.java @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2010-2018 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.amazonechocontrol.internal; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * The {@link HttpException} is used for http error codes + * + * @author Michael Geramb - Initial contribution + */ +@NonNullByDefault +public class HttpException extends RuntimeException { + + private static final long serialVersionUID = 1L; + int code; + + public int getCode() { + return code; + } + + public HttpException(int code, String message) { + super(message); + this.code = code; + } +} diff --git a/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/StateStorage.java b/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/StateStorage.java new file mode 100644 index 0000000000000..15c0785ec4dd6 --- /dev/null +++ b/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/StateStorage.java @@ -0,0 +1,113 @@ +/** + * Copyright (c) 2010-2018 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.amazonechocontrol.internal; + +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.util.Properties; + +import org.apache.commons.lang.StringUtils; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.config.core.ConfigConstants; +import org.eclipse.smarthome.core.thing.Thing; +import org.openhab.binding.amazonechocontrol.AmazonEchoControlBindingConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Store and load the state in and from a file + * + * @author Michael Geramb - Initial Contribution + */ +@NonNullByDefault +public class StateStorage { + private final Logger logger = LoggerFactory.getLogger(StateStorage.class); + + File propertyFile; + Thing thing; + @Nullable + Properties properties; + + public StateStorage(Thing thing) { + this.thing = thing; + propertyFile = new File( + ConfigConstants.getUserDataFolder() + File.separator + AmazonEchoControlBindingConstants.BINDING_ID + + File.separator + thing.getUID().getAsString().replace(':', '_') + ".properties"); + } + + public void storeState(@Nullable String key, @Nullable String value) { + synchronized (this) { + if (key == null) { + return; + } + Properties properties = initProperties(); + if (StringUtils.isEmpty(value)) { + properties.remove(key); + } else { + properties.setProperty(key, value); + } + // store the property also in OH to see it in the GUI + thing.setProperty(key, value); + saveProperties(); + } + } + + public @Nullable String findState(String key) { + synchronized (this) { + Properties properties = initProperties(); + Object value = properties.get(key); + if (value == null) { + // upgrade from BETA 9 configuration + String oldValue = thing.getProperties().get(key); + if (StringUtils.isNotEmpty(oldValue)) { + value = oldValue; + storeState(key, oldValue); + } + } + if (value != null) { + return value.toString(); + } + return null; + } + } + + private void saveProperties() { + Properties properties = initProperties(); + logger.debug("Create file {}.", propertyFile); + String directoryName = propertyFile.getParent(); + File directory = new File(directoryName); + if (!directory.exists()) { + directory.mkdirs(); + } + try (FileWriter fileWriter = new FileWriter(propertyFile)) { + properties.store(fileWriter, "Save properties"); + } catch (IOException e) { + logger.error("Saving properties failed {}", e); + } + } + + private Properties initProperties() { + Properties result = properties; + if (result == null) { + result = new Properties(); + if (propertyFile.exists()) { + try (FileReader fileReader = new FileReader(propertyFile)) { + result.load(fileReader); + } catch (IOException e) { + logger.error("Error occured on writing the property file.", e); + } + } + properties = result; + } + return result; + } +} diff --git a/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/discovery/AmazonEchoDiscovery.java b/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/discovery/AmazonEchoDiscovery.java new file mode 100755 index 0000000000000..5f510be9aa349 --- /dev/null +++ b/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/discovery/AmazonEchoDiscovery.java @@ -0,0 +1,225 @@ +/** + * Copyright (c) 2010-2018 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.amazonechocontrol.internal.discovery; + +import static org.openhab.binding.amazonechocontrol.AmazonEchoControlBindingConstants.*; + +import java.util.Date; +import java.util.HashSet; +import java.util.Hashtable; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.config.discovery.AbstractDiscoveryService; +import org.eclipse.smarthome.config.discovery.DiscoveryResult; +import org.eclipse.smarthome.config.discovery.DiscoveryResultBuilder; +import org.eclipse.smarthome.config.discovery.DiscoveryServiceCallback; +import org.eclipse.smarthome.config.discovery.ExtendedDiscoveryService; +import org.eclipse.smarthome.core.thing.ThingTypeUID; +import org.eclipse.smarthome.core.thing.ThingUID; +import org.openhab.binding.amazonechocontrol.handler.AccountHandler; +import org.openhab.binding.amazonechocontrol.internal.Connection; +import org.openhab.binding.amazonechocontrol.internal.jsons.JsonDevices.Device; +import org.osgi.service.component.annotations.Activate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link AmazonEchoDiscovery} is responsible for discovering echo devices on + * the amazon account specified in the binding. + * + * @author Michael Geramb - Initial contribution + */ +@NonNullByDefault +public class AmazonEchoDiscovery extends AbstractDiscoveryService implements ExtendedDiscoveryService { + + AccountHandler accountHandler; + private final Logger logger = LoggerFactory.getLogger(AmazonEchoDiscovery.class); + private final HashSet discoverdFlashBriefings = new HashSet(); + + @Nullable + ScheduledFuture startScanStateJob; + long activateTimeStamp; + + private @Nullable DiscoveryServiceCallback discoveryServiceCallback; + + @Override + public void setDiscoveryServiceCallback(DiscoveryServiceCallback discoveryServiceCallback) { + this.discoveryServiceCallback = discoveryServiceCallback; + } + + public AmazonEchoDiscovery(AccountHandler accountHandler) { + super(SUPPORTED_THING_TYPES_UIDS, 10); + this.accountHandler = accountHandler; + } + + public void activate() { + activate(new Hashtable()); + } + + @Override + public void deactivate() { + super.deactivate(); + } + + @Override + protected void startScan() { + stopScanJob(); + removeOlderResults(activateTimeStamp); + + setDevices(accountHandler.updateDeviceList()); + + String currentFlashBriefingConfiguration = accountHandler.getNewCurrentFlashbriefingConfiguration(); + discoverFlashBriefingProfiles(currentFlashBriefingConfiguration); + } + + protected void startAutomaticScan() { + if (!this.accountHandler.getThing().getThings().isEmpty()) { + stopScanJob(); + return; + } + Connection connection = this.accountHandler.findConnection(); + if (connection == null) { + return; + } + Date verifyTime = connection.tryGetVerifyTime(); + if (verifyTime == null) { + return; + } + if (new Date().getTime() - verifyTime.getTime() < 10000) { + return; + } + startScan(); + } + + @Override + protected void startBackgroundDiscovery() { + stopScanJob(); + startScanStateJob = scheduler.scheduleWithFixedDelay(this::startAutomaticScan, 3000, 1000, + TimeUnit.MILLISECONDS); + } + + @Override + protected void stopBackgroundDiscovery() { + stopScanJob(); + } + + void stopScanJob() { + @Nullable + ScheduledFuture currentStartScanStateJob = startScanStateJob; + if (currentStartScanStateJob != null) { + currentStartScanStateJob.cancel(false); + startScanStateJob = null; + } + } + + @Override + @Activate + public void activate(@Nullable Map config) { + super.activate(config); + if (config != null) { + modified(config); + } + activateTimeStamp = new Date().getTime(); + }; + + synchronized void setDevices(List deviceList) { + DiscoveryServiceCallback discoveryServiceCallback = this.discoveryServiceCallback; + if (discoveryServiceCallback == null) { + return; + } + for (Device device : deviceList) { + String serialNumber = device.serialNumber; + if (serialNumber != null) { + String deviceFamily = device.deviceFamily; + if (deviceFamily != null) { + ThingTypeUID thingTypeId; + if (deviceFamily.equals("ECHO")) { + thingTypeId = THING_TYPE_ECHO; + } else if (deviceFamily.equals("ROOK")) { + thingTypeId = THING_TYPE_ECHO_SPOT; + } else if (deviceFamily.equals("KNIGHT")) { + thingTypeId = THING_TYPE_ECHO_SHOW; + } else if (deviceFamily.equals("WHA")) { + thingTypeId = THING_TYPE_ECHO_WHA; + } else { + logger.debug("Unknown thing type '{}'", deviceFamily); + continue; + } + + ThingUID brigdeThingUID = this.accountHandler.getThing().getUID(); + ThingUID thingUID = new ThingUID(thingTypeId, brigdeThingUID, serialNumber); + if (discoveryServiceCallback.getExistingDiscoveryResult(thingUID) != null) { + continue; + } + if (discoveryServiceCallback.getExistingThing(thingUID) != null) { + continue; + } + DiscoveryResult result = DiscoveryResultBuilder.create(thingUID).withLabel(device.accountName) + .withProperty(DEVICE_PROPERTY_SERIAL_NUMBER, serialNumber) + .withProperty(DEVICE_PROPERTY_FAMILY, deviceFamily) + .withRepresentationProperty(DEVICE_PROPERTY_SERIAL_NUMBER).withBridge(brigdeThingUID) + .build(); + + logger.debug("Device [{}: {}] found. Mapped to thing type {}", device.deviceFamily, serialNumber, + thingTypeId.getAsString()); + + thingDiscovered(result); + } + } + } + } + + public synchronized void discoverFlashBriefingProfiles(String currentFlashBriefingJson) { + if (currentFlashBriefingJson.isEmpty()) { + return; + } + DiscoveryServiceCallback discoveryServiceCallback = this.discoveryServiceCallback; + if (discoveryServiceCallback == null) { + return; + } + + if (!discoverdFlashBriefings.contains(currentFlashBriefingJson)) { + + ThingUID freeThingUID = null; + int freeIndex = 0; + for (int i = 1; i < 1000; i++) { + String id = Integer.toString(i); + ThingUID brigdeThingUID = this.accountHandler.getThing().getUID(); + ThingUID thingUID = new ThingUID(THING_TYPE_FLASH_BRIEFING_PROFILE, brigdeThingUID, id); + if (discoveryServiceCallback.getExistingThing(thingUID) == null + && discoveryServiceCallback.getExistingDiscoveryResult(thingUID) == null) { + freeThingUID = thingUID; + freeIndex = i; + break; + } + } + if (freeThingUID == null) { + logger.debug("No more free flashbriefing thing ID found"); + return; + } + DiscoveryResult result = DiscoveryResultBuilder.create(freeThingUID).withLabel("FlashBriefing " + freeIndex) + .withProperty(DEVICE_PROPERTY_FLASH_BRIEFING_PROFILE, currentFlashBriefingJson) + .withBridge(accountHandler.getThing().getUID()).build(); + logger.debug("Flash Briefing {} discovered", currentFlashBriefingJson); + thingDiscovered(result); + discoverdFlashBriefings.add(currentFlashBriefingJson); + } + } + + public synchronized void removeExistingFlashBriefingProfile(@Nullable String currentFlashBriefingJson) { + if (currentFlashBriefingJson != null) { + discoverdFlashBriefings.remove(currentFlashBriefingJson); + } + } +} diff --git a/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonAutomation.java b/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonAutomation.java new file mode 100644 index 0000000000000..ab7103bd96a7c --- /dev/null +++ b/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonAutomation.java @@ -0,0 +1,43 @@ +/** + * Copyright (c) 2010-2018 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.amazonechocontrol.internal.jsons; + +import java.util.TreeMap; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + +/** + * The {@link JsonAutomation} encapsulate the GSON data of automation query + * + * @author Michael Geramb - Initial contribution + */ +@NonNullByDefault +public class JsonAutomation { + public @Nullable String automationId; + public @Nullable String name; + public @Nullable Trigger @Nullable [] triggers; + public @Nullable TreeMap sequence; + public @Nullable String status; + public long creationTimeEpochMillis; + public long lastUpdatedTimeEpochMillis; + + public class Trigger { + public @Nullable Payload payload; + public @Nullable String id; + public @Nullable String type; + } + + public class Payload { + public @Nullable String customerId; + public @Nullable String utterance; + public @Nullable String locale; + public @Nullable String marketplaceId; + } +} diff --git a/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonBluetoothStates.java b/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonBluetoothStates.java new file mode 100644 index 0000000000000..cd3dd54285547 --- /dev/null +++ b/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonBluetoothStates.java @@ -0,0 +1,61 @@ +/** + * Copyright (c) 2010-2018 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.amazonechocontrol.internal.jsons; + +import org.apache.commons.lang.StringUtils; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.openhab.binding.amazonechocontrol.internal.jsons.JsonDevices.Device; + +/** + * The {@link JsonBluetoothStates} encapsulate the GSON data of bluetooth state + * + * @author Michael Geramb - Initial contribution + */ +@NonNullByDefault +public class JsonBluetoothStates { + + public @Nullable BluetoothState findStateByDevice(@Nullable Device device) { + if (device == null) { + return null; + } + @Nullable + BluetoothState @Nullable [] bluetoothStates = this.bluetoothStates; + if (bluetoothStates == null) { + return null; + } + for (BluetoothState state : bluetoothStates) { + if (state != null && StringUtils.equals(state.deviceSerialNumber, device.serialNumber)) { + return state; + } + } + return null; + } + + public @Nullable BluetoothState @Nullable [] bluetoothStates; + + public class PairedDevice { + public @Nullable String address; + public boolean connected; + public @Nullable String deviceClass; + public @Nullable String friendlyName; + public @Nullable String @Nullable [] profiles; + + } + + public class BluetoothState { + public @Nullable String deviceSerialNumber; + public @Nullable String deviceType; + public @Nullable String friendlyName; + public boolean gadgetPaired; + public boolean online; + public @Nullable PairedDevice @Nullable [] pairedDeviceList; + + } +} diff --git a/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonDevices.java b/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonDevices.java new file mode 100755 index 0000000000000..82a6032746eb4 --- /dev/null +++ b/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonDevices.java @@ -0,0 +1,36 @@ +/** + * Copyright (c) 2010-2018 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.amazonechocontrol.internal.jsons; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + +/** + * The {@link JsonDevices} encapsulate the GSON data of device list + * + * @author Michael Geramb - Initial contribution + */ +@NonNullByDefault +public class JsonDevices { + + public class Device { + public @Nullable String accountName; + public @Nullable String serialNumber; + public @Nullable String deviceOwnerCustomerId; + public @Nullable String deviceAccountId; + public @Nullable String deviceFamily; + public @Nullable String deviceType; + public @Nullable String softwareVersion; + public boolean online; + public @Nullable String @Nullable [] capabilities; + + } + + public @Nullable Device @Nullable [] devices; +} diff --git a/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonEnabledFeeds.java b/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonEnabledFeeds.java new file mode 100644 index 0000000000000..c0b1112b7b0c9 --- /dev/null +++ b/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonEnabledFeeds.java @@ -0,0 +1,23 @@ +/** + * Copyright (c) 2010-2018 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.amazonechocontrol.internal.jsons; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + +/** + * The {@link JsonEnabledFeeds} encapsulate the GSON data of the enabled feeds list + * + * @author Michael Geramb - Initial contribution + */ +@NonNullByDefault +public class JsonEnabledFeeds { + public @Nullable JsonFeed @Nullable [] enabledFeeds; + +} diff --git a/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonFeed.java b/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonFeed.java new file mode 100644 index 0000000000000..73542f06f25c1 --- /dev/null +++ b/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonFeed.java @@ -0,0 +1,25 @@ +/** + * Copyright (c) 2010-2018 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.amazonechocontrol.internal.jsons; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + +/** + * The {@link JsonFeed} encapsulate the GSON data of feed + * + * @author Michael Geramb - Initial contribution + */ +@NonNullByDefault +public class JsonFeed { + public @Nullable Object feedId; + public @Nullable String name; + public @Nullable String skillId; + public @Nullable String imageUrl; +} diff --git a/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonMediaState.java b/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonMediaState.java new file mode 100755 index 0000000000000..2be8c9229a4dc --- /dev/null +++ b/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonMediaState.java @@ -0,0 +1,80 @@ +/** + * Copyright (c) 2010-2018 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.amazonechocontrol.internal.jsons; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + +/** + * The {@link JsonMediaState} encapsulate the GSON data of the current media state + * + * @author Michael Geramb - Initial contribution + */ +@NonNullByDefault +public class JsonMediaState { + + public @Nullable String clientId; + public @Nullable String contentId; + public @Nullable String contentType; + public @Nullable String currentState; + public @Nullable String imageURL; + public boolean isDisliked; + public boolean isLiked; + public boolean looping; + public @Nullable String mediaOwnerCustomerId; + public boolean muted; + public @Nullable String programId; + public int progressSeconds; + public @Nullable String providerId; + public @Nullable QueueEntry @Nullable [] queue; + public @Nullable String queueId; + public @Nullable Integer queueSize; + public @Nullable String radioStationId; + public int radioVariety; + public @Nullable String referenceId; + public @Nullable String service; + public boolean shuffling; + // public long timeLastShuffled; parsing fails with some values, so do not use it + public int volume; + + public class QueueEntry { + + public @Nullable String album; + public @Nullable String albumAsin; + public @Nullable String artist; + public @Nullable String asin; + public @Nullable String cardImageURL; + public @Nullable String contentId; + public @Nullable String contentType; + public int durationSeconds; + public boolean feedbackDisabled; + public @Nullable String historicalId; + public @Nullable String imageURL; + public int index; + public boolean isAd; + public boolean isDisliked; + public boolean isFreeWithPrime; + public boolean isLiked; + public @Nullable String programId; + public @Nullable String programName; + public @Nullable String providerId; + public @Nullable String queueId; + public @Nullable String radioStationCallSign; + public @Nullable String radioStationId; + public @Nullable String radioStationLocation; + public @Nullable String radioStationSlogan; + public @Nullable String referenceId; + public @Nullable String service; + public @Nullable String startTime; + public @Nullable String title; + public @Nullable String trackId; + public @Nullable String trackStatus; + + } +} diff --git a/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonMusicProvider.java b/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonMusicProvider.java new file mode 100644 index 0000000000000..b5e1cbd898604 --- /dev/null +++ b/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonMusicProvider.java @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2010-2018 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.amazonechocontrol.internal.jsons; + +import java.util.List; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + +/** + * The {@link JsonMusicProvider} encapsulate the GSON returned for a music provider + * + * @author Michael Geramb - Initial contribution + */ +@NonNullByDefault +public class JsonMusicProvider { + public @Nullable String displayName; + public @Nullable List<@Nullable Object> @Nullable [] supportedTriggers; + public @Nullable String icon; + public @Nullable List<@Nullable String> supportedProperties; + public @Nullable String id; + public @Nullable String availability; + public @Nullable String description; +} diff --git a/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonNotificationRequest.java b/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonNotificationRequest.java new file mode 100644 index 0000000000000..67a5d69cee9a3 --- /dev/null +++ b/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonNotificationRequest.java @@ -0,0 +1,37 @@ +/** + * Copyright (c) 2010-2018 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.amazonechocontrol.internal.jsons; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + +/** + * The {@link JsonNotificationRequest} encapsulate the GSON data for a notification request + * + * @author Michael Geramb - Initial contribution + */ +@NonNullByDefault +public class JsonNotificationRequest { + public @Nullable String type = "Reminder"; // "Reminder", "Alarm" + public @Nullable String status = "ON"; + public long alarmTime; + public @Nullable String originalTime; + public @Nullable String originalDate; + public @Nullable String timeZoneId; + public @Nullable String reminderIndex; + public @Nullable JsonNotificationSound sound; + public @Nullable String deviceSerialNumber; + public @Nullable String deviceType; + public @Nullable String recurringPattern; + public @Nullable String reminderLabel; + public boolean isSaveInFlight = true; + public @Nullable String id = "createReminder"; + public boolean isRecurring = false; + public long createdDate; +} diff --git a/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonNotificationResponse.java b/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonNotificationResponse.java new file mode 100644 index 0000000000000..8bd8067716faa --- /dev/null +++ b/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonNotificationResponse.java @@ -0,0 +1,65 @@ +/** + * Copyright (c) 2010-2018 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.amazonechocontrol.internal.jsons; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + +/** + * The {@link JsonNotificationResponse} encapsulate the GSON data for the result of a notification request + * + * @author Michael Geramb - Initial contribution + */ +@NonNullByDefault +public class JsonNotificationResponse { + // This is only a partial definition, see the example JSON below + public long alarmTime; + public long createdDate; + public @Nullable String deviceSerialNumber; + public @Nullable String deviceType; + public @Nullable String id; + public @Nullable String status; + public @Nullable String type; +} + +/* + * Example JSON: + * { + *    "alarmTime":1518864868060, + *    "createdDate":1518864863801, + *    "deviceSerialNumber":"XXXXXXXXXX", + *    "deviceType":"XXXXXXXXXX", + *    "id":"XXXXXXXXXX-XXXXXXXXXX-XXXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXX", + *    "musicAlarmId":null, + *    "musicEntity":null, + *    "notificationIndex":"XXXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXX", + *    "originalDate":null, + *    "originalTime":"11:54:28.060", + *    "provider":null, + *    "recurringPattern":null, + *    "remainingTime":0, + *    "reminderLabel":null, + *    "sound":{ + *       "displayName":"Clarity", + *       "folder":null, + *       "id":"system_alerts_melodic_05", + *       "providerId":"ECHO", + *       "sampleUrl":"https://s3.amazonaws.com/deeappservice.prod.notificationtones/system_alerts_melodic_05.mp3" + *    }, + *    "status":"OFF", + *    "timeZoneId":null, + *    "timerLabel":null, + *    "triggerTime":0, + *    "type":"Alarm", + *    "version":"2", + *    "alarmIndex":null, + *    "isSaveInFlight":true + * } + * + */ diff --git a/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonNotificationSound.java b/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonNotificationSound.java new file mode 100644 index 0000000000000..3bfc30af716f4 --- /dev/null +++ b/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonNotificationSound.java @@ -0,0 +1,26 @@ +/** + * Copyright (c) 2010-2018 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.amazonechocontrol.internal.jsons; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + +/** + * The {@link JsonNotificationSound} encapsulate the GSON data for a notification sound + * + * @author Michael Geramb - Initial contribution + */ +@NonNullByDefault +public class JsonNotificationSound { + public @Nullable String displayName; + public @Nullable String folder; + public @Nullable String id = "system_alerts_melodic_01"; + public @Nullable String providerId = "ECHO"; + public @Nullable String sampleUrl; +} diff --git a/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonNotificationSounds.java b/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonNotificationSounds.java new file mode 100644 index 0000000000000..9070bad204cec --- /dev/null +++ b/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonNotificationSounds.java @@ -0,0 +1,22 @@ +/** + * Copyright (c) 2010-2018 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.amazonechocontrol.internal.jsons; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + +/** + * The {@link JsonNotificationSounds} encapsulate the GSON data for a notification sounds + * + * @author Michael Geramb - Initial contribution + */ +@NonNullByDefault +public class JsonNotificationSounds { + public @Nullable JsonNotificationSound @Nullable [] notificationSounds; +} diff --git a/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonPlaySearchPhraseOperationPayload.java b/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonPlaySearchPhraseOperationPayload.java new file mode 100644 index 0000000000000..3b0d2a300f146 --- /dev/null +++ b/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonPlaySearchPhraseOperationPayload.java @@ -0,0 +1,28 @@ +/** + * Copyright (c) 2010-2018 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.amazonechocontrol.internal.jsons; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + +/** + * The {@link JsonPlaySearchPhraseOperationPayload} encapsulate the GSON for validation requests and results + * + * @author Michael Geramb - Initial contribution + */ +@NonNullByDefault +public class JsonPlaySearchPhraseOperationPayload { + public @Nullable String deviceType = "ALEXA_CURRENT_DEVICE_TYPE"; + public @Nullable String deviceSerialNumber = "ALEXA_CURRENT_DSN"; + public @Nullable String locale = "ALEXA_CURRENT_LOCALE"; + public @Nullable String customerId; + public @Nullable String searchPhrase; + public @Nullable String sanitizedSearchPhrase; + public @Nullable String musicProviderId = "ALEXA_CURRENT_DSN"; +} diff --git a/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonPlayValidationResult.java b/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonPlayValidationResult.java new file mode 100644 index 0000000000000..bf95a0e7a5348 --- /dev/null +++ b/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonPlayValidationResult.java @@ -0,0 +1,22 @@ +/** + * Copyright (c) 2010-2018 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.amazonechocontrol.internal.jsons; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + +/** + * The {@link JsonPlayValidationResult} encapsulate the GSON for validation result + * + * @author Michael Geramb - Initial contribution + */ +@NonNullByDefault +public class JsonPlayValidationResult { + public @Nullable JsonPlaySearchPhraseOperationPayload operationPayload; +} diff --git a/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonPlayerState.java b/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonPlayerState.java new file mode 100755 index 0000000000000..d8b1fe5475cc8 --- /dev/null +++ b/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonPlayerState.java @@ -0,0 +1,61 @@ +/** + * Copyright (c) 2010-2018 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ + +package org.openhab.binding.amazonechocontrol.internal.jsons; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + +/** + * The {@link JsonPlayerState} encapsulate the GSON data of the player state + * + * @author Michael Geramb - Initial contribution + */ +@NonNullByDefault +public class JsonPlayerState { + public @Nullable PlayerInfo playerInfo; + + public class PlayerInfo { + public @Nullable String state; + public @Nullable InfoText infoText; + public @Nullable InfoText miniInfoText; + public @Nullable Provider provider; + public @Nullable Volume volume; + public @Nullable MainArt mainArt; + + public @Nullable String queueId; + public @Nullable String mediaId; + + public class InfoText { + public boolean multiLineMode; + public @Nullable String subText1; + public @Nullable String subText2; + public @Nullable String title; + + } + + public class Provider { + public @Nullable String providerDisplayName; + public @Nullable String providerName; + } + + public class Volume { + public boolean muted; + public int volume; + } + + public class MainArt { + public @Nullable String altText; + public @Nullable String artType; + public @Nullable String contentType; + public @Nullable String url; + } + + } +} diff --git a/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonPlaylists.java b/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonPlaylists.java new file mode 100644 index 0000000000000..c9d8e76d0003d --- /dev/null +++ b/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonPlaylists.java @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2010-2018 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.amazonechocontrol.internal.jsons; + +import java.util.Map; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + +/** + * The {@link JsonPlayerState} encapsulate the GSON data of playlist query + * + * @author Michael Geramb - Initial contribution + */ +@NonNullByDefault +public class JsonPlaylists { + + public @Nullable Map playlists; + + public class PlayList { + public @Nullable String playlistId; + public @Nullable String title; + public int trackCount; + public int version; + } +} diff --git a/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonStartRoutineRequest.java b/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonStartRoutineRequest.java new file mode 100644 index 0000000000000..448a33e9f9d0a --- /dev/null +++ b/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonStartRoutineRequest.java @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2010-2018 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.amazonechocontrol.internal.jsons; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + +/** + * The {@link JsonStartRoutineRequest} encapsulate the GSON for starting a routine + * + * @author Michael Geramb - Initial contribution + */ +@NonNullByDefault +public class JsonStartRoutineRequest { + public @Nullable String behaviorId = "PREVIEW"; + public @Nullable String sequenceJson; + public @Nullable String status = "ENABLED"; +} diff --git a/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/statedescription/AmazonEchoDynamicStateDescriptionProvider.java b/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/statedescription/AmazonEchoDynamicStateDescriptionProvider.java new file mode 100644 index 0000000000000..5fbe6bfceeead --- /dev/null +++ b/addons/binding/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/statedescription/AmazonEchoDynamicStateDescriptionProvider.java @@ -0,0 +1,286 @@ +/** + * Copyright (c) 2010-2018 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.amazonechocontrol.internal.statedescription; + +import static org.openhab.binding.amazonechocontrol.AmazonEchoControlBindingConstants.*; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +import org.apache.commons.lang.StringUtils; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.thing.Channel; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.ThingRegistry; +import org.eclipse.smarthome.core.thing.binding.ThingHandler; +import org.eclipse.smarthome.core.thing.type.DynamicStateDescriptionProvider; +import org.eclipse.smarthome.core.types.StateDescription; +import org.eclipse.smarthome.core.types.StateOption; +import org.openhab.binding.amazonechocontrol.handler.AccountHandler; +import org.openhab.binding.amazonechocontrol.handler.EchoHandler; +import org.openhab.binding.amazonechocontrol.handler.FlashBriefingProfileHandler; +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.JsonBluetoothStates.BluetoothState; +import org.openhab.binding.amazonechocontrol.internal.jsons.JsonBluetoothStates.PairedDevice; +import org.openhab.binding.amazonechocontrol.internal.jsons.JsonDevices.Device; +import org.openhab.binding.amazonechocontrol.internal.jsons.JsonMusicProvider; +import org.openhab.binding.amazonechocontrol.internal.jsons.JsonNotificationSound; +import org.openhab.binding.amazonechocontrol.internal.jsons.JsonPlaylists; +import org.openhab.binding.amazonechocontrol.internal.jsons.JsonPlaylists.PlayList; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; +import org.osgi.service.component.annotations.ReferenceCardinality; +import org.osgi.service.component.annotations.ReferencePolicy; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.JsonSyntaxException; + +/** + * Dynamic channel state description provider. + * Overrides the state description for the controls, which receive its configuration in the runtime. + * + * @author Michael Geramb - Initial contribution + */ +@NonNullByDefault +@Component(service = { DynamicStateDescriptionProvider.class, + AmazonEchoDynamicStateDescriptionProvider.class }, immediate = true) +public class AmazonEchoDynamicStateDescriptionProvider implements DynamicStateDescriptionProvider { + + private final Logger logger = LoggerFactory.getLogger(AmazonEchoDynamicStateDescriptionProvider.class); + private @Nullable ThingRegistry thingRegistry; + + @Reference(cardinality = ReferenceCardinality.MANDATORY, policy = ReferencePolicy.DYNAMIC) + protected void setThingRegistry(ThingRegistry thingRegistry) { + this.thingRegistry = thingRegistry; + } + + protected void unsetThingRegistry(ThingRegistry thingRegistry) { + this.thingRegistry = thingRegistry; + } + + public @Nullable ThingHandler findHandler(Channel channel) { + ThingRegistry thingRegistry = this.thingRegistry; + if (thingRegistry == null) { + return null; + } + Thing thing = thingRegistry.get(channel.getUID().getThingUID()); + if (thing == null) { + return null; + } + return thing.getHandler(); + } + + @Override + public @Nullable StateDescription getStateDescription(Channel channel, + @Nullable StateDescription originalStateDescription, @Nullable Locale locale) { + if (originalStateDescription == null) { + return null; + } + ThingRegistry thingRegistry = this.thingRegistry; + if (thingRegistry == null) { + return originalStateDescription; + } + if (CHANNEL_TYPE_BLUETHOOTH_MAC.equals(channel.getChannelTypeUID())) { + EchoHandler handler = (EchoHandler) findHandler(channel); + if (handler == null) { + return originalStateDescription; + } + BluetoothState bluetoothState = handler.findBluetoothState(); + if (bluetoothState == null) { + return originalStateDescription; + } + PairedDevice[] pairedDeviceList = bluetoothState.pairedDeviceList; + if (pairedDeviceList == null) { + return originalStateDescription; + } + + ArrayList options = new ArrayList<>(); + options.add(new StateOption("", "")); + for (PairedDevice device : pairedDeviceList) { + if (device == null) { + continue; + } + if (device.address != null && device.friendlyName != null) { + options.add(new StateOption(device.address, device.friendlyName)); + } + } + StateDescription result = new StateDescription(originalStateDescription.getMinimum(), + originalStateDescription.getMaximum(), originalStateDescription.getStep(), + originalStateDescription.getPattern(), originalStateDescription.isReadOnly(), options); + return result; + + } else if (CHANNEL_TYPE_AMAZON_MUSIC_PLAY_LIST_ID.equals(channel.getChannelTypeUID())) { + EchoHandler handler = (EchoHandler) findHandler(channel); + if (handler == null) { + return originalStateDescription; + } + Connection connection = handler.findConnection(); + if (connection == null) { + return originalStateDescription; + } + Device device = handler.findDevice(); + if (device == null) { + return originalStateDescription; + } + JsonPlaylists playLists; + try { + playLists = connection.getPlaylists(device); + } catch (IOException | HttpException | URISyntaxException | JsonSyntaxException | ConnectionException e) { + logger.warn("Get playlist failed: {}", e); + return originalStateDescription; + } + ArrayList options = new ArrayList<>(); + options.add(new StateOption("", "")); + @Nullable + Map<@NonNull String, @Nullable PlayList @Nullable []> playlistMap = playLists.playlists; + if (playlistMap != null) { + for (PlayList[] innerLists : playlistMap.values()) { + if (innerLists != null && innerLists.length > 0) { + PlayList playList = innerLists[0]; + if (playList.playlistId != null && playList.title != null) { + options.add(new StateOption(playList.playlistId, + String.format("%s (%d)", playList.title, playList.trackCount))); + } + } + } + } + StateDescription result = new StateDescription(originalStateDescription.getMinimum(), + originalStateDescription.getMaximum(), originalStateDescription.getStep(), + originalStateDescription.getPattern(), originalStateDescription.isReadOnly(), options); + return result; + } else if (CHANNEL_TYPE_PLAY_ALARM_SOUND.equals(channel.getChannelTypeUID())) { + EchoHandler handler = (EchoHandler) findHandler(channel); + if (handler == null) { + return originalStateDescription; + } + Connection connection = handler.findConnection(); + if (connection == null) { + return originalStateDescription; + } + Device device = handler.findDevice(); + if (device == null) { + return originalStateDescription; + } + + JsonNotificationSound[] notificationSounds; + try { + notificationSounds = connection.getNotificationSounds(device); + } catch (IOException | HttpException | URISyntaxException | JsonSyntaxException | ConnectionException e) { + logger.warn("Get notification sounds failed: {}", e); + return originalStateDescription; + } + ArrayList options = new ArrayList<>(); + options.add(new StateOption("", "")); + + for (JsonNotificationSound notificationSound : notificationSounds) { + if (notificationSound.folder == null && notificationSound.providerId != null + && notificationSound.id != null && notificationSound.displayName != null) { + String providerSoundId = notificationSound.providerId + ":" + notificationSound.id; + options.add(new StateOption(providerSoundId, notificationSound.displayName)); + } + } + StateDescription result = new StateDescription(originalStateDescription.getMinimum(), + originalStateDescription.getMaximum(), originalStateDescription.getStep(), + originalStateDescription.getPattern(), originalStateDescription.isReadOnly(), options); + return result; + } else if (CHANNEL_TYPE_CHANNEL_PLAY_ON_DEVICE.equals(channel.getChannelTypeUID())) { + FlashBriefingProfileHandler handler = (FlashBriefingProfileHandler) findHandler(channel); + if (handler == null) { + return originalStateDescription; + } + AccountHandler accountHandler = handler.findAccountHandler(); + if (accountHandler == null) { + return originalStateDescription; + } + @NonNull + List<@NonNull Device> devices = accountHandler.getLastKnownDevices(); + if (devices.size() == 0) { + return originalStateDescription; + } + + ArrayList options = new ArrayList<>(); + options.add(new StateOption("", "")); + for (Device device : devices) { + if (device.capabilities != null && Arrays.asList(device.capabilities).contains("FLASH_BRIEFING")) { + options.add(new StateOption(device.serialNumber, device.accountName)); + } + } + StateDescription result = new StateDescription(originalStateDescription.getMinimum(), + originalStateDescription.getMaximum(), originalStateDescription.getStep(), + originalStateDescription.getPattern(), originalStateDescription.isReadOnly(), options); + return result; + } else if (CHANNEL_TYPE_MUSIC_PROVIDER_ID.equals(channel.getChannelTypeUID())) { + EchoHandler handler = (EchoHandler) findHandler(channel); + if (handler == null) { + return originalStateDescription; + } + Connection connection = handler.findConnection(); + if (connection == null) { + return originalStateDescription; + } + List musicProviders = connection.getMusicProviders(); + + ArrayList options = new ArrayList<>(); + for (JsonMusicProvider musicProvider : musicProviders) { + @Nullable + List<@Nullable String> properties = musicProvider.supportedProperties; + String providerId = musicProvider.id; + String displayName = musicProvider.displayName; + if (properties != null && properties.contains("Alexa.Music.PlaySearchPhrase") + && StringUtils.isNotEmpty(providerId) + && StringUtils.equals(musicProvider.availability, "AVAILABLE") + && StringUtils.isNotEmpty(displayName)) { + options.add(new StateOption(providerId, displayName)); + } + } + StateDescription result = new StateDescription(originalStateDescription.getMinimum(), + originalStateDescription.getMaximum(), originalStateDescription.getStep(), + originalStateDescription.getPattern(), originalStateDescription.isReadOnly(), options); + return result; + } else if (CHANNEL_TYPE_START_COMMAND.equals(channel.getChannelTypeUID())) { + EchoHandler handler = (EchoHandler) findHandler(channel); + if (handler == null) { + return originalStateDescription; + } + AccountHandler account = handler.findAccount(); + if (account == null) { + return originalStateDescription; + } + @NonNull + List<@NonNull FlashBriefingProfileHandler> flashbriefings = account.getFlashBriefingProfileHandlers(); + if (flashbriefings.isEmpty()) { + return originalStateDescription; + } + + ArrayList options = new ArrayList<>(); + options.addAll(originalStateDescription.getOptions()); + + for (FlashBriefingProfileHandler flashBriefing : flashbriefings) { + String value = FLASH_BRIEFING_COMMAND_PREFIX + flashBriefing.getThing().getUID().getId(); + String displayName = flashBriefing.getThing().getLabel(); + options.add(new StateOption(value, displayName)); + } + StateDescription result = new StateDescription(originalStateDescription.getMinimum(), + originalStateDescription.getMaximum(), originalStateDescription.getStep(), + originalStateDescription.getPattern(), originalStateDescription.isReadOnly(), options); + return result; + } + return originalStateDescription; + } +} diff --git a/addons/binding/pom.xml b/addons/binding/pom.xml index 26dc579ecd371..7ee51b93a07fa 100644 --- a/addons/binding/pom.xml +++ b/addons/binding/pom.xml @@ -20,6 +20,7 @@ org.openhab.binding.airquality org.openhab.binding.allplay org.openhab.binding.amazondashbutton + org.openhab.binding.amazonechocontrol org.openhab.binding.atlona org.openhab.binding.autelis org.openhab.binding.avmfritz diff --git a/features/openhab-addons/src/main/feature/feature.xml b/features/openhab-addons/src/main/feature/feature.xml index 6ca8d74be10b0..92a0bf1575ec8 100644 --- a/features/openhab-addons/src/main/feature/feature.xml +++ b/features/openhab-addons/src/main/feature/feature.xml @@ -28,6 +28,11 @@ mvn:org.openhab.binding/org.openhab.binding.amazondashbutton/${project.version} + + openhab-runtime-base + mvn:org.openhab.binding/org.openhab.binding.amazonechocontrol/${project.version} + + openhab-runtime-base mvn:org.openhab.binding/org.openhab.binding.atlona/${project.version}