Template to creat a dynamic entity_id list?

I’m hoping someone out there can put me out of my misery with this…

I want to, in a script, create a list of media players based on a similarly named set of input_booleans that are on.

The closest I can get is this:

entity_id: >
  {% for boolean in states.input_boolean if '_media_player' in boolean.entity_id %}
    {%- if is_state(boolean.entity_id, 'on') %}
      media_player.{{ boolean.entity_id.split('.')[1].split('_media_player')[0] }},
    {%- endif %}
  {%- endfor %}

Which does return a list but I can’t get rid of the training comma:

media_player.dining_room,
media_player.kitchen,

I also wonder if I need it all to be on one line?
I also tried with a leading - but the script then fails to recognise the entity_id as valid

- media_player.dining_room
- media_player.kitchen

And I thought my Python skills were improving :roll_eyes:
Any help appreciated. Thanks.

What are you trying to do with the list?
Not sure, but the problem is that the jinja output is always a string, not a list.

In a nutshell, I have one input_boolean for each Sonos.

When I do a Sonos Snapshot, Join or Unjoin I want the entity_id to be a list of those input_booleans that are 'on'.

I have successfully done this in other simpler cases by creating the list as a comma separated list and it does work e.g. (the script here is passed a variable room which is a list of room(s))

        entity_id: >
          {%- for x in room -%}
            input_boolean.{{ x }}_media_player{%- if not loop.last %},
            {%- endif %}
          {%- endfor -%}

but in the case in the OP I can’t find a way to remove the trailing comma.

Played a little :slightly_smiling_face:
The problem is that it loops over ALL booleans with ‘_media_player’ and prints ONLY the ones that are ‘on’.
So if the last boolean is not ‘on’, the last.loop will not work

Try:

{% for boolean in states.input_boolean if '_media_player' in boolean.entity_id and is_state(boolean.entity_id, 'on') %}
  media_player.{{ boolean.entity_id.split('.')[1].split('_media_player')[0] }}{%- if not loop.last %},{%- endif %}
{%- endfor %}
2 Likes

That’s great, Thanks!
I really appreciate it.

I use this template made with the help of @123

      media_players_active:
        friendly_name_template: >
          {% set count = states.input_boolean
            |selectattr('entity_id','in',state_attr('group.activate_media_players','entity_id'))
            |selectattr('state','eq','on')|list|length %} 
          {% set player = 'player' if count in [0,1] else 'players' %}
          {% set number = 'No' if count == 0 else count %} 
          {{number}} Media {{player}} active
        entity_id:
          - input_boolean.googlehome_woonkamer
          - input_boolean.googlehome_hall
          - input_boolean.googlehome_master_bedroom
          - input_boolean.googlehome_hobbykamer
          - input_boolean.googlehome_office
          - input_boolean.googlehome_dorm_marte
        value_template: >
          {% set rooms = states.input_boolean
            |selectattr('entity_id','in',state_attr('group.activate_media_players','entity_id'))
            |selectattr('state','eq','on') |map(attribute='object_id')|list %}
          {% set ns = namespace(speakers = '') %}
          {% for i in range(rooms | length) %}
            {% if states('input_boolean.' ~ rooms[i]) == 'on' %}
            {% set d = ', ' if ns.speakers | length > 0 else '' %}
            {% set ns.speakers = ns.speakers ~ d ~ 'media_player.' ~ rooms[i] %}
            {% endif %}
          {% endfor %}
          {% if ns.speakers|length|int == 0 %} None
          {% else %}
          {{ ns.speakers }}
          {% endif %}

but yours is way shorter and seems to render the same result :wink: I’ve adapted it to read:

{% for boolean in states.input_boolean if 'googlehome' in boolean.entity_id and is_state(boolean.entity_id, 'on') %}
  media_player.{{ boolean.entity_id.split('.')[1] }}{%- if not loop.last %},{%- endif %}
{%- endfor %}

and will test some further, to see what happens…of course, my template has a safeguard for 0 entities, where your template simply shows nothing?
nice to have more ways to do things :wink:

Yes it will show nothing but in my case there MUST be something. The script that uses it needs room to be passed to it from the calling automation so there will never (ha ha, yes, I know…) be no rooms.

… but not starting with the same data set. One iterates over the full set whereas the other over a subset (a group). Also, it won’t return ‘None’ if the list is empty (which, as I recall, was one of your requirements) but simply an empty string. Don’t overlook the fact the template I created wasn’t originally for your needs but for someone else (for announcing call to prayers) and was extended to meet your requirements (like ‘None’).

Nevertheless, this version is an elegant way of solving a very similar challenge. Kudos to @klogg and @VDRainer. I’ve bookmarked it for future reference.

sure, that’s what I mentioned in my response. It’s doing its job very nicely. Always keen to see if things can be made more efficient, and if adding a group as a subset can help, maybe I should do that also.

Noob here, just got a HA Green.

How do i get this script using the UI?