Socket.IOでセンサー&MongoDB〜AngularJSアプリ間の通信を行う:Arduinoで始めるWeb技術者のためのIoT入門(6)(3/3 ページ)
家電〜Webアプリ間の双方向通信をSocket.IOで行うアプリについて、サーバー側のArduino連携やMongoDBへのデータ保存などと、クライアント側のAngularJSに分けて動作を解説します。
クライアント側のUI実装
次は、クライアント側を作っていきます。前回解説した通り、画面は下記のようなレイアウトです。
「体感温度を表示する部分」と「エアコン操作の部分」を独立したUIコンポーネントにしています。それでは、順を追って説明していきます。
まずは、ブラウザーに最初に読み込まれるindex.htmlから見ていきましょう。「grunt build」コマンドを実行すると、依存スクリプトなどが自動的にindex.htmlに挿入されます。事前に「bower install」コマンドの実行をお忘れなく。
自分で変更する必要がある箇所は「ui-view」で展開するUIテンプレートです。今回は体感温度を表示する「heatIndex」とエアコンを操作するための「airConditiner」を指定します。
31 <body ng-app="hemsjsApp"> .. ... 36 <!-- Add your site or application content here --> 37 <div ui-view="heatIndex"></div> 38 <div ui-view="airConditioner"></div>
この「ui-view」に対応する「html」と「controller」の指定をclient/app/main.jsで行っています。ui-routerの機能を使います。
1 'use strict'; 2 3 angular.module('hemsjsApp') 4 .config(function ($stateProvider) { 5 $stateProvider 6 .state('main', { 7 url: '/', 8 controller: 'MainCtrl', 9 views: { 10 heatIndex: { 11 templateUrl: 'app/heatIndex/heatIndex.html', 12 controller: 'HeatIndexCtrl' 13 }, 14 airConditioner: { 15 templateUrl: 'app/airConditioner/airConditioner.html', 16 controller: 'AirConditionerCtrl' 17 } 18 } 19 }); 20 });
では、ここで指定したコードがどうなっているのか見てみましょう。
体感温度を表示するUIコンポーネント
まずは、データをViewに提供するコントローラーのコードです。
1 'use strict'; 2 3 angular.module('hemsjsApp').controller('HeatIndexCtrl', function ($scope, $http, socket) { 4 $scope.thermoHygro = {}; 5 6 socket.socket.on('ThermoHygroHistory:save', function (thermoHygro) { 7 $scope.thermoHygro = thermoHygro; 8 }); 9 10 $http.get('/api/thermoHygroHistories/last').success(function (thermoHygro) { 11 $scope.thermoHygro = thermoHygro; 12 }); 13 });
AngularJSのコントローラーでは、Viewに提供するデータと処理を記述します。$scopeのプロパティは値の変更が監視されており、その変更内容は自動的にDOMに反映されます。
かつてのJavaScriptコードは、対象となるエレメントを取得しテキストノードを変更するコードが多くなる傾向にありました。AngularJSを使うと、そういったコードを書かなくてよいため、非常にシンプルです。
6〜8行目では、新しく温度湿度データを取得した際に発生するイベントを拾っています。サーバーからのpushなので、Socket.IOを利用しています。受け取ったデータを$scope.thermoHygroに代入するだけでViewの表示が更新されます。
Socket.IOによるpushが行われるのは、サーバー側が新しく温度湿度データを取得したときだけでした。次の取得まで値が表示されないのは不便なので、10〜12行目で最後に取得したデータをリクエストし、レスポンスを$scope.thermoHygroに代入しています。
次にViewを見てみましょう。
1 <div class="wrapper border"> 2 <div class="label"><i class="fa fa-home"></i> 体感温度</div> 3 <div class="content"> 4 <div> 5 <span id="heatIndex" class="number">{{ thermoHygro.heatIndex | number:1 }}</span> 6 <span id="heatIndexUnit" class="unit gray">℃</span> 7 </div> 8 <span id="temperature" class="number gray">{{ thermoHygro.temperature | number:0 }}</span><span class="unit">℃</span> 9 <span id="humidity" class="number gray">{{ thermoHygro.humidity | number:0 }}</span><span class="unit">%</span> 10 <div id="measuredAt" class="gray">測定: {{ thermoHygro.createdAt | date:'HH:mm:ss'}}</div> 11 </div> 12 </div>
先ほどコントローラーで定義した$scope.thermoHygroは、ViewではthermoHygroという変数名でアクセスできます。それぞれの値に対してAngularJSのフィルターを使って有効数字やフォーマットを指定し、テキストノードにバインドしています。
エアコンを操作するUIコンポーネント
こちら側は、ボタンをクリックしたらSocket.IOでサーバーにイベントを伝達するのみです。
ボタンをクリック/タップした際のハンドラーをコントローラーで記述しています。
1 'use strict'; 2 3 angular.module('hemsjsApp').controller('AirConditionerCtrl', function ($scope, $log, socket) { 4 $scope.togglePower = function () { 5 socket.socket.emit('AC:toggle'); 6 }; 7 8 socket.socket.on('AC:toggled', function (data) { 9 $log.log('エアコンの電源を切り替えました'); 10 }); 11 });
ScoketIOでサーバーに伝達する処理は4〜6行目の$scope.togglePowerメソッドに記述しています。単にSocket.IOでemitしているだけです。ボタンをクリックしたときにこのメソッドがcallされる想定です。
エアコンの電源切り替えが終了したとき、Socket.IOで「AC:toggled」イベントが送られてきます。そのハンドラーが8〜10行目になりますが、現在はログ出力しているだけです。将来、画面にポップアップしてフィードバックする際に利用できることでしょう。
Viewに進みましょう。
1 <div class="wrapper"> 2 <div class="label"><i class="fa fa-cog"></i> エアコン管理</div> 3 <button id="btn-ac-control" ng-click="togglePower()"> 4 <div><i class="fa fa-power-off"></i></div> 5 <div class="description">ON / OFF</div> 6 </button> 7 </div>
最も重要な箇所が3行目の「ng-click="togglePower()"」です。ボタンエレメントをクリックしたときに、コントローラーで定義した$scope.togglePowerをcallします。
これでUI側の作り込みも完了です。
いざ、起動
「grunt serve:dist」コマンドでサーバーを起動します。minifyなどが行われた後、ブラウザーが自動的に開くでしょう。
ここにスマートフォンでアクセスすると、同じように体感温度が表示され、ボタンをタップするとエアコンの電源が切り替わります。しばらく待つと、WebSocketで最新の体感温度に更新されるでしょう。
ユーザー認証の機能もひな型ができていますので、グローバルに公開する際はその機能を組み込むようにしましょう。
双方向通信も可能なInternet of Things
以上、いかがでしたでしょうか。angular-fullstackジェネレーターを利用することで、拡張性の高いコード構成で、双方向通信も可能なInternet of Thingsの世界を実現させました。
この記事が種となって、皆さんが面白いシステムを作るきっかけとなれば幸いです。
著者プロフィール
岩永 義弘(いわなが よしひろ)
株式会社インターネットイニシアティブ
データ分析とワインが好物。通信アノマリ検知システムや地震速報配信システムの開発と運用を経た後、Webアプリのフロントエンドに手を伸ばし、図らずもフルスタックな道を突き進んでいる。最近は趣味でHTTP/2の実装を楽しんでいる。
Twitter:@y_iwanaga_
Bot:@quake_alert @WeatherAlertJP
Copyright © ITmedia, Inc. All Rights Reserved.
関連記事
- 忘れずに手を洗おう……ビッグデータとIoTの活用例
張り紙に頼る代わりに、センサーとInternet of Things(IoT)、ビッグデータといった技術を活用して手洗い忘れ防止を実現したケースを紹介する。 - 確定不能なデータたち――IoT時代を受け止めるOracle NoSQL、JSON Anywhere
エンタープライズを指向するOracle NoSQL、マルチデバイスでのデータハンドリングのための環境を整備するCouchbase、適用用途は異なるものの、IoT時代を見据えた開発を進める2つの非RDBをウォッチした。 - 冷蔵庫は「無実」――シマンテックがスパム発信元を調査
「インターネットにつながったスマート家電から75万通以上のスパムメールが発信された」という報道に関して、シマンテックは2014年1月27日、実際に感染していたのは同じホームネットワーク内のWindows搭載PCであり、冷蔵庫は「無実だ」とするブログを公開した。 - 「俺たちのJavaは、まだまだこれからだ」未来の鍵はInternet of Thingsにあり?〜JavaOne 2013まとめレポート(前編)
Java開発者の年次カンファレンス、JavaOne 2013がサンフランシスコで9月22〜26日に開催された。3つの基調講演、そして400を超えるセッションが行われるなど、圧巻のボリュームは、まさに「Java開発者の祭典」といえる。基調講演と主なセッション、全体の雰囲気を前中後編に分けてレポートする。 - IoTをクラウドで管理、「Microsoft Azure Intelligent Systems Service」プレビュー公開
米マイクロソフトは2014年4月15日、デバイスやセンサーといった「モノのインターネット」(IoT)からのデータを収集し、ビジネスインテリジェンスツールと結び付けて分析する「Microsoft Azure Intelligent Systems Service」の限定パブリックプレビューを公開した。