はじめに
株式会社ウフルでは、IoTシステムを構築するためのクラウドサービスであるenebularを提供しています。enebularでは、Node-REDフローの開発、そのフローのクラウドやデバイスへの配布を行なうことでIoTシステムを構築できます。さらに、enebularではInfoMotionというデータの可視化機能も提供しており、これを利用することでIoTシステムで集めたデータを可視化することもできます。
この記事では、センサデータを入出力するサーバ機能の開発と、そのサーバ機能に蓄積したセンサデータをInfoMotionで可視化する方法を示します(デバイスからセンサデータを出力する部分についてはダミーとします)。サーバ機能の実装にはクラウドアプリケーションプラットフォームであるherokuを利用します。
InfoMotionで可視化するデータは、Firebase、PubNub、API Gateway(AWSのAPI Gatewayを使って作成したサーバ機能を想定)のData Sourceに蓄積することを想定していますが、Node-REDフローを使ってもData Sourceであるサーバ機能を作成できることを説明したいと思います。
開発するNode-REDフローはenebular上で確認することができます。必要に応じご自分のenebularのProjectにImportしてご利用ください。
- センサデータを蓄積するサーバ機能(利用するにはpostgresノードのプロパティの変更が必要です)
-
ダミーのセンサデータ送信(利用するには
http request
ノードに設定したURLの変更が必要です)
準備
利用するサービスのユーザ登録
開発を始める前に以下のクラウドサービスのアカウントを取得します。
今回の開発はどちらも無料利用の範囲で試すことができます。
herokuのアプリケーション追加
enebularで作成したNode-REDフローを配置する場所となるherokuのアプリケーションを追加します。herokuにログインし、Dashboardからアプリケーションを追加します。センサデータを保存するサーバ機能になるのでアプリケーションの名前をsensor-data-repo
としました。ただし、herokuの名前は重複できないため、試す際には別の名前をご指定ください。
次にPostgreSQLを準備します。herokuのsensor-data-repo
のOverview画面からConfigure Add-ons
をクリックします。検索欄にHeroku Postgres
と入力し、PlanをHobby Dev - Free
を選んでProvision
を押します。
次にこのPostgreSQLのデータベースにテーブルを追加します。下記の記事等を参考に実施されると良いと思います。
今回は、データベースにテーブルを作るときに利用するSQLは下記とします。
これは部屋毎(roomname)にその部屋の温度(temperature)を記録し、記録した時刻(ts)を保存するためのテーブルを作るSQLです。
-- Table Definition ----------------------------------------------
CREATE TABLE sensordata_tbl (
id SERIAL PRIMARY KEY,
temperature numeric NOT NULL,
roomname text,
ts bigint NOT NULL
);
-- Indices -------------------------------------------------------
CREATE UNIQUE INDEX sensordata_tbl_pkey ON sensordata_tbl(id int4_ops);
開発
センサデータを蓄積するサーバ機能
enebularのNode-REDのWeb Editorを使用して、センサデータを蓄積するサーバ機能を開発します。
まず、enebularにサインインし、Projectを作成します。画面上部のProjects
をクリックし、右上のCreate Project
をクリックして適当なProject名を入力してSubmit
ボタンを押下します。
次にFlowを作成します。左のメニューからFlows
をクリックします。右下の+
ボタンを押下し、表示されたCreate Flow
ダイアログに適当な名前を入力してContinue
ボタンを押下します。表示された画面にあるEdit
ボタンを押下するとNode-REDのWeb Editorが開きます。Web Editorでフローを編集した場合、右上のデプロイ
ボタンを押下して保存します。このデプロイは、編集したフローをWeb Editor上で有効化することを意味し、クラウドやデバイスに配置するには、別途デプロイ作業が必要となります。
Web Editorでは以下の処理を開発します。
-
センサデータの配信
PostgreSQLに保存したセンサデータをHTTP(GET)で配信します。InfoMotionでは、HTTPリクエスト時にURLに以下のように開始時刻と終了時刻を指定することで可視化したい範囲の時間帯を指定します。時間は1970/1/1 00:00:00.000(GMT)からの経過ミリ秒数で指定します。
https://<サーバ名>/<path>?start=<開始時刻のミリ秒数>&end=<終了時刻のミリ秒数>
-
センサデータの受信
HTTPリクエスト(POST)でセンサデータを受け取りPostgreSQLに保存します。
作成するNode-REDフローは次のようになります。
PostgreSQLを利用するノードは標準では含まれないため、node-red-contrib-re-postgres
のノードをインストールします。[右上のメニュー]-[パレットの管理]-[ノードを追加]をクリックする。検索欄にnode-red-contrib-re-postgres
と入力し、ノードを追加
をクリックします。
各処理について説明します。
2021/5/8: node-red-contrib-postgresが利用できなくなっていたため同様の機能を提供するnode-red-contrib-re-postgresを利用するように修正しました
センサデータの配信
http
ノード
http
ノードにより、データ取得のリクエストを受け付けます。
プロパティを以下のように設定します。
メソッド: GET
URL: /apigw-datasource
これは上記URLにHTTPのGETリクエストを受け付けることを表しています。
function
ノード(query)
PostgreSQLに対するqueryを行なうSQLを作る処理を行います。function
ノードのプロパティに下記のJavaScriptを記載します。
const start = msg.payload.start; // startに設定された時刻を取得
const end = msg.payload.end; // endに設定された時刻を取得
const apiKey = msg.req.headers["x-api-key"]; // 認証に利用するx-api-keyヘッダの値を取得する
if( apiKey == null || apiKey != "test-api-key") { // 認証の値が一致するか確認する
node.error("authentication error", msg); // test-api-keyに一致しないならエラーとする
return;
}
if( start == null || end == null) {
node.error("parameter error", msg); // start又はendに値が設定されていなければエラーとする
} else {
msg.payload = "select * from sensordata_tbl where ts > " + start + " and ts < " + end + ";"; // msgにSQLを格納する(次のノードで利用する)
return msg;
}
postgres
ノード
上のfunctionノードで作成したSQLをPostgreSQLで実行します。
このノードには、PostgreSQLにアクセスするための情報をherokuのDashboardから取得し登録します。
herokuにログインし、sensor-data-repoのOverview画面を表示し次のようにリンクを辿ります。[Heroku Postgres]-[上部のSettings]-[右のView Credentials...]により、Credentials情報を表示します。
次にpostgres
ノードを配置して、ダブルクリックすると表示されるプロパティのServer項目の右にある鉛筆をクリックします。
herokuのCredential情報を参照し、表示された各入力欄に値を入力します。
Receive query output ?
をチェックします。これにより、SQLの実行が終わったら次のノードが呼ばれるようになります。
function
ノード(convert)
PostgreSQLから取得したデータをInfoMotionが読める形式に変換します。function
ノードのプロパティに下記のJavaScriptを記載します。
let list = [];
const results = msg.payload;
results.forEach((val, index, arr) => {
const obj = {
temperature: Number(val.temperature),
roomname: val.roomname,
ts: Number(val.ts)
};
list.push(obj);
})
msg.payload = list;
return msg;
roomname(部屋名)、温度(temerature)、時刻(ts)を含むJavaScriptのオブジェクトを作成しています。
http response
ノード
生成したJavaScriptオブジェクトを呼び出し元に返します。HTTPでは正常終了時の状態コードは200にするルールであるため、プロパティの状態コードは200とします。
センサデータの受信
http
ノード
http
ノードにより、センサデータを受信します。
プロパティを以下のように設定します。
メソッド: POST
URL: /sensordata
これは上記URLにHTTPのPOSTリクエストを受け付けることを表しています。
function
ノード(insert)
PostgreSQLに受信したデータをinsertするSQLを作る処理を行います。function
ノードのプロパティに下記のJavaScriptを記載します。
const roomname = msg.payload.roomname;
const temperature = msg.payload.temperature;
const apiKey = msg.req.headers["x-api-key"];
if( apiKey == null || apiKey != "test-api-key") {
node.error("authentication error", msg);
return;
}
if( temperature == null) {
node.error("parameter error", msg);
} else {
msg.payload = "insert into sensordata_tbl (roomname, temperature, ts) values ('" + roomname + "', " + temperature + ", " + Date.now() + ");";
return msg;
}
postgres
ノード
センサデータを保存するSQLを使ってPostgreSQLのデータベースに保存します。この設定内容は、センサデータの配信
のために設置したpostgres
ノードと同じ内容とします。
出力のhttp response
ノード
正常完了時の応答を返します。プロパティの状態コードに200を設定します。
エラーが発生したときの処理
catch
ノード
センサデータの配置
、センサデータの受信
の処理の中で発生したエラーを捕まえるためのノードです。上記で記したfunction
ノードに記載したJavaScriptの中で以下のように書いた箇所でエラーが出力され、これを捕まえることができます。
node.error("parameter error", msg);
機能のtemplate
ノード
呼び出し元に応答するエラーの内容を定義します。プロパティ画面には以下のように定義します。
http response
ノード
template
ノードで生成したJSONを呼び出し元に返します。HTTPの異常終了時の状態コードは内容により種類がありますが、今回は内部エラーを表す500をプロパティの状態コードに設定します。
herokuへのデプロイ
enebularを使って、作成したNode-REDフローをherokuに配置します。enebularのドキュメントのFrow Deploymentを参照し進めてください。
ダミーのセンサデータ送信
今回は、温度センサの代わりにダミーのNode-REDのフローを定義します。作成するフローを以下に示します。
inject
ノードを使って定期的(10秒毎)にイベントを発生させます。
次のfunction
ノード(ダミーデータ生成)ではダミーのセンサデータをランダムに作成します。プロパティに記載するJavaScriptを下記します。
const roomnames = ["living", "bedroom", "balcony"]
const roomname = roomnames[Math.floor(Math.random()*roomnames.length)]
msg.payload={roomname: roomname, temperature:15+Math.random()*5}
msg.headers = {"x-api-key":"test-api-key"} // 認証に用いるAPIキーを設定する
return msg;
http request
ノードでは、上記で作成したデータをherokuに配置したセンサデータの受信
機能に送付します。以下のように設定します。
URLは以下のように設定します。
https://sensor-data-repo.herokuapp.com/apigw-datasource
実行するには、上部のDeployボタンを押下した後、inject
ノードの左のボタンを押下すると10秒毎にランダムデータを生成し、そのデータをセンサデータの受信
機能に送付するようになります。
InfoMotionの作成
格納したセンサデータを可視化するためにenebularの機能の一つであるInfoMotionを使います。
まずData Source
を作成します。enebularにサインインし、次のようにリンクを辿ります。
[上部のProjects]-[作成したProject名]-[左のメニューのData Sources]-[右下の+ボタン]
表示されたダイアログのTitle(自由に決めてください)を入力し、Data Source Type
にはAPI Gateway
を入力します。Endpoint
とAPI Key
の入力欄が表示されますので、下記のように入力します。
Endpoint: https://sensor-data-repo.herokuapp.com/apigw-datasource
API Key: test-api-key
次に、可視化に用いるInfoTypeをImnportします。enebularの上部にあるDiscover
をクリックします。検索欄にlinechart
と入力し、enebularの帯が表示されたInfoTypeをクリックします。Preview画面が表示されますので、右上のImport
ボタンをクリックし、今回作成したProject名を選択してInfoTypeを取得します。
次に、左のメニューからInfoMotionsをクリックし、右下の+
ボタンを押下します。表示されたダイアログで、Name
と必要に応じDescription
を入力します。
[Manage Graphs
ボタン]-[Create Graph
ボタン]を押下し、次のように設定します。
Save
ボタンを押下し、作られたGraphをAdd
するとDashboardにグラフが追加されます。表示した例を以下に示します。
上部の時刻表示をクリックすると表示する時間帯を選択できます。また、Dashboardのレイアウトを保存したい場合はSave Layout
ボタンを押下します。
まとめ
heroku等の他社サービスをプラットフォームとして利用してはいますが、enebularの機能を主に利用してセンサデータの収集と、そのデータを可視化する機能を、ほぼプログラミングレスで開発できることを示しました。
今回はダミーで実現したセンサデバイス側の開発も、enebularではNode-REDを利用して実現できるため、センサデータの収集や可視化も含めたIoTシステムを全体を少ない手間で開発できます。
是非enebularの利用をご検討頂ければ幸いです。