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