Group Sonos based on presence (e.g. Motion)

This blueprint automatically groups a Sonos to a main device when presence (e.g. motion) is detected.

---
blueprint:
  name: Group Sonos on Motion
  description: >
    Group a Sonos device to a main device when presence (e.g. motion) is detected and
    the main device is playing music. Can be extended with custom conditions, for
    example, only group the Sonos when you're not asleep
  domain: automation
  input:
    presence_entity:
      name: A sensor to detect presence (can be a motion sensor)
      selector:
        entity:
    sonos_source:
      name: Sonos source
      description: Sonos entity to group the target Sonos to
      selector:
        entity:
          integration: sonos
    sonos_target:
      name: Sonos target
      description: Sonos target to group to the source Sonos
      selector:
        entity:
          integration: sonos
    no_presence_wait:
      name: Wait time
      description: Time to leave the sonos grouped after last presence is detected.
      default: 120
      selector:
        number:
          min: 1
          max: 3600
          unit_of_measurement: seconds
    custom_conditions:
      name: Custom conditions
      default: []
      description: >
        A list of custom condititions that also have to be met before grouping the
        sonos. Only available via YAML mode
    group_on_tv:
      name: Group on TV
      description: >
        Whether to also group the Sonos when the source is playing TV audio
      default: false
      selector:
        boolean:

mode: restart
max_exceeded: silent

variables:
  sonos_source: !input sonos_source
  sonos_target: !input sonos_target
  group_on_tv: !input group_on_tv

trigger:
  - platform: state
    entity_id: !input presence_entity
    to: "on"

  - platform: state
    entity_id: !input presence_entity
    to: "off"
    for:
      seconds: !input no_presence_wait

  - platform: state
    entity_id: !input sonos_source
    to: "playing"

  - platform: homeassistant
    event: start

  - platform: event
    event_type: automation_reloaded

action:
  - choose:
      - conditions:
          - condition: state
            entity_id: !input presence_entity
            state: "on"
          - condition: state
            entity_id: !input sonos_source
            state: "playing"
          - condition: or
            conditions:
              - condition: state
                entity_id: !input sonos_target
                state: "paused"
              - condition: state
                entity_id: !input sonos_target
                state: "idle"
          - '{{ group_on_tv or state_attr(sonos_source, "source")  != "TV" }}'
          - condition: and
            conditions: !input custom_conditions
          # Only join when we have not already joined,
          # since this would cause a 1 sec silence
          - '{{ sonos_target not in state_attr(sonos_source, "group_members") }}'
        sequence:
          - service: media_player.join
            data:
              group_members:
                - !input sonos_target
            target:
              entity_id: !input sonos_source

      - conditions:
          - condition: state
            entity_id:
              - !input presence_entity
            state: "off"
            for:
              seconds: !input no_presence_wait
        sequence:
          - service: media_player.unjoin
            data:
              entity_id: !input sonos_target

    default: []

8 Likes

did you intent to make the custom conditions as required? As is, it’s a requirement to have them

I did not, good find. The default value has been changed to [] which should fix this issue.

1 Like

If I’m reading this right, I need to set the Sonos target and Sonos source as well as motion sensor.

How would it work for this scenario?
Say I want to turn on music in bedroom when I walk into it. Sonos target = bedroom; sensor = bedroom sensor.
If I have music playing in the living room and walk into the bedroom then logic would dictate that I would set my automation source to living room. But say I’m playing music in the office and then walk to the bedroom, this won’t work because source was living room instead of office.

Is there a way to make this with a more generic source?

I guess you would need to create a second automation based on this blueprint where you’d use the office as a source and the bedroom as a target. Note that the blueprint only joins if the source is actually playing music. The reason the blueprint does not support multiple sources is so you have the flexibility to give priority to one of your sources. Let’s assume that you use two sources (office and living room) and one target (bedroom) and both of them are playing different music, how would the blueprint know where to join the bedroom to? By using two automations based on this blueprint, you can easily determine this yourself by passing an additional ‘custom_condition’.

Thanks for this. I’m setting it up now. Like you said, I’ll set-up multiple automations to cover each piece.

I think the next progression is to make like a “follow-you” based on presence. So if you go from living room to bedroom, it starts playing in bedroom (this is what you already have). If you leave bedroom, it stops playing in bedroom (you already have this). But if you stay in bedroom for a while without presence in living room, it stops playing in living room.

