Count history_stats starts at 1, not 0

I’m using a door and window sensor for a rain meter, and I’m getting some unexpected behavior when using history_stats. This is my config:

sensor:
    # Flips ON | TODAY
    # Determines how many times the sensor was in the ON state today
  - platform: history_stats
    unique_id: "aqara_rain_sensor_flips_on_today"
    name: "Aqara rain sensor flips/on (Today)"
    entity_id: binary_sensor.aqara_dw_2_open_closed
    state: "on"
    type: count
    start: "{{ now().replace(hour=0, minute=0, second=0, microsecond=0) }}"
    duration:
      hours: 24
    # Flips OFF | TODAY
    # Determines how many times the sensor was in the OFF state today
  - platform: history_stats
    unique_id: "aqara_rain_sensor_flips_off_today"
    name: "Aqara rain sensor flips/off (Today)"
    entity_id: binary_sensor.aqara_dw_2_open_closed
    state: "off"
    type: count
    start: "{{ now().replace(hour=0, minute=0, second=0, microsecond=0) }}"
    duration:
      hours: 24

Currently, there hasn’t been any rain for a few days, so the sensor has been in the same position for those days. This happens to be the closed (off) position. Now, since the sensor hasn’t had any state changes these last days, I’d expect the history_stats counter to show 0. Of course, that’s not how history_stats works (I mean it’s literally there in my own comment), it tracks “How many times the tracked entity matched the configured state during the time period”, and at the start of every day, the sensor is always in one state, so that counter will always be at 1.

I though of an automation that checks the state of both sensors at a few seconds after midnight, and sets both to 0. In heavy rainfall at midnight, that could cause some weird artefacts on the graph though.

So, is there an easier way to do this? Maybe a setting for history_stats to only track when the state changes?

I assume you are adding up the on and off state flips to get a total and then multiplying that by the tip volume to get the amount of rain?

If so here’s an alternative to using history stats:

(configuration.yaml)

template:
  - trigger:
      - id: count
        platform: state
        entity_id: binary_sensor.aqara_dw_2_open_closed
        to:
          - 'on'
          - 'off'
        from:
          - 'on'
          - 'off'
      - id: reset
        platform: time
        at: '0:00'
    sensor:
      - name: 'Rain per day'
        unit_of_meaurement: 'mm' # or cm
        state_class: measurement # only include this if you want long term statistics 
        device_class: precipitation
        state: >
          {% set mm_per_flip = 0.2 %}
          {% if trigger.id == 'reset' %}
            0
          {% else %}
            {{ this.state | float(0) + mm_per_flip }}
          {% endif %}

Change the mm / flip value to your bucket tip volume.

Yeah, that’s basically exactly what it should be IMO. Thanks Tom, you’re the real MVP.

I should’ve been able to figure this out myself, but I always lose the overview of what kind of things HA offers to work with, since there’s so much these days.

Hi. I made a similar system and when implementing your code, I got a weird response. Each flip is added but with the half value of the previous one. It means, the sum tends to 1. What’s wrong?

Share your sensor config. Format it correctly for the forum.

- trigger:
      - id: count
        platform: state
        entity_id: binary_sensor.pluviometre_contact
        to:
          - 'on'
          - 'off'
        from:
          - 'on'
          - 'off'
      - id: reset
        platform: time
        at: "00:00:00"
    sensor:
      - name: 'Rain per day'
        unit_of_measurement: 'mm' # or cm
        state_class: measurement # only include this if you want long term statistics
        unique_id: pluie_par_jour
        device_class: precipitation
        state: >
          {% set mm_per_flip = 0.5 %}
          {% if trigger.id == 'reset' %}
            0
          {% else %}
            {{ (this.state | float(0) + 1) * mm_per_flip }}
          {% endif %}

