SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

Bluemixではじめてみよう! 「IoT→クラウド」データ活用アプリケーション開発(AD)

IoTセンサーデータから過去の気象データをもとに体感温度を求めてツイートするアプリケーションをつくる

Bluemixではじめてみよう! 「IoT→クラウド」データ活用アプリケーション開発 【第2回】

  • このエントリーをはてなブックマークに追加

 IoT(Internet of Things:モノのインターネット)のセンサーで取得したデータをクラウド上のデータベースに蓄積し、分析・活用するアプリケーションを手軽に始めてみる連載の第2回です。今回は、IBMのPaaS「Bluemix」が提供するIoTデバイス接続サービス「IBM Watson IoT Platform」を経由して受信した温度・湿度データを、DBaaS(Database as a Service)の「IBM Cloudant」へ蓄積し、過去の気象データと照らして体感温度を伝えるメッセージを作成してツイートする、というアプリケーションを作成します。

  • このエントリーをはてなブックマークに追加

サンプルアプリケーションの概要

今回、サンプルとして作成するアプリケーションは「IoTデバイスのデータを受信してデータベースに保存し、保存したデータをもとに気温、湿度の平均値と不快指数を計算して定期的にTwitterへツイートする」というものです。 次の2つのアプリケーションで構成されます。

  • 「IoTデバイスのデータを受信してデータベースに保存する」アプリケーション
  • 「蓄積されたデータをもとに気温や湿度の平均値、不快指数を計算して定期的にTwitterへツイートする」アプリケーション

なお、ツイートするコメントには気温や湿度の平均値、不快指数のほか、それが「何年何月のどこ(日本国内のある地点)と同じくらい」かも、体感温度として加えることにしました。これは、気象庁が公開している過去の気象データと比較して割り出します。

サンプルアプリケーションが出力するツイートの例
サンプルアプリケーションが出力するツイートの例

Cloudantの概要

IoTでは多数のデバイスからシンプルだが大量のデータが送られてくることが想定されます。 しかもデータ構造は、ビジネス要件やデバイスの変化で日々変わる可能性があります。 これらの非構造化・ビックデータを蓄積・利用するには、それらに適したデータベースの選定が必要です。

こうした要件には、JSONデータを格納できるドキュメント型NoSQLデータベースが便利です。 今回、IoTデバイスから送信されてくるデータの格納先として、そうしたデータベースの1つである「IBM Cloudant」を利用することにします。 CloudantはDBaaS(Database as a Service)として提供されており、セットアップなどは不要で、すぐに使い始めることができます。 また、スケーラビリティが高く、利用者は運用管理や保守から解放されます。

なお、CloudantについてはCodeZineの過去記事「エンタープライズ分野で使えるNoSQLのDatabase as a Service『IBM Cloudant』」が参考になります。

Node-REDの概要

Node-RED」は、Node.js上で動作するオープンソースのソフトウェアです。 機能をカプセル化したノードと呼ばれるモジュールが用意されており、ブラウザベースのUIからノード同士を繋げて処理の流れを作成していきます。

Node-REDの画面
Node-REDの画面

直感的に操作できるので、複数のサービスを繋げるアプリケーションのプロトタイプ作成には最適です。 筆者は、タブレットから操作ができる点も気に入っています。

iPad ProからNode-REDを利用
iPad ProからNode-REDを利用

昨年、日本でもNode-REDユーザーグループが発足し、利用促進や情報交換が行われるようになりました。 また、IoTデバイスとして利用可能なRaspberry PiのOSである「Raspbian」にプリンストールされたりと今後の展開が期待されます。

Bluemixではボイラーテンプレート「Node-RED Starter」が用意されているので、すぐに使い始めることができます。 Bluemixのサービスと連携するためのノードも標準でいくつか提供されています。 このNode-RED Starterも利用してサンプルアプリケーションを作成します。

IoTセンサーシミュレーターの準備

IoTデータを活用したアプリケーションを作成をするためには、まずデータを計測・発信するデバイスを準備しないといけません。 身近なものとしては、スマートフォン[1]やArduinoやRaspberry Piの機器を利用する方法があります。

[1]: スマートフォンは位置情報、ジャイロセンサー、加速度計、コンパスなど、センサーの塊です。

ちなみに、昨年開催されたイベントで、筆者は仲間と協力して、Bluemixのサービス(IBM Watson IoT Platform + Node-RED + IBM XPages)を組み合せてドローンを操作・モニタリングするデモを行いました。 ドローンをブラウザベースのコントローラーで操作し、後ろのスクリーンではドローンからのジャイロセンサーのデータを受信して、ドローンの姿勢を3Dモデルでリアルタイムに表示しています。 データの送受信にはIBM Watson IoT Platform(以下、Watson IoT Platform)を利用しました。

Bluemixのサービスでドローンを操作・モニタリングするデモ
Bluemixのサービスでドローンを操作・モニタリングするデモ

ただし、今回はIoTを利用したアプリケーションの作成をすぐ体験できるように「IoTセンサーシミュレーター」を利用します。 IoTセンサーシミュレーターは、Watson IoT Platformの「Quickstart」で用意されているアプリケーションで、ブラウザから操作可能になっています。

試しに、ブラウザでIoTセンサーシミュレーターを開いてください。

IoTセンサーシミュレータ。左から温度、湿度、物体温度の画面
IoTセンサーシミュレーター。左から温度、湿度、物体温度の画面

画面右上の12桁の文字列が「デバイスID」です。アクセスするたび、異なる文字列が表示されます。このデバイスIDを使ってデータを取得します。 画面両端の[<]ボタンや[>]ボタンををクリックすると、画面がTemperature(気温)Humidity(湿度)Object Temperature(物体温度)に変わります。 画面下部の[↑]ボタンや[↓]ボタンをクリックすると、それぞれの数値を変更できます。

