はじめに
このご時世、加湿器は大切です。
このご時世でなくても、東京などの雪の降らない地方の冬は乾燥しやすいために加湿器は必須といえます。
今回は以下のものを組み合わせ、加湿器をスマートにしてSiriから制御することができるようにします。
- 普通の加湿器
- WiFiで制御できるコンセント
- Raspberry Pi
- 温度湿度センサー
- CdS
- AD変換IC
加湿器がスマートになることによって以下のことができるようになります。
- SiriからのON/OFF、目標湿度の設定
- タイマーや他のセンサーなどと組み合わせたON/OFF
- 目標湿度に従った制御
- タンクの水がなくなったのを検出してお知らせ
用意するもの
加湿器とラズパイ以外にかかるお金は合計しても二千円程度です。
Raspberry Pi
ご家庭にある普通のラズパイでGPIOがいくつか余っていればそのまま相乗りできます。
我が家では熱帯魚水槽や各種センサーが繋がっている3bに加湿器も繋げています。
加湿器
加湿器は余計な機能のないものを用意します。
スタート・ストップボタンとかタイマーとか中途半端に賢い機能は不要です。
「コンセントを挿せば動く、抜けば止まる」という単純さが必要です。
無駄なことはしなくていいので必要なことだけを忠実にしてくれるヤツをラズパイで手なづけます。
「中途半端はかえって面倒」とはまさに世の真理!
たとえば以下のような製品。
Amazon | アイリスオーヤマ 加湿器 加熱式加湿器 グリーン SHM-260R1-G | アイリスオーヤマ(IRIS OHYAMA) | 加湿器
我が家にあるのはもっと古い以下の製品ですが、この手の製品なんて毎年変わるものでもありません...
Amazon | VICS(ヴィックス) スチーム式加湿器 V750 | VICKS (ヴイックス) | ホーム&キッチン 通販
湿度センサー
ラズパイにつなげて湿度(と気温)がとれるセンサーです。
AM2322やDHT11などです。
温湿度センサ モジュール AM2322: センサ一般 秋月電子通商-電子部品・ネット通販
温湿度センサ モジュール DHT11: センサ一般 秋月電子通商-電子部品・ネット通販
CdSとA/D変換
今回ターゲットとする加湿器には水がなくなると赤く光るLEDがあるので、それを検出するのに使います。
適当にプルアップまたはプルダウンして測ります。
Raspberry Piではアナログ数値はそのままでは読めませんので、A/D変換をかけて読みます。
10bit 2ch ADコンバータ MCP3002-I/P: 半導体 秋月電子通商-電子部品・ネット通販
WiFi制御コンセント
以下の製品の場合はDHCPで固定IPv4を振り出すと、そのままそのIPアドレスを使って制御できます。
つまり、共有鍵のようなものは不要です。
[Amazon.co.jp: TP-Link WiFiスマートプラグ 2個セット 遠隔操作 Echo シリーズ / Googleホーム / LINE Clova 対応 音声コントロール ハブ不要 3年保証 HS105P2: ホーム&キッチン](https://www.amazon.co.jp/
/dp/B07FY4GDDQ)
工作
CdSを水切れ表示LEDの前につけ、遮光のため黒いシールで覆い、プルアップしてAD変換し、温度センサーもつなげます。
何度か試して、閾値を探します。
ソフトウェア
湿度を読む
別に目新しい話でもないので、以下を参照。
Raspberry PiとDHT11で温度・湿度を測る - Qiita
CdSを読む
別に目新しい話でもないので、以下を参照。
Raspberry Pi 3でpythonを使いA/Dコンバーターでアナログ信号を検出する! - Qiita
コンセント制御
別に目新しい話でも(ry
GitHub - softScheck/tplink-smartplug: TP-Link WiFi SmartPlug Client and Wireshark Dissector
制御プログラム本体
以下の処理をするループをまわします。
if 湿度の制御が必要 ; then
湿度を読み取る
if 現在の目標湿度より読んだ湿度が高い ; then
加湿器をオフ
else
加湿器をオン
if 加湿器稼働中 ; then
cdsの出力値を読み取る
if LED点灯 ;then
水なしフラグをたてる
else
水なしフラグをおろす
else
加湿器をオフ
homebridge
さて、ここまで駆け足でしたがここからは少し細かく...
homebridgeですが加湿器はHumidifierDehumidifier
となります。
今回は何でも制御できる便利なHttp Advanced AccessoryからCGI経由で繋げます。
GitHub - staromeste/homebridge-http-advanced-accessory: Supports all devices on HomeBridge Platform / Bridges devices to http
homebridge-http-advanced-accessory - npm
{
"accessory" : "HttpAdvancedAccessory",
"service" : "HumidifierDehumidifier",
"name" : "Humidifier",
"forceRefreshDelay": 300,
"debug" : false,
"optionCharacteristic" : [
"RelativeHumidityHumidifierThreshold",
"WaterLevel" ],
"props" : {
"CurrentHumidifierDehumidifierState": {
"validValues": [
0,
2 ]
},
"TargetHumidifierDehumidifierState": {
"validValues": [
1
]
},
"RelativeHumidityHumidifierThreshold": {
"Format": "float",
"Permissions": [
"pr",
"pw",
"ev"
],
"maxValue": 100,
"minStep": 1,
"minValue": 0,
"unit": "percentage"
},
"WaterLevel": {
"Format": "float",
"Permissions": [
"pr",
"ev"
],
"maxValue": 100,
"minValue": 0,
"unit": "percentage"
}
},
"urls" : {
"getCurrentRelativeHumidity": {
"url" : "http://localhost:801/httpadv/humi/state",
"mappers" : [
{
"type": "jpath",
"parameters": {
"jpath": "$.CurrentRelativeHumidity",
"index": 0
}
}
]
},
"getCurrentHumidifierDehumidifierState": {
"url" : "http://localhost:801/httpadv/humi/state",
"mappers" : [
{
"type": "jpath",
"parameters": {
"jpath": "$.CurrentHumidifierDehumidifierState",
"index": 0
}
}
]
},
"getTargetHumidifierDehumidifierState": {
"url" : "http://localhost:801/httpadv/humi/state",
"mappers" : [
{
"type": "jpath",
"parameters": {
"jpath": "$.TargetHumidifierDehumidifierState",
"index": 0
}
}
]
},
"getRelativeHumidityHumidifierThreshold": {
"url" : "http://helen.maidlab.jp:801/httpadv/humi/state",
"mappers" : [
{
"type": "jpath",
"parameters": {
"jpath": "$.RelativeHumidityHumidifierThreshold",
"index": 0
}
}
]
},
"getWaterLevel": {
"url" : "http://localhost:801/httpadv/humi/state",
"mappers" : [
{
"type": "jpath",
"parameters": {
"jpath": "$.WaterLevel",
"index": 0
}
}
]
},
"getActive": {
"url" : "http://localhost:801/httpadv/humi/state",
"mappers" : [
{
"type": "jpath",
"parameters": {
"jpath": "$.Active",
"index": 0
}
}
]
},
"setActive": {
"url" : "http://localhost:801/httpadv/humi/set?active=${value}",
"httpMethod":"GET",
"body" : "{value}",
"mappers" : []
},
"setRelativeHumidityHumidifierThreshold": {
"url" : "http://localhost:801/httpadv/humi/set?target=${value}",
"httpMethod":"GET",
"body" : "{value}",
"mappers" : []
}
}
}
stateのcgiは呼ばれたら以下のようなjsonを返すようにします。
{
"Active": 1,
"WaterLevel": 100,
"CurrentRelativeHumidity": 56,
"CurrentHumidifierDehumidifierState": 2,
"TargetHumidifierDehumidifierState": 1,
"RelativeHumidityHumidifierThreshold": 60
}
それぞれの項目の細かい意味は
HAP-NodeJS/HomeKit.ts at master · homebridge/HAP-NodeJS · GitHub
にあります。
- Active
自動制御中なら1、停止中なら0です。
実際に加湿しているかどうかではなく、加湿器の制御が有効かどうかということです。
- WaterLevel
水切れランプが点灯していれば0,そうでなければ100のbinaryな検出になります。
超音波の水面センサーや重量センサーを作ればもっと細かくとれるでしょう。
- CurrentRelativeHumidity
センサーでとってきた現在の部屋の相対湿度です。
- CurrentHumidifierDehumidifierState
加湿中は2、湿度が目標より高いなどで待機中は1、待機すらしてない(activeが0)のときは0です。
- TargetHumidifierDehumidifierState
加湿器の場合、これは1に固定です。
除湿機能もある場合は別の値にもなります。
- RelativeHumidityHumidifierThreshold
目標とする相対湿度の値です。
あとはsetする側のcgiも適当に書き、全部まとめてコンテナの中に封入しておきましょう。
完成!
iOS Home.app
iOSではこんな感じの画面です
可視化
緑色になっている部分が、加湿器が動作中(目標湿度より低い実測湿度)です。
このグラフには室外モニタ用のAM2320も載っていますが、この子は雨が降るとすぐに天井に張り付いてしまう子なのです...
冬の夜の湿度を高めに誘導しているのですが、それが本当に好ましいことなのかどうかは知りません...
おわりに
2020年、思わぬ要因による「おうち時間」の長時間化により、「ラズパイスマートホーム」「おうちハック」を楽しまれた方も多いのではないでしょうか。
この調子でおうちを快適にし、おうち時間を楽しみ、「おうちから出てもいいですよ」の時代までおうちで元気に過ごしましょう!
その後 (2022年秋追記)
- RaspberryPiではなく、ESP32にしました
- この加湿器は水漏れして壊れてしまったので、米国でみかける塩を加えて電気分解するタイプに変更しました
- 正常動作しているかどうかは、噴出口の温度センサーで測ります
- 重さセンサーを設置し、水の量を加湿器全体の重さで測るようにしました
- 観測値はESP32からinfluxdbに直接書き込み、homebridgeの方は
|> last()
の値を読むようにしました -
WebServer
もあげ、prometheusのメトリクスもだすようにしました(観測値ではなく正常稼働しているかどうかのモニタ) - おかげさまで感染することもなく過ごしております(笑)