Understanding code using Template variable

Hi folks,
Appreicaite if anyone can help me fixing tiny error (i guess) in the code. I have group.all_lights with three entities.

All_Lights:
  entities:
    - light.tz3000_oex7egmt_ts0001_9e1379d2_on_off
    - light.kitchen_lights
    - light.tz3000_el5kt5im_ts0502a_b196d9fe_level_light_color_on_off

I am using following code from CCOSTAN . The issue is that i get UndefinedError: list object has no element 1 error with the following code.

    {% if states.group.all_lights.state != 'off' -%}
      There are
  {% for state in states.light if state.state == 'on' -%}
      {%- if loop.last -%}
      {{ loop.index }}
      {%- endif -%}
  {%- endfor %}
  lights on right now.
  {% set comma = joiner(', ') %}
  The
  {% for group in states.group|groupby('state') -%}
      {%- for entity in group.list if entity.state == 'on'
      and entity.name.split(' ')[1]|lower == 'lights'
      and entity.name.split(' ')[0]|lower != 'all'
      and entity.name.split(' ')[0]|lower != 'interior'
      -%}
      {{ 'and' if loop.last and not loop.first else comma() }}
      {{ entity.name|replace('lights','')}}
      {%- endfor -%}
  {%- endfor -%}
  lights are on.
  {%- endif -%}

when i change from entity.name.split(' ')[1]|lower == 'lights' to entity.name.split(' ')[0]|lower == 'lights', i get following message.

There are
  1
  lights on right now.
  
  The
  lights are on.

with this change, i can see code is working but it is not returning entity name … just The xx lights are on so it looks like issue with entity.name.split(' ')[1]|lower line in the code. would anyone advise what this statement needs to be changed to please so that i can see what light is on the group please.

thank you very mcuh in advance…

I mean the only bug I see is in the if statement for the inner for loop you do this:

entity.name.split(' ')[1]|lower == 'lights'

But then in the code of the loop you do this:

entity.name|replace('lights','')

and don’t lowercase it. So if lower actually did change the case of lights then the replace wouldn’t work. But that’s not going to going to cause nothing to show up it just might make lights show up unexpectedly. Your entire template is reliant on friendly name matching a specific string pattern though so you might have to show some of your group entities that you think should be showing to help debug.

Also as an aside that template can be shortened a lot. Pretty sure you can eliminate all those for loops in favor of native jinja filters. I believe something like this should do the same thing:

{% if states.group.all_lights.state != 'off' -%}
  There are {{ states.light | selectattr('state', 'eq', 'on') | list | count }} lights on right now.
  {% set on_groups = states.group | selectattr('state', 'eq', 'on') | map(attribute='name')
            | reject('search', '(?i)^(all|interior)') | select('search', '(?i)[^ ]+ lights') | list %}
  The
  {% if on_groups | count > 1 %}
    {{ on_groups[:-1] | join(', ') }} and {{ on_groups[-1] }}
  {% else %}
    {{ on_groups[0] }}
  {% endif %}
  lights are on
{% endif %}

Actually realizing something else, in your group config you have this:

You’re aware that your capitalization in All_Lights does nothing right? If you changed that to all_lights nothing would be different. That only sets the entity ID (which is always lowercase), it does not set the friendly name. To set the friendly name for an old-style group you set name like this:

all_lights:
  name: All lights
  entities:
    - light.tz3000_oex7egmt_ts0001_9e1379d2_on_off
    - light.kitchen_lights
    - light.tz3000_el5kt5im_ts0502a_b196d9fe_level_light_color_on_off

I bring this up because your template is completely dependent on the friendly name being set to an exact pattern for it to work. The name of this “all lights” group may not matter but make sure you are setting it correctly in your other groups.

Sorry can you clarify? When you say “I am still getting the same error” do you mean the lack of results? Or are you seeing an error in the log?

Also when do you see that undefined error?

:man_facepalming: Shoot I forgot to close a string. I edited my post above and corrected the template if you want to try it again.

This is a version without loop:


      {% set lights = expand('group.all_lights') |list %}
      {% set on = lights |selectattr('state', 'eq', 'on') |map(attribute='name') |list %}

      {% if on |count > 0 %} There {{'is' if on |count ==1 else 'are'}} {{ on |count }} light{{'' if on |count==1 else 's'}} on right now:
      {{ on |join(', ') }}
      {% else %} All lights are off
      {% endif %}

EDIT: added singular and plural

1 Like

You’re assuming you can expand group.all_lights and get the info the author wants. They said their config for all lights is this:

But in the second part of that template where they lost out what lights are on they loop over states.group. Since all lights doesn’t have any groups that suggests two problems with using expand like that:

  1. There are no groups in all lights. So if all lights is true then they are looping over a different list, expand won’t get that.
  2. even if all lights does include those groups, expand expands recursively. So that will tell them which individual lights are on, they appear to want to know which groups are on.

I thought about using expand as something like that makes it easier. But didn’t seem to work with what they showed

It seems to me that the OP copied the initial code 1:1 from CCOSTAN without changings. Thus I’m not sure if an extended cod is needed at all.

Thank you very much for reply. I was hoping to keep the oringinal code for my own learning where possible. CCostan mentioned he havenot updated his HA instance since 2021 Dec so not sure what changes HA instroduced since then. Secondly, code seems to be working but failed to return the light whcih is on (second part in the code) so not sure what is breaking the code :frowning:

IMHO this cannot work because he had listed light groups. You, on the other hand, want to know which lamps of a single group are on.

This looks like a light. Is “all lights” a light group or an old-style group? Like what is it’s entity id, group.all_lights or light.all_lights? Because it looks like you made light groups not groups in which case you’re simply looking at the wrong domain.

yes, i am a novice learner so not sure what i need to change in the code to make it work? I am just trying to copy the author as i am learning step by step using his setup. thanks

If you absolutely want to use the original code, I would adapt it as follows:


{% if states.group.all_lights.state != 'off' -%}
      There are
  {% for state in expand('group.all_lights') if state.state == 'on' -%}
      {%- if loop.last -%}
      {{ loop.index }}
      {%- endif -%}
  {%- endfor %}
  lights on right now.
  {% set comma = joiner(', ') %}
  The
  {% for entity in expand('group.all_lights') -%}
      {{ ' and' if loop.last and not loop.first else comma() }}
      {{ entity.name }}
  {%- endfor -%}
  lights are on.
  {%- endif -%}

Thanks, I will close this post and have learned few things… really appreciate both your help. All codes shared prevoulsy now working… Thank you once again… key thing is the way the groups are defined in the groups.yaml :slight_smile:

The original code is outdated and there are now simpler, better ways of reporting which lights are on (several examples have already been presented and more can be found here and here). So unless you only want to use old-fashioned techniques, I suggest you consider using the most efficient modern ways of achieving your goal.

1 Like