家電〜Webアプリ間の双方向通信をSocket.IOで行うための設計や、MEANスタックのインストール、Yeomanによるアプリのひな型作成、温度湿度センサーからデータを読み取る方法などについて解説します。
前回の「JavaScriptで家電を操作するための赤外線信号の基礎知識」では、リモコンの赤外線パターンを読み取り、同じパルスを発生させる方法とSysExを使った通信の概要を紹介しました。
次はWebシステムと連携させて、家電をスマートフォンから操作するアプリケーションを作っていきます。実装に当たって、近年ホットなMEANスタック(MongoDB、Express、AngularJS、Node.jsを使ったアーキテクチャ)の上で、双方向通信を実現するためにSocket.IOを導入します。AngularJSに関心がある方も楽しめると思います。
今回はArduinoスケッチを完成させた後、システム全体の設計を解説し、アプリケーションの骨組みを作成する段階まで進みます。
そして、次回はAngularJSやMongoDBの解説を交えつつアプリケーションを完成させます。
今回の目的は、エアコンを遠隔地から操作して、快適な生活を送ることです。いざ出先から操作しようと思ったとき、「今、本当に操作をする必要があるのか?」を知りたくなります。寒ければエアコンの電源を入れたいし、快適な状態なら電源を入れる必要がありません。
これを判断するために、温度湿度センサーを使います。単純に温度と湿度を表示するのではなく、「体感温度」を算出することで、より良いUXにします(類似した指標として、「快適指数」が挙げられますが、数値の意味が直感的に分かりにくいので使わないことにしました)。
温度湿度センサーは「Grove Temperature & Humidity Sensor Pro(SEN51035P)」を使います。精度は下がりますが、安価な「SEN11301P」もありますので、お好みで選択してください。
Arduino IDEがバンドルしているFirmataライブラリは、SysExのSTRING_DATAコマンドを伝達する部分にメモリリークするバグがあります。そのまま使った場合、通信の累積量が一定のサイズを超えたときにArduinoから応答が来なくなります。ですので、次の手順で修正版に置き換えます。
cd /Applications/Arduino.app/Contents/Resources/Java/libraries/ cp -r Firmata /tmp/ rm -r Firmata git clone https://github.com/iwanaga/arduino.git Firmata
以上の作業により、スケッチ中の「#include <Firmata.h>」で展開される内容が更新されました。
StandardFirmataスケッチをベースにして、「赤外線パルスの発生」と「温度湿度の読み取り」機能を追加します。
ファイルが大きいので、GitHubにスケッチを公開しました。下記コマンドでダウンロードしてください。
git clone https://github.com/iwanaga/CustomFirmata.git
前回解説した赤外線パルス発生処理は587〜610行目にそのまま追加しています。それ以外の変更点を解説します。
639 void setup()
640 {
641 Firmata.setFirmwareVersion(FIRMATA_MAJOR_VERSION, FIRMATA_MINOR_VERSION);
642
643 Firmata.attach(ANALOG_MESSAGE, analogWriteCallback);
644 Firmata.attach(DIGITAL_MESSAGE, digitalWriteCallback);
645 Firmata.attach(REPORT_ANALOG, reportAnalogCallback);
646 Firmata.attach(REPORT_DIGITAL, reportDigitalCallback);
647 Firmata.attach(SET_PIN_MODE, setPinModeCallback);
648 Firmata.attach(STRING_DATA, stringCallback); // STRING_DATAコマンドのハンドラー
649 Firmata.attach(START_SYSEX, sysexCallback);
650 Firmata.attach(SYSTEM_RESET, systemResetCallback);
651
652 Firmata.begin(57600);
653 dht.begin(); // 温度湿度センサー初期化
654 systemResetCallback();
655 }
648行目では、SysExのSTRING_DATAコマンドを受け取ったときに実行したい関数を登録しています。「stringCallback」という関数を登録しています。
612 void stringCallback(char *myString)
613 {
614 int h = 0;
615 int t = 0;
616
617 String command = String(myString); // 文字列比較と結合を簡単にするためStringに変換
618 if ( command == "AC:toggle" ) { // エアコン電源ON/OFF命令
619 emitIRSignal();
620 Firmata.sendString("AC:toggled"); // SysEx STRING_DATA 送信
621 return;
622 } else if ( command == "TH:get") { // 温度湿度センサー読み取り命令
623 h = (int) dht.readHumidity(); // 湿度を読み取る
624 t = (int) dht.readTemperature(); // 温度を読み取る
625 if (isnan(h) || isnan(t)) {
626 Firmata.sendString("TH:er,er");
627 return;
628 }
629
630 String responseStr = String("TH:" + String(t) + "," + String(h)); // 連結
631 char response[responseStr.length() + 1];
632 responseStr.toCharArray(response, responseStr.length() + 1);
633 Firmata.sendString(response); // SysEx STRING_DATA 送信
634 return;
635 }
636 Firmata.sendString("XX:unknown");
637 }
そのstringCallbackの中身を定義しているのが612〜637行目です。SysExで受信した文字列は引数に渡されます。
受け取った文字列が「AC:toggle」と一致するときは、赤外線パルスを発生させた後、サーバーに向けてSysExで「AC:toggled」という文字列を送信します。受信した文字列が「TH:get」と一致するときは、温度湿度センサーから値を読み出します。読み出した後は、文字列として変換して連結し、SysExで送信します。
ここで利用した温度・湿度読み出しのライブラリは、公式サイトからダウンロードしてください。このライブラリをArduino IDEで利用するには、スケッチメニューから追加する必要があります。
追加したライブラリをインクルードしている箇所はスケッチの35行目「#include <DTH>」です。52行目で製品IDを指定しています。この温度湿度センサーは精度の違う製品が販売されており、正しい値を取得するための設定です。
このコードをコンパイルしてArduinoボードに書き込めば、Arduino側の準備は完了です。
Copyright © ITmedia, Inc. All Rights Reserved.