Iterate through a Group

Just doing some research on scripting and was curious about the following.

Let’s say I have a Group that has lights in it.

Is there a way to get the number of entity’s in that Group so that I could make loop to go through each of those lights? So if there were 5 lights that it could go through a loop 5 times?

In a template you can do that:

    {%- for entity_id in states.group.outside_doors.attributes.entity_id -%}
      {% set parts = entity_id.split('.') -%}
      {%- if states(entity_id) == 'on' %}
      {%- if loop.first %} {% elif loop.last %} and the {% else %}, the {% endif -%}{{ states[parts[0]][parts[1]].name }}{% endif -%}
    {%- endfor %}

That’s a template I use to walk all the entities in the outside doors group and list those that are open.

9 Likes

Awesome!

The only part I can’t seem to figure out is:

{% set parts = entity_id.split(’.’) -%}

What does entity_id.split(’.’) do?

It takes the entity_id and breaks it into an array, splitting on the . character.

Also checkout python script component

This is awesome! Thank you!

hey can you plz provide a full exmaple how/where you use this? I’m having a hard time to figure out how to use this…

Have a look here.

That automation is basically to send a notification if the doors are open when we’re away.

1 Like

Thanks. I figured it out yesterday with try and error. There is one issue though: what if there is only one device in the list? In this case loop.last is true at the first iteration and you get a " and device 1" message.

:man_shrugging: why iterate through a list of one? It should be pretty easy to address that, I’ve just never had to worry about it.

It is a list of more than one of course. but imagine a list of windows: you wanna check which one is open. so you iterate through the list and only on is state == open, thous you get only one loop iteration.

Say I have a group of entities A to D. When using your example, the loop first / last / else check always treats A as first regardless if it is in the list of open doors or not.

That is, if doors C and D are on, the loop check treats A as first, so output ends up being “, C and D” instead of “C and D”. But if doors open is A and D, output is as it should, that is “A and D”.

Perhaps I should make a new array, based on open doors instead of re-using entity_id?

Ah. Got it. (Still very much a beginner here.)

Instead of making another list, I’ll just have the check done early on; like this (row 1):

{%- for entity_id in states.group.outside_doors.attributes.entity_id if states(entity_id) == 'on' -%}
  {% set parts = entity_id.split(’.’) -%}
  {%- if loop.first %} {% elif loop.last %} and the {% else %}, the {% endif -%}{{ states[parts[0]][parts[1]].name }}
{%- endfor %}

That way, I will get the expected behaviour. If doors = A, B, C, D and open doors = C, D. Then instead of first in list entity_id always being the first door (A, in my example), now the first list entity_id is the first open door (ie. C). Output thus being “C and D” instead of “, C and D”.

2 Likes