When does a state trigger trigger?

Hi,

suppose I’ve a state trigger which should trigger a template sensor like this:

template
  - trigger:
      - platform: state
        entity_id: sensor.strava_0_0
        attribute: sport_type
        to: "Ride"
    sensor:
      - name: ...

does this trigger also trigger, if the state of the sensor changes but the attribute changes from “Ride” to “Ride”?

It triggers exclusively when the value of the attribute sport_type changes from some value other than ‘Ride’ to ‘Ride’.

Reference: State Trigger

thanks.

Would this work?

The trigger should trigger, if…

  1. the state of the sensor changes
  2. the attribute sport_type == “Ride”

The idea is:

  1. the first line of the template accesses the state of sensor.strava_0_0, thus I’d believe the template triggers, if the state of sensor.strava_0_0 changes
  2. the second line compares the attribute with “Ride”
template
  - trigger:
      - platform: template
        value_template: >
          {% set dummy = states('sensor.strava_0_0') %}
          {{ state_attr('sensor.strava_0_0', 'sport_type') == 'Ride' }}
    sensor:
      - name: ...
template:
  - trigger:
      - platform: state
        entity_id: sensor.strava_0_0
        attribute: sport_type
        to: "Ride"
      - platform: state
        entity_id: sensor.strava_0_0
        to:
    sensor:
      - name: ...

Will work, without needing to write a template.

You can drop the first line with dummy, it adds nothing to this. You already access the state of sensor.strava_0_0 in this part of the template:

{{ state_attr('sensor.strava_0_0', 'sport_type') == 'Ride' }}

Therefore the template will evaluate any time the state of sensor.strava_0_0 changes. And it will evaluate to true if the sport_type attribute is Ride, regardless of the state.

However it still won’t work for a different reason. A template trigger only triggers when the template was evaluating to false and now evaluates to true. So if the state of sensor.strava_0_0 and sport_type == 'Ride' before and after then it won’t fire. The template was true before and true after.

No it won’t. Triggers are independent, they aren’t AND’ed. So that will fire anytime the state of sensor.strava_0_0 changes (including any attribute). It will also trigger again if the state change changed the value of the attribute sport_type from something other then Ride to Ride

Indeed @CentralCommand which this description led me to believe was the intended behaviour, since the very first post already achieves the attribute only triggering.

Edited the post to add the null to, so it only triggers on state changes and not attributes.

Honestly, I don’t think there’s a way to accomplish your use case purely within the trigger. I think you’d have to do something like this:

trigger:
  platform: state
  entity_id: sensor.strava_0_0
  to:
sensor:
  ...
  state: >
    {% if trigger.to_state.attributes.sport_type == 'Ride' %}
      {# set the state of the sensor from the trigger #}
    {% else %}
      {{ this.state }}
    {% endif %}

So basically you trigger anytime the state of the sensor changes. Don’t look at the attribute, you’re specifically watching for any change in the state value.

Then in the state template, if the attribute has the correct value set the state of the sensor as normal. If the attribute does not have the correct value then keep the state unchanged.

This would be a place where the condition from automation would be convenient. That’s how you’d handle this in an automation. Unfortunately trigger template sensors don’t have that.

No, it doesn’t.

Which is notably not the same as their use case:

As in when both of those are true. Not when one or the other is true.

In which case - a template trigger for

{{ states.sensor.strava_0_0.last_updated }}

might be a better idea?

But still running your code in the state of the sensor?

Or even better -

listen for the event:

- platform: event
  event_type: strava_data_update

Sure, but I replied to the first post which contained no use case, merely a question about the posted example’s behavior.

The OP’s second post appears to clarify what they actually wish to achieve (and I haven’t replied to that one).

I know. Just to clarify I was quoting you to explain the issue with the post I was replying to since you nicely explained what the trigger in the original post actually did. I wasn’t pointing out an issue with your post.

Fair enough.

Hopefully the OP will rejoin the conversation soon and clarify why they want the described behavior (ostensibly to trigger on state-changes and then check if an attribute is a desired value).

@CentralCommand thanks. I believe this should do what I want.
Essentially the ‘else’ should “do nothing” and not even update the sensor.
If a sensor returns the same value as before, does returning this.state then generate a new entry in history?

I hoped that I could do it somehow with ha builtin means, but maybe it’s simpler to do it with some sort of script, e.g. like in PythonScriptsPro. The script service would be called by an automation.

The python script service would be something like this:

strava_update:
  sequence:
  - service: python_script.exec
    data:
      title: update sensor only if sport_type == Ride
      source: |
        if hass.states.get('sensor.strava_0_0').attributes['sport_type'] == 'Ride':
          hass.states.set('sensor.my_new_sensor', some_calculated_value, {})

Like literally does it make a new row in the db? I have no idea. I stopped paying attention to the db after bdraco did all the db optimizations early in 2022. Since now I can’t make it big even if I wanted to (and I use this trick a lot on my own sensors for reference).

The UI won’t show a change in state. And triggers looking for a change in state won’t fire with the exception of maybe this one:

trigger:
  platform: state
  entity_id: sensor.my_new_sensor

I don’t know if last_changed gets a new value. If so this will fire even though nothing changed except last_changed. You’d have to test. This won’t though:

trigger:
  platform: state
  entity_id: sensor.my_new_sensor
  to:

Using hass.states.set has its own set of challenges:

  1. Device classes dont work since it’s not really a sensor despite it’s name (has to be created by an integration as a sensor to be one, the fact that your entity id includes sensor is irrelevant)
  2. Cannot make it a statistic and have the value stored in long-term storage. Will always be treated as a strong state in the normal history table
  3. Entity will not survive restarts. It simply won’t exist until the next state update following a restart.

Making entities and managing the state of entities via hass.states.set is really discouraged. It has tons of gotchas that will trip you up because it’s basically only supported for testing.

If you’re going to do this it would be better to use an input helper. Still not a sensor so has some of the challenges above but at least it will survive restart. But personally I’d use the trigger template sensor. And maybe vote for this and/or this. Since either would eliminate the need for template trickery here.