また、デバイスIDをクリックすると、IoTセンサーシミュレーターが送信しているデータがグラフで表示されます。 数値を変更してグラフが変化することを確認してみましょう。 IoTセンサーシミュレーターをスマートフォンやタブレットから操作し、PCでグラフを確認してみると[2]、雰囲気がより伝わるかと思います。

IoTセンターシミュレーターで数値を変更した様子(グラフ)をPC上のブラウザで確認
IoTセンターシミュレーターで数値を変更した様子(グラフ)をPC上のブラウザで確認

これで、Watson IoT Platformへのデータ送信側の準備ができました。

なお、今回はシミュレーターを利用しましたが、ご興味のある方はIoTデバイス側のアプリケーションの作成にも挑戦してみてください。 Watson IoT Platform導入記事を解説している本連載の第1回が参考になります。 また、IBM Internet of Things Foundation Quickstartの「物理デバイスをお持ちの場合」にも参考になる情報があります。

IBM Internet of Things Foundation Quickstartの「物理デバイスをお持ちの場合」
IBM Internet of Things Foundation Quickstartの「物理デバイスをお持ちの場合」

[2]: PCでグラフを見る場合には、デバイスIDは手入力してください。

IoTを始めたい方も・本格導入を検討中の方も:おすすめソリューションのご紹介

ビジネスのパフォーマンスを高めようとさまざまな業種・企業で、IoT活用を前提とするプロジェクトが動き始めています。ただし、検討を始めて最初に出てくるのは、こんな要望ではないでしょうか。

「最初は実験的にスタートしたいから、小さく簡単に素早く始めたい」
「実運用に移ったときには10万・100万単位のセンサ/デバイスに対応できるスケーラビリティも確保したい」

これにお応えできるサービス・製品がIBMにあります。ぜひ、下記の資料をご覧ください。(編集部)

Node-REDの準備

次に、アプリケーションの作成環境の準備を行います。 Bluemixにログインして「ダッシュボード」を開き、画面上部のメニューから「カタログ」をクリックします。

ダッシュボードで「カタログ」をクリック
ダッシュボードで「カタログ」をクリック

「ボイラーテンプレート」の一覧が表示されるので、「Node-RED Starter」を探してクリックします。 このとき、画面左のメニューで表示するサービスなどを絞り込むこともできます。

ボイラーテンプレートの一覧で「Node-RED Starter」をクリック
ボイラーテンプレートの一覧で「Node-RED Starter」をクリック

Node-RED Starterの作成画面が開いたら、アプリケーションを作成する「スペース」を指定し、アプリケーションの「名前」と「ホスト」を入力して「作成」をクリックします。 ホスト名はBluemix全体でユニークである必要があります。

Node-RED Starter作成画面でスペースなどを入力
Node-RED Starter作成画面でスペースなどを入力

Bluemix上で環境構築(アプリケーションのステージング)が始まるので、終わるまでしばらく待ちます。

アプリケーションのステージング
アプリケーションのステージング

環境構築が完了すると「アプリは稼動しています」と表示されます。

アプリケーションのステージング完了
アプリケーションのステージング完了

画面左のメニューから「概要」をクリックし、作成されたアプリケーションを確認します。 上段の名前の下に表示されている「経路」が、今回作成したNode-REDフローエディターへのリンクです。

画面右にはアプリケーションの稼動状況およびログが表示されています。 また、画面下部には現在バインドされているサービスが表示されています。 Node-RED Starterでは、標準で「Cloudant NoSQL DB」がバインドされています。 「サービスまたはAPIの追加」から、その他のサービスを追加することもできます。

概要
概要

では、「経路」のリンクをクリックして、Node-REDフローエディターにアクセスしてみましょう。 リンク先の「Go to your Node-RED flow editor」をクリックします。

Node-RED in Bluemix
Node-RED in Bluemix

Node-REDフローエディター画面が開きます。エディター各部分の意味は表のとおりです。

Node-REDフローエディター
Node-REDフローエディター
Node-REDフローエディター各部分の意味
部分 名称 役割
ノードパレット 分類されたノードの一覧
シート シートごとにフローを作成する。「+」からシートを追加できる
ワークスペース ノードを配置して繋げ、フローを作成する
ノード 機能をカプセル化したモジュール
フロー ノードを繋げて処理の流れを定義したもの
デプロイ 作成したフローをデプロイする
情報またはデバッグコンソール 選択しているノードの情報またはデバッグコンソールを表示する

Node-REDでは、画面左のノードパレットからノードを画面中央のワークスペースに配置し、ノード同士を線で繋いでフロー(処理)を作成します。 処理およびデータは、ノードの左(インプットポート)から入り、右(アウトプットポート)から出て行くイメージです。 ノードによっては、左右両方または片方のポートしかないものがあります。

ノード同士を線で繋いでフローを作成する
ノード同士を線で繋いでフローを作成する

Node-RED Starterには、Bluemixの各種サービス(WatsonやdashDBなど)と連携できるノードがあらかじめ用意されています。

Bluemixの各種サービスと連携できるNode-RED Starterのノード
Bluemixの各種サービスと連携できるNode-RED Starterのノード

Node-REDの使い方

さて、アプリケーションの作成に入る前に、Node-REDに関するいくつかのトピックを紹介しましょう。

ログインユーザー名とパスワードの設定

Node-RED Starterの環境構築直後は、ログインパスワードが設定されていません。 このままの状態では、アプリケーションのURLにアクセスすると誰でもNode-REDフローエディターを利用できてしまいます。 使い始める前にパスワードを設定しておきましょう。 設定方法は、Node-REDフローエディターを開くボタンの下部にある「Learn how to password-protect your instance」に記述されています。

パスワードの設定方法
パスワードの設定方法

説明に従って、Bluemixの「環境変数」から「ユーザー定義」にユーザー名とパスワードを設定します。

環境変数のユーザー定義にユーザー名とパスワードを設定
環境変数のユーザー定義にユーザー名とパスワードを設定

これで、Node-REDフローエディターにアクセスしようとするとユーザー名とパスワードの入力が求められるようになります。

