Automation array for sensors

Needing some ideas on how to achieve an outcome. I am wanting my template to loop through a defined array and I then use the temp and last_changed states to trigger automation. I have been able to get the temp but have not been able to figure out how to get the last_changed value. My current code is below. Or am I thinking about this wrong and need to do nested statements to loop through all sensors and the array and have it filter out the ones in the array? The reason for wanting to do it this way is so I can quickly filter out a sensor that might be having issues until it is fixed and not always get an alert on it every x min. - Thanks

{% set sensors = ['sensor.freezer_one_temperature','sensor.freezer_two_temperature','sensor.freezer_four_temperature',
'sensor.freezer_five_temperature','sensor.freezer_six_temperature','sensor.freezer_seven_temperature'] %}
{%- for s in sensors -%}
{{ s + states(s) }}
{%- if states(s) | int>=0 and states(s) == 'unknown' -%}
{% if loop.last %}
{% if loop.index > 0 %}
true
{% else %}
false
{% endif %}
{% endif %}
{% endif %}  
{% endfor %}

I thought about this some more and did come up with a solution and posting it here in case someone else runs across this looking for a similar idea. I went away from the array to exclude the sensors I did not want to see.

{# Get All Sensors #}
{%-for s in states.sensor-%}
{# Exclude sensors #}
{%- if 'Three' not in s.name and 'Eight' not in s.name and 'SI7021' not in s.name and 'DS18B20' not in s.name and 'Temperature' in s.name and s.name.startswith('Freezer') -%}
{%- if (s.state | int>= 24 and s.state == 'unknown' or (as_timestamp(now())-as_timestamp(s.last_changed)) > 1200) == 1 -%}
{% if loop.index > 0 %}
true
{% else %}
false
{% endif %}
{%-endif-%}
{%-endif-%}
{%-endfor%}
2 Likes

Whatever it is that you are trying to do is unclear. The two examples you posted achieve completely different things so it’s hard to guess what is your goal.

If you can explain what you want to achieve, we can help you write a clean, compact template because the two examples you posted are, respectfully, rather awkward.

For example, if an entity’s state value is unknown then this is sufficient to confirm it:

states(s) == 'unknown'

However, your template does this strange and unnecessary thing:

states(s) | int>=0 and states(s) == 'unknown'

If the value is unknown then the int filter will report an implicit default value of 0 (but not in the next version of Home Assistant when it will be reported as an error because default values must be explicitly specified) and 0 >= 0 evaluates to true. However, that’s unnecessary because states(s) == 'unknown' already neatly performs the same test.

Anyway, that’s just one observation; there are several other peculiarities in that template.

If the goal of the first example is to report true if any of the sensor values is unavailable (otherwise report false) then this can do that:

{% set sensors = ['sensor.freezer_one_temperature','sensor.freezer_two_temperature','sensor.freezer_four_temperature',
'sensor.freezer_five_temperature','sensor.freezer_six_temperature','sensor.freezer_seven_temperature'] %}
{{ expand(sensors) | selectattr('state', 'eq', 'unavailable') | list | count > 0 }}

Thanks, @123, your response did answer my question.

That’s interesting because the only question in your first post is this one:

The answer to that question is “Yes, you are thinking about this wrong.” There’s no need for nested statements (not even a for-loop).


Perhaps you can explain how this can ever be a value equal to 1

{%- if (s.state | int>= 24 and s.state == 'unknown' or (as_timestamp(now())-as_timestamp(s.last_changed)) > 1200) == 1 -%}

Nothing on the left hand side of the equality symbol, ==, produces an integer value. EDIT I overlooked to consider that in python a boolean True and False are equivalent to integer 1 and 0.

I have re-read the first post and would agree it is unclear but was trying to find out how to expand the senors to be able to get all of the fields that are were returned. Also agree it is ugly code but it works and gives me what I need.

But to answer your question. Anytime one of those conditions is met it will equal one. Which is when I want the alert sent. So good sensors return 0 and bad return 1. So if the temp is over 24 or has a state of unknown or if the sensor has not reported in the amount of time it returns 1. This then will trigger the automation and send me the notification.

Good sensors
image

Bad sensors to receive an alert when it equals 1
image

I described as being awkward but I won’t disagree with you.

That’s not entirely correct. The result of each one of those tests is a boolean value, namely True or False (see examples below).

Admittedly, what I failed to consider in my previous statement is that, in python, boolean True and False are equivalent to integer 1 and 0. Therefore the equality test will indeed work. However, it’s superfluous because the if only needs a boolean true or false result.

Consider using Jinja2’s selectattr and rejectattr filters to include/exclude entities instead of employing a for-loop with a long-winded if like this:

{%- if 'Three' not in s.name and 'Eight' not in s.name and 'SI7021' not in s.name and 'DS18B20' not in s.name and 'Temperature' in s.name and s.name.startswith('Freezer') -%}

For example, this performs the same function as that line but without a for-loop

{{ states.sensor
  | selectattr('object_id', 'match', 'Freezer')
  | selectattr('object_id', 'search', 'Temperature')
  | rejectattr('object_id', 'search', 'Three|Eight|SI7021|DS18B20')
  | list }}

Additional filters can be used to select entities based on other criteria.