MEANスタックで家電制御アプリを作るための設計・準備と温度湿度センサーからのデータ読み取り:Arduinoで始めるWeb技術者のためのIoT入門(5)(1/3 ページ)
家電〜Webアプリ間の双方向通信をSocket.IOで行うための設計や、MEANスタックのインストール、Yeomanによるアプリのひな型作成、温度湿度センサーからデータを読み取る方法などについて解説します。
Socket.IOで、家電〜Webアプリ間の双方向通信を行うために
前回の「JavaScriptで家電を操作するための赤外線信号の基礎知識」では、リモコンの赤外線パターンを読み取り、同じパルスを発生させる方法とSysExを使った通信の概要を紹介しました。
次はWebシステムと連携させて、家電をスマートフォンから操作するアプリケーションを作っていきます。実装に当たって、近年ホットなMEANスタック(MongoDB、Express、AngularJS、Node.jsを使ったアーキテクチャ)の上で、双方向通信を実現するためにSocket.IOを導入します。AngularJSに関心がある方も楽しめると思います。
今回はArduinoスケッチを完成させた後、システム全体の設計を解説し、アプリケーションの骨組みを作成する段階まで進みます。
そして、次回はAngularJSやMongoDBの解説を交えつつアプリケーションを完成させます。
家電制御アプリのゴール
今回の目的は、エアコンを遠隔地から操作して、快適な生活を送ることです。いざ出先から操作しようと思ったとき、「今、本当に操作をする必要があるのか?」を知りたくなります。寒ければエアコンの電源を入れたいし、快適な状態なら電源を入れる必要がありません。
これを判断するために、温度湿度センサーを使います。単純に温度と湿度を表示するのではなく、「体感温度」を算出することで、より良いUXにします(類似した指標として、「快適指数」が挙げられますが、数値の意味が直感的に分かりにくいので使わないことにしました)。
温度湿度センサーは「Grove Temperature & Humidity Sensor Pro(SEN51035P)」を使います。精度は下がりますが、安価な「SEN11301P」もありますので、お好みで選択してください。
SysExでArduinoと通信するための準備
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.