diff --git a/README.md b/README.md index 8fd43e9..33046e3 100644 --- a/README.md +++ b/README.md @@ -4,15 +4,17 @@ control Amazon Alexa from command Line ``` alexa-remote-control [-d |ALL] -e > | - -b [list|<\"AA:BB:CC:DD:EE:FF\">] | -q | -r <\"station name\"|stationid> | - -s | -t | -u | -v | -w | - -i | -p | -a | -P | -S | -m [device_1 .. device_X] | - -lastalexa | -l | -h - -e : run command - -q : query queue + -b [list|<"AA:BB:CC:DD:EE:FF">] | -q | -r <"station name"|stationid> | + -s | -t | -u | -v | + -w | -i | -p | -P | -S | -a | -l | -h | + -m [device_1 .. device_X] | -lastalexa + + -e : run command, additional SEQUENCECMDs: + weather,traffic,flashbriefing,goodmorning,singasong,tellstory,speak:'' -b : connect/disconnect/list bluetooth device + -q : query queue -r : play tunein radio - -s : play library track + -s : play library track/library album -t : play Prime playlist -u : play Prime station -v : play Prime historical queue diff --git a/alexa_remote_control.sh b/alexa_remote_control.sh index 25f94c2..f70e138 100644 --- a/alexa_remote_control.sh +++ b/alexa_remote_control.sh @@ -28,6 +28,12 @@ # 2018-02-27: v0.9 unsuccessful logins will now give a short info how to debug the login # 2018-03-09: v0.9a workaround for login problem, force curl to use http1.1 # 2018-05-17: v0.9b update browser string and accept language +# 2018-05-23: v0.9c update accept language (again) +# 2018-06-12: v0.10 introducing TTS and more +# (thanks to Michael Geramb and his openHAB2 Amazon Echo Control binding) +# https://github.com/openhab/openhab2-addons/tree/master/addons/binding/org.openhab.binding.amazonechocontrol +# (thanks to Ralf Otto for implementing this feature in this script) +# 2018-06-13: v0.10a added album play of imported library # ### # @@ -41,7 +47,7 @@ EMAIL='amazon_account@email.address' PASSWORD='Very_Secret_Amazon_Account_Password' -LANGUAGE="de,en-US" +LANGUAGE="de-DE" #LANGUAGE="en-US" AMAZON='amazon.de' @@ -75,9 +81,13 @@ GUIVERSION=0 LIST="" LOGOFF="" COMMAND="" +TTS="" +SEQUENCECMD="" STATIONID="" QUEUE="" SONG="" +ALBUM="" +ARTIST="" TYPE="" ASIN="" SEEDID="" @@ -90,13 +100,17 @@ LASTALEXA="" usage() { - echo "$0 [-d |ALL] -e > | -b [list|<\"AA:BB:CC:DD:EE:FF\">] | -q | -r <\"station name\"|stationid> | -s | -t |" - echo " -u | -v | -w | -i | -p | -P | -S | -a | -m [device_1 .. device_X] | -lastalexa | -l | -h" - echo " -e : run command" + echo "$0 [-d |ALL] -e > |" + echo " -b [list|<\"AA:BB:CC:DD:EE:FF\">] | -q | -r <\"station name\"|stationid> |" + echo " -s | -t | -u | -v | -w |" + echo " -i | -p | -P | -S | -a | -m [device_1 .. device_X] | -lastalexa | -l | -h" + echo + echo " -e : run command, additional SEQUENCECMDs:" + echo " weather,traffic,flashbriefing,goodmorning,singasong,tellstory,speak:''" echo " -b : connect/disconnect/list bluetooth device" echo " -q : query queue" echo " -r : play tunein radio" - echo " -s : play library track" + echo " -s : play library track/library album" echo " -t : play Prime playlist" echo " -u : play Prime station" echo " -v : play Prime historical queue" @@ -179,6 +193,11 @@ while [ "$#" -gt 0 ] ; do fi SONG=$2 shift + if [ "${2#-}" = "${2}" -a -n "$2" ] ; then + ALBUM=$2 + ARTIST=$SONG + shift + fi ;; -t) if [ "${2#-}" != "${2}" -o -z "$2" ] ; then @@ -286,6 +305,29 @@ case "$COMMAND" in exit 1 fi ;; + speak:*) + SEQUENCECMD='Alexa.Speak' + TTS=$(echo ${COMMAND##*:} | sed -r 's/[^-a-zA-Z0-9_,?!]//g') + TTS=",\\\"textToSpeak\\\":\\\"${TTS}\\\"" + ;; + weather) + SEQUENCECMD='Alexa.Weather.Play' + ;; + traffic) + SEQUENCECMD='Alexa.Traffic.Play' + ;; + flashbriefing) + SEQUENCECMD='Alexa.FlashBriefing.Play' + ;; + goodmorning) + SEQUENCECMD='Alexa.GoodMorning.Play' + ;; + singasong) + SEQUENCECMD='Alexa.SingASong.Play' + ;; + tellstory) + SEQUENCECMD='Alexa.TellStory.Play' + ;; "") ;; *) @@ -421,13 +463,25 @@ list_devices() # # execute command +# (SequenceCommands by Michael Geramb and Ralf Otto) # run_cmd() { -${CURL} ${OPTS} -s -b ${COOKIE} -A "${BROWSER}" -H "DNT: 1" -H "Connection: keep-alive" -L\ - -H "Content-Type: application/json; charset=UTF-8" -H "Referer: https://alexa.${AMAZON}/spa/index.html" -H "Origin: https://alexa.${AMAZON}"\ - -H "csrf: $(awk "\$0 ~/.${AMAZON}.*csrf[ \\s\\t]+/ {print \$7}" ${COOKIE})" -X POST -d ${COMMAND}\ - "https://${ALEXA}/api/np/command?deviceSerialNumber=${DEVICESERIALNUMBER}&deviceType=${DEVICETYPE}" +if [ -n "${SEQUENCECMD}" ] + then + echo "Sequence command: ${SEQUENCECMD}" + COMMAND="{\"behaviorId\":\"PREVIEW\",\"sequenceJson\":\"{\\\"@type\\\":\\\"com.amazon.alexa.behaviors.model.Sequence\\\",\\\"startNode\\\":{\\\"@type\\\":\\\"com.amazon.alexa.behaviors.model.OpaquePayloadOperationNode\\\",\\\"type\\\":\\\"${SEQUENCECMD}\\\",\\\"operationPayload\\\":{\\\"deviceType\\\":\\\"${DEVICETYPE}\\\",\\\"deviceSerialNumber\\\":\\\"${DEVICESERIALNUMBER}\\\",\\\"locale\\\":\\\"${LANGUAGE}\\\",\\\"customerId\\\":\\\"${MEDIAOWNERCUSTOMERID}\\\"${TTS}}}}\",\"status\":\"ENABLED\"}" + + ${CURL} ${OPTS} -s -b ${COOKIE} -A "${BROWSER}" -H "DNT: 1" -H "Connection: keep-alive" -L\ + -H "Content-Type: application/json; charset=UTF-8" -H "Referer: https://alexa.${AMAZON}/spa/index.html" -H "Origin: https://alexa.${AMAZON}"\ + -H "csrf: $(awk "\$0 ~/.${AMAZON}.*csrf[ \\s\\t]+/ {print \$7}" ${COOKIE})" -X POST -d ${COMMAND}\ + "https://${ALEXA}/api/behaviors/preview" +else + ${CURL} ${OPTS} -s -b ${COOKIE} -A "${BROWSER}" -H "DNT: 1" -H "Connection: keep-alive" -L\ + -H "Content-Type: application/json; charset=UTF-8" -H "Referer: https://alexa.${AMAZON}/spa/index.html" -H "Origin: https://alexa.${AMAZON}"\ + -H "csrf: $(awk "\$0 ~/.${AMAZON}.*csrf[ \\s\\t]+/ {print \$7}" ${COOKIE})" -X POST -d ${COMMAND}\ + "https://${ALEXA}/api/np/command?deviceSerialNumber=${DEVICESERIALNUMBER}&deviceType=${DEVICETYPE}" +fi } # @@ -446,9 +500,15 @@ ${CURL} ${OPTS} -s -b ${COOKIE} -A "${BROWSER}" -H "DNT: 1" -H "Connection: keep # play_song() { + if [ -z "${ALBUM}" ] ; then + JSON="{\"trackId\":\"${SONG}\",\"playQueuePrime\":true}" + else + JSON="{\"albumArtistName\":\"${ARTIST}\",\"albumName\":\"${ALBUM}\"}" + fi + ${CURL} ${OPTS} -s -b ${COOKIE} -A "${BROWSER}" -H "DNT: 1" -H "Connection: keep-alive" -L\ -H "Content-Type: application/json; charset=UTF-8" -H "Referer: https://alexa.${AMAZON}/spa/index.html" -H "Origin: https://alexa.${AMAZON}"\ - -H "csrf: $(awk "\$0 ~/.${AMAZON}.*csrf[ \\s\\t]+/ {print \$7}" ${COOKIE})" -X POST -d "{\"trackId\":\"${SONG}\",\"playQueuePrime\":true}"\ + -H "csrf: $(awk "\$0 ~/.${AMAZON}.*csrf[ \\s\\t]+/ {print \$7}" ${COOKIE})" -X POST -d "${JSON}"\ "https://${ALEXA}/api/cloudplayer/queue-and-play?deviceSerialNumber=${DEVICESERIALNUMBER}&deviceType=${DEVICETYPE}&mediaOwnerCustomerId=${MEDIAOWNERCUSTOMERID}&shuffle=false" } @@ -707,7 +767,7 @@ if [ -n "$COMMAND" -o -n "$QUEUE" ] ; then for DEVICE in $(jq -r '.devices[] | select( .deviceFamily == "ECHO" or .deviceFamily == "KNIGHT" or .deviceFamily == "ROOK" or .deviceFamily == "WHA") | .accountName' ${DEVLIST} | sed -r 's/ /%20/g') ; do set_var if [ -n "$COMMAND" ] ; then - echo "sending cmd:${COMMAND} to dev:${DEVICE} type:${DEVICETYPE} serial:${DEVICESERIALNUMBER}" + echo "sending cmd:${COMMAND} to dev:${DEVICE} type:${DEVICETYPE} serial:${DEVICESERIALNUMBER} customerid:${MEDIAOWNERCUSTOMERID}" run_cmd else echo "queue info for dev:${DEVICE} type:${DEVICETYPE} serial:${DEVICESERIALNUMBER}" @@ -717,7 +777,7 @@ if [ -n "$COMMAND" -o -n "$QUEUE" ] ; then else set_var if [ -n "$COMMAND" ] ; then - echo "sending cmd:${COMMAND} to dev:${DEVICE} type:${DEVICETYPE} serial:${DEVICESERIALNUMBER}" + echo "sending cmd:${COMMAND} to dev:${DEVICE} type:${DEVICETYPE} serial:${DEVICESERIALNUMBER} customerid:${MEDIAOWNERCUSTOMERID}" run_cmd else echo "queue info for dev:${DEVICE} type:${DEVICETYPE} serial:${DEVICESERIALNUMBER}" diff --git a/alexa_remote_control_plain.sh b/alexa_remote_control_plain.sh index 2ef3df0..499242d 100644 --- a/alexa_remote_control_plain.sh +++ b/alexa_remote_control_plain.sh @@ -3,7 +3,7 @@ # Amazon Alexa Remote Control (PLAIN shell) # alex(at)loetzimmer.de # -# 2018-05-17: v0.9b (for updates see http://blog.loetzimmer.de/2017/10/amazon-alexa-hort-auf-die-shell-echo.html) +# 2018-06-13: v0.10a (for updates see http://blog.loetzimmer.de/2017/10/amazon-alexa-hort-auf-die-shell-echo.html) # ### # @@ -16,7 +16,7 @@ EMAIL='amazon_account@email.address' PASSWORD='Very_Secret_Amazon_Account_Password' -LANGUAGE="de,en-US" +LANGUAGE="de-DE" #LANGUAGE="en-US" AMAZON='amazon.de' @@ -51,9 +51,13 @@ GUIVERSION=0 LIST="" LOGOFF="" COMMAND="" +TTS="" +SEQUENCECMD="" STATIONID="" QUEUE="" SONG="" +ALBUM="" +ARTIST="" ASIN="" SEEDID="" HIST="" @@ -65,13 +69,17 @@ LASTALEXA="" usage() { - echo "$0 [-d ] -e > | -b [list|<\"AA:BB:CC:DD:EE:FF\">] | -q | -r | -s | -t |" - echo " -u | -v | -w | -a | -m [device_1 .. device_X] | -lastalexa | -l | -h" - echo " -e : run command" + echo "$0 [-d |ALL] -e > |" + echo " -b [list|<\"AA:BB:CC:DD:EE:FF\">] | -q | -r <\"station name\"|stationid> |" + echo " -s | -t | -u | -v | -w |" + echo " -a | -m [device_1 .. device_X] | -lastalexa | -l | -h" + echo + echo " -e : run command, additional SEQUENCECMDs:" + echo " weather,traffic,flashbriefing,goodmorning,singasong,tellstory,speak:''" echo " -q : query queue" echo " -b : connect/disconnect/list bluetooth device" echo " -r : play tunein radio" - echo " -s : play library track" + echo " -s : play library track/library album" echo " -t : play Prime playlist" echo " -u : play Prime station" echo " -v : play Prime historical queue" @@ -141,6 +149,11 @@ while [ "$#" -gt 0 ] ; do fi SONG=$2 shift + if [ "${2#-}" = "${2}" -a -n "$2" ] ; then + ALBUM=$2 + ARTIST=$SONG + shift + fi ;; -t) if [ "${2#-}" != "${2}" -o -z "$2" ] ; then @@ -245,6 +258,29 @@ case "$COMMAND" in exit 1 fi ;; + speak:*) + SEQUENCECMD='Alexa.Speak' + TTS=$(echo ${COMMAND##*:} | sed -r 's/[^-a-zA-Z0-9_,?!]//g') + TTS=",\\\"textToSpeak\\\":\\\"${TTS}\\\"" + ;; + weather) + SEQUENCECMD='Alexa.Weather.Play' + ;; + traffic) + SEQUENCECMD='Alexa.Traffic.Play' + ;; + flashbriefing) + SEQUENCECMD='Alexa.FlashBriefing.Play' + ;; + goodmorning) + SEQUENCECMD='Alexa.GoodMorning.Play' + ;; + singasong) + SEQUENCECMD='Alexa.SingASong.Play' + ;; + tellstory) + SEQUENCECMD='Alexa.TellStory.Play' + ;; "") ;; *) @@ -437,13 +473,25 @@ set_var() # # execute command +# (SequenceCommands by Michael Geramb and Ralf Otto) # run_cmd() { -${CURL} ${OPTS} -s -b ${COOKIE} -A "${BROWSER}" -H "DNT: 1" -H "Connection: keep-alive" -L\ - -H "Content-Type: application/json; charset=UTF-8" -H "Referer: https://alexa.${AMAZON}/spa/index.html" -H "Origin: https://alexa.${AMAZON}"\ - -H "csrf: $(awk "\$0 ~/.${AMAZON}.*csrf[ \\s\\t]+/ {print \$7}" ${COOKIE})" -X POST -d ${COMMAND}\ - "https://${ALEXA}/api/np/command?deviceSerialNumber=${DEVICESERIALNUMBER}&deviceType=${DEVICETYPE}" +if [ -n "${SEQUENCECMD}" ] + then + echo "Sequence command: ${SEQUENCECMD}" + COMMAND="{\"behaviorId\":\"PREVIEW\",\"sequenceJson\":\"{\\\"@type\\\":\\\"com.amazon.alexa.behaviors.model.Sequence\\\",\\\"startNode\\\":{\\\"@type\\\":\\\"com.amazon.alexa.behaviors.model.OpaquePayloadOperationNode\\\",\\\"type\\\":\\\"${SEQUENCECMD}\\\",\\\"operationPayload\\\":{\\\"deviceType\\\":\\\"${DEVICETYPE}\\\",\\\"deviceSerialNumber\\\":\\\"${DEVICESERIALNUMBER}\\\",\\\"locale\\\":\\\"${LANGUAGE}\\\",\\\"customerId\\\":\\\"${MEDIAOWNERCUSTOMERID}\\\"${TTS}}}}\",\"status\":\"ENABLED\"}" + + ${CURL} ${OPTS} -s -b ${COOKIE} -A "${BROWSER}" -H "DNT: 1" -H "Connection: keep-alive" -L\ + -H "Content-Type: application/json; charset=UTF-8" -H "Referer: https://alexa.${AMAZON}/spa/index.html" -H "Origin: https://alexa.${AMAZON}"\ + -H "csrf: $(awk "\$0 ~/.${AMAZON}.*csrf[ \\s\\t]+/ {print \$7}" ${COOKIE})" -X POST -d ${COMMAND}\ + "https://${ALEXA}/api/behaviors/preview" +else + ${CURL} ${OPTS} -s -b ${COOKIE} -A "${BROWSER}" -H "DNT: 1" -H "Connection: keep-alive" -L\ + -H "Content-Type: application/json; charset=UTF-8" -H "Referer: https://alexa.${AMAZON}/spa/index.html" -H "Origin: https://alexa.${AMAZON}"\ + -H "csrf: $(awk "\$0 ~/.${AMAZON}.*csrf[ \\s\\t]+/ {print \$7}" ${COOKIE})" -X POST -d ${COMMAND}\ + "https://${ALEXA}/api/np/command?deviceSerialNumber=${DEVICESERIALNUMBER}&deviceType=${DEVICETYPE}" +fi } # @@ -462,9 +510,15 @@ ${CURL} ${OPTS} -s -b ${COOKIE} -A "${BROWSER}" -H "DNT: 1" -H "Connection: keep # play_song() { + if [ -z "${ALBUM}" ] ; then + JSON="{\"trackId\":\"${SONG}\",\"playQueuePrime\":true}" + else + JSON="{\"albumArtistName\":\"${ARTIST}\",\"albumName\":\"${ALBUM}\"}" + fi + ${CURL} ${OPTS} -s -b ${COOKIE} -A "${BROWSER}" -H "DNT: 1" -H "Connection: keep-alive" -L\ -H "Content-Type: application/json; charset=UTF-8" -H "Referer: https://alexa.${AMAZON}/spa/index.html" -H "Origin: https://alexa.${AMAZON}"\ - -H "csrf: $(awk "\$0 ~/.${AMAZON}.*csrf[ \\s\\t]+/ {print \$7}" ${COOKIE})" -X POST -d "{\"trackId\":\"${SONG}\",\"playQueuePrime\":true}"\ + -H "csrf: $(awk "\$0 ~/.${AMAZON}.*csrf[ \\s\\t]+/ {print \$7}" ${COOKIE})" -X POST -d "${JSON}"\ "https://${ALEXA}/api/cloudplayer/queue-and-play?deviceSerialNumber=${DEVICESERIALNUMBER}&deviceType=${DEVICETYPE}&mediaOwnerCustomerId=${MEDIAOWNERCUSTOMERID}&shuffle=false" } @@ -658,7 +712,7 @@ fi if [ -n "$COMMAND" ] ; then set_var if [ -n "$COMMAND" ] ; then - echo "sending cmd:${COMMAND} to dev:${DEVICE} type:${DEVICETYPE} serial:${DEVICESERIALNUMBER}" + echo "sending cmd:${COMMAND} to dev:${DEVICE} type:${DEVICETYPE} serial:${DEVICESERIALNUMBER} customerid:${MEDIAOWNERCUSTOMERID}" run_cmd fi elif [ -n "$LEMUR" ] ; then