Yeah that’s not going to work. Not sure what I was thinking. Try this instead:

        state: >
          {% if trigger.id == 'reset' %}
            0
          {% else %}
            {{ (this.state | float(0) + 0.5 }}
          {% endif %}

I’ve corrected my original post too.

I’m also getting a strange value error. Instead of adding 0.1, the template below adds 0.2. Same for when I set it to 0.5, it adds 1. Seems like it’s triggering twice, but I don’t know how I can test that.

I changed the + 0.1 to * 1.1 and reset the value to 1. After clicking the switch twice, the value is now 1.4641, which equals to 1 * 1.1 * 1.1 * 1.1 * 1.1, so it’s definitely triggering twice. The question is: why?

  - trigger:
    - id: reset
      platform: state
      # entity_id: "binary_sensor.aqara_bedroom_door_open_closed"
      entity_id: "input_boolean.test_rain"
      to:
        - 'on'
        - 'off'
      from:
        - 'on'
        - 'off'
    - id: reset
      platform: time_pattern   # Had to change this, was throwing an error
      hours: "0"
      minutes: "0"
    sensor:
      - name: 'Rain per day test 3'
        unique_id: "rain_per_day_test"
        state_class: measurement # only include this if you want long term statistics 
        device_class: precipitation
        unit_of_measurement: mm
        state: >
          {{ this.attributes.flips | float(0) * (states("sensor.aqara_rain_meter_rainfall_per_tick") | float) }}
        attributes:
          flips: >-
            {% if trigger.id == "count" %}
              {{ this.attributes.flips | float(0) + 1 }}
            {% elif trigger.id == "reset" %}
              0
            {% endif %}

Edit: Yaml updated to also expose the flips attribute. The yaml works fine, it’s just triggering twice for some reason.

In my case, I have now the expected behaviour. Thanks for correcting.
Counting twice is not what you expect : from on to off and from off to on because your device is doing “flip” & “flap”?

1 Like

No, I confirmed using an input boolean (switch) and another device I had laying around, one 1 single action, the trigger triggers twice. I tried removing one on and one off from the to and from sections, to double check that wasn’t causing it, but it still triggered twice. See my updated yaml in the post above.

Your sensor could be bouncing, see if this fixes it:

- trigger:
      - id: count
        platform: state
        entity_id: binary_sensor.pluviometre_contact
        to:
          - 'on'
          - 'off'
        for: 1
        from:
          - 'on'
          - 'off'

Also you have the wrong trigger platform look closely at mine. It is a time trigger not a time pattern trigger.

Unfortunately not, now it simply adds 2 units with a 1 second delay.

Also, for those playing along at home: You can’t have for: x twice like in this example, you can only have it once. It works for both (/all) state transitions though, so in my case with 1 for: 1 I got a 1 second delay both when going from on to off, and going from off to on.

I know, it says so in my yaml that I had to change it to prevent errors. I guess something else caused the errors though, because now I can change it back to the time platform and it works fine. Doesn’t really matter for the end result though, both would’ve fired at midnight just fine.

are you running an early version of 2023.9? If yes, there’s a bug with trigger templates where they get resolved twice. IIRC 2023.9.2 fixes it.

1 Like

What are the odds, I’m running 2023.9.1. A quick update to 2023.9.2 confirms that was indeed the issue. Imagine the rabbit hole this could’ve lead to… Thanks Petro.

1 Like

The spelling is wrong on unit_of_measurement.

1 Like

This topic is old, but I recently stumbled upon the same behavior. A solution I used is to correct it in the rainfall calculation, Since the sum of the flips_on and flips_off sensors will always be one more than what is anticipated, you can just remove it in the template sensor that calculates the total rainfall:

      - name: Rainfall/day mm
        state_class: measurement
        unique_id: rainfall_day
        unit_of_measurement: mm
        icon: mdi:weather-pouring
        state: >-
          {% set count = (states('sensor.aqara_rain_sensor_flips_on') | int(0)) + (states('sensor.aqara_rain_sensor_flips_off') | int(0)) %}
          {# subtract 1 since the starting state is always 'on' or 'off' #}
          {% set mm = (count-1) * 0.52615 %}
          {% if count >= 0 %}
            {{ mm|round(1, 'floor') }}
          {% endif %}

Mostly just noting this in case anybody else ends up in this thread. Tom’s solution works well, too. I was vaguely worried about the count being off if my HA instance was offline at the stroke of midnight. As it happens, I now have both the individual on/off counters from history_stats and the template one running on my instance.

Cheers,
Ben