Play a random Spotify playlist on Squeezebox

This can be adapted to various media_player’s I’m sure. I’m running Logitech Media Server with the official Spotify Plugin plus the Triode protocol handler. That allows me to use Spotify URIs.

The secret sauce is that Jinja templates can return a random item from an array. I got excited when I figured that out.

The script I’m posting also makes an API call to turn on shuffle-by-song so that the playlists are shuffled. Source for that below as well.

Keep in mind that you’ll need to change the entity_id (media_player.squeezeplay for me) to match your squeezebox or other media device.

script:
  randomsqueeze:
    alias: Play random playlist on Squeeze
    sequence:
        #a bash script that turns on shuffle-by-song
      - service: shell_command.squeeze_shuffle_songs
      - service: media_player.play_media
        data: 
          #change this to match your player
          entity_id: media_player.squeezeplay
          media_content_type: PLAYLIST
        data_template:
           #add as many playlist or album IDs as you like
           media_content_id: >
            {{ ["spotify:user:netflixmusic:playlist:2X6z5kU0wMnKoar8i1RN6B", "spotify:user:ernestcline:playlist:5h6SYfQvJYAnr9S8Al4yOn", "spotify:user:stereogum:playlist:4VHDDPpx9BLScz0hMlFPqr"] | random}}
shell_command:
  squeeze_shuffle_songs: bash /home/pi/scripts/squeeze_shuffle_songs.sh

The bash script looks like this. Be sure to change the path in your shell_command to match wherever you put this (I created a scripts folder for these):

curl -X GET \
    -H "Content-Type: application/json" \
    -d '{"id":1,"method":"slim.request","params":["bc:5f:xx:xx:xx:xx",["playlist","shuffle",1]]}' \
    http://192.168.1.110:xx/jsonrpc.js

You’ll need to change that first parameter (bc:5f:xx:xx:xx:xx) to the ID of the player that you want to trigger shuffle on.

Also, I hate leaving the player in “random” mode because I typically like to use “play next” and “play last” when I’m manually building a playlist while listening. So I have this code that turns off shuffle when music stops:

automation:
  - alias: SqueezePlay stops playing
    trigger:
      - platform: state
        entity_id: media_player.squeezeplay
        to: 'off'
      - platform: state
        entity_id: media_player.squeezeplay
        to: 'idle'
    action: 
      - service: shell_command.squeeze_shuffle_off
shell_command:
  squeeze_shuffle_off: bash /home/pi/scripts/squeeze_shuffle_off.sh

squeeze_shuffle_off.sh looks really similar to squeeze_shuffle_songs.sh except for a zero in the shuffle payload:

curl -X GET \
    -H "Content-Type: application/json" \
    -d '{"id":1,"method":"slim.request","params":["bc:5f:xx:xx:xx:xx",["playlist","shuffle",0]]}' \
    http://192.168.1.x:9000/jsonrpc.js

And last but not least, I have a handy script that tells my HTPC to turn on the receiver and set the right input. The mechanics of that will vary widely depending on how your setup works, but here’s the automation to get you started:

automation:
## turn on receiver when music starts ##
  - alias: SqueezePlay begins playing
    trigger:
      - platform: state
        entity_id: media_player.squeezeplay
        to: 'playing'
        from: 'idle'
      - platform: state
        entity_id: media_player.squeezeplay
        to: 'playing'
        from: 'off'
    action: 
      # do whatever you want
8 Likes

Hey,

thank you for sharing, actually I was doing something similar in a far more complex way :blush:

I’m using your example and I’m getting this error:

TypeError: play_media() got an unexpected keyword argument 'enqueue'
16-10-15 10:37:31 homeassistant.core: BusHandler:Exception doing job
Traceback (most recent call last):
  File "/usr/src/app/homeassistant/core.py", line 865, in job_handler
    func(*args)
  File "/usr/src/app/homeassistant/core.py", line 730, in _execute_service
    service(call)
  File "/usr/src/app/homeassistant/core.py", line 586, in __call__
    self.func(call)
  File "/usr/src/app/homeassistant/components/media_player/__init__.py", line 384, in play_media_service
    player.play_media(media_type, media_id, **kwargs)
TypeError: play_media() got an unexpected keyword argument 'enqueue' 

I receive the same error both by running the script or by firing it manually from the Services section.

Any idea what’s this about??

That’s great @ih8gates, thanks for sharing.

I don’t have spotify but I’ll be adapting this for use with regular playlists. I’ve trying to work out how to do this for a while now.

Not sure what’s causing that. That looks like something happening inside of the Squeezeplayer code. Are you up-to-date with your HA install?

I’m in 0.28.2 …

What version you have?

wasn´t playmedia added quite recently for squeezebox?

Yup, my bad …

I just updated to latest verstion and works with no issue.

thank you guys! :slight_smile:

1 Like

I can’t seem to get the shuffling to work. If I put the command into putty it works but calling it from within homeassistant seemingly has no result and doesn’t throw any errors.

I have tried moving the location of the scripts, the .sh files from /home/pi/scripts/ to a folder within the raspberry pi AIO virtual environment ( /home/hass/.homeassistant/shcripts/ ).

I’ve tried changing the permissions with a chmod from putty on files and folders.

I’ve tried changing my shell commands configuration between !include_dir_merge_named, named, merge_list, list and directly in configuration.

