Template to generate string of entity_ids with low battery. Only include entities ending in "battery_level"

Great :grinning: thanks very much :+1:

{% set ns = namespace(below=[]) %}
{% for s in states.sensor 
   if s.entity_id.endswith('battery_level') and s.state != 'unknown' and s.state|int < 20 %}
{% set ns.below = ns.below + [s.entity_id] %}
{% endfor %}
{{ ns.below | reject('in', ['sensor.person1_phone_battery_level', 'sensor.person2_phone_battery_level'] ) | join(', ') }}
1 Like

FYI

Should you ever want to search for entities whose names contain battery_level and not just at the end of their name, you can use the recently introduced search and match functions.

Templating - Home Assistant (home-assistant.io)

REGULAR EXPRESSIONS

  • Test string is match(find, ignorecase=False) will match the find expression at the beginning of the string using regex.
  • Test string is search(find, ignorecase=True) will match the find expression anywhere in the string using regex.

I like the idea of the new tests, but I’m struggling with the syntax for actually using them. I thought that they’d be in the argument to a select() filter, but I can’t work out what it would look like. Have you been able to make either work?

Nevermind, figured it out after reviewing this thread.

In my humble opinion, the text in the documentation isn’t really enough to put it to use. I ended up with something like this:

{{ states|selectattr('entity_id', "search", "fr_")|map(attribute="entity_id")|join(",") }}

1 Like

I’ve used it, but not like that.

How have you used it? I’m curious if/where “string is match(find, ignorecase=False)” can actually be used somewhere.

Sorry, I wasn’t clear. I have used it the way you have as a Jinja2 test. I have not used it the way it is shown in the documentation. However, that way also works (but might not be the most common usage).

Thanks, I can see where that might be useful. I hadn’t thought of that, but it’s the most straightforward interpretation of the docs.

hello every, i would link to ask if there is a way to simplify the code below, most of the code have the same code, but i cannot figure it out.
@circa1665 @Troon @rccoleman

{% set ns = namespace(below=[]) %}


{% for s in states.light %}
{% if 'kitchen' in s.entity_id and not s.entity_id.endswith('indicator_led')  %}
{% set ns.below = ns.below + [s.entity_id] %}
{%- endif %}
{% endfor %}


{% for s in states.switch %}
{% if 'kitchen' in s.entity_id  %}
{% set ns.below = ns.below + [s.entity_id] %}
{%- endif %}
{% endfor %}

{% for s in states.fan %}
{% if 'kitchen' in s.entity_id  %}
{% set ns.below = ns.below + [s.entity_id] %}
{%- endif %}
{% endfor %}


{{ ns.below | reject('in', ['switch.horace_pc'] ) |join(', ') }}

Please don’t tag everyone in the thread. The second and third are easy and could use exactly the same syntax from here. The first could use something like this:

{{ states.light|selectattr("entity_id", "search", "kitchen")|rejectattr("entity_id", "search", ".*indicator_led$")|map(attribute="entity_id")|list }}

To put it all together, do something like this:

{% set lights = states.light|selectattr("entity_id", "search", "kitchen")|rejectattr("entity_id", "search", ".*indicator_led$")|map(attribute="entity_id")|list %}
{% set switches = states.switch|selectattr('entity_id', "search", "kitchen")|map(attribute="entity_id")|reject("eq", "switch.horace_pc")|list %}
{% set fans = states.fan|selectattr('entity_id', "search", "kitchen")|map(attribute="entity_id")|list %}
{{ lights+switches+fans|join(', ') }}
1 Like

thank you for reply, but it show an error message "TypeError: can only concatenate list (not "str") to list" text

it seem i cannot use + to print the output.

{{ lights+switches+fans|join(', ') }}

it can print out the result of

{{ lights | join(', ') }}

and aslo can print out the result of

{{ switches | join(', ') }}

but once i use + to print out all the result it shows this error.

Firstly, you have an errant “smart quote” in your join statement, although given the error message, I suspect that’s due to copying it incorrectly.

This:

{{ lights+switches+fans|join(', ') }}

says to add together:

  • the lights list
  • the switches list
  • the string output of fans|join(', ')

which is why you’re getting the error. Try:

{{ (lights+switches+fans)|join(', ') }}
1 Like

Thank you so much after i put the ( ) outside lights+switches+fans it success. You save my day man, thank you again!!!

It gets simpler if you use expand like this:

{{ expand(states.light, states.switch, states.fan)
    | selectattr("entity_id", "search", "kitchen")
    | rejectattr("entity_id", "search", ".*indicator_led$")
    | map(attribute="entity_id")
    | reject("eq", "switch.horace_pc")
    | list | join(", ") }}

Good catches, thanks! It’s always the last minute tweaks that get me!

{{ expand(states.light, states.switch, states.fan)
    | selectattr("entity_id", "search", "("kitchen","bedroom")")
    | rejectattr("entity_id", "search", ".*indicator_led$")
    | map(attribute="entity_id")
    | reject("eq", "switch.horace_pc")
    | list | join(", ") }}

hello, what if i wanna do something like “(“kitchen”,“bedroom”)” ??? selectattr or rejectattr the stringA & stringB & stringC included in the entity name? thanks a lot

{{ expand(states.light, states.switch, states.fan)
    | selectattr("entity_id", "search", "kitchen|bedroom")
    | rejectattr("entity_id", "search", ".*indicator_led$")
    | map(attribute="entity_id")
    | reject("eq", "switch.horace_pc")
    | list | join(", ") }}

If i do it like this than if will only shows bedroom’s result without kitchen

It works for me.

oh, thank you. i realize i typed “light|spotlight” for test. may be that’s problem!! thank you again

Maybe you should try this

{%- for s in states.sensor | selectattr('attributes.device_class', '==',
        'battery') if is_number(s.state) and s.state|int < 25
          %}
          {{s.entity_id}}{% if not loop.last %}, {% endif %}
        {%- endfor %}
1 Like