Squeezebox Audio Alert Script

I am using Let’s Encrypt, but I configured it outside of Home Assistant… I don’t have base_url, ssl_certificate or ssl_key defined under the http section in the configuration.yaml file. See below for my TTS config. You may have to edit the permissions of the tts directory, I can’t remember.

tts:

  • platform: google
    cache: true
    cache_dir: /volume1/homeassistant/tts
    time_memory: 300

Make sure you edit the line following line appropriately in both your save and restore script files:
JSONRPC=“http://user:[email protected]:9000/jsonrpc.js

Also, make sure in the LMS settings on the web interface under Advanced->Security, that password protection is enabled and have the user and pass set the same as in the JSONRPC line above. Lastly, try running the scripts from the command line directly if possible to get an idea of what is and isn’t working.

@frelev On my setup the tts would only work with HA not being https:// so to battle this condition I have my certs and everything else handled outside of HA so all I had to do was point my base URL to http inside of HA. I think this is the main problem. But since I force all traffic from the http to https I use a port outside to HA to use a http URL for the tts to work.

So if you hit my HA it will automatically force HTTPS but for URL calls from TTS it works just fine with HTTP

Hope this helps I battled this for a while also :smiley:

Spoke too soon, My restore is not working anymore. Not sure what I changed but it pauses plays the alert then powers off. But no matter the state of my player the file it creates is

0
0
0

@smazman Any thoughts of why? it always creates Off for the file?

I just did a test of the example I posted on Sept 18 and it is still working for me (tried various conditions: player off, music playing, music stopped). I would try running the scripts manually from the command line to see what might be going wrong (it will print out info about what it is doing). It should be writing 5 values to that .txt file (I only see 3 values shown in your post). If for some reason the scripts cannot get the power state of your player properly, you could modify the scripts so they ignore the power state.

Yes I was kind of confused why I only get three now before I got all of them I will investigate a little further and report back what I find. I tried deleting file.txt and letting it recreate, tried touching file.txt, tried chmod 777 file.txt. And of course I tried running direct from command line.

I don’t get the restore function of the playlist to work. The temporary playlist is made but the restore bash gives me only an empty playlist.

Edit: Found it: i changed some rights in the Playlists folder. Now its working again…

Has anyone been able to get this script to run in Hass.io on a raspberry pi 3? I am currently trying to get squeezebox_alert.sh to work (from my post 15 above). When I SSH into the pi and manually run this command it works fine (Note, I had to leave the mp3s on my synology where lms is running for this to work):
bash /config/squeezebox_alert.sh "kitchen" "00:01:02:03:04:05" "//volume1//homeassistant//mp3//beep_the_gate_is_open.mp3" 20

However, if I enter this same command under the “shell_command:” section in the configuration.yaml file, it only kind of works… it plays the alert, but doesn’t do anything after that, like restoring the playlist, volume and starting back up the previously playing song.

If I look in the LMS log I see a “malformed JSON string” when it tries to restore the volume. For debugging purposes I manually set the $prev_volume variable and this seems to get rid of that particular error… put then next curl command has the same error.

I suspect this has something to do with user permissions or something since it works when I run it from the command line via SSH. Does anybody have this working in hass.io and can recommend some suggestions? I am stuck.

Does hass.io not have things like chown and chmod? I must admit to knowing nothing about hass.io so ignore me if I’m talking rubbish :wink:

I read some threads where other people were having trouble using shell_commands in hass.io. I’m now looking into creating a hass.io add-on that calls the script.
https://home-assistant.io/developers/hassio/addon_tutorial/

1 Like

If anyone is interested, I created an squeezebox_alert addon for Hass.io. This was necessary due to shell_commands not getting executed correctly in Hass.io. This addon supports playing mp3 files stored locally on your LMS server and also playing audio generated using the TTS component. See below for instructions to set it up. Note, I have only tested this on Hass.io running on a Pi 3. Note, I used the Samba addon to create the files and sometimes had issues where a “^M” character appeared at the end of each line in the file. I used the SSH addon, edited the file using nano and pasted in the text directly to fix the issue. Reference https://home-assistant.io/developers/hassio/addon_tutorial/ for creating the add-on… it is actually very straight-forward.

  1. With Samba addon configured, open HASSIO network share. Create a new folder called “squeezebox_alert” in the addons folder. Create the following 4 files in the squeezebox_alert folder:
    Dockerfile
    config.json
    run.sh
    squeezebox_alert.sh

  2. Paste the contents below into each of the 4 files.

