Templating and Appending Lists

I am attempting to create a template that synchronizes the volumes of all of my smart speakers to the lowest volume speaker and I have 2 questions.

  1. How do I successfully append items to a list? The code I have is below, however, I cant seem to return a list of values. I’m wondering if the if-statement is creating a local variable and my “volume_level” list is being treated as a global. IDK what the issue is.
{%set volume_level = []%}
{% set speaker_list =
[
"media_player.google_nestmini_office",
"media_player.google_home_bedroom",
"media_player.google_nesthub_living_room",
"media_player.google_nestmini_kitchen"
]
%}
{%for speaker in speaker_list %}
    {%if state_attr(speaker, "volume_level") is float%}
        {% set volume_level = volume_level + [state_attr(speaker, "volume_level")]%}
    {%endif%}
{%endfor%}
{{min(volume_level)}}
  1. How do I implement this in an automation? Do I just add the keyword “value_template” where I would normally put a media_player volume?

Any help would be great. Thanks!

My understanding is that using the built-in filters is more effiicient than using a loop:

set speaker_list =
[
"media_player.google_nestmini_office",
"media_player.google_home_bedroom",
"media_player.google_nesthub_living_room",
"media_player.google_nestmini_kitchen"
]
%}
{{ expand(speaker_list) | rejectattr('attributes.volume_level','in', ['', 'null']) | map(attribute='attributes.volume_level') | min }}

But if you really want to use a loop you need to use namespace() to get data out of a loop:

set speaker_list =
[
"media_player.google_nestmini_office",
"media_player.google_home_bedroom",
"media_player.google_nesthub_living_room",
"media_player.google_nestmini_kitchen"
]
%}
{% set ns = namespace(volume_level=[])%}
{%for speaker in speaker_list %}
    {%if state_attr(speaker, "volume_level") is float%}
        {% set ns.volume_level = ns.volume_level + [state_attr(speaker, "volume_level")]%}
    {%endif%}
{%endfor%}
{{min(ns.volume_level)}}

EDIT Updated template per Petro’s advise.

attributes won’t be those states, you can remove that

2 Likes

Thanks! I wasn’t able to get the built in filter to work, however, I did get the loop to work.
Do you know if there is a way to use this data in an automation action setting a media player’s volume? I just tried this with no luck.

action:
  - service: media_player.volume_set
    data:
      volume_level: 
        value_template:
            {%set speaker_list =
            [
            "media_player.google_nestmini_office",
            "media_player.google_home_bedroom",
            "media_player.google_nesthub_living_room",
            "media_player.google_nestmini_kitchen"
            ]
            %}
            {% set ns = namespace(volume_level=[])%}
            {%for speaker in speaker_list %}
                {%if state_attr(speaker, "volume_level") is float%}
                    {% set ns.volume_level = ns.volume_level + [state_attr(speaker, "volume_level")]%}
                {%endif%}
            {%endfor%}
            {{min(ns.volume_level)}}
    target:
      entity_id: media_player.google_home_bedroom

remove “value_template:”

and add “>” after “volume_level:”

action:
  - service: media_player.volume_set
    data:
      volume_level: >
        {%set speaker_list =
        [
            "media_player.google_nestmini_office",
            "media_player.google_home_bedroom",
            "media_player.google_nesthub_living_room",
            "media_player.google_nestmini_kitchen"
        ]
        %}
        {% set ns = namespace(volume_level=[])%}
        {%for speaker in speaker_list %}
          {%if state_attr(speaker, "volume_level") is float%}
            {% set ns.volume_level = ns.volume_level + [state_attr(speaker, "volume_level")]%}
          {%endif%}
        {%endfor%}
        {{min(ns.volume_level)}}
    target:
      entity_id: media_player.google_home_bedroom