Node-REDへのログイン
Node-REDへのログイン

「Hello World」を書いてみる

それでは、最も簡単な例として、「Hello World」を表示するフローをNode-REDで書いてみましょう。 まず、画面左のノードパレットからInputのInjectノードとOutputのDebugノードをワークスペースにドラッグ&ドロップします。 そして、Injectノードのアウトプットポート(右側)からDebugノードのインプットノード(左側)へマウスをドラッグしてノード同士を繋ぎます。

フローの作成
フローの作成

Injectノードをダブルクリックするとノードの編集画面が開きます。 「Payload」欄のリストから「string」を選択し、“Hello World”と入力します。 入力した文字列は、payloadという名前のキーに格納されて後続のノードに渡されます。 「Name」欄は、ワークスペース上で表示するノードの名称(任意)です。 「Ok」をクリックして画面を閉じます。

ノードの編集画面
ノードの編集画面

画面右上の「Deploy」ボタンをクリックします。

作成したフローのデプロイ
作成したフローのデプロイ

デプロイが成功したら動かしてみましょう。 画面右上にある「debug」タブをクリックして、デバッグコンソールを表示しておきます。 Injectノードの左にあるインジェクトボタンをクリックして、デバッグコンソールに“Hello World”と表示されれば成功です。

Hello Worldの実行
Hello Worldの実行

Debugノードを使用したデバッグ

Debugノードはとてもよく使うノードです。 デフォルト設定では、受け取ったメッセージのpayloadキーの値のみを表示します。 フローで流れているJSON形式のメッセージ全体を表示したい場合には、Debugノードの編集画面の「Output」欄を「complete msg object」に変更します。

Debugノードの設定
Debugノードの設定

先ほどと同様に画面右上の「Deploy」ボタンをクリックして、実行します。 先ほどとは異なり、デバッグコンソールにJSON形式のメッセージ全体が表示されていることが確認できます。

デバッグコンソール
デバッグコンソール

ゴミ箱のアイコンをクリックするとデバッグコンソールをクリアできます。

デバッグコンソールのクリア
デバッグコンソールのクリア

デバッグコンソールへの出力を一時的にオフにしたい場合には、Debugノードの右側のボタンでオフにします。 もう一度クリックするとオンに戻ります。

Debugノードが増えてくるとフローのどの部分の情報なのかが分かりづらくなります。 状況に応じて切り替えると、デバッグ作業がしやすくなります。

デバッグコンソールへの出力ON/OFF
デバッグコンソールへの出力ON/OFF

フローのエクスポート/インポート

作成したフローは、JSON形式でエクスポートまたはインポートできます。

まず、エクスポートの方法です。 エクスポートしたいフローをワークスペース上で選択します。 この時、ドラッグしながら範囲指定すると複数のノードを一括で選択できます。 選択されたノードは淵が橙色で表示されます。 この状態から画面右上のメニューから「Export」-「Clipboard」を選択します。

エクスポート
エクスポート

表示されたテキストをクリップボードにコピーして別途保管します。

クリップボードへコピー
クリップボードへコピー

次に、インポートの方法です。 画面右上のメニューから「Import」-「Clipboard」を選択します。

インポート
インポート

先ほどエクスポートしたテキストを貼り付けてみましょう。

クリップボードからコピー
クリップボードからコピー

ワークスペースにインポートしたフローが追加されます。 ノードによってはインポート後、個別にノードの再設定(各種サービスへの接続情報など)が必要な場合があります。

このように、作成したフローを簡単にエクスポートまたはインポートできます。

Twitterへのツイートを行ってみる

次に、Twitterへツイートするフローを作成してみましょう。 使用可能なTwitterアカウントをお持ちでない方は、事前に登録をお願いします。

最初に、SocialのTwitterノード、Injectノード、Debugノードを配置して、下図のように繋ぎます。

Twitterへツイートするフローの配置
Twitterへツイートするフローの配置

Twitterノードの編集画面を開き、「Twitter ID」欄右端のペンのアイコンをクリックします。

Twitterノードの編集画面でペンのアイコンをクリック
Twitterノードの編集画面でペンのアイコンをクリック

「Click here to authenticate with Twitter.」をクリックします。

「Click here to authenticate with Twitter.」をクリック
「Click here to authenticate with Twitter.」をクリック

連携アプリの認証画面が表示されます。 Twitterへのログイン情報を入力して「連携アプリを認証」をクリックします。

連携アプリを認証
連携アプリを認証

次の表示が出たら認証は完了です。画面を閉じます。

連携アプリの認証が完了
連携アプリの認証が完了

Twitterノードの編集画面に戻ると「Twitter ID」に連携したTwitter IDが表示されます。 「Add」をクリックします。

「Add」をクリック
「Add」をクリック

「Ok」をクリックして編集画面を閉じます。

「Ok」をクリック
「Ok」をクリック

Twitterノードのステータスが青くなっていれば設定は完了です。

Twitterノードのステータスが青くなっていれば設定は完了
Twitterノードのステータスが青くなっていれば設定は完了

インジェクトボタンをクリックして、Twitterにタイムスタンプ値がツイートされていることを確認してください。

Twitterにタイムスタンプ値がツイートされた
Twitterにタイムスタンプ値がツイートされた

IoTを始めたい方も・本格導入を検討中の方も:おすすめソリューションのご紹介

ビジネスのパフォーマンスを高めようとさまざまな業種・企業で、IoT活用を前提とするプロジェクトが動き始めています。ただし、検討を始めて最初に出てくるのは、こんな要望ではないでしょうか。

「最初は実験的にスタートしたいから、小さく簡単に素早く始めたい」
「実運用に移ったときには10万・100万単位のセンサ/デバイスに対応できるスケーラビリティも確保したい」

これにお応えできるサービス・製品がIBMにあります。ぜひ、下記の資料をご覧ください。(編集部)

IoTセンサーシミュレーターのデータをCloudantへ保存するアプリケーションの作成

