Templates work in template dev tool, but not in sensor

I’m trying to write a couple of sensors to display the time since my device tracker has been updated and the last time it changed. I.e., when was the last update from my device, and when did my location actually change last? They’re pretty straightforward templates, as far as I can tell. They work in the template dev tool, but when I plug them into a sensor, the calculated times always read “0:00”.

Can anyone help here?

sensor:
  - platform: template
    sensors:
      location_steve_last_changed_text:
        value_template: >
          {%- set parts = ((now() - states.sensor.location_steve.last_changed) |string).split('.')[0].split(':') -%}
          {{ "Home" if is_state('device_tracker.steve', 'home') else "Away" }} for {{ parts[0] }}:{{ parts[1] }}

      location_steve_last_updated_text:
        value_template: >
          {%- set parts = ((now() - states.sensor.location_steve.last_updated) |string).split('.')[0].split(':') -%}
          Last updated {{ parts[0] }}:{{ parts[1] }} ago.

The two entities I’m referencing in these sensors, sensor.location_steve, and device_tracker.steve, are working fine. The sensor contains the raw JSON update from my device, which triggers an automation that publishes an MQTT topic for the device tracker that’s conditional on an accurate location.

Edit: Example results from the template dev tool:

Home for 0:10.
Last updated 0:05 ago.

Here’s a theory:

  • The template sensor only updates when it detects a state-change in sensor.location_steve.

  • At the moment it updates, last_changed is equal to now(). So the time difference is zero.

  • The reason why you see a non-zero value in the Template Editor is because you’re not looking at sensor.location_steve at the moment it changes but some time later. In contrast, the template sensor only evaluates sensor.location_steve when it changes.

Interesting. So in theory, I should be able to change now() to sensor.date_time and it should work as intended. I’ll give that a try.

I carried out an experiment. This always showed 00:00.

      garage_door_last_changed:
        value_template: >-
          {% set x = now() - states.binary_sensor.garage_door.last_changed %}
          Changed {{"{:02d}:{:02d}".format(x.seconds // 3600,(x.seconds % 3600) // 60)}} ago.

On the other hand, by obliging the template sensor to monitor sensor.time (updates every minute), this version showed a non-zero value as time passed.

      garage_door_last_changed:
        entity_id: sensor.time
        value_template: >-
          {% set x = now() - states.binary_sensor.garage_door.last_changed %}
          Changed {{"{:02d}:{:02d}".format(x.seconds // 3600,(x.seconds % 3600) // 60)}} ago.

BTW, the forum software mangled the formatting because it interprets a double-slash as the start of a comment when, in this case, it represents integer division.

Screenshot%20from%202019-04-29%2012-12-39

I think this works. For a while I thought it did not, because it seems that HA resets the last_updated and last_changed values when it restarts (or those values are just updated when restarted), so they still showed 0:00. But after a minute, they did update. I had to try to store the last updated time somewhere that wasn’t going to get
cleared. I was reporting hours:minutes, so I didn’t see the change until 1 minute in.

One of those little HA quirks. Effectively, last_updated and last_changed have lifespans. They are re-born after every restart. That throws a wrench into date-math calculating the age (duration) of the sensor’s state.