Templating to format timestamp

Hi,
So I followed the post here (How to edit sensor printout) and have got my time being formatted ok. My problem is that the time since last motion detection doesn’t seem to update until the “next” motion that is detected weirdly. Can anyone see what I’m doing wrong here?..

- platform: template
  sensors:
    last_motion_time:
      friendly_name: 'Time since last motion'
      value_template: >-
        {% set sensors = [states.binary_sensor.upstairs_motion, states.binary_sensor.downstairs_motion, states.binary_sensor.bedroom_motion, states.binary_sensor.kitchen_motion, states.binary_sensor.lounge_motion] %}
        {% for sensor in sensors %}
          {% if as_timestamp(sensor.last_changed) == as_timestamp(sensors | map(attribute='last_changed') | max) %}
            {{ now() - sensor.last_changed  }}
          {% endif %}
        {% endfor %}
        
- platform: template
  sensors:
    last_motion_time_templated:
      friendly_name: 'Time since last motion templated'
      value_template: >-
        {%- set slb = states.sensor.last_motion_time.state.split(' ') -%}
        {%- set count = slb | length -%}
        {%- set hms = slb[count - 1] -%}
        {%- set hms_trimmed = hms.split('.')[0] -%}
        {%- set hms_split = hms_trimmed.split(':') -%}
        {%- set hours = hms_split[0] | int -%}
        {%- set minutes = hms_split[1] | int -%}
        {%- set seconds = hms_split[2] | int -%}

        {%- if count == 3 -%}
          {{ slb[0] ~ ' ' ~ slb[1] ~ ' ' }}
        {%- endif -%}
        {%- if hours > 0 -%}
          {%- if hours == 1 -%}
            1 hour
          {%- else -%}
            {{ hours }} hours
          {%- endif -%}
        {%- endif -%}
        {%- if minutes > 0 -%}
          {%- if hours > 0 -%}
            {{ ', ' }}
          {%- endif -%}
          {%- if minutes == 1 -%}
            1 minute
          {%- else -%}
            {{ minutes }} minutes
          {%- endif -%}
        {%- endif -%}
        {%- if seconds > 0 -%}
          {%- if hours > 0 or minutes > 0 -%}
            {{ ', ' }}
          {%- endif -%}
          {%- if seconds == 1 -%}
            1 second
          {%- else -%}
            {{ seconds }} seconds
          {%- endif -%}
        {%- endif -%}
        {{ ' ago' }}

A template sensor only updates when one of the referenced entities updates. “now()” is not an entity, so the mere fact of time advancing will not cause your template sensor to be re-evaluated.

You can remedy that by using sensor.time. That entity will update once a minute. The easiest way to “use it” is by listing it in the template sensor’s entity_id parameter. This will simply cause the template sensor to be re-evaluated every minute.

- platform: time_date
  display_options:
    - 'time'
- platform: template
  sensors:
    last_motion_time:
      friendly_name: Time since last motion
      entity_id: sensor.time
      value_template: >
        {% set object_ids = ['upstairs_motion', 'downstairs_motion',
                             'bedroom_motion', 'kitchen_motion',
                             'lounge_motion'] %}
        {{ now() - states.binary_sensor
                   |selectattr('object_id', 'in', object_ids)
                   |map(attribute='last_changed')|max }}
2 Likes

This has even been highlighted in the templating documents for some time now.