前ページまでで、冒頭で紹介したサンプルアプリケーションを作成するための準備や基礎知識を一通り説明できました。 ここから、冒頭で紹介したサンプルアプリケーションの作成を始めます。 サンプルアプリケーションは2つのアプリケーションで構成されますが、まず最初に「IoTセンサーシミュレーターのデータを受信してCloudantへ保存する」アプリケーションを作成します。

IoTセンサーシミュレーターのデータ受信

Watson IoT Platformからのデータを受信するために、InputのibmiotノードとDebugノードを配置して繋ぎます。

IoTセンサーシミュレーターのデータを受信するフロー
IoTセンサーシミュレーターのデータを受信するフロー

ここで、冒頭で説明したIoTセンサーシミュレーターを開いてください[3]。IoTセンサーシミュレーターを開いた状態のまま、Node-REDエディターに戻ります。ibmiotノードの編集画面を開いて、IoTセンサーシミュレーターの画面右上のデバイスIDを「Device Id」欄に入力し、デプロイします。

ibmiotノード
ibmiotノード

デプロイ後、2秒ごとに受信したデータがデバッグコンソールに表示されるようになります。

IoTセンサーシミュレーターのデータ受信
IoTセンサーシミュレーターのデータ受信

[3]: スマートフォンやタブレットから開いてもかまいません。ただし、ロック状態になるとデータの送信が止まります。ロックを解除してIoTセンサーシミュレーターを再読み込みしてください。再読み込みするとデバイスIDが変わるため、ibmiotノードのデバイスIDの設定も変更する必要があります。

タイムスタンプの付与

IoTセンサーシミュレーターには日時のデータがありません。 後の利用を考えて、受信したデータに日時のデータを付与してみましょう。 JavaScriptを記述するためのFunctionのFunctionノードを配置して、次図のように繋ぎ変えてください。 ノードを繋いでいる線は、選択して[Delete]キーで削除できます。

FunctionのFunctionノードを配置
FunctionのFunctionノードを配置

Functionノードの編集画面を開き、JavaScriptコードを記述します。

Functionノードの編集画面でJavaScriptコードを記述
Functionノードの編集画面でJavaScriptコードを記述

記述したコードは次のとおりです。 1~11行目は、タイムスタンプの文字列を生成しています(例:“2016-01-31T12:00:00Z”)。 13~19行目は、後続のノードに渡すJSON形式のデータを生成してmsg.payloadプロパティに格納しています。msg.payloadプロパティには出力するデータを格納します。 21行目は、後続のノードにmsgオブジェクトを渡しています。

//タイムスタンプの生成
var getTimestamp = function (date) {
    var yyyy = date.getFullYear();
    var mm = ('0' + (date.getMonth() + 1)).slice(-2);
    var dd = ('0' + date.getDate()).slice(-2);
    var h = ('0' + date.getHours()).slice(-2);
    var m = ('0' + date.getMinutes()).slice(-2);
    var s = ('0' + date.getSeconds()).slice(-2);
    var ts = yyyy + '-' + mm + '-' + dd + 'T' + h + ':' + m + ':' + s + 'Z';
    return ts;
};

msg.payload =  {
    "name": msg.payload.d.name,
    "temp": msg.payload.d.temp,
    "humidity": msg.payload.d.humidity,
    "objectTemp": msg.payload.d.objectTemp,
    "timestamp": getTimestamp(new Date())
};

return msg;

ibmiotノードから受け取ったデータは、msg.payloadに格納されています。 後で利用しやすいようにpayloadのフォーマットを上書きして変更しています。

msg.payload
msg.payload

デバッグコンソールでタイムスタンプが付与されていることを確認します。

タイムスタンプの確認
タイムスタンプの確認

受信データを一定間隔で処理

IoTセンサーシミュレーターのデータは、先ほど見たとおり、2秒ごとに発信されています。 このまま受信したデータをすべてデータベースに保存すると、データが多くなりすぎます。 そこで、FunctionのDelayノードを利用して、一定間隔でデータを処理するようにフローを変更します。

Delayノード
Delayノード

Delayノードを配置して、編集画面を開きます。 「Action」を「Limit rate to」、「Rate」を「1」msg(s) per「Minute」と設定します。 また、途中のデータを破棄するために「drop intermediate messages」を有効にします。

Delayノードの編集画面
Delayノードの編集画面

それから、ibmiotノードとFunctionノードの間にDelayノードを繋げてデプロイします。 これで、デバッグコンソールに1分ごとに受信データが表示されるようになりました。

Delayノードを用いたフロー
Delayノードを用いたフロー

Cloudantへの保存

前項までで、受信データの準備はできました。 今後は、受信データをデータベースであるCloudantへ保存するフローを作成していきます。

まず、StorageのCloudantノードを配置します。StorageのCloudantノードには2種類ありますが、ここではインプットポート(左側)のみのノードを配置してください。

Cloudantノードを配置
Cloudantノードを配置

CloudantノードをFunctionノードの後ろに繋げます。

Cloudantへ保存するフロー
Cloudantへ保存するフロー

Cloudantノードの編集画面を開きます。 「Service」には、リストから「[アプリ名]-cloudantNoSQLDB」を選択します。 「Database」には、作成するデータベースの名前を任意に入力します(例:iotsensor)。 保存するのはmsg.payloadプロパティに格納されているデータのみでよいので、「Only store msg.payload object?」を有効にしておきます。

Cloudantノードの編集画面
Cloudantノードの編集画面

作成したフローをデプロイをすると、受信したデータがCloudantへ保存されていきます。簡単ですね。

受信したデータがCloudantへ保存されていく
受信したデータがCloudantへ保存されていく

保存されたデータを確認してみましょう。 Bluemixダッシュボードに戻って、サイドメニューの「サービス」-「Cloudant NoSQL DB」を開いてください。 それから、画面右下の「Launch」をクリックします。

Cloudant NoSQL DB
Cloudant NoSQL DB

