Template triggered limiting outcome to "true" and "false" instead of comparing old and new state, causing automations such as counting number of "on" binary sensors by device class relying on template unable to function

Ref:

My existing template trigger is:

{{ states.binary_sensor | rejectattr('attributes.device_class', 'undefined') | selectattr('attributes.device_class', 'eq', 'moisture') | selectattr('state', 'eq', 'on') | map(attribute = 'name') | list | length > 0 }}

And this is not ideal because it will only trigger upon first moisture sensor state become “on”.
Ideally the template should trigger upon any result changes, compared by its value.

To maintain the backward compatibility I think the behavior should be opt-in only, meaning user can toggle on a checkbox indicating they want the trigger to compare the template outcome without converting them to Boolean values.

I was able to locate the corresponding code:
In: core/homeassistant/helpers/event.py at c3cd60e0cb66f2ddae5165d652b091cec2ed8b96 · home-assistant/core · GitHub the _template_changed_listener calls result_as_boolean in: core/homeassistant/helpers/template.py at c3cd60e0cb66f2ddae5165d652b091cec2ed8b96 · home-assistant/core · GitHub

It is not immediately clear to me why it is trying to convert the result to Boolean, my guesses are:

  1. Maybe it is to address unstable arrays that introduce confusion among users why a trigger may run although the array contains same set of elements.
  2. Maybe it is to address some objects that are not possible to be rendered into strings? However it should be obviously if the template failed to render.

My proposal is to add debugging info regarding old and new state and always render the outcome into string for comparison, which will be most obvious in most cases.

It will also be easier to implement as a simple string comparison can decide if a trigger needs to be fired.

I’m currently working on the change and would like some feedback from someone more knowledgeable, thank you.

Template triggers fire when their result changes from true to false. That’s how they work. This allows for the largest possible range of templates while keeping the trigger mechanism as simple as possible.

Your changes will be rejected as there is an alternative to what you want to do that does not mess with this.

Create a template sensor that counts the number of sensors that are on. i.e. remove the > 0 from your template.

Use this sensor in a state trigger with a null to: state. This will trigger on any state change of your sensor. You can exclude the change to 0 with a state condition.

How about allowing state trigger to work with value_template then?

Highly doubtful as it is not required.

After giving it a deeper thought I think it is a bit clearer now, the trigger only firing when the template evaluation change from false to true so it is working as a threshold, however in my use case it is expected to be used as a filter(precondition) so it should fire whenever the evaluation is true.

I think this two use cases are not interchangable.

I think Tom mis-typed… the template’s evaluation has to change from false to true for a Template trigger to fire.

1 Like

Thanks for pointing it out.