I use a combination of unclesbob’s and tts.google_cloud_say. Essentially I prefer tts.google_cloud_say but it will interrupt. So I wrote a script that will check if all the entities are busy or not. If they aren’t it will use tts.google_cloud_say. If they are, it will use a combination of this broadcast for the busy speakers and the normal tts.google_cloud_say for the non-busy ones. It also (mostly) defeats the wabamm sound it makes prior to broadcasting when speakers are idle at least. It depends on having groups named the same as speaker groups so I can expand them and check them separately and control the volume/mute separately since google had to remove the speaker group volume management). IT also relies on a set of input_numbers as ‘default’ volume’ settings per speaker to return its volume to.
alias: TTS No Interrupt
sequence:
- if:
- condition: template
value_template: |-
{% set entities = expand(target) %}
{% set ready = entities
| selectattr('state','in',('idle','off','unavailable','paused'))
| list | length %}
{% set hamedia = entities
| rejectattr('state','in',('idle','off','unavailable','paused'))
| selectattr("attributes.app_name", 'defined')
| selectattr('attributes.app_name','in',('Home Assistant Media Player','Home Assistant Lovelace Player','Default Media Receiver'))
| map(attribute='entity_id') | list | length %}
{{ (ready + hamedia) == (entities | list | length) }}
then:
- service: media_player.volume_set
data:
volume_level: 0.001
data_template:
entity_id: '{{ expand(target)| map(attribute=''entity_id'') | join('', '') }}'
- delay:
hours: 0
minutes: 0
seconds: 0
milliseconds: 300
- choose:
- conditions:
- condition: template
value_template: '{{media_content_id | length > 0 }}'
sequence:
- service: media_player.play_media
target:
entity_id: '{{target.replace(''group.'',''media_player.'')}}'
data:
media_content_id: '{{ media_content_id }}'
media_content_type: '{{ media_content_type }}'
metadata: {}
- conditions:
- condition: template
value_template: '{{ message | count > 0 }}'
sequence:
- service: script.turn_on
data:
variables:
message: '{{message|default(''One Test Message One'',true) }}'
entity_id: '{{target.replace(''group.'',''media_player.'')}}'
target:
entity_id: script.cloud_say
default: []
- if:
- condition: template
value_template: '{{volume | default(0) > 0 }}'
alias: Custom volume requested.
then:
- service: media_player.volume_set
data:
volume_level: '{{ volume | default(''0.5'') }}'
data_template:
entity_id: |-
{% if is_state('input_boolean.company','on') %}
{{ expand(target) | map(attribute='entity_id') | reject('==','media_player.back_office_speaker') | join(', ') }}
{% else %}
{{ expand(target)| map(attribute='entity_id') | join(', ') }}
{% endif %}
- delay: '{{ delay_to_stop | default(10) }}'
- service: script.media_player_volume_set
alias: Correct the volume after the custom volume delay.
data:
entity_id: |-
{% if is_state('input_boolean.company','on') %}
{{ (expand(target) | map(attribute='entity_id') | reject('==','media_player.back_office_speaker') | join(', ')).split(', ') }}
{% else %}
{{ (expand(target)| map(attribute='entity_id') | join(', ')).split(', ') }}
{% endif %}
- delay:
hours: 0
minutes: 0
seconds: 0
milliseconds: 200
- if:
- condition: template
value_template: |-
{{ expand('media_player.kitchen_display')
| rejectattr('state','in',('idle','off','unavailable','paused'))
| selectattr('attributes.app_name', 'defined')
| selectattr('attributes.app_name','in',('Home Assistant Media Player','Home Assistant Lovelace Player','Default Media Receiver'))
| list | count > 0
and 'media_player.kitchen_display' in expand(target) | map(attribute='entity_id') | join(', ') }}
- condition: template
value_template: '{{ stop_display | default(true) }}'
then:
- wait_for_trigger:
- platform: state
entity_id: media_player.kitchen_display
from: playing
to: idle
timeout: |-
{% if delay_to_stop | default(0) > 0 %}
1
{% else %}
{{ delay_to_stop | default(10) }}
{% endif %}
- service: media_player.turn_off
target:
entity_id: media_player.kitchen_display
data: {}
else:
- if:
- condition: template
value_template: '{{ expand(target) | count > 0 }}'
then:
- variables:
available: |-
{% set entities = expand(target) %}
{% set ready = entities
| rejectattr('state','in',('idle','off','unavailable','paused'))
| selectattr("attributes.app_name", 'defined')
| selectattr('attributes.app_name','in',('Home Assistant Media Player','Home Assistant Lovelace Player','Default Media Receiver'))
| map(attribute='entity_id')
| list %}
{% set haready = entities
| selectattr('state','in',('idle','off','unavailable','paused'))
| map(attribute='entity_id')
| list %}
{% if is_state('input_boolean.company','on') %}
{{ (haready + ready) | unique | reject('==','media_player.back_office_speaker') | list }}
{% else %}
{{ (haready + ready) | unique | list }}
{% endif %}
busy: |-
{% set entities = expand(target) %}
{% set busy = entities
| rejectattr('state','in',('idle','off','unavailable','paused'))
| selectattr("attributes.app_name", 'defined')
| rejectattr('attributes.app_name','in',('Home Assistant Media Player','Home Assistant Lovelace Player','Default Media Receiver'))
| map(attribute='entity_id')
| list %}
{% if is_state('input_boolean.company','on') %}
{{ busy | reject('==','media_player.back_office_speaker') | list }}
{% else %}
{{ busy }}
{% endif %}
- if:
- condition: template
value_template: '{{available|count > 0}}'
then:
- service: tts.google_cloud_say
data:
entity_id: '{{available}}'
message: '{{message|default("Test Message",true) }}'
- repeat:
count: '{{ busy | count }}'
sequence:
- variables:
speaker: '{{ busy[repeat.index - 1] }}'
- if:
- condition: template
value_template: '{{ message | length > 0 }}'
then:
- service: script.turn_on
data:
variables:
message: >-
broadcast to {{ state_attr('' ~
speaker,'friendly_name') }}, {{message|default('Test
Message',true) }}
target:
entity_id: script.run_ga_command
else:
- if:
- condition: template
value_template: '{{ message | length > 0 }}'
then:
- service: script.turn_on
data:
variables:
message: >-
broadcast to {{ state_attr('' ~ speaker,'friendly_name')
}}, {{message|default('Test Message',true) }}
target:
entity_id: script.run_ga_command
mode: parallel
fields:
message:
description: Message to send
example: This is a message
target:
description: The group/entity to broadcast to
example: group.downstairs_speakers
media_content_id:
description: The media to send
example: https://ha.xxxxxxxxxx.xx:8123/local/light-chime.wav
media_content_type:
description: The type of media
example: audio/mp3
stop_display:
description: Stop the display at the end
example: true
volume:
description: Specify target volume
example: 0.5
delay_to_stop:
description: The Delay to stop the Display
example: 15
max: 10
I essentially funnel ALL notifications through the script above.
helper scripts:
alias: Media Player Volume Set
sequence:
- variables:
quiet: >-
{% if now() >
now().replace(hour=20).replace(minute=0).replace(second=0).replace(microsecond=0)
or now() < now().replace(hour=8).replace(minute=0).replace(second=0).replace(microsecond=0) %}
true
{% else %}
false
{% endif %}
quietfactor: '{% if quiet == "true" %}0.1{% else%}0{% endif %}'
- choose:
- conditions:
- condition: template
value_template: '{{ entity_id[0].startswith(''input_number'') }}'
alias: used for manually setting the volume based on the set input number
sequence:
- service: media_player.volume_set
data:
volume_level: '{{states(entity_id[0])|default(0.5)|float}}'
entity_id: >-
{{entity_id[0].replace('input_number.','media_player.').replace('_volume','')
}}
default:
- variables:
speakers: '{{ entity_id }}'
- repeat:
count: '{{ speakers | count }}'
sequence:
- variables:
speaker: '{{ speakers[repeat.index - 1] }}'
- service: media_player.volume_set
data:
volume_level: |-
{{( (states(speaker.replace('media_player.','input_number.')
~ '_volume')|default(0.5)|float) - (quietfactor|float) ) | float }}
entity_id: '{{speaker}}'
mode: restart
fields:
entity_id:
description: The entity(s) to broadcast to
example: media_player.back_office_speaker
alias: Run GA Command
sequence:
- service: notify.ga_command
data:
message: '{{ message }}'
mode: parallel
fields:
message:
description: Message to send
example: This is a message
alias: Media Player Volume Set
sequence:
- variables:
quiet: >-
{% if now() >
now().replace(hour=20).replace(minute=0).replace(second=0).replace(microsecond=0)
or now() < now().replace(hour=8).replace(minute=0).replace(second=0).replace(microsecond=0) %}
true
{% else %}
false
{% endif %}
quietfactor: '{% if quiet == "true" %}0.1{% else%}0{% endif %}'
- choose:
- conditions:
- condition: template
value_template: '{{ entity_id[0].startswith(''input_number'') }}'
alias: used for manually setting the volume based on the set input number
sequence:
- service: media_player.volume_set
data:
volume_level: '{{states(entity_id[0])|default(0.5)|float}}'
entity_id: >-
{{entity_id[0].replace('input_number.','media_player.').replace('_volume','')
}}
default:
- variables:
speakers: '{{ entity_id }}'
- repeat:
count: '{{ speakers | count }}'
sequence:
- variables:
speaker: '{{ speakers[repeat.index - 1] }}'
- service: media_player.volume_set
data:
volume_level: |-
{{( (states(speaker.replace('media_player.','input_number.')
~ '_volume')|default(0.5)|float) - (quietfactor|float) ) | float }}
entity_id: '{{speaker}}'
mode: restart
fields:
entity_id:
description: The entity(s) to broadcast to
example: media_player.back_office_speaker