データベースの一覧が表示されるので見てみると、ここまでの操作で作成された2つのデータベースが確認できます。 1つ目は「nodered」で、名前のとおりNode-REDの各種設定や作成したフローの情報が保存されています。 2つ目は、先ほどフローで作成したデータベース(例:iotsensor)です。

データベースの一覧
データベースの一覧

2つ目のデータベース名をクリックすると「All Documents」が開きます。 画面右に保存されているデータが表示されます。試しに一番上のデータを見てみましょう。 ペンのアイコンをクリックします。

All Documents
All Documents

先ほどNode-REDのフローから保存したデータが表示されます。 このようにCloudantでは、JSON形式でデータを保存しています。

CloudantにJSON形式で保存されたデータ
CloudantにJSON形式で保存されたデータ

以上で、「IoTセンサーシミュレーターのデータを受信してCloudantへ保存する」アプリケーションは完成です。

IoTを始めたい方も・本格導入を検討中の方も:おすすめソリューションのご紹介

ビジネスのパフォーマンスを高めようとさまざまな業種・企業で、IoT活用を前提とするプロジェクトが動き始めています。ただし、検討を始めて最初に出てくるのは、こんな要望ではないでしょうか。

「最初は実験的にスタートしたいから、小さく簡単に素早く始めたい」
「実運用に移ったときには10万・100万単位のセンサ/デバイスに対応できるスケーラビリティも確保したい」

これにお応えできるサービス・製品がIBMにあります。ぜひ、下記の資料をご覧ください。(編集部)

Cloudantの準備

次は、「蓄積されたデータをもとに気温や湿度の平均値、不快指数を計算して定期的にTwitterへツイートする」アプリケーションの作成です。 ただしその前に、Cloudantに蓄積したIoTセンサーシミュレーターからのデータを検索するときに使用するインデックスと、過去の気象データを保存するための新しいデータベースを作成します。

インデックスの作成(IoTセンサーシミュレーターのデータ検索用)

Cloudantに保存したIoTセンサーシミュレーターからのデータを日付で検索できるように、インデックスを作成します。 「+」アイコンをクリックし、メニューから「New Search Index」を選択します。

「New Search Index」を選択
「New Search Index」を選択

「Create Search Index」画面が表示されるので、「_design/」欄に「index」、「Index name」欄にIndex名(ここではindexByTimestamp)を入力してください。画面下段にある「Type」欄では「keyword」(トークン化なし)を選択してください。

「Search index function」には、次のJavaScriptコードを記述します。

function (doc) {
  index("timestamp", doc.timestamp);
}

index関数の1つ目のパラメータは、インデックスを照会するときに使用するフィールド名です。 2つ目のパラメータは、インデックスを作成するデータです。

「Create Search Index」画面で入力を終えた状態
「Create Search Index」画面で入力を終えた状態

新しいデータベースの作成

サンプルアプリケーションでは、過去の気象データから、IoTセンサーシミュレーターのデータから計算した気温、湿度の平均値や不快指数が、何年何月の日本のどこと同じかを求めます。 その過去の気象データをアプリケーションから利用できるように、もう1つデータベースを作成します。

気象データは気象庁のホームページからダウンロードできます。 ダウンロードしたデータをもとにExcelなどを利用してJSON形式のデータを作成し、Cloudantのデータベースにあらかじめ登録しておきます。

なお、気象庁の気象データには不快指数がありません。 そこで、今回は便宜的に月平均気温と月平均相対湿度から不快指数(整数値)を求めることにしました。 不快指数については、Wikipediaを参考にしてください。

不快指数の式
不快指数の式

では、画面右上の「Create Database」から新規のデータベースを作成します。 データベース名(例:meteorologicaldata)を入力して「Create」ボタンをクリックします。

Create Database
Create Database

新規のデータベースが作成されました。 続いて、「All Documents」の「+」アイコンからリストの「New Doc」を選択します。

「New Doc」を選択
「New Doc」を選択

新規データとして、過去の気象データからサンプルアプリケーション用に加工したJSON形式のデータを貼り付けます。1件のデータは次のような内容になっています。

{
  "_id": "07675560228950c3d8374c4092256841",
  "_rev": "2-80df6c02cae197b66fc0ad6da3db66f7",
  "discomfort": 18,
  "temperature": -15.2,
  "humidity": 56,
  "year": 2011,
  "month": 2,
  "place": "富士山",
  "min": -26.2,
  "max": -3.7
}

_idは、デフォルトで表示されているものを利用します。 このとき、_idの最後に「,」(カンマ)を付けるのを忘れないようにしてください。 _idは、ユニークになるようにすれば、任意に設定することも可能です。 _revは、保存すると自動で作成されるので入力する必要はありません。

上記データの意味は、「2011年(year)2月(month)の富士山(place)は平均気温マイナス15.2℃(temprature)、平均湿度56%(humidity)、不快指数18%(discomfort)、過去最低気温マイナス26.2℃(min)、過去最高気温マイナス3.7℃(max)」です。

ダウンロードしたデータから作成したJSON形式のデータを貼り付ける
ダウンロードしたデータから作成したJSON形式のデータを貼り付ける

なお、今回は簡単に登録できる手作業によるデータ登録方法を紹介したましたが、実際の活用では一括でデータを登録するアプリを別途用意したほうがよいでしょう。

インデックスの作成(過去の気象データの検索用)

前項で作成した気象データのデータベースに対してもインデックスを作成しておきます。 設定方法は、IoTセンサーシミュレーターのデータに対してインデックスを作成したときと同じです。

「Search index function」には、次のJavaScriptを記述してください。 検索に使うフィールドは不快指数のフィールドを指定します(例:discomfort)。

function (doc) {
  index("discomfort", doc.discomfort);
}
過去の気象データの検索用のインデックスを作成
過去の気象データの検索用のインデックスを作成

これでCloudant側の準備が終わりました。 次ページから、用意したデータを利用してツイートするほうのアプリケーションを作成します。

IoTを始めたい方も・本格導入を検討中の方も:おすすめソリューションのご紹介

