History stats from counter helper not working

Hi!

I have a counter helper that gets incremented based off of door sensor. I want to have a history_stats that gets me how many increments there have been per hour/day.

Currenty I’m doing the following:

- platform: history_stats
  name: "RainFall flips hour"
  entity_id: counter.rainfall_sensor_on_off_s
  state: value
  type: count
  start: "{{ now().replace(minute=0, second=0) }}"
  end: "{{ now() }}"

But no matter how many increments the counter gets, the value for the stats does not change. Am I doing something wrong or is there another way to go about doing this?

Has your counter state ever reported the literal string “value”, or just numbers?

Because that is what you are asking the history stats sensor to match against.

You are using the wrong integration. The History stats sensor has to match a single value like “on” or “off” or “42”.

Use the Utility Meter helper.

Thanks for the reply!

I tried using the Utility Meter but currently that does not give me the option to select a counter as a source for the data. Hm, now I’m thinking I should try to create one by hand, in yaml? Could that work?

I’m honestly not sure. I’ve never used a counter in a utility meter.

I am surprised the UI Helper wouldn’t let you use it.

Worth a try. Give it a go and if it does not work you should be able to use the binary sensor from your door sensor directly in the History stats sensor instead of the counter.

Are you counting on and off states or just on?

I created one in yaml. Not sure if it reports at every “cycle” interval, will check back in an hour.

I did it initially with history_stats on the on and off states but the thing that did not work there is that one of the stats, either the one for on or off would always show 1, so to me it seemed that it does not check the change in state, but the actual state.

This is what I used:

- platform: history_stats
  name: "Aqara Rainsensor flips/on"
  entity_id: binary_sensor.rain_gauge_sensor_contact
  state: "on"
  type: count
  start: "{{ now().replace(minute=0, second=0) }}"
  end: "{{ now() }}"
- platform: history_stats
  name: "Aqara Rainsensor flips/off"
  entity_id: binary_sensor.rain_gauge_sensor_contact
  state: "off"
  type: count
  start: "{{ now().replace(minute=0, second=0) }}"
  end: "{{ now() }}"

You can see from the history that at least one of the two was always at 1, even though no change occurred during that time:

It works with the utility meter!
Thanks a bunch for the answers!

I am curious though if if the history_stats should behave the way I describe above, when it gets “stuck” on the last value, or not. My understanding was that it needs to count changes, since it has count for type.

This is a long response, so if you were just venting and don’t really care about how history_stats works, you should ignore my reply completely.

——

The history_stats integration will exhibit behavior that will be unexpected by most laypeople when the results are verified against the user’s own calculations. Most people don’t go back to verify accuracy, especially against corner cases, so it just doesn’t impact most people. For example, if you want to count the number of times a light was in state: "on" each day, what would you expect the integration to report if the light was turned ON at noon on day 1, and turned OFF at noon on day 3? Was it on once or zero times on day 2? The documentation doesn’t cover these details and most people either never consider it or they just make an assumption and never verify it.

When you have a simple config like yours, these details become very noticeable.

I haven’t looked at the code (because I doubt I could understand it) but I have done some testing and my observations are:

  • When you use now() in the template, the template only gets rendered once per minute. This is in the docs, but in the template docs, not in the history_stats docs.
  • The history_stats sensor only updates when the template needs to be rendered (no faster than one minute after previous render) or if a value from the source sensor expires outside the window that was specified the config.
  • the count is calculated by counting rising edges in the observation window, with 2 caveats:
    • if the current state equals the state to be counted, the count can be no less than 1
    • if there are rising edges less than about 2 seconds apart they will be ignored
  • if the window duration is set for one minute, there is a race condition between the window period and the template rendering delay. When the sensor updates one minute after a source sensor change, there are often some fractions of a second remaining inside the observation window that the source was still considered to not have changed yet, so it can take an additional minute for the history_stats sensor to reflect the change in count. To fix this, a window duration of 59 seconds should be used.

Whether any of this behavior is a “bug” is debatable; it’s not documented either way so just because it doesn’t match a layperson’s expectations doesn’t mean it is broken.