Dockerfile:

ARG BUILD_FROM
FROM $BUILD_FROM

# Add env
ENV LANG C.UTF-8

# Install requirements for add-on
RUN apk add --no-cache jq curl

# Copy data for add-on
COPY squeezebox_alert.sh /
RUN chmod a+x /squeezebox_alert.sh
COPY run.sh /
RUN chmod a+x /run.sh

CMD [ "/run.sh" ]

config.json (NOTE: Update json_rpc below. This can also be done in the addon Options in the web interface)

{
  "name": "Squeezebox Alert",
  "version": "1",
  "slug": "squeezebox_alert",
  "description": "Play audio alerts through LMS",
  "startup": "application",
  "boot": "auto",
  "stdin": true,
  "options": {
    "json_rpc": "http://user:[email protected]:9000/jsonrpc.js"
  },
  "schema": {
    "json_rpc": "str"
  }
}

run.sh

#!/bin/bash
set -e

CONFIG_PATH=/data/options.json

JSONRPC=$(jq --raw-output ".json_rpc" $CONFIG_PATH)
echo "JSONRPC=$JSONRPC"

while read -r input; do
  echo "input=$input"

  PLAYLIST_NAME="$(echo "$input" | jq --raw-output '.playlist_name')"
  echo "[Info] Read playlist_name: $PLAYLIST_NAME"
  
  MAC="$(echo "$input" | jq --raw-output '.mac')"
  echo "[Info] Read mac: $MAC"

  ALERT_SONG="$(echo "$input" | jq --raw-output '.alert_song')"
  echo "[Info] Read alert_song: $ALERT_SONG"

  ALERT_VOLUME="$(echo "$input" | jq --raw-output '.alert_volume')"
  echo "[Info] Read alert_volume: $ALERT_VOLUME"

  ./squeezebox_alert.sh $JSONRPC $PLAYLIST_NAME $MAC $ALERT_SONG $ALERT_VOLUME &
done

squeezebox_alert.sh

#!/bin/bash

#squeezebox_alert.sh

JSONRPC=$1
PLAYLIST_NAME=$2
MAC=$3
ALERT_SONG=$4
ALERT_VOLUME=$5
#restore_playlist=${6:-1}
restore_playlist=1
echo "restore_playlist=$restore_playlist"

#get power state
power=$(curl -X GET -H "Content-Type: application/json" \
                  -d '{"id":1,"method":"slim.request","params":["'"$MAC"'",["power","?"]]}' \
                  $JSONRPC | jq '.result._power')

prev_power=0
if [[ $power =~ .*1.* ]] ; then
  prev_power=1 
fi
echo "prev_power=$prev_power"

#get play mode
mode=$(curl -X GET -H "Content-Type: application/json" \
                 -d '{"id":1,"method":"slim.request","params":["'"$MAC"'",["mode","?"]]}' \
                 $JSONRPC | jq '.result._mode')

prev_playmode=0
if [[ $mode =~ .*play.* ]] ; then
  prev_playmode=1
fi	 
echo "prev_playmode=$prev_playmode"

noplay=1
prev_time=0
if [ $prev_playmode -eq 1 ] ; then
  noplay=0
  
  # pause currently playing song
  curl -X GET -H "Content-Type: application/json" \
       -d '{"id":1,"method":"slim.request","params":["'"$MAC"'",["pause"]]}' $JSONRPC
  echo "pause currently playing song"

  # get paused time
  prev_time=$(curl -X GET -H "Content-Type: application/json" \
                   -d '{"id":1,"method":"slim.request","params":["'"$MAC"'",["time","?"]]}' \
                   $JSONRPC | jq '.result._time')
  echo "prev_time=$prev_time"
fi

# save current playlist
curl -X GET -H "Content-Type: application/json" \
     -d '{"id":1,"method":"slim.request","params":["'"$MAC"'",["playlist","save","'"$PLAYLIST_NAME"'","silent:1"]]}' $JSONRPC
echo "save current playlist"