ビジネスのパフォーマンスを高めようとさまざまな業種・企業で、IoT活用を前提とするプロジェクトが動き始めています。ただし、検討を始めて最初に出てくるのは、こんな要望ではないでしょうか。

「最初は実験的にスタートしたいから、小さく簡単に素早く始めたい」
「実運用に移ったときには10万・100万単位のセンサ/デバイスに対応できるスケーラビリティも確保したい」

これにお応えできるサービス・製品がIBMにあります。ぜひ、下記の資料をご覧ください。(編集部)

平均気温・湿度、不快指数を計算して定期的にツイートするアプリケーションの作成

前項までで、IoTセンサーシミュレーターのデータをCloudantへ保存するアプリケーションができました。 これから、蓄積されたデータを利用して定期的にツイートするアプリケーションを作成していきます。 作業しやすいように、Node-REDで新規のシートを追加してください。

アプリケーションのフローは次図のとおりです。

アプリケーション全体のフロー
アプリケーション全体のフロー

1段目(②〜⑤のノード)は、1時間ごとに実行して、現在時刻から1時間前までのデータを検索・取得するフローです。

2段目の前半(⑥〜⑦のノード)は、取得したデータをもとに不快指数を計算するフロー。後半(⑧〜⑨のノード)は、不快指数に一致する過去の気象データを検索・取得するフローです。

3段目(⑩〜⑪のノード)は、取得したデータをもとに文章を作成してTwitterへツイートするフローです。

説明は、上図に示したフローにあるノードごとに行っていきます。 ただし、説明の中ではDebugノードを省略しています。 アプリケーション自体には不要なためですが、動作確認を行いたいので、フロー作成後にDebugノードを追加します。

サンプルアプリケーションのフローをダウンロードできます

本記事のタイトル下にあるダウンロードリンクから、サンプルアプリケーションのフローをダウンロードできます。 本記事の2ページ目にある「フローのエクスポート/インポート」節で説明している方法でインポートし、アプリケーションを試すことができます。インポート後に、ibmiot, Cloudant, Twitterノードの設定を行ってデプロイしてください。

ファイル名「IoT2DB_flow.json」
「IoTデバイスのデータを受信してデータベースに保存する」アプリケーションのフロー
ファイル名「TweetData_flow.json」
「蓄積されたデータをもとに気温や湿度の平均値、不快指数を計算して定期的にTwitterへツイートする」アプリケーションのフロー

ノード①:定期的にTweetするフロー(フローの説明)

「定期的にTweetするフロー」はこのフローを説明するコメントです。このノードはワークスペース上にコメントを表示するためのノードで特に機能はありません。 作成するにはFunctionのCommentノードを配置し、「Title」にフローのタイトルを入力します。

①Commentノード「定期的にTweetするフロー」
①Commentノード「定期的にTweetするフロー」

ノード②:定期的に実行

このノードは、イベントを定期的に発生させるためのノードです。 Injectノードを配置して次表のように設定してください。

項目 設定値 備考
Payload timestamp このノードからのpayloadは利用しません。デフォルトのままで構いません
Topic (空欄)  
Repeat interval 周期は任意に設定してください。テスト中は短めがよいでしょう
Name (任意)  
②Injectノード「定期的に実行」
②Injectノード「定期的に実行」

ノード③:検索期間の設定

CloudantからIoTセンサーシミュレーターのデータを取り出すとき、どれくらいの期間(単位:分)のデータを取り出すかを設定します。 Functionノードを配置して、次のJavaScriptコードを設定します。

//検索期間の設定(現在の日時からspanで指定した期間を検索)
var getSearchText = function ( nowdate , span ) {
    var startdate = new Date( nowdate.getFullYear() , nowdate.getMonth() , nowdate.getDate() ,
    nowdate.getHours() , nowdate.getMinutes() - span , nowdate.getSeconds() );
    return getTimestamp( startdate ) + " TO " + getTimestamp( nowdate );
};
//タイムスタンプの生成
var getTimestamp = function ( date ) {
    var yyyy = date.getFullYear();
    mm = ('0' + (date.getMonth() + 1)).slice(-2);
    dd = ('0' + date.getDate()).slice(-2);
    h = ('0' + date.getHours()).slice(-2);
    m = ('0' + date.getMinutes()).slice(-2);
    s = ('0' + date.getSeconds()).slice(-2);
    ts = yyyy + '-' + mm + '-' + dd + 'T' + h + ':' + m + ':' + s + 'Z';
    return ts;
};
//表示用日付の生成
var getDisplayDatetime = function ( date ) {
    date.setTime(date.getTime() + (1000 * 60 * 60 * 9 ));    //1000*60秒*60分*9時間
    var yyyy = date.getFullYear();
    mm = ('0' + (date.getMonth() + 1)).slice(-2);
    dd = ('0' + date.getDate()).slice(-2);
    h = ('0' + date.getHours()).slice(-2);
    ts = yyyy + '年' + mm + '月' + dd + '日' + h + ':' + m + ':' + s;
    return ts;
};
var span = 60;
var nowdate = new Date();
msg.payload = getSearchText( nowdate , span );

//グローバル変数に日時を格納
context.global.date = getDisplayDatetime( nowdate );
context.global.span = span;

return msg;

1~6行目:検索期間の文字列を作成しています(例:2016年1月31日12:10:20から13:10:20までの場合、”2016-01-31T12:10:20Z TO 2016-01-31T13:10:20Z”)。

18~27行目:ツイート時に使用する日付の文字列を組み立てています。また、日本時間に変更しています。

28行目:検索期間(単位:分)を指定しています。

32~34行目:後続のノードで使用できるように、必要な値をグローバル変数へ設定しています。

③Functionノード「検索期間の設定」
③Functionノード「検索期間の設定」

ノード④:検索条件の設定

ここでは、Cloudantからデータを取り出すときに指定する条件(検索期間と最大取得数)を設定しています。 Functionノードを配置して、次のJavaScriptコードを設定します。