Though my personal opinion is that the integration is junk and so I will use trigger-based template sensors to calculate what I need, using the rules I think make sense, instead of using this integration.

1 Like

Wow, I bet it took you a while to figure this out.

I guess this is what I was not expecting:

if the current state equals the state to be counted, the count can be no less than 1

I expected to only count rising edge. Or, in your other example:

what would you expect the integration to report if the light was turned ON at noon on day 1, and turned OFF at noon on day 3

I would have expected it to be ON zero times, since it’s a count; for measuring duration, that would be different.

Thanks a lot for the detailed response, much appreciated!

So then I’m curious how would you solve what I’m trying to do? I have a door sensor that switches state every X ml of water rained. I want to see the hourly rate of rain, for example. So what I did now is an hourly utility meter and then I create a new template sensor based off of the utility meter, where I multiply by a constant to get mm/m2.

Would you do it differently?

I think the path Tom led you down is the right recommendation for anyone looking for a way to do this. It is easy to implement and easy to understand. It can be done mostly from the UI and the end result is exactly what you wanted.

The only downside, which may not even be a downside depending on your perspective, is that you end up with two separate entities to get to your end goal. So while I would also recommend that approach to others, in my own setup I would use a trigger based template sensor. It has to be created in YAML and it requires a decent understanding of templates and state objects, but it can do everything in one entity.

Which, again, for most people is two big negatives and one mediocre positive so it doesn’t make sense. I personally enjoy creating templates and I like to avoid intermediate entities whenever possible. I’m assuming you have an automation set up to increment your counter entity, and I would also replace both with a single trigger-based template sensor. If your end goal is just to have an hourly rain meter and you are starting with just the binary sensor, you can get there with a single trigger-based template sensor with no intermediate automations or counters or utility meters. But you’re trading several simple entities for one complex entity.

1 Like

I’m quite familiar with the jinja2 so that wouldn’t be a problem. Not quite sure though how you’d go about it, you need something to keep your state. Would you use a self-referencing sensor and update the values that way?

Something like this?

- trigger:
  - platform: state
    entity_id: binary_sensor.rain_gauge_sensor_contact
    to: "on"
  - platform: state
    entity_id: binary_sensor.rain_gauge_sensor_contact
    to: "off"
  sensor:
    - name: "Rain fall tmpl"
      unique_id: rain_fall_tmpl
      state: "{{ (states('sensor.rain_fall_tmpl') | float) + 0.63138 }}"
      unit_of_measurement: "mm"

This actually works. That’s pretty neat! Thanks a lot!

How would you then make hourly/daily/etc values out of this? Using utility meters?

Btw, you’re right, there’s an automation, the counter, the meter and then some template sensors. I, too, think that’s way too many entities.

You can improve it just slightly:

- trigger:
  - platform: state
    entity_id: binary_sensor.rain_gauge_sensor_contact
    to:
      - "on"
      - "off"
    from:
      - "on"
      - "off"
  sensor:
    - name: "Rain fall tmpl"
      unique_id: rain_fall_tmpl
      state: "{{ this.state | float(0) + 0.63138 }}"
      unit_of_measurement: "mm"
      state_class: total_increasing

If your end goal is to have multiple entities with different reset cycles (one daily, one weekly, one monthly, etc.) then the cleanest option is to have the one template sensor as the main source and a bunch of utility meters with different reset cycles.

Alternatively, if your end goal was to only have a single sensor that resets on an interval (daily, for example), then you could skip the utility meter and just do it in the template sensor:

- trigger:
  - platform: state
    entity_id: binary_sensor.rain_gauge_sensor_contact
    to:
      - "on"
      - "off"
    from:
      - "on"
      - "off"
  - platform: time
    at: "00:00"
  sensor:
    - name: "Rain fall tmpl daily"
      unique_id: rain_fall_tmpl_daily
      state: >
        {{ 0 if trigger.platform == 'time' else 
          this.state | float(0) + 0.63138 }}
      unit_of_measurement: "mm"
      state_class: total_increasing

Awesome stuff! Thanks a lot, learned a couple of thing with this.

1 Like