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:
          domain: binary_sensor
    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: 0
          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

mode: restart
max_exceeded: silent

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

trigger:
- platform: state
  entity_id: !input presence_entity
  to: 'on'
- platform: homeassistant
  event: start
- platform: event
  event_type: automation_reloaded

condition:
- condition: state
  entity_id: !input presence_entity
  state: 'on'
- condition: state
  entity_id: !input sonos_source
  state: 'playing'
- condition: or
  conditions:
    # Do not trigger the 'action' if our target is already playing some music
    - condition: state
      entity_id: !input sonos_target
      state: 'paused'
    - condition: state
      entity_id: !input sonos_target
      state: 'idle'
    # However, re-trigger the 'action' if we are already grouped to prevent early ungrouping
    - '{{ sonos_target in state_attr(sonos_source, "sonos_group") }}'
- '{{ state_attr(sonos_source, "source")  != "TV" }}'
- condition: and
  conditions: !input custom_conditions

action:
# Only join when we have not already joined, since this would cause a 1 sec silence
- choose:
    - conditions:
      - '{{ sonos_target not in state_attr(sonos_source, "sonos_group") }}'
      sequence:
      - service: sonos.join
        data:
          master: !input sonos_source
          entity_id: !input sonos_target
- wait_for_trigger:
    platform: state
    entity_id: !input presence_entity
    from: "on"
    to: "off"
- delay: !input no_presence_wait
- service: sonos.unjoin
  data:
    entity_id: !input sonos_target

EDIT: Fixed early ungrouping

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