Making music follow you around the home with Home Assistant and Sonos

I love walking around the house and having music playing. However, most of the time when I’m home alone, or if the internal doors are closed, I don’t need the music to be in every room. When playing music in other rooms, it would be nice for the speakers to group and un-group only when they’re needed.

 

Ingredients

Speakers. The most import piece of the puzzle. I’m using different types of Sonos Speakers, including the Sonos Play:1, the new Sonos One speaker, and a Sonos Playbar. Home Assistant has a great Sonos component, which exposes methods for grouping players together.

Software. I’m using Home Assistant as my Home Automation controller. You might be able to substitute this for another controller of your choice though.

Sensors. I’m using Z-wave motion sensors, specifically the Aeotec 4-in-1 Multisensors and Aeotec 6-in-1 Multisensors, to detect motion around my home. These have a simple “on” or “off” state in Home Assistant depending whether motion has been detected or not. You could also get a bit fancy and use door/window sensors or any other type of sensor available to you in Home Assistant.

It seems like a pretty basic idea; when motion is detected in Home Assistant, join the Sonos speaker in the room to the group. When motion is not detected, remove the speaker from the group. However, we need to give Home Assistant some more information so it knows what it needs to do.

The Latest In Your Inbox

Enter your email address below to receive my latest blog posts and videos about Home Automation in your Inbox

 

Adding  a Toggle Switch

We first want a main switch, which can be enabled or disabled. When this switch is turned on, Home Assistant will automatically group Sonos players together when motion is detected. If the switch is turned off, Home Assistant won’t do anything. This is important, as we might not always want music to follow us around the home.

We can easily do this with an input_boolean . Let’s set one up now.

 

 

Defining a Master Player

Home Assistant needs to know which player is the main/master player. This is important. Let’s assume you’re playing music in your kitchen and then you go into the bedroom. Home Assistant groups the kitchen and bedroom speakers together. Eventually motion will no longer be detected in the kitchen, so now the kitchen player is un-grouped. The only Sonos speaker playing music is the bedroom. This would be okay, but let’s assume you’re reading a book in your chair. Motion will stop being detected, and Home Assistant will go ahead and un-group the bedroom player as well. This will cause the music to stop playing in the bedroom (and now the entire house) altogether. No amount of flapping your hands will turn the music back on. What’s worse is what you were listening to will most likely be forgotten, because your speaker was un-grouped instead of pausing.

The purpose of the master player is to give Home Assistant a point of reference. It is the one player in the house which Home Assistant will not pause, or un-group. It will keep playing music until someone tells it to stop.

The master player could be a different speaker at any time. If you’re working in the office, your master player may be your office Sonos Play:3. If you’re cooking in the kitchen, then the master player may be the kitchen Sonos One. Because of this, we want a way for us to be able to easily select which speaker is the “master” speaker. I’m going to use an input_select  component to do that.

 

You’ll notice that the names of those speakers seem a bit rough. I’ve deliberately named them kitchen as opposed to Kitchen, or main_bedroom instead of Main Bedroom. This is because I am basing them on their Home Assistant entity_id . For example, in my Home Assistant I have media_player.kitchen  and media_player.main_bedroom  which are Sonos speakers. You’ll see why this is important soon.

 

Group Players Script

The first thing I’m going to do is create two Home Assistant scripts. One to group players, and another to un-group players. The use of scripts is important. If we ever get new Sonos speakers in the future, we only need to update the automation file for the logic. The scripts should be just set-and-forget.

First, here is a script that will add a new player to a Sonos Group.

That script does the following:

  1. It accepts a parameter called target_player . This is the entity_id  of the player you want to add to the group. So, if we move into the kitchen and want the kitchen Sonos to start playing, it would be set to media_player.kitchen .
  2. It checks to make sure the target player is not already playing something. This is useful if you’re watching TV on a Sonos Playbar, or you’re listening to music in different rooms. If the player is already playing something, don’t do anything.
  3. If the player isn’t playing anything, it will then group the target player to the player which is selected with the input_select.music_controller drop-down in the UI.

Before we go ahead and save that, I want to add one more feature. You’ll thank me for this.

Let’s assume you’ve watched TV the night before, and your Playbar is set to 45%. You’re listening to music at a peaceful 25%, and walk into the living room. Our script above includes in your Playbar, and because the Playbar is set to 45% volume, when it gets grouped it will start playing music at 45% and scare the absolute **** out of you. You’ll be fumbling for your phone or diving to the Playbar to try and frantically lower the volume before you wake-up someone in the house.

To solve this, I’m going to alter the script above to first set the volume of the target player to the same level as the controller. This means no matter what the previous volume level was, we will always set it back to the same level as the controller player first, to avoid that big shock.

 