And variations of the above - any ideas where I’m going wrong? Or even how to test if a shell command works from Hass at all?

Try creating a simple bash script that copies a file. Then trigger it from the services dev tab. Just to confirm that things are working.

In my example, you don’t need the script unless you also want to turn shuffle on/off. Playing a random music source should work without that. Maybe test that first if you’re having issues there?

Thanks @ih8gates.

It seems I can’t trigger a script at all. Perhaps something to do with permissions and the AIO being in a virtual environment. I can see another user having the same problem with it here.

The random music source has been working great. For the last two weeks I’ve been trying to build a radio from it that uses time conditions within the script to determine the set of playlists to choose from. Getting these conditions to work has been driving me nuts. I’m still trying but it looks like I’m going to have to ask for help with that one too.

FYI: I’m running the AIO on a Pi3. I haven’t had any permissions issues. I took a look and all of my scripts are owned by pi.

Thanks again - might be time for a clean install test since a simple copy script fails too. Time to order some spare SD cards.

Chances are I have broken something somewhere with my fiddling.

I bought a couple extra cards, but in practive, I’ve just been making IMG backups every once in a while. Cheaper.

Unfortunately, I’ve been doing that in theory rather than practice.

The plan was, clean install, get all basics working then image, (and incremental image each time I make major changes).
The day after I did my AIO clean install the async update came through and I’ve been fighting with it ever since.

I thought you might like to see how I adapted your script to make a radio station I turn on and off with Alexa. Here’s a simplified version of my music robot yaml.

robot_radio:
  alias: robot radio
  sequence:
    - service: script.morning_easy
    - service: script.evening_gentry
    - service: script.nicht_muzik
### Morning ###
morning_easy:
  alias: play random music in morning
  sequence:
    - condition: time
      before: '14:00:00'
      after: '06:00:01'
    - service: shell_command.squeeze_shuffle_songs
    - service: media_player.play_media
      data:
        entity_id: media_player.hoolio
        media_content_type: PLAYLIST
      data_template:
        media_content_id: >
         {{ ["PlaylistM1", "PlaylistM2", "PlaylistM3", "PlaylistM4", "PlaylistM5", "PlaylistM6", "PlaylistEM", "PlaylistM8", "PlaylistM9", "PlaylistM10"] | random}}

### Evening ###
evening_gentry:
  alias: play random music in evening
  sequence:
    - condition: time
      before: '21:00:00'
      after: '14:00:01'
    - service: shell_command.squeeze_shuffle_songs
    - service: media_player.play_media
      data:
        entity_id: media_player.hoolio
        media_content_type: PLAYLIST
      data_template:
        media_content_id: >
         {{ ["PlaylistE1", "PlaylistE2", "PlaylistE3", "PlaylistE4", "PlaylistE5", "PlaylistE6", "PlaylistE7", "PlaylistE8", "PlaylistE9", "PlaylistE10"] | random}}

### Night ###
nicht_muzik:
  alias: play random music at night
  sequence:
    - condition: time
      before: '23:59:00'
      after: '21:00:01'
    - service: shell_command.squeeze_shuffle_songs
    - service: media_player.play_media
      data:
        entity_id: media_player.hoolio
        media_content_type: PLAYLIST
      data_template:
        media_content_id: >
         {{ ["PlaylistN1", "PlaylistN2", "PlaylistN3", "PlaylistN4", "PlaylistN5", "PlaylistN6", "PlaylistN7", "PlaylistN8", "PlaylistN9", "PlaylistN10"] | random}}


robot_stop:
  alias: kill the radio
  sequence:
  - service: media_player.turn_off
    entity_id: media_player.hoolio

I have a bunch of playlists set up on my squeezeserver because my internet connection is rubbish. These playlists are split into different times of day based on my listening preferences. For an easy start to the day I have 10 different playlists called “PlaylistM1” “PlaylistM2” …M10 and the same thing setup for other times of day. Some of those playlists contain hundreds of songs so I get a lot of variety.

So via Ha-Bridge I say “Alexa, turn on robot radio” which runs the robot_radio script and the turn off command is linked to the robot_stop script at the end of the file.

I’m using include script: !include_dir_merge_named scripts in my config file so no hyphens on the scripts.

I wasn’t able to work out multiple instances of the time condition in a single script so I have worked around it by using scripts running sequentially within a script. If one fails to meet the condition it moves onto the next script. I suspect there is a far better way to do this.

2 Likes

I have worked out my shell command / .sh problems finally. I used a clean blank install and trial and error until I got it working and then replicated on my full install. Really I think I just needed to step away for a few days, too frustrated to see what was right in front of me perhaps…

For anyone else who has the same issue see here

Hi @ih8gates,

I was trying to use your script to play spotify over my chromecast (via LMS).
I managed to play single songs, but not being able to use playlists.
Also, every if i entered multiple song URIs in the script (to replace playlists), it can play only one song, not to mention shuffling. Any idea how i can make it work? Thanks!

If you get the Spotify URI for a playlist and load it with media_content_id, that should work. And does work for me every day.

I don’t think it’ll work with multiple separate tracks - each one will replace the first.

Thanks! May I know what plug-in you use for Spotify in LMS?

I use the Spotify 1.0 from Logitech and the Spotify Protocol Handler 1.1.1 (Triode).