Interval length of binary sensor state

If I have an automation with a binary sensor and its state goes from ‘on’ to ‘off’, how can I find out how long it was ‘on’?

1 Like

Could you give an example perhaps?

The examples on the History Stats sensor are all for given time periods, e.g. last hour/day/week/whatever.

I guess what jms3000 would like (and myself as well), is

  • sensor went from on to off
  • How long was the sensor in the ‘on’ state before this transition
1 Like

Exactly. The sensor goes on and off during the day, few hours on, few hours off. For every state change I need to know: how long was the interval. So there is a state trigger, and in the action-template I need the duration of the last interval. Is it possible to glue a timestamp attribute to the binary sensor?
set_attribute( binary_sensor.xxx, last_change, as_timestamp(now()))

That property already exists.

{{ states.binary_sensor.xxx.last_changed }}

It is a property of the state object, not an attribute. Notice the word attributes is missing between xxx and last_changed.

When I use last-changed, it gives me the amount of time between now and the state transition.

This is not the same as how long the sensor was in a given state?

last_changed gives the time that the last state change occured where something in the state changed. last_updated gives the time that the last update occured.

If you have a state object that has alot of attributes and one of the attributes updated, that will affect last_changed. If you have a binary_sensor with only the main state, it will pretty much give you the value you are looking for.

This seems like a duplicate of my quesion: Tracking time a sensor is on/true/state

So the solution is {{ as_timestamp(now()) - as_timestamp(states.binary_sensor.xxx.last_changed) }} ?

If you guys really want it to only occur on the main state, you’d need to get inventive.

You can use the custom variables component or a input_text or input_number. Make an automation that stores the current time.

- alias: store value
  trigger:
    platform: state
    entity_id: binary_sensor.xxx
  condition:
    condition: template
    value_template: >
      {{ trigger.from_state is defined and trigger.to_state is defined
          and trigger.from_state.state != trigger.to_state.state
          and trigger.to_state.state in ['on', 'off'] }}
  action:
    service: input_text.set_value
    data_template:
      entity_id: input_text.xxx
      value: "{{ as_timestamp(now()) }}"

Then make a sensor that tells you the current time it’s been in that state.

sensor:
  - platform: time_date
    display_options:
      - 'time'
  - platform: template
    sensors:
      xxx_time_difference:
        entity_id: sensor.time
        value_template: >
          {%- set time = as_timestamp(now()) - states('input_text.xxx') | float %}
          {%- set minutes = ((time % 3600) // 60) %}
          {%- set minutes = '{}min'.format(minutes) if minutes > 0 else '' %}
          {%- set hours = ((time % 86400) // 3600) %}
          {%- set hours = '{}hr '.format(hours) if hours > 0 else '' %}
          {%- set days = (time // 86400) %}
          {%- set days = '{}d '.format(days) if days > 0 else '' %}
          {{ 'Less than 1 min' if time < 60 else days + hours + minutes }}

That could be the simplest solution if there aren’t any other state changes.

This is my solution. To automations, one for the sensor for going on, one for going off. The on-automations checks the time of the last off-automation and vice versa.

- alias: auto_on
  trigger:
  - entity_id: binary_sensor.lumi_lumi_sensor_wleak_aq1_1_1280
    platform: state
    to: 'on'
  action: 
  - service: input_number.set_value
    data_template:
      entity_id: input_number.num1
      value: >-
        {{ as_timestamp(now()) - as_timestamp(states.automation.auto_off.attributes.last_triggered) }}

- alias: auto_off
  trigger:
  - entity_id: binary_sensor.lumi_lumi_sensor_wleak_aq1_1_1280
    platform: state
    to: 'off'
  action: 
  - service: input_number.set_value
    data_template:
      entity_id: input_number.num1
      value: >-
        {{ as_timestamp(now()) - as_timestamp(states.automation.auto_on.attributes.last_triggered) }}