MEANスタックで家電制御アプリを作るための設計・準備と温度湿度センサーからのデータ読み取りArduinoで始めるWeb技術者のためのIoT入門(5)(1/3 ページ)

家電〜Webアプリ間の双方向通信をSocket.IOで行うための設計や、MEANスタックのインストール、Yeomanによるアプリのひな型作成、温度湿度センサーからデータを読み取る方法などについて解説します。

» 2014年10月16日 18時00分 公開
[岩永義弘株式会社インターネットイニシアティブ]
「Arduinoで始めるWeb技術者のためのIoT入門」のインデックス

連載目次

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側の準備は完了です。

       1|2|3 次のページへ

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。