Now that I’ve got multiple Sonos speakers, I want to make the most of them by looking at some simple automations.
The first challenge was to play the radio while I’m getting ready for work.
There were several approaches I could take. I did think about alarms, but I wanted to keep my alarm separate. Nine times out of ten I wake up before the alarm – it’s really just a failsafe to stop me oversleeping. Since I can’t predict when I’ll wake up, I thought the best solution would be to have a simple voice command to turn the radio on. I also wanted it to play in all rooms, so that I can keep listening as I move around the house getting ready.
Sonos does not have voice support for grouping speakers, but luckily it’s supported by the API. Home Assistant came to the rescue.
I started off by creating a script to group all of my speakers, using the bedroom speaker as the master (it didn’t really matter which was the master):
sonos_group_all: alias: "Group all Sonos" sequence: - service: sonos.join data: master: media_player.bedroom entity_id: - media_player.kitchen - media_player.study
Note:
The service was media_player.sonos_join, and this changed to sonos.join in v0.93 of Home Assistant. Thanks to Robert for pointing this out in the comments below.
I then wanted to set the volume level. I sometimes use the bedroom speaker to play music to help me get to sleep and that’s often at a very low volume, so for my morning radio routine I created a script to set the right volume. I found the right level by experimenting and checking the values shown in the HA entities:
sonos_morning_volume: alias: "Morning Sonos" sequence: - service: media_player.volume_set entity_id: - media_player.bedroom - media_player.kitchen - media_player.study data: volume_level: 0.20
If need be I could have set a different level for each speaker.
The final step was to play the desired station. For some media players that would involve hunting around for the URL of the streaming source, and that URL is subject to change. There’s a much easier way with Sonos and Tunein radio.
I used the Sonos app to find radio stations and add them to my favourites:
Those favourites then show up as sources for the Sonos media player in Home Assistant (you may need to restart home assistant to refresh the source list):
Then all I had to do was call the scripts to set the volume and group the speakers before setting the source to the desired station:
sonos_morning_radio: alias: "Sonos Morning Radio" sequence: - service: script.turn_on entity_id: - script.sonos_morning_volume - script.sonos_group_all - service: media_player.select_source entity_id: media_player.bedroom data: source: "BBC Radio 1"
Finally, to add voice control, I added the script to my exposed entities for the emulated Hue component:
emulated_hue: type: alexa host_ip: 192.168.1.89 listen_port: 8300 expose_by_default: false off_maps_to_on_domains: - script - scene entities: script.sonos_group_all: name: "Group speakers" hidden: false script.sonos_ungroup: name: "Ungroup speakers" hidden: false script.sonos_morning_radio: name: "Morning radio" hidden: false
I also added the scripts to group and ungroup speakers so that I could call them separately if I chose to.
With all of that in place I can now say “Alexa, turn on morning radio” when I wake up – whatever time that is, regardless of any alarms I have set. To stop the music, all I have to do is say “Alexa, stop” – there’s no need for a separate script to turn the music off.
It’s not perfect and I may tweak the setup. Although I initially intended to use it in the morning, I’ve found it’s useful any time I want the radio playing throughout the house, so I may change it to a more generic name.
As it stands, stopping the music leaves the speakers grouped, which isn’t always what I want. I have to remember to ungroup them.
I could have implemented it as a switch that ran the script when it was turned on and then ran a script to stop the music and ungroup the speakers when it was switched off. The problem with that approach is it’s easy to forget. If I set it up as a switch and just said “Alexa, stop” instead of “Alexa, turn morning radio off” it would leave the switch on – and inconsistent with reality.
Capturing the right logic to know when to ungroup the speakers automatically is fairly complex and may not always work – I might, for example, want to stop the radio playing but leave the speakers grouped to play some other music. For now it’s easier to simply have an ungroup command. If I find that, in practice, I’m always ungrouping them at certain times, I can think about further automation.
in Home Automation
Thanks for this. It really helped me to get going with my own Sonos automations. Have you made any significant changes in the past few months.
I haven’t been doing much over the summer, but the winter months are coming and I’m hoping to get back to some more technical posts soon.
Stupid question, but where do you put the script in HA?
I break my configuration.yaml out with includes, so I have:
script: !include_dir_merge_named includes/script
Then in a subdirectory called includes/script, the script snippets are in a file called sonos.yaml
You could also have it all inline in your main configuration.yaml – just start a section called:
script:
Then add the snippets at the next level of indentation (2 spaces)
There is an error in the “Sonos Group All” Script. The service is incorrectly identified. Rather than reading;
sequence:
– service: media_player.sonos_join
It should read
sequence:
– service: sonos.join
Apart from that – thank you for the information. it helped me automate Sonos radio station selection and playing.
Thanks Robert, that’s one of the problems with older posts and the progress of Home Assistant.
The Sonos custom services moved from the media player domain to the sonos domain in v0.93 of HA – see the release notes:
https://www.home-assistant.io/blog/2019/05/16/release-93/
So media_player.sonos_join was correct at the time this was written, but it has subsequently changed. Thanks for pointing it out. I’ve edited the post to reflect the new service call.