Actually, that will only produce a result on startup and never update itself again (until the next restart). The reason is because the template contains no identifiable entities.
On startup, Home Assistant examines the template and assigns a “listener” to each identifiable entity. The listener detects when the entity changes state and causes the template the be re-evaluated (refreshed/updated).
If it cannot find entities, it assigns no listeners, evaluates the template once to produce a result, and then never evaluates the template again (until the next restart).
A common way to mitigate the issue is to specify an entity that changes its state periodically. For example, sensor.time changes state every minute and sensor.date changes state at the beginning of every day (moments after midnight). So the following Template Sensor would be evaluated once a day (and this assumes you have already configured sensor.date):
The second issue is that the variable count will not report the correct value. That’s because variables inside a for-loop don’t retain their value outside the for-loop.
You can prove it to yourself by copy-pasting the following into the Template Editor:
{% set count = 0 %}
{%- for count in range(0,5) -%}
{%- set count = count+1 -%}
Inside the for-loop: {{ count }}
{% endfor %}
Outside the for-loop: {{count}}
If we combine everything I’ve described above, we get the following:
dehydrated_plants:
friendly_name: "Plants needing water"
entity_id: sensor.date
value_template: >-
{% set ns = namespace(count = 0) %}
{% for plant in states.plant if 'moisture low' in plant.attributes.problem %}
{% set ns.count = ns.count+1 %}
{% endfor %}
{{ns.count}}
Finally, to answer your original question, using a for-loop to calculate the total is the only way because there is no Jinja2 filter in Home Assistant that allows you to select entities based on a free-form sub-string match (i.e. match for sub-string ‘cat’ in string ‘bats cats hats’).
To be precise, there is a filter to match a sub-string but only if it is at the beginning (startswith) or end (endswith) of the string. So if you know for certain that ‘moisture low’ is always at the beginning of string then I might be able to create a simpler template (maybe). It’s not a filter but a string method so, nope.
EDIT
This is a bit of a kludge but if ‘moisture low’ is always at the beginning of the value in the problem attribute, you can try this (paste it into the Template Editor; you will obviously need some plant sensors to be reporting ‘moisture low’ to get meaningful results):
Actually, that will only produce a result on startup and never update itself again (until the next restart). The reason is because the template contains no identifiable entities.
Correct. I have automations that call homeassistant.update_entity to force the update when certain sensors update.
But it’s good to know that the reason why it doesn’t update is because of lack of identifiable entities! That was a problem in other sensors of mine. Adding entity_id: sensor.date is certainly cleaner, so I’ll play around with that.
The second issue is that the variable count will not report the correct value. That’s because variables inside a for-loop don’t retain their value outside the for-loop.
Ah! Yes, you’re right. I’m too used to languages with nested scoping support.
Thank you for the help and the corrected template. Glad (and annoyed) to hear that the for loop approach is the best you can do.