おうちハックした自宅に2年すんでみたおはなし

毎日帰宅してからちょこちょこ直して2年、それなりに快適なおうちになりました。

# 材料

## 入力系 (センサー類)

### netatmo

* 屋外の気温、湿度
* 室内の気温、湿度、CO2濃度、大気圧、騒音レベル

が測定でき、クラウドにあがるのでAPIで叩くと数値を貰えます。
あまり頻度よく叩くと怒られます（笑）

### arduino

* ダスト（埃）センサー
* 空気質センサー
* 照度センサー
* 人感センサー
* 窓センサー（窓側に磁石をつけ、リードスイッチで開閉を検出）
* ドアセンサー（同上）

すべてarduinoに繋げ、arduinoに繋がったraspberry piからmongodbに書き込ませます。

![センサ1.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204320/74064e4b-293b-b3b9-5fd6-959b2054750f.jpeg)

すこしずつ増築していったのと、このArduinoはこの写真の基盤以外の仕事もしているために、信号線をD-Subで引き回しています。
もし今から同じものを新規でつくるのなら、技適取得済みWiFi搭載Arduinoみたいなものをぶらさげて、そこに電源だけ有線で供給するほうが良いでしょうね。
拡張性も高くなりますし、すっきりした配線になります。

![センサ2.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204320/f9be3739-310c-8cb4-418e-7a62c0ddd8c1.jpeg)


### 電力センサー

こちら参照

