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

Use the file editor plug-in and create the following folders/files
/config/blueprints/automation/groupsonos/groupsonos.yaml
The code goes into the groupsonos.yaml file

Version 2022.5 changed sonos_group for group_members, working version is below

Thanks for the blueprint, Marvin. So satisfying to use

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 sonos_source
    to: "playing"
  - 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, "group_members") }}'
  - '{{ group_on_tv or 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, "group_members") }}'
        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

Hi - Anyone have a more updated working blueprint? sonos.join seems to be removed from Home Assistant and replaced with media_player.join. I also replaced the unjoin with media_player.

Not sure if anything else has changed in the blueprint recently but the target speaker never joins the group.

I just had to change the action with a small re-org of the blueprint in addition to replacing sonos.join and sonos.unjoin to media_player and everything works.

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, “group_members”) }}’
        sequence:
      • service: media_player.join
        data:
        group_members: !input sonos_target
        target:
        entity_id: !input sonos_source

Would you mind sharing the full, updated blueprint?

Also interested in the updated blueprint, as I can’t get it to work ATM

This is what I’m using:

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 sonos_source
    to: “playing”
  • 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, “group_members”) }}’
  • ‘{{ group_on_tv or 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, “group_members”) }}’
        sequence:
      • service: media_player.join
        data:
        group_members: !input sonos_target
        target:
        entity_id: !input sonos_source
  • wait_for_trigger:
    platform: state
    entity_id: !input presence_entity
    from: “on”
    to: “off”
  • delay: !input no_presence_wait
  • service: media_player.unjoin
    data:
    entity_id: !input sonos_target

This seems to do exactly what I need, would you mind to share the code using the tags, please?
I know I can format it and make it work but it would help anyone else looking for something similar, even easier to read and understand what it does at a glance.
Thank you anyway!

1 Like

@e8link Could you share the formatted code?

When trying to import this blueprint, I get the following error:

while scanning a simple key in “”, line 110, column 1: ^ could not find expected ‘:’ in “”, line 111, column 1:

EDIT: Fixed early ungrouping
^

Is this template broken?

Fixed it! Apparently we are not allowed to put any text underneath the YAML block anymore.

Great blueprint! Thanks.

What is the format for the custom conditions? I just want to create a binary sensor that I can manually switch, to be able to disable these automations. Thanks heaps.

The same as you would specify any other conditions in YAML, for example:

...
custom_conditions:
      - condition: state
        entity_id: binary_sensor.some_extra_sensor
        state: "off"
        for:
          minutes: 10
      - condition: time
        before: "19:00:00"
1 Like

MarvinS,

Thank you so much for this great blueprint. I hope you don’t mind, but I added it to GitHub and created an updated topic. Obviously, I mentioned that you are the author of this blueprint!

I also did some minor modifications in order to make the blueprint a bit easier to use.

Thanks once again for your hard work! :muscle:

1 Like

So i’ve setup this automation and it seems to work great but i’m having 1 issue I’m not sure how to work around. If a speaker tries to join a already existing group via the speaker that didn’t originally start the session, then the two speaks would just great a separate group as part of a new session instead of joining the already existing group.

Currently I have a number of automations per room with the end goal being that i would like to have the music follow me regardless of where the music starts.

Any help appreciated.

Screenshot 2023-07-13 131513

1 Like

I have the exact same issue

Hm, there should be some logica added where HA remembers the player that started the session. I’ll have a look at it later today and see if I can figure out something.

2 Likes

Hi, did you find a solution/logic to solve this problem? I only found the solution of having one player the deignated master and start music from there and mute it when the room has no presence. But this works only when the music is started by an automation and not manual. Also this approach makes automations hell and is very much suboptimal.

And volume? How is this working because no the volume is very low or load… is there a option to use the volume of the masters device and follow this to the grouped devices?