# GET SETTINGS TO RESTORE AFTER PLAYING ALERT SONG
#get current volume 
prev_volume=$(curl -X GET -H "Content-Type: application/json" \
                   -d '{"id":1,"method":"slim.request","params":["'"$MAC"'",["mixer","volume","?"]]}' \
                   $JSONRPC | jq '.result._volume')
echo "prev_volume=$prev_volume"

#get current repeat setting
prev_repeat=$(curl -X GET -H "Content-Type: application/json" \
                   -d '{"id":1,"method":"slim.request","params":["'"$MAC"'",["playlist","repeat","?"]]}' \
                   $JSONRPC | jq '.result._repeat')
echo "prev_repeat=$prev_repeat"

# SET SETTINGS FOR ALERT SONG
#set ALERT_VOLUME to command argument value
curl -X GET -H "Content-Type: application/json" \
     -d '{"id":1,"method":"slim.request","params":["'"$MAC"'",["mixer","volume",'$ALERT_VOLUME']]}' $JSONRPC
echo "set ALERT_VOLUME"

#set repeat setting to 0
curl -X GET -H "Content-Type: application/json" \
     -d '{"id":1,"method":"slim.request","params":["'"$MAC"'",["playlist","repeat",0]]}' $JSONRPC
echo "set repeat_setting to 0"

# if ALERT_SONG is null, wait a second for song to start playing externally
if [ $ALERT_SONG = "null" ] ; then
  echo "waiting for external song to start playing"
  cur_mode="pause"
  while [[ $cur_mode != *play* ]]; do
    cur_mode=$(curl -X GET -H "Content-Type: application/json" \
                -d '{"id":1,"method":"slim.request","params":["'"$MAC"'",["mode","?"]]}' \
                $JSONRPC | jq '.result._mode')
 
    sleep 0.2
  done

else
  #play alert song (this will clear current playlist)
  curl -X GET -H "Content-Type: application/json" \
       -d '{"id":1,"method":"slim.request","params":["'"$MAC"'",["playlist","play","'"$ALERT_SONG"'"]]}' $JSONRPC
  echo "play alert song"
fi

# WAIT FOR ALERT SONG TO STOP PLAYING
echo "wait for alert song to stop playing"
cur_mode="play"
while [[ $cur_mode =~ .*play.* ]]; do
  sleep 0.2
  cur_mode=$(curl -X GET -H "Content-Type: application/json" \
              -d '{"id":1,"method":"slim.request","params":["'"$MAC"'",["mode","?"]]}' \
              $JSONRPC | jq '.result._mode')
done

echo "alert song stopped playing"

# RESTORE PREVIOUS SETTINGS
#restore prev_volume setting
curl -X GET -H "Content-Type: application/json" \
     -d '{"id":1,"method":"slim.request","params":["'"$MAC"'",["mixer","volume",'"$prev_volume"']]}' $JSONRPC
echo "restore prev_volume setting"

#restore prev_repeat setting
curl -X GET -H "Content-Type: application/json" \
     -d '{"id":1,"method":"slim.request","params":["'"$MAC"'",["playlist","repeat",'"$prev_repeat"']]}' $JSONRPC
echo "restore prev_repeat setting"

# resume previous playlist (always resume if previously playing)
if [ $prev_playmode -eq 1 ] || [ $restore_playlist -eq 1 ] ; then
  curl -X GET -H "Content-Type: application/json" \
       -d '{"id":1,"method":"slim.request","params":["'"$MAC"'",["playlist","resume","'"$PLAYLIST_NAME"'","noplay:'$noplay'"]]}' $JSONRPC
  echo "resume previous playlist"
fi

# RESUME PREVIOUSLY PLAYING MUSIC
if [ $prev_playmode -eq 1 ] ; then
  #skip ahead in song to prev_time
  curl -X GET -H "Content-Type: application/json" \
       -d '{"id":1,"method":"slim.request","params":["'"$MAC"'",["time",'"$prev_time"']]}' $JSONRPC
  echo "skip ahead in song to prev_time"
fi

#restore prev_power setting
if [ $prev_power -eq 0 ] ; then
  echo "prev_power setting was off, power off"
  curl -X GET -H "Content-Type: application/json" \
       -d '{"id":1,"method":"slim.request","params":["'"$MAC"'",["power",0]]}' $JSONRPC
