Add condition for trigger-based template sensors

The addition of trigger-based template sensors has greatly reduced the need for automations and helpers to parse data and make it easily accessible. In Discord, I often see that users want to define a condition where, if false, the state of the template sensor will remain unchanged. This is often the case when graphing values, where a periodic zero value is unwanted, and an availability template would result in discontinuities.

I see all kinds of syntax errors as users attempt to do it with something like this via a template:

- trigger:
    platform: state
    entity_id: input_text.test
  sensor:
    - name: test
      state: "{{ iif (trigger.to_state.state != 'unknown', trigger.to_state.state, states('sensor.test')) }}"

While it’s not a particularly difficult problem to solve, it’s not ideal for a fairly common task. First, since this isn’t supported in trigger-based template sensors, it unfortunately requires the use of states('sensor.test') to refer to the current value. Second, it requires some advanced templating that most users are not familiar with. Third, most users are unlikely to consider returning the current value of the sensor to leave the value unchanged, or to immediately know the syntax for doing so.

In contrast, adding a condition block similar to an automation would make it simpler, more intuitive, and more consistent with other flows in HA:

- trigger:
    platform: state
    entity_id: input_text.test
  condition:
    not:
      condition: state
      entity_id: input_text.test
      state: 'unknown'
  sensor:
    - name: test
      state: "{{ trigger.to_state.state }}"

The condition block would be evaluated exactly as others in Home Assistant, where if the entire block evaluates to false, the state of the resulting sensor remains unchanged. Since the sensor didn’t actually change state, a graph of its value wouldn’t be affected by the trigger.

Simple versions of this could be handled in the trigger with not_from: and not_to:, but that’s very limited compared to allowing for a condition block.

This makes sense, I like this. Although personally I would probably prefer that you could add conditions to triggers. Something like this:

trigger:
  platform: numeric_state
  entity_id: sensor.outlet_power
  above: 5
  condition:
    condition: state
    entity_id: binary_sensor.away
    state: 'off'

That way you don’t have to do things like this:

trigger:
  - id: power
    platform: numeric_state
    entity_id: sensor.outlet_power
    above: 5
  - ... Other triggers ...
condition:
  or:
    - not:
        condition: trigger
        id: power
    - condition: state
      entity_id: binary_sensor.away
      state: 'off'

Plus then it would work in trigger template sensors as well since they share the same triggers.

Also you would get less junk traces in automations. Usually if the trigger fires but the condition fails I don’t really want the trace clogging up the list personally.

4 Likes

Do the not_to and not_from options added in 2022.05 not work in trigger-based template sensors?

- trigger:
    platform: state
    entity_id: input_text.test
    not_to: 
      - 'unknown'
      - 'unavailable'
  sensor:
    - name: test
      state: "{{ trigger.to_state.state }}"
1 Like

I expect that they do, and I mentioned that at the end of my post. It would help for simple instances where you want to limit a trigger to anything other than a given set of states, but not if you want to combine multiple conditions or do something else more complex. Consider a case where you want to update the sensor value if the original sensor is not ‘unavailable’ or ‘unknown’ and is between 4 and 6:

- trigger:
    platform: state
    entity_id: input_text.test
    not_to: 
      - 'unknown'
      - 'unavailable'
  condition:
    - condition: numeric_state
      entity_id: input_text.test
      above: 4
      below: 6
  sensor:
    - name: test
      state: "{{ trigger.to_state.state }}"

The point being that conditions are much richer than triggers, and a common automation pattern is to trigger on anything you care about and filter in the condition. This extends that paradigm to template sensors.

- trigger:
    platform: state
    entity_id: input_text.test
  condition:
    - not:
        condition: state
        entity_id: input_text.test
        state:
          - 'unavailable'
          - 'unknown'
    - condition: numeric_state
      entity_id: input_text.test
      above: 4
      below: 6
  sensor:
    - name: test
      state: "{{ trigger.to_state.state }}"

I’m trying to add condition totrigger for some sensor, like the exemple on this post, but the result is:
property condition is not allowed

What am I doing wrong?
I am working within the templates.yaml file.
I cpiied the examples in this post, but that is the result.
I just can’t figure out

thanks
Stefano

Isn’t this an automation in the end?
OK, it’s much easier if you want to set values on a template sensor, so I like the idea, voted for that, but I don’t see this as reducing the number of automations… It is just moving the automations to another place (where an UI is not available)

It’s…a feature request. It doesn’t exist (yet).

The alternative would be to create helpers and use an automaton to set their value. A template sensor lets you calculate a value that can be used directly as its state.

Ok, tnks, it would be really helpful to have this functionality

I agree. I have been trying to create a sensor that keep track of the total energy used to charge an electric vehicle over time. The idea is to increase the sensor value with the difference in the car battery energy when it increases. The problem is that at startup, the triggered sensor should restore its previous value first before trigger gets fired. But it seems that the trigger gets fired before the sensor has recovered the previously stored value, so I am loosing it.

I believe I will have to use workaround with intermediate automation and helper to solve that. But it is less straightforward and add additional unnecessary states and triggers/workload on the system.

Having condition available in triggered sensor template, and ideally linked to the trigger itself as mentioned above, would be a better way to resolve that.

template:
  - sensor:
    - name: "ds7_battery_energy"
      unit_of_measurement: "kWh"
      state_class: measurement
      device_class: "energy_storage"
      state: > 
        {{ states('sensor.ds7_battery_level') | float / 100 * 13.2 }}
    
  - trigger:
    - platform: state
      entity_id: sensor.ds7_battery_energy        
      from:
    sensor:
      - name: "ds7_total_charge_energy"
        unit_of_measurement: "kWh"
        state_class: total
        device_class: "energy"
        state: >
          
          {% if has_value('trigger.to_state.state') and has_value('trigger.from_state.state') %}
              {% set delta_energy  = trigger.to_state.state|float - trigger.from_state.state|float %}
              {% if delta_energy > 0 %}
                {{ this + delta_energy }} 
              {% else %}
                 {{ this.state }} 
              {%- endif %}       
          {% else %}
             {{ this.state }} 
          {%- endif %}

An alternative for this could also be an update key like we already have the availability key.
The example given by Rob here could be written as:

- trigger:
    platform: state
    entity_id: input_text.test
  sensor:
    - name: test
      state: "{{ trigger.to_state.state }}"
      update: "{{ trigger.to_state.state not in ['unavailable', 'unknown'] and 4 < trigger.to_state.state | float(0) < 6 }}"

or using trigger variables

- trigger:
    platform: state
    entity_id: input_text.test
    variables:
      available: "{{ trigger.to_state.state not in ['unavailable', 'unknown'] }}"
      in_range: "{{  4 < trigger.to_state.state | float(0) < 6 }}"
  sensor:
    - name: test
      state: "{{ trigger.to_state.state }}"
      update: "{{ available and in_range }}"

This looks interesting and I’ve up voted the idea.
But referring to last post by @TheFes, what is the update: key in sensor?
Its not referred to here Template - Home Assistant

sensor:
    - name: test
      state: "{{ trigger.to_state.state }}"
      update: "{{ available and in_range }}"

It’s a feature request. We’re literally making things up :wink:

Just ran into a need for this. I want to update my sensor every 1 minute, but only under certain conditions. I can’t do it with jinja in the sensor section because source info is stored in various sensor attributes on trigger. I suppose I could conditionally store the source info based on my desired trigger conditions, but it’s an elaborate sensor already. Trigger conditions would be ideal. So upvoting.