Group Sonos and Ungroup Sonos Based on Presence - Scripts & Automations

I never quite understood why there is need for “master speaker variable” and it’s maintenance every 5 mins. Maybe I’m missing something, but this is my automation which does basically the same as the scripts in OP, but without that variable. It allows to set “volume offsets” for different speakers, and doesn’t join living room speaker to others when watching TV (however, it joins the other way - if you’re watching TV and go to kitchen for drink, kitchen speaker joins and you’ll hear TV there).

- id: '....'
  alias: General - Music
  description: ''
  variables:
    volume_adjustment:
      living_room_speaker: 0.6
      bedroom: 0.8
      kitchen: 1
  trigger:
  - platform: state
    entity_id: binary_sensor.living_room_motion_group
    id: living_room
    from:
    - 'on'
    - 'off'
    to:
    - 'on'
    - 'off'
    variables:
      speaker: media_player.living_room_speaker
  - platform: state
    entity_id: binary_sensor.kitchen_motion_group
    from:
    - 'on'
    - 'off'
    to:
    - 'on'
    - 'off'
    variables:
      speaker: media_player.kitchen
  - platform: state
    entity_id: binary_sensor.bedroom_motion_occupancy
    from:
    - 'on'
    - 'off'
    to:
    - 'on'
    - 'off'
    variables:
      speaker: media_player.bedroom
  condition:
  - condition: state
    entity_id: input_select.mode
    state:
    - Day
    - Evening
  - condition: or
    conditions:
    - condition: not
      conditions:
      - condition: trigger
        id: living_room
    - condition: state
      entity_id: media_player.android_tv
      state: unavailable
  action:
  - if:
    - condition: template
      value_template: '{{ trigger.to_state.state == ''on'' }}'
    then:
    - if:
      - condition: template
        value_template: '{{ states(speaker) != ''playing'' and states.media_player
          | selectattr(''attributes.group_members'', ''defined'') | selectattr(''state'',
          ''equalto'', ''playing'') | first | default(none) != None }}'
      then:
      - service: media_player.volume_set
        data:
          entity_id: '{{ speaker }}'
          volume_level: '{% set oldplayer = (states.media_player | selectattr(''attributes.group_members'',
            ''defined'') | selectattr(''state'', ''equalto'', ''playing'') | first)
            %} {{ oldplayer.attributes.volume_level * volume_adjustment[speaker.split(''.'')[1]]
            / volume_adjustment[oldplayer.object_id] }}'
      - service: media_player.join
        data:
          entity_id: '{{ (states.media_player | selectattr(''attributes.group_members'',
            ''defined'') | selectattr(''state'', ''equalto'', ''playing'') | first).attributes.group_members[0]
            }}'
          group_members: '{{ speaker }}'
    else:
    - if:
      - condition: template
        value_template: '{{ states(speaker) == ''playing'' and state_attr(speaker,
          ''group_members'') | count > 1 }}'
      then:
      - service: media_player.unjoin
        data:
          entity_id: '{{ speaker }}'
  mode: queued
  max: 10
2 Likes