自宅をまるごとNode-REDで制御


この記事は[Node-RED Advent Calendar 2017](https://qiita.com/advent-calendar/2017/nodered) 18日目のエントリーです。

##はじめに
これまで自宅の色々な電気設備をリモートでコントロールできるシステムを作ってきました。
基本的にはI/OをWirelessで飛ばせるようにして、色々とセンサーやコントローラをつけられるようにしたシステムをベースにIoT関連で繋がりそうなHueやSmartMeterなどを繋いで拡張していったものになります。
これについては[おうちハックAdvent Calendar 2017 10日目「卵が先か鶏が先か」](https://qiita.com/mnakada/items/fb606e6db58602167ccd)に書いています。
下回りの部分はC++やNode.jsで作っていますが、実際に家の色々なものを自動で動かす部分は全てNode-REDで制御しています。

ここでは自宅を制御しているNode-REDのプログラムを幾つか紹介していきたいと思います。Node-REDのプログラムとしてはシンプルなものばかりになります。
[GitHub](https://github.com/GeckoLink-com/HomeServer)にNode-REDを組み込んだホームサーバーのソースコードを公開しています。
[RaspberryPi用のSDカードイメージ](https://geckolink.com/download)も公開しています。子機を繋がず赤外線リモコンも要らなければRaspberryPi単独でも動作します。
##作成したNode
最初に制御システムとの繋ぎ込み用に作ったNodeを紹介します。下の画面のGeckoLinkのところにあるものです。
大きく分けて3種類、イベント検知するNode、中間でフィルターするNode、何かを実行するNodeになります。これらと既存のNodeを組み合わせて使っています。
<img width="1473" alt="Node-RED.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/159374/d7e12f89-ef27-8359-ff30-be514216ac44.jpeg">

###イベント検知Node
用途に応じて
status Node
event Node
elapsed time Node
remocon in Node
の4種類を用意しました。

####status Node
一番低レベルのレイヤーのNodeでpayloadに各種センサーのデータが変化のある度、または30秒周期の定期サンプリングの度に出力されるNodeです。全てのセンサーか1つのセンサーかを選んで出力する事ができます。
低レベル過ぎて実際には使っていません。他のNodeで出来ないようなことをやる時のために作ってあります。生のデータが来るのでfunction Nodeで色々と対応できます。


####event Node
一番良く使うNodeです。センサーとそのデータの範囲などの条件を設定して出力できるようにしたNodeです。
指定した温度センサーの温度が何度以下になったら出力する、などの使い方をします。センサーの種類に応じて下の条件設定の所は変化します。

<img width="400" alt="eventNode.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/159374/0f68254a-3ad9-a171-f877-63fb478fdd50.jpeg">

####elapsed time Node
これもよく使うNodeです。センサーとそのデータの条件と指定の継続時間で出力されます。
玄関の鍵のstateがopenの条件が5分間継続したら出力する、などの使い方をします。

<img width="400" alt="elapsedItimeNode.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/159374/3a96758b-8eeb-e388-ef88-797a68defbd9.jpeg">

####remocon in Node
親機、子機のリモコン受光部に何か赤外線リモコンのデータが来た時に通知するNodeです。
リモコン信号は、受光する親機、子機の指定、受け付けるリモコンコードの指定をすることが出来ます。
例えば、全ての受光部に入った全てのリモコンを受け付けるようにすると、いずれかの受光部に信号が入るとpayloadにリモコンデータを載せて出力されます。
また、リモコンコードを指定すれば特定のリモコンが押されたときだけ出力されるので、それをトリガーに何かをすることが出来ます。

<img width="400" alt="remoconInNode.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/159374/482fd989-cb5d-8517-cf1b-b926ca157716.jpeg">

###中間でフィルターするNode
これはswitch Node1つだけになります。

####switch Node
指定できる条件はevent Nodeと同様ですが、センサーは入力を出力に振り分けるための条件になります。タイマーイベントなどを入力にし、時間が来た時にセンサーの条件が成立していたら出力するような使い方をします。
例えば、朝6時に部屋の温度が低かったら出力を出したい場合にInjectで時間を指定してswitch Nodeに繋いで組み合わせます。

<img width="400" alt="switchNode.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/159374/2f1fcdf7-c3cd-b323-bb5b-9a149fc1bc64.jpeg">

###何かを実行するNode
用途に応じて
exec Node
command Node
remocon out Node
の3種類を用意しました。

####exec Node
一番低レベルのレイヤーのNodeでpayloadに積まれてきたコマンドを実行します。
これも低レベル過ぎて使っていません。何かの時に使えるように念のために用意しているNodeです。function Nodeでpayloadの中を作って繋ぎます。

####command Node
一番使っているNodeです。
入力があった時に指定の親機、子機にコマンドを発行して実行させるNodeです。
remocon in Nodeと組み合わせて、リモコンでHueのライトを操作するとかに使います。

<img width="400" alt="commandNode.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/159374/6bba5d92-09b2-bcb3-a3f1-a6a636fe2301.jpeg">

####remocon out Node
これもよく使っているNodeです。
入力があったら指定した親機、子機から指定したリモコンコードを出力します。

<img width="400" alt="remoconOutNode.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/159374/2028d2a5-fdfb-eb34-3592-61f265b330b9.jpeg">


##Node-REDでのプログラミング
実際に自宅を制御しているプログラムを紹介します。

###窓、ブラインド関連

####雨が降ってきたら窓を閉める
自宅は2Fがリビングなのですが、ここの南側の高窓が横開きの電動窓、北側はオーニングサッシとか横すべり出し窓とか呼ばれるタイプで横長の窓が縦と横に2連ずつ合計4まいの窓になっていてそれぞれの下側が外に上がって開くタイプの電動窓にになっています。換気のためによく開けっ放しにしているのですが、雨が降るとリビングが水浸しになってしまうので、雨雲が近づいてきたら自動で閉まるようにしました。
降雨センサーとネットの雨情報から条件を設定して、雨が降ってきたと判断したら電動の窓を閉めてメールで通知します。これはevent Nodeとswitch Node, command Nodeの組み合わせで実現しています。
switch Nodeを挟んでいるのは窓が閉まっていても閉めるボタンを押すとモーターが動作するので、雨が降っている間モーターに定期的に負荷がかかるのはよろしくないのでcloseだったら処理しないようにフィルターするためです。

![window_rain.jpg](https://qiita-image-store.s3.amazonaws.com/0/159374/4a58dc9f-9028-6cbe-24f9-d7668fbdf4ca.jpeg "window_rain.jpg")

####北側の窓を開けたら7秒後に一度停止する
これは説明しないと分からないですね。うちの北側の窓は通常は壁のスイッチで操作するのですがopenボタンを押すと最後まで開ききってほとんど水平の状態まで上がってしまいます。普段は45度くらい開いたところでstopボタンを押して止めていますがopenボタンをおしてから7秒くらいかかってstopを押すためにそこで待っていなくてはならず意外と面倒くさかったのでこれを自動化しました。
openボタンを押されたことを検知して7秒後にstopボタンを押すというプログラムです。
event Nodeとdelay Node, command Nodeを使っています。

![Window_delayedStop.jpg](https://qiita-image-store.s3.amazonaws.com/0/159374/f349ff9e-8632-c856-fdcf-d06fcd013789.jpeg "Window_delayedStop.jpg")

####リモコンで窓を制御する
リビングの南側と北側に電動の窓があって両方開けると風が通って気持ちが良いのですが、それぞれの窓の近くにスイッチがあります。
両方開けに行くのが面倒なのでリモコンでも操作できるようにしました。適当にリモコンコードを振って学習リモコンに学習させることで実現しています。
Remocon in Nodeとcommand Nodeを組み合わせています。

![Window_remocon.jpg](https://qiita-image-store.s3.amazonaws.com/0/159374/e65f4852-137c-9897-7874-e5576bccff17.jpeg "Window_remocon.jpg")

####朝は定時に、夜は日没にあわせてシャッターを制御する
寝室は平日は6:30に、土日は8:00に、寝室以外は8:00にシャッターを開けます。
夜は薄暗くなってきたら閉めたいので、日没の20分前に閉めるようにしています。
Inject Node、schedex Nodeで時間イベントを作って、command Nodeに繋いでいます。

![shutter_timer.jpg](https://qiita-image-store.s3.amazonaws.com/0/159374/a4bbc101-e3ac-2354-67d0-2461375e5ec1.jpeg "shutter_timer.jpg")

###エアコン、床暖房関連

####窓を開けたらエアコンを停止する
リビングの窓を開けるとリビングのエアコンを停止します。
event Node + command Nodeで実現しています。

![aircon_window1.jpg](https://qiita-image-store.s3.amazonaws.com/0/159374/18d64745-a28a-27fd-6633-94fd36ce4430.jpeg "aircon_window1.jpg")

####エアコンをつけたら窓を閉める
逆にリビングのエアコンをつけたら窓を閉めます。
これもevent Node + switch Node + command Nodeで実現しています。switch Nodeは窓が閉まってるのにコマンドが発行されるのを防止するためのものです。

![aircon_window2.jpg](https://qiita-image-store.s3.amazonaws.com/0/159374/19eda0c8-d777-4563-4121-37c45b6339c2.jpeg "aircon_window2.jpg")

####朝寒かったらリビングのエアコンをつける
朝6時にリビングの温度が18度を下回っていたら西側のエアコンを暖房20度でつけます。
12度を下回っていたら南側のエアコンもつけます。
旅行とかで家をあけている時などは自動運転したくないので、自動運転のon/offを設定する仮想スイッチを用意していて、これがonのときのみ実行されます。
inject Node + switch Node + command Nodeで実現しています。

![aircon_timer1.jpg](https://qiita-image-store.s3.amazonaws.com/0/159374/a1bd3aec-e5bc-c1a2-f16b-19ceefc0f009.jpeg "aircon_timer1.jpg")

####朝ものすごく寒かったらリビングの床暖房をつける
朝冷え込んでいるときは電化上手の割安な時間帯に一旦床暖房で温めておきます。
inject Node + switch Node + command Nodeで実現しています。

![aircon_timer2.jpg](https://qiita-image-store.s3.amazonaws.com/0/159374/3fb3d8ae-65b0-638e-a1da-899f2037e49f.jpeg "aircon_timer2.jpg")

###その他

####玄関の鍵が5分以上解錠状態だったらメールで通知する
よく鍵をかけたかどうか不安にだったので作ってみました。
玄関の鍵の解錠状態が5分間以上続いた時にメールで通知します。自動で閉めてもいいのですが、何も持たず庭に出て締め出されると困るのでメール通知だけにしています。閉め忘れてたときはリモートで鍵を閉められます。
elapsed time Node + mail Nodeです。

![entrance_lock.jpg](https://qiita-image-store.s3.amazonaws.com/0/159374/a9478aec-0155-6d0b-c94a-d46e630c7ff9.jpeg "entrance_lock.jpg")

####車のバッテリーが30分間以上12V以下になったらメールで通知する
車を使う時期と使わない時期があってバッテリーが上がってしまうことがあったので、車にもセンサーをつけておいてバッテリーの電圧が低下したらメール通知が来るようにしています。
車の場合始動時とかにバッテリーの電圧が急激に変化するので安定して低下した場合にメールが来るようにしています。
これもelapsed time Node + mail Nodeです。

![car_battery.jpg](https://qiita-image-store.s3.amazonaws.com/0/159374/6d847ed2-9ee6-d707-3d92-34ded3a8777b.jpeg "car_battery.jpg")

####Hueをリモコンで制御する
色調整とかはアプリからやるのでいいのですが、手軽にリモコンでon/offだけはしたかったので学習リモコンに登録したリモコンコードでon/offのトグル動作をするようにしています。
remocon in Nodeとcommand Nodeです。

![hue_remocon.jpg](https://qiita-image-store.s3.amazonaws.com/0/159374/82d3b2bc-7797-2ff8-6a4b-33ab2de489fe.jpeg "hue_remocon.jpg")

####消費電力が高くなったらエアコン、床暖房を停止してメールする
ブレーカーが落ちる前にエアコンとか床暖房を止めて全体が落ちるのを防止します。電気の使い方次第ですが、うまく使えば契約アンペアを1段階落とせるかもしれません。
うちは60A契約なのでJISの規定では定格の125% 75A使っていると120分以内、定格の200% 120A使っていると6分以内に遮断されるようです。マージンをどのくらい取るか次第ですが、最初6000Wですぐに止める設定にしていたらIHを使った途端にエアコンが止まってしまったので、すこし余裕を見て120% 7200W以上で10分継続もしくは150% 9000W以上で30秒継続すると消費電力の大きいエアコンと床暖房を停止してメールするようにしています。(様子見ながら調整が必要なので、目安としてざっくりとP=IVで計算してます)

![smartMeter.jpg](https://qiita-image-store.s3.amazonaws.com/0/159374/2c54f6cc-5366-6e97-46e2-2e9536e3e079.jpeg "smartMeter.jpg")

##まとめ
自宅を制御しているNode-REDプログラムを紹介しました。
Node-REDは簡単に使えてIoT用途で制御シーケンスを書いたりするには最適です。最初はjavascriptでシーケンスを記述できるように作っていたのですが、Node−REDを使い始めたら不要なことに気がついて全てNode-REDに移行してjavascriptの方は捨ててしまいました。

[こちらのページ](https://geckolink.com/programing)にも少し解説を書いていますのでよろしければ見てみてください。