mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-02-01 19:30:31 +00:00
a2445a7983
git-svn-id: https://svn.fhem.de/fhem/trunk@26735 2b470e98-0d58-463d-a4d8-8e2adae1ed80
5773 lines
249 KiB
Perl
5773 lines
249 KiB
Perl
# $Id$
|
|
#
|
|
##############################################
|
|
#
|
|
# 2022.11.22 v0.2.20
|
|
# - FEATURE: Unterstützung A4ZXE0RM7LQ7A Echo Dot Gen5
|
|
#
|
|
# 2022.11.21 v0.2.19
|
|
# - BUG: Auswertung FHEM Verzeichnis Attribut "fhem_home" eingeführt Standardwert = "/opt/fhem"
|
|
#
|
|
# 2022.11.21 v0.2.18
|
|
# - FEATURE: Unterstützung A2DS1Q2TPDJ48U Echo Dot Gen5 with Clock
|
|
# Unterstützung AQCGW9PSYWRF Polk React Soundbar
|
|
# Unterstützung A1VGB7MHSIEYFK Fire TV Cube Gen3
|
|
#
|
|
# 2022.11.14 v0.2.17
|
|
# - FEATURE: Unterstützung A1EIANJ7PNB0Q7 Echo Show 15
|
|
#
|
|
# 2022.09.12 v0.2.16
|
|
# - BUG: Activities Result "DISCARDED_NON_DEVICE_DIRECTED_INTENT" entfernt
|
|
#
|
|
# 2022.01.12 v0.2.15
|
|
# - FEATURE: Unterstützung A2Z8O30CD35N8F Sonos Arc
|
|
# Unterstützung A3EVMLQTU6WL1W Fire TV Stick 4K Max
|
|
# Unterstützung A39Y3UG1XLEJLZ Fitbit Sense
|
|
# Unterstützung A1XWJRHALS1REP Echo Show 5 2. Generation
|
|
#
|
|
# 2021.10.19 v0.2.14
|
|
# - BUG: https://forum.fhem.de/index.php/topic,82631.msg1175268.html#msg1175268 (Danke Benutzer JudgeDredd)
|
|
# - FEATURE: Unterstützung A31DTMEEVDDOIV FireTV Stick
|
|
#
|
|
# 2021.09.15 v0.2.13
|
|
# - CHANGE: Probleme set tunein (Danke Benutzer adn77)
|
|
#
|
|
# 2021.06.24 v0.2.12
|
|
# - FEATURE: Unterstützung A15996VY63BQ2D Echo Show 8 Gen2
|
|
# Unterstützung A2WFDCBDEXOXR8 Bose Soundbar 700
|
|
#
|
|
# 2021.05.18 v0.2.11
|
|
# - FEATURE: Unterstützung A1DL2DVDQVK3Q Fire Tab HD 10
|
|
#
|
|
# 2021.04.26 v0.2.10
|
|
# - CHANGE: Logeintrag "[Echodevice] [echodevice_SendCommand] [12] IGNORIERE Command=activities Abfrage in CMD_Queue schon vorhanden!" auf Loglevel 4 geändert
|
|
# - FEATURE: Unterstützung AIPK7MM90V7TB Echo Show Gen3
|
|
#
|
|
# 2021.02.10 v0.2.9
|
|
# - BUG: Probleme wenn getbehavior keine Antwort liefert.
|
|
# - CHANGE: CMD_Queue check
|
|
# ($hash->{model} eq "Reverb" || $hash->{model} eq "Sonos One" || $hash->{model} eq "Sonos Beam" Unterscheidung entfernt
|
|
# - FEATURE: Geräte Kennung THIRD_PARTY_AVS_SONOS_BOOTLEG hinzugefügt
|
|
#
|
|
# 2021.02.07 v0.2.8
|
|
# - BUG: Sonso aktualisiert keine voice Readings
|
|
#
|
|
# 2021.01.28 v0.2.7
|
|
# - BUG: Routinen werden nicht mehr angezeigt
|
|
#
|
|
# 2021.01.18 v0.2.6
|
|
# - BUG: item_shopping_delete,item_shopping_add,item_task_delete,item_task.add
|
|
# - FEATURE: Unterstützung A23FPV4BT7FH68 Yamaha YAS-209 Soundbar
|
|
# Untersützung A265XOI9586NML Fire TV Stick 4K
|
|
#
|
|
# 2020.12.11 v0.2.5
|
|
# - FEATURE: Text Kommando an Amazon schicken "set textcommand"
|
|
# Unterstützung A2WN1FJ2HG09UN Ultimate Alexa
|
|
#
|
|
# 2020.11.19 v0.2.4
|
|
# - CHANGE: get custom-history-records Dialog angepasst
|
|
# - FEATURE: Unterstützung A2U21SRK4QGSE1 Echo Dot Gen4
|
|
#
|
|
# 2020.11.18 v0.2.3
|
|
# - FEATURE: get custom-history-records
|
|
# Unterstützung A2H4LV5GIZ1JFT Echo Dot Gen4 with Clock
|
|
# Unterstützung AVE5HX13UR5NO Zero Touch (Logitech)
|
|
# Unterstützung A3GZUE7F9MEB4U Sony WH-100XM3
|
|
# Unterstützung A2J0R2SD7G9LPA Lenovo P10
|
|
# Unterstützung A1J16TEDOYCZTN Amazon Tablet
|
|
# Unterstützung A38EHHIB10L47V Fire HD 8 Tablet
|
|
# Unterstützung A112LJ20W14H95 Media Display
|
|
# Unterstützung A1H0CMF1XM0ZP4 Bose Soundtouch
|
|
# Unterstützung AAMFMBBEW2960 Garmin DriveSmart 65 with Amazon Alexa
|
|
# Unterstützung A2IVLV5VM2W81 Mobile Voice iOS";}
|
|
# Unterstützung A2TF17PFR55MTB Mobile Voice Android
|
|
# Unterstützung A3V3VA38K169FO Fire Tablet
|
|
# Unterstützung AVD3HM0HOJAAL Sonos One
|
|
# Unterstützung A1C66CX2XD756O Fire HD 8 Tablet
|
|
# Unterstützung A17LGWINFBUTZZ Anker Roav Car Charger
|
|
# Unterstützung A2XPGY5LRKB9BE FitBit watch
|
|
# Unterstützung A2Y04QPFCANLPQ Bose QC35 II
|
|
# Unterstützung A3BW5ZVFHRCQPO Alexa Car
|
|
# Unterstützung A303PJF6ISQ7IC Echo Auto
|
|
# Unterstützung A1ZB65LA390I4K Fire HD 10 Tablet
|
|
# Unterstützung AVU7CPPF2ZRAS Fire HD 8 Plus (2020)
|
|
# Unterstützung A24Z7PEXY4MDTK Sony WF-1000X
|
|
# Unterstützung ABN8JEI7OQF61 Sony WF-1000XM3
|
|
# Unterstützung A7S41FQ5TWBC9 Sony WH-1000XM4
|
|
#
|
|
# 2020.11.06 v0.2.2
|
|
# - FEATURE: Unterstützung A3RMGO6LYLH7YN Echo Dot Gen4
|
|
#
|
|
# 2020.10.07 v0.2.1
|
|
# - BUG: Not a HASH reference at ./FHEM/37_echodevice.pm line 2975
|
|
#
|
|
# 2020.10.05 v0.2.0
|
|
# - BUG: Not a HASH reference at ./FHEM/37_echodevice.pm line 3532
|
|
#
|
|
# 2020.09.25 v0.1.9
|
|
# - BUG: Not a HASH reference at ./FHEM/37_echodevice.pm line 2687
|
|
#
|
|
# 2020.05.06 v0.1.8
|
|
# - BUG: Zu viele Loginfos bei set "NPM_login refresh"
|
|
#
|
|
# 2020.04.27 v0.1.7
|
|
# - FEATURE: Unterstützung A1WAR447VT003J Yamaha MusicCast 20
|
|
# - BUG: set "NPM_login refresh"
|
|
# - CHANGE: get status erweitert
|
|
#
|
|
# 2020.04.22 v0.1.5
|
|
# - CHANGE: Mehr Loginfos bei set "NPM_login refresh"
|
|
#
|
|
# 2020.04.20 v0.1.4
|
|
# - CHANGE: Keepalive aktiviert (cookielogin6)
|
|
#
|
|
# 2020.04.14 v0.1.3
|
|
# - CHANGE: Mehr Loginfos bei set "NPM_login new"
|
|
#
|
|
# 2020.04.12 v0.1.2
|
|
# - CHANGE: Mehr Loginfos bei set "NPM_login new"
|
|
#
|
|
# 2020.04.08 v0.1.1
|
|
# - CHANGE: Keepalive aktiviert
|
|
# - BUG: set "NPM_login new"
|
|
# - FEATURE: Unterstützung A3RBAYBE7VM004 ECHO Studio
|
|
# Unterstützung A3SSG6GR8UU7SN ECHO SUB
|
|
# Unterstützung A1HNT9YTOBE735 Telekom Smart Speaker
|
|
# set sounds: (Sounds gemäß Routine-Übersicht)
|
|
#
|
|
# 2019.12.24 v0.1.0
|
|
# - FEATURE: Unterstützung A1Z88NGR2BK6A2 ECHO Show 8
|
|
# Unterstützung A2JKHJ0PX4J3L3 ECHO FireTv Cube 4K
|
|
#
|
|
# 2019.12.22 v0.0.60
|
|
# - FEATURE: Unterstützung A3VRME03NAXFUB ECHO Flex
|
|
# Unterstützung AKOAGQTKAS9YB ECHO Connect
|
|
# Unterstützung A3NTO4JLV9QWRB Gigaset L800HX
|
|
#
|
|
# 2019.11.05 v0.0.59
|
|
# - FEATURE: Nachricht an Handy App schicken "set mobilmessage"
|
|
# - CHANGE: Hilfetexte erweitert
|
|
#
|
|
# 2019.10.27 v0.0.58
|
|
# - FEATURE: Unterstützung A30YDR2MK8HMRV ECHO Gen 3
|
|
#
|
|
# 2019.10.17 v0.0.57
|
|
# - FEATURE: Unterstützung A3FX4UWTP28V1P ECHO Gen 3
|
|
#
|
|
# 2019.10.09 v0.0.56
|
|
# - FEATURE: Hintergrundbild ECHO SHOW ändern "set homescreen"
|
|
#
|
|
# 2019.09.20 v0.0.55
|
|
# - CHANGE: speak_volume Auswertung Account-Device/Echo-Device
|
|
# DEF xxx@xxx.de xxx = NPM Login Modus
|
|
# - BUGFIX: presence
|
|
#
|
|
# 2019.07.22 v0.0.54
|
|
# - FEATURE: Unterstützung A1RABVCI4QCIKC ECHO dot 3
|
|
#
|
|
# 2019.02.19 v0.0.53
|
|
# - FEATURE: Unterstützung A4ZP7ZC4PI6TO ECHO 5
|
|
# Unterstützung A1RTAM01W29CUP Alexa App for PC
|
|
# Unterstützung A21Z3CGI8UIP0F HEOS
|
|
#
|
|
# 2019.02.19 v0.0.52
|
|
# - FEATURE: Alarme "_originalDate" als Reading
|
|
# - BUGFIX: Readings *_count Wert
|
|
#
|
|
# 2019.02.18 v0.0.51z
|
|
# - BUGFIX: NPM Proxy IP Adresse / Port usw.
|
|
# set routine_play - Unterstützung Smart Home Geräte
|
|
# set speak - Sonderzeichen " entfernen
|
|
# get conversations https://forum.fhem.de/index.php/topic,82631.msg903955.html#msg903955
|
|
# Bluetooth Geräte bereinigen
|
|
# - FEATURE: Unterstützung AppRegisterLogin per NPM
|
|
# Unterstützung A10L5JEZTKKCZ8 VOBOT
|
|
# Unterstützung A1JJ0KFC4ZPNJ3 ECHO Input
|
|
# Unterstützung AKPGW064GI9HE Fire TV Stick 4K
|
|
# Unterstützung A37SHHQ3NUL7B5 Bose Home Speaker 500
|
|
# Unterstützung AVN2TMX8MU2YM Bose Home Speaker 500
|
|
# set speak_ssml https://docs.aws.amazon.com/polly/latest/dg/supported-ssml.html
|
|
# https://developer.amazon.com/de/docs/custom-skills/speech-synthesis-markup-language-ssml-reference.html
|
|
# get status - Statusinformationen zum Modul
|
|
# Attribut "ignorevoicecommand" https://forum.fhem.de/index.php/topic,82631.msg906424.html#msg906424
|
|
# Alarme "_recurringPattern" als Reading
|
|
# - CHANGE: https://forum.fhem.de/index.php/topic,82631.msg869460.html#msg869460
|
|
#
|
|
# 2018.12.02 v0.0.50
|
|
# - FEATURE: Unterstützung A32DDESGESSHZA Echo Dot Gen3
|
|
#
|
|
# 2018.11.13 v0.0.49
|
|
# - BUGFIX: reading voice
|
|
# Sonos Beam A3NPD82ABCPIDP
|
|
# - FEATURE: reading voice_timestamp
|
|
#
|
|
# 2018.10.30 v0.0.48i
|
|
# - CHANGE: Attribut browser_useragent_random (Standard=0)
|
|
# Neuer Status "connected but loginerror"
|
|
# - BUGFIX: https://forum.fhem.de/index.php/topic,82631.msg850171.html#msg850171
|
|
# CMD_QUEUE leeren wenn loginerror
|
|
# set loginwithcaptcha
|
|
# - FEATURE: Unterstützung A3R9S4ZZECZ6YL Fire Tab HD 10
|
|
# Unterstützung A3L0T0VL9A921N Fire Tab HD 8
|
|
# Unterstützung A2M4YX06LWP8WI Fire Tab 7
|
|
# Unterstützung A2E0SNTXJVT7WK Fire TV V1
|
|
# Unterstützung A2GFL5ZMWNE0PX Fire TV
|
|
# Unterstützung A12GXV8XMS007S Fire TV
|
|
# Unterstützung A3HF4YRA2L7XGC Fire TV Cube
|
|
# Unterstützung ADVBD696BHNV5 Fire TV Stick V1
|
|
# Unterstützung A2LWARUGJLBYEW Fire TV Stick V2
|
|
# Unterstützung AP1F6KUH00XPV ECHO Stereopaar
|
|
#
|
|
# 2018.10.25 v0.0.47
|
|
# - FEATURE: Unterstützung neuer Sonos Beam A15ERDAKK5HQQG
|
|
# - BUGFIX: browser_language default = de,en-US;q=0.7,en;q=0.3
|
|
# browser_useragent default = Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:62.0) Gecko/20100101 Firefox/62.0
|
|
#
|
|
# 2018.10.17 v0.0.46b
|
|
# - BUGFIX: Attribut intervalvoice 0=realtime bis 100 Sekunden
|
|
# - FEATURE: Reading "bluetooth_MAC-Adresse" zeigt Connected Status an (ECHO Device)
|
|
# Readings "config_address_from","config_address_to" und "config_address_between" (Account Device)
|
|
# Unterstützung neuer ECHO Show Gen2 AWZZ5CVHX2CD
|
|
# Unterstützung neuer ECHO Dot Gen3 A32DOYMUN6DTXA
|
|
#
|
|
# 2018.10.15 v0.0.45
|
|
# - FEATURE: Attribut intervalvoice 0=realtime bis 100 Sekunden
|
|
#
|
|
# 2018.10.10 v0.0.44
|
|
# - FEATURE: set alarm_off und alarm_on (Wecker und Musikwecker)
|
|
# set alarm_normal und alarm_repeat
|
|
# set routine_play (Abspielen und ausführen von Routinen)
|
|
# set info (Beliebig_Auf_Wiedersehen,Beliebig_Bestaetigung,Beliebig_Geburtstag,Beliebig_Guten_Morgen,Beliebig_Gute_Nacht,Beliebig_Ich_Bin_Zuhause,Beliebig_Kompliment,Erzaehle_Geschichte,Erzaehle_Was_Neues,Erzaehle_Witz,Kalender_Heute,Kalender_Morgen,Kalender_Naechstes_Ereignis,Nachrichten,Singe_Song,Verkehr,Wetter)
|
|
# set config_address_from config_address_to config_address_between (Einstellungen Verkehr)
|
|
# get address (Hier kann die Adresse gesucht werden für die set Befehle config_address_from config_address_to config_address_between)
|
|
# Unterstützung neuer ECHO Plus 2 A18O6U1UQFJ0XK
|
|
# Lautstärke sollte jetzt immer regelbar sein!
|
|
# - BUGFIX: Reading "currentTuneInID"
|
|
#
|
|
# 2018.10.08 v0.0.43a
|
|
# - CHANGE: set speak von Multiroom Geräten entfernt
|
|
# - BUGFIX: set Account Device
|
|
# get conversations
|
|
#
|
|
# 2018.09.03 v0.0.42
|
|
# - BUGFIX: Login
|
|
# - CHANGE: readingsBulkUpdateIfChanged to readingsBulkUpdate
|
|
#
|
|
# 2018.08.23 v0.0.41
|
|
# - BUGFIX: Login
|
|
#
|
|
# 2018.08.22 v0.0.40
|
|
# - FEATURE: set speak Natives TTS
|
|
# "set loginwithcaptcha"
|
|
# - CHANGE: browser_language default = de-DE
|
|
# browser_useragent default = Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:99.0) Gecko/20100101 Firefox/99.0
|
|
# Attribut "browser_save_data" wird jetzt auch am ECHO angezeigt
|
|
# - BUGFIX: 2FACode Authentifizierung
|
|
# "get actions" mit leeren Gerätennamen. Fehler im LOG
|
|
# Attribut disable
|
|
# Login
|
|
#
|
|
# 2018.06.08 v0.0.39
|
|
# - BUGFIX: get html_results
|
|
#
|
|
# 2018.06.07 v0.0.38
|
|
# - FEATURE: Anzeigen der Amazon Login Ergebnisse (get html_results)
|
|
# Attribut "browser_save_data"
|
|
#
|
|
# 2018.05.30 v0.0.37
|
|
# - BUGFIX: ReLogin bei "COOKIE ERROR"
|
|
# - FEATURE: Neues Attribut "browser_language"
|
|
#
|
|
# 2018.05.17 v0.0.36
|
|
# - CHANGE: Accept-Language: de,en-US
|
|
#
|
|
# 2018.05.17 v0.0.35
|
|
# - BUGFIX: Attribut "cookie"
|
|
#
|
|
# 2018.05.07 v0.0.34
|
|
# - BUGFIX: Attribut "intervalsettings"
|
|
# ReLogin bei "COOKIE ERROR"
|
|
#
|
|
# 2018.04.09 v0.0.33
|
|
# - CHANGE: get "help" zusätzliche Anleitung MP3 Streamserver & IceCast2
|
|
# TTS_Nachrichten werden mindestens mit der Laustärke von Reading "volume_alarm" abgespielt.
|
|
# Zwei Faktor Authentifizierung (set login2FACode) Danke Benutzer JoWiedmann https://forum.fhem.de/index.php/topic,82631.msg787815.html#msg787815
|
|
# Verstecken von Helper "CUSTOMER","COMMSID","COOKIE","DIRECTID","PASSWORD","USER","HTTP_CONNECTION" und "SERIAL"
|
|
# Verstecken von Readings "COOKIE","AWS_Access_Key" und "aws_secret_key"
|
|
# - FEATURE: Neues Reading "currentTuneInID"
|
|
# set "tts_translate" Übersetzung von der Webseite http://www.online-translator.com/ Reading="tts_translate_result"
|
|
# Neues Attribut "TTS_Translate_From"
|
|
# TTS Translate unterstützt folgende Sprachen:dutch,english,french,german,italian,japanese,korean,portuguese,russian,spanish und turkish
|
|
# TTS MP3 Länge ermitteln. Reading = "tts_lenght"
|
|
# TTS Nachrichte abspielen wenn schon ein TuneIn Sender läuft.
|
|
# - BUGFIX: Log Eintrag bei TTS & Attribut: "TTS_normalize" entfernt
|
|
# Name Attribut "TTS_Voice" WelshEnglish_Female_Gwyneth
|
|
# get settings
|
|
# Verzeichnis "echodevice" wurde nicht automatisch angelegt
|
|
#
|
|
# 2018.03.20 v0.0.32
|
|
# - FEATURE: Neues Attribut: "TTS_normalize" (only mp3 Outputformat!)
|
|
# - BUGFIX: remove sleep 0.5
|
|
#
|
|
# 2018-03-19 v0.0.31
|
|
# - BUGFIX: Amazone TTS Nachrichten < 3 Zeichen
|
|
# File "cache/pollyspeech.py", line 4, in <module>
|
|
# get "devices" https://forum.fhem.de/index.php/topic,82631.msg783487.html#msg783487
|
|
#
|
|
# 2018-03-18 v0.0.30
|
|
# - FEATURE: Text2Speech (TTS) inkl. Google und Amazon Stimmen
|
|
# Musik aus dem eigenen LAN abspielen
|
|
# Neue Attribute: ALLE "TTS_Voice" und "TTS_IgnorPlay"
|
|
# Neue Set Befehle: ACCOUNT "AWS_Access_Key","AWS_OutputFormat","AWS_Secret_Key","POM_Filename","POM_IPAddress","POM_TuneIn","TTS_Filename","TTS_IPAddress" und "TTS_TuneIn"
|
|
# Neue Set Befehle: Nur ECHO "tts", "playownmusic", "playownplaylist", "deleteownplaylist", und "saveownplaylist"
|
|
# - CHANGE: get "help"
|
|
# Reihenfolge get settings https://forum.fhem.de/index.php/topic,82631.msg781731.html#msg781731
|
|
#
|
|
# v0.0.29
|
|
# - FEATURE: Zwei Faktor Authentifizierung (set login2FACode) Danke Benutzer JoWiedmann https://forum.fhem.de/index.php/topic,82631.msg780848.html#msg780848
|
|
#
|
|
# v0.0.28
|
|
# - CHANGE: get "Conversations" auf nonBlocking
|
|
# get "tunein" auf nonBlocking & move to Echo Device & play link
|
|
# get "tracks" auf nonBlocking
|
|
# get "devices" auf nonBlocking
|
|
# set "autocreat_devices" auf nonBlocking
|
|
# httpversion = "1.1"
|
|
# - FEATURE: get "actions"
|
|
# get "primeplayeigene_albums"
|
|
# get "primeplayeigene_tracks"
|
|
# get "primeplayeigene_artists"
|
|
# get "primeplayeigeneplaylist"
|
|
# get "help"
|
|
# Multiroom add get settings & tunein
|
|
# - BUGFIX: primeplayeigene
|
|
#
|
|
# v0.0.27
|
|
# - BUGFIX: Not an ARRAY reference at ./FHEM/37_echodevice.pm line 1610
|
|
#
|
|
# v0.0.26
|
|
# - BUGFIX: read readings if amazon device is connected
|
|
#
|
|
# v0.0.25
|
|
# - BUGFIX: set reminder_normal
|
|
# Attribut disable
|
|
# no Internet connect
|
|
# - FEATURE: Attribut browser_useragent_random (Standard=1)
|
|
# Attribut intervallogin (Standard=60)
|
|
#
|
|
# v0.0.24
|
|
# - BUGFIX: Timer Readings
|
|
#
|
|
# v0.0.23
|
|
# - BUGFIX: Nested quantifiers in regex
|
|
# - CHANGE: Reading version
|
|
#
|
|
# v0.0.22
|
|
# - FEATURE: Attribut browser_useragent https://mwinkler.jimdo.com/smarthome/eigene-module/echodevice/#Attribute
|
|
#
|
|
# v0.0.21
|
|
# - CHANGE: Header
|
|
#
|
|
# v0.0.20
|
|
# - CHANGE: Cookie erstellen auf nonBlocking
|
|
# Cookie erstellen Timeout 10 sekunden
|
|
# - BUGFIX: div.
|
|
#
|
|
# v0.0.19
|
|
# - BUGFIX: Fehlt bei "get" der Punkt "conversations"
|
|
# Fehlt bei "set" der Punkt "textmessage"
|
|
#
|
|
# v0.0.18
|
|
# - FEATURE: autocreate Standard Raum "Amazon"
|
|
# - CHANGE: COOKIE wird nicht mehr erneuert!
|
|
#
|
|
# v0.0.17
|
|
# - FEATURE: refresh ECHO devices (Attribut autocreate_refresh)
|
|
# define icon to echo
|
|
# - CHANGE: Header
|
|
#
|
|
# v0.0.16
|
|
# - FEATURE: autocreate ECHO Spot
|
|
#
|
|
# v0.0.15
|
|
# - CHANGE: deletereading auf FHEM Command umgestellt
|
|
# - BUGFIX: MausicAlarm
|
|
#
|
|
# v0.0.14
|
|
# - FEATURE: autocreate ECHO Multiroom
|
|
# autocreate Sonos One
|
|
# autocreate Reverb
|
|
# - CHANGE: model im Klartext z.B. Echo Dot
|
|
#
|
|
# v0.0.13
|
|
# - BUGFIX: Cookie
|
|
#
|
|
# v0.0.12
|
|
# - FEATURE: Support Musicalarm
|
|
#
|
|
# v0.0.11.2
|
|
# - FEATURE: neue Readings timer_XX, reminder_X und alarm_xx
|
|
# neue Readings deviceAddress, timeZoneId
|
|
# Zeigt den Status für Mikrofon Reading = microphone
|
|
# Zeigt den Status ob der ECHO online ist. Reading = online
|
|
# - BUGFIX: Reading voice leer
|
|
# Div. Logeinträge wenn Variablen leer sind
|
|
# - CHANGE : Reading active entfernt
|
|
#
|
|
# v0.0.10
|
|
# - BUGFIX: Einkaufsliste und ToDo Liste (Fehler beim hinzufügen und entfernen von Einträgen)
|
|
#
|
|
# v0.0.9
|
|
# - BUGFIX: ECHO Devices Readings wurden nicht aktualisiert
|
|
#
|
|
# v0.0.8
|
|
# - FEATURE: Attribut tuneid_default (Hier kann ein Standard TuneIn Sender angegeben werden)
|
|
# set notifications_delete (löschen von Erinnerungen, Timer und Wecker)
|
|
# autocreate ECHO Show Geräte
|
|
# löschen und hinzufügen von Einkauflisten- und Task Einträgen
|
|
#
|
|
# v0.0.7
|
|
# - FEATURE: Interval Anpassung beim abspielen eines Songs
|
|
# - CHANGE: set reminder_normal ohne Datumsangabe (Reminder sofort ausgeführt))
|
|
#
|
|
# v0.0.6
|
|
# - CHANGE : Log Einträge reduziert
|
|
# Reading "voice" zum Echo Device verschoben
|
|
# - BUGFIX: set reminder_normal Text (Reminder sofort ausgeführt))
|
|
# ACCOUNT DEVICE macht jetzt die abfragen für wakeword, volume_alarm, dnd, active, bluetooth
|
|
# Standard Interval 60 Sekunden
|
|
#
|
|
# v0.0.5
|
|
# - CHANGE : set reminder_normal (durch weglassen der Uhrzeit wird der Reminder sofort ausgeführt)
|
|
# - FEATURE: Attribut reminder_delay (wird für reminder_normal benötigt. Standardwert = 10 sekunden)
|
|
#
|
|
# v0.0.4
|
|
# - CHANGE: set reminder vom ACCOUNT DEVICE entfernt
|
|
# set reminder zum Echo DEVICE hinzugefügt
|
|
# - FEATURE: set reminder_normal
|
|
# set reminder_repeat
|
|
#
|
|
# v0.0.3
|
|
# - BUGFIX: Anzeige set befehle primeplayeigene,primeplayeigeneplaylist,primeplaylist und primeplaysender
|
|
#
|
|
# v0.0.2
|
|
# - FEATURE: set primeplayeigene
|
|
# set primeplayeigeneplaylist
|
|
# set primeplaylist
|
|
# set primeplaysender
|
|
#
|
|
# v.0.0.1
|
|
# - BUGFIX: blocking restart fhem
|
|
# readings
|
|
#
|
|
# Copyright by Michael Winkler
|
|
# e-mail: michael.winkler at online.de
|
|
#
|
|
# This file is part of fhem.
|
|
#
|
|
# Fhem is free software: you can redistribute it andor modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation, either version 2 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# Fhem is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with fhem. If not, see <http://www.gnu.org/licenses/>.
|
|
#
|
|
# https://forum.fhem.de/index.php/topic,82631.0.html
|
|
#
|
|
##############################################################################
|
|
|
|
package main;
|
|
|
|
#use strict;
|
|
use Time::Local;
|
|
use Encode;
|
|
use Encode qw/from_to/;
|
|
use URI::Escape;
|
|
use Data::Dumper;
|
|
use JSON;
|
|
use utf8;
|
|
use Date::Parse;
|
|
use Time::Piece;
|
|
use lib ('./FHEM/lib', './lib');
|
|
use MP3::Info;
|
|
use MIME::Base64;
|
|
|
|
my $ModulVersion = "0.2.19";
|
|
my $AWSPythonVersion = "0.0.3";
|
|
my $NPMLoginTyp = "unbekannt";
|
|
my $QueueNumber = 0;
|
|
|
|
##############################################################################
|
|
sub echodevice_Initialize($) {
|
|
my ($hash) = @_;
|
|
my $name = $hash->{NAME};
|
|
|
|
$hash->{DefFn} = "echodevice_Define";
|
|
$hash->{UndefFn} = "echodevice_Undefine";
|
|
$hash->{NOTIFYDEV} = "global";
|
|
$hash->{NotifyFn} = "echodevice_Notify";
|
|
$hash->{GetFn} = "echodevice_Get";
|
|
$hash->{SetFn} = "echodevice_Set";
|
|
$hash->{AttrFn} = "echodevice_Attr";
|
|
$hash->{AttrList} = "disable:0,1 ".
|
|
"IODev ".
|
|
"TTS_Voice:AustralianEnglish_Female_Nicole,AustralianEnglish_Male_Russell,BrazilianPortuguese_Female_Vitoria,BrazilianPortuguese_Male_Ricardo,BritishEnglish_Female_Amy,BritishEnglish_Female_Emma,BritishEnglish_Male_Brian,CanadianFrench_Female_Chantal,CastilianSpanish_Female_Conchita,CastilianSpanish_Male_Enrique,Danish_Female_Naja,Danish_Male_Mads,Dutch_Female_Lotte,Dutch_Male_Ruben,French_Female_Celine,French_Male_Mathieu,German_Female_Google,German_Female_Marlene,German_Female_Vicki,German_Male_Hans,Icelandic_Female_Dora,Icelandic_Male_Karl,IndianEnglish_Female_Aditi,IndianEnglish_Female_Raveena,Italian_Female_Carla,Italian_Male_Giorgio,Japanese_Female_Mizuki,Japanese_Male_Takumi,Korean_Female_Seoyeon,Norwegian_Female_Liv,Polish_Female_Ewa,Polish_Female_Maja,Polish_Male_Jacek,Polish_Male_Jan,Portuguese_Female_Ines,Portuguese_Male_Cristiano,Romanian_Female_Carmen,Russian_Female_Tatyana,Russian_Male_Maxim,Swedish_Female_Astrid,Turkish_Female_Filiz,USEnglish_Female_Ivy,USEnglish_Female_Joanna,USEnglish_Female_Kendra,USEnglish_Female_Kimberly,USEnglish_Female_Salli,USEnglish_Male_Joey,USEnglish_Male_Justin,USEnglish_Male_Matthew,USSpanish_Female_Penelope,USSpanish_Male_Miguel,WelshEnglish_Female_Gwyneth,WelshEnglish_Male_Geraint ".
|
|
"TTS_IgnorPlay:0,1 ".
|
|
"TTS_normalize:slider,5,1,40 ".
|
|
"TTS_Translate_From:dutch,english,french,german,italian,japanese,korean,portuguese,russian,spanish,turkish ".
|
|
"intervalsettings ".
|
|
"intervallogin ".
|
|
"intervalvoice:slider,0,1,100 ".
|
|
"ignorevoicecommand ".
|
|
"speak_volume:slider,0,1,100 ".
|
|
"server ".
|
|
"cookie ".
|
|
"reminder_delay ".
|
|
"tunein_default ".
|
|
"autocreate_refresh:0,1 ".
|
|
"browser_useragent ".
|
|
"browser_language ".
|
|
"browser_save_data:0,1 ".
|
|
"browser_useragent_random:0,1 ".
|
|
"npm_proxy_port ".
|
|
"npm_proxy_ip ".
|
|
"npm_proxy_listen_ip ".
|
|
"npm_refresh_intervall ".
|
|
"npm_bin ".
|
|
"npm_bin_node ".
|
|
"fhem_home ".
|
|
$readingFnAttributes;
|
|
}
|
|
|
|
sub echodevice_Define($$$) {
|
|
my ($hash, $def) = @_;
|
|
my @a = split("[ \t][ \t]*", $def);
|
|
my ($found, $dummy);
|
|
|
|
return "syntax: define <name> echodevice <account> <password>" if(int(@a) != 4 );
|
|
my $name = $hash->{NAME};
|
|
|
|
$attr{$name}{server} = "layla.amazon.de" if( defined($attr{$name}) && !defined($attr{$name}{server}) );
|
|
|
|
RemoveInternalTimer($hash);
|
|
|
|
if($a[2] =~ /crypt/ || $a[2] =~ /@/ || $a[2] =~ /^\+/) {
|
|
$hash->{model} = "ACCOUNT";
|
|
|
|
my $user = $a[2];
|
|
my $pass = $a[3];
|
|
|
|
if ($user eq 'xxx@xxx.xx' and $pass eq "xxx") {
|
|
# Amazon NPM Login Modus
|
|
$hash->{LOGINMODE} = "NPM";
|
|
}
|
|
else {
|
|
# Amazon normal Login Modus
|
|
my $username = echodevice_encrypt($user);
|
|
my $password = echodevice_encrypt($pass);
|
|
$hash->{DEF} = "$username $password";
|
|
$hash->{helper}{".USER"} = $username;
|
|
$hash->{helper}{".PASSWORD"} = $password;
|
|
$hash->{LOGINMODE} = "NORMAL";
|
|
}
|
|
|
|
$hash->{helper}{TWOFA} = "";
|
|
$hash->{helper}{SERVER} = $attr{$name}{server};
|
|
$hash->{helper}{SERVER} = "layla.amazon.de" if(!defined($hash->{helper}{SERVER}));
|
|
$hash->{helper}{RUNLOGIN} = 0;
|
|
$hash->{helper}{".LOGINERROR"} = 0;
|
|
$modules{$hash->{TYPE}}{defptr}{"account"} = $hash;
|
|
|
|
$hash->{STATE} = "INITIALIZED";
|
|
|
|
# set default settings on first define
|
|
if ($init_done and $attr{$name}{icon} eq "" and $attr{$name}{room} eq "") {
|
|
$attr{$name}{icon} = 'echo';
|
|
$attr{$name}{room} = 'Amazon';
|
|
}
|
|
InternalTimer(gettimeofday() + 5 , "echodevice_FirstStart" , $hash, 0);
|
|
InternalTimer(gettimeofday() + 10 , "echodevice_GetSettings", $hash, 0);
|
|
}
|
|
else {
|
|
# Attribute
|
|
my $DeviceTyp = $a[2];
|
|
my $DeviceSerial = $a[3];
|
|
|
|
# Amazon ECHO Device
|
|
$hash->{STATE} = "INITIALIZED";
|
|
|
|
$hash->{model} = echodevice_getModel($DeviceTyp);#$a[2];
|
|
|
|
readingsBeginUpdate($hash);
|
|
readingsBulkUpdate($hash, "model", $hash->{model}, 1);
|
|
readingsBulkUpdate($hash, "state", "INITIALIZED", 1);
|
|
readingsEndUpdate($hash,1);
|
|
|
|
$hash->{helper}{DEVICETYPE} = $DeviceTyp;
|
|
$hash->{helper}{".SERIAL"} = $DeviceSerial;
|
|
$hash->{LOGINMODE} = "IODEV";
|
|
|
|
$modules{$hash->{TYPE}}{defptr}{$DeviceSerial} = $hash;
|
|
|
|
my $account = $modules{$hash->{TYPE}}{defptr}{"account"};
|
|
|
|
Log3 $name, 0, "[echodevice_Define] load ECHO Devicename=$name Devicetype=" . $DeviceTyp . " Devicemodel=" . $hash->{model};
|
|
|
|
$hash->{IODev} = $account;
|
|
$attr{$name}{IODev} = $account->{NAME} if( !defined($attr{$name}{IODev}) && $account);
|
|
|
|
if ($hash->{model} ne "THIRD_PARTY_AVS_MEDIA_DISPLAY") {
|
|
InternalTimer(gettimeofday() + 1, "echodevice_GetSettings", $hash, 0);
|
|
}
|
|
|
|
}
|
|
|
|
readingsSingleUpdate ($hash, "COOKIE_MODE", $hash->{LOGINMODE} ,0);
|
|
|
|
Log3 $name, 4, "[$name] [echodevice_Define] Getting auth URL return";
|
|
return undef;
|
|
}
|
|
|
|
sub echodevice_Undefine($$) {
|
|
my ($hash, $arg) = @_;
|
|
my $name = $hash->{NAME};
|
|
RemoveInternalTimer($hash);
|
|
delete( $modules{$hash->{TYPE}}{defptr}{"ACCOUNT"} ) if($hash->{model} eq "ACCOUNT");
|
|
delete( $modules{$hash->{TYPE}}{defptr}{$hash->{helper}{".SERIAL"}} ) if($hash->{model} ne "ACCOUNT");
|
|
return undef;
|
|
}
|
|
|
|
sub echodevice_Notify($$) {
|
|
my ($hash,$dev) = @_;
|
|
my $name = $hash->{NAME};
|
|
return if($dev->{NAME} ne "global");
|
|
return if(!grep(m/^INITIALIZED|REREADCFG$/, @{$dev->{CHANGED}}));
|
|
|
|
Log3 "echodevice", 4, "[$name] [echodevice_Notify] echodevice: notify reload";
|
|
|
|
return undef;
|
|
}
|
|
|
|
sub echodevice_Get($@) {
|
|
my ($hash, @a) = @_;
|
|
shift @a;
|
|
my $command = shift @a;
|
|
my $parameter = join(' ',@a);
|
|
my $name = $hash->{NAME};
|
|
|
|
my $usage = "Unknown argument $command, choose one of ";
|
|
|
|
return $usage if ($hash->{model} eq 'unbekannt');
|
|
return $usage if ($hash->{model} eq 'Sonos One');
|
|
return $usage if ($hash->{model} eq 'Sonos Beam');
|
|
|
|
if ($hash->{model} eq "Reverb") {
|
|
$usage .= "help:noArg " ;
|
|
}
|
|
elsif ($hash->{model} eq "ACCOUNT") {
|
|
$usage .= "settings:noArg devices:noArg actions:noArg tracks:noArg help:noArg conversations:noArg html_results:noArg address status:noArg customer-history-records:noArg";
|
|
}
|
|
else {
|
|
$usage .= "tunein settings:noArg primeplayeigene_albums primeplayeigene_tracks primeplayeigene_artists primeplayeigeneplaylist:noArg help:noArg html_results:noArg ";
|
|
}
|
|
|
|
#return "no get" if ($hash->{model} eq "Echo Multiroom");
|
|
return $usage if $command eq '?';
|
|
|
|
if ($command ne "help" || $command ne "help_results" || $command ne "status") {
|
|
}
|
|
elsif (IsDisabled($name)) {
|
|
$hash->{STATE} = "disabled";
|
|
readingsBeginUpdate($hash);
|
|
readingsBulkUpdate($hash, "state", "disabled", 1);
|
|
readingsEndUpdate($hash,1);
|
|
return "$name is disabled. Aborting...";
|
|
}
|
|
else {
|
|
}
|
|
|
|
my $ConnectState = "";
|
|
if($hash->{model} eq "ACCOUNT") {$ConnectState = $hash->{STATE}} else {$ConnectState = $hash->{IODev}->{STATE}}
|
|
|
|
if ($command eq "help") {
|
|
|
|
my $return = '<html><table align="" border="0" cellspacing="0" cellpadding="3" width="100%" height="100%" class="mceEditable"><tbody>';
|
|
$return .= "<p><strong>Hilfe:</strong></p>";
|
|
$return .= "<tr><td><strong>Dokumentation Modul  </strong></td><td><strong></strong></td></tr>";
|
|
$return .= "<tr><td>"."Beschreibung"." </td><td><a target=" . "_blank" . " href=" .'"' . 'https://mwinkler.jimdo.com/smarthome/eigene-module/echodevice' .'"'. "</a>https://mwinkler.jimdo.com/smarthome/eigene-module/echodevice</td></tr>";
|
|
$return .= "<tr><td>"."Readings"." </td><td><a target=" . "_blank" . " href=" .'"' . 'https://mwinkler.jimdo.com/smarthome/eigene-module/echodevice/#Readings' .'"'. "</a>https://mwinkler.jimdo.com/smarthome/eigene-module/echodevice/#Readings</td></tr>";
|
|
$return .= "<tr><td>"."Attribute"." </td><td><a target=" . "_blank" . " href=" .'"' . 'https://mwinkler.jimdo.com/smarthome/eigene-module/echodevice/#Attribute' .'"'. "</a>https://mwinkler.jimdo.com/smarthome/eigene-module/echodevice/#Attribute</td></tr>";
|
|
$return .= "<tr><td>"."Set"." </td><td><a target=" . "_blank" . " href=" .'"' . 'https://mwinkler.jimdo.com/smarthome/eigene-module/echodevice/#Set' .'"'. "</a>https://mwinkler.jimdo.com/smarthome/eigene-module/echodevice/#Set</td></tr>";
|
|
$return .= "<tr><td>"."Get"." </td><td><a target=" . "_blank" . " href=" .'"' . 'https://mwinkler.jimdo.com/smarthome/eigene-module/echodevice/#Get' .'"'. "</a>https://mwinkler.jimdo.com/smarthome/eigene-module/echodevice/#Get</td></tr>";
|
|
$return .= "<tr><td>"."Medieninformationen ermitteln"." </td><td><a target=" . "_blank" . " href=" .'"' . 'https://mwinkler.jimdo.com/smarthome/eigene-module/echodevice/#Medieninformationen_ermitteln' .'"'. "</a>https://mwinkler.jimdo.com/smarthome/eigene-module/echodevice/#Medieninformationen_ermitteln</td></tr>";
|
|
$return .= "<tr><td>"."Cookie_ermitteln"." </td><td><a target=" . "_blank" . " href=" .'"' . 'https://mwinkler.jimdo.com/smarthome/eigene-module/echodevice/#Cookie_ermitteln' .'"'. "</a>https://mwinkler.jimdo.com/smarthome/eigene-module/echodevice/#Cookie_ermitteln</td></tr>";
|
|
$return .= "<tr><td>"."Loginmit Captcha"." </td><td><a target=" . "_blank" . " href=" .'"' . 'https://mwinkler.jimdo.com/smarthome/eigene-module/echodevice/#Login_captcha' .'"'. "</a>https://mwinkler.jimdo.com/smarthome/eigene-module/echodevice/#Login_captcha</td></tr>";
|
|
$return .= "<tr><td>"."MP3 Playlisten"." </td><td><a target=" . "_blank" . " href=" .'"' . 'https://mwinkler.jimdo.com/smarthome/eigene-module/echodevice/#MP3_Playlisten' .'"'. "</a>https://mwinkler.jimdo.com/smarthome/eigene-module/echodevice/#MP3_Playlisten</td></tr>";
|
|
$return .= "<tr><td>"."Amazon Stimmen"." </td><td><a target=" . "_blank" . " href=" .'"' . 'https://mwinkler.jimdo.com/smarthome/eigene-module/echodevice/#AWS_Konfiguration' .'"'. "</a>https://mwinkler.jimdo.com/smarthome/eigene-module/echodevice/#AWS_Konfiguration</td></tr>";
|
|
$return .= "<tr><td> </td><td> </td></tr>";
|
|
|
|
$return .= "<tr><td><strong>Diverse Anleitungen</strong></td><td></td></tr>";
|
|
$return .= "<tr><td></td><td></td></tr>";
|
|
$return .= "<tr><td>"."Amazon ECHO TTS/POM"." </td><td><a target=" . "_blank" . " href=" .'"' . 'https://mwinkler.jimdo.com/smarthome/sonstiges/amazon-echo-tts-mp3s' .'"'. "</a>https://mwinkler.jimdo.com/smarthome/sonstiges/amazon-echo-tts-mp3s</td></tr>";
|
|
$return .= "<tr><td>"."MPD Streamserver"." </td><td><a target=" . "_blank" . " href=" .'"' . 'https://mwinkler.jimdo.com/smarthome/sonstiges/mpd-streamserver' .'"'. "</a>https://mwinkler.jimdo.com/smarthome/sonstiges/mpd-streamserver</td></tr>";
|
|
$return .= "<tr><td>"."MPD Web Frontend"." </td><td><a target=" . "_blank" . " href=" .'"' . 'https://mwinkler.jimdo.com/smarthome/sonstiges/mpd-webfrontend' .'"'. "</a>https://mwinkler.jimdo.com/smarthome/sonstiges/mpd-webfrontend</td></tr>";
|
|
$return .= "<tr><td>"."IceCast2"." </td><td><a target=" . "_blank" . " href=" .'"' . 'https://mwinkler.jimdo.com/smarthome/sonstiges/icecast2' .'"'. "</a>https://mwinkler.jimdo.com/smarthome/sonstiges/icecast2</td></tr>";
|
|
$return .= "<tr><td>"."NPM Login"." </td><td><a target=" . "_blank" . " href=" .'"' . 'https://mwinkler.jimdo.com/modul-echodevice-npm' .'"'. "</a>https://mwinkler.jimdo.com/modul-echodevice-npm</td></tr>";
|
|
$return .= "<tr><td> </td><td> </td></tr>";
|
|
|
|
$return .= "<tr><td><strong>Forum</strong></td><td></td></tr>";
|
|
$return .= "<tr><td></td><td></td></tr>";
|
|
$return .= "<tr><td>"."Forums Thread"." </td><td><a target=" . "_blank" . " href=" .'"' . 'https://forum.fhem.de/index.php/topic,82631.0.html' .'"'. "</a>https://forum.fhem.de/index.php/topic,82631.0.html</td></tr>";
|
|
$return .= "<tr><td> </td><td> </td></tr>";
|
|
|
|
$return .= "</tbody></table></html>";
|
|
|
|
return $return;
|
|
}
|
|
|
|
if ($command eq "html_results") {
|
|
|
|
my $timestamp ;
|
|
my $epoch_timestamp ;
|
|
my $return = '<html><table align="" border="0" cellspacing="0" cellpadding="3" width="100%" height="100%" class="mceEditable"><tbody>';
|
|
$return .= "<p><strong>Amazon HTML Results:</strong></p>";
|
|
$return .= "<tr><td><strong>Datum  </strong></td><td><strong>HTML Result Dateiname</strong></td></tr>";
|
|
|
|
opendir(DH, $FW_dir . "/echodevice/results");
|
|
my @files = readdir(DH);
|
|
closedir(DH);
|
|
|
|
my @filessorted = sort @files;
|
|
|
|
foreach my $file (@filessorted){
|
|
# skip . and ..
|
|
next if($file =~ /^\.$/);
|
|
next if($file =~ /^\.\.$/);
|
|
|
|
# Datum
|
|
$epoch_timestamp = 0 ;
|
|
$timestamp = 0 ;
|
|
if ((-e $FW_dir . "/echodevice/results/" . $file)) {
|
|
$epoch_timestamp = (stat($FW_dir . "/echodevice/results/" . $file))[9];
|
|
$timestamp = localtime($epoch_timestamp);
|
|
}
|
|
|
|
if ($hash->{model} eq "ACCOUNT" || index($file, $name) == 0 ) {
|
|
# $file is the file used on this iteration of the loop
|
|
$return .= "<tr><td>".$timestamp." </td><td><a target=" . "_blank" . " href=" .'"' . $FW_ME . '/echodevice/results/' . $file .'"'. "</a>" . $file . "</td></tr>";
|
|
}
|
|
}
|
|
|
|
$return .= "<tr><td> </td><td> </td></tr>";
|
|
$return .= "</tbody></table></html>";
|
|
|
|
return $return;
|
|
}
|
|
|
|
if ($command eq "status") {
|
|
|
|
my $return = '<html>';
|
|
|
|
#Allgemeine Informationen
|
|
$return .= '<table align="" border="0" cellspacing="0" cellpadding="3" width="100%" height="100%" class="mceEditable"><tbody>';
|
|
$return .= "<p><strong>Modul Infos:</strong></p>";
|
|
$return .= "<tr><td><strong>Beschreibung  </strong></td><td><strong>Bereich  </strong></td><td><strong>Wert</strong></td></tr>";
|
|
$return .= "<tr><td>STATE </td><td>Reading</td><td>" . ReadingsVal( $name, "state", "unbekannt") . "</td></tr>";
|
|
$return .= "<tr><td>Version </td><td>Reading</td><td>" . ReadingsVal( $name, "version", "unbekannt") . "</td></tr>";
|
|
$return .= "<tr><td>NPM Cookie Version </td><td>Reading</td><td>" . echodevice_NPMCheckVersion($hash,"cache/alexa-cookie/node_modules/alexa-cookie2/package.json","get status") . "</td></tr>";
|
|
$return .= "<tr><td>COOKIE_STATE </td><td>Reading</td><td>" . ReadingsVal( $name, "COOKIE_STATE", "unbekannt") . "</td></tr>";
|
|
$return .= "<tr><td>COOKIE_TYPE </td><td>Reading</td><td>" . ReadingsVal( $name, "COOKIE_TYPE", "unbekannt") . "</td></tr>";
|
|
$return .= "<tr><td>COOKIE_MODE </td><td>Reading</td><td>" . $hash->{LOGINMODE} . "</td></tr>";
|
|
$return .= "<tr><td>amazon_refreshtoken </td><td>Reading</td><td>" . ReadingsVal( $name, "amazon_refreshtoken", "unbekannt") . "</td></tr>";
|
|
#$return .= "<tr><td>.COOKIE </td><td>Reading</td><td>123</td></tr>";
|
|
|
|
# Attribute auslesen
|
|
while ( my ($key, $value) = each %{$attr{$name}} ) {
|
|
$return .= "<tr><td>" . $key . " </td><td>Attribut</td><td>" . $value . "</td></tr>";
|
|
}
|
|
|
|
$return .= "<tr><td> </td><td> </td><td> </td></tr></tbody></table>";
|
|
|
|
#Allgemeine Cookie Infos
|
|
$return .= '<table align="" border="0" cellspacing="0" cellpadding="3" width="100%" height="100%" class="mceEditable"><tbody>';
|
|
$return .= "<p><strong>Amazon Cookie:</strong></p>";
|
|
$return .= "<tr><td><strong>Beschreibung  </strong></td><td><strong>Bereich  </strong></td><td><strong>Wert</strong></td></tr>";
|
|
$return .= "<tr><td>.COOKIE </td><td>Reading</td><td>" . substr(ReadingsVal( $name, ".COOKIE", "unbekannt" ), 0, 20) . "....</td></tr>";
|
|
$return .= "<tr><td>COOKIE_STATE </td><td>Reading</td><td>" . ReadingsVal( $name, "COOKIE_STATE", "unbekannt") . "</td></tr>";
|
|
$return .= "<tr><td>COOKIE_TYPE </td><td>Reading</td><td>" . ReadingsVal( $name, "COOKIE_TYPE", "unbekannt") . "</td></tr>";
|
|
$return .= "<tr><td>amazon_refreshtoken </td><td>Reading</td><td>" . ReadingsVal( $name, "amazon_refreshtoken", "unbekannt") . "</td></tr>";
|
|
$return .= "<tr><td>.COOKIE </td><td>Helper</td><td>" . substr($hash->{helper}{".COOKIE"}, 0, 20) . "....</td></tr>";
|
|
$return .= "<tr><td>.COMMSID </td><td>Helper</td><td>" . substr($hash->{helper}{".COMMSID"}, 0, 20) . "....</td></tr>";
|
|
$return .= "<tr><td>.CSRF </td><td>Helper</td><td>" . substr($hash->{helper}{".CSRF"}, 0, 3) . "....</td></tr>";
|
|
$return .= "<tr><td>.DIRECTID </td><td>Helper</td><td>" . substr($hash->{helper}{".DIRECTID"}, 0, 20) . "....</td></tr>";
|
|
$return .= "<tr><td>RUNLOGIN </td><td>Helper</td><td>" . $hash->{helper}{RUNLOGIN} . "</td></tr>";
|
|
$return .= "<tr><td>RUNNING_REQUEST </td><td>Helper</td><td>" . $hash->{helper}{RUNNING_REQUEST} . "</td></tr>";
|
|
$return .= "<tr><td>LOGINERROR </td><td>Helper</td><td>" . $hash->{helper}{".LOGINERROR"} . "</td></tr>";
|
|
$return .= "<tr><td>FHEM_HOME </td><td>Attribut</td><td>" . AttrVal($name,"fhem_home","/opt/fhem") . "</td></tr>";
|
|
$return .= "<tr><td> </td><td> </td><td> </td></tr></tbody></table>";
|
|
|
|
$return .= "</html>";
|
|
|
|
return $return;
|
|
|
|
}
|
|
|
|
if ($ConnectState ne "connected") {
|
|
return "$name is not connected. Aborting...";
|
|
}
|
|
|
|
if ($command eq "settings") {
|
|
echodevice_GetSettings($hash);
|
|
return "OK" if($hash->{model} ne "ACCOUNT");
|
|
}
|
|
|
|
elsif($command eq "actions") {
|
|
echodevice_SendCommand($hash,"getcards","");
|
|
}
|
|
|
|
elsif($command eq "devices") {
|
|
echodevice_SendCommand($hash,"devices","");
|
|
}
|
|
|
|
elsif($command eq "conversations") {
|
|
echodevice_SendCommand($hash,"conversations","");
|
|
}
|
|
|
|
elsif($command eq "tunein") {
|
|
echodevice_SendCommand($hash,"searchtunein",$parameter);
|
|
}
|
|
|
|
elsif($command eq "tracks") {
|
|
echodevice_SendCommand($hash,"searchtracks",$parameter);
|
|
}
|
|
|
|
elsif($command eq "primeplayeigene_albums") {
|
|
echodevice_SendCommand($hash,"primeplayeigene_Albums",$parameter);
|
|
}
|
|
|
|
elsif($command eq "primeplayeigene_tracks") {
|
|
echodevice_SendCommand($hash,"primeplayeigene_Tracks",$parameter);
|
|
}
|
|
|
|
elsif($command eq "primeplayeigene_artists") {
|
|
echodevice_SendCommand($hash,"primeplayeigene_Artists",$parameter);
|
|
}
|
|
|
|
elsif($command eq "primeplayeigeneplaylist") {
|
|
echodevice_SendCommand($hash,"getprimeplayeigeneplaylist","");
|
|
}
|
|
|
|
elsif($command eq "address") {
|
|
echodevice_SendCommand($hash,"address",$parameter);
|
|
}
|
|
|
|
elsif($command eq "customer-history-records") {
|
|
echodevice_SendCommand($hash,"customer-history-records",$parameter);
|
|
}
|
|
|
|
return undef;
|
|
}
|
|
|
|
sub echodevice_Set($@) {
|
|
my ($hash, @a) = @_;
|
|
|
|
shift @a;
|
|
my $command = shift @a;
|
|
my $parameter = join(' ',@a);
|
|
my $name = $hash->{NAME};
|
|
my $ShoppingListe = ReadingsVal($name, "list_SHOPPING_ITEM", "");
|
|
my $TaskListe = ReadingsVal($name, "list_TASK", "");
|
|
my $tracks = AttrVal($name, 'tracks', AttrVal(AttrVal($name, 'IODev', $name), 'tracks', undef));
|
|
my $usage = 'Unknown argument $command, choose one of ';
|
|
|
|
return $usage if ($hash->{model} eq 'unbekannt');
|
|
|
|
if($hash->{model} eq "ACCOUNT") {
|
|
$usage .= 'autocreate_devices:noArg item_shopping_add item_task_add ';
|
|
$usage .= 'AWS_Access_Key AWS_Secret_Key TTS_IPAddress TTS_Filename TTS_TuneIn POM_TuneIn POM_IPAddress POM_Filename AWS_OutputFormat:mp3,ogg_vorbis,pcm textmessage ';# if(defined($hash->{helper}{".COMMSID"}));
|
|
$usage .= 'config_address_from config_address_to config_address_between mobilmessage ';
|
|
$usage .= 'login:noArg loginwithcaptcha login2FACode ' if($hash->{LOGINMODE} eq "NORMAL");
|
|
$usage .= 'NPM_install:noArg NPM_login:new,refresh ' if($hash->{LOGINMODE} eq "NPM");
|
|
|
|
# Einkaufsliste
|
|
my $ShoppingListe = ReadingsVal($name, "list_SHOPPING_ITEM", "");
|
|
my $TaskListe = ReadingsVal($name, "list_TASK", "");
|
|
$ShoppingListe =~ s/ / /g;
|
|
$TaskListe =~ s/ / /g;
|
|
$usage .= ' item_shopping_delete:'.$ShoppingListe;
|
|
$usage .= ' item_task_delete:'.$TaskListe;
|
|
}
|
|
|
|
elsif ($hash->{model} eq "Echo Multiroom" || $hash->{model} eq "Sonos Display" || $hash->{model} eq "Echo Stereopaar") {
|
|
$usage .= 'volume:slider,0,1,100 play:noArg pause:noArg next:noArg previous:noArg forward:noArg rewind:noArg shuffle:on,off repeat:on,off ';
|
|
$usage .= 'tunein primeplaylist primeplaysender primeplayeigene primeplayeigeneplaylist tts tts_translate:textField-long playownmusic:textField-long saveownplaylist:textField-long ';
|
|
|
|
if(defined($tracks)) {
|
|
$tracks =~ s/ /_/g;
|
|
$tracks =~ s/:/,/g;
|
|
$usage .= 'track:'.$tracks.' ';
|
|
}
|
|
else {
|
|
$usage .= 'track ';
|
|
}
|
|
# startownplaylist
|
|
$usage .= echodevice_GetOwnPlaylist($hash);
|
|
}
|
|
|
|
else {
|
|
|
|
$usage .= 'volume:slider,0,1,100 play:noArg pause:noArg next:noArg previous:noArg forward:noArg rewind:noArg shuffle:on,off repeat:on,off dnd:on,off volume_alarm:slider,0,1,100 ';
|
|
$usage .= 'info:Beliebig_Auf_Wiedersehen,Beliebig_Bestaetigung,Beliebig_Geburtstag,Beliebig_Guten_Morgen,Beliebig_Gute_Nacht,Beliebig_Ich_Bin_Zuhause,Beliebig_Kompliment,Erzaehle_Geschichte,Erzaehle_Was_Neues,Erzaehle_Witz,Kalender_Heute,Kalender_Morgen,Kalender_Naechstes_Ereignis,Nachrichten,Singe_Song,Verkehr,Wetter sounds:glocken,kirchenglocke,summer,tuerklingel_1,tuerklingel_2,tuerklingel_3,jubelnde_menschenmenge,publikumsapplaus,flugzeug,katastrophenalarm,motoren_an,schilde_hoch,sirenen,zappen,boing_1,boing_2,kamera,lufthupe,quitschende_tuer,tickende_uhr,trompete,hahn,hundegebell,katzenmauzen,loewengebruell,wolfsgeheul,gruselig_quitschende_tuer,weihnachtsglocken tunein primeplaylist primeplaysender primeplayeigene primeplayeigeneplaylist alarm_normal alarm_repeat reminder_normal reminder_repeat speak speak_ssml tts tts_translate:textField-long playownmusic:textField-long saveownplaylist:textField-long ';
|
|
$usage .= 'textcommand ';
|
|
|
|
$usage .= 'homescreen ' if ($hash->{model} eq "Echo Show 5" || $hash->{model} eq "Echo Show 8" || $hash->{model} eq "Echo Show" || $hash->{model} eq "Echo Show Gen2" || $hash->{model} eq "Echo Show Gen3");
|
|
|
|
# startownplaylist
|
|
$usage .= echodevice_GetOwnPlaylist($hash);
|
|
|
|
if(defined($tracks)) {
|
|
$tracks =~ s/ /_/g;
|
|
$tracks =~ s/:/,/g;
|
|
$usage .= 'track:'.$tracks.' ';
|
|
}
|
|
else {
|
|
$usage .= 'track ';
|
|
}
|
|
$usage .= 'bluetooth_connect:'.$hash->{helper}{bluetooth}.' bluetooth_disconnect:'.$hash->{helper}{bluetooth}.' ' if(defined($hash->{helper}{bluetooth}));
|
|
|
|
# Routinen auslesen
|
|
my $BehaviorName ;
|
|
my @Behaviors = ();
|
|
foreach my $BehaviorID (sort keys %{$hash->{IODev}->{helper}{"getbehavior"}}) {
|
|
#Log3 $name, 3, "[DEBUG] BehaviorID = " . $BehaviorID;
|
|
$BehaviorName = $hash->{IODev}->{helper}{"getbehavior"}{$BehaviorID}{triggers}[0]{payload}{utterance};
|
|
$BehaviorName =~ s/ /_/g;
|
|
#Log3 $name, 3, "[DEBUG] Name = " . $BehaviorName;
|
|
push @Behaviors, $BehaviorName . "@" . $BehaviorID;
|
|
}
|
|
|
|
# Reminder/Alarm auslesen
|
|
my @ncstrings = ();
|
|
my @Alarms = ();
|
|
|
|
my $NotifiResult ;
|
|
my $NotifiType ;
|
|
foreach my $NotifiID (sort keys %{$hash->{IODev}->{helper}{"notifications"}{$hash->{helper}{".SERIAL"}}}) {
|
|
if ($hash->{IODev}->{helper}{"notifications"}{$hash->{helper}{".SERIAL"}}{$NotifiID} ne "") {
|
|
$NotifiResult = $hash->{IODev}->{helper}{"notifications"}{$hash->{helper}{".SERIAL"}}{$NotifiID} ;
|
|
$NotifiType = (split("_",$NotifiResult))[0];
|
|
$NotifiResult =~s/ /_/g;
|
|
$NotifiResult =~s/,/_/g;
|
|
$NotifiResult =~s/@/_/g;
|
|
$NotifiResult .= "@" . $NotifiID ;
|
|
if (lc($NotifiType) eq "alarm" || lc($NotifiType) eq "musicalarm") {
|
|
push @Alarms, $NotifiResult;
|
|
}
|
|
push @ncstrings, $NotifiResult;
|
|
}
|
|
}
|
|
|
|
if (@Alarms) {
|
|
@Alarms = sort @Alarms;
|
|
$usage .= 'alarm_off:' . join(",", @Alarms). ' ';
|
|
$usage .= 'alarm_on:' . join(",", @Alarms). ' ';
|
|
}
|
|
|
|
if (@ncstrings) {
|
|
@ncstrings = sort @ncstrings;
|
|
$usage .= 'notifications_delete:' . join(",", @ncstrings). ' ';
|
|
}
|
|
|
|
if (@Behaviors) {
|
|
@Behaviors = sort @Behaviors;
|
|
$usage .= 'routine_play:' . join(",", @Behaviors). ' ';
|
|
}
|
|
}
|
|
|
|
return $usage if $command eq '?';
|
|
|
|
#return echodevice_Login($hash) if($command eq "login");
|
|
return echodevice_SendLoginCommand($hash,"cookielogin1","") if($command eq "login");
|
|
|
|
if($command eq "NPM_install"){
|
|
return echodevice_NPMInstall($hash);
|
|
}
|
|
|
|
if($command eq "NPM_login"){
|
|
return echodevice_getHelpText("no arg") if ( !defined($a[0]) );
|
|
return echodevice_NPMLoginNew($hash) if ($a[0] eq "new") ;
|
|
return echodevice_NPMLoginRefresh($hash) if ($a[0] eq "refresh");
|
|
}
|
|
|
|
if($command eq "loginwithcaptcha"){
|
|
return echodevice_getHelpText("HTML Result file does exits. Pleas activate the attribut browser_save_data") if ((!-e $FW_dir . "/echodevice/results/". $name . "_cookielogin4.html"));
|
|
return echodevice_getHelpText("no arg") if ( !defined($a[0]) );
|
|
$hash->{helper}{CAPTCHA} = $a[0];
|
|
echodevice_SendLoginCommand($hash,"cookielogin4captcha","");
|
|
return;
|
|
}
|
|
|
|
if($command eq "login2FACode"){
|
|
return echodevice_getHelpText("no arg") if ( !defined($a[0]) );
|
|
$hash->{helper}{TWOFA} = $a[0];
|
|
echodevice_SendLoginCommand($hash,"cookielogin4","");
|
|
return;
|
|
}
|
|
|
|
if(IsDisabled($name)) {
|
|
$hash->{STATE} = "disabled";
|
|
readingsBeginUpdate($hash);
|
|
readingsBulkUpdate($hash, "state", "disabled", 1);
|
|
readingsEndUpdate($hash,1);
|
|
return "$name is disabled. Aborting...";
|
|
}
|
|
|
|
my $ConnectState = "";
|
|
if($hash->{model} eq "ACCOUNT") {$ConnectState = $hash->{STATE}} else {$ConnectState = $hash->{IODev}->{STATE}}
|
|
|
|
if ($ConnectState ne "connected" && $command ne "login" && $command ne "login2FACode") {
|
|
return "$name is not connected. Aborting...";
|
|
}
|
|
|
|
# Allgemeine Einstellungen
|
|
if($command eq "bluetooth_connect"){
|
|
return echodevice_getHelpText("no arg") if ( !defined($a[0]) );
|
|
|
|
my @parameters = split("/",$a[0]);
|
|
$parameters[0] =~ s/-/:/g;
|
|
|
|
my $json = encode_json( { bluetoothDeviceAddress => $parameters[0] } );
|
|
|
|
echodevice_SendCommand($hash,"bluetooth_connect",$json);
|
|
}
|
|
|
|
elsif($command eq "autocreate_devices") {
|
|
readingsSingleUpdate ( $hash, "autocreate_devices", "running", 0 );
|
|
echodevice_SendCommand($hash,"autocreate_devices","");
|
|
}
|
|
|
|
elsif($command eq "bluetooth_disconnect"){
|
|
return echodevice_getHelpText("no arg") if ( !defined($a[0]) );
|
|
|
|
my @parameters = split("/",$a[0]);
|
|
$parameters[0] =~ s/-/:/g;
|
|
|
|
my $json = encode_json( { bluetoothDeviceAddress => $parameters[0] } );
|
|
|
|
echodevice_SendCommand($hash,"bluetooth_disconnect",$json);
|
|
}
|
|
|
|
elsif($command eq "dnd"){
|
|
return echodevice_getHelpText("no arg") if ( !defined($a[0]) );
|
|
|
|
my $json = encode_json( { deviceSerialNumber => $hash->{helper}{".SERIAL"},
|
|
deviceType => $hash->{helper}{DEVICETYPE},
|
|
enabled => ($a[0] eq "on")?"true":"false" } );
|
|
|
|
$json =~s/\"true\"/true/g;
|
|
$json =~s/\"false\"/false/g;
|
|
|
|
echodevice_SendCommand($hash,"dnd",$json);
|
|
}
|
|
|
|
elsif($command eq "volume") {
|
|
return echodevice_getHelpText("no arg") if ( !defined( $a[0] ) );
|
|
|
|
# Voluemeangabe prüfen
|
|
if ($a[0] >= 0 && $a[0] <= 100 ) {
|
|
readingsBeginUpdate($hash);
|
|
readingsBulkUpdate($hash, "volume", $a[0], 1);
|
|
readingsEndUpdate($hash,1);
|
|
echodevice_SendCommand($hash,"volume",$a[0]);
|
|
}
|
|
else {
|
|
return echodevice_getHelpText("Argument $a[0] does not seem to be a valid integer between 0 and 100");
|
|
}
|
|
}
|
|
|
|
elsif($command eq "volume_alarm") {
|
|
return echodevice_getHelpText("no arg") if ( !defined( $a[0] ) );
|
|
# Voluemeangabe prüfen
|
|
if ($a[0] >= 0 && $a[0] <= 100 ) {
|
|
|
|
my $json = encode_json( { deviceSerialNumber => $hash->{helper}{".SERIAL"},
|
|
deviceType => $hash->{helper}{DEVICETYPE},
|
|
softwareVersion => $hash->{helper}{VERSION},
|
|
volumeLevel => int($a[0]) } );
|
|
readingsBeginUpdate($hash);
|
|
readingsBulkUpdate($hash, "volume_alarm", $a[0], 1);
|
|
readingsEndUpdate($hash,1);
|
|
echodevice_SendCommand($hash,"volume_alarm",$json);
|
|
}
|
|
else {
|
|
return echodevice_getHelpText("Argument $a[0] does not seem to be a valid integer between 0 and 100");
|
|
}
|
|
}
|
|
|
|
elsif($command eq "config_address_from" || $command eq "config_address_to" || $command eq "config_address_between") {
|
|
echodevice_SendCommand($hash,$command,$parameter);
|
|
}
|
|
|
|
# Listen
|
|
elsif($command eq "item_task_delete" ) {
|
|
return echodevice_getHelpText("no arg") if ( !defined($parameter) );
|
|
echodevice_SendCommand($hash,"item_task_delete",$parameter)
|
|
}
|
|
|
|
elsif($command eq "item_shopping_delete" ) {
|
|
return echodevice_getHelpText("no arg") if ( !defined($parameter) );
|
|
echodevice_SendCommand($hash,"item_shopping_delete",$parameter)
|
|
}
|
|
|
|
elsif($command eq "item_task_add" ) {
|
|
return echodevice_getHelpText("no arg") if ( !defined($a[0]) );
|
|
|
|
my $json = JSON->new->utf8(1)->encode( { 'createdDateTime' => int(time),
|
|
'listId' => $hash->{helper}{TO_DO_LIST_ID},
|
|
'completed' => "false",
|
|
'value' => decode_utf8($parameter) } );
|
|
|
|
$json =~ s/\"true\"/true/g;
|
|
$json =~ s/\"false\"/false/g;
|
|
|
|
$parameter =~ s/ /_/g;
|
|
|
|
readingsBeginUpdate($hash);
|
|
if ($TaskListe eq "") {readingsBulkUpdate($hash, "list_TASK", $parameter , 1);}
|
|
else {readingsBulkUpdate($hash, "list_TASK", $parameter . "," . $TaskListe , 1); }
|
|
readingsEndUpdate($hash,1);
|
|
|
|
echodevice_SendCommand($hash,"item_task_add",$json)
|
|
}
|
|
|
|
elsif($command eq "item_shopping_add" ) {
|
|
return echodevice_getHelpText("no arg") if ( !defined($parameter) );
|
|
|
|
my $json = JSON->new->utf8(1)->encode( { 'createdDateTime' => int(time),
|
|
'listId' => $hash->{helper}{SHOPPING_LIST_ID},
|
|
'completed' => "false",
|
|
'value' => decode_utf8($parameter) } );
|
|
|
|
$json =~ s/\"true\"/true/g;
|
|
$json =~ s/\"false\"/false/g;
|
|
|
|
$parameter =~ s/ /_/g;
|
|
|
|
readingsBeginUpdate($hash);
|
|
if ($ShoppingListe eq "") {readingsBulkUpdate($hash, "list_SHOPPING_ITEM", $parameter , 1);}
|
|
else {readingsBulkUpdate($hash, "list_SHOPPING_ITEM", $parameter . "," . $ShoppingListe , 1); }
|
|
readingsEndUpdate($hash,1);
|
|
|
|
echodevice_SendCommand($hash,"item_shopping_add",$json)
|
|
}
|
|
|
|
# Erinnerungen / Timer / Wecker
|
|
elsif($command eq "reminder_normal" || $command eq "alarm_normal") {
|
|
return echodevice_getHelpText("no arg") if ( !defined($a[0]) );
|
|
|
|
my $reminder_delay = AttrVal($name, "reminder_delay", 10);
|
|
my $ReminderText ;
|
|
my $ReminderDate ;
|
|
|
|
my $Type;
|
|
|
|
$Type = "Reminder" if ($command eq "reminder_normal");
|
|
$Type = "Alarm" if ($command eq "alarm_normal");
|
|
|
|
# Reading festhalten
|
|
readingsBeginUpdate($hash);
|
|
readingsBulkUpdate($hash, lc($Type) . "_normal", join(' ',@a), 1);
|
|
readingsEndUpdate($hash,1);
|
|
|
|
my ($Tsec, $Tmin, $Thour, $Tmday, $Tmon, $Tyear, $Twday, $Tyday, $Tisdst) = localtime();
|
|
|
|
# Prüfen es sich um ein Datum handelt
|
|
if (index($a[0], "-") != -1){
|
|
$ReminderDate = str2time($a[0] . " " . $a[1]);
|
|
splice @a, 0, 1;
|
|
splice @a, 0, 1;
|
|
$ReminderText = join(' ',@a);
|
|
|
|
}
|
|
elsif (index($a[0], ":") != -1){
|
|
$ReminderDate = str2time(sprintf("%04d",$Tyear+1900)."-".sprintf("%02d",$Tmon+1)."-".sprintf("%02d",$Tmday)." ". $a[0]);
|
|
splice @a, 0, 1;
|
|
$ReminderText = join(' ',@a);
|
|
}
|
|
else {
|
|
$ReminderText = $parameter;
|
|
$ReminderDate = time + $reminder_delay;
|
|
}
|
|
|
|
my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime($ReminderDate);
|
|
|
|
my $json = encode_json( { alarmTime => $ReminderDate*1000,
|
|
createdDate => int(time)*1000,
|
|
deviceSerialNumber => $hash->{helper}{".SERIAL"},
|
|
deviceType => $hash->{helper}{DEVICETYPE},
|
|
id => "create".$Type,
|
|
isRecurring => "false",
|
|
isSaveInFlight => "true",
|
|
originalDate => sprintf("%04d",$year+1900)."-".sprintf("%02d",$mon+1)."-".sprintf("%02d",$mday),
|
|
originalTime => sprintf("%02d",$hour).":".sprintf("%02d",$min).":".sprintf("%02d",$sec).".000",
|
|
reminderLabel => decode_utf8($ReminderText),
|
|
status => "ON",
|
|
type => $Type});
|
|
|
|
$json =~ s/\"true\"/true/g;
|
|
$json =~ s/\"false\"/false/g;
|
|
|
|
echodevice_SendCommand($hash,"reminderitem",$json);
|
|
|
|
}
|
|
|
|
elsif($command eq "reminder_repeat" || $command eq "alarm_repeat") {
|
|
return echodevice_getHelpText("There are some arguments missing. [Zeitangabe] [Wiederholumgsmode] nachrichtentext ") if ( !defined($a[0]) );
|
|
|
|
my $Type;
|
|
|
|
$Type = "Reminder" if ($command eq "reminder_repeat");
|
|
$Type = "Alarm" if ($command eq "alarm_repeat");
|
|
|
|
# Reading festhalten
|
|
readingsBeginUpdate($hash);
|
|
readingsBulkUpdate($hash, lc($Type)."_repeat", join(' ',@a), 1);
|
|
readingsEndUpdate($hash,1);
|
|
|
|
# Vorbereitungen
|
|
my @parameters = split(":",$a[0]);
|
|
my $ReminderRecc = $a[1];
|
|
splice @a, 0, 1;
|
|
splice @a, 0, 1;
|
|
my $ReminderText = join(' ',@a);
|
|
my $recurringPattern = "";
|
|
|
|
if ($ReminderRecc eq "1") {$recurringPattern = "P1D";}
|
|
elsif ($ReminderRecc eq "2") {$recurringPattern = "XXXX-WD";}
|
|
elsif ($ReminderRecc eq "3") {$recurringPattern = "XXXX-WE";}
|
|
elsif ($ReminderRecc eq "4") {$recurringPattern = "XXXX-WXX-1";}
|
|
elsif ($ReminderRecc eq "5") {$recurringPattern = "XXXX-WXX-2";}
|
|
elsif ($ReminderRecc eq "6") {$recurringPattern = "XXXX-WXX-3";}
|
|
elsif ($ReminderRecc eq "7") {$recurringPattern = "XXXX-WXX-4";}
|
|
elsif ($ReminderRecc eq "8") {$recurringPattern = "XXXX-WXX-5";}
|
|
elsif ($ReminderRecc eq "9") {$recurringPattern = "XXXX-WXX-6";}
|
|
elsif ($ReminderRecc eq "10") {$recurringPattern = "XXXX-WXX-7";}
|
|
else {$recurringPattern = "P1D";}
|
|
|
|
my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime();
|
|
|
|
my $json = encode_json( { alarmTime => int(time)*1000,
|
|
createdDate => int(time)*1000 ,
|
|
deviceSerialNumber => $hash->{helper}{".SERIAL"},
|
|
deviceType => $hash->{helper}{DEVICETYPE},
|
|
id => "create".$Type,
|
|
isRecurring => "true",
|
|
isSaveInFlight => "true",
|
|
recurringPattern => $recurringPattern,
|
|
originalDate => sprintf("%04d",$year+1900)."-".sprintf("%02d",$mon+1)."-".sprintf("%02d",$mday),
|
|
originalTime => sprintf("%02d",$parameters[0]).":".sprintf("%02d",$parameters[1]).":00.000",
|
|
status => "ON",
|
|
reminderLabel => decode_utf8($ReminderText),
|
|
type => $Type});
|
|
|
|
$json =~ s/\"true\"/true/g;
|
|
$json =~ s/\"false\"/false/g;
|
|
|
|
Log3( $name, 5, "[$name] set ".lc($Type)."_repeat $parameters[0]:$parameters[1] $ReminderRecc Message = $ReminderText");
|
|
|
|
echodevice_SendCommand($hash,"reminderitem",$json);
|
|
|
|
}
|
|
|
|
elsif($command eq "notifications_delete"){
|
|
|
|
return echodevice_getHelpText("no arg") if ( !defined($a[0]));
|
|
|
|
my @parameters = split("@",$parameter);
|
|
|
|
# Reminder aus dem hash entfernen
|
|
$hash->{IODev}->{helper}{"notifications"}{$hash->{helper}{".SERIAL"}}{$parameters[1]} = "";
|
|
|
|
echodevice_SendCommand($hash,"notifications_delete",$parameters[1]);
|
|
}
|
|
|
|
elsif($command eq "alarm_off"){
|
|
return echodevice_getHelpText("no arg") if ( !defined($a[0]));
|
|
echodevice_SendCommand($hash,"alarm_off",$a[0]);
|
|
}
|
|
|
|
elsif($command eq "alarm_on"){
|
|
return echodevice_getHelpText("no arg") if ( !defined($a[0]));
|
|
echodevice_SendCommand($hash,"alarm_on",$parameter);
|
|
}
|
|
|
|
# Routinen
|
|
elsif($command eq "routine_play"){
|
|
return echodevice_getHelpText("no arg") if ( !defined($a[0]));
|
|
echodevice_SendCommand($hash,"routine_play",$parameter);
|
|
}
|
|
|
|
# Nachrichten
|
|
elsif($command eq "textmessage"){
|
|
return echodevice_getHelpText("no arg") if ( !defined($a[0]) );
|
|
return echodevice_getHelpText("There are some arguments missing. [conversationId] nachrichtentext ") if ( !defined($a[1]) );
|
|
|
|
echodevice_SendCommand($hash,$command,join(' ',@a));
|
|
}
|
|
|
|
elsif($command eq "mobilmessage"){
|
|
return echodevice_getHelpText("no arg") if ( !defined($a[0]) );
|
|
echodevice_SendCommand($hash,$command,join(' ',@a));
|
|
}
|
|
|
|
elsif($command eq "message_delete"){
|
|
|
|
#return "No argument given" if ( !defined($a[0]));
|
|
|
|
#my @parameters = split("@",$parameter);
|
|
|
|
# Reminder aus dem hash entfernen
|
|
#$hash->{IODev}->{helper}{"notifications"}{$hash->{helper}{".SERIAL"}}{$parameters[1]} = "";
|
|
|
|
|
|
echodevice_SendCommand($hash,"message_delete","");
|
|
}
|
|
|
|
# Medien
|
|
elsif($command eq "tunein" || $command eq "ttstunein"){
|
|
|
|
my $tuneinID ;
|
|
if ( !defined($a[0]) && AttrVal($name,"tunein_default","none") eq "none" ) {
|
|
return echodevice_getHelpText("No argument given. You can set attribut tunein_default!");
|
|
}
|
|
elsif (!defined($a[0])) {$tuneinID = AttrVal($name,"tunein_default","none");}
|
|
else {$tuneinID = $a[0];}
|
|
|
|
# Player aktualisieren
|
|
readingsBeginUpdate($hash);
|
|
readingsBulkUpdate($hash, "tunein", $tuneinID, 1);
|
|
readingsBulkUpdate($hash, "playStatus", "playing", 1);
|
|
readingsEndUpdate($hash,1);
|
|
|
|
echodevice_SendCommand($hash,"tunein",$tuneinID);
|
|
|
|
InternalTimer( gettimeofday() + 10, "echodevice_GetSettings", $hash, 0);
|
|
}
|
|
|
|
elsif($command eq "primeplaylist"){
|
|
return echodevice_getHelpText("no arg") if ( !defined($a[0]) );
|
|
|
|
# Reading festhalten
|
|
readingsBeginUpdate($hash);
|
|
readingsBulkUpdate($hash, "primeplaylist", $a[0], 1);
|
|
readingsBulkUpdate($hash, "playStatus", "playing", 1);
|
|
readingsEndUpdate($hash,1);
|
|
|
|
my $json = encode_json( { asin => $a[0] } );
|
|
echodevice_SendCommand($hash,$command,$json);
|
|
|
|
InternalTimer( gettimeofday() + 5, "echodevice_GetSettings", $hash, 0);
|
|
}
|
|
|
|
elsif($command eq "primeplayeigeneplaylist"){
|
|
return echodevice_getHelpText("no arg") if ( !defined($a[0]) );
|
|
|
|
# Reading festhalten
|
|
readingsBeginUpdate($hash);
|
|
readingsBulkUpdate($hash, "primeplayeigeneplaylist", $a[0], 1);
|
|
readingsBulkUpdate($hash, "playStatus", "playing", 1);
|
|
readingsEndUpdate($hash,1);
|
|
|
|
my $json = encode_json( { playlistId => $a[0] } );
|
|
echodevice_SendCommand($hash,$command,$json);
|
|
|
|
InternalTimer( gettimeofday() + 3, "echodevice_GetSettings", $hash, 0);
|
|
}
|
|
|
|
elsif($command eq "primeplaysender"){
|
|
return echodevice_getHelpText("no arg") if ( !defined($a[0]) );
|
|
|
|
# Reading festhalten
|
|
readingsBeginUpdate($hash);
|
|
readingsBulkUpdate($hash, "primeplaysender", $a[0], 1);
|
|
readingsBulkUpdate($hash, "playStatus", "playing", 1);
|
|
readingsEndUpdate($hash,1);
|
|
|
|
my $json = encode_json( { seed => '{"type":"KEY","seedId":"' . $a[0] .'"}' ,stationName => $a[0],seedType => "KEY" } );
|
|
echodevice_SendCommand($hash,$command,$json);
|
|
|
|
InternalTimer( gettimeofday() + 3, "echodevice_GetSettings", $hash, 0);
|
|
}
|
|
|
|
elsif($command eq "primeplayeigene"){
|
|
return echodevice_getHelpText("no arg") if ( !defined($a[0]) );
|
|
|
|
# Reading festhalten
|
|
readingsBeginUpdate($hash);
|
|
readingsBulkUpdate($hash, "primeplayeigene", $a[0], 1);
|
|
readingsBulkUpdate($hash, "playStatus", "playing", 1);
|
|
readingsEndUpdate($hash,1);
|
|
|
|
my @PlayItem = split (/@/s, $parameter);
|
|
my $json = encode_json( { albumArtistName => $PlayItem[0],albumName => $PlayItem[1]} );
|
|
echodevice_SendCommand($hash,$command,$json);
|
|
|
|
InternalTimer( gettimeofday() + 3, "echodevice_GetSettings", $hash, 0);
|
|
}
|
|
|
|
elsif($command eq "track"){
|
|
|
|
return echodevice_getHelpText("no arg") if ( !defined($a[0]) );
|
|
|
|
# Reading festhalten
|
|
readingsBeginUpdate($hash);
|
|
readingsBulkUpdate($hash, "track", $a[0], 1);
|
|
readingsBulkUpdate($hash, "playStatus", "playing", 1);
|
|
readingsEndUpdate($hash,1);
|
|
|
|
my $json = encode_json( { trackId => $a[0],
|
|
playQueuePrime => "false"} );
|
|
|
|
$json =~s/\"true\"/true/g;
|
|
$json =~s/\"false\"/false/g;
|
|
echodevice_SendCommand($hash,$command,$json);
|
|
|
|
InternalTimer( gettimeofday() + 3, "echodevice_GetSettings", $hash, 0);
|
|
}
|
|
|
|
elsif($command eq "AWS_Access_Key" || $command eq "AWS_Secret_Key" ) {
|
|
readingsBeginUpdate($hash);
|
|
readingsBulkUpdate($hash, lc(".$command"), echodevice_encrypt($parameter), 1);
|
|
readingsEndUpdate($hash,1);
|
|
}
|
|
|
|
elsif($command eq "TTS_Filename" || $command eq "POM_Filename" || $command eq "TTS_TuneIn" || $command eq "POM_TuneIn" || $command eq "AWS_OutputFormat" || $command eq "TTS_IPAddress" || $command eq "POM_IPAddress" ) {
|
|
readingsBeginUpdate($hash);
|
|
readingsBulkUpdate($hash, lc($command), $parameter, 1);
|
|
readingsEndUpdate($hash,1);
|
|
}
|
|
|
|
elsif($command eq "tts") {
|
|
|
|
return echodevice_getHelpText("no arg") if ( !defined($a[0]) );
|
|
|
|
return echodevice_getHelpText("TTS can not play. The ECHO device $name is playing other media.") if (AttrVal($hash->{IODev}->{NAME},"TTS_IgnorPlay",1) == 0 && ReadingsVal( $name, "playStatus", "stopped") eq "playing" && ReadingsVal($name , "currentTuneInID", "-") eq "-");
|
|
return echodevice_getHelpText("TTS can not play. The ECHO device $name is playing other media.") if (AttrVal($name,"TTS_IgnorPlay",1) == 0 && ReadingsVal( $name, "playStatus", "stopped") eq "playing" && ReadingsVal($name , "currentTuneInID", "-") eq "-");
|
|
return echodevice_getHelpText("TTS can not play. Please define TTS_IPAdrees at the ECHO ACCOUNT DEVICE " . $hash->{IODev}->{NAME}) if (ReadingsVal($hash->{IODev}->{NAME} , lc("TTS_IPAddress"), "none") eq "none");
|
|
|
|
my $TTS_Voice = AttrVal($name,"TTS_Voice","German_Female_Google");
|
|
|
|
if ($TTS_Voice eq "German_Female_Google") {
|
|
echodevice_Google($hash,$parameter,$command);
|
|
}
|
|
else {
|
|
echodevice_Amazon($hash,$parameter,$command);
|
|
}
|
|
|
|
}
|
|
|
|
elsif($command eq "tts_translate") {
|
|
|
|
return echodevice_getHelpText("no arg") if ( !defined($a[0]) );
|
|
|
|
return echodevice_getHelpText("TTS can not play. The ECHO device $name is playing other media.") if (AttrVal($hash->{IODev}->{NAME},"TTS_IgnorPlay",1) == 0 && ReadingsVal( $name, "playStatus", "stopped") eq "playing" && ReadingsVal($name , "currentTuneInID", "-") eq "-");
|
|
return echodevice_getHelpText("TTS can not play. The ECHO device $name is playing other media.") if (AttrVal($name,"TTS_IgnorPlay",1) == 0 && ReadingsVal( $name, "playStatus", "stopped") eq "playing" && ReadingsVal($name , "currentTuneInID", "-") eq "-");
|
|
return echodevice_getHelpText("TTS can not play. Please define TTS_IPAdrees at the ECHO ACCOUNT DEVICE " . $hash->{IODev}->{NAME}) if (ReadingsVal($hash->{IODev}->{NAME} , lc("TTS_IPAddress"), "none") eq "none");
|
|
|
|
my $TTS_Voice = AttrVal($name,"TTS_Voice","German_Female_Google");
|
|
my $TTS_Translate_From = AttrVal($name,"TTS_Translate_From","german");
|
|
my $TTS_CodeOutput = "en";
|
|
my $TTS_CodeInput = "de";
|
|
|
|
# Output
|
|
if (index(lc($TTS_Voice), 'english') >= 0) {
|
|
$TTS_CodeOutput = "en";
|
|
}
|
|
elsif (index(lc($TTS_Voice), 'french') >= 0) {
|
|
$TTS_CodeOutput = "fr";
|
|
}
|
|
elsif (index(lc($TTS_Voice), 'portuguese') >= 0) {
|
|
$TTS_CodeOutput = "pt";
|
|
}
|
|
elsif (index(lc($TTS_Voice), 'spanish') >= 0) {
|
|
$TTS_CodeOutput = "es";
|
|
}
|
|
elsif (index(lc($TTS_Voice), 'dutch') >= 0) {
|
|
$TTS_CodeOutput = "nl";
|
|
}
|
|
elsif (index(lc($TTS_Voice), 'italian') >= 0) {
|
|
$TTS_CodeOutput = "it";
|
|
}
|
|
elsif (index(lc($TTS_Voice), 'japanese') >= 0) {
|
|
$TTS_CodeOutput = "ja";
|
|
}
|
|
elsif (index(lc($TTS_Voice), 'korean') >= 0) {
|
|
$TTS_CodeOutput = "ko";
|
|
}
|
|
elsif (index(lc($TTS_Voice), 'russian') >= 0) {
|
|
$TTS_CodeOutput = "ru";
|
|
}
|
|
elsif (index(lc($TTS_Voice), 'turkish') >= 0) {
|
|
$TTS_CodeOutput = "tr";
|
|
}
|
|
elsif (index(lc($TTS_Voice), 'german') >= 0) {
|
|
$TTS_CodeOutput = "de";
|
|
}
|
|
else {
|
|
return "TTS can not play. Please define other TTS_Voice. Language not supported. Supported languages are:dutch,english,french,german,italian,japanese,korean,portuguese,russian,spanish and turkish";
|
|
}
|
|
|
|
# Input
|
|
if ($TTS_Translate_From eq "dutch") {$TTS_CodeInput = "nl"}
|
|
elsif ($TTS_Translate_From eq "english") {$TTS_CodeInput = "en"}
|
|
elsif ($TTS_Translate_From eq "french") {$TTS_CodeInput = "fr"}
|
|
elsif ($TTS_Translate_From eq "german") {$TTS_CodeInput = "de"}
|
|
elsif ($TTS_Translate_From eq "italian") {$TTS_CodeInput = "it"}
|
|
elsif ($TTS_Translate_From eq "japanese") {$TTS_CodeInput = "ja"}
|
|
elsif ($TTS_Translate_From eq "portuguese") {$TTS_CodeInput = "pl"}
|
|
elsif ($TTS_Translate_From eq "russian") {$TTS_CodeInput = "ru"}
|
|
elsif ($TTS_Translate_From eq "spanish") {$TTS_CodeInput = "es"}
|
|
elsif ($TTS_Translate_From eq "turkish") {$TTS_CodeInput = "tr"}
|
|
|
|
if ($TTS_CodeInput eq $TTS_CodeOutput) {
|
|
return echodevice_getHelpText("TTS can not play. Please define other TTS_Voice or TTS_Translate_From. Input and output languages are the same!");
|
|
}
|
|
|
|
my $json = "{ dirCode:'" . $TTS_CodeInput . "-" . $TTS_CodeOutput . "', template:'General', text:'" .urlEncode($parameter) . "', lang:'de', limit:'3000',useAutoDetect:false, key:'123', ts:'MainSite',tid:'', IsMobile:false}";
|
|
|
|
echodevice_SendCommand($hash,$command,$json);
|
|
|
|
}
|
|
|
|
elsif($command eq "playownmusic") {
|
|
return echodevice_getHelpText("no arg") if ( !defined($a[0]) );
|
|
return echodevice_getHelpText("POM can not play. Please define POM_IPAdrees at the ECHO ACCOUNT DEVICE ") . $hash->{IODev}->{NAME} if (ReadingsVal($hash->{IODev}->{NAME} , lc("POM_IPAddress"), "none") eq "none");
|
|
echodevice_PlayOwnMP3($hash,$parameter);
|
|
}
|
|
|
|
elsif($command eq "saveownplaylist") {
|
|
return echodevice_getHelpText("no arg") if ( !defined($a[0]) );
|
|
echodevice_SaveOwnPlaylist($hash,$parameter);
|
|
}
|
|
|
|
elsif($command eq "playownplaylist") {
|
|
return echodevice_getHelpText("no arg") if ( !defined($a[0]) );
|
|
my $WEBAddress = ReadingsVal($hash->{IODev}->{NAME} , lc("POM_IPAddress"), "none");
|
|
return echodevice_getHelpText("POM can not play. Please define POM_IPAdrees at the ECHO ACCOUNT DEVICE ") . $hash->{IODev}->{NAME} if ($WEBAddress eq "none");
|
|
echodevice_PlayOwnMP3($hash,"http://" . $WEBAddress . "/playlists/" . $parameter);
|
|
}
|
|
|
|
elsif($command eq "deleteownplaylist") {
|
|
return echodevice_getHelpText("no arg")if ( !defined($a[0]) );
|
|
# Playliste löschen
|
|
if ((-e $FW_dir . "/echodevice/playlists/". $parameter)) {unlink $FW_dir . "/echodevice/playlists/".$parameter}
|
|
}
|
|
|
|
elsif($command eq "speak"){
|
|
return echodevice_getHelpText("no arg") if ( !defined($a[0]) );
|
|
echodevice_SendCommand($hash,$command,join(' ',@a));
|
|
}
|
|
|
|
elsif($command eq "speak_ssml"){
|
|
return echodevice_getHelpText("no arg") if ( !defined($a[0]) );
|
|
echodevice_SendCommand($hash,$command,join(' ',@a));
|
|
}
|
|
|
|
elsif($command eq "sounds"){
|
|
return echodevice_getHelpText("no arg") if ( !defined($a[0]) );
|
|
echodevice_SendCommand($hash,$command,join(' ',@a));
|
|
}
|
|
|
|
elsif($command eq "info"){
|
|
return echodevice_getHelpText("no arg") if ( !defined($a[0]) );
|
|
echodevice_SendCommand($hash,$command,join(' ',@a));
|
|
}
|
|
|
|
elsif($command eq "homescreen"){
|
|
return echodevice_getHelpText("no arg") if ( !defined($a[0]) );
|
|
echodevice_SendCommand($hash,$command,join(' ',@a));
|
|
}
|
|
|
|
elsif($command eq "textcommand"){
|
|
return echodevice_getHelpText("no arg") if ( !defined($a[0]) );
|
|
echodevice_SendCommand($hash,$command,join(' ',@a));
|
|
}
|
|
|
|
else {
|
|
echodevice_SendMessage($hash,$command,$parameter);
|
|
# Player aktualisieren
|
|
InternalTimer( gettimeofday() + 2, "echodevice_GetSettings", $hash, 0);
|
|
}
|
|
|
|
return ;
|
|
}
|
|
|
|
#########################
|
|
sub echodevice_SendMessage($$$) {
|
|
my ($hash,$command,$value) = @_;
|
|
my $name = $hash->{NAME};
|
|
|
|
my $json = encode_json( {} );
|
|
|
|
if($command eq "volume") {
|
|
$json = encode_json( { type => 'VolumeLevelCommand',
|
|
volumeLevel => 0+$value,
|
|
contentFocusClientId => undef } );
|
|
}
|
|
|
|
elsif ($command eq "play") {
|
|
$json = encode_json( { type => 'PlayCommand',
|
|
contentFocusClientId => undef } );
|
|
}
|
|
|
|
elsif ($command eq "pause") {
|
|
$json = encode_json( { type => 'PauseCommand',
|
|
contentFocusClientId => undef } );
|
|
}
|
|
|
|
elsif ($command eq "next") {
|
|
$json = encode_json( { type => 'NextCommand',
|
|
contentFocusClientId => undef } );
|
|
}
|
|
|
|
elsif ($command eq "previous") {
|
|
$json = encode_json( { type => 'PreviousCommand',
|
|
contentFocusClientId => undef } );
|
|
}
|
|
|
|
elsif ($command eq "forward") {
|
|
$json = encode_json( { type => 'ForwardCommand',
|
|
contentFocusClientId => undef } );
|
|
}
|
|
|
|
elsif ($command eq "rewind") {
|
|
$json = encode_json( { type => 'RewindCommand',
|
|
contentFocusClientId => undef } );
|
|
}
|
|
|
|
elsif ($command eq "shuffle") {
|
|
$json = encode_json( { type => 'ShuffleCommand',
|
|
shuffle => ($value eq "on"?"true":"false"),
|
|
contentFocusClientId => undef } );
|
|
}
|
|
|
|
elsif ($command eq "repeat") {
|
|
$json = encode_json( { type => 'RepeatCommand',
|
|
repeat => ($value eq "on"?"true":"false"),
|
|
contentFocusClientId => undef } );
|
|
}
|
|
|
|
else {
|
|
Log3 ($name, 4, "[$name] [echodevice_SendMessage] Unknown command $command $value");
|
|
return ;
|
|
}
|
|
|
|
Log3 ($name, 4, "[$name] [echodevice_SendMessage] command $command $value");
|
|
|
|
$json =~s/\"true\"/true/g;
|
|
$json =~s/\"false\"/false/g;
|
|
|
|
echodevice_SendCommand($hash,"command",$json);
|
|
|
|
}
|
|
|
|
sub echodevice_SendCommand($$$) {
|
|
my ( $hash, $type, $SendData ) = @_;
|
|
my $name = $hash->{NAME};
|
|
my $SendUrl;
|
|
my $SendDataL;
|
|
|
|
Log3 $name, 4, "[$name] [echodevice_SendCommand] [$type] START";
|
|
|
|
if($hash->{model} eq "ACCOUNT") {
|
|
return undef if(!defined($hash->{helper}{SERVER}));
|
|
$SendUrl = "https://".$hash->{helper}{SERVER};
|
|
}
|
|
|
|
else {
|
|
return undef if(!defined($hash->{IODev}->{helper}{SERVER}));
|
|
$SendUrl = "https://".$hash->{IODev}->{helper}{SERVER};
|
|
}
|
|
|
|
my $SendParam ;
|
|
my $SendMetode = "GET" ;
|
|
|
|
# Ohne JSON
|
|
if ($type eq "bluetoothstate") {
|
|
$SendUrl .= "/api/bluetooth?cached=true&_=".int(time);
|
|
}
|
|
|
|
elsif ($type eq "notifications") {
|
|
$SendUrl .= "/api/notifications?cached=true&_=".int(time);
|
|
}
|
|
|
|
elsif ($type eq "getdnd") {
|
|
$SendUrl .= "/api/dnd/device-status-list?_=".int(time);
|
|
}
|
|
|
|
elsif ($type eq "getbehavior") {
|
|
$SendUrl .= "/api/behaviors/v2/automations?limit=100";
|
|
}
|
|
|
|
elsif ($type eq "getdevicesettings") {
|
|
$SendUrl .= "/api/device-preferences";
|
|
}
|
|
|
|
elsif ($type eq "getisonline") {
|
|
$SendUrl .= "/api/devices-v2/device?cached=true&_=".int(time);
|
|
}
|
|
|
|
elsif ($type eq "wakeword") {
|
|
$SendUrl .= "/api/wake-word?_=".int(time);
|
|
}
|
|
|
|
elsif ($type eq "alarmvolume") {
|
|
$SendUrl .= "/api/device-notification-state?_=".int(time);
|
|
}
|
|
|
|
elsif ($type eq "activities") {
|
|
if (int(AttrVal($name,"intervalvoice",999999)) != 999999) {
|
|
$SendUrl .= "/api/activities?startTime=&size=10&offset=1&_=".int(time);
|
|
}
|
|
else {
|
|
$SendUrl .= "/api/activities?startTime=&size=50&offset=1&_=".int(time);
|
|
}
|
|
}
|
|
|
|
elsif ($type eq "player") {
|
|
$SendUrl .= "/api/np/player?deviceSerialNumber=".$hash->{helper}{".SERIAL"}."&deviceType=".$hash->{helper}{DEVICETYPE}."&screenWidth=1392&_=".int(time);
|
|
}
|
|
|
|
elsif ($type eq "media") {
|
|
$SendUrl .= "/api/media/state?deviceSerialNumber=".$hash->{helper}{".SERIAL"}."&deviceType=".$hash->{helper}{DEVICETYPE}."&screenWidth=1392&_=".int(time);
|
|
}
|
|
|
|
elsif ($type eq "reminderitem") {
|
|
$SendUrl .= "/api/notifications/createReminder";
|
|
$SendMetode = "PUT";
|
|
}
|
|
|
|
elsif ($type eq "command") {
|
|
$SendUrl .= "/api/np/command?deviceSerialNumber=".$hash->{helper}{".SERIAL"}."&deviceType=".$hash->{helper}{DEVICETYPE};
|
|
$SendMetode = "POST";
|
|
}
|
|
|
|
elsif ($type eq "tunein" || $type eq "ttstunein" ) {
|
|
$SendUrl .= "/api/entertainment/v1/player/queue?deviceSerialNumber=".$hash->{helper}{".SERIAL"}."&deviceType=".$hash->{helper}{DEVICETYPE};
|
|
$SendData = encode_json( { contentToken => 'music:'. encode_base64(encode_base64('["music/tuneIn/stationId","'.$SendData.'"]|{"previousPageId":"TuneIn_SEARCH"}', ''), '') } );
|
|
$SendDataL = $SendData ;
|
|
$SendMetode = "PUT";
|
|
}
|
|
|
|
elsif ($type eq "getnotifications" ) {
|
|
$SendUrl .= "/api/notifications";
|
|
$SendData = "";
|
|
}
|
|
|
|
elsif ($type eq "notifications_delete" ) {
|
|
$SendUrl .= "/api/notifications/".$hash->{helper}{DEVICETYPE}."-".$hash->{helper}{".SERIAL"}."-".$SendData;
|
|
$SendMetode = "DELETE";
|
|
$SendData = "";
|
|
$SendDataL = $SendData ;
|
|
}
|
|
|
|
elsif ($type eq "routine_play") {
|
|
$SendUrl .= "/api/behaviors/preview";
|
|
$SendMetode = "POST";
|
|
|
|
my @parameters = split("@",$SendData);
|
|
my $sequenceJson = encode_json($hash->{IODev}->{helper}{"getbehavior"}{$parameters[1]}{sequence});
|
|
|
|
$sequenceJson =~ s/"/\\"/g;
|
|
|
|
#Log3 $name, 3, "[$name] [DEBUG] JSONORG=" . $sequenceJsonTest;
|
|
#Log3 $name, 3, "[$name] [DEBUG] JSONNEW=" . $sequenceJson;
|
|
|
|
$SendData = '{"behaviorId":"'.$parameters[1].'","sequenceJson":"'.$sequenceJson.'","status":"'.$hash->{IODev}->{helper}{"getbehavior"}{$parameters[1]}{status}.'"}';
|
|
my $AlexaType = $hash->{helper}{DEVICETYPE};
|
|
my $AlexaDSN = $hash->{helper}{".SERIAL"};
|
|
$SendData =~ s/ALEXA_CURRENT_DEVICE_TYPE/$AlexaType/g;
|
|
$SendData =~ s/ALEXA_CURRENT_DSN/$AlexaDSN/g;
|
|
$SendDataL = $SendData;
|
|
}
|
|
|
|
elsif ($type eq "mobilmessage") {
|
|
$SendUrl .= "/api/behaviors/preview";
|
|
$SendMetode = "POST";
|
|
my $Messagetext = $SendData;
|
|
$Messagetext =~ s/"/'/g;
|
|
$SendData = '{"behaviorId":"PREVIEW","sequenceJson":"{\"@type\":\"com.amazon.alexa.behaviors.model.Sequence\",\"startNode\":{\"operationPayload\":{\"notificationMessage\":\"' . $Messagetext .'\",\"alexaUrl\":\"#v2/behaviors\",\"customerId\":\"' . $hash->{helper}{".CUSTOMER"} .'\",\"title\":\"FHEM\"},\"type\":\"Alexa.Notifications.SendMobilePush\",\"@type\":\"com.amazon.alexa.behaviors.model.OpaquePayloadOperationNode\",\"skillId\":\"amzn1.ask.1p.routines.messaging\",\"name\":null},\"sequenceId\":\"amzn1.alexa.sequence.8f5aa289-c6d4-4a6f-a1b9-5b182e23be1e\"}","status":"ENABLED"}';
|
|
$SendDataL = $SendData;
|
|
}
|
|
|
|
elsif ($type eq "alarm_off" || $type eq "alarm_on" ) {
|
|
|
|
my @parameters = split("@",$SendData);
|
|
my @AlarmType = split("_",$SendData);
|
|
my @StateType = split("_",$type);
|
|
my $SetTo = uc($StateType[1]);
|
|
|
|
$SendUrl = "https://alexa.amazon.de/api/notifications/".$hash->{helper}{DEVICETYPE}."-".$hash->{helper}{".SERIAL"};#."-12".$parameters[1]."12";
|
|
$SendMetode = "PUT";
|
|
|
|
$SendData = '{"id":"'.$hash->{helper}{DEVICETYPE}.'-'.$hash->{helper}{".SERIAL"}.'-'.$parameters[1].'","createdDate":0,"deferredAtTime":null,"deviceSerialNumber":"'.$hash->{helper}{".SERIAL"}.'","deviceType":"'.$hash->{helper}{DEVICETYPE}.'","geoLocationTriggerData":null,"musicAlarmId":'.$hash->{IODev}->{helper}{$AlarmType[0]}{$hash->{helper}{".SERIAL"}}{$parameters[1]}{"musicAlarmId"}.',"musicEntity":'.$hash->{IODev}->{helper}{$AlarmType[0]}{$hash->{helper}{".SERIAL"}}{$parameters[1]}{"musicEntity"}.',"notificationIndex":"'.$parameters[1].'","originalDate":"'.$hash->{IODev}->{helper}{$AlarmType[0]}{$hash->{helper}{".SERIAL"}}{$parameters[1]}{"originalDate"}.'","originalTime":"'.$hash->{IODev}->{helper}{$AlarmType[0]}{$hash->{helper}{".SERIAL"}}{$parameters[1]}{"originalTime"}.'","personProfile":null,"provider":'.$hash->{IODev}->{helper}{$AlarmType[0]}{$hash->{helper}{".SERIAL"}}{$parameters[1]}{"provider"}.',"recurringPattern":';
|
|
|
|
if ($hash->{IODev}->{helper}{$AlarmType[0]}{$hash->{helper}{".SERIAL"}}{$parameters[1]}{"recurringPattern"} eq "null" || lc($AlarmType[0]) eq "musicalarm") {
|
|
$SendData .= "null";
|
|
}
|
|
else {
|
|
$SendData .= '"'.$hash->{IODev}->{helper}{$AlarmType[0]}{$hash->{helper}{".SERIAL"}}{$parameters[1]}{"recurringPattern"}.'","sound":{"cid":"c13489","attributes":{"displayName":"Simple Alarm","folder":null,"id":"system_alerts_melodic_01","providerId":"ECHO","sampleUrl":"https://s3.amazonaws.com/deeappservice.prod.notificationtones/system_alerts_melodic_01.mp3"},"_changing":false,"_previousAttributes":{},"changed":{},"id":"system_alerts_melodic_01","_pending":false,"hasSynced":false,"_isExpired":false,"_listeners":{"l13490":{"displayName":"Simple Alarm","folder":null,"id":"system_alerts_melodic_01","providerId":"ECHO","sampleUrl":"https://s3.amazonaws.com/deeappservice.prod.notificationtones/system_alerts_melodic_01.mp3"}},"_listenerId":"l13490","_events":{"sync":[{"context":{"displayName":"Simple Alarm","folder":null,"id":"system_alerts_melodic_01","providerId":"ECHO","sampleUrl":"https://s3.amazonaws.com/deeappservice.prod.notificationtones/system_alerts_melodic_01.mp3"},"ctx":{"displayName":"Simple Alarm","folder":null,"id":"system_alerts_melodic_01","providerId":"ECHO","sampleUrl":"https://s3.amazonaws.com/deeappservice.prod.notificationtones/system_alerts_melodic_01.mp3"}}]},"providerId":null,"displayName":null,"sampleUrl":null,"folder":null}';
|
|
}
|
|
|
|
$SendData .= ',"remainingTime":'.$hash->{IODev}->{helper}{$AlarmType[0]}{$hash->{helper}{".SERIAL"}}{$parameters[1]}{"remainingTime"}.',"reminderLabel":null,"skillInfo":null,"sound":{"displayName":"Simple Alarm","folder":null,"id":"system_alerts_melodic_01","providerId":"ECHO","sampleUrl":"https://s3.amazonaws.com/deeappservice.prod.notificationtones/system_alerts_melodic_01.mp3"},"status":"'.$SetTo.'","targetPersonProfiles":null,"timeZoneId":null,"timerLabel":null,"triggerTime":0,"type":"'.$AlarmType[0].'","version":"16","alarmTime":'.$hash->{IODev}->{helper}{$AlarmType[0]}{$hash->{helper}{".SERIAL"}}{$parameters[1]}{"alarmTime"}.',"alarmIndex":null,"isSaveInFlight":true}';
|
|
}
|
|
|
|
elsif ($type eq "message_delete" ) {
|
|
$SendUrl .= "/api/device-preferences/G090L90964350E96";
|
|
$SendMetode = "PUT";
|
|
}
|
|
|
|
elsif ($type eq "track" ) {
|
|
$SendUrl .= "/api/cloudplayer/queue-and-play?deviceSerialNumber=".$hash->{helper}{".SERIAL"}."&deviceType=".$hash->{helper}{DEVICETYPE}."&mediaOwnerCustomerId=".$hash->{IODev}->{helper}{".CUSTOMER"};
|
|
$SendMetode = "POST";
|
|
}
|
|
|
|
elsif ($type eq "primeplaylist" ) {
|
|
$SendUrl .= "/api/prime/prime-playlist-queue-and-play?deviceSerialNumber=".$hash->{helper}{".SERIAL"}."&deviceType=".$hash->{helper}{DEVICETYPE}."&mediaOwnerCustomerId=".$hash->{IODev}->{helper}{".CUSTOMER"};
|
|
$SendMetode = "POST";
|
|
}
|
|
|
|
elsif ($type eq "primeplayeigeneplaylist" ) {
|
|
$SendUrl .= "/api/cloudplayer/queue-and-play?deviceSerialNumber=".$hash->{helper}{".SERIAL"}."&deviceType=".$hash->{helper}{DEVICETYPE}."&mediaOwnerCustomerId=".$hash->{IODev}->{helper}{".CUSTOMER"};
|
|
$SendMetode = "POST";
|
|
}
|
|
|
|
elsif ($type eq "primeplaysender" ) {
|
|
$SendUrl .= "/api/gotham/queue-and-play?deviceSerialNumber=".$hash->{helper}{".SERIAL"}."&deviceType=".$hash->{helper}{DEVICETYPE}."&mediaOwnerCustomerId=".$hash->{IODev}->{helper}{".CUSTOMER"};
|
|
$SendMetode = "POST";
|
|
}
|
|
|
|
elsif ($type eq "primeplayeigene" ) {
|
|
$SendUrl .= "/api/cloudplayer/queue-and-play?deviceSerialNumber=".$hash->{helper}{".SERIAL"}."&deviceType=".$hash->{helper}{DEVICETYPE}."&mediaOwnerCustomerId=".$hash->{IODev}->{helper}{".CUSTOMER"};
|
|
$SendMetode = "POST";
|
|
}
|
|
|
|
elsif ($type eq "textmessage" ) {
|
|
|
|
my @parameters = split(" ",$SendData);
|
|
my $conversationid = shift @parameters;
|
|
my $parameter = join(" ",@parameters);
|
|
|
|
$SendUrl = "https://alexa-comms-mobile-service.amazon.com/users/".$hash->{helper}{".COMMSID"}."/conversations/".$conversationid."/messages";
|
|
$SendMetode = "POST";
|
|
$SendData = JSON->new->pretty(1)->utf8(1)->encode([{ "type" => "message/text",
|
|
"payload" => {"text" => decode_utf8($parameter)} }] );
|
|
$SendData =~s/\//\\\//;
|
|
|
|
}
|
|
|
|
elsif ($type eq "volume_alarm" ) {
|
|
$SendUrl .= "/api/device-notification-state/".$hash->{helper}{DEVICETYPE}."/".$hash->{helper}{VERSION}."/".$hash->{helper}{".SERIAL"};
|
|
$SendMetode = "PUT";
|
|
}
|
|
|
|
elsif ($type eq "dnd" ) {
|
|
$SendUrl .= "/api/dnd/status";
|
|
$SendMetode = "PUT";
|
|
}
|
|
|
|
elsif ($type eq "bluetooth_connect" ) {
|
|
$SendUrl .= "/api/bluetooth/pair-sink/".$hash->{helper}{DEVICETYPE}."/".$hash->{helper}{".SERIAL"};
|
|
$SendMetode = "POST";
|
|
}
|
|
|
|
elsif ($type eq "bluetooth_disconnect" ) {
|
|
$SendUrl .= "/api/bluetooth/disconnect-sink/".$hash->{helper}{DEVICETYPE}."/".$hash->{helper}{".SERIAL"};
|
|
$SendMetode = "POST";
|
|
}
|
|
|
|
elsif ($type eq "namedListsIDs") {
|
|
$SendUrl .= "/api/namedLists";
|
|
}
|
|
|
|
elsif ($type eq "listitems_task" || $type eq "listitems_shopping" ) {
|
|
$SendUrl .= "/api/todos?size=100&startTime=&endTime=&completed=false&type=".$SendData."&deviceSerialNumber=&deviceType=&_=".int(time);
|
|
$SendDataL = $SendData ;
|
|
$SendData = "";
|
|
}
|
|
|
|
elsif ($type eq "item_shopping_add" ) {
|
|
$SendUrl .= "/api/namedLists/" . $hash->{helper}{SHOPPING_LIST_ID} . "/item";
|
|
$SendMetode = "POST";
|
|
$SendDataL = $SendData;
|
|
}
|
|
|
|
elsif ($type eq "item_task_add" ) {
|
|
$SendUrl .= "/api/namedLists/" . $hash->{helper}{TO_DO_LIST_ID} . "/item";
|
|
$SendMetode = "POST";
|
|
$SendDataL = $SendData;
|
|
}
|
|
|
|
elsif ($type eq "item_task_delete" ) {
|
|
|
|
my $json = JSON->new->utf8(1)->encode( {'value' => $hash->{helper}{"ITEMS"}{TASK}{TEXT}{$SendData},
|
|
'listId' => $hash->{helper}{TO_DO_LIST_ID},
|
|
'id' => $hash->{helper}{"ITEMS"}{TASK}{ID}{$SendData}});
|
|
|
|
$json =~ s/\"true\"/true/g;
|
|
$json =~ s/\"false\"/false/g;
|
|
|
|
$SendUrl .= "/api/namedLists/" . $hash->{helper}{TO_DO_LIST_ID} . "/item/" . $hash->{helper}{"ITEMS"}{TASK}{ID}{$SendData};
|
|
$SendMetode = "DELETE";
|
|
$SendData = $json;
|
|
$SendDataL = $SendData;
|
|
|
|
}
|
|
|
|
elsif ($type eq "item_shopping_delete" ) {
|
|
|
|
my $json = JSON->new->utf8(1)->encode( {'value' => $hash->{helper}{"ITEMS"}{SHOPPING_ITEM}{TEXT}{$SendData},
|
|
'listId' => $hash->{helper}{SHOPPING_LIST_ID},
|
|
'id' => $hash->{helper}{"ITEMS"}{SHOPPING_ITEM}{ID}{$SendData}});
|
|
|
|
$json =~ s/\"true\"/true/g;
|
|
$json =~ s/\"false\"/false/g;
|
|
|
|
$SendUrl .= "/api/namedLists/" . $hash->{helper}{SHOPPING_LIST_ID} . "/item/" . $hash->{helper}{"ITEMS"}{SHOPPING_ITEM}{ID}{$SendData};
|
|
$SendMetode = "DELETE";
|
|
$SendData = $json;
|
|
$SendDataL = $SendData;
|
|
|
|
}
|
|
|
|
elsif ($type eq "account" ) {
|
|
#Log3 $name, 2, "[$name] [echodevice_SendCommand] [$type] START";
|
|
$SendUrl = "https://alexa-comms-mobile-service.amazon.com/accounts";
|
|
$SendMetode = "GET";
|
|
$SendData = "";
|
|
}
|
|
|
|
elsif ($type eq "homegroup" ) {
|
|
$SendUrl = "https://alexa-comms-mobile-service.amazon.com/users/".$hash->{helper}{".COMMSID"}."/identities?includeUserName=true";
|
|
$SendMetode = "GET";
|
|
}
|
|
|
|
elsif ($type eq "conversations" ) {
|
|
$SendUrl = "https://alexa-comms-mobile-service.amazon.com/users/".$hash->{helper}{".COMMSID"}."/conversations?latest=true&includeHomegroup=true&unread=false&modifiedSinceDate=1970-01-01T00:00:00.000Z&includeUserName=true";
|
|
}
|
|
|
|
elsif ($type eq "devices" || $type eq "autocreate_devices" || $type eq "devicesstate") {
|
|
$SendUrl .= "/api/devices-v2/device?cached=true&_=".int(time);
|
|
}
|
|
|
|
elsif ($type eq "searchtunein" ) {
|
|
$SendUrl .= "/api/tunein/search?query=".uri_escape_utf8(decode_utf8($SendData))."&mediaOwnerCustomerId=".$hash->{IODev}->{helper}{".CUSTOMER"}."&_=".int(time);
|
|
$SendDataL = $SendData ;
|
|
$SendData = "";
|
|
}
|
|
|
|
elsif ($type eq "searchtracks" ) {
|
|
$SendUrl .= "/api/cloudplayer/playlists/IMPORTED-V0-OBJECTID?deviceSerialNumber=".$hash->{helper}{".SERIAL"}."&deviceType=".$hash->{helper}{DEVICETYPE}."&size=50&offset=&mediaOwnerCustomerId=".$hash->{helper}{".CUSTOMER"}."&_=".int(time);
|
|
}
|
|
|
|
elsif ($type eq "getcards" ) {
|
|
$SendUrl .= "/api/cards?limit=50&beforeCreationTime=".int(time)."000&_=".int(time);
|
|
}
|
|
|
|
elsif ($type eq "primeplayeigene_Albums" || $type eq "primeplayeigene_Tracks") {
|
|
my $querytype = substr($type,16);
|
|
$SendData =~ s/ /+/g;
|
|
$SendUrl .= "/api/cloudplayer/search?deviceSerialNumber=".$hash->{helper}{".SERIAL"}."&deviceType=".$hash->{helper}{DEVICETYPE}. "&size=50&category=$querytype&query=". $SendData . "&offset=0" . "&mediaOwnerCustomerId=".$hash->{IODev}->{helper}{".CUSTOMER"}."&_=".int(time);
|
|
$SendDataL = $SendData ;
|
|
$SendData = "";
|
|
}
|
|
|
|
elsif ($type eq "primeplayeigene_Artists" ) {
|
|
$SendData =~ s/ /+/g;
|
|
$SendUrl .= "/api/cloudplayer/albums?deviceSerialNumber=".$hash->{helper}{".SERIAL"}."&deviceType=".$hash->{helper}{DEVICETYPE}. "&size=50&artistName=". $SendData ."&mediaOwnerCustomerId=".$hash->{IODev}->{helper}{".CUSTOMER"}."&_=".int(time);
|
|
$SendDataL = $SendData ;
|
|
$SendData = "";
|
|
}
|
|
|
|
elsif ($type eq "getprimeplayeigeneplaylist" ) {
|
|
$SendUrl .= "/api/cloudplayer/playlists?deviceSerialNumber=".$hash->{helper}{".SERIAL"}."&deviceType=".$hash->{helper}{DEVICETYPE}. "&mediaOwnerCustomerId=".$hash->{IODev}->{helper}{".CUSTOMER"}."&_=".int(time);
|
|
}
|
|
|
|
elsif ($type eq "tts_translate" ) {
|
|
$SendUrl = "http://www.online-translator.com/services/soap.asmx/GetTranslation";
|
|
$SendMetode = "POST";
|
|
}
|
|
|
|
elsif ($type eq "sounds" ) {
|
|
|
|
#Allgemeine Veariablen
|
|
$SendUrl .= "/api/behaviors/preview";
|
|
$SendMetode = "POST";
|
|
|
|
$SendData = echodevice_getsequenceJson($hash,lc($SendData),"");
|
|
$SendDataL = $SendData;
|
|
}
|
|
|
|
elsif ($type eq "info" ) {
|
|
|
|
#Allgemeine Veariablen
|
|
$SendUrl .= "/api/behaviors/preview";
|
|
$SendMetode = "POST";
|
|
|
|
$SendData = echodevice_getsequenceJson($hash,lc($SendData),"");
|
|
$SendDataL = $SendData;
|
|
}
|
|
|
|
elsif ($type eq "getsettingstraffic") {
|
|
$SendUrl .= "/api/traffic/settings";
|
|
$SendMetode = "GET";
|
|
$SendDataL = "";
|
|
$SendData = "";
|
|
}
|
|
|
|
elsif ($type eq "address") {
|
|
$SendUrl .= "/api/traffic/suggest?q=".urlEncode($SendData)."&suggestionType=LOCATION_ADDRESS";
|
|
$SendMetode = "GET";
|
|
$SendDataL = $SendData ;
|
|
$SendData = "";
|
|
}
|
|
|
|
elsif ($type eq "customer-history-records") {
|
|
$SendUrl = "https://www.amazon.de/alexa-privacy/apd/rvh/customer-history-records/?startTime=0&endTime=2005090388459&recordType=VOICE_HISTORY&maxRecordSize=100";
|
|
$SendMetode = "GET";
|
|
$SendDataL = "" ;
|
|
$SendData = "";
|
|
}
|
|
|
|
elsif ($type eq "config_address_from" || $type eq "config_address_to" || $type eq "config_address_between") {
|
|
$SendUrl .= "/api/traffic/settings";
|
|
$SendMetode = "POST";
|
|
|
|
my $InternFrom ;
|
|
my $InternTo ;
|
|
my $InternBetween ;
|
|
|
|
$hash->{helper}{"getsettingstraffic"}{from} = $SendData if ($type eq "config_address_from");
|
|
$hash->{helper}{"getsettingstraffic"}{to} = $SendData if ($type eq "config_address_to");
|
|
$hash->{helper}{"getsettingstraffic"}{between} = $SendData if ($type eq "config_address_between");
|
|
|
|
#JSON String zusammenbauen
|
|
if ($hash->{helper}{"getsettingstraffic"}{from} ne "") {
|
|
$InternFrom = '"origin":{"label":"' . $hash->{helper}{"getsettingstraffic"}{from} . '"}'
|
|
}
|
|
else {
|
|
$InternFrom = '"origin":null';
|
|
}
|
|
|
|
if ($hash->{helper}{"getsettingstraffic"}{to} ne "") {
|
|
$InternTo = '"destination":{"label":"' . $hash->{helper}{"getsettingstraffic"}{to} . '"}'
|
|
}
|
|
else {
|
|
$InternTo = '"destination":null';
|
|
}
|
|
|
|
if ($hash->{helper}{"getsettingstraffic"}{between} ne "") {
|
|
$InternBetween = '"waypoints":[{"label":"' . $hash->{helper}{"getsettingstraffic"}{between} . '"}]'
|
|
}
|
|
else {
|
|
$InternBetween = '"waypoints":[]';
|
|
}
|
|
|
|
# Send JSON String fertigstellen
|
|
$SendData = '{'.$InternFrom.','.$InternTo.','.$InternBetween.',"preferredTransportMode":"CAR","transportNames":null}' ;
|
|
$SendDataL = $SendData ;
|
|
|
|
}
|
|
|
|
elsif ($type eq "volume") {
|
|
|
|
#Allgemeine Veariablen
|
|
$SendUrl .= "/api/behaviors/preview";
|
|
$SendMetode = "POST";
|
|
|
|
$SendData = echodevice_getsequenceJson($hash,$type,$SendData);
|
|
$SendDataL = $SendData;
|
|
}
|
|
|
|
elsif ($type eq "speak") {
|
|
|
|
#Allgemeine Veariablen
|
|
$SendUrl .= "/api/behaviors/preview";
|
|
$SendMetode = "POST";
|
|
|
|
my $sequenceJson;
|
|
|
|
# Sonderzeichen entfernen
|
|
$SendData =~s/"/ /g;
|
|
|
|
my $SpeakVolume;
|
|
$SpeakVolume = int(AttrVal($hash->{IODev}{NAME},"speak_volume",0));
|
|
$SpeakVolume = int(AttrVal($name,"speak_volume",0)) if($SpeakVolume == 0);
|
|
|
|
if($SpeakVolume > 0){
|
|
#if(ReadingsVal($name , "volume", 50) < ReadingsVal($name , "volume_alarm", 50)) {
|
|
$SendData = '{"behaviorId":"PREVIEW","sequenceJson":"{\"@type\":\"com.amazon.alexa.behaviors.model.Sequence\",\"startNode\":{\"@type\":\"com.amazon.alexa.behaviors.model.SerialNode\",\"nodesToExecute\":[{\"@type\":\"com.amazon.alexa.behaviors.model.OpaquePayloadOperationNode\",\"type\":\"Alexa.DeviceControls.Volume\",\"operationPayload\":{\"deviceSerialNumber\":\"' . $hash->{helper}{".SERIAL"} . '\",\"customerId\":\"' . $hash->{IODev}->{helper}{".CUSTOMER"} .'\",\"locale\":\"de-DE\",\"value\":\"'.$SpeakVolume.'\",\"deviceType\":\"' . $hash->{helper}{DEVICETYPE} . '\"}},{\"@type\":\"com.amazon.alexa.behaviors.model.OpaquePayloadOperationNode\",\"type\":\"Alexa.Speak\",\"operationPayload\":{\"locale\":\"de-DE\",\"deviceSerialNumber\":\"' . $hash->{helper}{".SERIAL"} . '\",\"customerId\":\"' . $hash->{IODev}->{helper}{".CUSTOMER"} .'\",\"deviceType\":\"' . $hash->{helper}{DEVICETYPE} . '\",\"textToSpeak\":\"'.$SendData.'\"}},{\"@type\":\"com.amazon.alexa.behaviors.model.OpaquePayloadOperationNode\",\"type\":\"Alexa.DeviceControls.Volume\",\"operationPayload\":{\"deviceSerialNumber\":\"' . $hash->{helper}{".SERIAL"} . '\",\"customerId\":\"' . $hash->{IODev}->{helper}{".CUSTOMER"} .'\",\"locale\":\"de-DE\",\"value\":\"'.ReadingsVal($name , "volume", 50).'\",\"deviceType\":\"' . $hash->{helper}{DEVICETYPE} . '\"}}]}}","status":"ENABLED"}'
|
|
}
|
|
else {
|
|
$SendData = echodevice_getsequenceJson($hash,$type,$SendData);
|
|
}
|
|
|
|
$SendDataL = $SendData;
|
|
}
|
|
|
|
elsif ($type eq "speak_ssml") {
|
|
|
|
#Allgemeine Veariablen
|
|
$SendUrl .= "/api/behaviors/preview";
|
|
$SendMetode = "POST";
|
|
|
|
my $sequenceJson;
|
|
|
|
# Sonderzeichen entfernen
|
|
$SendData =~s/"/'/g;
|
|
|
|
my $SpeakVolume;
|
|
$SpeakVolume = int(AttrVal($hash->{IODev}{NAME},"speak_volume",0));
|
|
$SpeakVolume = int(AttrVal($name,"speak_volume",0)) if($SpeakVolume == 0);
|
|
|
|
if($SpeakVolume > 0){
|
|
$SendData = '{"behaviorId":"PREVIEW","sequenceJson":"{\"@type\":\"com.amazon.alexa.behaviors.model.Sequence\",\"startNode\":{\"@type\":\"com.amazon.alexa.behaviors.model.SerialNode\",\"nodesToExecute\":[{\"@type\":\"com.amazon.alexa.behaviors.model.OpaquePayloadOperationNode\",\"type\":\"Alexa.DeviceControls.Volume\",\"operationPayload\":{\"deviceSerialNumber\":\"' . $hash->{helper}{".SERIAL"} . '\",\"customerId\":\"' . $hash->{IODev}->{helper}{".CUSTOMER"} .'\",\"locale\":\"de-DE\",\"value\":\"'.$SpeakVolume.'\",\"deviceType\":\"' . $hash->{helper}{DEVICETYPE} . '\"}},{\"@type\":\"com.amazon.alexa.behaviors.model.OpaquePayloadOperationNode\",\"type\":\"AlexaAnnouncement\",\"operationPayload\":{\"expireAfter\":\"PT5S\",\"content\":[{\"locale\":\"\",\"display\":{\"title\":\"FHEM\",\"body\":\"Speak\"},\"speak\":{\"type\":\"ssml\",\"value\":\"' . $SendData . '\"}}],\"customerId\":\"' . $hash->{IODev}->{helper}{".CUSTOMER"} .'\",\"target\":{\"customerId\":\"' . $hash->{IODev}->{helper}{".CUSTOMER"} .'\",\"devices\":[{\"deviceSerialNumber\":\"' . $hash->{helper}{".SERIAL"} . '\",\"deviceTypeId\":\"' . $hash->{helper}{DEVICETYPE} . '\"}]}}},{\"@type\":\"com.amazon.alexa.behaviors.model.OpaquePayloadOperationNode\",\"type\":\"Alexa.DeviceControls.Volume\",\"operationPayload\":{\"deviceSerialNumber\":\"' . $hash->{helper}{".SERIAL"} . '\",\"customerId\":\"' . $hash->{IODev}->{helper}{".CUSTOMER"} .'\",\"locale\":\"de-DE\",\"value\":\"'.ReadingsVal($name , "volume", 50).'\",\"deviceType\":\"' . $hash->{helper}{DEVICETYPE} . '\"}}]}}","status":"ENABLED"}'
|
|
}
|
|
else {
|
|
$SendData = '{"behaviorId": "PREVIEW","sequenceJson": "{\"@type\":\"com.amazon.alexa.behaviors.model.Sequence\",\"startNode\":{\"@type\":\"com.amazon.alexa.behaviors.model.OpaquePayloadOperationNode\",\"type\":\"AlexaAnnouncement\",\"operationPayload\":{\"expireAfter\":\"PT5S\",\"content\":[{\"locale\":\"\",\"display\":{\"title\":\"FHEM\",\"body\":\"Speak\"},\"speak\":{\"type\":\"ssml\",\"value\":\"' . $SendData . '\"}}],\"customerId\":\"' . $hash->{IODev}->{helper}{".CUSTOMER"} .'\",\"target\":{\"customerId\":\"' . $hash->{IODev}->{helper}{".CUSTOMER"} .'\",\"devices\":[{\"deviceSerialNumber\":\"' . $hash->{helper}{".SERIAL"} . '\",\"deviceTypeId\":\"' . $hash->{helper}{DEVICETYPE} . '\"}]}}}}","status": "ENABLED"}';
|
|
}
|
|
|
|
$SendDataL = $SendData;
|
|
}
|
|
|
|
elsif ($type eq "homescreen" ) {
|
|
$SendUrl .= "/api/background-image";
|
|
$SendMetode = "POST";
|
|
|
|
$SendData = '{"backgroundImageID":"JqIFZhtBTx25wLGTJGdNGQ","backgroundImageType":"PERSONAL_PHOTOS","backgroundImageURL":"'.$SendData.'","deviceSerialNumber":"'.$hash->{helper}{".SERIAL"}.'","deviceType":"'.$hash->{helper}{DEVICETYPE}.'","softwareVersion":"'.$hash->{helper}{VERSION}.'"}';
|
|
|
|
$SendDataL = $SendData;
|
|
|
|
}
|
|
|
|
elsif ($type eq "textcommand") {
|
|
$SendUrl .= "/api/behaviors/preview";
|
|
$SendMetode = "POST";
|
|
my $Messagetext = $SendData;
|
|
$Messagetext =~ s/"/'/g;
|
|
$SendData = '{"behaviorId":"PREVIEW","sequenceJson":"{\"@type\":\"com.amazon.alexa.behaviors.model.Sequence\",\"startNode\":{\"@type\": \"com.amazon.alexa.behaviors.model.OpaquePayloadOperationNode\",\"nodeState\": null,\"name\": null,\"type\": \"Alexa.TextCommand\",\"skillId\": \"amzn1.ask.1p.tellalexa\",\"operationPayload\": {\"customerId\": \"' . $hash->{helper}{".CUSTOMER"} .'\",\"deviceType\": \"' . $hash->{helper}{DEVICETYPE} . '\",\"deviceSerialNumber\": \"' . $hash->{helper}{".SERIAL"} . '\",\"text\": \"' . $Messagetext .'\",\"locale\": \"de-DE\"},\"presentationDataList\": null,\"clientData\": null,\"context\": null,\"tag\": null},\"sequenceId\":\"amzn1.alexa.sequence.8f5aa289-c6d4-4a6f-a1b9-5b182e23be1e\"}","status":"ENABLED"}';
|
|
$SendDataL = $SendData;
|
|
}
|
|
|
|
else {
|
|
return;
|
|
}
|
|
|
|
# Log
|
|
Log3 $name, 4, "[$name] [echodevice_SendCommand] [$type] PushToCmdQueue SendURL =" .echodevice_anonymize($hash, $SendUrl);
|
|
Log3 $name, 4, "[$name] [echodevice_SendCommand] [$type] PushToCmdQueue SendData=" .$SendDataL;
|
|
|
|
#2018.01.14 - Übergabe SendCommandQuery
|
|
$SendParam = {
|
|
url => $SendUrl,
|
|
hash => $hash,
|
|
data => $SendData,
|
|
method => $SendMetode,
|
|
CL => $hash->{CL},
|
|
httpversion => "1.1",
|
|
type => $type
|
|
};
|
|
|
|
#2018.01.14 - PushToCmdQueue
|
|
|
|
my $QueueSize = scalar @{$hash->{helper}{CMD_QUEUE}};
|
|
my $FoundCMDQueue = 0;
|
|
my $Loglevel = 3;
|
|
my @GetSettings = ("getnotifications","alarmvolume","bluetoothstate","getdnd","wakeword","listitems_task","listitems_shopping","getdevicesettings","getisonline","devices","namedListsIDs","devicesstate","account","cookielogin6","activities","getbehavior","getsettingstraffic");
|
|
# Doppelte Queue Einträge herausfiltern
|
|
foreach my $CMDQueue (@{$hash->{helper}{CMD_QUEUE}}) {
|
|
if ($CMDQueue->{type} eq $type) {
|
|
if ((grep { $_ eq $type } @GetSettings)) {
|
|
$Loglevel = 4 if ($type eq "activities");
|
|
Log3 $name, $Loglevel, "[$name] [echodevice_SendCommand] [$QueueSize] IGNORIERE Command=" . $type . ' Abfrage in CMD_Queue schon vorhanden!';
|
|
$FoundCMDQueue = 1;
|
|
last;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($FoundCMDQueue == 0) {
|
|
push @{$hash->{helper}{CMD_QUEUE}}, $SendParam;
|
|
echodevice_HandleCmdQueue($hash);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
sub echodevice_HandleCmdQueue($) {
|
|
my ($hash, $param) = @_;
|
|
my $name = $hash->{NAME};
|
|
|
|
return undef if(!defined($hash->{helper}{CMD_QUEUE}));
|
|
$hash->{helper}{RUNNING_REQUEST} = 0 if(!defined($hash->{helper}{RUNNING_REQUEST}));
|
|
|
|
#Header auslesen
|
|
my $AmazonHeader;
|
|
|
|
# Browser User Agent
|
|
my $HeaderLanguage = AttrVal($name,"browser_language","de,en-US;q=0.7,en;q=0.3");
|
|
my $UserAgent = AttrVal($name,"browser_useragent","Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:62.0) Gecko/20100101 Firefox/62.0");
|
|
|
|
if (AttrVal($name,"browser_useragent_random",0) == 1) {
|
|
$UserAgent = join('', map{('a'..'z','A'..'Z',0..9)[rand 62]} 0..20);
|
|
}
|
|
|
|
# Queuenumber
|
|
$QueueNumber += 1;
|
|
|
|
readingsSingleUpdate ($hash, "BrowserUserAgent", $UserAgent ,0);
|
|
readingsSingleUpdate ($hash, "BrowserLanguage", $HeaderLanguage ,0);
|
|
$hash->{helper}{CMD_QUEUE_NUMBER} = $QueueNumber ;
|
|
|
|
# if($hash->{model} eq "ACCOUNT") {$AmazonHeader = "Cookie: ".$hash->{helper}{".COOKIE"}."\r\ncsrf: ".$hash->{helper}{".CSRF"}."\r\nContent-Type: application/json; charset=UTF-8";}
|
|
# else {$AmazonHeader = "Cookie: ".$hash->{IODev}->{helper}{".COOKIE"}."\r\ncsrf: ".$hash->{IODev}->{helper}{".CSRF"}."\r\nContent-Type: application/json; charset=UTF-8";}
|
|
|
|
if($hash->{model} eq "ACCOUNT") {$AmazonHeader = "User-Agent: ". $UserAgent ."\r\nAccept-Language: " . $HeaderLanguage . "\r\nDNT: 1\r\nConnection: keep-alive\r\nUpgrade-Insecure-Requests: 1\r\nCookie:".$hash->{helper}{".COOKIE"}."\r\ncsrf: ".$hash->{helper}{".CSRF"}."\r\nContent-Type: application/json; charset=UTF-8";}
|
|
else {$AmazonHeader = "User-Agent: ". $UserAgent ."\r\nAccept-Language: " . $HeaderLanguage . "\r\nDNT: 1\r\nConnection: keep-alive\r\nUpgrade-Insecure-Requests: 1\r\nCookie:".$hash->{IODev}->{helper}{".COOKIE"}."\r\ncsrf: ".$hash->{IODev}->{helper}{".CSRF"}."\r\nContent-Type: application/json; charset=UTF-8";}
|
|
|
|
if(not($hash->{helper}{RUNNING_REQUEST}) and @{$hash->{helper}{CMD_QUEUE}})
|
|
{
|
|
|
|
my $params = {
|
|
url => $param->{url},
|
|
header => $AmazonHeader,
|
|
timeout => 10,
|
|
noshutdown => 1,
|
|
keepalive => 1,
|
|
method => $param->{method},
|
|
data => $param->{data},
|
|
CL => $param->{CL},
|
|
hash => $hash,
|
|
type => $param->{type},
|
|
httpversion => $param->{httpversion},
|
|
queuenumber => $QueueNumber,
|
|
callback => \&echodevice_Parse
|
|
};
|
|
|
|
my $request = pop @{$hash->{helper}{CMD_QUEUE}};
|
|
|
|
map {$hash->{helper}{".HTTP_CONNECTION"}{$_} = $params->{$_}} keys %{$params};
|
|
map {$hash->{helper}{".HTTP_CONNECTION"}{$_} = $request->{$_}} keys %{$request};
|
|
|
|
my $type = $hash->{helper}{".HTTP_CONNECTION"}{type};
|
|
|
|
$hash->{helper}{RUNNING_REQUEST} = 1;
|
|
|
|
my $QueueSize = scalar @{$hash->{helper}{CMD_QUEUE}};
|
|
|
|
Log3 $name, 4, "[$name] [echodevice_HandleCmdQueue] [$type] [$QueueNumber] [$QueueSize] send command=" .echodevice_anonymize($hash, $hash->{helper}{".HTTP_CONNECTION"}{url}). " Data=" . $hash->{helper}{".HTTP_CONNECTION"}{data};
|
|
HttpUtils_NonblockingGet($hash->{helper}{".HTTP_CONNECTION"});
|
|
|
|
}
|
|
else {
|
|
Log3 $name, 4, "[$name] [echodevice_HandleCmdQueue] RUNNING_REQUEST=" . $hash->{helper}{RUNNING_REQUEST} . " type=" . $hash->{helper}{".HTTP_CONNECTION"}{type} if($hash->{helper}{RUNNING_REQUEST} == 1);
|
|
}
|
|
}
|
|
|
|
sub echodevice_SendLoginCommand($$$) {
|
|
my ( $hash, $type, $SendData ) = @_;
|
|
my $name = $hash->{NAME};
|
|
my $SendUrl;
|
|
my $param;
|
|
my $HeaderLanguage = AttrVal($name,"browser_language","de,en-US;q=0.7,en;q=0.3");
|
|
|
|
# Überspringen wenn Attr cookie gesetzt ist!
|
|
if(AttrVal( $name, "cookie", "none" ) ne "none" && $type ne "cookielogin6") {
|
|
Log3 $name, 3, "[$name] [echodevice_SendLoginCommand] echodevice_FirstStart";
|
|
echodevice_FirstStart($hash);
|
|
return;
|
|
}
|
|
|
|
Log3 $name, 4, "[$name] [echodevice_SendLoginCommand] [$type]";
|
|
|
|
# Browser User Agent
|
|
my $UserAgent = AttrVal($name,"browser_useragent","Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:62.0) Gecko/20100101 Firefox/62.0");
|
|
|
|
if (AttrVal($name,"browser_useragent_random",0) == 1) {
|
|
$UserAgent = join('', map{('a'..'z','A'..'Z',0..9)[rand 62]} 0..20);
|
|
}
|
|
|
|
readingsSingleUpdate ($hash, "BrowserUserAgent", $UserAgent ,0);
|
|
readingsSingleUpdate ($hash, "BrowserLanguage", $HeaderLanguage ,0);
|
|
|
|
# COOKIE LOGIN
|
|
if ($type eq "cookielogin1" ) {
|
|
$param->{url} = "https://".$hash->{helper}{SERVER}."/";
|
|
$param->{method} = "GET";
|
|
$param->{ignoreredirects} = 1;
|
|
$param->{header} = "User-Agent: ". $UserAgent ."\r\nAccept-Language: " . $HeaderLanguage . "\r\nDNT: 1\r\nConnection: keep-alive\r\nUpgrade-Insecure-Requests: 1";
|
|
$param->{callback} = \&echodevice_Parse;
|
|
$param->{type} = $type;
|
|
$param->{hash} = $hash;
|
|
$param->{timeout} = 10;
|
|
$param->{httpversion} = "1.1";
|
|
|
|
# Informationen füs Log
|
|
Log3 $name, 4, "[$name] [echodevice_SendLoginCommand] [$type] Accept-Language: $HeaderLanguage";
|
|
Log3 $name, 4, "[$name] [echodevice_SendLoginCommand] [$type] User-Agent: $UserAgent";
|
|
|
|
#Daten zurücksetzen
|
|
$hash->{helper}{".login_postdata"} = "";
|
|
$hash->{helper}{".login_location"} = "";
|
|
$hash->{helper}{".login_sessionid"} = "";
|
|
$hash->{helper}{".login_cookiestring"} = "";
|
|
|
|
readingsSingleUpdate ($hash, ".COOKIE", "" ,0);
|
|
readingsSingleUpdate ($hash, "COOKIE_TYPE", "NEW" ,0);
|
|
readingsSingleUpdate ($hash, "COOKIE_STATE", "START" ,0);
|
|
}
|
|
|
|
if ($type eq "cookielogin2" ) {
|
|
$param->{url} = "https://".$hash->{helper}{SERVER}."/";
|
|
$param->{method} = "GET";
|
|
$param->{header} = "User-Agent: ".$UserAgent."\r\nAccept-Language: " . $HeaderLanguage . "\r\nDNT: 1\r\nConnection: keep-alive\r\nUpgrade-Insecure-Requests: 1";
|
|
$param->{callback} = \&echodevice_Parse;
|
|
$param->{type} = $type;
|
|
$param->{hash} = $hash;
|
|
$param->{timeout} = 10;
|
|
$param->{httpversion} = "1.1";
|
|
}
|
|
|
|
if ($type eq "cookielogin3" ) {
|
|
|
|
my $location = $hash->{helper}{".login_location"};
|
|
my $cookiestring = $hash->{helper}{".login_cookiestring"};
|
|
my $postdata = $hash->{helper}{".login_postdata"};
|
|
|
|
#Log3 $name, 3, "cookielogin3: ".$hash->{helper}{".login_cookiestring"} ;
|
|
#Log3 $name, 3, "cookielogin3: ".$hash->{helper}{".login_postdata"} ;
|
|
|
|
$param->{url} = "https://www.amazon.de/ap/signin";
|
|
$param->{method} = "POST";
|
|
$param->{header} = "User-Agent: ".$UserAgent."\r\nAccept-Language: " . $HeaderLanguage . "\r\nDNT: 1\r\nConnection: keep-alive\r\nUpgrade-Insecure-Requests: 1\r\nReferer: $location\r\nCookie: $cookiestring";
|
|
$param->{callback} = \&echodevice_Parse;
|
|
$param->{data} = $postdata;
|
|
$param->{type} = $type;
|
|
$param->{hash} = $hash;
|
|
#$param->{timeout} = 10;
|
|
$param->{httpversion} = "1.0";
|
|
}
|
|
|
|
if ($type eq "cookielogin4" ) {
|
|
|
|
my $location = $hash->{helper}{".login_location"};
|
|
my $cookiestring = $hash->{helper}{".login_cookiestring"};
|
|
my $postdata = $hash->{helper}{".login_postdata"};
|
|
my $sessionid = $hash->{helper}{".login_sessionid"};
|
|
|
|
Log3 $name, 4, "cookielogin4: ".$hash->{helper}{".login_cookiestring"} ;
|
|
Log3 $name, 4, "cookielogin4: ".$hash->{helper}{".login_postdata"} ;
|
|
|
|
$param->{url} = "https://www.amazon.de/ap/signin";
|
|
$param->{method} = "POST";
|
|
$param->{header} = "User-Agent: ".$UserAgent."\r\nAccept-Language: " . $HeaderLanguage . "\r\nDNT: 1\r\nConnection: keep-alive\r\nUpgrade-Insecure-Requests: 1\r\nReferer: https://www.amazon.de/ap/signin/$sessionid\r\nCookie: $cookiestring";
|
|
$param->{callback} = \&echodevice_Parse;
|
|
|
|
|
|
|
|
if ($hash->{helper}{TWOFA} eq "" || substr $hash->{helper}{TWOFA}, 0, 1 eq "n" || substr $hash->{helper}{TWOFA}, 0, 1 eq "u" ) {
|
|
readingsSingleUpdate ($hash, "2FACode", "not used" ,0);
|
|
$param->{data} = $postdata."email=".uri_escape(echodevice_decrypt($hash->{helper}{".USER"}))."&password=".uri_escape(echodevice_decrypt($hash->{helper}{".PASSWORD"}));#."&rememberMe=true";
|
|
Log3 $name, 4, "[$name] [echodevice_SendLoginCommand] [$type] 2FACode not use";
|
|
#Log3 $name, 4, "[$name] [echodevice_SendLoginCommand] [$type] " . $param->{data};
|
|
}
|
|
else {
|
|
readingsSingleUpdate ($hash, "2FACode", "used " .$hash->{helper}{TWOFA} ,0);
|
|
my $zweiFA = $hash->{helper}{TWOFA} . "&rememberDevice";
|
|
$param->{data} = $postdata."email=".uri_escape(echodevice_decrypt($hash->{helper}{".USER"}))."&password=".uri_escape(echodevice_decrypt($hash->{helper}{".PASSWORD"})).$zweiFA;
|
|
Log3 $name, 4, "[$name] [echodevice_SendLoginCommand] [$type] 2FACode use " . $hash->{helper}{TWOFA} ;
|
|
}
|
|
|
|
$param->{ignoreredirects} = 1;
|
|
$param->{type} = $type;
|
|
$param->{hash} = $hash;
|
|
#$param->{timeout} = 10;
|
|
$param->{httpversion} = "1.0";
|
|
$hash->{helper}{TWOFA} = "";
|
|
}
|
|
|
|
if ($type eq "cookielogin4captcha" ) {
|
|
|
|
my $location = $hash->{helper}{".login_location"};
|
|
my $cookiestring = $hash->{helper}{".login_cookiestring"};
|
|
my $sessionid = $hash->{helper}{".login_sessionid"};
|
|
|
|
$param->{url} = "https://www.amazon.de/ap/signin";
|
|
$param->{method} = "POST";
|
|
$param->{header} = "User-Agent: ".$UserAgent."\r\nAccept-Language: " . $HeaderLanguage . "\r\nDNT: 1\r\nConnection: keep-alive\r\nUpgrade-Insecure-Requests: 1\r\nReferer: https://www.amazon.de/ap/signin/$sessionid\r\nCookie: $cookiestring";
|
|
$param->{callback} = \&echodevice_Parse;
|
|
|
|
# Captcha Infos einlesen
|
|
my $HTMLFilename = $name . "_cookielogin4.html";
|
|
my $file = $FW_dir . "/echodevice/results/" . $HTMLFilename ;
|
|
my $document = do {
|
|
local $/ = undef;
|
|
open my $fh, "<", $file
|
|
or die "could not open $file: $!";
|
|
<$fh>;
|
|
};
|
|
|
|
my @formparams = ('create', 'workflowState','appActionToken','appAction','showRmrMe','captchaObfuscationLevel','openid.identity','forceValidateCaptcha','pageId','ces','openid.return_to','prevRID','openid.assoc_handle','openid.mode','prepopulatedLoginId','failedSignInCount','openid.claimed_id','openid.ns','showPasswordChecked','rememberMe','use_image_captcha');
|
|
my $postdata = "";
|
|
foreach my $formparam (@formparams){
|
|
my $value = ($document =~ /type="hidden" name="$formparam" value="(.*)"/);
|
|
$value = $1;
|
|
$value =~ /^(.*?)"/;
|
|
$postdata .= $formparam."=".$1."&"
|
|
}
|
|
|
|
$param->{data} = $postdata."email=".uri_escape(echodevice_decrypt($hash->{helper}{".USER"}))."&guess=" .$hash->{helper}{CAPTCHA}."&password=".uri_escape(echodevice_decrypt($hash->{helper}{".PASSWORD"}));#."&rememberMe=true";
|
|
#Log3 $name, 4, "[$name] [echodevice_SendLoginCommand] [$type] " . $param->{data};
|
|
|
|
$param->{ignoreredirects} = 1;
|
|
$param->{type} = $type;
|
|
$param->{hash} = $hash;
|
|
$param->{timeout} = 10;
|
|
$param->{httpversion} = "1.1";
|
|
$hash->{helper}{TWOFA} = "";
|
|
$hash->{helper}{CAPTCHA} = "";
|
|
}
|
|
|
|
if ($type eq "cookielogin5" ) {
|
|
|
|
my $cookiestring = $hash->{helper}{".login_cookiestring"};
|
|
|
|
$param->{url} = "https://".$hash->{helper}{SERVER}."/api/bootstrap?version=0&_=".int(time);
|
|
$param->{header} = "User-Agent: ".$UserAgent."\r\nAccept-Language: " . $HeaderLanguage . "\r\nDNT: 1\r\nConnection: keep-alive\r\nUpgrade-Insecure-Requests: 1\r\nReferer: https://".$hash->{helper}{SERVER}."/spa/index.html\r\nOrigin: https://".$hash->{helper}{SERVER}."\r\nCookie: $cookiestring";
|
|
$param->{callback} = \&echodevice_Parse;
|
|
$param->{type} = $type;
|
|
$param->{hash} = $hash;
|
|
$param->{httpversion} = "1.1";
|
|
}
|
|
|
|
if ($type eq "cookielogin6" ) {
|
|
$param->{url} = "https://".$hash->{helper}{SERVER}."/api/bootstrap";
|
|
$param->{header} = 'Cookie: '.$hash->{helper}{".COOKIE"};
|
|
$param->{callback} = \&echodevice_ParseAuth;
|
|
$param->{noshutdown} = 1;
|
|
$param->{keepalive} = 1;
|
|
$param->{type} = $type;
|
|
$param->{hash} = $hash;
|
|
$param->{timeout} = 10;
|
|
$param->{httpversion} = "1.1";
|
|
}
|
|
|
|
HttpUtils_NonblockingGet($param);
|
|
|
|
}
|
|
|
|
sub echodevice_Parse($$$) {
|
|
my ($param, $err, $data) = @_;
|
|
my $hash = $param->{hash};
|
|
my $name = $hash->{NAME};
|
|
my $msgtype = $param->{type};
|
|
my $msgnumber = $param->{queuenumber};
|
|
|
|
Log3 $name, 4, "[$name] [echodevice_Parse] [$msgtype] [$msgnumber] ";
|
|
Log3 $name, 5, "[$name] [echodevice_Parse] [$msgtype] [$msgnumber] DATA Dumper=" . Dumper(echodevice_anonymize($hash, $data));
|
|
|
|
$hash->{helper}{RUNNING_REQUEST} = 0;
|
|
|
|
if ($msgtype eq "account") {
|
|
Log3 $name, 4, "[$name] [echodevice_Parse] [$msgtype] [$msgnumber] DATA Dumper=" . Dumper(echodevice_anonymize($hash, $data));
|
|
}
|
|
|
|
# Nächsten Auftrag starten
|
|
echodevice_HandleCmdQueue($hash);
|
|
|
|
# HTML Informationen mit schreiben
|
|
if (AttrVal($name,"browser_save_data",0) == 1) {
|
|
|
|
#Verzeichnis echodevice anlegen
|
|
mkdir($FW_dir . "/echodevice", 0777) unless(-d $FW_dir . "/echodevice" );
|
|
mkdir($FW_dir . "/echodevice/results", 0777) unless(-d $FW_dir . "/echodevice/results" );
|
|
|
|
# Eventuell vorhandene Datei löschen
|
|
my $HTMLFilename = $name . "_" . $msgtype . ".html";
|
|
my $HeaderFilename = $name . "_" . $msgtype . "_header.html";
|
|
if ((-e $FW_dir . "/echodevice/results/". $HTMLFilename)) {unlink $FW_dir . "/echodevice/results/".$HTMLFilename}
|
|
if ((-e $FW_dir . "/echodevice/results/". $HeaderFilename)) {unlink $FW_dir . "/echodevice/results/".$HeaderFilename}
|
|
|
|
# Datei anlegen
|
|
open(FH, ">$FW_dir/echodevice/results/$HTMLFilename");
|
|
print FH $data;
|
|
close(FH);
|
|
|
|
# Datei anlegen
|
|
open(FH, ">$FW_dir/echodevice/results/$HeaderFilename");
|
|
print FH $param->{httpheader};
|
|
close(FH);
|
|
|
|
}
|
|
|
|
# COOKIE LOGIN Part
|
|
if($msgtype eq "cookielogin1") {
|
|
|
|
my $location = $param->{httpheader};
|
|
$location =~ /Location: (.+?)\s/;
|
|
$location = $1;
|
|
|
|
#$location = "https://www.amazon.de/ap/signin?_encoding=UTF8&accountStatusPolicy=&disableCorpSignUp=&openid.assoc_handle=deflex&openid.claimed_id=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0%2Fidentifier_select&openid.identity=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0%2Fidentifier_select&openid.mode=checkid_setup&openid.ns=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0&openid.ns.pape=http%3A%2F%2Fspecs.openid.net%2Fextensions%2Fpape%2F1.0&openid.pape.max_auth_age=0&openid.return_to=https%3A%2F%2Flayla.amazon.de%2Fgp%2Fyourstore%3Fie%3DUTF8%26action%3Dsign-out%26path%3D%252Fgp%252Fyourstore%26ref_%3Dpd_irl_gw_r%26signIn%3D1%26useRedirectOnSuccess%3D1";
|
|
|
|
$hash->{helper}{".login_location"} = $location;
|
|
|
|
#Log3 $name, 3, "Cookie 3 : ".$hash->{helper}{".login_location"} ;
|
|
|
|
echodevice_SendLoginCommand($hash,"cookielogin2","");
|
|
return;
|
|
}
|
|
|
|
if($msgtype eq "cookielogin2") {
|
|
|
|
my (@cookies) = ($param->{httpheader} =~ /Set-Cookie: (.*)\s/g);
|
|
|
|
my $cookiestring = "";
|
|
my $sessionid = "";
|
|
foreach my $cookie (@cookies){
|
|
next if($cookie =~ /1970/);
|
|
$cookie =~ /(.*) (expires=|Version=|Domain)/;
|
|
$cookiestring .= $1." ";
|
|
|
|
#Session ID
|
|
my @SessionID = split("=",$1);
|
|
|
|
if (@SessionID[0] eq "session-id") {
|
|
$sessionid = @SessionID[1];
|
|
$sessionid =~ s/;//g;
|
|
Log3 $name, 4, "Cookie 2 : COO = ".$sessionid ;
|
|
$sessionid = $cookie;
|
|
}
|
|
}
|
|
|
|
#my @formparams = ('appActionToken', 'appAction', 'openid.return_to', 'prevRID', 'workflowState', 'showPasswordChecked');
|
|
my @formparams = ('create', 'workflowState','appActionToken', 'appAction', 'showRmrMe', 'openid.return_to', 'prevRID', 'openid.identity', 'openid.assoc_handle', 'openid.mode', 'failedSignInCount', 'openid.claimed_id', 'pageId', 'openid.ns', 'showPasswordChecked');
|
|
my $postdata = "";
|
|
foreach my $formparam (@formparams){
|
|
my $value = ($data =~ /type="hidden" name="$formparam" value="(.*)"/);
|
|
$value = $1;
|
|
$value =~ /^(.*?)"/;
|
|
$postdata .= $formparam."=".$1."&"
|
|
}
|
|
|
|
$hash->{helper}{".login_postdata"} = $postdata;
|
|
$hash->{helper}{".login_cookiestring"} = $cookiestring;
|
|
$hash->{helper}{".login_sessionid"} = $sessionid;
|
|
|
|
#Log3 $name, 3, "Cookie 2 : login_postdata = ".$hash->{helper}{".login_postdata"} ;
|
|
#Log3 $name, 3, "Cookie 2 : login_cookiestring = ".$hash->{helper}{".login_cookiestring"} ;
|
|
#Log3 $name, 3, "Cookie 2 : login_sessionid = ".$hash->{helper}{".login_sessionid"} ;
|
|
|
|
echodevice_SendLoginCommand($hash,"cookielogin3","");
|
|
return;
|
|
}
|
|
|
|
if($msgtype eq "cookielogin3") {
|
|
|
|
#my @formparams = ('appActionToken', 'appAction', 'openid.return_to', 'prevRID', 'workflowState', 'showPasswordChecked');
|
|
my @formparams = ('create', 'workflowState','appActionToken', 'appAction', 'showRmrMe', 'openid.return_to', 'prevRID', 'openid.identity', 'openid.assoc_handle', 'openid.mode', 'failedSignInCount', 'openid.claimed_id', 'pageId', 'openid.ns', 'showPasswordChecked');
|
|
my $postdata = "";
|
|
foreach my $formparam (@formparams){
|
|
my $value = ($data =~ /type="hidden" name="$formparam" value="(.*)"/);
|
|
$value = $1;
|
|
$value =~ /^(.*?)"/;
|
|
$postdata .= $formparam."=".$1."&"
|
|
}
|
|
|
|
my (@cookies2) = ($param->{httpheader} =~ /Set-Cookie: (.*)\s/g);
|
|
|
|
my $sessionid = "";
|
|
my $cookiestring2 = "";
|
|
foreach my $cookie (@cookies2){
|
|
next if($cookie =~ /1970/);
|
|
$cookie =~ /(.*) (expires|Version|Domain)/;
|
|
$cookiestring2 .= $1." ";
|
|
$cookiestring2 =~ /ubid-acbde=(.*);/;
|
|
$sessionid = $1;
|
|
}
|
|
|
|
$hash->{helper}{".login_postdata"} = $postdata;
|
|
$hash->{helper}{".login_sessionid"} = $sessionid;
|
|
$hash->{helper}{".login_cookiestring"} = $hash->{helper}{".login_cookiestring"} . $cookiestring2;
|
|
|
|
#Log3 $name, 3, "Cookie 3 : ".$hash->{helper}{".login_postdata"} ;
|
|
#Log3 $name, 3, "Cookie 3 : ".$hash->{helper}{".login_sessionid"} ;
|
|
#Log3 $name, 3, "Cookie 3 : ".$hash->{helper}{".login_cookiestring"} ;
|
|
|
|
|
|
echodevice_SendLoginCommand($hash,"cookielogin4","");
|
|
return;
|
|
}
|
|
|
|
if($msgtype eq "cookielogin4" || $msgtype eq "cookielogin4captcha") {
|
|
|
|
my (@cookies3) = ($param->{httpheader} =~ /Set-Cookie: (.*)\s/g);
|
|
|
|
my $cookiestring3 = "";
|
|
my $cookiestring = $hash->{helper}{".login_cookiestring"};
|
|
|
|
foreach my $cookie (@cookies3){
|
|
#Log3 $name, 5, "Cookie: ".$cookie;
|
|
next if($cookie =~ /1970/);
|
|
$cookie =~ s/Version=1; //g;
|
|
$cookie =~ /(.*) (expires|Version|Domain)/;
|
|
$cookie = $1;
|
|
next if($cookiestring =~ /\Q$cookie\E/);
|
|
$cookiestring3 .= $cookie." ";
|
|
}
|
|
#Log3 $name, 4, "[$name] [echodevice_Parse] [cookiestring3] = $cookiestring3";
|
|
$hash->{helper}{".login_cookiestring"}.= $cookiestring3;
|
|
#Log3 $name, 3, "Cookie 4 : ".$cookiestring3 ;
|
|
|
|
#$cookiestring3 =~s/"//g;
|
|
#Log3 $name, 3, "Cookie 4 : ".$cookiestring3 ;
|
|
|
|
#Log3 $name, 3, "Cookie 4 : ".$hash->{helper}{".login_cookiestring"} ;
|
|
echodevice_SendLoginCommand($hash,"cookielogin5","");
|
|
return;
|
|
}
|
|
|
|
if($msgtype eq "cookielogin5") {
|
|
|
|
my (@cookies4) = ($param->{httpheader} =~ /Set-Cookie: (.*)\s/g);
|
|
my $cookiestring4 = "";
|
|
my $cookiestring = $hash->{helper}{".login_cookiestring"};
|
|
|
|
foreach my $cookie (@cookies4){
|
|
#Log3 $name, 5, "Cookie: ".$cookie;
|
|
next if($cookie =~ /1970/);
|
|
$cookie =~ s/Version=1; //g;
|
|
$cookie =~ /(.*) (expires|Version)/;
|
|
$cookie = $1;
|
|
next if($cookiestring =~ /\Q$cookie\E/);
|
|
$cookiestring4 .= $cookie." ";
|
|
}
|
|
$cookiestring .= $cookiestring4;
|
|
|
|
$hash->{helper}{".login_cookiestring"}.= $cookiestring4;
|
|
|
|
if($cookiestring =~ /doctype html/) {
|
|
#RemoveInternalTimer($hash);
|
|
Log3 $name, 4, "[$name] [echodevice_Parse] [$msgtype] [$msgnumber] Login failed";
|
|
readingsBeginUpdate($hash);
|
|
readingsBulkUpdate($hash, "state", "unauthorized", 1);
|
|
readingsEndUpdate($hash,1);
|
|
$hash->{STATE} = "LOGIN ERROR";
|
|
return undef;
|
|
}
|
|
#Log3 $name, 4, "[$name] [echodevice_Parse] [cookiestring] = $cookiestring";
|
|
$hash->{helper}{".COOKIE"} = $cookiestring;
|
|
$hash->{helper}{".COOKIE"} =~ /csrf=([-\w]+)[;\s]?(.*)?$/ if(defined($hash->{helper}{".COOKIE"}));
|
|
$hash->{helper}{".CSRF"} = $1 if(defined($hash->{helper}{".COOKIE"}));
|
|
#Log3 $name, 3, "Cookie 4 : ".$cookiestring ;
|
|
|
|
if(defined($hash->{helper}{".COOKIE"})){
|
|
readingsSingleUpdate ($hash, ".COOKIE", $hash->{helper}{".COOKIE"} ,0); # Cookie als READING festhalten!
|
|
readingsSingleUpdate ($hash, "COOKIE_TYPE", "NEW" ,0);
|
|
}
|
|
echodevice_SendLoginCommand($hash,"cookielogin6","");
|
|
return;
|
|
}
|
|
|
|
if($msgtype eq "cookielogin6") {
|
|
readingsSingleUpdate ($hash, "COOKIE_STATE", "OK" ,0);
|
|
echodevice_SendCommand($hash,"devices","");
|
|
return;
|
|
}
|
|
|
|
if($msgtype eq "notifications_delete" || $msgtype eq "alarm_on" || $msgtype eq "alarm_off" || $msgtype eq "reminderitem") {
|
|
|
|
my $IODev = $hash->{IODev}->{NAME};
|
|
Log3 $name, 4, "[$name] [echodevice_Parse] [$msgtype] [$msgnumber] sendToFHEM get $IODev settings";
|
|
print (fhem( "get $IODev settings" )) ;
|
|
|
|
return;
|
|
}
|
|
|
|
if($data =~ /doctype html/ || $data =~ /cookie is missing/){
|
|
#RemoveInternalTimer($hash);
|
|
Log3 $name, 4, "[$name] [echodevice_Parse] [$msgtype] [$msgnumber] Invalid cookie";
|
|
readingsBeginUpdate($hash);
|
|
readingsBulkUpdate($hash, "state", "unauthorized", 1);
|
|
readingsEndUpdate($hash,1);
|
|
$hash->{STATE} = "COOKIE ERROR";
|
|
|
|
return undef;
|
|
}
|
|
|
|
if($err){
|
|
Log3 $name, 4, "[$name] [echodevice_Parse] [$msgtype] [$msgnumber] connection error $msgtype $err";
|
|
return undef;
|
|
}
|
|
|
|
if($data =~ /No routes found/){
|
|
# Spezial set Volume
|
|
if ($msgtype eq "command") {}
|
|
else {
|
|
Log3 $name, 4, "[$name] [echodevice_Parse] [$msgtype] [$msgnumber] No routes found $msgtype";
|
|
readingsBeginUpdate($hash);
|
|
readingsBulkUpdate($hash, "state", "timeout", 1);
|
|
readingsEndUpdate($hash,1);
|
|
}
|
|
return undef;
|
|
}
|
|
|
|
if($data =~ /UnknownOperationException/){
|
|
Log3 $name, 4, "[$name] [echodevice_Parse] [$msgtype] [$msgnumber] Unknown Operation";
|
|
readingsBeginUpdate($hash);
|
|
readingsBulkUpdate($hash, "state", "unknown", 1);
|
|
readingsEndUpdate($hash,1);
|
|
return undef;
|
|
}
|
|
|
|
if($msgtype eq "setting" || $msgtype eq "command"){
|
|
InternalTimer( gettimeofday() + 3, "echodevice_GetSettings", $hash, 0);
|
|
return undef;
|
|
}
|
|
|
|
elsif($msgtype eq "null" || $msgtype eq "primeplayeigeneplaylist" || $msgtype eq "primeplayeigene" || $msgtype eq "primeplaysender" || $msgtype eq "primeplaylist" || $msgtype eq "textmessage" || $msgtype eq "volume_alarm" || $msgtype eq "bluetooth_disconnect" || $msgtype eq "bluetooth_connect" || $msgtype eq "dnd" || $msgtype eq "list" || $msgtype eq "track") {
|
|
return undef;
|
|
}
|
|
|
|
elsif($msgtype eq "item_task_delete" || $msgtype eq "item_task_add") {
|
|
echodevice_SendCommand($hash,"listitems_task","TASK");
|
|
return undef;
|
|
}
|
|
|
|
elsif($msgtype eq "item_shopping_delete" || $msgtype eq "item_shopping_add") {
|
|
echodevice_SendCommand($hash,"listitems_shopping","SHOPPING_ITEM");
|
|
return undef;
|
|
}
|
|
|
|
if($@) {
|
|
if($data =~ /doctype html/ || $data =~ /cookie is missing/){
|
|
#RemoveInternalTimer($hash);
|
|
Log3 $name, 4, "[$name] [echodevice_Parse] [$msgtype] [$msgnumber] Invalid cookie";
|
|
readingsBeginUpdate($hash);
|
|
readingsBulkUpdate($hash, "state", "unauthorized", 1);
|
|
readingsEndUpdate($hash,1);
|
|
$hash->{STATE} = "COOKIE ERROR";
|
|
#InternalTimer( gettimeofday() + 10, "echodevice_CheckAuth", $hash, 0) if($hash->{model} eq "ACCOUNT");
|
|
|
|
return undef;
|
|
}
|
|
readingsBeginUpdate($hash);
|
|
readingsBulkUpdate($hash, "state", "error", 1);
|
|
readingsEndUpdate($hash,1);
|
|
Log3 $name, 4, "[$name] [echodevice_Parse] [$msgtype] [$msgnumber] json evaluation error ".$@."\n".Dumper(echodevice_anonymize($hash, $data));
|
|
|
|
return undef;
|
|
}
|
|
|
|
readingsBeginUpdate($hash);
|
|
readingsBulkUpdateIfChanged($hash, "state", "connected", 1);
|
|
readingsEndUpdate($hash,1);
|
|
|
|
# Prüfen ob es sich um ein json String handelt!
|
|
if (index($data, '{') == -1) {$data = '{"data": "nodata"}';}
|
|
|
|
my $json = eval { JSON->new->utf8(0)->decode($data) };
|
|
|
|
if($msgtype eq "activities") {
|
|
if (ref($json) eq "HASH") {
|
|
if(defined($json->{activities}) && ref($json->{activities}) eq "ARRAY") {
|
|
foreach my $card (@{$json->{activities}}) {
|
|
# Device ID herausfiltern
|
|
my $sourceDeviceIds = "";
|
|
foreach my $cards (@{$card->{sourceDeviceIds}}) {
|
|
$sourceDeviceIds = $cards->{serialNumber};
|
|
}
|
|
|
|
# Informationen in das ECHO Device eintragen
|
|
if(defined($modules{$hash->{TYPE}}{defptr}{$sourceDeviceIds})) {
|
|
my $echohash = $modules{$hash->{TYPE}}{defptr}{$sourceDeviceIds};
|
|
#my $timestamp = int(time - ReadingsAge($echohash->{NAME},'voice',time))-5;
|
|
my $timestamp = int(ReadingsVal($echohash->{NAME},'voice_timestamp',9999));
|
|
my $IgnoreVoiceCommand = AttrVal($name,"ignorevoicecommand","");
|
|
#Log3 $name, 3, "[$name] [echodevice_Parse] [" . $echohash->{NAME} . "] timestamp = $timestamp / " . int($card->{creationTimestamp});
|
|
|
|
#next if($timestamp eq $card->{creationTimestamp});
|
|
next if($timestamp >= int($card->{creationTimestamp}));
|
|
#next if($timestamp >= int($card->{creationTimestamp}/1000));
|
|
next if($card->{description} !~ /firstUtteranceId/);
|
|
|
|
#https://forum.fhem.de/index.php/topic,82631.msg906424.html#msg906424
|
|
next if($IgnoreVoiceCommand ne "" && $card->{description} =~ m/$IgnoreVoiceCommand/i);
|
|
next if($card->{activityStatus} eq "DISCARDED_NON_DEVICE_DIRECTED_INTENT");
|
|
|
|
my $textjson = $card->{description};
|
|
$textjson =~ s/\\//g;
|
|
my $cardjson = eval { JSON->new->utf8(0)->decode($textjson) };
|
|
|
|
next if($@);
|
|
next if(!defined($cardjson->{summary}));
|
|
next if($cardjson->{summary} eq "");
|
|
|
|
$echohash->{".updateTimestamp"} = FmtDateTime(int($card->{creationTimestamp}/1000));
|
|
readingsBeginUpdate($echohash);
|
|
readingsBulkUpdate($echohash, "voice", $cardjson->{summary}, 1);
|
|
readingsBulkUpdate($echohash, "voice_timestamp", $card->{creationTimestamp}, 1);
|
|
readingsEndUpdate($echohash,1);
|
|
$echohash->{CHANGETIME}[0] = FmtDateTime(int($card->{creationTimestamp}/1000));
|
|
#Log3 $name, 3, "[$name] [echodevice_Parse] [" . $echohash->{NAME} . "] Alexatext = ".$cardjson->{summary};
|
|
}
|
|
}
|
|
}
|
|
|
|
# Timer für Realtime Check!
|
|
my $IntervalVoice = int(AttrVal($name,"intervalvoice",999999));
|
|
|
|
if ($IntervalVoice != 999999 && $hash->{STATE} eq "connected" && AttrVal($name,"disable",0) == 0) {
|
|
Log3 $name, 5, "[$name] [echodevice_Parse] [$msgtype] [$msgnumber] refresh voice command IntervalVoice=$IntervalVoice ";
|
|
$hash->{helper}{echodevice_refreshvoice} = 1;
|
|
$hash->{helper}{echodevice_refreshvoice_lastdate} = time();
|
|
RemoveInternalTimer($hash, "echodevice_refreshvoice");
|
|
InternalTimer(gettimeofday() + $IntervalVoice , "echodevice_refreshvoice", $hash, 0);
|
|
}
|
|
else {
|
|
$hash->{helper}{echodevice_refreshvoice} = 0;
|
|
}
|
|
}
|
|
else {
|
|
Log3 $name, 3, "[$name] [echodevice_Parse] [$msgtype] [$msgnumber] WRONG JSON Type Type=" . ref($json);
|
|
}
|
|
}
|
|
|
|
elsif($msgtype eq "account") {
|
|
|
|
my $i=1;
|
|
if ($data eq '{"data": "nodata"}') {
|
|
}
|
|
else {
|
|
if(ref($json) eq 'ARRAY') {
|
|
foreach my $account (@{$json}) {
|
|
$hash->{helper}{".COMMSID"} = $account->{commsId} if(defined($account->{commsId}));
|
|
$hash->{helper}{".DIRECTID"} = $account->{directedId} if(defined($account->{directedId}));
|
|
last if(1<$i++);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
elsif($msgtype eq "cards") {
|
|
my $timestamp = int(time - ReadingsAge($name,'voice',time));
|
|
return undef if(!defined($json->{cards}));
|
|
return undef if(ref($json->{cards}) ne "ARRAY");
|
|
foreach my $card (reverse(@{$json->{cards}})) {
|
|
#next if($card->{cardType} ne "TextCard");
|
|
#next if($card->{sourceDevice}{serialNumber} ne $hash->{helper}{".SERIAL"});
|
|
next if($timestamp >= int($card->{creationTimestamp}/1000));
|
|
next if(!defined($card->{playbackAudioAction}{mainText}));
|
|
readingsBeginUpdate($hash);
|
|
$hash->{".updateTimestamp"} = FmtDateTime(int($card->{creationTimestamp}/1000));
|
|
readingsBulkUpdate( $hash, "voice", $card->{playbackAudioAction}{mainText}, 1 );
|
|
$hash->{CHANGETIME}[0] = FmtDateTime(int($card->{creationTimestamp}/1000));
|
|
readingsEndUpdate($hash,1);
|
|
}
|
|
return undef;
|
|
}
|
|
|
|
elsif($msgtype eq "media") {
|
|
|
|
readingsBeginUpdate($hash);
|
|
|
|
if (defined($json->{currentState} )) {
|
|
if ($json->{currentState} ne "IDLE") {
|
|
#echodevice_SendCommand($hash,"player",""); # Player läuft! Daten abfragen!
|
|
}
|
|
else {
|
|
readingsBulkUpdate($hash, "progress", "0", 1);
|
|
readingsBulkUpdate($hash, "progresslen", "0", 1);
|
|
readingsBulkUpdate($hash, "shuffle", $json->{shuffling}?"on":"off", 1) if(defined($json->{shuffling}));
|
|
readingsBulkUpdate($hash, "repeat", $json->{looping}?"on":"off", 1) if(defined($json->{looping}));
|
|
readingsBulkUpdate($hash, "volume", $json->{volume}, 1) if(defined($json->{volume}));
|
|
readingsBulkUpdate($hash, "mute", $json->{muted}?"on":"off", 1) if(defined($json->{muted}));
|
|
}
|
|
}
|
|
|
|
readingsEndUpdate($hash,1);
|
|
}
|
|
|
|
elsif($msgtype eq "player") {
|
|
|
|
# Beenden wenn keine Daten vorhanden!
|
|
if(defined($json->{playerInfo})){
|
|
readingsBeginUpdate($hash);
|
|
my $TempTuneInName ;
|
|
my $TempTuneInURL ;
|
|
|
|
# Play Status
|
|
if(!defined($json->{playerInfo}{state}) || $json->{playerInfo}{state} eq "IDLE" ){
|
|
readingsBulkUpdate($hash, "playStatus", "stopped", 1);
|
|
readingsBulkUpdate($hash, "currentArtwork", "-", 1);
|
|
readingsBulkUpdate($hash, "currentTitle", "-", 1);
|
|
readingsBulkUpdate($hash, "currentArtist", "-", 1);
|
|
readingsBulkUpdate($hash, "currentAlbum", "-", 1);
|
|
readingsBulkUpdate($hash, "currentTuneInID", "-", 1);
|
|
readingsBulkUpdate($hash, "channel", "-", 1);
|
|
readingsBulkUpdate($hash, "progress", 0, 1);
|
|
readingsBulkUpdate($hash, "progresslen", 0, 1);
|
|
}
|
|
else {
|
|
|
|
readingsBulkUpdate($hash, "playStatus", lc($json->{playerInfo}{state}), 1);
|
|
|
|
if(defined($json->{playerInfo}{infoText})) {
|
|
readingsBulkUpdate($hash, "currentTitle", $json->{playerInfo}{infoText}{title}, 1) if(defined($json->{playerInfo}{infoText}{title}));
|
|
readingsBulkUpdate($hash, "currentArtist", $json->{playerInfo}{infoText}{subText1}, 1) if(defined($json->{playerInfo}{infoText}{subText1}));
|
|
readingsBulkUpdate($hash, "currentAlbum", $json->{playerInfo}{infoText}{subText2}, 1) if(defined($json->{playerInfo}{infoText}{subText2}));
|
|
readingsBulkUpdate($hash, "currentTitle", "-", 1) if(!defined($json->{playerInfo}{infoText}{title}));
|
|
readingsBulkUpdate($hash, "currentArtist", "-", 1) if(!defined($json->{playerInfo}{infoText}{subText1}));
|
|
readingsBulkUpdate($hash, "currentAlbum", "-", 1) if(!defined($json->{playerInfo}{infoText}{subText2}));
|
|
}
|
|
|
|
if(defined($json->{playerInfo}{provider})) {
|
|
readingsBulkUpdate($hash, "channel", $json->{playerInfo}{provider}{providerName}, 1) if(defined($json->{playerInfo}{provider}{providerName}));
|
|
$TempTuneInName = "TuneIn" if (lc($json->{playerInfo}{provider}{providerName}) eq 'tunein live-radio' || lc($json->{playerInfo}{provider}{providerName}) eq 'tunein-liveradio') ;
|
|
} else {
|
|
readingsBulkUpdate($hash, "channel", "-", 1);
|
|
}
|
|
|
|
if(defined($json->{playerInfo}{mainArt})) {
|
|
if(defined($json->{playerInfo}{mainArt}{url})){
|
|
readingsBulkUpdate($hash, "currentArtwork", $json->{playerInfo}{mainArt}{url}, 1);
|
|
$TempTuneInURL = $json->{playerInfo}{mainArt}{url};
|
|
}
|
|
else{
|
|
readingsBulkUpdate($hash, "currentArtwork", "-", 1);
|
|
}
|
|
}
|
|
|
|
if (lc($json->{playerInfo}{state}) eq "playing") {
|
|
# TuneIn ID festhalten
|
|
if ($TempTuneInURL ne "" && $TempTuneInName eq "TuneIn") {
|
|
my @TuneInID = split("/",$TempTuneInURL);
|
|
if (@TuneInID >= 3) {
|
|
$TempTuneInName = @TuneInID[3];
|
|
$TempTuneInName =~ s/(\D+)//;
|
|
$TempTuneInName =~ s/(\D+)//;
|
|
$TempTuneInName = "s" . $TempTuneInName;
|
|
}
|
|
else {
|
|
$TempTuneInName = "-";
|
|
}
|
|
readingsBulkUpdate($hash, "currentTuneInID", $TempTuneInName , 1);
|
|
}
|
|
else {
|
|
readingsBulkUpdate($hash, "currentTuneInID", "-", 1);
|
|
}
|
|
}
|
|
else {
|
|
readingsBulkUpdate($hash, "currentTuneInID", "-", 1);
|
|
}
|
|
|
|
if(defined($json->{playerInfo}{progress})) {
|
|
readingsBulkUpdate($hash, "progress", $json->{playerInfo}{progress}{mediaProgress}, 1) if(defined($json->{playerInfo}{progress}{mediaProgress}));
|
|
readingsBulkUpdate($hash, "progress", 0, 1) if(!defined($json->{playerInfo}{progress}{mediaProgress}));
|
|
readingsBulkUpdate($hash, "progresslen", $json->{playerInfo}{progress}{mediaLength}, 1) if(defined($json->{playerInfo}{progress}{mediaLength}));
|
|
readingsBulkUpdate($hash, "progresslen", 0, 1) if(!defined($json->{playerInfo}{progress}{mediaLength}));
|
|
}
|
|
|
|
if(defined($json->{playerInfo}{volume})) {
|
|
readingsBulkUpdate($hash, "volume", $json->{playerInfo}{volume}{volume}, 1) if(defined($json->{playerInfo}{volume}{volume}));
|
|
readingsBulkUpdate($hash, "mute", $json->{playerInfo}{volume}{muted}?"on":"off", 1) if(defined($json->{playerInfo}{volume}{muted}));
|
|
}
|
|
|
|
if(defined($json->{playerInfo}{transport}{shuffle})) {
|
|
if($json->{playerInfo}{transport}{shuffle} eq "SELECTED") {readingsBulkUpdate($hash, "shuffle", "true", 1);}
|
|
else{readingsBulkUpdate($hash, "shuffle", "false", 1);}
|
|
}
|
|
|
|
if(defined($json->{playerInfo}{transport}{repeat})) {
|
|
if($json->{playerInfo}{transport}{repeat} eq "SELECTED") {readingsBulkUpdate($hash, "repeat", "true", 1);}
|
|
else{readingsBulkUpdate($hash, "repeat", "false", 1);}
|
|
}
|
|
}
|
|
readingsEndUpdate($hash,1);
|
|
}
|
|
}
|
|
|
|
elsif($msgtype eq "getbehavior") {
|
|
$hash->{helper}{"getbehavior"} = ();
|
|
|
|
return if (ref($json) ne "ARRAY");
|
|
|
|
foreach my $behavior (@{$json}) {
|
|
$hash->{helper}{"getbehavior"}{$behavior->{automationId}} = ();
|
|
$hash->{helper}{"getbehavior"}{$behavior->{automationId}}{triggers} = $behavior->{triggers};
|
|
$hash->{helper}{"getbehavior"}{$behavior->{automationId}}{sequence} = $behavior->{sequence};
|
|
$hash->{helper}{"getbehavior"}{$behavior->{automationId}}{status} = $behavior->{status};
|
|
}
|
|
}
|
|
|
|
elsif($msgtype eq "namedListsIDs") {
|
|
|
|
if (ref($json) eq "HASH") {
|
|
if(!defined($json->{lists})) {}
|
|
elsif (ref($json->{lists}) ne "ARRAY") {}
|
|
else {
|
|
foreach my $device (@{$json->{lists}}) {
|
|
if ($device->{type} eq "SHOPPING_LIST") {$hash->{helper}{SHOPPING_LIST_ID} = $device->{itemId}}
|
|
if ($device->{type} eq "TO_DO") {$hash->{helper}{TO_DO_LIST_ID} = $device->{itemId}}
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
Log3 $name, 5, "[$name] [echodevice_Parse] [$msgtype] [$msgnumber] WRONG JSON Type Type=" . ref($json);
|
|
}
|
|
|
|
}
|
|
|
|
elsif($msgtype eq "listitems_task" || $msgtype eq "listitems_shopping" ) {
|
|
my $listtype ;#= $param->{listtype};
|
|
my @listitems;
|
|
my $Firststart = "1";
|
|
my $Text ;
|
|
my $TextOriginal;
|
|
|
|
$listtype = "TASK" if ($msgtype eq "listitems_task");
|
|
$listtype = "SHOPPING_ITEM" if ($msgtype eq "listitems_shopping");
|
|
|
|
foreach my $item ( @{ $json->{values} } ) {
|
|
|
|
if ($Firststart eq "1"){
|
|
$hash->{helper}{"ITEMS"}{$item->{type}} = ();
|
|
$Firststart = "0";
|
|
}
|
|
|
|
$TextOriginal = $item->{text};
|
|
|
|
next if ($item->{complete});
|
|
$item->{text} =~ s/,/;/g;
|
|
$item->{text} =~ s/ /_/g;
|
|
$Text = $item->{text};
|
|
push @listitems, $item->{text};
|
|
|
|
$hash->{helper}{"ITEMS"}{$item->{type}}{"ID"}{$item->{text}} = (split("#", $item->{itemId}))[1];
|
|
$hash->{helper}{"ITEMS"}{$item->{type}}{"TEXT"}{$item->{text}} = $TextOriginal;
|
|
|
|
}
|
|
readingsBeginUpdate($hash);
|
|
|
|
if (@listitems) {
|
|
readingsBulkUpdate( $hash, "list_".$listtype, join(",", @listitems), 1 );
|
|
} else {
|
|
readingsBulkUpdate( $hash, "list_".$listtype, "", 1 );
|
|
}
|
|
|
|
readingsEndUpdate($hash,1);
|
|
}
|
|
|
|
elsif($msgtype eq "getnotifications") {
|
|
my @ncstrings;
|
|
@ncstrings = ();
|
|
$hash->{helper}{"notifications"} = ();
|
|
my $RunningID = time();
|
|
my $NotifiCount ;
|
|
my $NotifiReTime = 99999999;
|
|
my $TimerReTime = 99999999 ;
|
|
my $iFrom ;
|
|
my $HelperNotifyID ;
|
|
|
|
if (ref($json) eq "HASH") {
|
|
foreach my $device (@{$json->{notifications}}) {
|
|
|
|
#next if ($device->{status} eq "OFF" && (lc($device->{type}) ne "reminder" || lc($device->{type}) ne "timer"));
|
|
|
|
$HelperNotifyID = $device->{notificationIndex};
|
|
|
|
my $ncstring ;
|
|
|
|
if(lc($device->{type}) eq "reminder") {
|
|
$ncstring = $device->{type} . "_" . FmtDateTime($device->{alarmTime}/1000) . "_";
|
|
$ncstring .= $device->{recurringPattern} . "_" if (defined($device->{recurringPattern}));
|
|
$ncstring .= $device->{reminderLabel} ;
|
|
}
|
|
elsif(lc($device->{type}) eq "timer") {
|
|
$ncstring = $device->{type} . "_" . $device->{remainingTime}
|
|
}
|
|
else {
|
|
$ncstring = $device->{type} . "_" . $device->{originalTime} ;
|
|
}
|
|
$hash->{helper}{"notifications"}{$device->{deviceSerialNumber}}{$device->{notificationIndex}} = $ncstring;
|
|
|
|
#Reading anlegen
|
|
my $echohash = $modules{$hash->{TYPE}}{defptr}{$device->{deviceSerialNumber}};
|
|
|
|
if (!defined($hash->{helper}{"notifications"}{"_".$device->{deviceSerialNumber}}{"count_" . $device->{type}})) {
|
|
$NotifiCount = 1;
|
|
}
|
|
else {
|
|
$NotifiCount = int($hash->{helper}{"notifications"}{"_".$device->{deviceSerialNumber}}{"count_" . $device->{type}}) + 1
|
|
}
|
|
|
|
next if(!defined($echohash));
|
|
|
|
readingsBeginUpdate($echohash);
|
|
if(lc($device->{type}) eq "reminder") {
|
|
readingsBulkUpdate( $echohash, lc($device->{type}) . "_" . sprintf("%02d",$NotifiCount) . "_alarmtime" , FmtDateTime($device->{alarmTime}/1000), 1 );
|
|
readingsBulkUpdate( $echohash, lc($device->{type}) . "_" . sprintf("%02d",$NotifiCount) . "_alarmticks" , $device->{alarmTime}/1000, 1 );
|
|
readingsBulkUpdate( $echohash, lc($device->{type}) . "_" . sprintf("%02d",$NotifiCount) . "_id" , $device->{notificationIndex},1);
|
|
readingsBulkUpdate( $echohash, lc($device->{type}) . "_" . sprintf("%02d",$NotifiCount) . "_recurring" , $device->{recurringPattern},1) if (defined($device->{recurringPattern}));
|
|
readingsBulkUpdate( $echohash, lc($device->{type}) . "_" . sprintf("%02d",$NotifiCount) . "_recurring" , 0,1) if (!defined($device->{recurringPattern}));
|
|
}
|
|
elsif(lc($device->{type}) eq "timer") {
|
|
readingsBulkUpdate( $echohash, lc($device->{type}) . "_" . sprintf("%02d",$NotifiCount) . "_remainingtime" , int($device->{remainingTime} / 1000), 1 );
|
|
readingsBulkUpdate( $echohash, lc($device->{type}) . "_" . sprintf("%02d",$NotifiCount) . "_id" , $device->{notificationIndex},1);
|
|
|
|
if (int($device->{remainingTime} / 1000) < $TimerReTime) {
|
|
$TimerReTime = int($device->{remainingTime} / 1000);
|
|
readingsBulkUpdate( $echohash, lc($device->{type}) . "_remainingtime" , int($device->{remainingTime} / 1000), 1 );
|
|
readingsBulkUpdate( $echohash, lc($device->{type}) . "_id" , $device->{notificationIndex},1);
|
|
}
|
|
|
|
if ($TimerReTime <$NotifiReTime) {$NotifiReTime = $TimerReTime;}
|
|
}
|
|
else {
|
|
|
|
$hash->{helper}{$device->{type}}{$device->{deviceSerialNumber}}{$HelperNotifyID} = ();
|
|
|
|
if ($device->{musicEntity} eq "") {
|
|
$hash->{helper}{$device->{type}}{$device->{deviceSerialNumber}}{$HelperNotifyID}{"musicEntity"} = "null";
|
|
}
|
|
else {
|
|
$hash->{helper}{$device->{type}}{$device->{deviceSerialNumber}}{$HelperNotifyID}{"musicEntity"} = '"'.$device->{musicEntity}.'"';
|
|
}
|
|
|
|
if ($device->{musicAlarmId} eq "") {
|
|
$hash->{helper}{$device->{type}}{$device->{deviceSerialNumber}}{$HelperNotifyID}{"musicAlarmId"} = "null";
|
|
}
|
|
else {
|
|
$hash->{helper}{$device->{type}}{$device->{deviceSerialNumber}}{$HelperNotifyID}{"musicAlarmId"} = '"'.$device->{musicAlarmId}.'"';
|
|
}
|
|
|
|
if ($device->{recurringPattern} eq "") {
|
|
$hash->{helper}{$device->{type}}{$device->{deviceSerialNumber}}{$HelperNotifyID}{"recurringPattern"} = "null";
|
|
}
|
|
else {
|
|
$hash->{helper}{$device->{type}}{$device->{deviceSerialNumber}}{$HelperNotifyID}{"recurringPattern"} = $device->{recurringPattern};
|
|
}
|
|
|
|
if ($device->{provider} eq "") {
|
|
$hash->{helper}{$device->{type}}{$device->{deviceSerialNumber}}{$HelperNotifyID}{"provider"} = "null";
|
|
}
|
|
else {
|
|
$hash->{helper}{$device->{type}}{$device->{deviceSerialNumber}}{$HelperNotifyID}{"provider"} = '"'.$device->{provider}.'"';
|
|
}
|
|
|
|
$hash->{helper}{$device->{type}}{$device->{deviceSerialNumber}}{$HelperNotifyID}{"remainingTime"} = $device->{remainingTime};
|
|
$hash->{helper}{$device->{type}}{$device->{deviceSerialNumber}}{$HelperNotifyID}{"alarmTime"} = $device->{alarmTime};
|
|
$hash->{helper}{$device->{type}}{$device->{deviceSerialNumber}}{$HelperNotifyID}{"originalDate"} = $device->{originalDate};
|
|
$hash->{helper}{$device->{type}}{$device->{deviceSerialNumber}}{$HelperNotifyID}{"originalTime"} = $device->{originalTime};
|
|
|
|
readingsBulkUpdate( $echohash, lc($device->{type}) . "_" . sprintf("%02d",$NotifiCount) . "_originalTime" , $device->{originalTime}, 1 );
|
|
readingsBulkUpdate( $echohash, lc($device->{type}) . "_" . sprintf("%02d",$NotifiCount) . "_originalDate" , $device->{originalDate}, 1 );
|
|
readingsBulkUpdate( $echohash, lc($device->{type}) . "_" . sprintf("%02d",$NotifiCount) . "_id" , $device->{notificationIndex},1);
|
|
readingsBulkUpdate( $echohash, lc($device->{type}) . "_" . sprintf("%02d",$NotifiCount) . "_status" , lc($device->{status}),1);
|
|
readingsBulkUpdate( $echohash, lc($device->{type}) . "_" . sprintf("%02d",$NotifiCount) . "_recurring" , $device->{recurringPattern},1) if (defined($device->{recurringPattern}));
|
|
readingsBulkUpdate( $echohash, lc($device->{type}) . "_" . sprintf("%02d",$NotifiCount) . "_recurring" , 0,1) if (!defined($device->{recurringPattern}));
|
|
|
|
}
|
|
# Infos im Hash hinterlegen
|
|
$hash->{helper}{"notifications"}{"_".$device->{deviceSerialNumber}}{"count_" . $device->{type}} = $NotifiCount;
|
|
$hash->{helper}{"notifications"}{"_".$device->{deviceSerialNumber}}{lc($device->{type})."_aktiv"} = 1;
|
|
readingsEndUpdate($echohash,1);
|
|
}
|
|
|
|
# Notifications Counter setzen
|
|
foreach my $DeviceID (sort keys %{$modules{$hash->{TYPE}}{defptr}}) {
|
|
foreach my $NotifyCounter (sort keys %{$hash->{helper}{"notifications"}{"_".$DeviceID}}) {
|
|
if ($NotifyCounter =~ m/count/ ) {
|
|
my $echohash = $modules{$hash->{TYPE}}{defptr}{$DeviceID};
|
|
readingsSingleUpdate($echohash, lc((split ("_", $NotifyCounter))[1]). "_count" ,$hash->{helper}{"notifications"}{"_".$DeviceID}{$NotifyCounter} , 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
# Timer neu setzen wenn der Timer gleich abläuft
|
|
if ($NotifiReTime < 60 && $NotifiReTime > 0) {InternalTimer(gettimeofday() + $NotifiReTime , "echodevice_GetSettings", $hash, 0);}
|
|
|
|
# Readings bereinigen
|
|
my $nextupdate = int(AttrVal($name,"intervalsettings",60));
|
|
|
|
foreach my $DeviceID (sort keys %{$modules{$hash->{TYPE}}{defptr}}) {
|
|
|
|
next if (echodevice_getModel($modules{$hash->{TYPE}}{defptr}{$DeviceID}{model}) eq "Echo Multiroom");
|
|
next if (echodevice_getModel($modules{$hash->{TYPE}}{defptr}{$DeviceID}{model}) eq "Sonos Display");
|
|
next if (echodevice_getModel($modules{$hash->{TYPE}}{defptr}{$DeviceID}{model}) eq "Echo Stereopaar");
|
|
next if (echodevice_getModel($modules{$hash->{TYPE}}{defptr}{$DeviceID}{model}) eq "unbekannt");
|
|
|
|
my $DeviceName = $modules{$hash->{TYPE}}{defptr}{$DeviceID}{NAME};
|
|
my $echohash = $modules{$hash->{TYPE}}{defptr}{$DeviceID};
|
|
readingsBeginUpdate($echohash);
|
|
|
|
# Timer auswerten
|
|
my $TimerAktiv = 0;
|
|
foreach my $i (1..20) {
|
|
my $ReadingAge = int(ReadingsAge($DeviceName, "timer_" . sprintf("%02d",$i) . "_remainingtime", 2000));
|
|
|
|
if ($ReadingAge == 2000){last;}
|
|
elsif ($ReadingAge > $nextupdate) {
|
|
readingsDelete($echohash, "timer_" . sprintf("%02d",$i) . "_id") ;
|
|
readingsDelete($echohash, "timer_" . sprintf("%02d",$i) . "_remainingtime") ;
|
|
}
|
|
else {$TimerAktiv=1;}
|
|
}
|
|
|
|
if ($TimerAktiv == 0) {
|
|
readingsBulkUpdate( $echohash, "timer_count" , 0,1);
|
|
readingsBulkUpdate( $echohash, "timer_id" , "-",1);
|
|
readingsBulkUpdate( $echohash, "timer_remainingtime" , 0,1);
|
|
}
|
|
|
|
# Erinnerungen auswerten
|
|
my $ReminderAktiv = 0;
|
|
$ReminderAktiv = $hash->{helper}{"notifications"}{"_".$DeviceID}{"reminder_aktiv"} if (defined($hash->{helper}{"notifications"}{"_".$DeviceID}{"reminder_aktiv"}));
|
|
|
|
if ($ReminderAktiv eq "0") {
|
|
readingsBulkUpdate( $echohash, "reminder_count" , 0,1);
|
|
}
|
|
else {
|
|
$hash->{helper}{"notifications"}{"_".$DeviceID}{"reminder_aktiv"} = 0
|
|
}
|
|
|
|
$iFrom = int(ReadingsVal($DeviceName, "reminder_count", 0)) +1 ;
|
|
|
|
foreach my $i ($iFrom..20) {
|
|
|
|
if (ReadingsVal($DeviceName, "reminder_" . sprintf("%02d",$i) . "_alarmticks", "none") ne "none"){
|
|
readingsDelete($echohash, "reminder_" . sprintf("%02d",$i) . "_id") ;
|
|
readingsDelete($echohash, "reminder_" . sprintf("%02d",$i) . "_alarmticks") ;
|
|
readingsDelete($echohash, "reminder_" . sprintf("%02d",$i) . "_alarmtime") ;
|
|
readingsDelete($echohash, "reminder_" . sprintf("%02d",$i) . "_recurring") ;
|
|
}
|
|
else {last;}
|
|
}
|
|
|
|
# Alarm auswerten
|
|
my $AlarmAktiv = 0;
|
|
$AlarmAktiv = $hash->{helper}{"notifications"}{"_".$DeviceID}{"alarm_aktiv"} if (defined($hash->{helper}{"notifications"}{"_".$DeviceID}{"alarm_aktiv"}));
|
|
|
|
if ($AlarmAktiv eq "0") {
|
|
readingsBulkUpdate( $echohash, "alarm_count" , 0,1);
|
|
}
|
|
else {
|
|
$hash->{helper}{"notifications"}{"_".$DeviceID}{"alarm_aktiv"} = 0
|
|
}
|
|
|
|
$iFrom = int(ReadingsVal($DeviceName, "alarm_count", 0)) +1 ;
|
|
|
|
foreach my $i ($iFrom..20) {
|
|
|
|
if (ReadingsVal($DeviceName, "alarm_" . sprintf("%02d",$i) . "_id", "none") ne "none"){
|
|
readingsDelete($echohash, "alarm_" . sprintf("%02d",$i) . "_id") ;
|
|
readingsDelete($echohash, "alarm_" . sprintf("%02d",$i) . "_originalTime") ;
|
|
readingsDelete($echohash, "alarm_" . sprintf("%02d",$i) . "_originalDate") ;
|
|
readingsDelete($echohash, "alarm_" . sprintf("%02d",$i) . "_status") ;
|
|
readingsDelete($echohash, "alarm_" . sprintf("%02d",$i) . "_recurring") ;
|
|
}
|
|
else {last;}
|
|
}
|
|
|
|
# Musikalarm auswerten
|
|
my $MusikAlarmAktiv = 0;
|
|
$MusikAlarmAktiv = $hash->{helper}{"notifications"}{"_".$DeviceID}{"musikalarm_aktiv"} if (defined($hash->{helper}{"notifications"}{"_".$DeviceID}{"musicalarm_aktiv"}));
|
|
|
|
if ($MusikAlarmAktiv eq "0") {
|
|
readingsBulkUpdate( $echohash, "musicalarm_count" , 0,1);
|
|
}
|
|
else {
|
|
$hash->{helper}{"notifications"}{"_".$DeviceID}{"musicalarm_aktiv"} = 0
|
|
}
|
|
|
|
$iFrom = int(ReadingsVal($DeviceName, "musicalarm_count", 0)) +1 ;
|
|
|
|
foreach my $i ($iFrom..20) {
|
|
|
|
if (ReadingsVal($DeviceName, "musicalarm_" . sprintf("%02d",$i) . "_id", "none") ne "none"){
|
|
readingsDelete($echohash, "musicalarm_" . sprintf("%02d",$i) . "_id") ;
|
|
readingsDelete($echohash, "musicalarm_" . sprintf("%02d",$i) . "_originalTime") ;
|
|
readingsDelete($echohash, "musicalarm_" . sprintf("%02d",$i) . "_originalDate") ;
|
|
readingsDelete($echohash, "musicalarm_" . sprintf("%02d",$i) . "_status") ;
|
|
readingsDelete($echohash, "musicalarm_" . sprintf("%02d",$i) . "_recurring") ;
|
|
}
|
|
else {last;}
|
|
}
|
|
readingsEndUpdate($echohash,1);
|
|
}
|
|
}
|
|
}
|
|
|
|
elsif($msgtype eq "homegroup") {
|
|
$hash->{helper}{HOMEGROUP} = $json->{homeGroupId} if(defined($json->{homeGroupId}));
|
|
$hash->{helper}{SIPS} = $json->{aor} if(defined($json->{aor}));
|
|
}
|
|
|
|
elsif($msgtype eq "bluetoothstate") {
|
|
my @btstrings;
|
|
my @btdevices;
|
|
|
|
my $echohash;
|
|
my $ConnectState;
|
|
|
|
foreach my $device (@{$json->{bluetoothStates}}) {
|
|
@btstrings = ();
|
|
if(defined($modules{$hash->{TYPE}}{defptr}{$device->{deviceSerialNumber}})) {
|
|
foreach my $btdevice (@{$device->{pairedDeviceList}}) {
|
|
next if(!defined($btdevice->{friendlyName}));
|
|
next if (echodevice_getModel($btdevice->{deviceType}) eq "Reverb");
|
|
next if (echodevice_getModel($btdevice->{deviceType}) eq "unbekannt");
|
|
|
|
$echohash = $modules{$hash->{TYPE}}{defptr}{$device->{deviceSerialNumber}};
|
|
|
|
$btdevice->{address} =~ s/:/-/g;
|
|
$btdevice->{friendlyName} =~ s/ /_/g;
|
|
$btdevice->{friendlyName} =~ s/,/./g;
|
|
|
|
if (int($btdevice->{connected}) == 0) {$ConnectState = "disconnected";}
|
|
elsif (int($btdevice->{connected}) == 1) {$ConnectState = "connected"}
|
|
else {$ConnectState = "unknown";}
|
|
|
|
readingsSingleUpdate($echohash, "bluetooth_" . $btdevice->{address} ,$ConnectState , 1);
|
|
|
|
my $btstring .= $btdevice->{address}."/".$btdevice->{friendlyName};
|
|
push @btstrings, $btstring;
|
|
push @btdevices, "bluetooth_" . $btdevice->{address};
|
|
}
|
|
$modules{$hash->{TYPE}}{defptr}{$device->{deviceSerialNumber}}->{helper}{bluetooth} = join(",", @btstrings) if (@btstrings);
|
|
$modules{$hash->{TYPE}}{defptr}{$device->{deviceSerialNumber}}->{helper}{bluetooth} = "-" if(!defined($modules{$hash->{TYPE}}{defptr}{$device->{deviceSerialNumber}}->{helper}{bluetooth}));
|
|
}
|
|
}
|
|
# Bluetooth Geräte bereinigen!
|
|
my $echohash;
|
|
|
|
foreach my $DeviceID (sort keys %{$modules{$hash->{TYPE}}{defptr}}) {
|
|
$echohash = $modules{$hash->{TYPE}}{defptr}{$DeviceID};
|
|
foreach my $BluetoothDevice (sort keys %{$modules{$hash->{TYPE}}{defptr}{$DeviceID}{READINGS}}) {
|
|
if ( grep( /^$BluetoothDevice$/, @btdevices ) ) {
|
|
#Log3 $name, 5, "DEBUG $name [bluetoothstate] FOUND Device=" . $DeviceID . " Reading=" . $BluetoothDevice if ($BluetoothDevice =~ m/bluetooth_/ );
|
|
}
|
|
else {
|
|
readingsDelete($echohash, $BluetoothDevice ) if ($BluetoothDevice =~ m/bluetooth_/ );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
elsif($msgtype eq "getdnd") {
|
|
foreach my $device (@{$json->{doNotDisturbDeviceStatusList}}) {
|
|
if(defined($modules{$hash->{TYPE}}{defptr}{$device->{deviceSerialNumber}})) {
|
|
next if (echodevice_getModel($device->{deviceType}) eq "Reverb");
|
|
next if (echodevice_getModel($device->{deviceType}) eq "Echo Multiroom");
|
|
next if (echodevice_getModel($device->{deviceType}) eq "Echo Stereopaar");
|
|
next if (echodevice_getModel($device->{deviceType}) eq "Sonos Display");
|
|
next if (echodevice_getModel($device->{deviceType}) eq "Sonos One");
|
|
next if (echodevice_getModel($device->{deviceType}) eq "Sonos Beam");
|
|
next if (echodevice_getModel($device->{deviceType}) eq "unbekannt");
|
|
my $echohash = $modules{$hash->{TYPE}}{defptr}{$device->{deviceSerialNumber}};
|
|
readingsBeginUpdate($echohash);
|
|
readingsBulkUpdate($echohash, "dnd", $device->{enabled}?"on":"off", 1);
|
|
readingsEndUpdate($echohash,1);
|
|
}
|
|
}
|
|
}
|
|
|
|
elsif($msgtype eq "alarmvolume") {
|
|
foreach my $device (@{$json->{deviceNotificationStates}}) {
|
|
if(defined($modules{$hash->{TYPE}}{defptr}{$device->{deviceSerialNumber}})) {
|
|
next if (echodevice_getModel($device->{deviceType}) eq "Reverb");
|
|
next if (echodevice_getModel($device->{deviceType}) eq "Echo Multiroom");
|
|
next if (echodevice_getModel($device->{deviceType}) eq "Sonos Display");
|
|
next if (echodevice_getModel($device->{deviceType}) eq "Echo Stereopaar");
|
|
next if (echodevice_getModel($device->{deviceType}) eq "unbekannt");
|
|
my $echohash = $modules{$hash->{TYPE}}{defptr}{$device->{deviceSerialNumber}};
|
|
readingsBeginUpdate($echohash);
|
|
readingsBulkUpdate($echohash, "volume_alarm", $device->{volumeLevel}, 1)if(defined($device->{volumeLevel}));
|
|
readingsEndUpdate($echohash,1);
|
|
}
|
|
}
|
|
}
|
|
|
|
elsif($msgtype eq "dndset") {
|
|
readingsBeginUpdate($hash);
|
|
readingsBulkUpdate($hash, "dnd", $json->{enabled}?"on":"off", 1) if(defined($json->{enabled}));
|
|
readingsEndUpdate($hash,1);
|
|
}
|
|
|
|
elsif($msgtype eq "tunein") {
|
|
}
|
|
|
|
elsif($msgtype eq "ttstunein") {
|
|
InternalTimer(gettimeofday() + $hash->{helper}{lasttuneindelay} , "echodevice_StartLastMedia" , $hash, 0);
|
|
Log3 $name, 4, "[$name] [echodevice_ParseTTSMP3] Setze echodevice_StartLastMedia Timer in " . $hash->{helper}{lasttuneindelay} . " Sekunden.";
|
|
|
|
}
|
|
|
|
elsif($msgtype eq "tts_translate") {
|
|
|
|
my $TTS_Translate_Result = "ERROR no result!!!!";
|
|
my $TTS_Translate_ResultTags = "";
|
|
|
|
if (defined($json->{d})) {
|
|
if (defined($json->{d}{result})) {
|
|
$TTS_Translate_Result = $json->{d}{result};
|
|
}
|
|
|
|
if (defined($json->{d}{resultNoTags})) {
|
|
$TTS_Translate_ResultTags = $json->{d}{resultNoTags};
|
|
}
|
|
}
|
|
|
|
# Prüfen ob Text erkannt wurde
|
|
if (index($TTS_Translate_Result,'<div') >=0 && $TTS_Translate_ResultTags ne "" ) {
|
|
# Kein Text erkannt!
|
|
my @TTS_ResultArray = split("\n",$TTS_Translate_ResultTags);
|
|
$TTS_Translate_Result = substr($TTS_ResultArray[1], 5,index($TTS_ResultArray[1],",")-5 );
|
|
}
|
|
|
|
# Verzeichnis anlegen
|
|
my $filedir = "cache";
|
|
mkdir($filedir, 0777) unless(-d $filedir );
|
|
|
|
# Text in Datei zwischenspeichern
|
|
open(FH, ">$filedir/$name.html");
|
|
print FH $TTS_Translate_Result;
|
|
close(FH);
|
|
|
|
# Reading aktualisieren.
|
|
readingsBeginUpdate($hash);
|
|
readingsBulkUpdate($hash, "tts_translate_result",$TTS_Translate_Result , 1);
|
|
readingsEndUpdate($hash,1);
|
|
|
|
# Datei wieder auslesen
|
|
open FILE, "$filedir/$name.html" or do {
|
|
return;
|
|
};
|
|
chomp(my $TTS_Translate_Result = <FILE>);
|
|
close FILE;
|
|
|
|
# TTS Nachricht abspielen
|
|
if ($TTS_Translate_Result ne "ERROR no result!!!!") {
|
|
echodevice_Amazon($hash,$TTS_Translate_Result,$msgtype);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
elsif($msgtype eq "wakeword") {
|
|
foreach my $device (@{$json->{wakeWords}}) {
|
|
if(defined($modules{$hash->{TYPE}}{defptr}{$device->{deviceSerialNumber}})) {
|
|
my $echohash = $modules{$hash->{TYPE}}{defptr}{$device->{deviceSerialNumber}};
|
|
readingsBeginUpdate($echohash);
|
|
#readingsBulkUpdate($echohash, "active", $device->{active}?"true":"false", 1) if(defined($device->{active}));
|
|
readingsBulkUpdate($echohash, "wakeword", $device->{wakeWord}, 1) if(defined($device->{wakeWord}));
|
|
#readingsBulkUpdate($echohash, "midfield", $device->{midFieldState}, 1) if(defined($device->{midFieldState}));
|
|
readingsEndUpdate($echohash,1);
|
|
}
|
|
}
|
|
}
|
|
|
|
elsif($msgtype eq "getdevicesettings") {
|
|
foreach my $device (@{$json->{devicePreferences}}) {
|
|
if(defined($modules{$hash->{TYPE}}{defptr}{$device->{deviceSerialNumber}})) {
|
|
my $echohash = $modules{$hash->{TYPE}}{defptr}{$device->{deviceSerialNumber}};
|
|
next if (echodevice_getModel($device->{deviceType}) eq "Echo Multiroom");
|
|
next if (echodevice_getModel($device->{deviceType}) eq "Echo Stereopaar");
|
|
next if (echodevice_getModel($device->{deviceType}) eq "unbekannt");
|
|
readingsBeginUpdate($echohash);
|
|
readingsBulkUpdate($echohash, "microphone", $device->{notificationEarconEnabled}?"false":"true", 1) if(defined($device->{notificationEarconEnabled}));
|
|
readingsBulkUpdate($echohash, "deviceAddress", $device->{deviceAddress}, 1) if(defined($device->{deviceAddress}));
|
|
readingsBulkUpdate($echohash, "timeZoneId", $device->{timeZoneId}, 1) if(defined($device->{timeZoneId}));
|
|
readingsEndUpdate($echohash,1);
|
|
}
|
|
}
|
|
}
|
|
|
|
elsif($msgtype eq "getisonline") {
|
|
foreach my $device (@{$json->{devices}}) {
|
|
if(defined($modules{$hash->{TYPE}}{defptr}{$device->{serialNumber}})) {
|
|
my $echohash = $modules{$hash->{TYPE}}{defptr}{$device->{serialNumber}};
|
|
next if (echodevice_getModel($device->{deviceType}) eq "Echo Multiroom");
|
|
next if (echodevice_getModel($device->{deviceType}) eq "Echo Stereopaar");
|
|
next if (echodevice_getModel($device->{deviceType}) eq "Sonos Display");
|
|
next if (echodevice_getModel($device->{deviceType}) eq "unbekannt");
|
|
readingsBeginUpdate($echohash);
|
|
readingsBulkUpdate($echohash, "online", $device->{online}?"true":"false", 1) if(defined($device->{online}));
|
|
readingsEndUpdate($echohash,1);
|
|
}
|
|
}
|
|
}
|
|
|
|
elsif($msgtype eq "conversations") {
|
|
|
|
my $return = '<html><table align="" border="0" cellspacing="0" cellpadding="3" width="100%" height="100%" class="mceEditable"><tbody>';
|
|
$return .= "<p>Conversations:</p>";
|
|
$return .= "<tr><td><strong>ID</strong></td><td><strong>Date</strong></td><td><strong>Message</strong></td></tr>";
|
|
my $conversations_date = "";
|
|
my $conversations_msg = "";
|
|
|
|
if(!defined($json->{conversations})) {}
|
|
elsif(ref($json->{conversations}) ne "ARRAY") {}
|
|
else{
|
|
foreach my $conversation (@{$json->{conversations}}) {
|
|
if(defined($conversation->{lastMessage}{payload}{text})){
|
|
$conversations_date = $conversation->{lastMessage}{time};
|
|
$conversations_msg = substr($conversation->{lastMessage}{payload}{text},0,32);
|
|
$conversations_msg =~ s/[\x0A\x0D]//g;
|
|
} else {
|
|
$conversations_msg = "no previous messages";
|
|
$conversations_date = "no date";
|
|
}
|
|
$return .= "<tr><td>".$conversation->{conversationId}." </td><td>".$conversations_date." </td><td>".$conversations_msg." </td></tr>";
|
|
}
|
|
}
|
|
$return .= "</tbody></table></html>";
|
|
asyncOutput( $param->{CL}, $return );
|
|
}
|
|
|
|
elsif($msgtype eq "devices" || $msgtype eq "autocreate_devices") {
|
|
|
|
my $autocreated = 0;
|
|
my $autocreate = 0;
|
|
my $isautocreated = 0;
|
|
$autocreate=1 if($msgtype eq "autocreate_devices");
|
|
|
|
my $return = '<html><table align="" border="0" cellspacing="0" cellpadding="3" width="100%" height="100%" class="mceEditable"><tbody>';
|
|
$return .= "<p>Devices:</p>";
|
|
$return .= "<tr><td><strong>Serial</strong></td><td><strong>Family</strong></td><td><strong>Devicetype</strong></td><td><strong>Name</strong></td></tr>";
|
|
|
|
if(!defined($json->{devices})) {}
|
|
elsif (ref($json->{devices}) ne "ARRAY") {}
|
|
else {
|
|
foreach my $device (@{$json->{devices}}) {
|
|
#next if($device->{deviceFamily} eq "UNKNOWN");
|
|
#next if($device->{deviceFamily} eq "FIRE_TV");
|
|
#next if($device->{deviceFamily} =~ /AMAZON/);
|
|
$isautocreated = 0;
|
|
if($autocreate && ($device->{deviceFamily} eq "UNKNOWN" || $device->{deviceFamily} eq "FIRE_TV" || $device->{deviceFamily} eq "TABLET" || $device->{deviceFamily} eq "ECHO" || $device->{deviceFamily} eq "KNIGHT" || $device->{deviceFamily} eq "THIRD_PARTY_AVS_SONOS_BOOTLEG" || $device->{deviceFamily} eq "THIRD_PARTY_AVS_MEDIA_DISPLAY" || $device->{deviceFamily} eq "WHA" || $device->{deviceFamily} eq "ROOK" )) {
|
|
if( defined($modules{$hash->{TYPE}}{defptr}{"$device->{serialNumber}"}) ) {
|
|
Log3 $name, 4, "[$name] [echodevice_Parse] device '$device->{serialNumber}' already defined";
|
|
if (AttrVal($name, "autocreate_refresh", 0) == 1) {
|
|
my $devicehash = $modules{$hash->{TYPE}}{defptr}{"$device->{serialNumber}"};
|
|
print (fhem( "attr " . $devicehash->{NAME} ." alias " .$device->{accountName} )) if( defined($device->{accountName}) );
|
|
print (fhem( "attr " . $devicehash->{NAME} ." icon echo" ))if (-e "././www/images/fhemSVG/echo.svg");
|
|
}
|
|
}
|
|
else {
|
|
$isautocreated = 1;
|
|
my $devname = "ECHO_".$device->{serialNumber};
|
|
my $define= "$devname echodevice ".$device->{deviceType}." ".$device->{serialNumber};
|
|
|
|
Log3 $name, 3, "[$name] [echodevice_Parse] create new device '$devname'";
|
|
my $cmdret= CommandDefine(undef,$define);
|
|
if($cmdret) {
|
|
Log3 $name, 1, "[$name] [echodevice_Parse] Autocreate: An error occurred while creating device for serial '$device->{serialNumber}': $cmdret";
|
|
}
|
|
else {
|
|
$cmdret= CommandAttr(undef,"$devname alias ".$device->{accountName}) if( defined($device->{accountName}) );
|
|
$cmdret= CommandAttr(undef,"$devname icon echo" )if (-e "././www/images/fhemSVG/echo.svg");
|
|
$cmdret= CommandAttr(undef,"$devname IODev $name");
|
|
$cmdret= CommandAttr(undef,"$devname room Amazon");
|
|
$autocreated++;
|
|
}
|
|
|
|
$hash->{helper}{VERSION} = $device->{softwareVersion} if(!defined($hash->{helper}{VERSION}));
|
|
$hash->{helper}{".CUSTOMER"} = $device->{deviceOwnerCustomerId} if(!defined($hash->{helper}{".CUSTOMER"}));
|
|
$hash->{helper}{".SERIAL"} = $device->{serialNumber} if(!defined($hash->{helper}{".SERIAL"}));
|
|
$hash->{helper}{DEVICETYPE} = $device->{deviceType} if(!defined($hash->{helper}{DEVICETYPE}));
|
|
}
|
|
|
|
}
|
|
elsif($device->{deviceFamily} eq "ECHO") {
|
|
Log3 $name, 4, "[echodevice_GetSettings] SET 2 DEF=" . $hash->{DEF} . " TYPE=".$device->{deviceType} . 'SN Hash=' . $hash->{helper}{".SERIAL"} . ' SN Result=' . $device->{serialNumber} ;
|
|
$hash->{helper}{VERSION} = $device->{softwareVersion} if(!defined($hash->{helper}{VERSION}));
|
|
$hash->{helper}{".CUSTOMER"} = $device->{deviceOwnerCustomerId} if(!defined($hash->{helper}{".CUSTOMER"}));
|
|
$hash->{helper}{".SERIAL"} = $device->{serialNumber} if(!defined($hash->{helper}{".SERIAL"}));
|
|
$hash->{helper}{DEVICETYPE} = $device->{deviceType} if(!defined($hash->{helper}{DEVICETYPE}));
|
|
if( defined($modules{$hash->{TYPE}}{defptr}{"$device->{serialNumber}"}) ) {
|
|
my $devicehash = $modules{$hash->{TYPE}}{defptr}{"$device->{serialNumber}"};
|
|
}
|
|
}
|
|
if ($isautocreated == 0) {
|
|
$return .= "<tr><td>".$device->{serialNumber}." </td><td>".$device->{deviceFamily}." </td><td>".$device->{deviceType}." </td><td>".$device->{accountName}." </td></tr>";
|
|
}
|
|
else {
|
|
$return .= "<tr><td><strong>*".$device->{serialNumber}." </strong></td><td><strong>".$device->{deviceFamily}." </strong></td><td><strong>".$device->{deviceType}." </strong></td><td><strong>".$device->{accountName}." </strong></td></tr>";
|
|
}
|
|
|
|
}
|
|
|
|
foreach my $device (@{$json->{devices}}) {
|
|
my $devicehash = $modules{$hash->{TYPE}}{defptr}{"$device->{serialNumber}"};
|
|
next if( !defined($devicehash) );
|
|
|
|
$devicehash->{model} = echodevice_getModel($device->{deviceType});#$device->{deviceType};
|
|
|
|
readingsBeginUpdate($devicehash);
|
|
readingsBulkUpdate($devicehash, "model", $devicehash->{model}, 1);
|
|
readingsBulkUpdate($devicehash, "presence", ($device->{online}?"present":"absent"), 1);
|
|
#readingsBulkUpdate($devicehash, "state", "absent", 1) if(!$device->{online});
|
|
readingsBulkUpdate($devicehash, "version", $device->{softwareVersion}, 1);
|
|
readingsEndUpdate($devicehash,1);
|
|
$devicehash->{helper}{".SERIAL"} = $device->{serialNumber};
|
|
$devicehash->{helper}{DEVICETYPE} = $device->{deviceType};
|
|
$devicehash->{helper}{NAME} = $device->{accountName};
|
|
$devicehash->{helper}{FAMILY} = $device->{deviceFamily};
|
|
$devicehash->{helper}{VERSION} = $device->{softwareVersion};
|
|
$devicehash->{helper}{".CUSTOMER"} = $device->{deviceOwnerCustomerId};
|
|
|
|
if ($device->{deviceFamily} eq "ECHO" || $device->{deviceFamily} eq "KNIGHT") {
|
|
Log3 $name, 4, "[echodevice_GetSettings] SET 4 DEF=" . $devicehash->{DEF} . " TYPE=".$device->{deviceType} . 'SN Hash=' . $devicehash->{helper}{".SERIAL"} . ' SN Result=' . $device->{serialNumber} ;
|
|
$hash->{helper}{".SERIAL"} = $device->{serialNumber};
|
|
$hash->{helper}{DEVICETYPE} = $device->{deviceType};
|
|
}
|
|
}
|
|
|
|
readingsSingleUpdate ($hash, "autocreate_devices", "found: ".$autocreated, 0 ) if($msgtype eq "autocreate_devices");
|
|
|
|
$return .= "</tbody></table>";
|
|
$return .= "<p><strong>* ".$autocreated." devices created</strong></p>" if($msgtype eq "autocreate_devices");
|
|
$return .= "</html>";
|
|
}
|
|
|
|
$return =~ s/'/'/g;
|
|
asyncOutput( $param->{CL}, $return );
|
|
}
|
|
|
|
elsif($msgtype eq "devicesstate") {
|
|
if (ref($json) eq "HASH") {
|
|
if(!defined($json->{devices})) {}
|
|
elsif (ref($json->{devices}) ne "ARRAY") {}
|
|
else {
|
|
foreach my $device (@{$json->{devices}}) {
|
|
my $devicehash = $modules{$hash->{TYPE}}{defptr}{"$device->{serialNumber}"};
|
|
next if( !defined($devicehash) );
|
|
|
|
$devicehash->{model} = echodevice_getModel($device->{deviceType});#$device->{deviceType};
|
|
Log3 $name, 4, "[echodevice_GetSettings] SET 6 DEF=" . $devicehash->{DEF} . " TYPE=".$device->{deviceType}. 'SN Hash=' . $devicehash->{helper}{".SERIAL"} . ' SN Result=' . $device->{serialNumber} . " Model=" .$devicehash->{model} ;
|
|
readingsBeginUpdate($devicehash);
|
|
readingsBulkUpdate($devicehash, "model", $devicehash->{model}, 1);
|
|
readingsBulkUpdate($devicehash, "presence", ($device->{online}?"present":"absent"), 1);
|
|
#readingsBulkUpdate($devicehash, "state", "absent", 1) if(!$device->{online});
|
|
readingsBulkUpdate($devicehash, "version", $device->{softwareVersion}, 1);
|
|
readingsEndUpdate($devicehash,1);
|
|
$devicehash->{helper}{".SERIAL"} = $device->{serialNumber};
|
|
$devicehash->{helper}{DEVICETYPE} = $device->{deviceType};
|
|
$devicehash->{helper}{NAME} = $device->{accountName};
|
|
$devicehash->{helper}{FAMILY} = $device->{deviceFamily};
|
|
$devicehash->{helper}{VERSION} = $device->{softwareVersion};
|
|
$devicehash->{helper}{".CUSTOMER"} = $device->{deviceOwnerCustomerId};
|
|
|
|
if ($device->{deviceFamily} eq "ECHO" || $device->{deviceFamily} eq "KNIGHT") {
|
|
Log3 $name, 4, "[echodevice_GetSettings] SET 5 DEF=" . $devicehash->{DEF} . " TYPE=".$device->{deviceType}. 'SN Hash=' . $devicehash->{helper}{".SERIAL"} . ' SN Result=' . $device->{serialNumber} ;
|
|
$hash->{helper}{".SERIAL"} = $device->{serialNumber};
|
|
$hash->{helper}{DEVICETYPE} = $device->{deviceType};
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
Log3 $name, 5, "[$name] [echodevice_Parse] [$msgtype] [$msgnumber] WRONG JSON Type Type=" . ref($json);
|
|
}
|
|
}
|
|
|
|
elsif($msgtype eq "searchtunein") {
|
|
my $tuneincount = 0;
|
|
|
|
my $return = '<html><table align="" border="0" cellspacing="0" cellpadding="3" width="100%" height="100%" class="mceEditable"><tbody>';
|
|
$return .= "<p>TuneIn:</p>";
|
|
$return .= "<tr><td><strong>ID</strong></td><td><strong>Name</strong></td><td><strong>Start</strong></td></tr>";
|
|
|
|
if (!defined($json->{browseList})) {}
|
|
elsif (ref($json->{browseList}) ne "ARRAY") {}
|
|
else {
|
|
# Play on Device
|
|
foreach my $result (@{$json->{browseList}}) {
|
|
next if(!$result->{available});
|
|
next if($result->{contentType} ne "station");
|
|
$tuneincount ++;
|
|
$return .= "<tr><td>".$result->{id}." </td><td>".$result->{name}." </td><td><a href=" . '/fhem?cmd.Test=set%20' .$name .'%20tunein%20'.$result->{id}.'>play ' . "</a></td></tr>";
|
|
}
|
|
}
|
|
|
|
$return .= "</tbody></table>";
|
|
$return .= "<p><strong>".$tuneincount. " tunein IDs found</strong></p>";
|
|
$return .= "</html>";
|
|
$return =~ s/'/'/g;
|
|
|
|
asyncOutput( $param->{CL}, $return );
|
|
}
|
|
|
|
elsif($msgtype eq "searchtracks") {
|
|
my $trackcount = 0;
|
|
my $return = '<html><table align="" border="0" cellspacing="0" cellpadding="3" width="100%" height="100%" class="mceEditable"><tbody>';
|
|
my $tracktitle = "";
|
|
$return .= "<p>Tracks:</p>";
|
|
$return .= "<tr><td><strong>ID</strong></td><td><strong>Title</strong></td></tr>";
|
|
|
|
if (!defined($json->{playlist}{entryList})) {}
|
|
elsif (ref($json->{playlist}{entryList}) ne "ARRAY") {}
|
|
else {
|
|
foreach my $track (@{$json->{playlist}{entryList}}) {
|
|
if(defined($track->{metadata}{title})){$tracktitle = $track->{metadata}{title};}
|
|
else {$tracktitle= "unknown title";}
|
|
$trackcount ++;
|
|
$return .= "<tr><td>".$track->{trackId}." </td><td>".$tracktitle." </td></tr>";
|
|
}
|
|
}
|
|
|
|
$return .= "</tbody></table>";
|
|
$return .= "<p><strong>".$trackcount." track IDs found</strong></p>";
|
|
$return .= "</html>";
|
|
$return =~ s/'/'/g;
|
|
|
|
asyncOutput( $param->{CL}, $return );
|
|
}
|
|
|
|
elsif($msgtype eq "primeplayeigene_Albums" || $msgtype eq "primeplayeigene_Tracks" || $msgtype eq "primeplayeigene_Artists" ) {
|
|
my $querytype = substr($msgtype,16);
|
|
my $albumcount = 0;
|
|
|
|
my $artistcolum = "";
|
|
$artistcolum = "<td><strong>Title  </strong></td><td><strong>ID  </strong></td>" if ($msgtype eq "primeplayeigene_Tracks" ) ;
|
|
|
|
my $return = '<html><table align="" border="0" cellspacing="0" cellpadding="3" width="100%" height="100%" class="mceEditable"><tbody>';
|
|
$return .= "<p>$querytype:</p>";
|
|
$return .= "<tr><td><strong>Artist  </strong></td><td><strong>Albumname  </strong></td>$artistcolum<td><strong>Tracks  </strong></td><td><strong>Start</strong></td></tr>";
|
|
|
|
if (!defined($json->{selectItemList})) {}
|
|
elsif (ref($json->{selectItemList}) ne "ARRAY") {}
|
|
else {
|
|
# Play on Device
|
|
foreach my $result (@{$json->{selectItemList}}) {
|
|
#next if(!$result->{available});
|
|
#next if($result->{contentType} ne "station");
|
|
$albumcount ++;
|
|
if ($msgtype eq "primeplayeigene_Tracks" ) {
|
|
$return .= "<tr><td>".$result->{metadata}{albumArtistName}." </td><td>".$result->{metadata}{albumName}." </td><td>".$result->{metadata}{title}." </td><td>".$result->{metadata}{objectId}." </td><td>1 </td><td><a href=" . '/fhem?cmd.Test=set%20' .$name .'%20track%20'.$result->{metadata}{objectId}.'>play ' . "</a></td></tr>";
|
|
}
|
|
else {
|
|
$return .= "<tr><td>".$result->{metadata}{albumArtistName}." </td><td>".$result->{metadata}{albumName}." </td><td>".$result->{numTracks}." </td><td><a href=" . '/fhem?cmd.Test=set%20' .$name .'%20primeplayeigene%20'.urlEncode($result->{metadata}{albumArtistName})."@".urlEncode($result->{metadata}{albumName}).'>play ' . "</a></td></tr>";
|
|
}
|
|
}
|
|
}
|
|
|
|
$return .= "</tbody></table>";
|
|
$return .= "<p><strong>".$albumcount. " ". lc($querytype) ." IDs found</strong></p>";
|
|
$return .= "</html>";
|
|
$return =~ s/'/'/g;
|
|
|
|
asyncOutput( $param->{CL}, $return );
|
|
}
|
|
|
|
elsif($msgtype eq "getprimeplayeigeneplaylist" ) {
|
|
|
|
my $playlistcount = 0;
|
|
|
|
my $return = '<html><table align="" border="0" cellspacing="0" cellpadding="3" width="100%" height="100%" class="mceEditable"><tbody>';
|
|
$return .= "<p>Playlists:</p>";
|
|
$return .= "<tr><td><strong>Name  </strong></td><td><strong>ID  </strong></td><td><strong>Tracks  </strong></td><td><strong>Start</strong></td></tr>";
|
|
if (!defined($json->{playlists})) {}
|
|
elsif (ref($json->{playlists}) ne "HASH") {}
|
|
else {
|
|
foreach my $result (sort keys %{$json->{playlists}}) {
|
|
$playlistcount ++;
|
|
$return .= "<tr><td>".$result." </td><td>".$json->{playlists}{"$result"}[0]{playlistId}." </td><td>".$json->{playlists}{"$result"}[0]{trackCount}." </td><td><a href=" . '/fhem?cmd.Test=set%20' .$name .'%20primeplayeigeneplaylist%20'.$json->{playlists}{"$result"}[0]{playlistId}.'>play ' . "</a></td></tr>";
|
|
}
|
|
}
|
|
|
|
$return .= "</tbody></table>";
|
|
$return .= "<p><strong>".$playlistcount. " playlist IDs found</strong></p>";
|
|
$return .= "</html>";
|
|
$return =~ s/'/'/g;
|
|
|
|
asyncOutput( $param->{CL}, $return );
|
|
}
|
|
|
|
elsif($msgtype eq "getcards") {
|
|
|
|
my $return = '<html><table align="" border="0" cellspacing="0" cellpadding="3" width="100%" height="100%" class="mceEditable"><tbody>';
|
|
|
|
$return .= "<p>Actions:</p>";
|
|
$return .= "<tr><td><strong>Title</strong></td><td><strong>Subtitle</strong></td><td><strong>Voice</strong></td><td><strong>Device</strong></td></tr>";
|
|
|
|
if (!defined($json->{cards})) {}
|
|
elsif (ref($json->{cards}) ne "ARRAY") {}
|
|
else {
|
|
foreach my $cards (@{$json->{cards}}) {
|
|
my $devicehash = $modules{$hash->{TYPE}}{defptr}{"$cards->{sourceDevice}{serialNumber}"};
|
|
my $devicename = $devicehash->{NAME};
|
|
my $VoiceText = $cards->{playbackAudioAction}{mainText};
|
|
$VoiceText = "No voice command detected. Action was started by the Alexa app." if ($VoiceText eq "");
|
|
|
|
if ($devicename ne ""){
|
|
if (AttrVal( $devicename, "alias", "none" ) ne "none") {$devicename = AttrVal( $devicename, "alias", "none" );}
|
|
$return .= "<tr><td>".$cards->{title}." </td><td>".$cards->{subtitle}." </td><td>".$VoiceText." </td><td>".$devicename." </td></tr>";
|
|
}
|
|
}
|
|
}
|
|
|
|
$return .= "</tbody></table>";
|
|
$return .= "</html>";
|
|
$return =~ s/'/'/g;
|
|
|
|
asyncOutput( $param->{CL}, $return );
|
|
}
|
|
|
|
elsif($msgtype eq "getsettingstraffic") {
|
|
|
|
readingsBeginUpdate($hash);
|
|
$hash->{helper}{"getsettingstraffic"} = ();
|
|
|
|
if ((!defined($json->{origin}{label}))) {
|
|
$hash->{helper}{"getsettingstraffic"}{from} = "";
|
|
readingsBulkUpdate ($hash, "config_address_from", "-", 1);
|
|
}
|
|
else{
|
|
$hash->{helper}{"getsettingstraffic"}{from} = encode_utf8($json->{origin}{label});
|
|
readingsBulkUpdate ($hash, "config_address_from", $json->{origin}{label}, 1);
|
|
}
|
|
|
|
if ((!defined($json->{destination}{label}))) {
|
|
$hash->{helper}{"getsettingstraffic"}{to} = "";
|
|
readingsBulkUpdate ($hash, "config_address_to", "-", 1);
|
|
}
|
|
else{
|
|
$hash->{helper}{"getsettingstraffic"}{to} = encode_utf8($json->{destination}{label});
|
|
readingsBulkUpdate ($hash, "config_address_to", $json->{destination}{label}, 1);
|
|
}
|
|
|
|
if (ref($json->{waypoints}) ne "ARRAY") {
|
|
$hash->{helper}{"getsettingstraffic"}{between} = "";
|
|
readingsBulkUpdate ($hash, "config_address_between", "-", 1);
|
|
}
|
|
else{
|
|
if ($json->{waypoints}[0]{label} eq "") {
|
|
$hash->{helper}{"getsettingstraffic"}{between} = "";
|
|
readingsBulkUpdate ($hash, "config_address_between", "-", 1);
|
|
}
|
|
else {
|
|
$hash->{helper}{"getsettingstraffic"}{between} = encode_utf8($json->{waypoints}[0]{label});
|
|
readingsBulkUpdate ($hash, "config_address_between", $json->{waypoints}[0]{label}, 1);
|
|
}
|
|
}
|
|
readingsEndUpdate ($hash,1);
|
|
}
|
|
|
|
elsif($msgtype eq "address") {
|
|
|
|
my $addresscount = 0;
|
|
|
|
my $return = '<html><table align="" border="0" cellspacing="0" cellpadding="3" width="100%" height="100%" class="mceEditable"><tbody>';
|
|
$return .= "<p>Adressen:</p>";
|
|
$return .= "<tr><td><strong>Adresse</strong></td><td><strong> Start</strong></td><td><strong> Z.-Ziel</strong></td><td><strong> Ziel</strong></td></tr>";
|
|
|
|
if (!defined($json->{suggestionList})) {}
|
|
elsif (ref($json->{suggestionList}) ne "ARRAY") {}
|
|
else {
|
|
# Play on Device
|
|
foreach my $result (@{$json->{suggestionList}}) {
|
|
#next if(!$result->{available});
|
|
#next if($result->{contentType} ne "station");
|
|
$addresscount ++;
|
|
$return .= "<tr><td>".$result->{internalLabel}." </td><td> <a href=" . '/fhem?cmd.Test=set%20' .$name .'%20config_address_from%20'.urlEncode($result->{internalLabel}).'>set' . "</a></td><td> <a href=" . '/fhem?cmd.Test=set%20' .$name .'%20config_address_between%20'.urlEncode($result->{internalLabel}).'>set' . "</a></td><td> <a href=" . '/fhem?cmd.Test=set%20' .$name .'%20config_address_to%20'.urlEncode($result->{internalLabel}).'>set' . "</a></td></tr>";
|
|
}
|
|
}
|
|
|
|
$return .= "</tbody></table>";
|
|
$return .= "<p><strong>".$addresscount. " Adressen gefunden</strong></p>";
|
|
$return .= "</html>";
|
|
$return =~ s/'/'/g;
|
|
|
|
if ($addresscount == 0) {
|
|
asyncOutput( $param->{CL}, "Die Adresse konnte nicht gefunden werden!" );
|
|
}
|
|
else {
|
|
asyncOutput( $param->{CL}, $return );
|
|
}
|
|
}
|
|
|
|
elsif($msgtype eq "customer-history-records") {
|
|
|
|
my $addresscount = 0;
|
|
my $Voicetext;
|
|
my $return = '<html><table align="" border="0" cellspacing="0" cellpadding="3" width="100%" height="100%" class="mceEditable"><tbody>';
|
|
$return .= "<p>Sprachaufnahmen-Verlauf:</p>";
|
|
$return .= "<tr><td><strong>Datum</strong></td><td><strong> Echoname</strong></td><td><strong> Aufname</strong></td></tr>";
|
|
|
|
if (!defined($json->{customerHistoryRecords})) {}
|
|
elsif (ref($json->{customerHistoryRecords}) ne "ARRAY") {}
|
|
else {
|
|
# Play on Device
|
|
foreach my $result (@{$json->{customerHistoryRecords}}) {
|
|
foreach my $Voicerecords (@{$result->{voiceHistoryRecordItems}}) {
|
|
|
|
next if ($Voicerecords->{recordItemType} eq "TTS_REPLACEMENT_TEXT") ;
|
|
my ($S, $M, $H, $d, $m, $Y) = localtime($result->{timestamp} / 1000);
|
|
$m += 1;
|
|
$Y += 1900;
|
|
my $dt = sprintf("%02d.%02d.%04d %02d:%02d:%02d", $d,$m, $Y, $H, $M, $S);
|
|
$addresscount ++;
|
|
|
|
if ($Voicerecords->{transcriptText} eq "") {$Voicetext = "Falsch erkannt";} else {$Voicetext=$Voicerecords->{transcriptText};}
|
|
|
|
my $MP3Filename = $Voicerecords->{recordItemKey} . ".mp3";
|
|
$MP3Filename =~ s/#//g;
|
|
|
|
$return .= "<tr><td>" . $dt . " </td><td> ". $result->{device}{"deviceName"} . '</td><td> ' . '<audio controls><source src="' . $FW_ME . '/echodevice/VoiceRecords/' . $MP3Filename .'" type="audio/wav">' . '<a target="_blank" href=' . '"' . $FW_ME . '/echodevice/VoiceRecords/' . $MP3Filename .'"' . '>play' . "</a>" . '</audio>' . "</td><td><p>" . $Voicetext . "</p> </td></tr>";
|
|
|
|
if ((-e $FW_dir . "/echodevice/VoiceRecords/". $MP3Filename)) {
|
|
Log3 $name, 4, "[$name] [echodevice_AmazonVoiceMP3] Use EXIST MP3File = " . $MP3Filename ;
|
|
}
|
|
else {
|
|
Log3 $name, 4, "[$name] [echodevice_AmazonVoiceMP3] Download MP3File = " . $MP3Filename ;
|
|
|
|
#Header auslesen
|
|
my $AmazonHeader;
|
|
|
|
# Browser User Agent
|
|
my $HeaderLanguage = AttrVal($name,"browser_language","de,en-US;q=0.7,en;q=0.3");
|
|
my $UserAgent = AttrVal($name,"browser_useragent","Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:62.0) Gecko/20100101 Firefox/62.0");
|
|
|
|
if (AttrVal($name,"browser_useragent_random",0) == 1) {
|
|
$UserAgent = join('', map{('a'..'z','A'..'Z',0..9)[rand 62]} 0..20);
|
|
}
|
|
|
|
if($hash->{model} eq "ACCOUNT") {$AmazonHeader = "User-Agent: ". $UserAgent ."\r\nAccept-Language: " . $HeaderLanguage . "\r\nDNT: 1\r\nConnection: keep-alive\r\nUpgrade-Insecure-Requests: 1\r\nCookie:".$hash->{helper}{".COOKIE"}."\r\ncsrf: ".$hash->{helper}{".CSRF"}."\r\nContent-Type: application/json; charset=UTF-8";}
|
|
else {$AmazonHeader = "User-Agent: ". $UserAgent ."\r\nAccept-Language: " . $HeaderLanguage . "\r\nDNT: 1\r\nConnection: keep-alive\r\nUpgrade-Insecure-Requests: 1\r\nCookie:".$hash->{IODev}->{helper}{".COOKIE"}."\r\ncsrf: ".$hash->{IODev}->{helper}{".CSRF"}."\r\nContent-Type: application/json; charset=UTF-8";}
|
|
|
|
my $params = {
|
|
url => "https://www.amazon.de/alexa-privacy/apd/rvh/audio?uid=" . urlEncode($Voicerecords->{utteranceId}),
|
|
header => $AmazonHeader,
|
|
timeout => 10,
|
|
noshutdown => 1,
|
|
keepalive => 1,
|
|
method => "GET",
|
|
CL => $param->{CL},
|
|
hash => $hash,
|
|
type => $MP3Filename,
|
|
httpversion => $param->{httpversion},
|
|
callback => \&echodevice_AmazonVoiceMP3
|
|
};
|
|
|
|
HttpUtils_NonblockingGet($params);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
$return .= "</tbody></table>";
|
|
$return .= "<p><strong>".$addresscount. " Sprachaufnahmen gefunden</strong></p>";
|
|
$return .= "</html>";
|
|
$return =~ s/'/'/g;
|
|
|
|
if ($addresscount == 0) {
|
|
asyncOutput( $param->{CL}, "Es konnten keine Sprachaufnahmen gefunden werden!" );
|
|
}
|
|
else {
|
|
asyncOutput( $param->{CL}, $return );
|
|
}
|
|
}
|
|
|
|
else {
|
|
Log3 $name, 4, "[$name] [echodevice_Parse] [$msgtype] [$msgnumber] json for unknown message \n".Dumper(echodevice_anonymize($hash, $json));
|
|
}
|
|
|
|
}
|
|
|
|
##########################
|
|
sub echodevice_GetSettings($) {
|
|
|
|
my ($hash) = @_;
|
|
my $name = $hash->{NAME};
|
|
my $nextupdate = int(AttrVal($name,"intervalsettings",60));
|
|
my $ConnectState = "";
|
|
|
|
return if($hash->{model} eq "unbekannt");
|
|
|
|
# ECHO Device disable
|
|
if (AttrVal($name,"disable",0) == 1) {
|
|
RemoveInternalTimer($hash, "echodevice_GetSettings");
|
|
InternalTimer(gettimeofday() + $nextupdate, "echodevice_GetSettings", $hash, 0);
|
|
return;
|
|
}
|
|
|
|
# ECHO am Account registrierern
|
|
if($hash->{model} ne "ACCOUNT") {
|
|
$hash->{IODev}->{helper}{"DEVICETYPE"} = $hash->{helper}{"DEVICETYPE"} ;
|
|
$hash->{IODev}->{helper}{".SERIAL"} = $hash->{helper}{".SERIAL"};
|
|
$hash->{IODev}->{helper}{"VERSION"} = $hash->{helper}{"VERSION"};
|
|
}
|
|
|
|
if($hash->{model} eq "ACCOUNT") {$ConnectState = $hash->{STATE}} else {$ConnectState = $hash->{IODev}->{STATE}}
|
|
|
|
Log3 $name, 5, "[$name] [echodevice_GetSettings] start refresh settings" ;
|
|
|
|
if ($ConnectState eq "connected") {
|
|
|
|
if($hash->{model} eq "ACCOUNT") {
|
|
echodevice_SendCommand($hash,"getnotifications","");
|
|
echodevice_SendCommand($hash,"alarmvolume","");
|
|
echodevice_SendCommand($hash,"bluetoothstate","");
|
|
echodevice_SendCommand($hash,"getdnd","");
|
|
echodevice_SendCommand($hash,"wakeword","");
|
|
echodevice_SendCommand($hash,"listitems_task","TASK");
|
|
echodevice_SendCommand($hash,"listitems_shopping","SHOPPING_ITEM");
|
|
echodevice_SendCommand($hash,"getdevicesettings","");
|
|
echodevice_SendCommand($hash,"getisonline","");
|
|
|
|
echodevice_SendCommand($hash,"devices","") if ($hash->{helper}{VERSION} eq "");
|
|
echodevice_SendCommand($hash,"namedListsIDs","") if ($hash->{helper}{SHOPPING_LIST_ID} eq "");
|
|
echodevice_SendCommand($hash,"devicesstate","");
|
|
|
|
echodevice_SendCommand($hash,"account","") if ($hash->{helper}{".COMMSID"} eq "");
|
|
echodevice_SendLoginCommand($hash,"cookielogin6","");
|
|
|
|
# Voice Reading
|
|
my $IntervalVoice = int(AttrVal($name,"intervalvoice",999999));
|
|
$hash->{helper}{echodevice_refreshvoice} = 0 if ($hash->{helper}{echodevice_refreshvoice} eq "");
|
|
$hash->{helper}{echodevice_refreshvoice_lastdate} = time() if ($hash->{helper}{echodevice_refreshvoice_lastdate} eq "");
|
|
|
|
if ($hash->{helper}{echodevice_refreshvoice} == 0 && $IntervalVoice != 999999) {
|
|
Log3 $name, 5, "[$name] [echodevice_GetSettings] refresh voice command IntervalVoice=$IntervalVoice ";
|
|
$hash->{helper}{echodevice_refreshvoice} = 1;
|
|
InternalTimer(gettimeofday() + $IntervalVoice , "echodevice_refreshvoice", $hash, 0);
|
|
}
|
|
|
|
elsif ($hash->{helper}{echodevice_refreshvoice} == 1 && time() - $hash->{helper}{echodevice_refreshvoice_lastdate} >= $IntervalVoice + 20 ){
|
|
Log3 $name, 5, "[$name] [echodevice_GetSettings] restart refresh voice command IntervalVoice=$IntervalVoice DIFF " . (time() - $hash->{helper}{echodevice_refreshvoice_lastdate}) . ">=" . ($IntervalVoice + 20) ;
|
|
RemoveInternalTimer($hash, "echodevice_refreshvoice");
|
|
InternalTimer(gettimeofday() + $IntervalVoice , "echodevice_refreshvoice", $hash, 0);
|
|
}
|
|
|
|
else {
|
|
Log3 $name, 5, "[$name] [echodevice_GetSettings] refresh voice command";
|
|
echodevice_SendCommand($hash,"activities","");
|
|
}
|
|
|
|
echodevice_SendCommand($hash,"getbehavior","");
|
|
echodevice_SendCommand($hash,"getsettingstraffic","");
|
|
}
|
|
else {
|
|
|
|
Log3 $name, 4, "[echodevice_GetSettings] Devicename=$name DEF=" . $hash->{DEF} . " DEVICETYPE=" . $hash->{helper}{DEVICETYPE} . " Model=" . $hash->{model};
|
|
|
|
if ($hash->{model} eq "Reverb" || $hash->{model} eq "Sonos One" || $hash->{model} eq "Sonos Beam") {
|
|
if ($hash->{IODev}{STATE} eq "connected") {
|
|
readingsBeginUpdate($hash);
|
|
readingsBulkUpdate($hash, "state", $hash->{IODev}{STATE}, 1);
|
|
readingsEndUpdate($hash,1);
|
|
}
|
|
else {$nextupdate = 10;}
|
|
}
|
|
else
|
|
{
|
|
if (ReadingsVal($name, "playStatus", "off") ne "paused") {
|
|
my $CalcInterval = int(ReadingsVal($name, "progresslen", 0)) - (int(ReadingsVal($name, "progress", 0)) + $nextupdate);
|
|
if ($CalcInterval < 0) {}
|
|
elsif ($CalcInterval < ($nextupdate -1) ){$nextupdate = $CalcInterval + 4;}
|
|
|
|
Log3( $name, 4, "[$name] [echodevice_GetSettings] Timer CINTERVAL = " . $CalcInterval);
|
|
}
|
|
if ($hash->{IODev}{STATE} eq "connected") {
|
|
echodevice_SendCommand($hash,"player","");
|
|
echodevice_SendCommand($hash,"media","");
|
|
}
|
|
else {
|
|
$nextupdate = 10;
|
|
}
|
|
}
|
|
|
|
# Readings löschen
|
|
readingsDelete($hash, "COOKIE_STATE") ;
|
|
readingsDelete($hash, "COOKIE_TYPE") ;
|
|
readingsDelete($hash, "2FACode") ;
|
|
readingsDelete($hash, "BrowserUserAgent") ;
|
|
}
|
|
|
|
# Readings Bereinigung
|
|
readingsDelete($hash, "active") if (ReadingsVal($name , "active", "none") ne "none");
|
|
|
|
Log3( $name, 4, "[$name] [echodevice_GetSettings] Timer INTERVAL = " . $nextupdate);
|
|
}
|
|
else {
|
|
Log3 $name, 5, "[$name] [echodevice_GetSettings] unknown state / state = $ConnectState" ;
|
|
}
|
|
|
|
RemoveInternalTimer($hash, "echodevice_GetSettings");
|
|
InternalTimer(gettimeofday() + $nextupdate, "echodevice_GetSettings", $hash, 0);
|
|
return;
|
|
}
|
|
|
|
##########################
|
|
sub echodevice_FirstStart($) {
|
|
|
|
my ($hash) = @_;
|
|
my $name = $hash->{NAME};
|
|
my $CookieDevice = "";
|
|
|
|
readingsSingleUpdate ($hash, "version", $ModulVersion ,0);
|
|
readingsSingleUpdate ($hash, "autocreate_devices", "stop", 0 );
|
|
|
|
# Migration NPM von Version älter 0.0.55
|
|
if ((ReadingsVal($name, "COOKIE_TYPE", "unbekannt") eq "READING_NPM" || ReadingsVal($name, "COOKIE_TYPE", "unbekannt") eq "NPM_Login" ) && ReadingsVal($name, "amazon_refreshtoken", "unbekannt") eq "vorhanden" && $hash->{DEF} ne "xxx\@xxx.xx xxx") {
|
|
$hash->{DEF} = "xxx\@xxx.xx xxx";
|
|
$hash->{LOGINMODE} = "NPM";
|
|
}
|
|
|
|
if(AttrVal( $name, "cookie", "none" ) ne "none") {
|
|
readingsSingleUpdate ($hash, "COOKIE_TYPE", "ATTRIBUTE" ,0);
|
|
$hash->{helper}{".COOKIE"} = AttrVal( $name, "cookie", "none" );
|
|
$hash->{helper}{".COOKIE"} =~ s/Cookie: //g;
|
|
$hash->{helper}{".COOKIE"} =~ /csrf=([-\w]+)[;\s]?(.*)?$/;
|
|
$hash->{helper}{".CSRF"} = $1;
|
|
readingsSingleUpdate ($hash, ".COOKIE", $hash->{helper}{".COOKIE"} ,0); # Cookie als READING festhalten!
|
|
}
|
|
elsif (ReadingsVal( $name, ".COOKIE", "none" ) ne "none") {
|
|
|
|
$hash->{helper}{".COOKIE"} = ReadingsVal( $name, ".COOKIE", "none" );
|
|
|
|
# Prüfen ob es sich um ein NPM Login handelt
|
|
if (index($hash->{helper}{".COOKIE"}, "{") != -1) {
|
|
# NPM Login erkannt
|
|
readingsSingleUpdate ($hash, "COOKIE_TYPE", "READING_NPM" ,0);
|
|
$hash->{helper}{".COOKIE"} =~ /"localCookie":".*session-id=(.*)","?/;
|
|
$hash->{helper}{".COOKIE"} = "session-id=" . $1;
|
|
$hash->{helper}{".COOKIE"} =~ /csrf=([-\w]+)[;\s]?(.*)?$/ if(defined($hash->{helper}{".COOKIE"}));
|
|
$hash->{helper}{".CSRF"} = $1 if(defined($hash->{helper}{".COOKIE"}));
|
|
}
|
|
else {
|
|
# OLD Style
|
|
readingsSingleUpdate ($hash, "COOKIE_TYPE", "READING" ,0);
|
|
$hash->{helper}{".COOKIE"} =~ s/Cookie: //g;
|
|
$hash->{helper}{".COOKIE"} =~ /csrf=([-\w]+)[;\s]?(.*)?$/;
|
|
$hash->{helper}{".CSRF"} = $1;
|
|
}
|
|
}
|
|
else {
|
|
readingsSingleUpdate ($hash, "COOKIE_TYPE", "NEW" ,0);
|
|
}
|
|
|
|
Log3 $name, 4, "[$name] [echodevice_FirstStart] COOKIE = " . $hash->{helper}{".COOKIE"};
|
|
Log3 $name, 4, "[$name] [echodevice_FirstStart] COOKIE_TYPE = " . ReadingsVal( $name, "COOKIE_TYPE", "none" );
|
|
|
|
$hash->{STATE} = "INITIALIZED";
|
|
echodevice_CheckAuth($hash);
|
|
|
|
if(defined($hash->{helper}{".COOKIE"})) {
|
|
echodevice_SendCommand($hash,"devices","");
|
|
echodevice_SendCommand($hash,"account","");
|
|
}
|
|
|
|
# Alte Readingsbereinigen
|
|
readingsDelete($hash, "COOKIE");
|
|
|
|
# Migration aws_secret_key & aws_access_key
|
|
if (ReadingsVal($name , "aws_access_key", "none") ne "none") {
|
|
readingsSingleUpdate ($hash, ".aws_access_key", ReadingsVal($name , lc("AWS_Access_Key"), "none") ,0);
|
|
readingsDelete($hash, "aws_access_key");
|
|
}
|
|
if (ReadingsVal($name , lc("aws_secret_key"), "none") ne "none") {
|
|
readingsSingleUpdate ($hash, ".aws_secret_key", ReadingsVal($name , lc("aws_secret_key"), "none") ,0);
|
|
readingsDelete($hash, "aws_secret_key");
|
|
}
|
|
|
|
# Login Timer setzen
|
|
RemoveInternalTimer($hash, "echodevice_LoginStart");
|
|
InternalTimer(gettimeofday() + 10, "echodevice_LoginStart", $hash, 0);
|
|
}
|
|
|
|
sub echodevice_LoginStart($) {
|
|
my ($hash) = @_;
|
|
my $name = $hash->{NAME};
|
|
my $nextupdate = int(AttrVal($name,"intervallogin",60));
|
|
my $npm_refresh_intervall = int(AttrVal($name,"npm_refresh_intervall",6000));
|
|
my $DeviceState = "";
|
|
|
|
# Bestehenden Timer löschen
|
|
RemoveInternalTimer($hash, "echodevice_LoginStart");
|
|
|
|
# ECHO Device disable
|
|
if (AttrVal($name,"disable",0) == 1) {
|
|
echodevice_setState($hash,"disable");
|
|
$DeviceState = "disable";
|
|
}
|
|
else {
|
|
$DeviceState = "enable";
|
|
if ($hash->{STATE} ne "connected" && $hash->{STATE} ne "connected but loginerror") {
|
|
if ($hash->{STATE} eq "disable") {
|
|
echodevice_setState($hash,"connected");
|
|
}
|
|
else {
|
|
if (index(ReadingsVal($name , ".COOKIE", "0"), "{") != -1) {
|
|
echodevice_SendLoginCommand($hash,"cookielogin6","");# if($hash->{LOGINMODE} eq "NORMAL");
|
|
}
|
|
else {
|
|
if($hash->{LOGINMODE} eq "NORMAL") {
|
|
Log3 $name, 4, "[$name] [echodevice_LoginStart] start login";
|
|
$hash->{helper}{RUNLOGIN} = 0;
|
|
echodevice_SendLoginCommand($hash,"cookielogin1","") if(!defined($attr{$name}{cookie}));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
elsif ($hash->{STATE} eq "connected but loginerror") {
|
|
Log3 $name, 3, "[$name] [echodevice_LoginStart] connected but loginerror";
|
|
echodevice_SendLoginCommand($hash,"cookielogin6","");# if($hash->{LOGINMODE} eq "NORMAL");
|
|
}
|
|
else {
|
|
if (index(ReadingsVal($name , ".COOKIE", "0"), "{") != -1) {
|
|
# Refresh COOKIE
|
|
if (ReadingsAge($name,'.COOKIE',0) > $npm_refresh_intervall) {
|
|
Log3 $name, 3, "[$name] [echodevice_LoginStart] Alter COOKIE=" . ReadingsAge($name,'.COOKIE',0) ."/$npm_refresh_intervall Refresh Cookie!";
|
|
echodevice_NPMLoginRefresh($hash);
|
|
}
|
|
else {
|
|
Log3 $name, 4, "[$name] [echodevice_LoginStart] Alter COOKIE=" . ReadingsAge($name,'.COOKIE',0) . "/$npm_refresh_intervall";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
InternalTimer(gettimeofday() + $nextupdate, "echodevice_LoginStart", $hash, 0);
|
|
Log3 $name, 4, "[$name] [echodevice_LoginStart] [$DeviceState] set next internal timer start in $nextupdate seconds.";
|
|
}
|
|
|
|
sub echodevice_CheckAuth($) {
|
|
my ($hash) = @_;
|
|
my $name = $hash->{NAME};
|
|
return undef if($hash->{model} ne "ACCOUNT");
|
|
|
|
# Erneut Login ausführen wenn Cookie nicht gesetzt wurde!
|
|
if(!defined($hash->{helper}{".COOKIE"})) {
|
|
echodevice_SendLoginCommand($hash,"cookielogin1","") if($hash->{LOGINMODE} eq "NORMAL");
|
|
}
|
|
else {
|
|
echodevice_SendLoginCommand($hash,"cookielogin6","");
|
|
}
|
|
|
|
return undef;
|
|
}
|
|
|
|
sub echodevice_ParseAuth($$$) {
|
|
my ($param, $err, $data) = @_;
|
|
my $hash = $param->{hash};
|
|
my $name = $hash->{NAME};
|
|
my $msgtype = $param->{type};
|
|
|
|
my $nextupdate = int(AttrVal($name,"intervallogin",60));
|
|
|
|
Log3 $name, 4, "[$name] [echodevice_ParseAuth] [$msgtype] ";
|
|
Log3 $name, 5, "[$name] [echodevice_ParseAuth] [$msgtype] DATA Dumper=" . Dumper(echodevice_anonymize($hash, $data));
|
|
|
|
# HTML Informationen mit schreiben
|
|
if (AttrVal($name,"browser_save_data",0) == 1) {
|
|
#Verzeichnis echodevice anlegen
|
|
mkdir($FW_dir . "/echodevice", 0777) unless(-d $FW_dir . "/echodevice" );
|
|
mkdir($FW_dir . "/echodevice/results", 0777) unless(-d $FW_dir . "/echodevice/results" );
|
|
|
|
# Eventuell vorhandene Datei löschen
|
|
my $HTMLFilename = $name . "_" . $msgtype . ".html";
|
|
my $HeaderFilename = $name . "_" . $msgtype . "_header.html";
|
|
if ((-e $FW_dir . "/echodevice/results/". $HTMLFilename)) {unlink $FW_dir . "/echodevice/results/".$HTMLFilename}
|
|
if ((-e $FW_dir . "/echodevice/results/". $HeaderFilename)) {unlink $FW_dir . "/echodevice/results/".$HeaderFilename}
|
|
|
|
# Datei anlegen
|
|
open(FH, ">$FW_dir/echodevice/results/$HTMLFilename");
|
|
print FH $data;
|
|
close(FH);
|
|
|
|
# Datei anlegen
|
|
open(FH, ">$FW_dir/echodevice/results/$HeaderFilename");
|
|
print FH $param->{httpheader};
|
|
close(FH);
|
|
}
|
|
|
|
if($err){
|
|
echodevice_LostConnect($hash,"connection error = $err");
|
|
return undef;
|
|
}
|
|
|
|
if($data =~ /cookie is missing/) {
|
|
echodevice_LostConnect($hash,"connection error = cookie is missing");
|
|
return undef;
|
|
}
|
|
|
|
my $json = eval { JSON->new->utf8(0)->decode($data) };
|
|
if($@) {
|
|
echodevice_LostConnect($hash,"JSON error = no content");
|
|
return undef;
|
|
}
|
|
|
|
if($json->{authentication}{authenticated}){
|
|
|
|
if ($hash->{helper}{".LOGINERROR"} >= 1) {
|
|
Log3 $name, 3, "[$name] [echodevice_ParseAuth] reset loginerror from " . $hash->{helper}{".LOGINERROR"} . " to 0" ;
|
|
$hash->{helper}{".LOGINERROR"} = 0;
|
|
}
|
|
|
|
echodevice_setState($hash,"connected");
|
|
readingsBeginUpdate($hash);
|
|
readingsBulkUpdate($hash, "state", "connected", 1);
|
|
readingsBulkUpdate($hash, "COOKIE_STATE", "OK", 1);
|
|
readingsEndUpdate($hash,1);
|
|
$hash->{helper}{".CUSTOMER"} = $json->{authentication}{customerId};
|
|
Log3 $name, 4, "[$name] [echodevice_ParseAuth] JSON OK = {authentication}{authenticated}";
|
|
}
|
|
|
|
elsif($json->{authentication}) {
|
|
echodevice_LostConnect($hash,"JSON error = {authentication}");
|
|
}
|
|
return undef;
|
|
}
|
|
|
|
sub echodevice_LostConnect($$){
|
|
my ($hash,$State) = @_;
|
|
my $name = $hash->{NAME};
|
|
|
|
$hash->{helper}{CMD_QUEUE} = (); # Query zurücksetzen
|
|
Log3 $name, 4, "[$name] [echodevice_LostConnect] clear CMD_QUEUE" ;
|
|
|
|
if ($hash->{helper}{".LOGINERROR"} >= 5) {
|
|
$hash->{helper}{".LOGINERROR"} = 0;
|
|
Log3 $name, 3, "[$name] [echodevice_LostConnect] $State / Generate new COOKIE! / set loginerror to 0" ;
|
|
echodevice_setState($hash,"disconnected");
|
|
}
|
|
else {
|
|
$hash->{helper}{".LOGINERROR"} = $hash->{helper}{".LOGINERROR"} + 1;
|
|
Log3 $name, 3, "[$name] [echodevice_LostConnect] $State / set loginerror to " . $hash->{helper}{".LOGINERROR"};
|
|
echodevice_setState($hash,"connected but loginerror");
|
|
}
|
|
}
|
|
|
|
##########################
|
|
# HELPER
|
|
##########################
|
|
sub echodevice_getModel($){
|
|
my ($ModelNumber) = @_;
|
|
my $name = $hash->{NAME};
|
|
|
|
if ($ModelNumber eq "AB72C64C86AW2" || $ModelNumber eq "Echo") {return "Echo";}
|
|
elsif($ModelNumber eq "A3S5BH2HU6VAYF" || $ModelNumber eq "Echo Dot") {return "Echo Dot";}
|
|
elsif($ModelNumber eq "A32DOYMUN6DTXA" || $ModelNumber eq "Echo Dot") {return "Echo Dot Gen3";}
|
|
elsif($ModelNumber eq "A32DDESGESSHZA" || $ModelNumber eq "Echo Dot") {return "Echo Dot Gen3";}
|
|
elsif($ModelNumber eq "A1RABVCI4QCIKC" || $ModelNumber eq "Echo Dot") {return "Echo Dot Gen3";}
|
|
elsif($ModelNumber eq "A3RMGO6LYLH7YN" || $ModelNumber eq "Echo Dot") {return "Echo Dot Gen4";}
|
|
elsif($ModelNumber eq "A2U21SRK4QGSE1" || $ModelNumber eq "Echo Dot") {return "Echo Dot Gen4";}
|
|
elsif($ModelNumber eq "A2H4LV5GIZ1JFT" || $ModelNumber eq "Echo Dot") {return "Echo Dot Gen4 with Clock";}
|
|
elsif($ModelNumber eq "A2DS1Q2TPDJ48U" || $ModelNumber eq "Echo Dot") {return "Echo Dot Gen5 with Clock";}
|
|
elsif($ModelNumber eq "A10A33FOX2NUBK" || $ModelNumber eq "Echo Spot") {return "Echo Spot";}
|
|
elsif($ModelNumber eq "A1NL4BVLQ4L3N3" || $ModelNumber eq "Echo Show") {return "Echo Show";}
|
|
elsif($ModelNumber eq "AWZZ5CVHX2CD" || $ModelNumber eq "Echo Show") {return "Echo Show Gen2";}
|
|
elsif($ModelNumber eq "AIPK7MM90V7TB" || $ModelNumber eq "Echo Show") {return "Echo Show Gen3";}
|
|
elsif($ModelNumber eq "A4ZP7ZC4PI6TO" || $ModelNumber eq "Echo Show 5") {return "Echo Show 5";}
|
|
elsif($ModelNumber eq "A1XWJRHALS1REP" || $ModelNumber eq "Echo Show 5") {return "Echo Show 5 Gen2";}
|
|
elsif($ModelNumber eq "A4ZXE0RM7LQ7A" || $ModelNumber eq "Echo Show 5") {return "Echo Show 5 Gen5";}
|
|
elsif($ModelNumber eq "A1Z88NGR2BK6A2" || $ModelNumber eq "Echo Show 8") {return "Echo Show 8";}
|
|
elsif($ModelNumber eq "A15996VY63BQ2D" || $ModelNumber eq "Echo Show 8") {return "Echo Show 8 Gen2";}
|
|
elsif($ModelNumber eq "A1EIANJ7PNB0Q7" || $ModelNumber eq "Echo Show 15") {return "Echo Show 15 Gen1";}
|
|
elsif($ModelNumber eq "A2M35JJZWCQOMZ" || $ModelNumber eq "Echo Plus") {return "Echo Plus";}
|
|
elsif($ModelNumber eq "A1JJ0KFC4ZPNJ3" || $ModelNumber eq "Echo Input") {return "Echo Input";}
|
|
elsif($ModelNumber eq "A18O6U1UQFJ0XK" || $ModelNumber eq "Echo Plus 2") {return "Echo Plus 2";}
|
|
elsif($ModelNumber eq "A3VRME03NAXFUB" || $ModelNumber eq "Echo Flex") {return "Echo Flex";}
|
|
elsif($ModelNumber eq "A3FX4UWTP28V1P" || $ModelNumber eq "Echo") {return "Echo Gen3";}
|
|
elsif($ModelNumber eq "A30YDR2MK8HMRV" || $ModelNumber eq "Echo") {return "Echo Gen3";}
|
|
elsif($ModelNumber eq "A3RBAYBE7VM004" || $ModelNumber eq "Echo Studio") {return "Echo Studio";}
|
|
elsif($ModelNumber eq "A3SSG6GR8UU7SN" || $ModelNumber eq "Echo Sub") {return "Echo Sub";}
|
|
elsif($ModelNumber eq "AILBSA2LNTOYL" || $ModelNumber eq "Reverb") {return "Reverb";}
|
|
elsif($ModelNumber eq "A15ERDAKK5HQQG" || $ModelNumber eq "Sonos Display") {return "Sonos Display";}
|
|
elsif($ModelNumber eq "A2OSP3UA4VC85F" || $ModelNumber eq "Sonos One") {return "Sonos One";}
|
|
elsif($ModelNumber eq "A3NPD82ABCPIDP" || $ModelNumber eq "Sonos Beam") {return "Sonos Beam";}
|
|
elsif($ModelNumber eq "A2Z8O30CD35N8F" || $ModelNumber eq "Sonos Arc") {return "Sonos Arc";}
|
|
elsif($ModelNumber eq "A7WXQPH584YP" || $ModelNumber eq "Echo Gen2") {return "Echo Gen2";}
|
|
elsif($ModelNumber eq "A3C9PE6TNYLTCH" || $ModelNumber eq "Echo Multiroom") {return "Echo Multiroom";}
|
|
elsif($ModelNumber eq "AP1F6KUH00XPV" || $ModelNumber eq "Echo Stereopaar") {return "Echo Stereopaar";}
|
|
elsif($ModelNumber eq "A1DL2DVDQVK3Q" || $ModelNumber eq "Fire Tab HD 10") {return "Fire Tab HD 10";}
|
|
elsif($ModelNumber eq "A3R9S4ZZECZ6YL" || $ModelNumber eq "Fire Tab HD 10") {return "Fire Tab HD 10";}
|
|
elsif($ModelNumber eq "A3L0T0VL9A921N" || $ModelNumber eq "Fire Tab HD 8") {return "Fire Tab HD 8";}
|
|
elsif($ModelNumber eq "A2M4YX06LWP8WI" || $ModelNumber eq "Fire Tab 7") {return "Fire Tab 7";}
|
|
elsif($ModelNumber eq "A2E0SNTXJVT7WK" || $ModelNumber eq "Fire TV V1") {return "Fire TV V1";}
|
|
elsif($ModelNumber eq "A2GFL5ZMWNE0PX" || $ModelNumber eq "Fire TV") {return "Fire TV";}
|
|
elsif($ModelNumber eq "A12GXV8XMS007S" || $ModelNumber eq "Fire TV") {return "Fire TV";}
|
|
elsif($ModelNumber eq "A3HF4YRA2L7XGC" || $ModelNumber eq "Fire TV Cube") {return "Fire TV Cube";}
|
|
elsif($ModelNumber eq "A1VGB7MHSIEYFK" || $ModelNumber eq "Fire TV Cube Gen3") {return "Fire TV Cube Gen3";}
|
|
elsif($ModelNumber eq "ADVBD696BHNV5" || $ModelNumber eq "Fire TV Stick V1") {return "Fire TV Stick V1";}
|
|
elsif($ModelNumber eq "A2LWARUGJLBYEW" || $ModelNumber eq "Fire TV Stick V2") {return "Fire TV Stick V2";}
|
|
elsif($ModelNumber eq "AKPGW064GI9HE" || $ModelNumber eq "Fire TV Stick 4K") {return "Fire TV Stick 4K";}
|
|
elsif($ModelNumber eq "A265XOI9586NML" || $ModelNumber eq "Fire TV Stick 4K") {return "Fire TV Stick 4K";}
|
|
elsif($ModelNumber eq "A3EVMLQTU6WL1W" || $ModelNumber eq "Fire TV Stick 4K Max") {return "Fire TV Stick 4K Max";}
|
|
elsif($ModelNumber eq "A31DTMEEVDDOIV" || $ModelNumber eq "Fire TV Stick 4K") {return "Fire TV";}
|
|
elsif($ModelNumber eq "A2JKHJ0PX4J3L3" || $ModelNumber eq "ECHO FireTv Cube 4K") {return "ECHO FireTv Cube 4K";}
|
|
elsif($ModelNumber eq "A10L5JEZTKKCZ8" || $ModelNumber eq "VOBOT") {return "VOBOT";}
|
|
elsif($ModelNumber eq "A37SHHQ3NUL7B5" || $ModelNumber eq "Bose Home Speaker 500") {return "Bose Home Speaker 500";}
|
|
elsif($ModelNumber eq "AVN2TMX8MU2YM" || $ModelNumber eq "Bose Home Speaker 500") {return "Bose Home Speaker 500";}
|
|
elsif($ModelNumber eq "A1RTAM01W29CUP" || $ModelNumber eq "Alexa App for PC") {return "Alexa App for PC";}
|
|
elsif($ModelNumber eq "A21Z3CGI8UIP0F" || $ModelNumber eq "HEOS") {return "HEOS";}
|
|
elsif($ModelNumber eq "AKOAGQTKAS9YB" || $ModelNumber eq "Echo Connect") {return "Echo Connect";}
|
|
elsif($ModelNumber eq "A3NTO4JLV9QWRB" || $ModelNumber eq "Gigaset L800HX") {return "Gigaset L800HX";}
|
|
elsif($ModelNumber eq "A1HNT9YTOBE735" || $ModelNumber eq "Telekom Smart Speaker") {return "Telekom Smart Speaker";}
|
|
elsif($ModelNumber eq "A1WAR447VT003J" || $ModelNumber eq "Yamaha MusicCast 20") {return "Yamaha MusicCast 20";}
|
|
elsif($ModelNumber eq "AVE5HX13UR5NO" || $ModelNumber eq "Zero Touch (Logitech)") {return "Zero Touch (Logitech)";}
|
|
elsif($ModelNumber eq "A3GZUE7F9MEB4U" || $ModelNumber eq "Sony WH-100XM3") {return "Sony WH-100XM3";}
|
|
elsif($ModelNumber eq "A2J0R2SD7G9LPA" || $ModelNumber eq "Lenovo P10") {return "Lenovo P10";}
|
|
elsif($ModelNumber eq "A1J16TEDOYCZTN" || $ModelNumber eq "Amazon Tablet") {return "Amazon Tablet";}
|
|
elsif($ModelNumber eq "A38EHHIB10L47V" || $ModelNumber eq "Fire HD 8 Tablet") {return "Fire HD 8 Tablet";}
|
|
elsif($ModelNumber eq "A112LJ20W14H95" || $ModelNumber eq "Media Display") {return "Media Display";}
|
|
elsif($ModelNumber eq "A1H0CMF1XM0ZP4" || $ModelNumber eq "Bose Soundtouch") {return "Bose Soundtouch";}
|
|
elsif($ModelNumber eq "AAMFMBBEW2960" || $ModelNumber eq "Garmin DriveSmart 65 with Amazon Alexa") {return "Garmin DriveSmart 65 with Amazon Alexa";}
|
|
elsif($ModelNumber eq "A2IVLV5VM2W81" || $ModelNumber eq "Mobile Voice iOS") {return "Mobile Voice iOS";}
|
|
elsif($ModelNumber eq "A2TF17PFR55MTB" || $ModelNumber eq "Mobile Voice Android") {return "Mobile Voice Android";}
|
|
elsif($ModelNumber eq "A3V3VA38K169FO" || $ModelNumber eq "Fire Tablet") {return "Fire Tablet";}
|
|
elsif($ModelNumber eq "AVD3HM0HOJAAL" || $ModelNumber eq "Sonos One") {return "Sonos One";}
|
|
elsif($ModelNumber eq "A1C66CX2XD756O" || $ModelNumber eq "Fire HD 8 Tablet") {return "Fire HD 8 Tablet";}
|
|
elsif($ModelNumber eq "A17LGWINFBUTZZ" || $ModelNumber eq "Anker Roav Car Charger") {return "Anker Roav Car Charger";}
|
|
elsif($ModelNumber eq "A2XPGY5LRKB9BE" || $ModelNumber eq "FitBit watch") {return "FitBit watch";}
|
|
elsif($ModelNumber eq "A2Y04QPFCANLPQ" || $ModelNumber eq "Bose QC35 II") {return "Bose QC35 II";}
|
|
elsif($ModelNumber eq "A2WFDCBDEXOXR8" || $ModelNumber eq "Bose Soundbar") {return "Bose Soundbar";}
|
|
elsif($ModelNumber eq "A3BW5ZVFHRCQPO" || $ModelNumber eq "Alexa Car") {return "Alexa Car";}
|
|
elsif($ModelNumber eq "A303PJF6ISQ7IC" || $ModelNumber eq "Echo Auto") {return "Echo Auto";}
|
|
elsif($ModelNumber eq "A1ZB65LA390I4K" || $ModelNumber eq "Fire HD 10 Tablet") {return "Fire HD 10 Tablet";}
|
|
elsif($ModelNumber eq "AVU7CPPF2ZRAS" || $ModelNumber eq "Fire HD 8 Plus (2020)") {return "Fire HD 8 Plus (2020)";}
|
|
elsif($ModelNumber eq "A24Z7PEXY4MDTK" || $ModelNumber eq "Sony WF-1000X") {return "Sony WF-1000X";}
|
|
elsif($ModelNumber eq "ABN8JEI7OQF61" || $ModelNumber eq "Sony WF-1000XM3") {return "Sony WF-1000XM3";}
|
|
elsif($ModelNumber eq "A7S41FQ5TWBC9" || $ModelNumber eq "Sony WH-1000XM4") {return "Sony WH-1000XM4";}
|
|
elsif($ModelNumber eq "A2WN1FJ2HG09UN" || $ModelNumber eq "Ultimate Alexa") {return "Ultimate Alexa";}
|
|
elsif($ModelNumber eq "A23FPV4BT7FH68" || $ModelNumber eq "Yamaha YAS-209 Soundbar"){return "Yamaha YAS-209 Soundbar";}
|
|
elsif($ModelNumber eq "A39Y3UG1XLEJLZ" || $ModelNumber eq "Fitbit Sense") {return "Fitbit Sense";}
|
|
elsif($ModelNumber eq "AQCGW9PSYWRF" || $ModelNumber eq "Polk React Soundbar") {return "Polk React Soundbar";}
|
|
|
|
elsif($ModelNumber eq "") {return "";}
|
|
elsif($ModelNumber eq "ACCOUNT") {return "ACCOUNT";}
|
|
else {return "unbekannt";}
|
|
|
|
}
|
|
|
|
sub echodevice_getHelpText($){
|
|
my ($HelpTextType) = @_;
|
|
my $ReturnHelpText = "<html><p><strong>Help:</strong></p>";
|
|
|
|
if ($HelpTextType eq "no arg") {
|
|
$ReturnHelpText .= "No argument given.";
|
|
}
|
|
else {
|
|
$ReturnHelpText .= $HelpTextType;
|
|
}
|
|
|
|
#Allgemeine Infos
|
|
$ReturnHelpText .= "<br><br>More informations: <a target=" . "_blank" . " href=" .'"' . 'https://mwinkler.jimdo.com/smarthome/eigene-module/echodevice/#Set' .'"'. "</a>https://mwinkler.jimdo.com/smarthome/eigene-module/echodevice/#Set</html>";
|
|
|
|
return $ReturnHelpText;
|
|
}
|
|
|
|
sub echodevice_Attr($$$) {
|
|
|
|
my ($cmd, $name, $attrName, $attrVal) = @_;
|
|
my $hash = $defs{$name};
|
|
|
|
if( $attrName eq "cookie" ) {
|
|
#my $hash = $defs{$name};
|
|
if( $cmd eq "set" ) {
|
|
$attrVal =~ s/Cookie: //g;
|
|
$hash->{helper}{".COOKIE"} = $attrVal;
|
|
$hash->{helper}{".COOKIE"} =~ /csrf=([-\w]+)[;\s]?(.*)?$/;
|
|
$hash->{helper}{".CSRF"} = $1;
|
|
$hash->{STATE} = "INITIALIZED";
|
|
}
|
|
}
|
|
|
|
if ( $attrName eq "server" ) {
|
|
#my $hash = $defs{$name};
|
|
if( $cmd eq "set" ) {
|
|
$hash->{helper}{SERVER} = $attrVal;
|
|
}
|
|
}
|
|
|
|
$attr{$name}{$attrName} = $attrVal;
|
|
|
|
return;
|
|
}
|
|
|
|
sub echodevice_anonymize($$) {
|
|
my ($hash, $string) = @_;
|
|
my $s1 = $hash->{helper}{".SERIAL"};
|
|
my $s2 = $hash->{helper}{".CUSTOMER"};
|
|
my $s3 = $hash->{helper}{HOMEGROUP};
|
|
my $s4 = $hash->{helper}{".COMMSID"};
|
|
my $s5;
|
|
$s5 = echodevice_decrypt($hash->{helper}{".USER"}) if(defined($hash->{helper}{".USER"}));
|
|
$s5 = echodevice_decrypt($hash->{IODev}->{helper}{".USER"}) if(defined($hash->{IODev}->{helper}{".USER"}));;
|
|
$s1 = "SERIAL" if(!defined($s1));
|
|
$s2 = "CUSTOMER" if(!defined($s2));
|
|
$s3 = "HOMEGROUP" if(!defined($s3));
|
|
$s4 = "COMMSID" if(!defined($s4));
|
|
$s5 = "USER" if(!defined($s5));
|
|
$string =~ s/$s1/SERIAL/g;
|
|
$string =~ s/$s2/CUSTOMER/g;
|
|
$string =~ s/$s3/HOMEGROUP/g;
|
|
$string =~ s/$s4/COMMSID/g;
|
|
$string =~ s%$s5%USER%g;
|
|
return $string;
|
|
}
|
|
|
|
sub echodevice_encrypt($) {
|
|
my ($decoded) = @_;
|
|
my $key = getUniqueId();
|
|
my $encoded;
|
|
|
|
return $decoded if( $decoded =~ /\Qcrypt:\E/ );
|
|
|
|
for my $char (split //, $decoded) {
|
|
my $encode = chop($key);
|
|
$encoded .= sprintf("%.2x",ord($char)^ord($encode));
|
|
$key = $encode.$key;
|
|
}
|
|
|
|
return 'crypt:'.$encoded;
|
|
}
|
|
|
|
sub echodevice_decrypt($) {
|
|
my ($encoded) = @_;
|
|
my $key = getUniqueId();
|
|
my $decoded;
|
|
|
|
return $encoded if( $encoded !~ /crypt:/ );
|
|
|
|
$encoded = $1 if( $encoded =~ /crypt:(.*)/ );
|
|
|
|
for my $char (map { pack('C', hex($_)) } ($encoded =~ /(..)/g)) {
|
|
my $decode = chop($key);
|
|
$decoded .= chr(ord($char)^ord($decode));
|
|
$key = $decode.$key;
|
|
}
|
|
|
|
return $decoded;
|
|
}
|
|
|
|
sub echodevice_setState($$) {
|
|
my ($hash,$State) = @_;
|
|
my $name = $hash->{NAME};
|
|
|
|
Log3 $name, 3, "[$name] [echodevice_setState] to $State" if($hash->{STATE} ne $State) ;
|
|
|
|
foreach my $DeviceID (sort keys %{$modules{$hash->{TYPE}}{defptr}}) {
|
|
my $echohash = $modules{$hash->{TYPE}}{defptr}{$DeviceID};
|
|
readingsBeginUpdate($echohash);
|
|
readingsBulkUpdateIfChanged( $echohash, "state" , $State,1);
|
|
readingsEndUpdate($echohash,1);
|
|
}
|
|
|
|
readingsBeginUpdate($hash);
|
|
readingsBulkUpdateIfChanged($hash, "state", $State, 1);
|
|
readingsEndUpdate($hash,1);
|
|
|
|
return;
|
|
}
|
|
|
|
sub echodevice_getsequenceJson($$$) {
|
|
my ($hash,$Bereich,$Parameter) = @_;
|
|
my $ResultString ;
|
|
my $BereichString;
|
|
my $BereichValue = "";
|
|
my $Optionals = "";
|
|
|
|
if (lc($Bereich) eq "kalender_heute") {
|
|
$BereichString = '\"type\":\"Alexa.Calendar.PlayToday\"';
|
|
}
|
|
|
|
elsif(lc($Bereich) eq "kalender_morgen") {
|
|
$BereichString = '\"type\":\"Alexa.Calendar.PlayTomorrow\"';
|
|
}
|
|
|
|
elsif(lc($Bereich) eq "kalender_naechstes_ereignis") {
|
|
$BereichString = '\"type\":\"Alexa.Calendar.PlayNext\"'
|
|
}
|
|
|
|
elsif(lc($Bereich) eq "nachrichten") {
|
|
$BereichString = '\"type\":\"Alexa.FlashBriefing.Play\"';
|
|
}
|
|
|
|
elsif(lc($Bereich) eq "verkehr") {
|
|
$BereichString = '\"type\":\"Alexa.Traffic.Play\"';
|
|
}
|
|
|
|
elsif(lc($Bereich) eq "wetter") {
|
|
$BereichString = '\"type\":\"Alexa.Weather.Play\"';
|
|
}
|
|
|
|
elsif(lc($Bereich) eq "volume") {
|
|
$BereichString = '\"type\":\"Alexa.DeviceControls.Volume\"';
|
|
$BereichValue = '\"value\":\"'.$Parameter.'\",';
|
|
}
|
|
|
|
elsif(lc($Bereich) eq "speak") {
|
|
$BereichString = '\"type\":\"Alexa.Speak\"';
|
|
$BereichValue = '\"textToSpeak\":\"'.$Parameter.'\",';
|
|
}
|
|
|
|
elsif(lc($Bereich) eq "erzaehle_geschichte") {$BereichString = '\"type\":\"Alexa.TellStory.Play\"';}
|
|
elsif(lc($Bereich) eq "erzaehle_witz") {$BereichString = '\"type\":\"Alexa.Joke.Play\"';}
|
|
elsif(lc($Bereich) eq "erzaehle_was_neues") {$BereichString = '\"type\":\"Alexa.GoodMorning.Play\"';}
|
|
elsif(lc($Bereich) eq "singe_song") {$BereichString = '\"type\":\"Alexa.SingASong.Play\"';}
|
|
elsif(lc($Bereich) eq "beliebig_auf_wiedersehen") {$BereichString = '\"type\":\"Alexa.CannedTts.Speak\"';$BereichValue = '\"cannedTtsStringId\":\"alexa.cannedtts.speak.curatedtts-category-goodbye/alexa.cannedtts.speak.curatedtts-random\",';}
|
|
elsif(lc($Bereich) eq "beliebig_bestaetigung") {$BereichString = '\"type\":\"Alexa.CannedTts.Speak\"';$BereichValue = '\"cannedTtsStringId\":\"alexa.cannedtts.speak.curatedtts-category-confirmations/alexa.cannedtts.speak.curatedtts-random\",';}
|
|
elsif(lc($Bereich) eq "beliebig_geburtstag") {$BereichString = '\"type\":\"Alexa.CannedTts.Speak\"';$BereichValue = '\"cannedTtsStringId\":\"alexa.cannedtts.speak.curatedtts-category-birthday/alexa.cannedtts.speak.curatedtts-random\",';}
|
|
elsif(lc($Bereich) eq "beliebig_gute_nacht") {$BereichString = '\"type\":\"Alexa.CannedTts.Speak\"';$BereichValue = '\"cannedTtsStringId\":\"alexa.cannedtts.speak.curatedtts-category-goodnight/alexa.cannedtts.speak.curatedtts-random\",';}
|
|
elsif(lc($Bereich) eq "beliebig_guten_morgen") {$BereichString = '\"type\":\"Alexa.CannedTts.Speak\"';$BereichValue = '\"cannedTtsStringId\":\"alexa.cannedtts.speak.curatedtts-category-goodmorning/alexa.cannedtts.speak.curatedtts-random\",';}
|
|
elsif(lc($Bereich) eq "beliebig_ich_bin_zuhause") {$BereichString = '\"type\":\"Alexa.CannedTts.Speak\"';$BereichValue = '\"cannedTtsStringId\":\"alexa.cannedtts.speak.curatedtts-category-iamhome/alexa.cannedtts.speak.curatedtts-random\",';}
|
|
elsif(lc($Bereich) eq "beliebig_kompliment") {$BereichString = '\"type\":\"Alexa.CannedTts.Speak\"';$BereichValue = '\"cannedTtsStringId\":\"alexa.cannedtts.speak.curatedtts-category-compliments/alexa.cannedtts.speak.curatedtts-random\",';}
|
|
#
|
|
elsif(lc($Bereich) eq "glocken") {$BereichString = '\"type\":\"Alexa.Sound\"';$BereichValue = '\"soundStringId\":\"bell_02\",';}
|
|
elsif(lc($Bereich) eq "kirchenglocke") {$BereichString = '\"type\":\"Alexa.Sound\"';$BereichValue = '\"soundStringId\":\"amzn_sfx_church_bell_1x_02\",';}
|
|
elsif(lc($Bereich) eq "summer") {$BereichString = '\"type\":\"Alexa.Sound\"';$BereichValue = '\"soundStringId\":\"buzzers_pistols_01\",';}
|
|
elsif(lc($Bereich) eq "tuerklingel_1") {$BereichString = '\"type\":\"Alexa.Sound\"';$BereichValue = '\"soundStringId\":\"amzn_sfx_doorbell_01\",';}
|
|
elsif(lc($Bereich) eq "tuerklingel_2") {$BereichString = '\"type\":\"Alexa.Sound\"';$BereichValue = '\"soundStringId\":\"amzn_sfx_doorbell_chime_01\",';}
|
|
elsif(lc($Bereich) eq "tuerklingel_3") {$BereichString = '\"type\":\"Alexa.Sound\"';$BereichValue = '\"soundStringId\":\"amzn_sfx_doorbell_chime_02\",';}
|
|
#
|
|
elsif(lc($Bereich) eq "jubelnde_menschenmenge") {$BereichString = '\"type\":\"Alexa.Sound\"';$BereichValue = '\"soundStringId\":\"amzn_sfx_large_crowd_cheer_01\",';}
|
|
elsif(lc($Bereich) eq "publikumsapplaus") {$BereichString = '\"type\":\"Alexa.Sound\"';$BereichValue = '\"soundStringId\":\"amzn_sfx_crowd_applause_01\",';}
|
|
#
|
|
elsif(lc($Bereich) eq "flugzeug") {$BereichString = '\"type\":\"Alexa.Sound\"';$BereichValue = '\"soundStringId\":\"futuristic_10\",';}
|
|
elsif(lc($Bereich) eq "katastrophenalarm") {$BereichString = '\"type\":\"Alexa.Sound\"';$BereichValue = '\"soundStringId\":\"amzn_sfx_scifi_alarm_04\",';}
|
|
elsif(lc($Bereich) eq "motoren_an") {$BereichString = '\"type\":\"Alexa.Sound\"';$BereichValue = '\"soundStringId\":\"amzn_sfx_scifi_engines_on_02\",';}
|
|
elsif(lc($Bereich) eq "schilde_hoch") {$BereichString = '\"type\":\"Alexa.Sound\"';$BereichValue = '\"soundStringId\":\"amzn_sfx_scifi_sheilds_up_01\",';}
|
|
elsif(lc($Bereich) eq "sirenen") {$BereichString = '\"type\":\"Alexa.Sound\"';$BereichValue = '\"soundStringId\":\"amzn_sfx_scifi_alarm_01\",';}
|
|
elsif(lc($Bereich) eq "zappen") {$BereichString = '\"type\":\"Alexa.Sound\"';$BereichValue = '\"soundStringId\":\"zap_01\",';}
|
|
#
|
|
elsif(lc($Bereich) eq "boing_1") {$BereichString = '\"type\":\"Alexa.Sound\"';$BereichValue = '\"soundStringId\":\"boing_01\",';}
|
|
elsif(lc($Bereich) eq "boing_2") {$BereichString = '\"type\":\"Alexa.Sound\"';$BereichValue = '\"soundStringId\":\"boing_03\",';}
|
|
elsif(lc($Bereich) eq "kamera") {$BereichString = '\"type\":\"Alexa.Sound\"';$BereichValue = '\"soundStringId\":\"camera_01\",';}
|
|
elsif(lc($Bereich) eq "lufthupe") {$BereichString = '\"type\":\"Alexa.Sound\"';$BereichValue = '\"soundStringId\":\"air_horn_03\",';}
|
|
elsif(lc($Bereich) eq "quitschende_tuer") {$BereichString = '\"type\":\"Alexa.Sound\"';$BereichValue = '\"soundStringId\":\"squeaky_12\",';}
|
|
elsif(lc($Bereich) eq "tickende_uhr") {$BereichString = '\"type\":\"Alexa.Sound\"';$BereichValue = '\"soundStringId\":\"clock_01\",';}
|
|
elsif(lc($Bereich) eq "trompete") {$BereichString = '\"type\":\"Alexa.Sound\"';$BereichValue = '\"soundStringId\":\"amzn_sfx_trumpet_bugle_04\",';}
|
|
#
|
|
elsif(lc($Bereich) eq "hahn") {$BereichString = '\"type\":\"Alexa.Sound\"';$BereichValue = '\"soundStringId\":\"amzn_sfx_rooster_crow_01\",';}
|
|
elsif(lc($Bereich) eq "hundegebell") {$BereichString = '\"type\":\"Alexa.Sound\"';$BereichValue = '\"soundStringId\":\"amzn_sfx_dog_med_bark_1x_02\",';}
|
|
elsif(lc($Bereich) eq "katzenmauzen") {$BereichString = '\"type\":\"Alexa.Sound\"';$BereichValue = '\"soundStringId\":\"amzn_sfx_cat_meow_1x_01\",';}
|
|
elsif(lc($Bereich) eq "loewengebruell") {$BereichString = '\"type\":\"Alexa.Sound\"';$BereichValue = '\"soundStringId\":\"amzn_sfx_lion_roar_02\",';}
|
|
elsif(lc($Bereich) eq "wolfsgeheul") {$BereichString = '\"type\":\"Alexa.Sound\"';$BereichValue = '\"soundStringId\":\"amzn_sfx_wolf_howl_02\",';}
|
|
#
|
|
elsif(lc($Bereich) eq "gruselig_quitschende_tuer") {$BereichString = '\"type\":\"Alexa.Sound\"';$BereichValue = '\"soundStringId\":\"horror_10\",';}
|
|
elsif(lc($Bereich) eq "weihnachtsglocken") {$BereichString = '\"type\":\"Alexa.Sound\"';$BereichValue = '\"soundStringId\":\"christmas_05\",';}
|
|
|
|
$ResultString = '{"behaviorId":"PREVIEW","sequenceJson":"{\"@type\":\"com.amazon.alexa.behaviors.model.Sequence\",\"startNode\":{\"@type\":\"com.amazon.alexa.behaviors.model.OpaquePayloadOperationNode\",' . $BereichString . ',\"operationPayload\":{\"deviceType\":\"' . $hash->{helper}{DEVICETYPE} . '\",\"deviceSerialNumber\":\"' . $hash->{helper}{".SERIAL"} . '\",'.$BereichValue .'\"locale\":\"de-DE\",\"customerId\":\"' . $hash->{IODev}->{helper}{".CUSTOMER"} .'\"}}}","status":"ENABLED"}';
|
|
|
|
return $ResultString;
|
|
}
|
|
|
|
sub echodevice_refreshvoice($) {
|
|
my ($hash) = @_;
|
|
echodevice_SendCommand($hash,"activities","");
|
|
}
|
|
|
|
##########################
|
|
# NPM HELPER
|
|
##########################
|
|
sub echodevice_NPMInstall($){
|
|
|
|
my ($hash) = @_;
|
|
my $name = $hash->{NAME};
|
|
|
|
my $InstallResult = '<html><p><strong>Installationsergebnis</strong></p><br>';
|
|
my $npm_bin = AttrVal($name,"npm_bin","/usr/bin/npm");
|
|
|
|
my $npm_fhem_home = AttrVal($name,"fhem_home","/opt/fhem");
|
|
|
|
if (!(-d $npm_fhem_home)) {
|
|
Log3 $name, 3, "[$name] [echodevice_NPMLoginRefresh] npm_fhem_home $npm_fhem_home existiert nicht!! Bitte das Attribut fhem_home entsprechend einrichten " ;
|
|
return;
|
|
}
|
|
|
|
# Prüfen ob npm installiert ist
|
|
if (!(-e $npm_bin)) {
|
|
$InstallResult .= '<p>Das Bin <strong>' . $npm_bin . '</strong> wurde nicht gefunden. Bitte zuerst das Linux Paket NPM installieren. Folgenden Befehl koennt Ihr hier verwenden:</p>';
|
|
$InstallResult .= '<p><strong><font color="blue">sudo apt-get install npm</font></strong></p><br>';
|
|
$InstallResult .= '<p>Sollte das Linux Paket NPM schon installiert sein, muesst Ihr ggf. das Attribut "<strong>npm_bin</strong>" entsprechend anpassen. Standard=/usr/bin/npm</p>';
|
|
$InstallResult .= '<br><form><input type="button" value="Zurück" onClick="history.go(-1);return true;"></form>';
|
|
$InstallResult .= "</html>";
|
|
$InstallResult =~ s/'/'/g;
|
|
Log3 $name, 3, "[$name] [echodevice_NPMInstall] " . $npm_bin . " not found" ;
|
|
return $InstallResult;
|
|
}
|
|
|
|
# Verzeichnis anlegen
|
|
mkdir($npm_fhem_home . "/cache", 0777) unless(-d "cache" );
|
|
mkdir($npm_fhem_home . "/cache/alexa-cookie", 0777) unless(-d $npm_fhem_home . "/cache/alexa-cookie" );
|
|
mkdir($npm_fhem_home . "/cache/alexa-cookie/node_modules", 0777) unless(-d $npm_fhem_home . "/cache/alexa-cookie/node_modules" );
|
|
|
|
# Prüfen ob schon eine Installation vorhanden ist ggf. Modul löschen
|
|
if (-e $npm_fhem_home . "/cache/alexa-cookie/node_modules/alexa-cookie2/alexa-cookie.js") {
|
|
$InstallResult .= "Vorhandene Installation wird aktualisiert<br>";
|
|
unlink "cache/alexa-cookie/node_modules/alexa-cookie2/alexa-cookie.js";
|
|
}
|
|
else {$InstallResult .= "Installation wird angestartet<br>";}
|
|
|
|
open CMD,'-|','sudo ' . $npm_bin . ' install --prefix ' . $npm_fhem_home . '/cache/alexa-cookie alexa-cookie2' or die $@;
|
|
my $line;
|
|
while (defined($line=<CMD>)) {$InstallResult .= $line. "<br>";}
|
|
close CMD;
|
|
|
|
# Prüfen ob das alexa-cookie Modul vorhanden ist
|
|
if (-e $npm_fhem_home . "/cache/alexa-cookie/node_modules/alexa-cookie2/alexa-cookie.js") {$InstallResult .= '<p><strong><font color="green">Installation erfolgreich durchgefuehrt</font></strong></p>';}
|
|
else {$InstallResult .= '<p><strong><font color="red">!!Installation fehlgeschlagen!!</font></strong></p>';}
|
|
|
|
# Zurückbutton
|
|
$InstallResult .= '<br><form><input type="button" value="Zurück" onClick="history.go(-1);return true;"></form>';
|
|
$InstallResult .= "</html>";
|
|
$InstallResult =~ s/'/'/g;
|
|
|
|
return $InstallResult;
|
|
}
|
|
|
|
sub echodevice_NPMLoginNew($){
|
|
my ($hash) = @_;
|
|
my $name = $hash->{NAME};
|
|
my $number = $hash->{NR};
|
|
my $InstallResult = '<html><p><strong>Login Ergebnis</strong></p><br>';
|
|
my $npm_bin_node = AttrVal($name,"npm_bin_node","/usr/bin/node");
|
|
my $npm_fhem_home = AttrVal($name,"fhem_home","/opt/fhem");
|
|
|
|
$NPMLoginTyp = "NPM Login New " . localtime();
|
|
|
|
# Prüfen ob node installiert ist
|
|
if (!(-e $npm_bin_node)) {
|
|
$InstallResult .= '<p>Das Bin <strong>' . $npm_bin_node . '</strong> wurde nicht gefunden. Bitte zuerst das Linux Paket NPM installieren. Folgenden Befehl koennt Ihr hier verwenden:</p>';
|
|
$InstallResult .= '<p><strong><font color="blue">sudo apt-get install npm</font></strong></p><br>';
|
|
$InstallResult .= '<p>Sollte das Linux Paket NPM schon installiert sein, muesst Ihr ggf. das Attribut "<strong>npm_bin_node</strong>" entsprechend anpassen. Standard=/usr/bin/node</p>';
|
|
$InstallResult .= '<br><form><input type="button" value="Zurück" onClick="history.go(-1);return true;"></form>';
|
|
$InstallResult .= "</html>";
|
|
$InstallResult =~ s/'/'/g;
|
|
Log3 $name, 3, "[$name] [echodevice_NPMLoginNew] " . $npm_bin_node . " not found" ;
|
|
return $InstallResult;
|
|
}
|
|
|
|
# Node Version prüfen
|
|
close NODEVER;
|
|
open NODEVER,'-|', 'node -v' or die $@;
|
|
my $NodeResult;
|
|
my $NodeLoop = "2";
|
|
do {
|
|
$NodeResult=<NODEVER>;
|
|
$NodeResult =~ s/v//g;
|
|
|
|
#Log3 $name, 3, "[$name] [echodevice_NPMLoginNew] Node Version $NodeResult";
|
|
if (version->declare($NodeResult)->numify < version->declare('8.10')->numify ) {
|
|
|
|
$InstallResult .= '<p>Die installierte Node Version <strong>' . $NodeResult . '</strong> ist zu alt. Bitte zuerst die Node Version auf Minimum <strong>8.12</strong> aktualisieren. Folgende Befehle koennt Ihr hier verwenden:</p>';
|
|
$InstallResult .= '<p><strong><font color="blue">sudo apt-get install curl</font></strong></p>';
|
|
$InstallResult .= '<p><strong><font color="blue">curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -</font></strong></p>';
|
|
$InstallResult .= '<p><strong><font color="blue">sudo apt-get update</font></strong></p>';
|
|
$InstallResult .= '<p><strong><font color="blue">sudo apt-get install nodejs</font></strong></p><br>';
|
|
$InstallResult .= '<br><form><input type="button" value="Zurück" onClick="history.go(-1);return true;"></form>';
|
|
$InstallResult .= "</html>";
|
|
$InstallResult =~ s/'/'/g;
|
|
Log3 $name, 3, "[$name] [echodevice_NPMLoginNew] Node Version " . $NodeResult . " is to old! Pleas make an update";
|
|
return $InstallResult;
|
|
|
|
}
|
|
else {Log3 $name, 3, "[$name] [echodevice_NPMLoginNew] Node Version " . $NodeResult;}
|
|
|
|
|
|
|
|
} while ($NodeLoop eq "1");
|
|
|
|
# Prüfen ob das alexa-cookie Mdoul vorhanden ist
|
|
if (!(-e "cache/alexa-cookie/node_modules/alexa-cookie2/alexa-cookie.js")) {
|
|
$InstallResult .= '<p>Das alexa-cookie Modul wurde nicht gefunden. Bitte fuehrt am Amazon Account Device einen set "<strong>NPM_install</strong>" durch </p>';
|
|
$InstallResult .= '<br><form><input type="button" value="Zurück" onClick="history.go(-1);return true;"></form>';
|
|
$InstallResult .= "</html>";
|
|
$InstallResult =~ s/'/'/g;
|
|
Log3 $name, 3, "[$name] [echodevice_NPMLoginNew] alexa-cookie modul not found" ;
|
|
return $InstallResult;
|
|
}
|
|
|
|
# Version prüfen;
|
|
echodevice_NPMCheckVersion($hash,"cache/alexa-cookie/node_modules/alexa-cookie2/package.json","echodevice_NPMLoginNew");
|
|
|
|
my $ProxyPort = AttrVal($name,"npm_proxy_port","3002");
|
|
my $OwnIP = "127.0.0.1";
|
|
|
|
# Eigene IP-Adresse ermitteln
|
|
my $cmdLine = 'ip -o addr show | awk \'/inet/ {print $2, $3, $4}\'';
|
|
my @ips = `$cmdLine`;
|
|
|
|
foreach my $ipLine (@ips) {
|
|
my ($interface, undef, $ipParts) = split(' ', $ipLine);
|
|
my ($ip) = split('/', $ipParts);
|
|
Log3 $name, 3, "[$name] [echodevice_NPMLoginNew] Check Interface=$interface IP=$ip";
|
|
if ($interface ne 'lo' and (!(index($interface, "tun") != -1))) {
|
|
if (!(index($ip, ":") != -1)) {
|
|
$OwnIP = $ip ;
|
|
Log3 $name, 3, "[$name] [echodevice_NPMLoginNew] Result Interface=$interface IP=$ip";
|
|
}
|
|
}
|
|
else {
|
|
Log3 $name, 3, "[$name] [echodevice_NPMLoginNew] Ignor Interface=$interface IP=$ip";
|
|
}
|
|
}
|
|
|
|
my $ProxyIP = AttrVal($name,"npm_proxy_ip",$OwnIP);
|
|
|
|
if ($ProxyIP eq "127.0.0.1") {
|
|
$InstallResult .= '<p>Die Ermittlung der IP-Adresse <strong>' . $ProxyIP . '</strong> des FHEM Servers hat nicht funktioniert, bitte das Attribut "<strong>npm_proxy_ip</strong>" entsprechend anpassen.</p>';
|
|
$InstallResult .= '<br><form><input type="button" value="Zurück" onClick="history.go(-1);return true;"></form>';
|
|
$InstallResult .= "</html>";
|
|
$InstallResult =~ s/'/'/g;
|
|
Log3 $name, 3, "[$name] [echodevice_NPMLoginNew] wrong IP-Address" ;
|
|
return $InstallResult;
|
|
}
|
|
|
|
# Proxy Listen IP
|
|
my $ProxyListenIP = AttrVal($name,"npm_proxy_listen_ip",$OwnIP);
|
|
|
|
# Prüfen ob der Port belegt ist
|
|
my $PORTLoop = "1";
|
|
my $NetstatFound = "1";
|
|
close PORT;
|
|
open PORT,'-|', 'netstat -a' or do {$NetstatFound= "0"};
|
|
|
|
if ($NetstatFound eq "1") {
|
|
my $PORTResult;
|
|
do {
|
|
$PORTResult=<PORT>;
|
|
|
|
Log3 $name, 4, "[$name] [echodevice_NPMLoginNew] Result Proxy Port $PORTResult" if ($PORTResult ne "");
|
|
|
|
if (index($PORTResult, ":" . $ProxyPort . " " ) != -1) {
|
|
$PORTLoop = "2";
|
|
Log3 $name, 3, "[$name] [echodevice_NPMLoginNew] Result Proxy Port $PORTResult";
|
|
}
|
|
|
|
$PORTLoop = "3" if ($PORTResult eq "");
|
|
|
|
} while ($PORTLoop eq "1");
|
|
|
|
close PORT;
|
|
}
|
|
|
|
if ($PORTLoop eq "2") {
|
|
$InstallResult .= '<p>Der angegebene Proxy Port <strong>' . $ProxyPort . '</strong> ist in Benutzung, bitte das Attribut "<strong>npm_proxy_port</strong>" entsprechend anpassen.</p>';
|
|
$InstallResult .= '<br><form><input type="button" value="Zurück" onClick="history.go(-1);return true;"></form>';
|
|
$InstallResult .= "</html>";
|
|
$InstallResult =~ s/'/'/g;
|
|
Log3 $name, 3, "[$name] [echodevice_NPMLoginNew] Proxy Port $ProxyPort is in use" ;
|
|
return $InstallResult;
|
|
}
|
|
elsif ($PORTLoop eq "1") {
|
|
$InstallResult .= '<p>Die Pruefung des angegebenen Proxy Ports <strong>' . $ProxyPort . '</strong> hat nicht funktioniert. Zum Pruefen des Proxy Ports wird die Anwendung "netstat" benoetigt. Folgende Befehle koennt Ihr hier verwenden:</p>';
|
|
$InstallResult .= '<p><strong><font color="blue">sudo apt-get update</font></strong></p>';
|
|
$InstallResult .= '<p><strong><font color="blue">sudo apt-get install net-tools</font></strong></p><br>';
|
|
$InstallResult .= '<br><form><input type="button" value="Zurück" onClick="history.go(-1);return true;"></form>';
|
|
$InstallResult .= "</html>";
|
|
$InstallResult =~ s/'/'/g;
|
|
Log3 $name, 3, "[$name] [echodevice_NPMLoginNew] Proxy Port netstat not found" ;
|
|
return $InstallResult;
|
|
}
|
|
else {
|
|
Log3 $name, 3, "[$name] [echodevice_NPMLoginNew] Proxy Port $ProxyPort is free";
|
|
}
|
|
|
|
Log3 $name, 3, "[$name] [echodevice_NPMLoginNew] Proxy IP $ProxyIP";
|
|
|
|
my $SkriptContent = "alexaCookie = require('alexa-cookie2');" . "\n";
|
|
$SkriptContent .= "fs = require('fs');" . "\n";
|
|
$SkriptContent .= "" . "\n";
|
|
$SkriptContent .= "const config = {" . "\n";
|
|
$SkriptContent .= " logger: console.log," . "\n";
|
|
$SkriptContent .= " setupProxy: true," . "\n";
|
|
$SkriptContent .= " proxyOwnIp: '$ProxyIP'," . "\n";
|
|
$SkriptContent .= " proxyPort: $ProxyPort," . "\n";
|
|
$SkriptContent .= " proxyListenBind: '$ProxyListenIP'," . "\n";
|
|
$SkriptContent .= " proxyLogLevel: 'info'" . "\n";
|
|
$SkriptContent .= "};" . "\n";
|
|
$SkriptContent .= "" . "\n";
|
|
$SkriptContent .= "alexaCookie.generateAlexaCookie('LoginFHEM', 'xxxx', config, (err, result) => {" . "\n";
|
|
$SkriptContent .= " console.log('RESULT: ' + err + ' / ' + JSON.stringify(result));" . "\n";
|
|
$SkriptContent .= " fs.writeFileSync('" . $npm_fhem_home . "/cache/alexa-cookie/" . $number . "result.json', JSON.stringify(result) , 'utf-8'); " . "\n";
|
|
$SkriptContent .= " if (result && result.csrf) {" . "\n";
|
|
$SkriptContent .= " alexaCookie.stopProxyServer();" . "\n";
|
|
$SkriptContent .= " }" . "\n";
|
|
$SkriptContent .= "});" . "\n";
|
|
$SkriptContent .= "" . "\n";
|
|
|
|
my $filename = $npm_fhem_home . "/cache/alexa-cookie/" . $number . "create-cookie.js";
|
|
|
|
# Altes Skript löschen
|
|
if ((-e $filename)) {unlink $filename};
|
|
|
|
# Neues Skript anlegen
|
|
open(FH, ">$filename");
|
|
print FH $SkriptContent;
|
|
close(FH);
|
|
|
|
# Prüfen ob das alexa-cookie Mdoul vorhanden ist
|
|
if (!(-e $filename)) {
|
|
$InstallResult .= '<p>Das Skript zum Amazon Login konnte nicht gefunden werden!</p>';
|
|
$InstallResult .= '<br><form><input type="button" value="Zurück" onClick="history.go(-1);return true;"></form>';
|
|
$InstallResult .= "</html>";
|
|
$InstallResult =~ s/'/'/g;
|
|
Log3 $name, 3, "[$name] [echodevice_NPMLoginNew] $filename not found" ;
|
|
return $InstallResult;
|
|
}
|
|
|
|
my $CreatCookie;
|
|
|
|
# Infos festhalten
|
|
readingsSingleUpdate( $hash, "amazon_refreshtoken", "wird erzeugt",1 );
|
|
|
|
# Skript ausführen
|
|
close CMD;
|
|
open CMD,'-|', $npm_bin_node . ' ' . $filename or die $@;
|
|
my $line;
|
|
my $Loop = "1";
|
|
my $LoopCount = 0;
|
|
do {
|
|
$line=<CMD>;
|
|
$CreatCookie .= $line. "<br>";
|
|
|
|
if ($line ne "") {Log3 $name, 3, "[$name] [echodevice_NPMLoginNew] Result $line"}
|
|
else {$LoopCount +=1;}
|
|
|
|
$Loop = "2" if (index($line, "Please check credentials") != -1) ;
|
|
$Loop = "2" if (index($line, "Proxy-Server listening on port") != -1) ;
|
|
$Loop = "3" if (index($line, "Final Registraton Result") != -1) ;
|
|
$Loop = "4" if ($line eq "" && $LoopCount > 100);
|
|
} while ($Loop eq "1");
|
|
|
|
if ($Loop eq "2") {
|
|
$InstallResult .= 'Bitte den Link anklicken und die Amazonanmeldung durchfuehren.<br>';
|
|
$InstallResult .= '<a target="_blank" href="http://' . $ProxyIP . ':' . $ProxyPort . '/">http://' . $ProxyIP . ':' . $ProxyPort . '</a><br>';
|
|
$InstallResult .= '<br><form><input type="button" value="Zurück" onClick="history.go(-1);return true;"></form>';
|
|
$InstallResult .= "</html>";
|
|
$InstallResult =~ s/'/'/g;
|
|
Log3 $name, 3, "[$name] [echodevice_NPMLoginNew] Result: Bitte den Link anklicken und die Amazonanmeldung durchfuehren.";
|
|
InternalTimer(gettimeofday() + 3 , "echodevice_NPMWaitForCookie" , $hash, 0);
|
|
return $InstallResult;
|
|
}
|
|
elsif($Loop eq "3") {
|
|
$InstallResult .= '<p><strong><font color="green">Refreshtoken wurde erfolgreich erstellt</font></strong></p>';
|
|
$InstallResult .= '<br><form><input type="button" value="Zurück" onClick="history.go(-1);return true;"></form>';
|
|
$InstallResult .= "</html>";
|
|
$InstallResult =~ s/'/'/g;
|
|
Log3 $name, 3, "[$name] [echodevice_NPMLoginNew] Result: Refreshtoken wurde erfolgreich erstellt.";
|
|
InternalTimer(gettimeofday() + 3 , "echodevice_NPMWaitForCookie" , $hash, 0);
|
|
return $InstallResult;
|
|
}
|
|
elsif($Loop eq "4") {
|
|
$InstallResult .= '<p><strong><font color="red">Es ist ein Fehler aufgetreten!! Bitte das FHEM Log pruefen.</font></strong></p>';
|
|
$InstallResult .= '<br><form><input type="button" value="Zurück" onClick="history.go(-1);return true;"></form>';
|
|
$InstallResult .= "</html>";
|
|
$InstallResult =~ s/'/'/g;
|
|
Log3 $name, 3, "[$name] [echodevice_NPMLoginNew] Result: Es ist ein Fehler aufgetreten!! Bitte das FHEM Log pruefen.";
|
|
return $InstallResult;
|
|
}
|
|
else {
|
|
Log3 $name, 3, "[$name] [echodevice_NPMLoginNew] Result: Es ist ein Fehler aufgetreten!! Bitte das FHEM Log pruefen.!!!!!!";
|
|
return $InstallResult;
|
|
}
|
|
|
|
}
|
|
|
|
sub echodevice_NPMLoginRefresh($){
|
|
my ($hash) = @_;
|
|
my $name = $hash->{NAME};
|
|
my $number = $hash->{NR};
|
|
my $RefreshCookie = ReadingsVal($name , ".COOKIE", "0");
|
|
|
|
my $InstallResult = '<html><p><strong>Login Ergebnis</strong></p><br>';
|
|
my $npm_bin_node = AttrVal($name,"npm_bin_node","/usr/bin/node");
|
|
my $npm_fhem_home = AttrVal($name,"fhem_home","/opt/fhem");
|
|
|
|
$NPMLoginTyp = "NPM Login Refresh " . localtime();
|
|
|
|
if (!(-d $npm_fhem_home)) {
|
|
Log3 $name, 3, "[$name] [echodevice_NPMLoginRefresh] npm_fhem_home $npm_fhem_home existiert nicht!! Bitte das Attribut fhem_home entsprechend einrichten " ;
|
|
return;
|
|
}
|
|
|
|
# Prüfen ob npm installiert ist
|
|
Log3 $name, 4, "[$name] [echodevice_NPMLoginRefresh] check $npm_bin_node" ;
|
|
if (!(-e $npm_bin_node)) {
|
|
$InstallResult .= '<p>Das Bin <strong>' . $npm_bin_node . '</strong> wurde nicht gefunden. Bitte zuerst das Linux Paket NPM installieren. Folgenden Befehl koennt Ihr hier verwenden:</p>';
|
|
$InstallResult .= '<p><strong><font color="blue">sudo apt-get install npm</font></strong></p><br>';
|
|
$InstallResult .= '<p>Sollte das Linux Paket NPM schon installiert sein, muesst Ihr ggf. das Attribut "<strong>npm_bin_node</strong>" entsprechend anpassen. Standard=/usr/bin/node</p>';
|
|
$InstallResult .= '<br><form><input type="button" value="Zurück" onClick="history.go(-1);return true;"></form>';
|
|
$InstallResult .= "</html>";
|
|
$InstallResult =~ s/'/'/g;
|
|
Log3 $name, 3, "[$name] [echodevice_NPMLoginRefresh] " . $npm_bin_node . " not found" ;
|
|
return $InstallResult;
|
|
}
|
|
|
|
# Prüfen ob das alexa-cookie Mdoul vorhanden ist
|
|
Log3 $name, 4, "[$name] [echodevice_NPMLoginRefresh] check alexa-cookie.js" ;
|
|
if (!(-e "cache/alexa-cookie/node_modules/alexa-cookie2/alexa-cookie.js")) {
|
|
$InstallResult .= '<p>Das alexa-cookie Modul wurde nicht gefunden. Bitte fuehrt am Amazon Account Device einen set "<strong>NPM_install</strong>" durch </p>';
|
|
$InstallResult .= '<br><form><input type="button" value="Zurück" onClick="history.go(-1);return true;"></form>';
|
|
$InstallResult .= "</html>";
|
|
$InstallResult =~ s/'/'/g;
|
|
Log3 $name, 3, "[$name] [echodevice_NPMLoginRefresh] alexa-cookie modul not found" ;
|
|
return $InstallResult;
|
|
}
|
|
|
|
# Version prüfen;
|
|
echodevice_NPMCheckVersion($hash,"cache/alexa-cookie/node_modules/alexa-cookie2/package.json","echodevice_NPMLoginRefresh");
|
|
|
|
# Prüfen ob das Refresh Cookie gültig ist!
|
|
Log3 $name, 4, "[$name] [echodevice_NPMLoginRefresh] check Refresh Cookie String" ;
|
|
if (substr($RefreshCookie,0,1) ne "{") {
|
|
$InstallResult .= '<p>Das angegebene Refreshtoken Cookie ist ungeueltig! Refreshtoken="<strong>' . $RefreshCookie . '</strong>"</p>';
|
|
$InstallResult .= '<br><form><input type="button" value="Zurück" onClick="history.go(-1);return true;"></form>';
|
|
$InstallResult .= "</html>";
|
|
$InstallResult =~ s/'/'/g;
|
|
Log3 $name, 3, "[$name] [echodevice_NPMLoginRefresh] refreshtoken unkown!! refreshtoken=" . $RefreshCookie;
|
|
return $InstallResult;
|
|
}
|
|
|
|
Log3 $name, 4, "[$name] [echodevice_NPMLoginRefresh] build " . $number . "refresh-cookie.js";
|
|
my $SkriptContent = "alexaCookie = require('alexa-cookie2');" . "\n";
|
|
$SkriptContent .= "fs = require('fs');" . "\n";
|
|
$SkriptContent .= "" . "\n";
|
|
$SkriptContent .= "const config = {" . "\n";
|
|
$SkriptContent .= " logger: console.log," . "\n";
|
|
$SkriptContent .= " formerRegistrationData: " . $RefreshCookie . "\n";
|
|
$SkriptContent .= "};" . "\n";
|
|
$SkriptContent .= "" . "\n";
|
|
$SkriptContent .= "alexaCookie.refreshAlexaCookie(config, (err, result) => {" . "\n";
|
|
$SkriptContent .= " console.log('RESULT: ' + err + ' / ' + JSON.stringify(result));" . "\n";
|
|
$SkriptContent .= " fs.writeFileSync('" . $npm_fhem_home . "/cache/alexa-cookie/" . $number . "result.json', JSON.stringify(result) , 'utf-8'); " . "\n";
|
|
$SkriptContent .= "});" . "\n";
|
|
$SkriptContent .= "" . "\n";
|
|
|
|
my $filename = $npm_fhem_home . "/cache/alexa-cookie/" . $number . "refresh-cookie.js";
|
|
#$InstallResult .= '<form><input type="button" value="Zurück" onClick="history.go(-1);return true;"></form><br>';
|
|
|
|
# Altes Skript löschen
|
|
if ((-e $filename)) {unlink $filename};
|
|
|
|
# Neues Skript anlegen
|
|
open(FH, ">$filename");
|
|
print FH $SkriptContent;
|
|
close(FH);
|
|
|
|
# Prüfen ob das alexa-cookie Mdoul vorhanden ist
|
|
Log3 $name, 4, "[$name] [echodevice_NPMLoginRefresh] check " . $number . "refresh-cookie.js";
|
|
if (!(-e $filename)) {
|
|
$InstallResult .= '<p>Das Skript zum Amazon Login konnte nicht gefunden werden!</p>';
|
|
$InstallResult .= '<br><form><input type="button" value="Zurück" onClick="history.go(-1);return true;"></form>';
|
|
$InstallResult .= "</html>";
|
|
$InstallResult =~ s/'/'/g;
|
|
Log3 $name, 3, "[$name] [echodevice_NPMLoginNew] refresh-cookie.js not found" ;
|
|
return $InstallResult;
|
|
}
|
|
|
|
# Skript ausführen
|
|
close CMD;
|
|
Log3 $name, 4, "[$name] [echodevice_NPMLoginRefresh] start $npm_bin_node $filename";
|
|
open CMD,'-|',$npm_bin_node . ' ' . $filename . ' &';
|
|
|
|
Log3 $name, 4, "[$name] [echodevice_NPMLoginRefresh] start InternalTimer echodevice_NPMWaitForCookie";
|
|
InternalTimer(gettimeofday() + 1 , "echodevice_NPMWaitForCookie" , $hash, 0);
|
|
|
|
return ;#$InstallResult;
|
|
|
|
}
|
|
|
|
sub echodevice_NPMWaitForCookie($){
|
|
my ($hash) = @_;
|
|
my $name = $hash->{NAME};
|
|
my $number = $hash->{NR};
|
|
my $npm_fhem_home = AttrVal($name,"fhem_home","/opt/fhem");
|
|
|
|
my $filename = $npm_fhem_home . "/cache/alexa-cookie/" . $number . "result.json";
|
|
my $CanDelete = 0;
|
|
my $ExistSkript = "false";
|
|
my $CookieResult;
|
|
|
|
if ($NPMLoginTyp =~ m/Refresh/) {
|
|
$ExistSkript = $number . "refresh-cookie.js = true" if (-e $npm_fhem_home . "cache/alexa-cookie/" . $number . "refresh-cookie.js");
|
|
}
|
|
else {
|
|
$ExistSkript = $number . "create-cookie.js = true" if (-e $npm_fhem_home . "cache/alexa-cookie/" . $number . "create-cookie.js");
|
|
}
|
|
|
|
if (-e $filename) {
|
|
# Informationen eintragen
|
|
open(MAILDAT, "<$filename") || die "Datei wurde nicht gefunden\n";
|
|
while(<MAILDAT>){
|
|
if (index($_, "{") != -1) {
|
|
$CookieResult = $_;
|
|
Log3 $name, 3, "[$name] [echodevice_NPMWaitForCookie] [$NPMLoginTyp] write new refreshtoken";
|
|
# Log3 $name, 3, "[$name] [echodevice_NPMWaitForCookie] [$NPMLoginTyp] $CookieResult";
|
|
readingsSingleUpdate( $hash, "amazon_refreshtoken", "vorhanden",1 );
|
|
readingsSingleUpdate( $hash, ".COOKIE", $CookieResult,1 );
|
|
readingsSingleUpdate( $hash, "COOKIE_TYPE", "NPM_Login",1 );
|
|
|
|
$hash->{helper}{".COOKIE"} = $CookieResult;
|
|
$hash->{helper}{".COOKIE"} =~ /"localCookie":".*session-id=(.*)","?/;
|
|
$hash->{helper}{".COOKIE"} = "session-id=" . $1;
|
|
$hash->{helper}{".COOKIE"} =~ /csrf=([-\w]+)[;\s]?(.*)?$/ if(defined($hash->{helper}{".COOKIE"}));
|
|
$hash->{helper}{".CSRF"} = $1 if(defined($hash->{helper}{".COOKIE"}));
|
|
|
|
# result.json & Skripte löschen
|
|
if (-e $filename) {unlink $filename;}
|
|
if (-e $npm_fhem_home . "cache/alexa-cookie/" . $number . "create-cookie.js") {unlink $npm_fhem_home . "cache/alexa-cookie/" . $number . "create-cookie.js";}
|
|
if (-e $npm_fhem_home . "cache/alexa-cookie/" . $number . "refresh-cookie.js") {unlink $npm_fhem_home . "cache/alexa-cookie/" . $number . "refresh-cookie.js";}
|
|
|
|
echodevice_setState($hash,"connected");
|
|
}
|
|
else {
|
|
readingsSingleUpdate( $hash, "amazon_refreshtoken", "wait for refreshtoken",1 );
|
|
Log3 $name, 3, "[$name] [echodevice_NPMWaitForCookie] [$NPMLoginTyp] wait for refreshtoken / refreshtoken unkown!! refreshtoken=" . $_ . " EXIST " . $ExistSkript;
|
|
InternalTimer(gettimeofday() + 1 , "echodevice_NPMWaitForCookie" , $hash, 0);
|
|
}
|
|
}
|
|
close(MAILDAT);
|
|
}
|
|
else {
|
|
Log3 $name, 4, "[$name] [echodevice_NPMWaitForCookie] [$NPMLoginTyp] wait for refreshtoken exist " . $ExistSkript ;
|
|
InternalTimer(gettimeofday() + 1 , "echodevice_NPMWaitForCookie" , $hash, 0);
|
|
}
|
|
}
|
|
|
|
sub echodevice_NPMCheckVersion ($$$) {
|
|
|
|
my ($hash,$filename,$LogBereich) = @_;
|
|
my $name = $hash->{NAME};
|
|
my $Modulversion = "unknown";
|
|
|
|
if (-e $filename) {
|
|
open(VERSION, "<$filename");
|
|
while(<VERSION>){
|
|
if ($_ =~ m/version/) {
|
|
my @Result = split(/"/,$_);
|
|
$Modulversion = @Result[3];
|
|
Log3 $name, 4, "[$name] [$LogBereich] Version alexa-cookie.js = $Modulversion";}
|
|
}
|
|
close(VERSION);
|
|
}
|
|
else {Log3 $name, 4, "[$name] [$LogBereich] Version alexa-cookie.js = unknown";}
|
|
|
|
return $Modulversion;
|
|
}
|
|
|
|
##########################
|
|
# TTS/POM
|
|
##########################
|
|
sub echodevice_AWSPython($$) {
|
|
my ($hash,$Skriptfile) = @_;
|
|
my $name = $hash->{NAME};
|
|
|
|
#Verzeichnis anlegen
|
|
my $filedir ="cache";
|
|
mkdir($filedir, 0777) unless(-d $filedir );
|
|
|
|
my $filename = $filedir ."/". $Skriptfile;
|
|
|
|
# Prüfen ob die Datei erstezt werden muss
|
|
if ($AWSPythonVersion eq ReadingsVal($hash->{IODev}->{NAME} , lc("AWS_PythonVersion"), "0") && (-e $filename)) {
|
|
Log3 "echodevice", 4, "[$name] [echodevice_AWSPython] file $filename exist";
|
|
return;
|
|
}
|
|
|
|
Log3 "echodevice", 3, "[$name] [echodevice_AWSPython] file $filename not exist or to old";
|
|
|
|
readingsBeginUpdate($hash->{IODev});
|
|
readingsBulkUpdate($hash->{IODev}, lc("AWS_PythonVersion"), $AWSPythonVersion, 1);
|
|
readingsEndUpdate($hash->{IODev},1);
|
|
|
|
#altes Skript löschen
|
|
if ((-e $filename)) {unlink $filename};
|
|
|
|
#Skript Inhalt
|
|
my $SkriptContent = "# IAM API (CreateUser) adapted to Polly service\n";
|
|
$SkriptContent .= "import sys, os, base64, datetime, hashlib, hmac, urllib\n";
|
|
$SkriptContent .= "sys.path.append('../')\n";
|
|
$SkriptContent .= "# Parameter\n";
|
|
$SkriptContent .= "MessageText = sys.argv[1]\n";
|
|
$SkriptContent .= "MessageVoice = sys.argv[2]\n";
|
|
$SkriptContent .= "access_key = sys.argv[3]\n";
|
|
$SkriptContent .= "secret_key = sys.argv[4]\n";
|
|
$SkriptContent .= "OutputFormat = sys.argv[7]\n";
|
|
$SkriptContent .= "# DEFs\n";
|
|
$SkriptContent .= "def sign(key, msg):\n";
|
|
$SkriptContent .= " return hmac.new(key, msg.encode('utf-8'), hashlib.sha256).digest()\n";
|
|
$SkriptContent .= "\n";
|
|
$SkriptContent .= "def getSignatureKey(key, dateStamp, regionName, serviceName):\n";
|
|
$SkriptContent .= " kDate = sign(('AWS4' + key).encode('utf-8'), dateStamp)\n";
|
|
$SkriptContent .= " kRegion = sign(kDate, regionName)\n";
|
|
$SkriptContent .= " kService = sign(kRegion, serviceName)\n";
|
|
$SkriptContent .= " kSigning = sign(kService, 'aws4_request')\n";
|
|
$SkriptContent .= " return kSigning\n";
|
|
$SkriptContent .= "# ************* REQUEST VALUES *************\n";
|
|
$SkriptContent .= "method = 'POST'\n";
|
|
$SkriptContent .= "service = 'polly'\n";
|
|
$SkriptContent .= "region = 'eu-west-1'\n";
|
|
$SkriptContent .= "host = service+'.'+region+'.amazonaws.com'\n";
|
|
$SkriptContent .= "api = '/v1/speech'\n";
|
|
$SkriptContent .= "endpoint = 'https://'+host+api\n";
|
|
$SkriptContent .= "content_type = 'application/json'\n";
|
|
$SkriptContent .= "# ************* REQUEST CONTENT ************\n";
|
|
$SkriptContent .= "request_parameters = '{'\n";
|
|
$SkriptContent .= "request_parameters += '" . '"' . "OutputFormat" . '"' . ": " . '"' . "' + OutputFormat + '" . '"' . ",'\n";
|
|
$SkriptContent .= "request_parameters += '" . '"' . "Text" . '"' . ": " . '"' . "' + MessageText + '" . '"' . ",'\n";
|
|
$SkriptContent .= "request_parameters += '" . '"' . "TextType" . '"' . ": " . '"' . "text" . '"' . ",'\n";
|
|
$SkriptContent .= "request_parameters += '" . '"' . "VoiceId" . '"' . ": " . '"' . "' + MessageVoice + '" . '"' . "'\n";
|
|
$SkriptContent .= "request_parameters += '}'\n";
|
|
$SkriptContent .= "# Create a date for headers and the credential string\n";
|
|
$SkriptContent .= "t = datetime.datetime.utcnow()\n";
|
|
$SkriptContent .= "amz_date = t.strftime('%Y%m%dT%H%M%SZ')\n";
|
|
$SkriptContent .= "date_stamp = t.strftime('%Y%m%d')\n";
|
|
$SkriptContent .= "# ************* TASK 1: CREATE A CANONICAL REQUEST *************\n";
|
|
$SkriptContent .= "canonical_uri = api\n";
|
|
$SkriptContent .= "canonical_querystring = ''\n";
|
|
$SkriptContent .= "canonical_headers = 'content-type:' + content_type + '\\n' + 'host:' + host + '\\n' + 'x-amz-date:' + amz_date + '\\n'\n";
|
|
$SkriptContent .= "signed_headers = 'content-type;host;x-amz-date'\n";
|
|
$SkriptContent .= "payload_hash = hashlib.sha256(request_parameters).hexdigest()\n";
|
|
$SkriptContent .= "canonical_request = method + '\\n' + canonical_uri + '\\n' + canonical_querystring + '\\n' + canonical_headers + '\\n' + signed_headers + '\\n' + payload_hash\n";
|
|
$SkriptContent .= "# ************* TASK 2: CREATE THE STRING TO SIGN*************\n";
|
|
$SkriptContent .= "algorithm = 'AWS4-HMAC-SHA256'\n";
|
|
$SkriptContent .= "credential_scope = date_stamp + '/' + region + '/' + service + '/' + 'aws4_request'\n";
|
|
$SkriptContent .= "string_to_sign = algorithm + '\\n' + amz_date + '\\n' + credential_scope + '\\n' + hashlib.sha256(canonical_request).hexdigest()\n";
|
|
$SkriptContent .= "# ************* TASK 3: CALCULATE THE SIGNATURE *************\n";
|
|
$SkriptContent .= "signing_key = getSignatureKey(secret_key, date_stamp, region, service)\n";
|
|
$SkriptContent .= "signature = hmac.new(signing_key, (string_to_sign).encode('utf-8'), hashlib.sha256).hexdigest()\n";
|
|
$SkriptContent .= "# ************* TASK 4: ADD SIGNING INFORMATION TO THE REQUEST *************\n";
|
|
$SkriptContent .= "authorization_header = algorithm + ' ' + 'Credential=' + access_key + '/' + credential_scope + ', ' + 'SignedHeaders=' + signed_headers + ', ' + 'Signature=' + signature\n";
|
|
$SkriptContent .= "# ************* TASK 5: ADD SIGNING INFORMATION TO FHEM *************\n";
|
|
$SkriptContent .= "f=open(sys.argv[5],'wb')\n";
|
|
$SkriptContent .= "f.write(amz_date)\n";
|
|
$SkriptContent .= "f.close()\n";
|
|
$SkriptContent .= "f=open(sys.argv[6],'wb')\n";
|
|
$SkriptContent .= "f.write(authorization_header)\n";
|
|
$SkriptContent .= "f.close()\n";
|
|
|
|
open(FH, ">$filename");
|
|
print FH $SkriptContent;
|
|
close(FH);
|
|
|
|
}
|
|
|
|
sub echodevice_Amazon($$$) {
|
|
my ($hash,$parameter,$type) = @_;
|
|
my $name = $hash->{NAME};
|
|
|
|
my $AWS_Access_Key = ReadingsVal($hash->{IODev}->{NAME} , lc(".AWS_Access_Key"), "none");
|
|
my $AWS_Secret_Key = ReadingsVal($hash->{IODev}->{NAME} , lc(".AWS_Secret_Key"), "none");
|
|
|
|
if ( $AWS_Access_Key eq "none" ) {
|
|
readingsSingleUpdate( $hash, "tts_error", "No AWS_Access_Key Value",1 );
|
|
return "No AWS_Access_Key Value" ;
|
|
}
|
|
if ( $AWS_Secret_Key eq "none" ){
|
|
readingsSingleUpdate( $hash, "tts_error", "No AWS_Secret_Key Value",1 );
|
|
return "No AWS_Secret_Key Value";
|
|
}
|
|
|
|
#Defaults
|
|
my $TTS_Voice = AttrVal($name,"TTS_Voice","German_Female_Marlene");
|
|
my $AWS_Format = ReadingsVal($hash->{IODev}->{NAME} , lc("AWS_OutputFormat"), "mp3");
|
|
my @VoiceName = split("_",$TTS_Voice);
|
|
|
|
#Verzeichnis anlegen
|
|
my $filedir = "cache";
|
|
mkdir($filedir, 0777) unless(-d $filedir );
|
|
|
|
#Temp Dateien
|
|
my $AWS_File_AMZDate = $filedir . "/amzdate";
|
|
my $AWS_File_Header = $filedir . "/header";
|
|
|
|
if ((-e "$AWS_File_AMZDate")) {unlink "$AWS_File_AMZDate"}
|
|
if ((-e "$AWS_File_Header")) {unlink "$AWS_File_Header"}
|
|
|
|
# Länge der Nachricht prüfen. Bei kleiner 3 wird noch ein " ," angehängt!
|
|
$parameter .= " ," if (length($parameter) < 3) ;
|
|
|
|
# Python Skript ausführen
|
|
echodevice_AWSPython($hash,"pollyspeech.py");
|
|
my $ret = system('python ' . $filedir . '/pollyspeech.py "' . $parameter .'" ' . @VoiceName[2] .' '. echodevice_decrypt($AWS_Access_Key) . " " . echodevice_decrypt($AWS_Secret_Key) . " " . $AWS_File_AMZDate . " " . $AWS_File_Header . " " . $AWS_Format);
|
|
|
|
# Infos auswerten
|
|
my $AWSDate;
|
|
open FILE, $AWS_File_AMZDate or do {
|
|
Log3 $name, 3, "[$name] [echodevice_Amazon] Could not read from $AWS_File_AMZDate";
|
|
readingsSingleUpdate( $hash, "tts_error", "Could not read from $AWS_File_AMZDate",1 );
|
|
return;
|
|
};
|
|
chomp(my $AWSDate = <FILE>);
|
|
close FILE;
|
|
|
|
my $AWSHeader;
|
|
open FILE, $AWS_File_Header or do {
|
|
Log3 $name, 3, "[$name] [echodevice_Amazon] Could not read from $AWS_File_Header";
|
|
readingsSingleUpdate( $hash, "tts_error", "Could not read from $AWS_File_Header",1 );
|
|
return;
|
|
};
|
|
chomp(my $AWSHeader = <FILE>);
|
|
close FILE;
|
|
|
|
# MP3 Download starten
|
|
my $params = {
|
|
url => "https://polly.eu-west-1.amazonaws.com/v1/speech",
|
|
header => "Authorization: ".$AWSHeader."\r\nX-Amz-Date: ".$AWSDate."\r\nContent-Type: application/json",
|
|
method => "POST",
|
|
data => '{"OutputFormat": "' . $AWS_Format . '","Text": "' . $parameter .'","TextType": "text","VoiceId": "' . @VoiceName[2] . '"}',
|
|
hash => $hash,
|
|
type => $type,
|
|
callback => \&echodevice_ParseTTSMP3
|
|
};
|
|
|
|
HttpUtils_NonblockingGet($params);
|
|
|
|
}
|
|
|
|
sub echodevice_Google($$$) {
|
|
my ($hash,$parameter,$type) = @_;
|
|
my $name = $hash->{NAME};
|
|
|
|
# ersetze Sonderzeichen die Google nicht auflösen kann
|
|
my $MessageText = decode_utf8($parameter);
|
|
$MessageText =~ s/ä/ae/g;
|
|
$MessageText =~ s/ö/oe/g;
|
|
$MessageText =~ s/ü/ue/g;
|
|
$MessageText =~ s/Ä/Ae/g;
|
|
$MessageText =~ s/Ö/Oe/g;
|
|
$MessageText =~ s/Ü/Ue/g;
|
|
$MessageText =~ s/ß/ss/g;
|
|
|
|
Log3 $name, 4, "[$name] [echodevice_ParseTTSMP3] TTS Message length=" . length($MessageText) ;
|
|
|
|
if (length($MessageText) > 200) {
|
|
Log3 $name, 3, "[$name] [echodevice_ParseTTSMP3] TTS Message to long!";
|
|
readingsSingleUpdate( $hash, "tts_error", "TTS Message to long",1 );
|
|
$MessageText = substr($MessageText,0,202)
|
|
}
|
|
|
|
# MP3 Download starten
|
|
my $params = {
|
|
url => "http://translate.google.com/translate_tts?tl=de&client=tw-ob&q=" . uri_escape($MessageText),
|
|
method => "GET",
|
|
hash => $hash,
|
|
type => $type,
|
|
callback => \&echodevice_ParseTTSMP3
|
|
};
|
|
|
|
HttpUtils_NonblockingGet($params);
|
|
}
|
|
|
|
sub echodevice_AmazonVoiceMP3($) {
|
|
my ($param, $err, $data) = @_;
|
|
my $hash = $param->{hash};
|
|
my $name = $hash->{NAME};
|
|
my $type = $param->{type};
|
|
Log3 $name, 4, "[$name] [echodevice_AmazonVoiceMP3] [$type] URL = " . $param->{url};
|
|
Log3 $name, 4, "[$name] [echodevice_AmazonVoiceMP3] [$type] HEADER = " . $param->{header};
|
|
Log3 $name, 4, "[$name] [echodevice_AmazonVoiceMP3] [$type] KEY = " . $param->{type};
|
|
Log3 $name, 4, "[$name] [echodevice_AmazonVoiceMP3] [$type] ERROR = " . $err if ($err);
|
|
Log3 $name, 5, "[$name] [echodevice_AmazonVoiceMP3] [$type] DATA = " . $data;
|
|
|
|
#ReadingsVal($hash->{IODev}->{NAME} , lc("TTS_Filename"), "")
|
|
my $MP3Filename = $param->{type};
|
|
|
|
Log3 $name, 4, "[$name] [echodevice_AmazonVoiceMP3] [$type] MP3File = " . $MP3Filename;
|
|
|
|
if ($data eq "") {
|
|
Log3 $name, 3, "[$name] [echodevice_AmazonVoiceMP3] [$type] no data received";
|
|
readingsSingleUpdate( $hash, "tts_error", "no data received",1 );
|
|
return;
|
|
}
|
|
|
|
#Verzeichnis echodevice anlegen
|
|
mkdir($FW_dir . "/echodevice", 0777) unless(-d $FW_dir . "/echodevice" );
|
|
mkdir($FW_dir . "/echodevice/VoiceRecords", 0777) unless(-d $FW_dir . "/echodevice/VoiceRecords" );
|
|
|
|
# MP3 Datei anlegen
|
|
open(FH, ">$FW_dir/echodevice/VoiceRecords/$MP3Filename");
|
|
print FH $data;
|
|
close(FH);
|
|
|
|
}
|
|
|
|
sub echodevice_ParseTTSMP3($) {
|
|
my ($param, $err, $data) = @_;
|
|
my $hash = $param->{hash};
|
|
my $name = $hash->{NAME};
|
|
my $type = $param->{type};
|
|
Log3 $name, 4, "[$name] [echodevice_ParseTTSMP3] [$type] URL = " . $param->{url};
|
|
Log3 $name, 4, "[$name] [echodevice_ParseTTSMP3] [$type] DATA = " . $param->{data};
|
|
Log3 $name, 5, "[$name] [echodevice_ParseTTSMP3] [$type] HEADER = " . $param->{header};
|
|
Log3 $name, 4, "[$name] [echodevice_ParseTTSMP3] [$type] ERROR = " . $err if ($err);
|
|
Log3 $name, 5, "[$name] [echodevice_ParseTTSMP3] [$type] DATA = " . $data;
|
|
|
|
#ReadingsVal($hash->{IODev}->{NAME} , lc("TTS_Filename"), "")
|
|
my $MP3Filename = $name . ".mp3";
|
|
my $M3UFilename = ReadingsVal($hash->{IODev}->{NAME} , lc("TTS_Filename"), "live18-hq.aac.m3u");
|
|
|
|
Log3 $name, 4, "[$name] [echodevice_ParseTTSMP3] [$type] MP3File = " . $MP3Filename;
|
|
Log3 $name, 4, "[$name] [echodevice_ParseTTSMP3] [$type] M3UFile = " . $M3UFilename;
|
|
|
|
if ($data eq "") {
|
|
Log3 $name, 3, "[$name] [echodevice_ParseTTSMP3] [$type] no data received";
|
|
readingsSingleUpdate( $hash, "tts_error", "no data received",1 );
|
|
return;
|
|
}
|
|
|
|
#Verzeichnis echodevice anlegen
|
|
mkdir($FW_dir . "/echodevice", 0777) unless(-d $FW_dir . "/echodevice" );
|
|
|
|
# MP3/M3U Datei löschen
|
|
if ((-e $FW_dir . "/echodevice/". $MP3Filename)) {unlink $FW_dir . "/echodevice/". $MP3Filename}
|
|
if ((-e $FW_dir . "/echodevice/". $M3UFilename)) {unlink $FW_dir . "/echodevice/".$M3UFilename}
|
|
|
|
# MP3 Datei anlegen
|
|
open(FH, ">$FW_dir/echodevice/$MP3Filename");
|
|
print FH $data;
|
|
close(FH);
|
|
|
|
# MP3 TTS_normalize
|
|
my $TTS_normalize_value = 200;
|
|
$TTS_normalize_value = AttrVal($hash->{IODev}->{NAME}, "TTS_normalize", 100) if (AttrVal($hash->{IODev}->{NAME}, "TTS_normalize", 100) != 100 ) ;
|
|
$TTS_normalize_value = AttrVal($name, "TTS_normalize", 100) if (AttrVal($name, "TTS_normalize", 100) != 100 ) ;
|
|
|
|
if ($TTS_normalize_value != 200 ) {
|
|
Log3 $name, 4, "[$name] [echodevice_ParseTTSMP3] [$type] MP3 dBFS = " . $TTS_normalize_value ;
|
|
system("normalize-mp3 -a " . $TTS_normalize_value . "dBFS " . $FW_dir . "/echodevice/" . $MP3Filename . " > /dev/null 2>&1");
|
|
if (!-e "/usr/bin/normalize-mp3") {Log3 $name, 3, "[$name] [echodevice_ParseTTSMP3] [$type] Missing /usr/bin/normalize-mp3";}
|
|
if (!-e "/usr/bin/mpg123") {Log3 $name, 3, "[$name] [echodevice_ParseTTSMP3] [$type] Missing /usr/bin/mpg123";}
|
|
if (!-e "/usr/bin/lame") {Log3 $name, 3, "[$name] [echodevice_ParseTTSMP3] [$type] Missing /usr/bin/lame";}
|
|
|
|
}
|
|
|
|
# M3U Datei erzeugen
|
|
open(FH, ">$FW_dir/echodevice/$M3UFilename");
|
|
print FH "http://" . ReadingsVal($hash->{IODev}->{NAME} , lc("TTS_IPAddress"), "live18-hq.aac.m3u") . "/" . $MP3Filename;
|
|
close(FH);
|
|
|
|
# Länge feststellen
|
|
my $MP3_Info = get_mp3info("$FW_dir/echodevice/$MP3Filename");
|
|
my $MP3_Time;
|
|
if ($MP3_Info && defined($MP3_Info->{SECS})) {
|
|
$MP3_Time = int($MP3_Info->{SECS}+1);
|
|
readingsSingleUpdate( $hash, "tts_lenght", $MP3_Time ,1 );
|
|
Log3 $name, 4, "[$name] [echodevice_ParseTTSMP3] [$type] MP3 len = $MP3_Time Sekunden.";
|
|
}
|
|
|
|
$hash->{helper}{lasttuneindelay} = $MP3_Time;
|
|
$hash->{helper}{lastvolume} = ReadingsVal($name , "volume", 50);
|
|
$hash->{helper}{lasttuneinid} = ReadingsVal($name , "currentTuneInID", "-");
|
|
$hash->{helper}{lasttype} = $type;
|
|
|
|
if(ReadingsVal($name , "volume", 50) < ReadingsVal($name , "volume_alarm", 50)) {
|
|
echodevice_SendMessage($hash,"pause","");
|
|
echodevice_SendCommand($hash,"volume",ReadingsVal($name , "volume_alarm", 50));
|
|
Log3 $name, 4, "[$name] [echodevice_ParseTTSMP3] [$type] set volume to " . ReadingsVal($name , "volume_alarm", 50);
|
|
}
|
|
|
|
InternalTimer(gettimeofday() + 1.5 , "echodevice_StartTTSMessage" , $hash, 0);
|
|
Log3 $name, 4, "[$name] [echodevice_ParseTTSMP3] Setze echodevice_StartTTSMessage Timer";
|
|
|
|
}
|
|
|
|
sub echodevice_PlayOwnMP3($$) {
|
|
my ($hash,$M3UContent) = @_;
|
|
my $name = $hash->{NAME};
|
|
|
|
Log3 $name, 4, "[$name] [echodevice_PlayOwnMP3] M3UContent = " . $M3UContent;
|
|
|
|
#ReadingsVal($hash->{IODev}->{NAME} , lc("TTS_Filename"), "")
|
|
my $M3UFilename = ReadingsVal($hash->{IODev}->{NAME} , lc("POM_Filename"), "stream.m3u");
|
|
|
|
Log3 $name, 4, "[$name] [echodevice_PlayOwnMP3] M3UFile= " . $M3UFilename;
|
|
|
|
if ($M3UContent eq "") {
|
|
Log3 $name, 3, "[$name] [echodevice_PlayOwnMP3] no data received";
|
|
return;
|
|
}
|
|
|
|
# M3U Datei löschen
|
|
if ((-e $FW_dir . "/echodevice/". $M3UFilename)) {unlink $FW_dir . "/echodevice/".$M3UFilename}
|
|
|
|
# Content zusammenbauen
|
|
my $M3UContentWR;
|
|
my @M3UConntentArray = split /\n+/, $M3UContent;
|
|
foreach (@M3UConntentArray) {
|
|
if (lc(substr($_,0,4)) eq 'http') {
|
|
$M3UContentWR .= $_ . "\n";
|
|
Log3 $name, 4, "[$name] [echodevice_SaveOwnMP3] " . $_;
|
|
}
|
|
}
|
|
|
|
# M3U Datei erzeugen
|
|
open(FH, ">$FW_dir/echodevice/$M3UFilename");
|
|
print FH $M3UContentWR;
|
|
close(FH);
|
|
|
|
echodevice_SendCommand($hash,"tunein",ReadingsVal($hash->{IODev}->{NAME} , lc("POM_TuneIn"), "s167655"));
|
|
}
|
|
|
|
sub echodevice_SaveOwnPlaylist($$) {
|
|
my ($hash,$M3UContent) = @_;
|
|
my $name = $hash->{NAME};
|
|
my $M3UFilename;
|
|
my $M3UContentWR;
|
|
|
|
Log3 $name, 4, "[$name] [echodevice_SaveOwnMP3] M3UContent = " . $M3UContent;
|
|
Log3 $name, 4, "[$name] [echodevice_SaveOwnMP3] M3UFile = " . $M3UFilename;
|
|
|
|
if ($M3UContent eq "") {
|
|
Log3 $name, 3, "[$name] [echodevice_SaveOwnMP3] no content received";
|
|
return;
|
|
}
|
|
|
|
# Playlist Name auslesen
|
|
my @M3UConntentArray = split /\n+/, $M3UContent;
|
|
$M3UFilename = @M3UConntentArray[0];
|
|
|
|
# Div. Zeichen ersetzen
|
|
$M3UFilename =~ s/\s+/_/g;
|
|
$M3UFilename =~ s/\W/_/g;
|
|
$M3UFilename .= ".m3u";
|
|
|
|
Log3 $name, 4, "[$name] [echodevice_SaveOwnMP3] M3UFile = " . $M3UFilename;
|
|
|
|
# Content zusammenbauen
|
|
foreach (@M3UConntentArray) {
|
|
if (lc(substr($_,0,4)) eq 'http') {
|
|
$M3UContentWR .= $_ . "\n";
|
|
Log3 $name, 4, "[$name] [echodevice_SaveOwnMP3] " . $_;
|
|
}
|
|
}
|
|
|
|
#Verzeichnis echodevice anlegen
|
|
mkdir($FW_dir . "/echodevice", 0777) unless(-d $FW_dir . "/echodevice" );
|
|
|
|
#Verzeichnis playlists anlegen
|
|
mkdir($FW_dir . "/echodevice/playlists", 0755) unless(-d $FW_dir . "/echodevice/playlists" );
|
|
|
|
# M3U Datei löschen
|
|
if ((-e $FW_dir . "/echodevice/playlists/". $M3UFilename)) {unlink $FW_dir . "/echodevice/playlists/".$M3UFilename}
|
|
|
|
# M3U Datei erzeugen
|
|
open(FH, ">$FW_dir/echodevice/playlists/$M3UFilename");
|
|
print FH $M3UContentWR;
|
|
close(FH);
|
|
|
|
}
|
|
|
|
sub echodevice_GetOwnPlaylist($) {
|
|
my ($hash) = @_;
|
|
my $name = $hash->{NAME};
|
|
|
|
# startownplaylist
|
|
if (-d $FW_dir . "/echodevice/playlists") {
|
|
|
|
my $M3UFiles;
|
|
|
|
opendir(DH, $FW_dir . "/echodevice/playlists");
|
|
my @files = readdir(DH);
|
|
closedir(DH);
|
|
|
|
foreach my $file (@files){
|
|
# skip . and ..
|
|
next if($file =~ /^\.$/);
|
|
next if($file =~ /^\.\.$/);
|
|
Log3 $name, 5, "[$name] [echodevice_GetOwnPlaylist] found filename = $file";
|
|
if ($M3UFiles eq "") {
|
|
$M3UFiles = $file;
|
|
}
|
|
else {
|
|
$M3UFiles .= ",".$file;
|
|
}
|
|
}
|
|
Log3 $name, 5, "[$name] [echodevice_GetOwnPlaylist] return = " . "playownplaylist:" . $M3UFiles ." ";
|
|
if ($M3UFiles ne "") {
|
|
return "playownplaylist:" . $M3UFiles ." " . "deleteownplaylist:" . $M3UFiles ." ";
|
|
}
|
|
else {
|
|
return ;
|
|
}
|
|
}
|
|
|
|
else {
|
|
return;
|
|
}
|
|
|
|
}
|
|
|
|
sub echodevice_StartLastMedia($) {
|
|
my ($hash) = @_;
|
|
my $name = $hash->{NAME};
|
|
my $type = $hash->{helper}{lasttype};
|
|
|
|
if($hash->{helper}{lastvolume} < ReadingsVal($name , "volume_alarm", 50)) {
|
|
echodevice_SendCommand($hash,"volume",$hash->{helper}{lastvolume});
|
|
Log3 $name, 4, "[$name] [echodevice_StartLastMedia] [$type] set volume to " . $hash->{helper}{lastvolume};
|
|
}
|
|
|
|
if ($hash->{helper}{lasttuneinid} ne "-" && $hash->{helper}{lasttuneinid} ne "s237481" && $hash->{helper}{lasttuneinid} ne "s204188") {
|
|
echodevice_SendCommand($hash,"tunein",$hash->{helper}{lasttuneinid}) ;
|
|
Log3 $name, 4, "[$name] [echodevice_StartLastMedia] [$type] starte TuneIN ID " . $hash->{helper}{lasttuneinid};
|
|
}
|
|
|
|
# Settings erneut einlesen
|
|
InternalTimer(gettimeofday() + 5, "echodevice_GetSettings", $hash, 0);
|
|
|
|
}
|
|
|
|
sub echodevice_StartTTSMessage($) {
|
|
my ($hash) = @_;
|
|
my $name = $hash->{NAME};
|
|
|
|
# TTS starten
|
|
echodevice_SendCommand($hash,"ttstunein",ReadingsVal($hash->{IODev}->{NAME} , lc("TTS_TuneIn"), "s237481"));
|
|
}
|
|
|
|
1;
|
|
|
|
=pod
|
|
=item device
|
|
=item summary Amazon Echo remote control
|
|
=item summary_DE Amazon Echo remote control
|
|
=begin html
|
|
|
|
<a name="echodevice"></a>
|
|
<h3>echodevice</h3>
|
|
<ul>
|
|
Basic remote control for Amazon Echo devices. You can find the complete documentation here.
|
|
<br/><br/><a href="https://mwinkler.jimdo.com/smarthome/eigene-module/echodevice/" target="_blank"><b><font size=4 color="blue">https://mwinkler.jimdo.com/smarthome/eigene-module/echodevice/</font></b></a>
|
|
|
|
<br/><br/>
|
|
<b>Define</b>
|
|
<ul>
|
|
<code>define <name> echodevice <DeviceID> [DeviceType]</code>
|
|
<br>
|
|
Example: <code>define <Name> echodevice <Amazon account> <Amazon Kennwort></code>
|
|
<br>
|
|
Example: <code>define <Name> echodevice </code>
|
|
</ul>
|
|
<br>
|
|
<b>Set</b>
|
|
<ul>
|
|
<li><code>...</code>
|
|
<br>
|
|
...
|
|
</li><br>
|
|
</ul>
|
|
<b>Get</b>
|
|
<ul>
|
|
<li><code>settings</code>
|
|
<br>
|
|
Manually reload setings (dnd, bluetooth, wakeword)
|
|
</li><br>
|
|
<li><code>devices</code>
|
|
<br>
|
|
Displays a list of Amazon devices connected to your account
|
|
</li>
|
|
</ul>
|
|
<br>
|
|
<b>Readings</b>
|
|
<ul>
|
|
<li><code>...</code>
|
|
<br>
|
|
...
|
|
</li><br>
|
|
</ul>
|
|
<br>
|
|
<b>Attributes</b>
|
|
<ul>
|
|
<li><code>interval</code>
|
|
<br>
|
|
Poll interval in seconds (300)
|
|
</li><br>
|
|
<li><code>cookie</code>
|
|
<br>
|
|
Amazon access cookie, has to be entered for the module to work
|
|
</li><br>
|
|
<li><code>server</code>
|
|
<br>
|
|
Amazon server used for controlling the Echo
|
|
</li><br>
|
|
</ul>
|
|
</ul>
|
|
|
|
=end html
|
|
|
|
=begin html_DE
|
|
|
|
<a name="echodevice"></a>
|
|
<h3>echodevice</h3>
|
|
<ul>
|
|
Basic remote control fuer Amazon Echo devices. Die komplette Dokumentation findet Ihr hier.
|
|
<br/><br/><a href="https://mwinkler.jimdo.com/smarthome/eigene-module/echodevice/" target="_blank"><b><font size=4 color="blue">https://mwinkler.jimdo.com/smarthome/eigene-module/echodevice/</font></b></a>
|
|
|
|
<br/><br/>
|
|
<b>Define</b>
|
|
<ul>
|
|
<code>define <name> echodevice <DeviceID> [DeviceType]</code>
|
|
<br>
|
|
Example: <code>define <Name> echodevice <Amazon account> <Amazon Kennwort></code>
|
|
<br>
|
|
Example: <code>define <Name> echodevice </code>
|
|
</ul>
|
|
<br>
|
|
<b>Set</b>
|
|
<ul>
|
|
<li><code>...</code>
|
|
<br>
|
|
...
|
|
</li><br>
|
|
</ul>
|
|
<b>Get</b>
|
|
<ul>
|
|
<li><code>settings</code>
|
|
<br>
|
|
Manually reload setings (dnd, bluetooth, wakeword)
|
|
</li><br>
|
|
<li><code>devices</code>
|
|
<br>
|
|
Displays a list of Amazon devices connected to your account
|
|
</li>
|
|
</ul>
|
|
<br>
|
|
<b>Readings</b>
|
|
<ul>
|
|
<li><code>...</code>
|
|
<br>
|
|
...
|
|
</li><br>
|
|
</ul>
|
|
<br>
|
|
<b>Attributes</b>
|
|
<ul>
|
|
<li><code>interval</code>
|
|
<br>
|
|
Poll interval in seconds (300)
|
|
</li><br>
|
|
<li><code>cookie</code>
|
|
<br>
|
|
Amazon access cookie, has to be entered for the module to work
|
|
</li><br>
|
|
<li><code>server</code>
|
|
<br>
|
|
Amazon server used for controlling the Echo
|
|
</li><br>
|
|
</ul>
|
|
</ul>
|
|
|
|
=end html_DE
|
|
|
|
=cut |