Hi,
want to share my sonos auto music follow setup - it took a while to develop, hope you find some inspiration in this
My setup: I have sonos loudspeakers in every room
My target:
-
Whenever I enter a room (motion sensor based), music should start playing depending on the time of the day with different volume and playlist, playlist should play in shuffle mode
-
Music should follow us around in the house - so that I hear in every room the same music when motion is detected and music switches off when I leave the room
-
I wanted flexibility though, being able to e.g. disable autofollow / automusic mode, to play separate things
-
it should nicely interplay with my tts announcements (I call him jarvis)
-
on terrace, I want to be able to decouple the motion sensor as the motion sensor does not cover every corner of the terrace so that the music continues playing
-
I wanted a “panic button” to switch everything off - I call it “focus time”
-
In the bedroom, I don’t want music to play when somebody is sleeping
How I did it: -
I decided the speaker in the hallway is my master speaker. this one always plays along when some other speaker in the house is active - however, it might be muted when there is no motion in the hallway
-
In order to realize this, I programmed a template sensor “multimedia_sonos_instruction” which basically tells my automations what to do. This was a difficult sensor to create but it runs very stable since a couple of months
Here comes my configuration:
input_select:
multimedia_sonos_stations_early_morning:
name: Early Morning Radio
icon: mdi:broadcast
options:
- " "
multimedia_sonos_stations_morning:
name: Morning Radio
icon: mdi:broadcast
options:
- " "
multimedia_sonos_stations_day:
name: Day Radio
icon: mdi:broadcast
options:
- " "
multimedia_sonos_stations_evening:
name: Evening Radio
icon: mdi:broadcast
options:
- " "
multimedia_sonos_stations_night:
name: Night Radio
icon: mdi:broadcast
options:
- " "
input_boolean:
multimedia_focus_time:
name: Focus Time
icon: mdi:chat-sleep
multimedia_terrace_override_occupied:
icon: mdi:radio
name: Sonos Override Occupied
multimedia_sonos_autofollow:
icon: mdi:radio
name: Sonos Follow
multimedia_mancave_automusic:
icon: mdi:radio
name: Auto Music
multimedia_terrace_automusic:
icon: mdi:radio
name: Auto Music
multimedia_livingroom_automusic:
icon: mdi:radio
name: Auto Music
multimedia_bedroom_automusic:
icon: mdi:radio
name: Auto Music
multimedia_hallway_automusic:
icon: mdi:radio
name: Auto Music
multimedia_bathroom_automusic:
icon: mdi:radio
name: Auto Music
input_number:
multimedia_sonos_livingroom_volume_night:
name: Night Volume
icon: mdi:brightness-3
mode: box
step: 0.01
min: 0
max: 0.70
multimedia_sonos_livingroom_volume_morning:
name: Morning Volume
icon: mdi:weather-sunset-up
mode: box
step: 0.01
min: 0
max: 0.70
multimedia_sonos_livingroom_volume_day:
name: Day Volume
icon: mdi:white-balance-sunny
mode: box
step: 0.01
min: 0
max: 0.70
multimedia_sonos_livingroom_volume_evening:
name: Evening Volume
icon: mdi:weather-sunset-down
mode: box
step: 0.01
min: 0
max: 0.70
multimedia_sonos_bedroom_volume_night:
name: Night Volume
icon: mdi:brightness-3
mode: box
step: 0.01
min: 0
max: 0.70
multimedia_sonos_bedroom_volume_morning:
name: Morning Volume
icon: mdi:weather-sunset-up
mode: box
step: 0.01
min: 0
max: 0.70
multimedia_sonos_bedroom_volume_day:
name: Day Volume
icon: mdi:white-balance-sunny
mode: box
step: 0.01
min: 0
max: 0.70
multimedia_sonos_bedroom_volume_evening:
name: Evening Volume
icon: mdi:weather-sunset-down
mode: box
step: 0.01
min: 0
max: 0.70
multimedia_sonos_mancave_volume_night:
name: Night Volume
icon: mdi:brightness-3
mode: box
step: 0.01
min: 0
max: 0.70
multimedia_sonos_mancave_volume_morning:
name: Morning Volume
icon: mdi:weather-sunset-up
mode: box
step: 0.01
min: 0
max: 0.70
multimedia_sonos_mancave_volume_day:
name: Day Volume
icon: mdi:white-balance-sunny
mode: box
step: 0.01
min: 0
max: 0.70
multimedia_sonos_mancave_volume_evening:
name: Evening Volume
icon: mdi:weather-sunset-down
mode: box
step: 0.01
min: 0
max: 0.70
multimedia_sonos_hallway_volume_night:
name: Night Volume
icon: mdi:brightness-3
mode: box
step: 0.01
min: 0
max: 0.70
multimedia_sonos_hallway_volume_morning:
name: Morning Volume
icon: mdi:weather-sunset-up
mode: box
step: 0.01
min: 0
max: 0.70
multimedia_sonos_hallway_volume_day:
name: Day Volume
icon: mdi:white-balance-sunny
mode: box
step: 0.01
min: 0
max: 0.70
multimedia_sonos_hallway_volume_evening:
name: Evening Volume
icon: mdi:weather-sunset-down
mode: box
step: 0.01
min: 0
max: 0.70
multimedia_sonos_bathroom_volume_night:
name: Night Volume
icon: mdi:brightness-3
mode: box
step: 0.01
min: 0
max: 0.70
multimedia_sonos_bathroom_volume_morning:
name: Morning Volume
icon: mdi:weather-sunset-up
mode: box
step: 0.01
min: 0
max: 0.70
multimedia_sonos_bathroom_volume_day:
name: Day Volume
icon: mdi:white-balance-sunny
mode: box
step: 0.01
min: 0
max: 0.70
multimedia_sonos_bathroom_volume_evening:
name: Evening Volume
icon: mdi:weather-sunset-down
mode: box
step: 0.01
min: 0
max: 0.70
multimedia_sonos_terrace_volume_night:
name: Night Volume
icon: mdi:brightness-3
mode: box
step: 0.01
min: 0
max: 0.70
multimedia_sonos_terrace_volume_morning:
name: Morning Volume
icon: mdi:weather-sunset-up
mode: box
step: 0.01
min: 0
max: 0.70
multimedia_sonos_terrace_volume_day:
name: Day Volume
icon: mdi:white-balance-sunny
mode: box
step: 0.01
min: 0
max: 0.70
multimedia_sonos_terrace_volume_evening:
name: Evening Volume
icon: mdi:weather-sunset-down
mode: box
step: 0.01
min: 0
max: 0.70
input_text:
multimedia_sonos_station_early_morning:
name: "Station Early Morning"
max: 255
multimedia_sonos_station_morning:
name: "Station Morning"
max: 255
multimedia_sonos_station_day:
name: "Station Day"
max: 255
multimedia_sonos_station_evening:
name: "Station Evening"
max: 255
multimedia_sonos_station_night:
name: "Station Night"
max: 255
sensor:
- platform: template
sensors:
multimedia_sonos_instruction:
friendly_name: Sonos Instruction
value_template: >
{% set MyAction = namespace(value='no action') %}
{% set MasterSpeaker = 'media_player.sonos_hallway' %}
{% set TimeNow = as_timestamp(now()) | int(default=0) %}
{% if states('input_boolean.multimedia_focus_time') == 'off' %}
{% if states('input_boolean.multimedia_sonos_autofollow') == 'on' %}
{% if states('input_boolean.jarvis_announcement_wait') == 'off' %}
{% for speaker in states.media_player
if ('sonos' in speaker.entity_id)
and speaker.state != 'unknown'
and speaker.state != 'unavailable'
and MyAction.value == 'no action' %}
{% set myplayer = speaker.entity_id %}
{% set area = myplayer | replace('media_player.sonos_','') %}
{% set ingroup = namespace(value='no') %}
{% for mymember in state_attr(MasterSpeaker, 'group_members') %}
{% if loop.length > 1 %}
{% if mymember == myplayer %}
{% set ingroup.value = 'yes' %}
{% endif %}
{% endif %}
{% endfor %}
{% if states('input_boolean.multimedia_' + area + '_automusic') == 'on' and myplayer != MasterSpeaker and myplayer != 'media_player.sonos_bedroom' and state_attr(myplayer, 'media_title') != 'TV' and myplayer != 'media_player.sonos_terrace' %}
{% if states('sensor.' + area + '_occupied') == 'on' %}
{% if states(myplayer) == 'playing' %}
{% if ingroup.value == 'no' %}
{% set MyAction.value = myplayer + ' - stop' %}
{% endif %}
{% else %}
{% if states(MasterSpeaker) == 'playing' %}
{% set MyAction.value = myplayer + ' - join' %}
{% elif states(MasterSpeaker) != 'unknown' or states(MasterSpeaker) != 'unavailable' %}
{% set MyAction.value = MasterSpeaker + ' - play muted' %}
{% endif %}
{% endif %}
{% else %}
{% if states(myplayer) == 'playing' %}
{% set MyAction.value = myplayer + ' - leave' %}
{% endif %}
{% endif %}
{% elif states('input_boolean.multimedia_' + area + '_automusic') == 'on' and myplayer != MasterSpeaker and myplayer != 'media_player.sonos_bedroom' and state_attr(myplayer, 'media_title') != 'TV' and myplayer == 'media_player.sonos_terrace' and states('input_boolean.multimedia_terrace_override_occupied') == 'off' %}
{% if states('sensor.' + area + '_occupied') == 'on' %}
{% if states(myplayer) == 'playing' %}
{% if ingroup.value == 'no' %}
{% set MyAction.value = myplayer + ' - stop' %}
{% endif %}
{% else %}
{% if states(MasterSpeaker) == 'playing' %}
{% set MyAction.value = myplayer + ' - join' %}
{% elif states(MasterSpeaker) != 'unknown' or states(MasterSpeaker) != 'unavailable' %}
{% set MyAction.value = MasterSpeaker + ' - play muted' %}
{% endif %}
{% endif %}
{% else %}
{% if states(myplayer) == 'playing' %}
{% set MyAction.value = myplayer + ' - leave' %}
{% endif %}
{% endif %}
{% elif states('input_boolean.multimedia_' + area + '_automusic') == 'on' and myplayer != MasterSpeaker and myplayer != 'media_player.sonos_bedroom' and state_attr(myplayer, 'media_title') != 'TV' and myplayer == 'media_player.sonos_terrace' and states('input_boolean.multimedia_terrace_override_occupied') == 'on' %}
{% if states(myplayer) == 'playing' %}
{% if ingroup.value == 'no' %}
{% set MyAction.value = myplayer + ' - stop' %}
{% endif %}
{% else %}
{% if states(MasterSpeaker) == 'playing' %}
{% set MyAction.value = myplayer + ' - join' %}
{% elif states(MasterSpeaker) != 'unknown' or states(MasterSpeaker) != 'unavailable' %}
{% set MyAction.value = MasterSpeaker + ' - play muted' %}
{% endif %}
{% endif %}
{% elif myplayer == 'media_player.sonos_livingroom' and state_attr(myplayer, 'media_title') == 'TV' %}
{% if ingroup.value == 'yes' %}
{% set MyAction.value = myplayer + ' - leave' %}
{% endif %}
{% elif states('input_boolean.multimedia_' + area + '_automusic') == 'on' and myplayer == 'media_player.sonos_bedroom' %}
{% if states('sensor.' + area + '_occupied') == 'on' and (states('sensor.bedroom_sleeping') == 'off')
and (states('input_boolean.wake_mode') == 'off')
and (states('sensor.time_of_day') != 'night') %}
{% if states(myplayer) == 'playing' %}
{% if ingroup.value == 'no' %}
{% set MyAction.value = myplayer + ' - stop' %}
{% endif %}
{% else %}
{% if states(MasterSpeaker) == 'playing' %}
{% set MyAction.value = myplayer + ' - join' %}
{% elif states(MasterSpeaker) != 'unknown' or states(MasterSpeaker) != 'unavailable' %}
{% set MyAction.value = MasterSpeaker + ' - play muted' %}
{% endif %}
{% endif %}
{% else %}
{% if states(myplayer) == 'playing' %}
{% set MyAction.value = myplayer + ' - leave' %}
{% endif %}
{% endif %}
{% elif states('input_boolean.multimedia_' + area + '_automusic') == 'off' and myplayer != MasterSpeaker %}
{% if ingroup.value == 'yes' %}
{% set MyAction.value = myplayer + ' - leave' %}
{% endif %}
{% elif myplayer == MasterSpeaker %}
{% if states('input_boolean.multimedia_' + area + '_automusic') == 'on' and states('sensor.' + area + '_occupied') == 'on' and state_attr('media_player.sonos_livingroom', 'media_title') != 'TV' %}
{% if states(myplayer) == 'playing' and state_attr(MasterSpeaker, 'is_volume_muted') == true %}
{% set MyAction.value = myplayer + ' - unmute' %}
{% elif states(myplayer) != 'playing' %}
{% set MyAction.value = myplayer + ' - play' %}
{% endif %}
{% elif states('input_boolean.multimedia_' + area + '_automusic') == 'on' and states('sensor.' + area + '_occupied') == 'on' and state_attr('media_player.sonos_livingroom', 'media_title') == 'TV' and state_attr(MasterSpeaker, 'is_volume_muted') == false %}
{% set MyAction.value = myplayer + ' - mute' %}
{% elif states('input_boolean.multimedia_' + area + '_automusic') == 'on' and states('sensor.' + area + '_occupied') == 'off' %}
{% if states(myplayer) == 'playing' and state_attr(MasterSpeaker, 'is_volume_muted') == false %}
{% set MyAction.value = myplayer + ' - mute' %}
{% elif states(myplayer) == 'playing' and ingroup.value == 'no' and (TimeNow % 15 < 2) %}
{% set MyAction.value = myplayer + ' - stop' %}
{% endif %}
{% elif states('input_boolean.multimedia_' + area + '_automusic') == 'off' and ingroup.value == 'yes' and state_attr(MasterSpeaker, 'is_volume_muted') == false and states(myplayer) == 'playing' %}
{% set MyAction.value = myplayer + ' - mute' %}
{% elif states('input_boolean.multimedia_' + area + '_automusic') == 'off' and ingroup.value == 'no' and states(myplayer) == 'playing' and (TimeNow % 15 < 2) %}
{% set MyAction.value = myplayer + ' - stop' %}
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
{% endif %}
{% endif %}
{{ MyAction.value }}
multimedia_sonos_what_to_play:
friendly_name: Sonos What To Play
value_template: >
{% if states('sensor.time_of_day') == 'morning' %}
{{ states('input_text.multimedia_sonos_station_morning') }}
{% elif states('sensor.time_of_day') == 'day' %}
{{ states('input_text.multimedia_sonos_station_day') }}
{% elif states('sensor.time_of_day') == 'evening' %}
{{ states('input_text.multimedia_sonos_station_evening') }}
{% elif states('sensor.time_of_day') == 'night' %}
{% set CurrentTime = ((as_timestamp(now()) | timestamp_custom("%H:%M", default='00:00')).split(":")[0] | int(default=0))*60+(as_timestamp(now()) | timestamp_custom("%H:%M", default='00:00')).split(":")[1] | int(default=0) %}
{% set CurrentEndOfNight = (states('sensor.current_end_of_night').split(":")[0] | int(default=0))*60 + states('sensor.current_end_of_night').split(":")[1] | int(default=0) %}
{% set CurrentTimeH = as_timestamp(now()) | timestamp_custom("%H:%M", default='00:00') %}
{% set StartOfNight = states('sensor.calc_start_of_night') %}
{% if CurrentTime > CurrentEndOfNight - 120 and CurrentTimeH < StartOfNight %}
{{ states('input_text.multimedia_sonos_station_early_morning') }}
{% else %}
{{ states('input_text.multimedia_sonos_station_night') }}
{% endif %}
{% endif %}
script:
multimedia_sonos_stop:
alias: multimedia_sonos_stop
mode: queued
fields:
target_player:
description: Player you want to stop
example: media_player.sonos_livingroom
sequence:
- condition: template
value_template: >
{% if target_player is not none and target_player != false and target_player != '' %}
true
{% else %}
false
{% endif %}
- service: media_player.media_pause
data:
entity_id: >
{{ target_player }}
multimedia_sonos_leave:
alias: multimedia_sonos_leave
mode: queued
fields:
target_player:
description: Player you want to leave
example: media_player.sonos_livingroom
sequence:
- condition: template
value_template: >
{% if target_player is not none and target_player != false and target_player != '' %}
true
{% else %}
false
{% endif %}
- service: media_player.unjoin
data:
entity_id: >
{{ target_player }}
multimedia_sonos_join:
alias: multimedia_sonos_join
mode: queued
fields:
target_player:
description: Player you want to join in
example: media_player.sonos_livingroom
sequence:
- condition: template
value_template: >
{% if target_player is not none and target_player != false and target_player != '' %}
true
{% else %}
false
{% endif %}
- service: media_player.volume_set
data:
volume_level: >
{% set myvariable = 'input_number.multimedia_' + target_player | replace('media_player.','') + '_volume_' + states('sensor.time_of_day') %}{{ states(myvariable) }}
target:
entity_id: >
{{ target_player }}
- service: media_player.join
data_template:
group_members: >
{{ target_player }}
entity_id: "media_player.sonos_hallway"
multimedia_sonos_play:
alias: multimedia_sonos_play
mode: queued
fields:
target_player:
description: start playing
example: media_player.sonos_livingroom
sequence:
- service: media_player.shuffle_set
data:
shuffle: true
target:
entity_id: >
{{ target_player }}
- service: media_player.volume_set
data:
volume_level: >
{% set myvariable = 'input_number.multimedia_' + target_player | replace('media_player.','') + '_volume_' + states('sensor.time_of_day') %}{{ states(myvariable) }}
target:
entity_id: >
{{ target_player }}
- service: media_player.volume_mute
data:
is_volume_muted: false
target:
entity_id: >
{{ target_player }}
- service: media_player.select_source
data:
source: >
{{ states('sensor.multimedia_sonos_what_to_play') }}
target:
entity_id: >
{{ target_player }}
- service: media_player.media_play
data: {}
target:
entity_id: >
{{ target_player }}
multimedia_sonos_play_muted:
alias: multimedia_sonos_play_muted
mode: queued
fields:
target_player:
description: start playing
example: media_player.sonos_livingroom
sequence:
- service: media_player.shuffle_set
data:
shuffle: true
target:
entity_id: >
{{ target_player }}
- service: media_player.volume_set
data:
volume_level: >
{% set myvariable = 'input_number.multimedia_' + target_player | replace('media_player.','') + '_volume_' + states('sensor.time_of_day') %}{{ states(myvariable) }}
target:
entity_id: >
{{ target_player }}
- service: media_player.volume_mute
data:
is_volume_muted: true
target:
entity_id: >
{{ target_player }}
- service: media_player.select_source
data:
source: >
{{ states('sensor.multimedia_sonos_what_to_play') }}
target:
entity_id: >
{{ target_player }}
- service: media_player.media_play
data: {}
target:
entity_id: >
{{ target_player }}
multimedia_sonos_mute:
alias: multimedia_sonos_mute
mode: queued
fields:
target_player:
description: mute
example: media_player.sonos_livingroom
sequence:
- service: media_player.volume_mute
data:
is_volume_muted: true
target:
entity_id: >
{{ target_player }}
multimedia_sonos_unmute:
alias: multimedia_sonos_unmute
mode: queued
fields:
target_player:
description: mute
example: media_player.sonos_livingroom
sequence:
- service: media_player.volume_mute
data:
is_volume_muted: false
target:
entity_id: >
{{ target_player }}
automation:
- alias: multimedia_sonos_update_selected_play_station
description: ""
trigger:
- platform: state
entity_id:
- input_select.multimedia_sonos_stations_early_morning
- platform: state
entity_id:
- input_select.multimedia_sonos_stations_morning
- platform: state
entity_id:
- input_select.multimedia_sonos_stations_day
- platform: state
entity_id:
- input_select.multimedia_sonos_stations_evening
- platform: state
entity_id:
- input_select.multimedia_sonos_stations_night
condition:
- condition: template
value_template: "{{ trigger.to_state.state != ' ' }}"
action:
- service: input_text.set_value
data:
value: |
{{ trigger.to_state.state }}
target:
entity_id: >
input_text.{{ trigger.entity_id | replace('input_select.','') |
replace('stations','station') }}
mode: queued
max: 10
- alias: multimedia_sonos_instructions
description: ""
trigger:
- platform: time_pattern
minutes: /2
- platform: state
entity_id:
- sensor.multimedia_sonos_instruction
condition:
- condition: not
conditions:
- condition: state
entity_id: sensor.multimedia_sonos_instruction
state: no action
- condition: template
value_template: >
{{ states(states('sensor.multimedia_sonos_instruction').split(" - ")[0])
!= 'unavailable' }}
- condition: template
value_template: >
{{ states(states('sensor.multimedia_sonos_instruction').split(" - ")[0])
!= 'unknown' }}
- condition: state
entity_id: input_boolean.jarvis_announcement_wait
state: "off"
action:
- choose:
- conditions:
- condition: template
value_template: |
{{ 'join' in states('sensor.multimedia_sonos_instruction') }}
sequence:
- service: script.multimedia_sonos_join
data:
target_player: >
{{ states('sensor.multimedia_sonos_instruction').split(" - ")[0]
}}
- conditions:
- condition: template
value_template: |
{{ 'leave' in states('sensor.multimedia_sonos_instruction') }}
sequence:
- service: script.multimedia_sonos_leave
data:
target_player: >
{{ states('sensor.multimedia_sonos_instruction').split(" - ")[0]
}}
- conditions:
- condition: template
value_template: >
{{ states('sensor.multimedia_sonos_instruction').split(" - ")[1]
== 'play' }}
sequence:
- service: script.multimedia_sonos_play
data:
target_player: >
{{ states('sensor.multimedia_sonos_instruction').split(" - ")[0]
}}
- conditions:
- condition: template
value_template: >
{{ states('sensor.multimedia_sonos_instruction').split(" - ")[1]
== 'stop' }}
sequence:
- service: script.multimedia_sonos_stop
data:
target_player: >
{{ states('sensor.multimedia_sonos_instruction').split(" - ")[0]
}}
- conditions:
- condition: template
value_template: >
{{ states('sensor.multimedia_sonos_instruction').split(" - ")[1]
== 'play muted' }}
sequence:
- service: script.multimedia_sonos_play_muted
data:
target_player: >
{{ states('sensor.multimedia_sonos_instruction').split(" - ")[0]
}}
- conditions:
- condition: template
value_template: >
{{ states('sensor.multimedia_sonos_instruction').split(" - ")[1]
== 'mute' }}
sequence:
- service: script.multimedia_sonos_mute
data:
target_player: >
{{ states('sensor.multimedia_sonos_instruction').split(" - ")[0]
}}
- conditions:
- condition: template
value_template: >
{{ states('sensor.multimedia_sonos_instruction').split(" - ")[1]
== 'unmute' }}
sequence:
- service: script.multimedia_sonos_unmute
data:
target_player: >
{{ states('sensor.multimedia_sonos_instruction').split(" - ")[0]
}}
mode: queued
- alias: multimedia_sonos_change_music_time_of_day
description: ""
trigger:
- platform: state
entity_id:
- sensor.time_of_day
condition:
- condition: state
entity_id: media_player.sonos_hallway
state: playing
action:
- delay:
hours: 0
minutes: 5
seconds: 0
milliseconds: 0
- service: media_player.media_pause
data: {}
target:
entity_id: media_player.sonos_hallway
mode: single
- id: multimedia_sonos_playlist_update
alias: multimedia_sonos_playlist_update
description: ""
trigger:
- platform: state
entity_id: sensor.sonos_favorites
- platform: homeassistant
event: start
- platform: time_pattern
minutes: /1
condition: []
action:
- service: input_select.set_options
data:
options: |
{{ state_attr('sensor.sonos_favorites', 'items').values() | list + [' '] }}
target:
entity_id: input_select.multimedia_sonos_stations_day
- service: input_select.set_options
data:
options: |
{{ state_attr('sensor.sonos_favorites', 'items').values() | list + [' '] }}
target:
entity_id: input_select.multimedia_sonos_stations_morning
- service: input_select.set_options
data:
options: |
{{ state_attr('sensor.sonos_favorites', 'items').values() | list + [' '] }}
target:
entity_id: input_select.multimedia_sonos_stations_evening
- service: input_select.set_options
data:
options: |
{{ state_attr('sensor.sonos_favorites', 'items').values() | list + [' '] }}
target:
entity_id: input_select.multimedia_sonos_stations_early_morning
- service: input_select.set_options
data:
options: |
{{ state_attr('sensor.sonos_favorites', 'items').values() | list + [' '] }}
target:
entity_id: input_select.multimedia_sonos_stations_night
mode: single