#概要
RaspberryPiと赤外線リモコンで,スマートハウス環境を構築しました.といっても,エアコンと照明の制御だけですが,家の外からON/OFFが切り替えられたり,タイマーで自動化ができます.少々お金はかかります(\8,500くらい)が,作る時間としては,土日あればできるぐらいで,すごくお手軽です.
#デモ動画
myThingsで家電を操作する!: https://t.co/EP2usq6EtX、@YouTube がアップロード
— こたうち@関西人Python使い東京勢 (@kotauchisunsun) 2017年3月31日
#なぜ作ったか?
理由は2つあります.1つは「時刻」でエアコンをON/OFFしたかったからです.画像を見てもらうと分かりますが,エアコンの「入タイマー」は「何時間後」に「エアコンをONにするか」を設定します.そのため,「午前7時に暖房をつける」といった操作がしにくいUIになっています.そのため,夜作業をしていて,寝る時間がいつもとずれると,寝る前に入りタイマーの設定を操作する必要性がありました.そのため,何らかの方法で「時刻によってエアコンをつけたい」という課題がありました.
2つ目は「家の外からエアコンを操作したい」という要望がありました.夏場に会社から家に帰ってくると非常に部屋の温度が高く,非常に過ごしにくい.ということが多々ありました.そのため,「家の外からエアコンを操作したい」という課題が生まれました.
ただこの課題を解決をする方法として,もうすでにいろいろな製品が発表されています.例えば,iRemoconやIRKitなどがあります.しかし,これらは1つめの「時刻によってエアコンをつけたい」ということが出来ません.これらを行うためには別にサーバーを用意する必要があります.また,複雑な条件や制御を行うのであれば,「自作するほうがおもしろい.」と思って作りました.
#準備するもの
大体\8,500です.ここでは,LANケーブルやHDMIのケーブル.USBのminiBケーブルの値段は除いています.
#システム図
非常に簡単なアーキテクチャです.
- myThingsアプリでボタンをタップ
- myThingsがSlackに定型文を書き込みます.
- Raspberry Pi 3上で動いているNode.jsがSlackを監視し,メッセージを読み取ります.
- メッセージ内容に基づき,赤外線リモコンから各種家電に信号が送られます.
このようなアーキテクチャにしているのは「スマホからGUIで操作したい.」「自宅のネットワークをセキュアに保ちたい」という理由からです.自分の家の家電を操作するために,自前のアプリをわざわざ作るのは大変です.そのため「既存で使えるものを利用したい」となりました.また,実際にアプリを作った場合,自分の家のネットワークをポート開放し,サーバーを公開するのが,簡単に実装できる方法です.しかし,そのような方法はセキュリティ的には避けたほうが良いと思いました.そのため,「アプリからサーバーへ直接プッシュする」というアプローチではなく,「アプリから中継サーバーへプッシュする.自宅のサーバーは,中継サーバーからプルする.」というアプローチのほうがセキュアであると考えました.しかし,この中継サーバーを作るには,コストがかかるため,出来るだけ避けたいのも事実です.
「手軽にスマホでGUIが作ることが可能」で,「中継サーバーはできるだけ簡単に作りたい」,そのうえで,「RaspberryPiから中継サーバーのデータを簡単に参照できる」方法を考えた場合,このアーキテクチャになりました.
またmyThingsを利用する利点として,AndroidとiPhoneの両デバイスに対応しているので,一度片方で設定してしまえば,両デバイスで使える.という利点があります.
#実装手順
##赤外線リモコンの準備(ファーム書き換え)
今回,使った赤外線リモコンAD00020Pですが,ソースコードがオープンになっており,Raspberry Piでも動作確認が取れていて,非常に使いやすいものとなっています.しかし,一方で問題もあります.それは,「一部家電には赤外線リモコンとして動作しない.」ことがあります.私の家の家電が,それに該当しており,赤外線リモコンのファームの書き換えが必要となります.これは私はWindowsで作業しました.
-
ファーム書き換え用ツールのダウンロード
ビットトレードワンの赤外線リモコンのサポートページから,「ファームウェア書換えツール」をダウンロードして,解凍します. -
最新ファームウェアのダウンロード
リンクから最新のv 2.1.6のバージョンのファームのデータをダウンロードをします. -
1.で解凍したフォルダから,HIDBootLoader.exeを起動し,2.のファームウェアのデータを焼きます.
この部分に実はハマるポイントがあって,それは1.のページにある 「〔SONY,TMY,丸善追加対応ファームウェア(こちらはdisklessfun様提供コードになります)〕> [zip]」はファームとして書き込んでも期待した動作をしない.ということです.これは私の環境での実験ですが,このファームはSONY,TMY,丸善のリモコンだけに対応したバージョンのようで,他社の赤外線リモコンは一切動かなくなりました.これを改善して色々な赤外線リモコンに対応したバージョンがv2.1.6で,こちらを使う必要があります.
##Raspberry Piの準備(赤外線リモコン)
赤外線リモコンをLinuxで扱うようにコードは有志によって公開されています.しかし,Raspberry Piのそのままの環境では動かないので,USBの開発環境のライブラリをインストールします.
pi@raspberrypi:~ $ sudo apt-get install libusb-1.0-0-dev
そのあと,コードをcloneしてきて,ビルドを行います.
pi@raspberrypi:~/ $ git clone https://github.com/kjmkznr/bto_ir_cmd
Cloning into 'bto_ir_cmd'...
remote: Counting objects: 17, done.
remote: Total 17 (delta 0), reused 0 (delta 0), pack-reused 17
Unpacking objects: 100% (17/17), done.
Checking connectivity... done.
pi@raspberrypi:~/bto_ir_cmd $ make
cc -c bto_ir_cmd.c
cc -Wall -o bto_ir_cmd bto_ir_cmd.o -lusb-1.0
これでRaspberry Piから赤外線リモコンを操作する準備は完了です.非常に簡単です.
##赤外線データのキャプチャ
これも非常に簡単です.
- 赤外線リモコンを受信モードで待機
pi@raspberrypi:~/bto_ir_cmd $ sudo ./bto_ir_cmd -e -r
Extend mode on.
Receive mode
- 赤外線リモコンに向けて,操作したいリモコンのボタンを押す.
- 赤外線のデータが表示されます.
pi@raspberrypi:~/bto_ir_cmd $ sudo ./bto_ir_cmd -e -r
Extend mode on.
Receive mode
Received code: 0140980220E004000000060220E00400413680320000066000008000061B0000000000
このように,データを取得することが出来ます.この場合,データは
0140980220E004000000060220E00400413680320000066000008000061B0000000000
となります.これは,私の家のエアコンの暖房をONにするデータで,warm_dataとしてファイルに保存しました.
これを用いて実際にエアコンを操作したい場合,
pi@raspberrypi:~/bto_ir_cmd $ sudo ./bto_ir_cmd -e -t `cat warm_data`
Extend mode on.
Transfer mode
Transfer code: 0140980220E004000000060220E00400413680320000066000008000061B0000000000
というコマンドを打つことで,赤外線の情報が送信されます.
#Slackの準備
あまり詳細には説明しませんが,今回は,"mythings"という部屋を作成し,この部屋にアクセスするBot Applicationとして,トークンの発行を行いました.
このトークンは後々のnode.jsアプリケーションで必要となります.
#node.jsアプリの準備
##node.jsのバージョンアップ
Slackのチャンネルは準備されたので,あとはRaspberry Piで動かすだけです.しかし,ここにも問題があります.Raspberry Piにインストールできるnode.jsのバージョンがv0.10系で,Slackを操作するライブラリが必要としているnode.jsのバージョンがv4.0系となっています.そのため,少々面倒な手順を踏む必要があります.
pi@raspberrypi:~/bto_ir_cmd $ sudo apt-get install nodejs npm
pi@raspberrypi:~/bto_ir_cmd $ npm install -g n
pi@raspberrypi:~/bto_ir_cmd $ sudo n stable
pi@raspberrypi:~/bto_ir_cmd $ sudo sudo apt-get purge -y nodejs npm
参考:http://qiita.com/seibe/items/36cef7df85fe2cefa3ea
##botスクリプトの準備
次にnode.js上で動くスクリプトを実装します.
var RtmClient = require('@slack/client').RtmClient;
var CLIENT_EVENTS = require('@slack/client').CLIENT_EVENTS;
var RTM_EVENTS = require('@slack/client').RTM_EVENTS;
var exec = require('child_process').exec;
var bot_token = '取得したSlackのトークン';
var rtm = new RtmClient(bot_token);
// The client will emit an RTM.AUTHENTICATED event on successful connection, with the `rtm.start` payload if you want to cache it
rtm.on(CLIENT_EVENTS.RTM.AUTHENTICATED, function (rtmStartData) {
console.log(`Logged in as ${rtmStartData.self.name} of team ${rtmStartData.team.name}, but not yet connected to a channel`);
});
rtm.on(RTM_EVENTS.MESSAGE, function handleRtmMessage(message) {
console.log('Message:', message);
if(message.text == "warm aircon") {
console.log("turn on aircon warm.");
exec('sudo ./bto_ir_cmd -e -t `cat warm_data`', (err, stdout, stderr) => {
if (err) { console.log(err); }
console.log(stdout);
});
} else if(message.text == "cool aircon") {
console.log("turn on aircon cool.");
exec('sudo ./bto_ir_cmd -e -t `cat cool_data`', (err, stdout, stderr) => {
if (err) { console.log(err); }
console.log(stdout);
});
} else if(message.text == "stop aircon") {
console.log("turn on aircon stop.");
exec('sudo ./bto_ir_cmd -e -t `cat stop_data`', (err, stdout, stderr) => {
if (err) { console.log(err); }
console.log(stdout);
});
} else if(message.text == "light off") {
console.log("turn off light.");
exec('for i in `seq 1 3`; do sudo ./bto_ir_cmd -e -t `cat light`; sleep 2.0; done', (err, stdout, stderr) => {
if (err) { console.log(err); }
console.log(stdout);
});
} else if(message.text == "light on") {
console.log("turn on light.");
exec('sudo ./bto_ir_cmd -e -t `cat light`', (err, stdout, stderr) => {
if (err) { console.log(err); }
console.log(stdout);
});
}
});
rtm.start();
ほぼサンプルコードをコピペして,bto_ir_cmdをキックするように書き換えただけのスクリプトです.トークンや部屋の情報を書き換えてご利用ください.
このスクリプトでは,Slackのチャンネルに特定の言葉(warm aircon)という言葉がつぶやかれたのを検知すると,bto_ir_cmdをキックし,エアコンをつける.といった挙動になっています.
先の例では,warm_dataというエアコンの暖房をONにするだけのデータを作りましたが,
- エアコンの暖房をONにする(warm_data)
- エアコンの冷房をONにする(cool_data)
- エアコンをOFFにする(stop_data)
- 部屋の電灯を切り替える(light_data)
の4種類を用意して利用しています.
電灯を消すコードが
'for i in `seq 1 3`; do sudo ./bto_ir_cmd -e -t `cat light`; sleep 2.0; done'
というコードになっているのは,私の家の電灯の仕様で,点灯状態から完全な消灯にするために,ボタンを3回押す必要があるからです.このあたりも個人でチューニングしていただけたらと思います.
これで,Slackに'warm aircon'とつぶやくと,Raspberry Piがエアコンの暖房をONにしてくれる機構が完成しました.
#myThingsの準備
最後にmyThingsのアプリ側の設定です.これも非常に簡単です.
「ボタン」をトリガーにして,Slackの「mythings」チャンネルに「warm aircon」と投稿するだけの簡単な設定を入れました.
これでmyThingsのボタンを押すとエアコンの暖房がONになります!!
#最後に
IoTという言葉がバズワードとして流行し,色々な製品が出ていますが,個人的には今一つ食指が動きませんでした.特に厳しい.と思うのはスマホアプリ+ハードの組み合わせです.いかに面白いハードであっても,アプリ以外の操作が不可能な仕様になっているため,ハックができないことも多いです.しかし,一方でこのAD00020Pのような赤外線リモコンのように仕様がオープンで,必要十分な機能がハック可能な状態で提供されているのは素晴らしい.と思います.こういう製品が多く増えてほしいですね.欲を言えば,センサでいろんな値がまるっととれるやつとか.
一台家の中に動いてるマシンがあると割と遊べます.そういう意味でもRaspberry Piは,知見もたまっていて,このような製品の中では枯れてていますし,ついでにこういうハックをやってみるのも楽しいと思います.