History stats sensor measuring night screen time is unknown during day

I’ve got a history stats sensor measuring screen time during night because you know… Little darn devils…

It works fine while I’m checking the sensor during the night but when day comes and the stop point is reached for the sensor, it won’t keep displaying the measured activity at my dashboard, instead it goes unknown which isn’t helpful. How can I prevent this?

Now all I miss is an automation disconnecting internet for the person in question when time goes over a certain amount :imp:

Sorry for image, file editor on mobile won’t let me copy.

The problem is obviously that now() is now!

So on the 18th January at 23:30 replace is doing the correct thing.
However after midnight - you are asking it to start at 11pm tonight, which is in the future.

Or the past depending on location and :spiral_calendar: :hourglass_flowing_sand: :timer_clock:the date line

Try this:

start: >-
  {% set n = now().replace(hour=23,minute=0,second=0) %}
  {{ (n - timedelta(days=1)) if now().hour < 23 else n }}

Did a quick edit because my previous solution was checking if n.hour < 23 when it should obviously be checking now().hour

1 Like

If I have understood the example in the documentation, this should report the cumulative on time for the 8 hour period between 23:00 and 07:00.

- platform: history_stats
  name: Ellinore nightly screen time
  unique_id: history_stats_ellinore_nightly_screen_time
  entity_id: binary_sensor.ellinores_phone_interaction
  state: 'on'
  type: time
  end: "{{ (now().replace(minute=0, second=0, microsecond=0) + timedelta(hours=17)).replace(hour=7) }}"
  duration:
    hours: 8

It’s based on this example:


NOTE

The screenshot cropped some of the details of your example so I took a guess at the values of unique_id and entity_id. The main difference from your version is the use of the end option instead of start.

Both excellent answers from @123 and @mobile.andrew.jones
I totally missed the fact that now() includes a date :man_facepalming:

I tried the suggestion of @123 as it seemed more straight forward, will report back tomorrow when I see how it works. Both should theoretically work though.

Actually I got good use out of the answer from @123 as well in another similar thing. I hope I got it right:

  - platform: history_stats
    name: Ellinore daytime screen time ratio
    unique_id: history_stats_ellinore_daytime_screen_time_ratio
    entity_id: binary_sensor.ellinores_phone_interactive
    state: "on"
    type: ratio
    start: "{{ now().replace(hour=7, minute=0, second=0) }}"
    # end: "{{ now() }}"
    end: >-
          {% set n = now().replace(hour=23,minute=0,second=0) %}
          {{ (now()) if now().hour < 23 else n }}

1 Like

So it turned out that didn’t work unfortunately. Same issue: meter becomes unknown after the end of the metering period and remains unknown through the entire day, which is when I want to review it. It’s pretty clear that it goes unknown right when the measuring period end from the looks of this:

(assuming if it worked, that the line should stay at the top value until reset back to zero)

start: >-
  {% set s = today_at("23:00") %}
  {{ (s - timedelta(days=1)) if now().hour < 7 else s }}
duration:
  hours: 8

Maybe that?

EDIT:

Actually there is an example on the docs that might do what we need -

end: "{{ (now().replace(minute=0, second=0, microsecond=0) + timedelta(hours=8)).replace(hour=16) }}"
duration:
    hours: 24

that measures 4pm until 4pm. So following the example - it would be something like:

end: "{{ (now().replace(minute=0, second=0, microsecond=0) - timedelta(hours=23)).replace(hour=23) }}"
duration:
    hours: 8

I have tested that in the template editor and it seems to do the job.

I’m using something similar to that:

  - platform: history_stats
    name: Ellinore nightly screen time
    unique_id: history_stats_ellinore_nightly_screen_time
    entity_id: binary_sensor.ellinores_phone_interactive
    state: "on"
    type: time
    end: "{{ (now().replace(minute=0, second=0, microsecond=0) + timedelta(hours=17)).replace(hour=7) }}" # end at 7, at right side of dateline
    duration:
      hours: 8

It works, but I get the unknown state as soon as the clock passes 7am. I guess my problem here is that I want to STOP measuring at 7am but still display the result in the sensor until it resets at 23 and starts counting again.

1 Like

Maybe to find out if it is a bug or not, you should create a temporary sensor - and hardcode the start to be 11pm yesterday and end to be 7am today, and see if it gives you data or is still unknown?

sensor:
  - platform: history_stats
    name: Ellinore nightly screen hours
    unique_id: history_stats_ellinore_nightly_screen_time
    entity_id: binary_sensor.ellinores_phone_interactive
    state: "on"
    type: time
    end: "{{ today_at('23:00') }}"
    duration:
      hours: 8


template:
  - trigger: 
      - platform: state
        entity_id: sensor.ellinore_nightly_screen_hours
        not_to:
          - 'unknown'
          - 'unavailable'
    sensor:
      - name: Ellinore nightly screen time
        state: "{{ trigger.to_state.state }}"

I did run a similar test and it seems to produce the same result. I guess it’s time to file a bug to let the big guns look at it.

I’ve considered just that, but I feel it’s a lot of clutter and wonder if this is really the way it should be.