How to set start of a history_stats sensor to zero every time the device starts?

Hello!

I try to create a History Sensor which should show me how long a Device is running.
What i mad until now is this:

    - platform: history_stats
      unique_id: "history_laufzeit_therme"
      entity_id: switch.og_bad_therme_schalter
      name: history_laufzeit_therme
      state: 'on'
      type: time
      start: '{{ as_timestamp( now().replace(hour=0).replace(minute=0).replace(second=0)) }}'
      end: '{{ now() }}'   

It’s working fine on the first run of the Device but it reset only at midnight but it’s the best I could do.
What do I have to change so the Reset is every time the Device starts?

There have to be a way because History knows when the Device is on and off but I didn’t find out what code I have to put in start:

Do you have an Idea where too find that Information?

Or is history_stat the wrong solution for my project?

Thank you in advance for any hint!

The template for start would be:

{{ states.switch.og_bad_therme_schalter.last_changed }}

You can also do it with a pair of template sensors instead of using History Stats:

template:
  - trigger:
      - platform: state
        entity_id: switch.og_bad_therme_schalter
        to: 'on'
        from: 'off'
    sensor:
      - name: Bad Therm Last On
        unique_id: bad_therm_last_on_001
        state: "{{ now() }}"
  - sensor:
      - name: Bad Therm On Time
        unique_id: bad_therm_on_time_001
        state_class: measurement
        unit_of_measurement: hours
        state: >
          {% if is_state('switch.og_bad_therme_schalter', 'off') %}
            0
          {% else %}
            {{ (now() - states('sensor.bad_therm_last_on') | as_datetime).total_seconds()/3600 }}
          {% endif %}
1 Like

Thank you!!
Yes, that make more sense to do it this way.

Sorry to ask again but I was trying a little bit but it did not work so i think I didn’t understand correct.
I used my reading-light for testing because its easier to do.

That is the Template-Code:

template:
  - trigger:
      - platform: state
        entity_id: light.og_wohnzimmer_wandverbau_leselicht
        to: 'on'
        from: 'off'
    sensor:
      - name: leselicht_last_on
        state: "{{ now() }}"
  - sensor:
      - name: leselicht_on_time
        state: >
          {% if is_state('light.og_wohnzimmer_wandverbau_leselicht', 'off') %}
            0
          {% else %}
            {{ (now() - states('sensor.leselicht_last_on') | as_datetime).total_seconds/3600 }}
          {% endif %}
  - sensor:
      - name: leselicht_on_time_notroundet
        state: >
          {% if is_state('light.og_wohnzimmer_wandverbau_leselicht', 'off') %}
            0
          {% else %}
            {{ (now() - states('sensor.leselicht_last_on') | as_datetime) }}
          {% endif %}

And this is what I get when put it in Template Editor:

{{states('sensor.leselicht_last_on')}}
{{states('sensor.leselicht_on_time')}}
{{states('sensor.leselicht_on_time_notroundet')}}
{{states('light.og_wohnzimmer_wandverbau_leselicht')}}
{{ (now() - states('sensor.leselicht_last_on') | as_datetime)}}

Result when Light is OFF

2023-10-18 22:01:40.751944+02:00
0
0
off
0:08:33.154819

Result when Light is ON

2023-10-18 22:11:19.176932+02:00
unavailable
0:00:00.006885
on
0:00:09.730093

If I use the

.total_seconds/3600

in the Formula, the Template-Editor show me an Error.
TypeError: unsupported operand type(s) for /: ‘builtin_function_or_method’ and 'int’
I guess thats also the reason why

'sensor.leselicht_on_time'

is changing to unavailable
That’s why I created the second sensor.(which is not stopping …)

(now() - states('sensor.leselicht_last_on') | as_datetime)

is resetting to 0 and then count up. Thats exactly what I want. But when I switch off the Light it keeps running and do not stop.

I could do a workaround writing the value from one sensor into another and stop doing this as soon entity state is OFF but I’m afraid that will create CPU Load if I do this every Second (or 10 Seconds) especially I use more of this counters in Future.

OK, that’s a lot of text. I hope I wrote al Informations that are important.
Again, Thank you for your help!

That should be .total_seconds()/3600

I’m not sure I understand what you are trying to say about the second sensor…

Sorry. I meant, because I got the state “unavailable”, I added this to your example:

 - sensor:
      - name: leselicht_on_time_notroundet
        state: >
          {% if is_state('light.og_wohnzimmer_wandverbau_leselicht', 'off') %}
            0
          {% else %}
            {{ (now() - states('sensor.leselicht_last_on') | as_datetime) }}
          {% endif %}

It’s the same as in your example but without the .total_seconds/3600 so it returns a Timestamp.

.total_seconds()/3600 is working (If I understand right It covert the value into hours?)

But both variants are still counting up when the entity is switched to OFF.

They should return 0 when the light is off.

You are right. The problem was sitting on the Keyboard :sweat_smile:

I finally managed to do what I had in Mind so I want to thank you for your help and patience!

One last Question:
The Sensor is only updating every Minute. Is it possible to set a shorter update interval?

I Tried scan_intervalbut it seems not to work.

So this is how I made it:

template:
  - trigger:
      - platform: state
        entity_id: light.og_wohnzimmer_wandverbau_leselicht
        to: 'on'
        from: 'off'
    sensor:
      - name: leselicht_last_on
        state: "{{ now() }}"
  - sensor:
      - name: leselicht_on_time
        state: >
          {% if is_state('light.og_wohnzimmer_wandverbau_leselicht', 'off') %}
            0
          {% else %}
            {{ (now() - states('sensor.leselicht_last_on') | as_datetime).total_seconds()/3600 }}
          {% endif %}

sensor:
    
    - platform: template
    
      sensors:
      
        leselicht_on_time_timestamp:
            value_template: >
                {{ (timedelta(hours=states('sensor.leselicht_on_time') | float(0)) | string)[:-7] }}  
        leselicht_lastrun:
            value_template: >
                {{ (timedelta(hours=states('input_number.ztest1') | float(0)) | string)[:-7] }}
        leselicht_totalrun:
            value_template: >
                {{ (timedelta(hours=states('input_number.ztest2') | float(0)) | string)[:-7] }}           

And this is is (a quick and dirty) dashboard from testing:

I made an automation that take the values and write them into helpers before the sensor is resetting to 0 when entity is turned off.

Automation YAML
alias: TEST Laufzeitzähler
description: ""
trigger: []
condition: []
action:
  - service: input_number.set_value
    data:
      value: >-
        {{ (now() - states('sensor.leselicht_last_on') |
        as_datetime).total_seconds()/3600}}
    target:
      entity_id: input_number.ztest1
  - service: input_number.set_value
    data:
      value: >-
        {{ (now() - states('sensor.leselicht_last_on') |
        as_datetime).total_seconds()/3600 +  states('input_number.ztest2')|
        float }}
    target:
      entity_id: input_number.ztest2
  - type: turn_off
    device_id: 56aaa29eec036cbe815803a980ded614
    entity_id: c8843c18c29bdaac710e677159bef559
    domain: light
mode: single

I don’t know if this is the best solution but it’s working :smiley:
Because there where I will use this Automation the entity is only switched off with an automation so the helpers are always updated.
I know, it would not work if the entity would be switched off directly.

That is the expected behavior… a state-based Template sensor will render its template any time a referenced entity updates and every minute when template includes now().
I wouldn’t recommend do so, but you could switch to a trigger-based Template sensor with a Time-Pattern trigger.

scan_interval is not a valid configuration variable for Template sensors

Your “automation” doesn’t have a trigger… that’s likely to cause issues. If you have a set of actions that you want to be able to call from other automations or the dashboard, but you do not have a specific trigger, use a Script not an Automation. However, there is no need to perform those calculations again…

template:
  - trigger:
      - platform: state
        entity_id: sensor.leselicht_on_time
        to:
          - '0'
          - '0.0'
        not_from:
          - unknown
          - unavailable 
    sensor:
      - name: Leselicht Previous On Hours
        state: "{{ trigger.from_state.state }}"
      - name: Leselicht Previous On Seconds
        state: "{{ trigger.from_state.state * 3600 }}"

Thank you for all your Input.
I Finally made it.

And I learned a lot new stuff that I’ll try to use in the future.