Persistent version of "last-changed" for the UI?

I can see why it would be a problem if there was no way to check when Home Assistant last started.

But overall, the current method has a much higher probability of being incorrect and constitutes a more risky assumption than letting last-changed survive a restart intact @frenck.

For many entities a last-changed value that survives a restart will still be correct. But assuming state changes upon a restart will almost be certainly incorrect for most entities.

Take this scanario: 13:00 window sensor switches to open, 13:15 Home assistant reboots, 13:30 user checks.

If the user is aware that Home Assistant restarted, the assumption that it would have missed any state changed during this time makes complete sense. A surviving last-changed state (13:00) is a correct assumption here, while 13:15 as last state change is counter intuitive and incorrect. It’s only intuitive to those who know how Home Assistant’s startup process works, which shouldn’t be a requirement for its correct usage.

I see three options for making this work better:

  1. If the state of a sensor is different after Home Assistant starts from when it shut down, make the assumption that the state changed upon start. If it is still the same, keep the last-changed time from before the start.
  2. In addition to 1: What could be considered is a time-limit. For example, if Home Assistant has been switched off for 2h, all last-changed values are reset.
  3. A function for templates that makes it easy to check whether the last state change was due to a restart.
  4. A function for templates that makes it easy when the last state change was, but lets the user decide whether to consider the “unavailable” state. For example: {{ last_changed('sensor.some_entity_id', 1) }} where the default is to consider all states, and 1 is “method 1”, which ignores unavailable.
2 Likes

I really think only point 1 is needed. A comparison of the startup state object to the last shutdown state object. Anything that’s different (main state, & attributes) will cause the startup state to be honored over the shutdown state. Make this the default and couple that with an option to have this functionality disabled per entity.

4 Likes

There’s another issue I haven’t seen mentioned here with the last updated/changed: forced updates.

I was made aware of this when I reported an issue with the new live logbook (since fixed). Logbook entries were being created even when the state value was not actually difference.

It turns out that states can be force updated which ends up changing the last updated/changed time even when the value is not actually different. Perhaps a HA dev can clarify if I’m off with the technical details of this explanation.

Here is the issue for anyone curious:

I tried to find this generic solution on the forum but no luck. If by any chance you may know where this example is, it would be very helpful to share it, thanks!

I was hoping 123 would link it because I don’t have his posts memorized. @123, sorry for pinging you, but do you have an example post where you explained how to create MQTT discovery and a sensor with an automation?

Thanks. In the meantime, I found two related posts:

6 Likes

Thanks

Thanks a lot. The device creation is really the icing on the cake. I wished I knew this earlier. :heart_eyes:

1 Like

I’ve read the thread but I think I’m still missing something. I understand you can make a MQTT Discovery “device” which can mirror your sensor. Then you have an automation that updates the MQTT device when the real device changes to on/off? From that I could just use that new fake MQTT device on the dashboard instead and the last-changed attrib would always be only from on/off. The problem there is what happens when the device actually becomes unavailable? It wouldn’t show that on the dashboard then would it?

1 Like

No, you make a sensor that stores the last_changed.

No, you don’t store the state, you store the last_changed

Ah okay, in that case what’s the benefit over just using a helper to store that…? Wouldn’t you still need something like the “secondaryinfo-entity-row” custom UI component to show that under the entity on the dashboard too?

It can’t be modified. Your automation creates it for you instead of you manually creating it. So you setup the automations and you’re done. Instead of: Create helper, Create automation, hide helper from ui, etc.

Yep

Just to confirm…

A script that will create a mqtt discovery sensor for each device to track. That will contain the last_changed attribute. This only needs to be ran once to initially create them.

One automation with triggers for each sensor changing from on/off. That will publish the current time to the relevant mqtt sensor.

Display the sensor as normal in the UI but use secondaryinfo-entity-row to show the new “last_changed” from the mqtt sensor.

Yep, or you can just manually create the MQTT sensor in configuration.yaml. I prefer the automation because you can write an automation that loops multiple sensors for you with a repeat. Then you only have 1 configuration.

Yep

Yes. If you want to view it as ‘x minutes ago’, you need to make it a device_class: timestamp and the format of the time should be .isoformat(). e.g. {{ states.sensor.xyz.last_changed.isoformat() }} or from a trigger… {{ trigger.to_state.last_changed.isoformat() }}

1 Like

Finally got around to trying this… It’s probably obvious but what am I missing here? This creates the sensor fine, the automation publishes a timestamp to the mqtt sensor fine (I can see it under “state” in MQTT explorer) and I can see the state of the sensor in HA showing the timestamp. As soon as I add the timestamp device_class it breaks and changes to unknown in HA, if I remove it then it works but that means the ‘x minutes ago’ doesn’t work when I use it…

service: mqtt.publish
data:
  topic: homeassistant/sensor/office_balcony_door/config
  retain: true
  payload: |
    {
      "name": "Office balcony door",
      "unique_id": "office_balcony_door_mqtt",
      "state_topic": "homeassistant/sensor/office_balcony_door/state",
      "device_class": "timestamp"
    }

Automation sends:

payload: "{{ now().timestamp() }}"

{{ now().isoformat() }}

Also you need value_template: “{{ value }}” I think, on mobile so can’t check atm. Inside the config payload

You’re right, that sets the sensor perfectly now thanks! Although I’m not sure if it’s a limitation of “secondaryinfo-entity-row” but using {{ states.sensor.xyz.last_changed.isoformat() }} to set the secondary info just ends up printing the actual timestamp. Using the new sensor just as an entity shows it as “X mins ago”.

entity: binary_sensor.office_balcony_door_contact
type: custom:secondaryinfo-entity-row
secondary_info: '{{ states.sensor.office_balcony_door.last_changed.isoformat() }}'

It’s probably a limitation of the secondary_info row. You can use…

secondary_info: "{{ states('sensor.office_balcony_door') | as_datetime | relative_time }}"
1 Like