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.
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:
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.
{% 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 %}
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:
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.
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
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
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
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.