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 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

  • Gerson Ferreira

    wow! As a newbie I am astonished with that config. I need time to read it carefully 10 times. Nice work. Thank you for sharing.

  • Coolie “Coolie1101” Trini

    Would love to impliment this, but too many family members moving around.

  • Scott Wishart

    Hey Phil, great post, it enabled me to build an automation to ‘move’ music (manually selecting source, destination and overlap time) from one location to another using Logitech Media Server and a mixture of Android devices, a PC and a Raspberry Pi running various SqueezePlayer ports 🙂
    I’ve just bought a Sonos Play:1 and was assuming I could easily use media_player.play_media service calls to start Sonos playing internet radio stations or local playlists on my media server, but I just can’t get Sonos to play anything, other than mp3 files hosted on the internet via http… am I missing something? How do you start your chillout playlist?
    Thanks, and keep up the podcasts too 🙂

    • Thanks Scott!

      For things like the playlists and stations, you have to add those to your Sonos favourites in the app. Once done, you’ll be able to select them from the Home Assistant UI via a dropdown, and then also scripts and automations .

      Cheers

  • Håkan Pettersson

    Hi! Greetings from sweden… Its a lovely script! Are u still using it? Cant get it to work…. Probably need some changing through home assistants many updates. I would love to get my hands on an updated script… Cheers!

    • Henrik Christiansen

      Hopefully you figured it out by now – if not, you’ll need to make a small change to the scripts. In newer versions of Home Assistant, the service is no longer called media_player.sonos_join, but rather sonos.join – and sonos.unjoin.
      Change these two services (lines 34 and 30 for the join and unjoin script, respectively), and it’ll work wonders again. 🙂

  • Henrik Christiansen

    Phil,
    I mentioned this in a reply below to Håkan, but I’ll make a top-level comment too. In newer HA versions the service has changed from media_player.sonos_join to sonos.join (and media_player.sonos_unjoin to sonos.unjoin), so for those who copy-paste the scripts, it won’t fully trigger.

    Otherwise, thank you very much for this! I’ve been running this since January this year, and it has been such a good experience. Not only is it convenient, but it’s such a cool thing to show off – I’ve impressed loads of friends with it. Thank you again!

    • Good call Henrik! I’ve updated those (hopefully got them all)

      I’m glad you like it! It is pretty cool walking around the house and the music just follows you. For the most part Home Automation can be hard to “see” or experience on demand, but simply moving around you can experience this which is great.

  • Codryn

    Can Sonos be replaced with Echo dot?

    • Possibly with the Alexa media player custom component, but I don’t think so.

      • Codryn

        Thank you for reply, well that sucks I need 9 speakers and for 9 sonos is just too much 🙁

        • Codryn

          Another q..having a 2 floor house, how

          Z-Stick can communicate with sensors? Should I have 2 sticks one for each floor?

          • Z-wave should mesh, so one stick should be more than enough. Just make sure you’re using z-wave devices that are powered from the wall (not batteries). These will act as repeaters, and extend your z-wave range,

          • Codryn

            Thank you for your kind answers. So if I understand correctly I need a z-wave usb stick on first floor inside synology nas where the home assistant docker is running, aeon sensors 6in1 in every desired room and upstairs a z-wave repeater plugged in 230v outlet ?

          • Correct.

            I would also recommend powering a couple of your 6in1’s via USB power. When this is done, those sensors become repeaters as well and will increase the mesh network/range.

            Most of the issues you’ll face with Zigbee or Zwave devices are because there isn’t enough powered devices to make a reliable mesh network. So the more you can power with USB or mains, the better.

      • Dave Beiler

        why not?

        • I don’t think the Alexa Media Player component allows you to group players in and out of a group, you can only play to specified Alexa groups.

          See the docs to see if there’s a way: https://github.com/custom-components/alexa_media_player/wiki#play-in-alexa-groups

          • Dave Beiler

            It is currently not possible to play to an Alexa group using routines. However, there is currently a hack that may or may not work where you can play to an Alexa group using any Alexa entity on that account. For example, to play to the “everywhere group”. NOTE: We are sending to media_player.guest_room instead of media_player.everywhere

          • That’s right. So in this article I’m talking about having the music move around rooms. Which requires removing single media players from playing at a time.

            So if you have three media players

            Office
            Bedroom
            Kitchen

            You’ll want music to stop playing on one or two as you move around the house. For those three speakers above, you’ll need to create 9 groups in Alexa and then change the group based on which rooms are occupied. Add a fourth speaker and you’ll need to create 256 groups to achieve what I am doing in this article with Sonos.

          • Dave Beiler

            i appreciate your assistance and quick response, how do you get 256 groups? is that a typo?

          • Actually my maths might be wrong.

            I think this might the correct way to calculate the number of groups needed

            3 Speakers = 3 * 3 = 9
            4 Speakers = 4 * 4 = 16
            5 Speakers = 5 * 5 = 25

            This is to do it exactly how I have it in my example in the article. If you were instead happy to “zone” your speakers say one half of the house, then you could simplify it a bit and not need as many groups.

          • Dave Beiler

            So i broke down your steps into main points, when do you create these groups?
            – configuration
            – input select
            – Group players (add new player to group) and ungroup players
            – Adding the automations when motion is detected
            – Ungroup player when motion is not detected
            – Automation when music follows you
            – Automation to change the master/controller player when in study (important)

          • Do you mean the Alexa player groups?

            They should be created in the Alexa app and then you may need to restart Home Assistant to be able to control them. However note that no entities will be created in Home Assistant for Alexa Media groups. You will need to find a way to manage which group should be used based on your own logic in Home Assistant. You’ll most likely need to create another input_select and some automations with templates to work out the logic of which group to select.

            For example
            Is motion detected in Room A but not Room B? Then select Alexa Group 1.
            Is motion detected in Room A only? Select Alexa Group 2
            Is motion detected in Room B only? Select Alexa Group 3
            Is motion detected in Room B but not room A? Then select Group 4

            Then once you’ve worked out the logic for which rooms the music should be played in, then you’ll call the appropriate service in the Alexa Media Player link above to update which players are used.

            An important note here though. When you change rooms with the Alexa Media Player, you are calling a media play service. This means that the current song playing may be played from beginning when you call the service to change Alexa groups. Not as clean as the Sonos way unfortunately

          • Dave Beiler

            thanks! I may just invest in some sonos in the future to make it simple (for background music).
            Last question, you only have 1 automation.yaml, do i need to make duplicates of these for each motion detection sensor?

          • Yeah the Home Assistant Sonos integration makes this pretty easy to do. You might be able to do it with other brands of speakers, but don’t hold me to that.

            I personally use Home Assistant packages to split my configuration. However putting all of the automations I have marked as automation.yaml in one file is fine.

            You can use one single automation to group, and one single automation to ungroup if you prefer. This is what I have done, check the “Using Multiple Motion Sensors for One Speaker” section. Essentially you’ll need to use a Home Assistant template to change which speaker is grouped/ungrouped based on the motion sensor that triggered the automation.

  • André Lung

    Awesome automation! But as I see it, your master stays on all the time, right? Do you know any way to “transfer” music to another speaker (with the current playback position)?

Start typing and press Enter to search