サンプルアプリの動作
それでは、ヒトがテレビを点けるところから、テレビを見ているかを判断し、テレビを見ていなければ自動的にテレビが消えるところまで、Wasted energy of TVの動作を追ってみましょう。
1. ヒトがテレビを点ける
最近のスマートテレビはAPI経由で状態取得や操作ができるようですが、今回用いたテレビにはそのような機能がありませんでした。そこで今回は、赤外線リモコンによる電源操作を傍受することで、テレビを点けた(あるいは消した)ことを認識します。

- Raspberry Piに接続された赤外線センサーが、赤外線リモコンの電源操作信号を受信したら、Raspberry Piと直結されたEdison 1号機へ「テレビの電源が操作された」ことを伝える
- Edison 1号機はConsul KVSに記録されているテレビの電源状態を調べ、消えていたテレビが点いたということを記録する
下図は実際に構築したWasted energy of TVの赤外線センサーまわりの写真です。テレビの主電源を操作した場合や、赤外線リモコンの制御信号の認識に失敗した場合に備え、Consul KVSに記録してあるテレビの電源状態を強制的に変更するスイッチも付けてあります。

2. テレビを見ているかを判断する
ヒトが集中してテレビを見ているのかを正確に判定するのは容易ではありませんが、少なくともテレビに顔を向けていなければ、そのヒトはテレビを見ていないと判断しても良いでしょう。そこで今回は、テレビに取り付けたUSBカメラの映像を解析し、テレビに正面を向けている顔の有無を判別することで、テレビを見ているヒトがいることを認識します。

- Edison 2号機はテレビに取り付けられたUSBカメラから映像フレームを取り出し、OpenCVを用いて顔認識を行って「テレビに正面を向けている顔の数」を数える
- Edison 2号機はConsul KVSへ「テレビに正面を向けている顔」の有無を記録する
テレビに取り付けられたUSBカメラの映像を、インターネットにそのまま送信するのは憚られます。これはデータ量が莫大だという問題もありますし、プライバシー的にも同意しづらいものだからです。またOpenCVを用いた顔認識はリアルタイム性が必要な処理なので、cloudで処理させるにはタイムラグが気になります。そのためこの処理は、fog内で実行させています。
下図はテレビに取り付けたUSBカメラまわりの写真です。

3. fogからcloudへテレビの視聴状況データを連携する
テレビの電源状態やテレビに正面を向けている顔の数は、それぞれバラバラに記録されているだけで、単体では意味を成しません。Edison 3号機はそれらを統合し、「時系列のテレビの視聴状況」という意味のあるデータに変換してcloudへ送信します。cloudは受け取ったテレビの視聴状況データをデータベースへ蓄積します。

- Edison 3号機は、Consul KVSからテレビの電源状態と、テレビに正面を向けている顔の数を5秒ごとに取得する
-
テレビが点いている場合、以下のフォーマットのjsonデータを生成し、MQTTを用いてcloudのMQTT Brokerへ送信する(val → 正面を向けている顔が1つでもあれば1、1つもなければ -1)
{time:"現在時刻", val:1 or -1} - cloudのMQTT Brokerは、受信した「テレビの視聴状況データ」をデータベースへ蓄積する
次の動画は、ここまで説明した「ヒトがテレビを点け、視聴状況を認識し、cloudへ連携する」という一連の流れを実演したものです。
4. 視聴状況を可視化する
テレビの視聴状況を可視化するために、Node-REDでREST APIを提供しましょう。このNode-REDフローは、次のような処理を行います(※緑色のノードは、デバッグ用ノードです)。

-
Request for target dayノードは、定義したエンドポイントへ到達したGETリクエストのQuery Stringを次のMongo Queryノードへ渡す -
Mongo Queryノードは、渡されたQuery Stringをもとに、指定した日の視聴状況データをKey-Value DBサービスから取得するクエリを生成する -
Mongo DB find (data)ノードは、クエリを実行し、検索結果をaggregate every 2 minutesノードへ渡す -
aggregate every 2 minutesノードは、検索結果のvalを00:00:00から2分ごとの期間で集計する- 視聴状況データは5秒ごとに送信されているため、ずっとテレビを見ていた場合は集計値が24になるが、半分だけ見ていた場合は0になり、テレビが点いていたのに見てないことが多かった場合は負の値になる
-
HTTP Responseノードは、期間ごとの集計結果を返す
GUIアプリは、指定された日の2分ごとの視聴状況データをこのREST APIから取得し、集計値に比例させて青~紫~赤と連続的に色を変化させることで、テレビの視聴状況を時系列で可視化します。

5. テレビを見ていなければ自動的にテレビが消える
最後に、誰も見ていないテレビは自動的に消してしまいましょう。この機能は、テレビの視聴状況をcloudで時系列に分析し、一定期間ずっとテレビが見られていない場合には、cloudからfogへテレビの電源OFFメッセージを送信することで実現しています。

- Node-REDのtimerノードによって、テレビの視聴状況を定期的にチェックする
- テレビが点いているのに、設定された時間連続してテレビを見ていない(その期間のvalがすべて-1)場合、MQTTを用いてcloudからfogへ電源OFFメッセージを送る
- Edison 3号機は電源OFFメッセージを受信すると、Consulクラスタへ電源OFFイベントを発火させる
- Edison 1号機はConsulクラスタの電源OFFイベントを監視しており、電源OFFイベントが発生したことを検知するとRaspberry Piへ「テレビの電源を消す」ことを伝える
- Raspberry Piに接続された赤外線LEDが、電源操作信号にあたる赤外線パルスを発信することで、テレビの電源を消す
1.と2.を実現するNode-REDフローは次のようになります。紙面の都合で詳細な説明は割愛しますが、少し複雑ですね。

まとめ
本記事では、IoTとfog computingの考え方や、fog computingの役割分担を意識したサンプルアプリの実装について解説しました。このサンプルアプリを動作させるには、それなりに多くのデバイスやセンサー類が必要になるため、実際に試してみるにはハードルが高いことは否めません。ただ環境構築手順やソースコードは参考になるかもしれませんので、ご一読いただけますと幸いです。
なお、本記事で紹介したサンプルアプリ「Wasted energy of TV」は、IBM Bluemix Challenge 2015でIoT賞を受賞いたしました。関係各位には、この場を借りて御礼を申し上げます。