fi
  1. Perform the necessary steps to install the squeezebox_alert addon in Hass.io. See here:
    https://home-assistant.io/developers/hassio/addon_tutorial/#step-2-installing-and-testing-your-add-on

  2. Add the necessary lines to your configuration.yaml file (not complete).
    example uses in configuration.yaml (1.8 KB)

1 Like

Thanks for doing this. I’ll test it out when I have some time this week. It’s always bugged me that the TTS platform doesn’t natively work for Squeezebox in Hass.

Actually, I believe TTS does work “natively” with squeezebox, but my script allows restoring of the current playlist, and resuming currently playing music… which the TTS component will not do on its own. If you don’t care about that then you just need to add the appropriate entries to your configuration.yaml file:

media_player:
  - platform: squeezebox
    host: 192.168.1.100
    port: 9000
    username: user 
    password: pass

tts:
  - platform: google
    cache: true
    cache_dir: /config/tts
    time_memory: 300

And add this to an automation (where media_player.kitchen is a squeezebox player):

  - service: tts.google_say
    entity_id: media_player.kitchen
    data:
       message: 'This is a test.'

I never got it to work. The TTS mp3 file would be created and sent to LMS but no audio ever came out to the speakers. I believe the last time I was looking into it, the issue seemed to be a conflict with the Let’s Encrypt SSL. I believe it did work before I implemented the SSL. Do you use the Let’s Encrypt certificate?

Oh OK. I have Let’s Encrypt running on another device (synology) which uses a reverse proxy to pass traffic to the Pi 3 which is running Home Asssistant, so I don’t need to touch the SSL params in the configuration.yaml file for Home Assistant. I’m not currently using SSL on the LMS connection though since it was causing things to act very strange.

Just thought I would chime in here - the script works fine for me but only on hardware players - on squeezelite I get the same issue - it won’t play the TTS audio.

The only issue I have is that when a playlist is set to random, resuming doesn’t play the next song from the original playlist as it must get reshuffled - pretty minor.

Thanks for the script :slight_smile:

Thank you for this. It was so simple to set up! Is your instance successfully restoring the power to an off state?
Mine will turn on and play the alert, but it will always restore the last playlist and begin playing music even if it was previously off before the script started.

Everything else is working great!

Are you running the addon or the script? If the script, which one?

Sorry, I should’ve been clearer. I’m running the addon with Hass.io

TTS or local mp3? If TTS, you might have to adjust the delay in the yaml file (see my example yaml file above) or maybe the sleep value in the script… Using a delay is kind of a hack to allow the addon to work with TTS (as well as a local mp3). It should really be cleaned up to use the HA API. I really only use the local mp3 method.

Also try SSHing in and viewing each of the addon files to make sure there aren’t any stray control chars at the end of any of the lines. (Or just paste contents again.)

Lastly, go to the squeezebox_alert addon config page in the hass webui and refresh the log. Make sure it is properly reading the state of your player before the alert song is played… doesn’t sound like it is.

@smazman Hey thanks for the addon, Awesome!

But i’m having an issue got it installed and running no problem but the audio stops for the tts and speaks and then doesn’t restore. I do not see the *.txt file. Where is it created under the /config? or somewhere else?

here is the last bit in the logs from the addon I changed my mac address to 00:00:00:00:00 just for the post :slight_smile:

alert song stopped playing
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed

  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
100   186  100    99  100    87     99     87  0:00:01 --:--:--  0:00:01  181k
{"params":["00:00:00:00:00",["mixer","volume","87"]],"method":"slim.request","id":1,"result":{}}restore prev_volume setting
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed

  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
100   190  100   101  100    89    101     89  0:00:01 --:--:--  0:00:01  185k
{"params":["00:00:00:00:00",["playlist","repeat","0"]],"method":"slim.request","id":1,"result":{}}restore prev_repeat setting
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed

  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
100   222  100   117  100   105    117    105  0:00:01 --:--:--  0:00:01  1620
{"method":"slim.request","params":["00:00:00:00:00",["playlist","resume","office","noplay:0"]],"result":{},"id":1}resume previous playlist
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed

  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
100   190  100   102  100    88    102     88  0:00:01 --:--:--  0:00:01  185k
{"params":["00:00:00:00:00",["time","104.44559410286"]],"method":"slim.request","id":1,"result":{}}skip ahead in song to prev_time
input={"playlist_name": "office", "mac": "00:00:00:00:00", "alert_volume": 65}