Un-group Players Script

Now that we have a script to group players together, we need one which will do the opposite. This will be called when we leave a room.

This script just calls media_player.sonos_unjoin  against our player, but only if the player is playing.

 

Adding the Automations

Now we’ve got the scripts setup, it’s time for the fun part. The automations. I try to keep my automations as lean as possible. You could create an automation for each sensor, naming them like “group study player when motion detected”. However I prefer to keep everything in a single automation if I can. So, here is my automation for grouping players when motion is detected.

There’s only two conditions for this script to fire. First, our input_boolean  for following music must be turned on. Second, the controller player must be playing music. If no music is playing on the controller, then there’s nothing to do.

If those conditions are met, then our script script.sonos_group_from_motion is called. (Be sure to check how your script is named, my scripts are saved in individual files which determine their entity_id’s. See here for more information.)

The magic comes in the template used to determine the target_player . We’re using the trigger  variable, which is passed to to the automation. It will allow us to check which motion sensor triggered the automation to fire. We can then match the motion sensor up to the player which is in the room. This comes in handy if we ever need to add additional speakers and motion sensors in the mix. We just need to update these automation templates.

There’s also a similar automation to un-group the players when motion is not detected:

 

Using Multiple Motion Sensors for One Speaker

To improve accuracy, you may have setup multiple motion sensors in a room. This is particularly the case if you live in an open-plan apartment. We can change the template and add some conditions to account for these so that

  • If a room has multiple motion sensors, if any motion sensor activates the room should be grouped into the playing music; and
  • Only un-group said room if both motion sensors have not detected motion

I’m going to set this up on my kitchen speaker. I have two motion sensors that can detect motion near the kitchen, one is the entry motion sensor (which is already in the automation). I’m going to add in the dining motion sensor, with the rules above.

And now to make sure both motion detectors have not seen motion before un-grouping:

 

Automating When Music Follows You

We can choose when music should start to follow you around. I’ve setup an automation which automatically disables the input_boolean.follow_music  once music has stopped playing for at least fifteen minutes. Here’s how I do that:

That automation will check the controller speaker every five minutes. If it has not been playing anything for more than fifteen minutes, it turns off the input_boolean.follow_music  input.

Another automation I use is to change the master/controller player to the office Sonos when my study desk turns on. I have a Z-wave Smart Switch which monitors the power usage of my PC monitor. When that goes up, it turns on an input_boolean  which tells Home Assistant I am sitting at my desk, and not to turn the lights off if I’m sitting still.

 

I don’t have Sonos, can I use this with something else?

While I only use Sonos speakers for my multi-room audio, there are other platforms now that are starting to roll out multi-room audio as well, like Chromecast and Google Home. I’ve read on Reddit that some people are suggesting having motion sensors set the volume of other players to zero when there’s no motion. So, you could have a Chromecast Audio in your study, and one in your kitchen and when the kitchen motion sensor stops detecting motion, Home Assistant could set the volume on the kitchen Chromecast Audio to zero. When motion is detected again, it brings up the volume again. Another option is using Snapcast and Raspberry Pi’s. If these are something you’re interested in, here’s some links which may point you in the right direction:

 

Wrapping Up

This is a pretty neat way to use Home Assistant and templating to control things around the house. If you’re a sports fan, and have people over to watch the Cricket or Superbowl (I won’t judge you), you could setup a Sonos speaker in the bathroom. If someone goes into the bathroom, group the Sonos Playbar together with the bathroom speaker so people can hear every score while they’re in the bathroom. Or perhaps have a spooky Halloween track playing, and as people move around your house speakers tune in to the track to make it feel like those spooky voices are following them.

Recommended Posts
  • Bernie Blais

    This is really interesting Phil, and I will surely try to integrate this solution when I am further down in my setup. I currently have all the components, just need to get to it. I do see a couple of scenarios that I will try to implement once I get a better grasp of all these scripts and components. The first one being to only enable this feature if I am alone in the house, my wife would not understand this and would just want me to turn it off. Also, to not group the Living Room speaker if the TV is playing since both are in the same room. But this is an excellent feature and great use of automation.

    • Thanks Bernie,

      Yes, I’ve had to take account for both of those points into account 🙂

      I have a script which fires when I get home. It waits 5 minutes, then if I am home alone it sets music to follow me, then starts my chillout playlist on Spotify. If before the 5 minutes is up and someone else is home, then the script doens’t continue and exits so the music doesn’t play.

      For the TV, I have a Harmony Hub, so I can check to see if it is off in home assistant before I group the playbar in using a template

Start typing and press Enter to search