Maintaining .last_changed through restart & YAML reload

There are several suggestions elsewhere that replicating a sensor with a trigger sensor will maintain its state during a restart (or YAML reload). I’ve got a binary_sensor and I really need know when it last changed in the real world, so I created a trigger sensor as below. However the trigger sensor’s .last_changed gets changed just as the source binary_sensor’s does. Is this right or am I doing something wrong?

  - trigger:
    - platform: state
      entity_id: binary_sensor.slwisrestricted
      not_to:
        - unknown
        - unavailable    
    sensor:
    - name: slwisrestricted
      unique_id: slwisrestricted
      state: "{{ states('binary_sensor.slwisrestricted') }}"
      attributes:
        laston: "{{ now() if trigger.to_state.state == 'on' else this.attributes.laston }}"

All help gratefully received.

I suspect the binary_sensor’s state on startup is momentarily unavailable and is then set to a nominal state (on/off) by its underlying integration. This brief state-change is sufficient to trigger your Trigger-based Template Sensor’s State Trigger.

Try this version which ignores state-changes from unknown/unavailable.

- trigger:
    - platform: state
      entity_id: binary_sensor.slwisrestricted
      not_from:
        - unknown
        - unavailable    
      not_to:
        - unknown
        - unavailable    
    sensor:
    - name: slwisrestricted
      unique_id: slwisrestricted
      state: "{{ states('binary_sensor.slwisrestricted') }}"
      attributes:
        laston: "{{ now() if trigger.to_state.state == 'on' else this.attributes.laston }}"

Perhaps a better way to define the trigger is to explicitly specify the desired state-changes instead of the undesired ones.

- trigger:
    - platform: state
      entity_id: binary_sensor.slwisrestricted
      from:
        - 'on'
        - 'off'    
      to:
        - 'off'
        - 'on'

Thanks. I just tried your 2nd suggestion (explicit on/off) and the .last_changed is still getting changed on a YAML reload. Looking again at the history, the source binary sensor is surviving a reload but neither survives a restart. The state of the new sensor is retained during a restart.

Looks like there’s no workaround for it. last_changed is known to be updated on restart for all entities.

Thanks again for looking at this. What I’ll do is add an attribute like this:

  - trigger:
    - platform: state
      entity_id: binary_sensor.slwisrestricted
      from:
        - 'on'
        - 'off'    
      to:
        - 'off'
        - 'on'
    sensor:
    - name: slwisrestricted
      unique_id: slwisrestricted
      state: "{{ states('binary_sensor.slwisrestricted') }}"
      attributes:
        laston: "{{ now() if trigger.to_state.state == 'on' else this.attributes.laston }}"
        last_changed: '{{ now() }}'

Should do the trick, no?

Yes, as long as you understand they’re two different properties of the entity’s state object.

states.binary_sensor.slwisrestricted.last_changed
states.binary_sensor.slwisrestricted.attributes.last_changed

Reference

State Object

This is the one that is automatically updated on startup.

states.binary_sensor.slwisrestricted.last_changed

Indeed. I was planning on using state_attr('sensor.slwisrestricted','last_changed') to refer to it.

Yes that will work. There’s no control over the entity’s last_changed property so duplicating it is the last resort to gain control over when its value is set. FWIW, I assume you chose to use the same name to maintain consistency (you’re not obligated to do that).


NOTE

You may wish to consider saving the datetime string in ISO8601 format. It’s the preferred format used in Home Assistant wherever a datetime string is employed. The difference is very subtle (space character replaced by T).

        last_changed: '{{ now().isoformat() }}'
1 Like