msg.payload = {
    'query': 'timestamp:[' + msg.payload + ']',
    'limit': 200
};

return msg;

2行目:ノード④で作成した検索期間の文字列('query')を指定しています。

3行目:検索結果の最大取得数('limit')を指定しています。

④Functionノード「検索条件の設定」
④Functionノード「検索条件の設定」

IoTを始めたい方も・本格導入を検討中の方も:おすすめソリューションのご紹介

ビジネスのパフォーマンスを高めようとさまざまな業種・企業で、IoT活用を前提とするプロジェクトが動き始めています。ただし、検討を始めて最初に出てくるのは、こんな要望ではないでしょうか。

「最初は実験的にスタートしたいから、小さく簡単に素早く始めたい」
「実運用に移ったときには10万・100万単位のセンサ/デバイスに対応できるスケーラビリティも確保したい」

これにお応えできるサービス・製品がIBMにあります。ぜひ、下記の資料をご覧ください。(編集部)

ノード⑤:期間内のデータを検索

このノードで、CloudantからIoTセンサーシミュレーターのデータを取り出します。 StorageのCloudantノードを配置し、次表のように設定してください。 使用するノードは、左右両方にポートがあるCloudantノードです。

左右両方にポートがあるCloudantノードを使う
左右両方にポートがあるCloudantノードを使う
項目 設定値 備考
Service [アプリ名]-cloudantNoSQLDB  
Database [データベース名] 例:iotsensor
Search by search index  
  index/[インデックス名] 例:indexByTimestamp
Name [任意]  
⑤Cloudantノード「期間内のデータを検索」
⑤Cloudantノード「期間内のデータを検索」

ノード⑥:平均気温と平均湿度の計算

ノード⑤で取り出したデータから、平均気温と平均湿度を計算します。 Functionノードを配置して、次のJavaScriptコードを設定します。

//平均値を計算
var getAverage = function( arr ) {
    var sum = 0;
    arr.forEach(function( elm ) {
        sum += elm;
    });
    return Math.round(sum / arr.length);
};

var total = msg.cloudant.total_rows;
if ( total === 0 ){
    //データが見つからなかった場合は処理を終了する(後続にmsgを返さない)
} else {
    //データの取得
    var timestamp = [];
    var temp = [];
    var humidity = [];
    obj = msg.payload;
    for ( var i in obj ) {
        var iotfdata = obj[ i ];
        var name1 = "temp";
        var name2 = "humidity";
        var name3 = "timestamp";
        temp.push(iotfdata[name1]);
        humidity.push(iotfdata[name2]);
        timestamp.push(iotfdata[name3]);
    }

    msg.payload = {
        "timestamp" : timestamp ,
        "temp" : temp ,
        "humidity" : humidity ,
        "avgtemp" : getAverage( temp ) ,
        "avghumidity" : getAverage( humidity )
    };

    return msg;
}

1~8行目:平均値の計算を行っています。

10行目:検索結果のデータ件数(msg.cloudant.total_rows)を取得しています。

11~12行目:取得したデータ件数が0件の場合、そのまま処理を終了します。 後続のフローにmsgを渡さないと、以降のフローは動作せず終了します。 取得したデータが1件でもある場合、平均気温と平均湿度を求めます。

29~35行目:後続のノードに渡すデータを作成しています。

⑥Functionノード「平均気温と平均湿度の計算」
⑥Functionノード「平均気温と平均湿度の計算」

ノード⑦:不快指数の計算

平均気温、平均湿度に続き、ここでは不快指数を計算します。 Functionノードを配置して、次のJavaScriptコードを設定します。

//不快指数の計算
var getDiscomfortIndex = function ( Td , H ) {
    return 0.81 * Td + 0.01 * H * (0.99 * Td - 14.3) + 46.3;
};

var temp = msg.payload.avgtemp;
var humidity = msg.payload.avghumidity;
var discomfort = Math.round(getDiscomfortIndex( temp , humidity ));

//グローバル変数に不快指数を格納
context.global.temp = temp;
context.global.humidity = humidity;
context.global.discomfort = discomfort;

msg.payload = discomfort;

return msg;

1~8行目:不快指数の計算を行っています。

10~13行目:グローバル変数に結果を設定しています。

15行目:後続のノードに渡す不快指数の値を設定しています。

⑦Functionノード「不快指数の計算」
⑦Functionノード「不快指数の計算」

IoTを始めたい方も・本格導入を検討中の方も:おすすめソリューションのご紹介

ビジネスのパフォーマンスを高めようとさまざまな業種・企業で、IoT活用を前提とするプロジェクトが動き始めています。ただし、検討を始めて最初に出てくるのは、こんな要望ではないでしょうか。

「最初は実験的にスタートしたいから、小さく簡単に素早く始めたい」
「実運用に移ったときには10万・100万単位のセンサ/デバイスに対応できるスケーラビリティも確保したい」

これにお応えできるサービス・製品がIBMにあります。ぜひ、下記の資料をご覧ください。(編集部)

ノード⑧:検索条件の設定

ここでは、Cloudantから過去の気象データを取り出すときの検索条件を設定します。 Functionノードを配置して、次のJavaScriptコードを設定します。

msg.payload = {
    'query': 'discomfort:' + msg.payload ,
    'limit': 200
};

return msg;

2行目:ノード⑦で計算した不快指数を指定しています。

⑧Functionノード「検索条件の設定」
⑧Functionノード「検索条件の設定」

ノード⑨:気象データを検索

ノード⑧で設定した検索条件を使って、Cloudantから過去の気象データを取得します。 左右両方にポートがあるCloudantノードを配置して、次表のように設定してください。

項目 設定値 備考
Service [アプリ名]-cloudantNoSQLDB  
Database [データベース名] 例:meteorologicaldata
Search by search index  
  index/[インデックス名] 例:indexByDiscomfort
Name [任意]  
⑨Cloudantノード「気象データを検索」
⑨Cloudantノード「気象データを検索」