Edit: My bigger issue is that apparently my Sonos speakers don’t seem to update their status within Home Assistant most of the time.

this automation is great, but i have one issue i can’t figure out. when the kitchen (source) is already grouped with the living room, and i walk into the bathroom (target), the music in the kitchen stops. But when the living room is grouped with the kitchen, and i walk into the bathroom, everything stays on. any ideas?

This issue does not sound familiar to me. Could you post the relevant automations so I can help you out?

alias: bathroom_music_sync
description: ''
use_blueprint:
  path: MarvinS/group-sonos-based-on-presence-e-g-motion.yaml
  input:
    no_presence_wait: 60
    presence_entity: group.bathroom_motion_sensors
    sonos_source: media_player.kitchen
    sonos_target: media_player.bathroom
    custom_conditions: []

Thanks for the help, that’s what I have

I’ve tried importing this blueprint but get “while scanning for the next token found character ’' that cannot start any token in "<unicode string>", line 49, column 11: to: 'on' ^”.

Any idea what I might be doing wrong?

Sorry that was my mistake, I made an error on my side. Could you try to import it again?

Has anybody had any luck grouping their target speakers with a Playbar playing TV audio as the source?

I’ve setup this blueprint to use Play speaker to Play speaker, but have no luck with TV Playbar to Play speaker. The sensor detects the motion but no action happens.

To make things more confusing, if I click the “Run Actions” button it works perfectly, but motion won’t make this one run.

In case you need my setup, I’ve listed it below.

alias: Group Sonos on Motion
description: ''
use_blueprint:
  path: homeassistant/sonos_followme.yaml
  input:
    presence_entity: binary_sensor.kitchen_motionsensor
    sonos_source: media_player.playbar
    sonos_target: media_player.kitchen_sonos
    custom_conditions: []

Thanks for your help!

1 Like

That’s odd. Are you playing music, or watching TV? The blueprint does not group the Sonos when the input entity has “TV” as the source.

As for the ‘Run Actions’, it makes sense that this works as it skips the triggers/condition part of the blueprint.

Yes the Playbar is playing audio from the TV.

The aim is to have the kitchen speaker group to the Playbar (TV) and play the tv audio into the kitchen when we’re in there. At the moment the tv volume gets turned up too high so it can be heard in the kitchen.

You mentioned that the blueprint does not group when the tv is the source so I get the feeling this is intended. If I were to remove something like the like below do you think I could achieve the grouping after?

- '{{ state_attr(sonos_source, "source") != "TV" }}'

Thanks Marvin.

Yes this was intended, because I only wanted to use this blueprint to have music follow me around the house. Removing the line you supplied would get you the desired effect. I will make this configurable in a new version of the blueprint.

Thanks Martin. I did remove that line and the TV audio followed me as expected.

Great idea about adding it into the next version of the blueprint. Thanks again for your work!

Thanks Martin for your great blueprint, was struggling to get it working on my own.

I modified your blueprint to accept a boolean as input so I can use more triggers than only motion.

Terrific blueprint. This is a great idea. A couple quick suggestions: I also modified to remove the binary_sensor filter. Modified to remove the ‘TV’ filter line. And I also learned that a zero wait_time did not work. So I made my wait_time’s 1 second. I point all of my grouping automations back to a single sonos as the source, then play everything on that source. Makes playing music in the house so simple :partying_face:.

Thanks for the feedback :). Made the following changes:

  • Added ‘Group on TV’ option
  • Increased min_value for no_presence_wait to 1
  • Removed binary_sensor filter from presence_entity

Thanks for sharing this, @MarvinS! This sounds like an awesome idea, but I haven’t been able to get it to work yet. I’m both new to Home Assistant and also a coding rookie, so please forgive me if I’m missing something obvious, but I’m trying to import directly from the URL:

And I’m receiving this error:

while scanning a simple key in "<unicode string>", line 107, column 1: </code></pre> ^ could not find expected ':' in "<unicode string>", line 108, column 1: <p>EDIT: Fixed early ungrouping<br> ^

I’ve been able to get other blueprints to import via sometimes included import buttons or using a GitHub link, but this one won’t work for me. Let me know if I’m doing something wrong or you have any other helpful tips. Appreciate it!