☔ DIY Zigbee rain gauge

Depends on the solder you are using, best to consult the datasheet. Here’s a quick reference chart: Soldering Temperature Chart

60/40 lead solder tends to be the easiest to start out with, I personally use Kester K100LD lead free (it’s almost as easy to work with). As with any solder make sure you clean your hands and clean your workspace after working, don’t inhale the fumes.

If you can purchase some perfboard it may be worth practicing soldiering and desoldering wires or other cheap components from it until you get the hang of it.

Good morning, another stupid question. Does anyone have an idea for an automation that tells you whether it’s raining or not and doesn’t constantly change every few minutes? Best regards :wave:t2:

Something like this might be more suitable for detecting rain.

You might also be able to hook it up to an aqara sensor instead of an ESP.

1 Like

I’ve made a small jig to hold the aquara sensor in the same form factor as the original sensor. The reed switch is still 90deg from the optimal orientation but it works fine for me. This is placed so the reed switch is closed half the time, not momentarily every tip.

https://www.printables.com/model/823854-rain-gauge-aquara-holder

3 Likes

Hi All

I 3D printed this one / Used Aqara sensor SS4H-RG Smart Rain Gauge – DIY project based on ESP32 and ESPHome – Smart Solutions for Home

But I need some help, this is my config. But for some reason when there is no rain it still reports 0.5mm for the day

I cant seem to workout what is wrong with my code? I want to get this fixed because its adding approx 15mm to every months rainfall total.

sensor:
 - platform: history_stats
   name: "Aqara Rainsensor flips/on"
   entity_id: binary_sensor.rainmeter_opening
   state: "on"
   type: count
   start: "{{ now() - timedelta(hours=24)}}"
   end: "{{ now() }}"
 - platform: history_stats
   name: "Aqara Rainsensor flips/off"
   entity_id: binary_sensor.rainmeter_opening
   state: "off"
   type: count
   start: "{{ now() - timedelta(hours=24)}}"
   end: "{{ now() }}"
template:
  - sensor:
      - name: Rainfall [day]
        state_class: measurement
        unique_id: rainfall_day
        unit_of_measurement: mm
        icon: mdi:weather-pouring
        state: >-
          {% set count = (states('sensor.aqara_rainsensor_flips_on') | int(0)) + (states('sensor.aqara_rainsensor_flips_off') | int(0)) %}
          {% set mm = count * 0.52615 %}
          {% if count >= 0 %}
            {{ mm|round(1, 'floor') }}
          {% endif %}

Does anyone have any ideas (this is my first experience with HA so I am new to the code)

thanks

Your rain gauge works differently than the one in the original post. The original post only counts the on states, this one counts both states.

I suspect that the history_stats sensor binary_sensor.rainmeter_opening counts 1 if the current state is either on or off, regardless if it changed or not. Or do you restart HA every night or something like that, causing a state change?

It looks like @ekainz uses the same counting method, perhaps he can share his config :slight_smile:

Unfortunately, nothing works anymore :frowning:
What could be the problem?
Is this a HomeAssistant bug?

@ekainz Can you please share your actual config? :pray:

It means that zwischenTropfen has no value. Print all the variables there to see what is wrong.

HA server is only restarted when there is a power outage.

I wonder if the state is resetting itself on its own?

I don’t understand that. That’s all there is to it. What else should I add?

