Template sensor showing relative time

Hi,

I have a sensor template with value “Unknown”, whereas it should display the relative time.

I have defined a sensor template defined like this:

template:
  - trigger:
      - platform: state
        entity_id: binary_sensor.beweging_wachtruimte
        to: 'on'
    sensor:
      - name: "Last Movement"
        unique_id: Beweging_Wachtruimte_Tijd
        state: "{{ relative_time(states.binary_sensor.beweging_wachtruimte.last_changed) }}"
        device_class: timestamp

The value is “Unknown” if I navigate to this entity.

However, when I enter "{{ relative_time(states.binary_sensor.beweging_wachtruimte.last_changed) }} in the template editor, it returns exactly what I need.

So what am I doing wrong?

[Edit]
Ok, by removing the “device_class: timestamp”, the template sensor now generates the value “0 seconds”. But it is not updated afterwards. In some way, that makes sense. The value of this template is only calculated at the time motion is detected.

But that doesn’t bring me closer to my solution. :frowning_face: I want to easily see when the last time motion was detected (relatively).

Your sensor will always be 0 seconds because the sensor and along with it, its last_changed property has to change for the trigger to fire and the template to be rendered.

You could use a time trigger firing every xx seconds to achieve your goal.

I you create a Template Sensor with:

device_class: timestamp

then it expects the value of state to be date and time in ISO format. Your state template doesn’t do that so that’s why it reports unknown.

If you remove device_class, the sensor will simply report the result of relative_time which expresses the elapsed time as a phrase (like “5 minutes ago” or “1 day ago”).

It will be updated each time the the binary_sensor’s state changes to on. However, that means it will report “0 seconds” (because the elapsed time between when it triggers and now is effectively zero).

Try this version:

template:
  - trigger:
      - platform: state
        entity_id: binary_sensor.beweging_wachtruimte
        to: 'on'
        from: 'off'
      - platform: time_pattern
        minutes: '/1'
    sensor:
      - name: "Last Movement"
        unique_id: Beweging_Wachtruimte_Tijd
        state: >
          {{ relative_time(states.binary_sensor.beweging_wachtruimte.last_changed 
              if trigger.platform == 'state'
              else this.attributes.last_on_at | as_datetime) }}
        attributes:
          last_on_at: >
            {{ states.binary_sensor.beweging_wachtruimte.last_changed 
                if trigger.platform == 'state'
                else this.attributes.last_on_at }}

Initially it will probably report unknown. Make the binary_sensor turn on and then the Trigger-based Template Sensor should report the correct elapsed time, “0 seconds”, and then update itself every minute. I tested it and confirmed it works on my system.

1 Like

Hi @123,

Thanks a lot. This is indeed working perfectly, thanks a lot!!!

Two (minor) remarks:

  • I’m pretty new to HA. But with the method above, we are actually solving a visualization issue by modifying the underlying data. I would expect that the template sensor would just contain a timestamp (epoch value) and that in the Lovelace entity card you could specify how you want to visualize it. It would make more sense, but I guess this is a HA limitation. Anyway, the solution you provided works fine for me.
  • A small cosmetics issue. People that log on as an end-user in HA using another language (e.g. Dutch) would still see “Minutes” instead of “Minuten”. So this part is not really translated. Again, not really an issue. People in my household understand English fine.

Thanks!

1 Like

Hi,

I’m trying to take this to the next level.
I have two motion detectors in one (big) room. I want to create a template sensor showing the “Last motion detected at” (relative time), if motion was detected by either one of these sensors.

I tried adapting the template provided, but unfortunately my HA is still too limited.

  - trigger:
      - platform: state
        entity_id: binary_sensor.motionsensor1
        to: 'on'
        from: 'off'
      - platform: state
        entity_id: binary_sensor.motionsensor2
        to: 'on'
        from: 'off'
      - platform: time_pattern
        minutes: '/1'
    sensor:
      - name: "Last motion"
        unique_id: Last_Motion_inThisRoom
        state: >
          {{ relative_time(states.binary_sensor.motionsensor1.last_changed 
              if trigger.platform == 'state'
              else this.attributes.last_on_at | as_datetime) }}
          {{ relative_time(states.binary_sensor.motionsensor2.last_changed 
              if trigger.platform == 'state'
              else this.attributes.last_on_at | as_datetime) }}
        attributes:
          last_on_at: >
            {{ states.binary_sensor.motionsensor1.last_changed 
                if trigger.platform == 'state'
                else this.attributes.last_on_at }}

I think I got the trigger mechanism right, but the rest is obviously wrong…

Try this:

- trigger:
      - platform: state
        entity_id:
          - binary_sensor.motionsensor1
          - binary_sensor.motionsensor2
        to: 'on'
        from: 'off'
      - platform: time_pattern
        minutes: '/1'
    sensor:
      - name: "Last motion"
        unique_id: Last_Motion_inThisRoom
        state: >
          {{ relative_time(states[trigger.entity_id].last_changed 
              if trigger.platform == 'state'
              else this.attributes.last_on_at | as_datetime) }}
        attributes:
          last_on_at: >
            {{ states[trigger.entity_id].last_changed 
                if trigger.platform == 'state'
                else this.attributes.last_on_at }}
1 Like

Thanks, that was exactly what I needed. states[trigger.entity_id], I’ll have to remember that. Thanks!

Reference: Templating - State Trigger

2 Likes

Hi 123,

im trying to use your sample for another usecase. Maybe you can help me out. Your code is working fine, but I want that the relative time is only “updating” if the state of the binary sensor is on. If it change to off, it should stop the last value. If its switching to on again, it should start from 0.

Can you help me out a little bit? Im struggling how to template this…

thanks a lot!

regards

Alex

Sorry, this is no longer fresh in my mind. On first glance it already appears to work the way you have requested. If that’s not the case then hopefully someone else can help you make it do what you want.

Okay, thanks for your reply. currently its still updating when its off or on. It just reset if its switch from off to on.

I would change ‘state’-field as follows:

      {% if is_state('binary_sensor.motionsensor1', 'on') or is_state('binary_sensor.motionsensor2', 'on') %}
      {{ relative_time(states[trigger.entity_id].last_changed 
          if trigger.platform == 'state'
          else this.attributes.last_on_at | as_datetime) }}
      {% else %}
      {{ states('sensor.Last_Motion_inThisRoom') }}
      {% endif %}
1 Like

Thanks Heinz,

this is working like expected. :slight_smile:
Merry christmas to all. :santa: