將雨量計改造成能夠透過Zigbee無線通訊整合到Home Assistant

玩Home Assistant快要四年半了,這是一個比較早期就做好的裝置,因為電池沒電了,換電池清理一下,順便寫個記錄。當初用意是戶外如果下雨,我可以收到通知然後把衣服收進來,更進階的用法是讓電動曬衣架自己縮回去?但這些玩法在我買了烘衣機之後都變得毫無意義了。

這個雨量計是一個小型氣象站的配件,它的外觀就是一個盒子,盒子上的集水槽中間有個洞讓雨水可以從這裡流下去。

拆開外殼後會看到一個像翹翹板的裝置,雨水從集水槽的洞流進來後,會累積在較高處的翹翹板上,累積到一定的量之後會往下傾斜將雨水排掉,換另一邊繼續收集雨水。每一次收集、集滿、傾斜和排水的過程所收集到的雨水體積是固定的,這是它的原理。

翹翹板中間有一塊小磁鐵,左右傾斜的過程中會觸發凹槽裡電路板上的磁簧開關,磁簧開關上有二條導線連到小型氣象站主機上,這樣主機就可以收到磁簧開關短路和斷路的訊號。

但我沒有小型氣象站的主機,我只有Home Assistant的主機跟Zigbee閘道器,把它改成透過Zigbee無線通訊連接Home Assistant是比較好處理的方式。拿一個小米Zigbee版本的門窗感應器並將外殼拆開,鈕扣電池背面的電路板上可以看見磁簧開關,如下圖箭頭處,將磁簧開關二側剪掉並將雨量計的二條導線取適當長度焊上去。

焊完後的樣子,將門窗感應器的電路板塞進雨量計凹槽中,跟雨量計的電路板放在一起。

雨水會經由下方的孔洞排出去,不會有什麼積水的問題。

依序組裝回去,這樣就結束了。不過這個雨量計有點輕,在過去的使用經驗裡,它是比較容易被吹倒的,螺絲孔是要把它固定在小型氣象站上,最後固定在角鋼的橫桿上應該就可以了。

再來是算術的部分,經過多次的測試,拿量杯量100mL的水倒下去,平均會觸發60次,也就是一次大約1.67mL,換算成立方公厘為單位的話是1670。雨量計集水槽面積約為49mm*108mm左右,所以單次觸發的累積雨量是

1670 / (49*108) = 0.3156mm

回到Home Assistant,首先需要一個counter計算觸發次數。

rain_today:
  name: Rain_Today
  initial: 0
  restore: true
  step: 1
  icon: mdi:counter

再來是二個automation,第一個automation會在門窗感應器由on變成off時將counter.rain_today增加一個step的值,第二個則是在00:00時將counter.rain_today歸0。

- alias: Alarms:RainToday_Counter
  trigger:
    - platform: state
      entity_id: binary_sensor.balcony4ff_raingauge_contactsensor_contact
      from: "on"
      to: "off"
  condition:
    - condition: numeric_state
      entity_id: sensor.detectors_homeassistos_uptime
      above: 0.03
  action:
    - service: counter.increment
      entity_id: counter.rain_today
  mode: queued

- alias: Alarms:RainToday_Counter_Reset
  trigger:
    - platform: time
      at: "00:00"
  action:
    - service: counter.reset
      entity_id: counter.rain_today
  mode: queued

所以當天雨量的sensor就是觸發次數*03156後,取小數點下一位無條件捨去。

- platform: template
  sensors:
    rain_today:
      value_template: >-
        {% set count = states('counter.rain_today') | int %}
        {{ count * 0.3156 | round(1, 'floor') }}
      unit_of_measurement: mm

開始下雨時要通知的寫法是這樣思考的,雨可以是一陣一陣,但下雨通知絕對不能是雨量計每觸發一次就通知一次,所以

  1. 雨量計被觸發時,檢查如果過去一小時沒下雨,就發出下雨通知。
  2. 過去五分鐘沒下雨,就發出雨停通知。

所以先準備過去五分鐘和過去一小時的雨量計算,可以從history_stats下手,需要二個sensor,分別計算過去一小時和過去五分鐘到現在,雨量計被觸發的次數。程式碼可以這樣寫

- platform: history_stats
  name: Rain_in_1hour
  entity_id: binary_sensor.balcony4ff_raingauge_contactsensor_contact
  state: "off"
  type: count
  end: "{{ now() }}"
  duration:
    hours: 1

- platform: history_stats
  name: Rain_in_5min
  entity_id: binary_sensor.balcony4ff_raingauge_contactsensor_contact
  state: "off"
  type: count
  end: "{{ now() }}"
  duration:
    minutes: 5

再來是下雨的通知,當符合「雨量計被觸發」且觸發時「過去一小時的累積雨量為0」就會執行Line通知。本來還有個tts廣播,但因為買了烘衣機後這個機制就沒這麼重要,所以最後拿掉了。

- alias: Alarms:Start_Raining_Notify
  initial_state: true
  trigger:
    - platform: state
      entity_id: binary_sensor.balcony4ff_raingauge_contactsensor_contact
      from: "on"
      to: "off"
  condition:
    - condition: template
      value_template: "{{ states.sensor.rain_in_1hour.state | float == 0 }}"
  action:
    - service: notify.notify_line
      data:
        message: 開始下雨了。
    - service: automation.turn_on
      data:
        entity_id: automation.alarms_stop_raining_notify
    - service: automation.turn_off
      data:
        entity_id: automation.alarms_start_raining_notify
  mode: queued

最後是雨停的通知,只要過去五分鐘累積雨量為0就表示雨停了。

- alias: Alarms:Stop_Raining_Notify
  initial_state: false
  trigger:
    - platform: template
      value_template: "{{ states.sensor.rain_in_5min.state | float == 0 }}"
  action:
    - service: notify.notify_line
      data:
        message: 雨停了。
    - service: automation.turn_on
      data:
        entity_id: automation.alarms_start_raining_notify
    - service: automation.turn_off
      data:
        entity_id: automation.alarms_stop_raining_notify
  mode: queued

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

返回頂端