Here again the whole part from the configuration.yml:

  - sensor:
    - name: "Regen Intensitaet"
      unique_id: regen_intensitaet
      state: >
          {% set letzterTropfen = (as_timestamp(now()) - as_timestamp(states.binary_sensor.diy_zigbee_regenmesser_contact.last_changed)) %}
          {% set zwischenTropfen = states('sensor.regen_sensor_zeit_zwischen_tropfen') | as_timedelta %}
          {% set max_zeit = max(letzterTropfen, zwischenTropfen.total_seconds()) %}
                        
          {{ (0.30303 / (max_zeit / 3600)) | round(1, default=0) }} {# replace 0.30303 with your mm of rain per tip value #}
      state_class: measurement
      device_class: precipitation_intensity
      unit_of_measurement: "mm/h"
  - trigger:
      - platform: state
        entity_id: binary_sensor.diy_zigbee_regenmesser_contact
  - sensor:
      - name: Regen Sensor Zeit zwischen Tropfen
        unique_id: regen_sensor_zeit_zwischen_tropfen
        state: >
            {{ (now() - trigger.states.binary_sensor.diy_zigbee_regenmesser_contact.last_changed).total_seconds() }}
        state_class: measurement
        unit_of_measurement: "s"
  - sensor:
      - name: Regen Heute
        unit_of_measurement: mm
        state_class: total_increasing
        unique_id: regen_heute
        state: >-
          {% set count = states('sensor.regensensor_flips') | int(0) %}
          {% set mm = count * 0.30303 %}
          {% if count >= 0 %}
            {{ mm|round(1, 'floor') }}
          {% endif %}
        # If you have issues with the history sensor doubling after restarting HA, add the line below
        availability: "{{ (states('sensor.regensensor_flips') not in ('unknown', 'unavailable')) }}"

- sensor:
  - platform: history_stats
    name: Regensensor flips 
    entity_id: binary_sensor.diy_zigbee_regenmesser_contact #The aqara sensor
    state: 'off'
    type: count
    start: '{{ now().replace(hour=0, minute=0, second=0) }}'
    end: '{{ now() }}'

There’s really not much more to my config, I have an automation that increments counter.rain_sensor_tips on each tip and resets at midnight, a template to convert those values to mm, and some statistics sensors.

I recommend starting with my code verbatim, getting that to work, then editing the variable names.

sensor:
  - platform: statistics
    name: 60 Second Rainfall
    unique_id: rainfall_60sec
    entity_id: sensor.rainfall_today
    state_characteristic: sum_differences_nonnegative
    max_age:
      seconds: 60
  - platform: statistics
    name: 5 Minute Rainfall
    unique_id: rainfall_5min
    entity_id: sensor.rainfall_today
    state_characteristic: sum_differences_nonnegative
    max_age:
      minutes: 5
  - platform: statistics
    name: 15 Minute Rainfall
    unique_id: rainfall_15min
    entity_id: sensor.rainfall_today
    state_characteristic: sum_differences_nonnegative
    max_age:
      minutes: 15
  - platform: statistics
    name: 60 Minute Rainfall
    unique_id: rainfall_60min
    entity_id: sensor.rainfall_today
    state_characteristic: sum_differences_nonnegative
    max_age: 
      hours: 1
  - platform: statistics
    name: 6 Hour Rainfall
    unique_id: rainfall_6hour
    entity_id: sensor.rainfall_today
    state_characteristic: sum_differences_nonnegative
    max_age: 
      hours: 6
  - platform: statistics
    name: 24 Hour Rainfall
    unique_id: rainfall_24hour
    entity_id: sensor.rainfall_today
    state_characteristic: sum_differences_nonnegative
    max_age: 
      hours: 24
  - platform: statistics
    name: 7 Day Rainfall
    unique_id: rainfall_7day
    entity_id: sensor.rainfall_today
    state_characteristic: sum_differences_nonnegative
    max_age: 
      days: 7
  - platform: statistics
    name: 30 Day Rainfall
    unique_id: rainfall_30day
    entity_id: sensor.rainfall_today
    state_characteristic: sum_differences_nonnegative
    max_age: 
      days: 30
  - platform: statistics
    name: 365 Day Rainfall
    unique_id: rainfall_365day
    entity_id: sensor.rainfall_today
    state_characteristic: sum_differences_nonnegative
    max_age: 
      days: 365

template:
    - sensor:
      - name: "Rainfall Today"
        unit_of_measurement: mm
        state_class: total_increasing
        unique_id: rainfall_today
        state: >-
          {% set count = states('counter.rain_sensor_tips') | int(0) %}
          {% set mm = count * 0.1 %}
          {% if count >= 0 %}
            {{ mm|round(1, 'floor') }}
          {% endif %}
        availability: "{{ (states('counter.rain_sensor_tips') not in ('unknown', 'unavailable')) }}"
      - name: "Rain Intensity"
        unique_id: rain_intensity
        state: >
            {% set lastTip = (as_timestamp(now()) - as_timestamp(states.binary_sensor.rain_sensor.last_changed)) %}
            {% set betweenTips = states('sensor.rain_sensor_time_between_tips') | as_timedelta %}
            {% set max_time = max(lastTip, betweenTips.total_seconds()) %}
                        
            {{ (0.1 / (max_time / 3600)) | round(1, default=0) }}
        state_class: measurement
        device_class: precipitation_intensity
        unit_of_measurement: "mm/h"
    - trigger:
        - platform: state
          entity_id: binary_sensor.rain_sensor
      sensor:
        - name: Rain Sensor time between tips
          unique_id: rain_sensor_time_between_tips
          state: >
              {{ (now() - trigger.from_state.last_changed).total_seconds() }}
          state_class: measurement
          unit_of_measurement: "s"

Heres the automation:

alias: Rain Sensor
description: ""
trigger:
  - platform: state
    entity_id:
      - binary_sensor.rain_sensor
    from: "on"
    to: "off"
    id: "0"
  - platform: state
    entity_id:
      - binary_sensor.rain_sensor
    from: "off"
    to: "on"
    id: "0"
  - platform: time
    at: "00:00:00"
    id: "1"
condition: []
action:
  - choose:
      - conditions:
          - condition: trigger
            id:
              - "0"
        sequence:
          - service: counter.increment
            metadata: {}
            data: {}
            target:
              entity_id: counter.rain_sensor_tips
      - conditions:
          - condition: trigger
            id:
              - "1"
        sequence:
          - service: counter.reset
            metadata: {}
            data: {}
            target:
              entity_id: counter.rain_sensor_tips
mode: single

1 Like

I personally just found it easier to count flips with a counter helper and an automation to increment, that way home assistant restarts don’t affect my values. I find it generally less confusing.

2 Likes

Is it possible to use this method but with wifi instead of Zigbee?

Yes, you can, with an ESP32 or ESP8266. However it would probably be need to be wired to a power outlet, as wifi consumes a lot of power compared to zigbee. That’s why I used zigbee for this. For comparison, the aqara sensor has been using the same battery since I created this post. (3+ years!)

1 Like

yea. My setup will be 2 years come this June. Still reads 100% battery life which I find very strange, but it still tipping. 6.6mm of rain in the last 3 hrs as I am writing this post.

1 Like

Sadly I got this error in log file:

  • Template variable error: ‘None’ has no attribute ‘total_seconds’ when rendering ‘{% set lastTip = (as_timestamp(now()) - as_timestamp(states.binary_sensor.diy_zigbee_regenmesser_contact.last_changed)) %} {% set betweenTips = states(‘sensor.regen_sensor_zeit_zwischen_tropfen’) | as_timedelta %} {% set max_time = max(lastTip, betweenTips.total_seconds()) %} {{ (0,30303 / (max_time / 3600)) | round(1, default=0) }}’

And the intensity is always at 0,0mm/h also when its raining heavy :frowning:

Do you know why?

I’ve recently set-up the rain gauge and am very thankful for the contribution.
I don’t think the Daily Rainfall function is working and I don’t know why.
There are currently 74 sensor flips but no daily rainfall amount. Rainfall today = unknown, same for weekly, monthly and annual, of course.
Here is an exerpt of my configuration.yaml -

group: !include groups.yaml
automation: !include automations.yaml
script: !include scripts.yaml
scene: !include scenes.yaml
sensor: !include sensors.yaml
#template: !include templates.yaml

# Example configuration.yaml entry
utility_meter:
  energy:
    source: sensor.pixel_4a_steps_sensor
    name: Daily Steps
    cycle: daily
  rain_week:
    source: sensor.rainfall_today 
    cycle: weekly
    unique_id: rainfall_week
  rain_month:
    source: sensor.rainfall_today 
    cycle: monthly
    unique_id: rainfall_month
  rain_year:
    source: sensor.rainfall_today 
    cycle: yearly
    unique_id: rainfall_year
    
template:
   - sensor:
       - name: Rainfall Today
         device_class: precipitation
         unit_of_measurement: in
         state_class: total_increasing
         unique_id: rainfall_today
         state: >-
          {% set count = states('sensor.rainsensor_flips') | int(0) %}
          {% set in = count * 0.01193 %}
          {% if count >= 0 %}
            {{ in|round(1, 'floor') }}
          {% endif %}
          # If you have issues with the history sensor doubling after restarting HA, add the line below (@BigG)
          #availability: "{{ (states('sensor.rainsensor_flips') not in ('unknown', 'unavailable')) }}"

sensors.yaml exerpt below -

- platform: history_stats
  name: Rain sensor flips 
  entity_id: binary_sensor.rain_sensor_on_off
  state: 'off'
  type: count
  start: '{{ now().replace(hour=0, minute=0, second=0) }}'
  end: '{{ now() }}'
      

Input is appreciated.
Thanks!

Thought that I had discovered an error.
I replaced ‘sensor.rainsensor_flips’ with "sensor.rain_sensor_flips’ but no joy.

Okay, so the flips are working. What is the entity id of that sensor? That should be added to the following code block


{% set count = states('sensor.rainsensor_flips') | int(0) %}
{% set in = count * 0.01193 %}
{% if count >= 0 %}
    {{ in|round(1, 'floor') }}
{% endif %}

Paste this code block into the developer tools, to see what the output is.

Any errors in the logs by the way?

Thank you for responding.
Here is what I pasted into Developer Template:

{% set count = states('sensor.rain_sensor_flips') | int(0) %}
{% set in = count * 0.01193 %}
{% if count >= 0 %}
    {{ in|round(1, 'floor') }}
{% endif %}

The output is 0.4 (39 counts currently today).
I feel like I am missing something obvious. I’m going to include below the configuration and sensors files again. Perhaps someone will see something that I am not seeing.
configuration.yaml

# Configure a default setup of Home Assistant (frontend, api, etc)
default_config:

# Text to speech
tts:
  - platform: google_translate

group: !include groups.yaml
automation: !include automations.yaml
script: !include scripts.yaml
scene: !include scenes.yaml
sensor: !include sensors.yaml
#template: !include templates.yaml

# Example configuration.yaml entry
utility_meter:
  energy:
    source: sensor.pixel_4a_steps_sensor
    name: Daily Steps
    cycle: daily
  rain_week:
    source: sensor.rainfall_today 
    cycle: weekly
    unique_id: rainfall_week
  rain_month:
    source: sensor.rainfall_today 
    cycle: monthly
    unique_id: rainfall_month
  rain_year:
    source: sensor.rainfall_today 
    cycle: yearly
    unique_id: rainfall_year
    
template:
   - sensor:
       - name: Rainfall Today
         device_class: precipitation
         unit_of_measurement: in
         state_class: total_increasing
         unique_id: rainfall_today
         state: >-
          {% set count = states('sensor.rain_sensor_flips') | int(0) %}
          {% set in = count * 0.01193 %}
          {% if count >= 0 %}
            {{ in|round(1, 'floor') }}
          {% endif %}
          # If you have issues with the history sensor doubling after restarting HA, add the line below (@BigG)
          #availability: "{{ (states('sensor.rain_sensor_flips') not in ('unknown', 'unavailable')) }}"

sensors.yaml

- platform: rest
  name: JSON soil
  json_attributes:
    - dt
    - t10
    - moisture
    - t0
  scan_interval: 50000
  resource: https://api.agromonitoring.com/agro/1.0/soil?polyid=
  value_template: "{{ value_json.soildata }}"
- platform: template
  sensors:
    soil_10cm:
      friendly_name: "Soil at 10cm"
      value_template: "{{ (state_attr('sensor.json_soil', 't10') | float * 9/5 - 459.67) | round(2) }}"
      entity_id: sensor.soil_10cm_f
      unit_of_measurement: "F"

    soil_moisture:
      friendly_name: "Soil moisture"
      value_template: "{{ state_attr('sensor.json_soil', 'moisture') }}"
      entity_id: sensor.soil_moisture
      unit_of_measurement: "VWC"

    soil_surface:
      friendly_name: "Soil Surface"
      value_template: "{{ (state_attr('sensor.json_soil', 't0') | float * 9/5 - 459.67) | round(2) }}"
      entity_id: sensor.soil_surface_f
      unit_of_measurement: "F"
      
- platform: history_stats
  name: Rain sensor flips 
  entity_id: binary_sensor.rain_sensor_on_off
  state: 'off'
  type: count
  start: '{{ now().replace(hour=0, minute=0, second=0) }}'
  end: '{{ now() }}'