ノード⑩:Tweet文書の作成

ノード⑨で取り出した気象データを使って、ここでツイートする文を組み立てます。 Functionノードを配置して、次のJavaScriptコードを設定します。

//体感温度
var getWindchillFactor = function( discomfort ) {
    var comment = '';
    if (discomfort < 55) {
        comment = 'に寒いですね!';
    } else if ( discomfort >= 55 && discomfort < 60 ){
        comment = 'に肌寒いですね!';
    } else if ( discomfort >= 60 && discomfort < 65 ){
        comment = 'ですね!';
    } else if ( discomfort >= 65 && discomfort < 70 ){
        comment = 'に快いですね!';
    } else if ( discomfort >= 70 && discomfort < 75 ){
        comment = 'に暑くはないですね!';
    } else if ( discomfort >= 75 && discomfort < 80 ){
        comment = 'にやや暑いですね!';
    } else if ( discomfort >= 80 && discomfort < 85 ){
        comment = 'に暑くて汗が出ますね!';
    } else {
        comment = 'に暑くてたまらないですね!';
    }
    return comment;
};

var total = msg.cloudant.total_rows;
var date = context.global.date;
var temp = context.global.temp;
var humidity = context.global.humidity;
var discomfort = context.global.discomfort;

tweetText = date + '頃のデバイス近辺の平均気温は' + temp + '度、平均湿度は' + humidity + '%、不快指数は' + discomfort + 'です。';

if ( total === 0 ){
    msg.payload = tweetText + ' ' + '似た気候の場所はどこだろう?';
} else {
    var obj = msg.payload;
    msg.payload = tweetText +
                obj[0].year + '年' + obj[0].month + '月の' + obj[0].place + 'のよう' + getWindchillFactor( discomfort ) +
                '(最高気温:' + obj[0].max + '度、最低気温:' + obj[0].min + '度)';
}
return msg;

1~22行目:不快指数から体感温度のコメントを作成しています。

24行目:検索結果のデータ件数(msg.cloudant.total_rows)を取得しています。

25~28行目:グローバル変数から日付、平均気温と湿度、不快指数を取得しています。

30行目~:ツイートする文章を作成しています。

⑩Functionノード「Tweet文書の作成」
⑩Functionノード「Tweet文書の作成」

ノード⑪:Tweet

最後の処理として、ノード⑪で組み立てた文をTwitterにツイートします。 Twitterノードを配置して「Node-REDの使い方 - Twitterへのツイートを行ってみる」の手順に従ってTwiiter IDを設定してください。

⑪Twitterノード
⑪Twitterノード

Twitterアカウントが準備できない場合は次のステップに進んでください。 ツイートする代わりにデバッグコンソールで確認だけは可能です。

Debugノードの設定

最初に示したフローの図にはありませんでしたが、ノード⑪までの処理の結果を確認するために、フローの最後にDebugノードを配置してください。

Debugノードを追加
Debugノードを追加

以上で、フローは完成です。次ページで実行してみます。

IoTを始めたい方も・本格導入を検討中の方も:おすすめソリューションのご紹介

ビジネスのパフォーマンスを高めようとさまざまな業種・企業で、IoT活用を前提とするプロジェクトが動き始めています。ただし、検討を始めて最初に出てくるのは、こんな要望ではないでしょうか。

「最初は実験的にスタートしたいから、小さく簡単に素早く始めたい」
「実運用に移ったときには10万・100万単位のセンサ/デバイスに対応できるスケーラビリティも確保したい」

これにお応えできるサービス・製品がIBMにあります。ぜひ、下記の資料をご覧ください。(編集部)

アプリケーションの実行

アプリケーションを実行する前に、データがCloudantの中に存在している必要があります。 実行前にIoTセンサーシミュレーターを開いて、ある程度データを蓄積しておいてください。

手動でアプリケーションを実行したい場合は、インジェクトボタンをクリックします。 まずは、デバッグコンソールにツイートした文が表示されていかどうかを確認してください。

デバッグコンソールにツイートした文が表示された
デバッグコンソールにツイートした文が表示された

そして、Twitterにその文がツイートされていれば実行は成功です!

ツイートの確認
ツイートの確認

最後に

Bluemixには、Watson IoT Platform、Cloudant、Node-RED以外にも、Watsonなど魅力的なサービスがあり、それらのサービスと連携したアプリケーションを素早く作成して公開できます。

サービスの一例(Watson関連)
サービスの一例(Watson関連)

今回は、Twitterを利用しましたが、例えばWatsonの「Text to Speech(音声合成)」サービスを利用すれば、情報を音声で読み上げるサイトを構築できます。 また、「Insights for Weather」サービスを利用して、現在の天気や今後の予報を取得・表示するなどのアプリケーションも考えられます。

去る2月18日に、日本IBMとソフトバンクが「IBM Watson」を利用した日本語版コグニティブサービスの提供を開始するという発表がありました(記事)。今後、BluemixおよびNode-RED Starterから日本語のWatsonサービスが利用できるようになることが期待されます。筆者も楽しみに待ちたいと思います。

IoTを始めたい方も・本格導入を検討中の方も:おすすめソリューションのご紹介

ビジネスのパフォーマンスを高めようとさまざまな業種・企業で、IoT活用を前提とするプロジェクトが動き始めています。ただし、検討を始めて最初に出てくるのは、こんな要望ではないでしょうか。

「最初は実験的にスタートしたいから、小さく簡単に素早く始めたい」
「実運用に移ったときには10万・100万単位のセンサ/デバイスに対応できるスケーラビリティも確保したい」

これにお応えできるサービス・製品がIBMにあります。ぜひ、下記の資料をご覧ください。(編集部)

この記事は参考になりましたか?

  • このエントリーをはてなブックマークに追加

【AD】本記事の内容は記事掲載開始時点のものです 企画・制作 株式会社翔泳社

この記事は参考になりましたか?

この記事をシェア

  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/9282 2016/04/04 02:08

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング