☔ DIY Zigbee rain gauge

What a satisfying project, thanksto parrel for his effort. Regarding the Utility Meter, does it use the calendar to roll over or is it a simple timer ie if I commence measuring mid-week, when will the weekly rollover occur, same with the monthly, when will that happen?
Thanks.

Could I also ask, where do I put the code for the apex charts?
Many thanks.

Thank you! It will be reset at the beginning of the given period, more info here: Utility Meter - Home Assistant

The Apexcharts code needs to be added to your dashboard (Lovelace). First make sure you have installed the Apexcharts addon in HACS. You can add it the same way as you add other cards to your dashboard, but then click on “view code editor” and paste the YAML

Did that, all working now, thanks so much.

1 Like

Finally rain. I received confirmation that it works perfectly.

1 Like

Thanks for the writeup, @parrel!

I implemented one for my yard; here are some things I learned:

  1. You can simplify the build by just using the Aqara sensor board as-is and replacing the Misol sensor board with it. Details: The Aqara sensor has its own reed sensor already on the board and it is happily triggered by the magnet in the Misol rain gauge. If you remove the PC board from the Misol sensor and keep the plastic shim (inner “tray” that the board sits in within the Aqara sensor housing), this allows the sensor board to slide into the location of the Aqara sensor board that came with the Misol sensor. I used some scrap rubber pieces to ensure the Aqara sensor board remains in the correct position within the Misol housing, and this works great so far. Super quick and no soldering required!

  2. I saw some double-counting of bucket tips occasionally when using the Aqara reed sensor - I suspect it’s that there’s some recoil when the bucket tips, and sometimes it’s just enough to trip the sensor a second time. It also could be that that Aqara sensor is more sensitive than the OEM one in the Misol gauge. I’ve resolved this by moving the reed sensor all the way to one side of the Misol housing so that the sensor reads open when the bucket is tipped to one side and closed when tipped to the other. I’m guessing there may be some loss of battery life vs. the original design of only reading closed briefly when the bucket was in the process of tipping.

  3. I tried calibrating my sensor via adding drops with a syringe until it tipped, but I got inconsistent results (20% or more variation). I then set up a rig to empty a 500ml water bottle into the sensor over about an hour. This was reasonably consistent (~5% variation), but read about 20% higher than the syringe method. Using the 500ml bottle for calibration, I got about 2.0ml per bucket tip vs. the 1.67ml mentioned in the original post.

  4. I’ve found it useful to have a debug switch (input_toggle Helper) that prevents bucket tips from counting toward actual rainfall data; this way, if you need to calibrate the sensor, move it, replace the battery, etc., you can prevent it from errantly counting rainfall and polluting your long-term statistics.

  5. Home Assistant does a good job of metric/imperial conversions if you want that. You can set up all your templates/sensors using metric units and then you can have HA display imperial units in the UI if you like. That keeps the calculations simpler.

And some questions I have for those who’ve implemented this sensor:

  1. When observing the sensor operating with the cover off, I noticed that frequently there are a few drops of water that stay in the bucket on the side that should have been empty. This affects how much water it takes for the next bucket tip. I tried applying some (automotive) wax to the inside of the bucket and putting some dry lube spray on the bucket pivot, but this did not solve the problem. I’m curious if others have noticed this and found a good way to prevent water from staying in the bucket as it tips. Note the water in the right side of the bucket in the picture below. I imagine this affects the accuracy/consistency of the sensor.
    image

  2. The rain intensity sensor calculation keeps the last value indefinitely until there’s another bucket tip. Is there a best practice for getting the intensity to go back to zero once it stops raining? Here is an example from when I ran my irrigation this morning; the bottom graph (intensity) should go back to zero once there is no more rain at approx 7:30AM. I’m sure there’s some templating that would address this; just wondering if there’s an easier way.

Finally, here are some code examples for some of the things I did a little differently than the original post, in case others find them useful.

Prod and Debug Bucket Tip Sensors:
(in sensors.yaml file)

- trigger:
    - platform: state
      entity_id: binary_sensor.rain_sensor_bucket
      from: "on"
      to: "off"
    - platform: state
      entity_id: binary_sensor.rain_sensor_bucket
      from: "off"
      to: "on"
  binary_sensor:
    - name: "Rain Bucket Tipped - Prod"
      unique_id: RainBucketTippedProd
      state: "{{ is_state('input_boolean.rain_sensor_debug_mode', 'off') }}"
      auto_off: 0.100

- trigger:
    - platform: state
      entity_id: binary_sensor.rain_sensor_bucket
      from: "on"
      to: "off"
    - platform: state
      entity_id: binary_sensor.rain_sensor_bucket
      from: "off"
      to: "on"
  binary_sensor:
    - name: "Rain Bucket Tipped - Debug"
      unique_id: RainBucketTippedDebug
      state: "{{ is_state('input_boolean.rain_sensor_debug_mode', 'on') }}"
      auto_off: 0.100

Rainfall Quantity and Intensity Sensors (including calibration data):
(in templates.yaml)

- sensor:
    - name: Rainfall Today - Debug
      unit_of_measurement: mm
      state_class: total_increasing
      device_class: precipitation
      unique_id: RainfallTodayDebug
      state: >-
        {% set sensor_area_cm2 = (10.96 * 4.96) |round(2) %}
        {% set rain_ml_per_rainfall_mm = sensor_area_cm2 * 0.1 %}
        {% set calibration_water_bottle_capacity_ml = 500 %} 
        {% set calibration_tips_per_bottle = (247, 259, 259, 247, 266, 262, 244, 266) %}
        {% set rain_per_tip_ml = (calibration_water_bottle_capacity_ml / average(calibration_tips_per_bottle)) | round(2) %}
        {% set rainfall_per_tip_mm = (rain_per_tip_ml / rain_ml_per_rainfall_mm) | round(2) %}
        {% set tip_count = states('sensor.rain_sensor_bucket_tips_today_debug') | int(0) %}
        {% set rainfall_today_mm = (tip_count * rainfall_per_tip_mm)| round(1, 'floor') %}
        {{ rainfall_today_mm }}
      availability: "{{ (states('sensor.rain_sensor_bucket_tips_today_debug') not in ('unknown', 'unavailable')) }}"

    - name: Rainfall Intensity - Debug
      unit_of_measurement: mm/h
      state_class: measurement
      device_class: precipitation_intensity
      unique_id: RainIntensityDebug
      state: >-
        {% set rainfall_gradient_hourly = ((state_attr('binary_sensor.rainfall_today_trend_debug', 'gradient') | float(default=0)) * 3600) | round(1, 'floor') %}
        {{ max(rainfall_gradient_hourly, 0) }}

And the values of the intermediate variables in the Rainfall Today sensor above:

Sensor Area (cm^2): 54.36
Rain (ml) per Rainfall (mm): 5.436
Calibration Water Bottle (ml): 500
Calibration Tips per Bottle (ml): (247, 259, 259, 247, 266, 262, 244, 266)
Rain (ml) per Bucket Tip: 1.95
Rainfall (mm) per Bucket Tip: 0.36
7 Likes

Thank you for the work and share it!

I make this adapter and share it in Thingiverse Aqara zigbee rain meter adapter by gallynero - Thingiverse

1 Like

Great write up and I like the debug sensor and the way you measured the rain gauge.

For the remaining water, you could try rainx, it works very well on glass, maybe it does on plastics as well.

I wanted to align my daily rainfall with my local weather provider. Their rainfall data runs from 7am-7am so I made these changes

  • platform: history_stats
    name: Rainsensor flips
    entity_id: binary_sensor.lumi_lumi_sensor_magnet_aq2_opening_2
    state: “off”
    type: count
    start: ‘{{ now().replace(hour=7, minute=0, second=0) }}’
    duration:
    hours: 24

but the counter still reset at 00 hrs instead of 07 hrs. What am I doing wrong? Thanks.

- platform: history_stats
    name: Rainsensor flips
    entity_id:  binary_sensor.lumi_lumi_sensor_magnet_aq2_opening_2
    state: "off"
    type: count
    start: '{{ now().replace(hour=7, minute=0, second=0) }}'
    duration:
      hours: 24

From the docs:

Next 4 pm: 24 hours, from the last 4 pm till the next 4 pm. If it hasn’t been 4 pm today, that would be 4 pm yesterday until 4 pm today. If it is already past 4 pm today, it will be 4 pm today until 4 pm tomorrow. When changing the start time, then add or subtract to the 8-hour buffer to match the next midnight.

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

When I inserted that line I got this error message
Configuration invalid!

Invalid config for [sensor.history_stats]: You must provide exactly 2 of the following: start, end, duration. Got {‘platform’: ‘history_stats’, ‘name’: ‘Rainsensor flips’, ‘entity_id’: ‘binary_sensor.lumi_lumi_sensor_magnet_aq2_opening_2’, ‘state’: ‘off’, ‘type’: ‘count’, ‘start’: ‘{{ now().replace(hour=7, minute=0, second=0) }}’, ‘end’: ‘{{ (now().replace(minute=0, second=0, microsecond=0) + timedelta(hours=8)).replace(hour=16) }}’, ‘duration’: {‘hours’: 24}}. (See ?, line ?).

  • platform: history_stats

    name: Rainsensor flips

    entity_id: binary_sensor.lumi_lumi_sensor_magnet_aq2_opening_2

    state: “off”

    type: count

    start: ‘{{ now().replace(hour=7, minute=0, second=0) }}’

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

    duration:

    hours: 24

Remove start:

Oh OK, I am hopeless at yaml but at least my rain sensor works great :grin:

1 Like

Yeah, I thought about Rain-X first, but the bottle specifically says not to use on plastics unless approved by the plastic manufacturer… I’m assuming that means it eats some types of plastics. Anyone tried it already? :slight_smile:

I decided that I wasn’t ok with the Rain Intensity sensor keeping its last non-zero value until either more rain comes or the clock strikes midnight. See the 3rd graph below:

So I made a new history_stats sensor to track the amount of rain that’s fallen in the last 10 minutes. Here’s the (sensors.yaml) YAML code:

- platform: history_stats
  unique_id: RainSensorBucketTipsLast10MinutesDebug
  name: Rain Sensor Bucket Tips Last 10 Minutes - Debug
  entity_id: binary_sensor.rain_bucket_tipped_debug
  state: 'on'
  type: count
  start: '{{ (now() - timedelta(minutes=10)) }}'
  end: '{{ now() }}'  

From there, I modified my Rain Intensity template sensor to look like this. Here’s the (templates.yaml) YAML code:

- sensor:
    - name: Rainfall Intensity - Debug
      unit_of_measurement: mm/h
      state_class: measurement
      device_class: precipitation_intensity
      unique_id: RainIntensityDebug
      state: >-
        {% set rainfall_gradient_hourly = ((state_attr('binary_sensor.rainfall_today_trend_debug', 'gradient') | float(default=0)) * 3600) | round(1, 'floor') %}
        {% if states('sensor.rain_sensor_bucket_tips_last_10_minutes_debug')|float(default=0) > 0.000 %}
          {{ max(rainfall_gradient_hourly, 0) }}
        {% else %}
          0
        {% endif %}

And here’s what the new behavior looks like when I artifically made it rain by tipping the bucket a bunch of times manually:

image

Essentially, when the rain stops, the Rain Intensity sensor holds its value for 10 minutes and then drops to zero. I might set the “10 minute” value to something lower eventually, but for now, it seemed like a reasonable starting point.

4 Likes

Looks really nice and many thanks for sharing your code. Unfortunately I don’t really get how to add this. I’ve added both code snippets to the appropriate yaml files, but can’t seem to figure out where to hook up the rain flips sensor.

The rainfall debug sensor is available in HA, but since I have nowhere a match with my rain flips sensor, it stays 0.

Does anyone have an STL file for an equivalent of the Misol housing?

Or even the fairly detailed dimensions so I can CAD one up to share?

Is there a way to delete the old data used for testing at all

hello,
nice project and thanx to all crazy guys here with all this crazy ideas and solutions!
as a hassio fool, it was really hard, but i was happy to get this project run :slight_smile:

i tried @erikg s solution, to reset the Rain Intensitiy after 10min, when no rain falls, but i cant get it working.
with Template Editor i always getting “5”, doesnt matter if i use < or > in the if statement?
sensor.regensensor_flips_zero_resets shows me “0” in the DevTools States
even when i change state with SetState to other values, i never get another result than 5?? why?
i had tried |int() as well?

herer is the part from the TemplateEditor…

          {% if states('sensor.regensensor_flips_zero_reset')|float(0) > 0.000 %}
            {{ max(rain_hour, 0) }}
          {% else %}
            5  #5 just for testing, should be 0
          {% endif %}

what i made wrong?
thank you in advance
br
Frank