[3GPI とラズパイで家庭の消費電力量をグラフ表示する \- Qiita](https://qiita.com/osamasao/items/a38707465e8f8a9948ed)

![電力1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204320/cddf1158-aa1d-09d3-c14d-c15aa3033144.jpeg)
![電力2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204320/e650892e-2b43-a7f0-7425-eecaf613d650.jpeg)

chart.jsとwebsocketでリアルタイムグラフを描くこともできます。

参考: [websocketを使ってリアルタイムなグラフ - Qiita](https://qiita.com/onsen_koichi/items/39199d60fca7ecf8964e)

キャリブレーションしてないので単位が怪しいのはご愛敬（笑）

![電力3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204320/e43153d0-f9fd-48c2-759c-dd861adb8a8e.png)

httpsでオレオレCAで作ったクライアント証明書をもっている端末からだけアクセスできるようにします。
これをすると、ID/Passの管理をしなくていいので楽ですね。

### I2C温度湿度センサ

I2Cの温度、湿度センサーもあるのですが、今のところ使っていません。

### 熱帯魚水槽

Dallas one-wireというプロトコルで話す水温センサーと、pHセンサーがあります。

参考: [Arduinoで水温計DS18B20を使う : 試行錯誤な日々](http://asukiaaa.blogspot.com/2016/01/arduinods18b20.html)
参考: [arduinoでpHメーター（動作確認編）: くま出没注意](http://chairoirirakuma.cocolog-nifty.com/blog/2018/09/arduinoph-b0d3.html)

私が使っているのは: [pH METER : センサ一般 秋月電子通商-電子部品・ネット通販](http://akizukidenshi.com/catalog/g/gM-12547/)

## 出力系

### 赤外線

こちら参照

[格安スマートリモコンの作り方 \- Qiita](https://qiita.com/takjg/items/e6b8af53421be54b62c9)

httpからirkit風のプロトコルで叩けるようなプログラムを書いて動かしておきます。
pythonのBottleとか使えば簡単です。

ちなみにこのirrp.pyのjsonは、irkitのjsonの数値の1/2でそのまま流用ができます（デバイスによっては再学習しないとうまくいかないこともあります）。

これで以下の装置を動かしています。

 * エアコン（冷房、暖房、除湿、それぞれに「パワフル」と「静音」）
 * 空気清浄機（「パワフル」と「静音」）
 * サーキュレーター
 * プロジェクター
 * PC用ディスプレイ

### WoL

常時稼働ではないパソコンはWoLで動かします。
シャットダウンやスリープは、windowsならwinexeで、unix系ならsshです。

### WiFiスマートコンセント

こちら参照

[WiFi制御スマートコンセントを換気扇に繋げて、省エネ快適生活を目指す \- Qiita](https://qiita.com/curtain6935/items/7d29275d483171579880)

複数買ったので、あちこちにつなげてあります。

 * 換気扇
 * パソコンの周辺機器
 * 電気ポット (必要なときだけ沸かすため、ティファールのように扱う事が可能）
 * 従来型ライト
 * 熱帯魚水槽冷却装置
 * 加湿器

### Hue

言わずと知れたPhilips Hueですね。

### ロボット掃除機

ハックしやすくお安いモデルとしてecovacsを使いました。

[github wpietri/sucks: Simple command\-line script for the Ecovacs series of robot vacuums](https://github.com/wpietri/sucks)

### 時計

クラウドファンディングで買った文字を表示できる時計に動作状況を表示しています。

[Glance Clock](https://glanceclock.com/)

### スマホ通知

人間に知らせる必要がありそうなイベントについてはpushoverで通知もさせています。

参考: [pushoverでいつでもどこでも呼ばれる環境をつくる \- Qiita](https://qiita.com/regtan/items/163147b0b43978f05958)

### mac音声読み上げ

macのsayコマンドが便利です。

```
echo "室温が4度になったので暖房を16度にします" | ssh mac say
```

と数字も読み上げてくれます。

### muninのグラフ

munin-nodeのpluginとして、温度等を出します。
どんな生活しているか一目瞭然。
ひぃ〜

### ログ

mongodbにログを追加します。
cappedでdbを作ると、勝手に古いものから消えていってくれますね。
ログはライフログを作るのに使っています。

## 位置関係

ユーザ、つまり私がどこにいるのか調べる必要があります。

iOSユーザの場合はhomebridgeにダミースイッチを用意しておいて、ホームアプリでの在宅・外出判定で概ねうまくいきます。
ただ、それだけですと距離に応じた制御、「近くに来たら強く冷やして、帰宅しら弱くする」というような制御はできません。

* スマホの位置情報（~~Proximity Events (公開終了した模様)~~ Locativeというアプリからwebhook。誤動作あり）
* スマホのWiFi DHCP固定振り出しアドレスへのping状況（省電力で応答しないこともあるので注意）
* 人感センサー（太陽光による誤動作あり）

と、誤動作対策として

* 照度センサー
* 日の出、日没時刻（緯度経度から計算）
* iOS標準カレンダーの「お休み」の記載状況（caldavでとる）
* OpenVPNの端点の位置（巷のWiFiスポットに繋がっているときは明らかに外出中）
* CO2濃度 (窓があいていると無意味)
* 窓センサ (CO2の無効化用）
* 窓・ドアセンサ (これらを操作しているということは、泥棒でもない限り住人)

も併用して誤動作の少ない方法で「家にいるのかいないのか」を検出します。
これだけでも、毎日帰宅後に調整するというのが結構続きました（笑）

## 独立系

残念ながら外部から制御するのが難しいものとして、

* スマートロック
* morninカーテン

も一応あります。

カーテンは夏の平日昼間は遮熱のために閉じていますが、祝日やお休みの日でも動いてしまうのでなんとかしたいところです...

# 使用ソフトウェア

全部dockerの中にいれておきます。

## homebridge

AppleのHomeKitにつながるnodejs。
dockerに閉じ込めるときはavahiに注意が必要です。

## mongodb

データの保存にはmongodbを使っています。
時系列データをcapedなコレクションに保存しておけば、古いものから勝手に捨ててくれます。
最新のものをとる、指定の時間に最も近い記録をとる、といったこともクエリーのみでできますし、change streamsを使うと「変化があったら起こしてね、それまで寝てるから」ができます。

## Mosquitto

MQTTですね。

## 自分で書いたスクリプト

メインとなる制御スクリプトは、chagne streamsに起こしてもらうのを待って、各デバイスの状態をmongoに聞いてから設定して眠る、というループを回しています。
change streamのpipelineの$matchはupdateでは評価されないのが玉に瑕。

このメインスクリプトはセンサー自体は直接読みません。
センサーを読むのは別のコンテナで、そこは読んだ値を延々とmongodbに書いてきます。
センサーのつながっているデバイスの近くで動かします。
changestreamを使うのでセンサーを自分で読みに行くタイミングが決定できないことと、センサーへの問い合わせはロックしてしまうことやエラー処理が複雑になるためです。

# つくりかた

## 第一段階 入力1出力nの関係

まず、単純な組み合わせからつくりました。

### 人の位置に連動した変更

帰宅する直前に接近を検出して、予め部屋を暖かくしたり涼しくしたり、ポットを動かしたりします。
逆に外出すれば家電は停止しますが、ロボット掃除機は動き出します。

### 省エネのための制御

窓が開放されているのにエアコンや空気清浄機、加湿器をいれても無駄です。
また、外気のほうが涼しいのにエアコンで冷房をかけるのもおかしな話です。
HueはLEDとはいえ昼行灯も電気の無駄ですね。

窓を開けた瞬間にエアコンを停止させ、窓が閉まったらまた動かすとかもします。

### 快適な空調

エアコンは一口に「設定温度xx度」といっても、冷房/暖房がありますが、我が家にあるモデルでは更に「パワフル」「静音」の区別があり、「除湿」の有無もあります。
ちょっとしたスマート家電操作アプリ（gateboxなど）では温度までしかいけないでしょうが、自分で作る場合は「湿度が高いときは除湿」なども可能ですね。

また、ダストセンサーが高い数値をだしているときは、空気清浄機を動かしたほうがいいかもしれません。
空気質センサーやCO2センサーが高い数値をだしているときも、換気扇を動かしたほうがいいでしょう。

### ブレーカーが動作しないための制御

ブレーカーが遮断してくれるのはあまり好ましくありません。
サーバ類は家庭用UPSで保護していますが、いろいろ面倒なので、電力消費が増えたときは自動で電気ポットやエアコンを停止させます。
うちの場合、オーブンレンジと乾燥機を同時利用したりすると警告を発して、予防的停止が走り、エアコンやポットなどが停止し、30分以内に消費電力が戻れば再起動、といった制御をします。

### 水槽高温時

熱帯魚水槽は高温になると熱帯魚が死んでしまいます。
「熱帯」魚のくせに、熱帯ではないはずの日本の夏には弱いのです。

水槽用の小さなファンがあるので、それを制御して高温時は冷やし、それでも追いつかない時は部屋のエアコンを動作させています。
でも、それが動作するのは8月の最も暑い季節だけですね。

### homebridgeからの制御

Apple製品から制御できるようにhomebridgeを経由してスマホやパソコンに繋げます。

Siriから「ベランダのドアは開いてる？」とか「掃除機を動かして」とかいろんなことができます。

## 第二段階 入力n 出力mの関係

さて、ここまでは単純な二者程度の関係だったのですが、生活していると複雑なシナリオがでてきますので、そこをやりました。
if文の山になります。

### 出勤時のみ掃除機動作

外出時の掃除機も、お仕事に行く時だけ動くようにします。
お休みの日(土日、祝日(googleの日本の休日カレンダーから取得)や休暇の日(自分のiCloudカレンダーから取得))は動かないようにします。
最初、在宅の時間を積算して「12時間以上在宅で」とかやったのですが、あまり意味ないとわかった(自分でその日は掃除機が動作するかどうかの予測がつかないため、部屋の電源コードを片付けても徒労に終わることがある)ので「平日は毎日掃除機」としました。
普段は1時間だけ動作させ、休み明けの日のみ「電池がなくなるまで全自動」で動作させています。

### 睡眠時

具体的には、siriに「おやすみ」をいった後ですね。
不要なモノは停止させてokですが、寝苦しくて起きてしまっても困りますので、控えめの空調制御をしています。

### プロジェクターまわり

うちはテレビが無い（本当に持っていない。NHK受信料も合法的に払わなくていい）のですが、プロジェクターにApple TVが繋がっています。
これでdアニメやネトフリを見ているときは部屋は暗くなって欲しいですし、空調は静かになってほしいです。
とはいえ、不快になるレベルで停止されても困ります。

一方、ゲーム（windowsからAirParrot）をやっているときはそんなに暗く静かにする必要もありません。
プロジェクターの動作状況と、空気関連、音圧関連を組み合わせ、やはり快適さは維持したまま、快適になるようにします。

エアコン、空気清浄機の「パワフル」「静音」も、プロジェクターや睡眠の状況によって変動させます。

### その他のシーン

料理をしているときとお風呂にいっているときについては特別な条件をつけました。
いちいち「今からお料理するよ」みたいなのも面倒なので、人感センサーを使って検出します。

### 電気代削減

電気代も削減せねばなりませんが、「どこまで快適さを保ったまま無駄を削るか」という話になります。
試行錯誤の結果、「四季を人間が入力する（気象データでやろとうしたのですが、結構条件が難しい）」という変数をひとつ設けてif文の山をつくりました。
たぶん機械学習的手法が使えると思うのですが、私は自分でif書いたほうが速いのでif文の山をつくりました。

## 第三段階　ヘルスケア的なもの

ここがウチでは、まだ出来ていないところです。

* fitbitから睡眠状況をリアルタイムに取れるか？
* CO2センサー、空気質センサー、音圧センサーで人間の活動状況がとれるか？
* 画像認識でいけるか？

たぶんこれらを頑張れば、
[UR都市機構と東洋大学INIAD、2030年のスマートホームを想定した「Open Smart UR」スタートアップモデル公開 \| IoT NEWS](https://iotnews.jp/archives/127982)
に多少迫ることができるかと思います。

ただ、現状、別に健康だし、たいして困らないんですよね…

# 知見

## センサーと機械制御は難しい

私が普段かいているプログラムは「エラーがおきたらcatch」などで済むのですが、「センサー → 演算 → 機械制御」はそれとは違う難しさがあります。
センサーはエラーを出していなくても誤検出をしますし、機械もうまくいったつもりでも、正しく制御できているとは限りません。
人間がいないのに人感センサーが何かに反応してしまったり、赤外線信号を出したのに何かの理由で伝わらなかったり、ということは頻繁におこります。

想定していない矛盾した状況が発生すると、発振してしまうこともあります。
iPadを自宅に忘れてiPhoneだけもって外出したとき、在宅と不在の検出が発振してしまったことがあります。

この程度のおうちハックですら結構面倒なのですから、飛行機や電車の制御はとても大変でしょうね...
おうちハックで死ぬことはありませんが、ソフトウェアのバグで飛行機は落ちますから... 737MAXのように!

## 1つだけで出来ることは限られている

「スマホからエアコンを制御できます」ではさほど意味がないのです。
ほかのセンサーと繋げて、「○○が○○したら、冷房がはいる」とならないと、赤外線リモコンがスマホに置き換えられただけで、あまり意味がありません。

## 1:n で出来ることは限られている

世の中そんなに単純ではありません。
「○○が○○したら、冷房がはいる」だけでも、例外的事象や他の制約を加味してくれないと困ります。
IFTTTでは限界があります。

## n:m は複雑であり、決まった答えがない

「毎日、○○が○○したら○○してほしい」という所に、「ただし休日はのぞく」「休日とは曜日だけではない、日本の祝日もあるし、自分が有休をとった日もある」「窓が開いているときは除く」「だが余りに○○なときは動作」とかやりだすと、結構複雑です。

沢山の条件がからみ、組み合わせ爆発がおこり、ライフスタイルによって人の数だけ答えがあるでしょう。
ウチは私の行動パターンに合わせてつくってあるので、「平日昼間は不在」「夜は寝る」「土日でも同じ時間に起床」といった前提で組んでいますが、これがもし夜勤やシフトのある人、生活リズムの狂った人なら、まったく違う制御になるでしょう。
実際にこの手のおうちハックが普及する過程においては、使用者がその条件をプログラムすることは無理ですから機械学習の手法が用いられることでしょう。
ちょうどメールのSPAM分類と同じで「このメールは世間一般ではどうだから知らないがわたしにとっては不要/重要」という指示をしばらくしているとメーラーか自分色に染まって勝手に分類してくれるのと同じですね。

一人暮らしではなく複数人が同居する場合はさらに複雑でしょう。
子どもがいる場合、そもそもおうちハックはまだ危険かもしれません。

## HomePodは便利

「ヘイSiri、冷房をつけて」などは、かなり便利です。
さらに、ユーザインタフェイスも丸投げできます。

ただ、まだSiriではできないことも多く、HomePodに「一時間後にエアコンを止めて」と言っても「すみません、私にはコマンドの予約はできません」と言われてしまったり、一度に複数の機材を操作しようとしてもダメなので、まだまだ（Appleがすべき）改善の余地はありますね。

とはいえ、リモコンを探すとかスマホを触るとかせずに家電制御ができるのはかなり便利です。

## 支援、自動、そして提案へ

ユーザから見た場合、最初の段階は「支援」です。
「Siriで簡単にエアコンを操作させることができます」といった感じですね。
「アマゾンで簡単に注文できるよ」や「AIで自動車の運転が簡単になりました」という感じです。

次の段階は「自動」です。
人間が快適になるように、勝手にエアコン・換気扇・加湿器・空気清浄機・ライトといったものを制御してくれます。
人間が明示的に頼む頻度を減らします。
「アマゾンから足りなくなりそうな頃に定期便で届くよ」や「AIで自動運転です」という感じですね。

ウチはここまでの段階です。
次はできていません。

更なる段階は「提案」ではないかと思います。
「昨日夜ふかししたでしょ、今日は早めに寝ないと明日つらいよ？ だから寝やすい環境に自動的にもっていくよ」といった提案型の自動化です。
「『こんな新製品が出たんだけど、あなたなら気に入ってくれると思う』とアマゾンが注文前に届けてくれる」とか「『そろそろ出かけないとあなたが先日買ったコンサートに遅刻するよ』と自動運転自動車の迎車が勝手に来る」というような感じですね。
これはなかなか難しいですし、プライバシーなどの問題もあるでしょうが、やがてそういう時代が来るでしょう。
そういう下らない事は機械に任せて、もっと人間にしかできない本質的活動に専念するべきなのですよ。

「俺はデブだから夏のエアコンは16度じゃないと眠れないんだよ！」みたいなエアコン操作を繰り返していると、やがて寝る時間になると勝手に冷えはじめるのだけど、少しずつ温度を上げて「痩せなきゃ」という雰囲気を機械が勝手に作り出していく... ちょっとディストピアだけどそれで当人が苦もなく痩せられるのなら良いのかもしれません。

## スマートホーム生活は一度やったら辞められない

人間、快適さに慣れるというのは恐ろしいことです。
たまに実家に帰ると、壁のスイッチを触らないと照明がつかないことに愕然としてしまいます（笑）。
赤外線リモコンなんていうものも、すぐにどこに置いたか忘れてしまいます。

逆に、私の家に遊びに来た人は、「勝手にエアコンが動いて怖い」といいます（笑）。

## おうちハックは、健康にも財布にも地球にも優しい

機械は物理法則、計算理論に従って黙々と動きます。
気まぐれで夜更かしすることも、気分が乗らないからといってサボることもありません。
そんな機械に制御されたおうちに住んでいると、人間もまた規則正しい生活、決まった時間に寝て、決まった時間に起きる生活になってきます。
睡眠負債が取り沙汰される昨今、これは健康にも良いことですね。
このおうちハックのお陰かどうかは知りませんが、ここ一年くらい、風邪はひいてないと思います。
人によっては精神的ストレスになるかもしれませんが...

「昼行灯をしない」「外気のほうが涼しい時は冷房はかけない」などといった省エネは、財布にやさしいです。
副次的に地球にも優しい訳です。
Raspberry pi代金は難しいかもしれませんが、電子パーツを買うお金くらいなら、簡単に電気代の差額として元を取ることができます。

## 千里の道も一歩から

ここまで作るのに2年かかっています。
馬上(車上)、枕上、厠上、風呂桶上で「あ、あれやるといいかも」と思い浮かんだら、速やかにメモ。
そして帰宅後実装して、問題があれば直す。
帰宅後に長時間やるわけにもいかないので、時間を決めて少し進めてgitに突っ込んでおいて出来たらブランチ切り替え。
これを毎日のようにしていました。
センサーや機械を動かすプログラムは、センサーの誤動作や想定していない状況にいかに対処するかという部分が多くなるので、なかなか一発で問題なく動くということはありませんね。

まだまだ先は長そうですが、とりあえずqiitaに書いてみました。

# 今後の野望

## 窓開閉

[自動で窓を開閉する装置 \- YouTube](https://www.youtube.com/watch?v=cf_hSJqCg_g)

これは機械工作が大変そうです...

## 水槽まわり

タイマーで単純に動作している「照明」「CO2添加」「エアレーション」といったものを制御したいところですが、これも、それほど必要性はありません。
水中のCO2, O2濃度は流石に自宅で測るのはお金が足りませんね（笑）

## 独立して動作しているものをなんとかする

Qrioのスマートロックと、moninのカーテン。
BTをハックするのは大変なのですが、QrioはBTなしのAndroidからも操作できます。
ということは、Androidエミュレータをqemuの中で動かして、qemuごとというかkvmごと外からvncdotoolで操作すれば、Qrioを外から操作できるはずです...
小石を動かすためにショベルカーを持ってくるような話なので、あまり気が進みませんが（笑）

## 物理侵入撃退

物理的な侵入検出、つまり、住人はどこか遠くにいるはずなのにドアセンサーが開放を検出した、というときに、法律の範囲内で威嚇や撃退をするという話です。
ポケモンショック光線が合法かは分かりませんが、その程度ならできそうですね（笑）。

そんなに危険な場所に住んでいる訳ではないので必要性があるとも思えませんし、実際に問題がおきても困るのですることはありませんが（笑）。

# 追記 2019年暮

上記「今後の課題」は特になにも出来ていませんが、物理侵入検出とスマホへの通知とhueが赤色点滅は作りました。
動作確認は一度しましたが本番を検出したことがないので意味があるのかは不明です（笑）。

いまは安定して動作しており誤動作もなく快適そのもの...

慣れとは恐ろしいもので、たまに人様の家で「しゃべる家電」に出会うと、「コイツのウェイクアップワードは何だっけ？」と考えてから「一方的に家電がしゃべるだけで人間の言葉は聞いてくれない」ことに気づくことがあります。

「マイマイ日立、シャワーからお湯を出していただきたく」
「ハイショー」

...嫌すぎる...

# 追記 2022年冬

あれから幾星霜...

## センサー制御をESP32に変更

![a.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204320/1dd31325-3db4-0da8-50db-589684ef2524.jpeg)

Arduinoに繋げてあったセンサーをESP32に変更しました。
WiFiで繋がり、制御側PCとはMQTTとhttpで通信します。
観測データ類はMQTTで、赤外線リモコンとePaper表示はhttpで動きます。
さらに、biffやらなにやらの通知もさせています。
天気予報はyahooからスクレイピングしています。

Netatmoも以下のESP32に置換してあります。
[ESP32でNetatmo Weather Stationもどきを作る - Qiita](https://qiita.com/curtain6935/items/b317e9b5c99ff091afe4)

ESP32は楽しいですね。
即物的に有益なことをさせてもいいですけど、安くて小さいので単なるインテリアグッズ作成にもよさそうです。
「メールがくると読み上げてくれる伝書鳩」「月の満ち欠けに連動して光る石」「明日の天気を占う水晶玉」「遠距離恋愛の相手の部屋の明るさと連動する暖炉」とか...
「異世界はaitendo通販とともに（回路図とソースの巻末付録つき）」なんてね。
[明日の天気を予知してくれる魔法のランタンをつくる - Qiita](https://qiita.com/curtain6935/items/74173c5697f9d1ecfff7)

## WiFiコンセントをTP-Linkに変更

tuyaのようにMITMしてkeyを取る必要もなく、無線のつかみも安定します。
IoT専用のvlanを切って隔離することでプライバシーを確保、IoT機器を排除したメインのSSIDはFreeRadiusを使ってWPA2-Enterpriseにしました。

[softScheck/tplink-smartplug: TP-Link WiFi SmartPlug Client and Wireshark Dissector](https://github.com/softScheck/tplink-smartplug)

## カーテン制御をswitchbotに変更

switchbotのカーテンはローカルからBLEで制御できます。
残念ながらswitchbot LockのAPIは2022年冬の時点では公開されていないようです。

[OpenWonderLabs/python-host: The python code running on Raspberry Pi or other Linux based boards to control SwitchBot.](https://github.com/OpenWonderLabs/python-host)