說到我房間裡的 IoT 控制系統,從 2021 年起我就一直在用一套自己開發的 IoT 協議名為 Home Dynamic。這套系統的原理和詳情可在我另一篇文章( 從零開始的 IoT 系統設計 )裡找到,但是簡單來說它就是一個很簡單的 HTTP RESTful request 模型下的迷你 IoT 系統,可以用於開關電燈和透過 Tasmota firmware 來控制幾個 Sonoff 的 WiFi Smart Switch 而已。
到最近,因為我香港的房間要整修,所以我就把房間裡有點 hacky 的系統升級到新的自動化系統。Home Dynamic v2 (簡稱 HDSv2)雖然在設計的時候已經有考慮到很多不同的使用場景和可能出現的問題(如 off grid control,伺服器 / relay 的 SPOF 等等),但是其控制 latency 總是讓我覺得有點煩惱。即使後來 ArozOS 改用 Golang 重寫,從按按鈕到電燈真的亮起的時間大概也只是在 2 – 3 秒內,這個速度跟我去按一個物理開關還是有很明顯的差別。所以在新裝潢的房間裡,我採用了一個更新版本的 HDS 協議來開發我的新自動化系統,現在我把它暫稱為 HDSv3。
控制器硬體部分
那說到 IoT 跟自動化,在提軟體之前一定要先講講硬體。畢竟只要硬體夠強,軟體再爛也是能跑得很順暢(望向 python) 。這次為了未來的擴展性和標準化,這次我選用了半工業級的硬體。下圖中是我用的繼電器模組,是一片市售的 4 路 WiFi 繼電器模組。它是使用 ESP12E 作為主控制器,跟先前的 HDSv2 一樣都是基於相同的 MCU。因此大部分 HDSv2 的源碼能夠直接移植到 v3 然後下載到這片板子上。雖然這片東西可以使用 110 – 220V 輸入,但是因為我原先整套系統都是用 24V 的,因此這部分的機能就白白被我浪費掉了(
那當然,這片東西不能就這樣放在我的桌面上。因此我買了一個 DIN Rail 用的外殼,然後把整個組好的安裝到 DIN Rail 上。
那你可能會好奇,既然是控制燈光,那一個簡單的繼電器模組就可以做到了。旁邊那兩個盒子又是甚麼?
如果你仔細看一下那個繼電器模組的照片,你就會發現那個模組真的單純在做切換而已,它本身並沒有供電能力。所以為了讓接上去的 LED 燈條有電力供應,就必須透過另一個裝置為 Relay 的 NO (Normally Open)端供電。這裡中間的模組就是作為一個 power distribution hub 的用法來提供 4 個相同於 Vin 的輸出和 3 個可調節的輸出。
而最左邊的是 LED strip 的限流模組,大概就是因為 24V 的燈條用 24V 供電的話會太光,所以那個小黑色模組裡面是一個簡單的 XL6009 自動升降壓模組來把電壓調整到大約 19.2V (我喜歡的亮度)
軟體與控制部分
講到軟體部分,就不得不提一下 IoT 技術了。說真的,雖然我知道很多不同的 IoT 通訊協議,從 MQTT(DIY 很多人用,基於 TCP/IP)、 Zigbee (IKEA 那套)到工業用的 RS485 / RS232 之類的,我還是比較喜歡用 2.4Ghz WiFi。雖然距離短、用電量高,但是本來我的裝置就是用來控制電源的(aka 長期會有電源供應),加上香港地方實在太少,我想盡量省下一個放 hub 的空間 + 本身房間已經有 WiFi 覆蓋,所以自然地 WiFi 是最好的選擇,所以我還是選擇了基於 TCP/IP 的協議。
考慮到設備的相容性、不用額外安裝程式便能控制等優點,在眾多基於 TCP/IP 的協議下我選擇了 RESTFUL。一來是所有手機都有網頁瀏覽器,即使伺服器炸掉只要有一台手機能連接到同一網絡便可以透過 p2p 的方式控制 IoT 裝置。另一個好處是 RESTFUL API 實在太通用了,從 ESPHome 到 Home Assitant,最好支援的裝置類型依然是基於 RESTFUL API 的裝置,再加上怎樣看 HTTP request 這東西在未來 10 年應該都會還存在(畢竟是 Web 技術的基礎),選它一定沒錯(
而為了解決 HDSv2 每次一定要打開手機連上伺服器才能開關電源的問題,v3 在每個裝置中加入了 mDNS resolver。只要透過 RESTFUL API / hardcode 一個要控制的 device 的 UUID 進去,signaling device 便能透過定期 / 即時 resolve mDNS address 到 IPv4 地址,然後透過 http client 來讓 worker device 動作。你有發現一個神奇的部分了嗎?就是 mDNS resolve 這功能其實不必要很複雜的 network stack 也能做到,所以為了控制我這個新的 Relay module,我開源了一套 5 路的 IoT 開關。
這東西在按下去的時候就可以對應到 Relay module 上面的 4 個繼電器,透過 resolve mDNS 的方式來無線控制燈光。而最下面的按鈕是為了 update resolve 用的,例如說大停電之後 router 重啟 DHCP table 指派的 IP 可能會跑掉,這個時候按一下最後一個按鈕便能手動讓 MCU 重新 resolve 一次 mDNS 並更新存在裡面的 IPv4 地址。當然,這個動作也可以使用類似 task scheduler 之類的 library 定期更新,但是我開發這個是自用的就不搞這麼複雜了。
最後效果
最後我決定把第一個 relay 用給牆壁上的 passive lighting LED strip 用。效果還是滿不錯的。留意看下圖,在置物架木板底部黏著 IoT 的開關按鈕;而在牆壁跟木窗台之間安裝了 2米的暖光 LED 燈條 。我覺得像這樣整套 IoT 系統被藏在看不到的地方才是最好的設計方案。