I have a group of speakers setup in Google app. Then it will show up in HA with a volume control. Then when you get a new speaker add it to the group.
Google’s Groups do not work this way anymore since the sonos lawsuit I do not believe.
As far as I know since the Google / Sonos issue we are unable to set the volume on a Google speaker group.
As for making a HA group, I did this to send TTS and they were obviously not synchronised so I went back to calling TTS across the Google speaker groups and set volumes per entity like your example above. I cant say I ever tried to set volume via a HA group but in theory is would work but without any real benefit over calling them individually.
I personally just created 3 scenes, Daytime, Evening / Night and Important, all 3 scripts set the volumes per entity again like your above example with some set to different levels of volume based on location and or speaker size for example.
I then have an automation that sets them based on time of day and some automations that will capture there state, run the script to change them and revert them back if necessary, like important notices etc.
This is how I do it.
default:
- variables:
speakers: "{{ entity_id }}"
- repeat:
count: "{{ speakers | count }}"
sequence:
- variables:
speaker: "{{ speakers[repeat.index - 1] }}"
- service: script.turn_on
data:
variables:
volume_level: |-
{{( (states(speaker.replace('media_player.','input_number.')
~ '_volume')|default(0.5)|float(0.5)) - (quietfactor|float(0)) ) | float(0.5) }}
entity_id: "{{speaker}}"
target:
entity_id: script.media_player_volume_set_helper
With a helper:
alias: Media Player Volume Set Helper
sequence:
- service: media_player.volume_set
data:
volume_level: "{{ volume_level|default(\"0.5\", true) | float}}"
entity_id: "{{entity_id|default(\"no\", true)}}"
mode: parallel
fields:
volume_level:
description: volume_level to set
example: 0.5
entity_id:
description: entity_id
example: media_player.all_speakers
max: 10
Thank you for your reply @rossk
Thank you for responding to this part also. I can tell you know what I’m after because you’ve already been down the same road it sounds like.
So you think if I create a HA group with all of the speakers in it and then run the service for media player volume set, it will change the volume on all? This would be better than me calling out each individual speaker in each target area and would help with bypassing the google/ sonos spat.
Yeah, this is exactly what I’m after. Something like this. So you set yours on a per entity basis also. Hmmm.
Would you possibly share your 3 scripts and an example of how you are using the automation you speak of when you get time.
Your definitely doing what I’m after essentially, I’m just trying to figure out the cleanest way to go about it. My HA instance feels like such a mess sometimes.
Thank you @rossk, @calisro, and @Arh for your responses here. All very helpful
@calisro Thank you so much for this and the help you have given me in past post. I will take a good look at it to ensure I understand it and very possibly use it to make mine better. I’m definitely not at your level of abilities but maybe one day. haha
You can use scenes. For my case, I use just a variable. Not hte best solution. Look at this:
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 %}"
- variables:
speakers: "{{ entity_id }}"
- repeat:
count: "{{ speakers | count }}"
sequence:
- variables:
speaker: "{{ speakers[repeat.index - 1] }}"
- service: script.turn_on
data:
variables:
volume_level: |-
{{( (states(speaker.replace('media_player.','input_number.')
~ '_volume')|default(0.5)|float(0.5)) - (quietfactor|float(0)) ) | float(0.5) }}
entity_id: "{{speaker}}"
target:
entity_id: script.media_player_volume_set_helper
mode: restart
fields:
entity_id:
description: The entity(s) to broadcast to
example: media_player.back_office_speaker
The quiet factor is just subtracted from the ‘normal’ volume each time i set. I call this script each time I tts broadcast.
So I set the time when I’d like the tts announcement to be ‘softer’. and I subtract 10% from the volume during those times when I broadcast via the script. It works for me. I store all the ‘standard’ volumes per each google home in a input_number so that they always stay at that volume even after my kids adjust theirs when listiening to music. Its all very clumbsy but Google made it this way and its worse since the Sonos suit.
I have HA groups setup as mirrors of my google groups. So when I pass in what I am broadcasting to, it acts on the inidividual devices. You can see the ‘replace’ functions there.
If you get time, would you help me understand how all of your code is working, you are much more advanced than I am with this stuff.
I don’t really follow what all this is doing at all. replace?, default?, float?, quietfactor?
What is this thing doing?
Oh geeze, I have no clue what some of this is doing. Are those templates? Can you explain what is going on there when you have time.
Also “fields:”, “max:”, I’ve never seen that used before.
You’re making me feel like such a failure. lol
- 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 %}"
This is the amount by which I will decrease the normal volume by during the time outside of the ‘quiet’ window.
- variables:
speakers: "{{ entity_id }}"
This is a variable that holds the entity id(s) passed to teh script.
- repeat:
count: "{{ speakers | count }}"
This just means repeat the below action for each entity_id defined in the ‘speakers’ variable.
sequence:
- variables:
speaker: "{{ speakers[repeat.index - 1] }}"
This is just part of the loop. Moving to the next speaker in the passed set.
- service: script.turn_on
data:
variables:
volume_level: |-
{{( (states(speaker.replace('media_player.','input_number.')
~ '_volume')|default(0.5)|float(0.5)) - (quietfactor|float(0)) ) | float(0.5) }}
entity_id: "{{speaker}}"
target:
entity_id: script.media_player_volume_set_helper
This called the helper script to adjust the volume for the ONE speaker. I do this in a script just so I can use the ‘turn_on’ service so the calling script does not wait. Helps it do it faster across all my google homes.
This is how you pass variables to a script from a calling script/service. See here:
@calisro Thank you so much for explaining all of this because I know it takes time. I really do appreciate it.
My God though. You must be a programmer for a living. haha
I’m done. I should’ve paid more attention in school in my programming classes. hahaha.
I will take some time over the next little bit to understand all of this and I may come back in the next few days with some followups.
Thank you again for giving me a thorough understanding of my options and another possible approach I can take on this concept.
So you said, you have mirrored your google home groups to home assistant groups. If you send a volume set service call to that HA group, does it work? Or am I completely off base and mixing concepts that don’t go together?
Yes you can call the group directly. I choose not to do that because I needed it to be flexible to set the volumes differently for each speaker in the groups or individually.
Yeah, I was thinking about that also. I’m sure what you’ve shown me will probably be my end approach. My stop gap will probably be what you just said because of the shortcoming that you/ I picked up on immediately.
Rob, thank you again for helping me understand this stuff. The water can get deep fast I’ve learned.
If you’re interested, you can reduce this:
- 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 %}"
to this:
- variables:
quiet: "{{ now() > today_at('20:00') or now() < today_at('08:00') }}"
quietfactor: "{{ iif(quiet, 0.1, 0) }}"
EDIT
Another way to write this:
{{ now() > today_at('20:00') or now() < today_at('08:00') }}
is this:
{{ not today_at('08:00') < now() < today_at('20:00') }}
but it’s a bit less intuitive (because it refers to the time period that’s not “quiet”).
@123 I honestly love when you chime in and shorten these yamls. I learn a lot. Thanks for that!
@wtstreetglow
If you want to set it for all of your speakers of a certain integration you could use the following:
{{(expand(integration_entities("sonos"))|selectattr("domain","in","media_player")|map(attribute="entity_id")|list)}}
or when you need the device_ids:
{%set speakers = namespace(device_id=[])%}
{%for e in (expand(integration_entities("sonos"))|selectattr("domain","in","media_player")|map(attribute="entity_id")|list)%}
{%set speakers.device_id=speakers.device_id+[device_id(e)]%}
{%endfor%}
{{speakers.device_id}}
If you’re interested, the first template can be reduced to this:
{{ integration_entities('sonos') | select('match', 'media_player') | list }}
and the second one to this:
{{ integration_entities('sonos') | select('match', 'media_player')
| map('device_id') | list }}
@Grumblezz This is great. Thank you for adding this to the conversation. Very valuable. That was one of my issues also. I just was getting the low hanging fruit first and because I’m not super advanced with this stuff.
I can already see an issue in the future of a volume of 0.6 being much louder with sonos that a volume of 0.6 with the google home mini (and I guess, this issue would exist between devices also, not just manufacturer). I was hoping to work towards some type of volume “normalization” somehow at some point. Essentially, I have all of these ideas but not the capabilities to do them yet. haha.
Thank you for this @123 I have no doubt I will use some of these ideas in the next little bit. You all are so much more advanced than I am. **sigh
Again, thank you for all of the help you have given me currently and in the past. I am very happy with HA. It makes so many other systems look so bad. But it is also extremely complex.
It’s a shame Google didn’t fight back about that lawsuit with Sonos Sonos didn’t invent the concept of "Master’ volume. It’s been around as far back as I can remember.
I think it takes intellectual property just a bit too far. Or Google just didn’t feel like dealing with it with Sonos.