概要
エヌシーアイ総合システムのtaguchyです。
普段は主にBtoCのWEBシステムや、BtoB向けWEB APIの開発などをしています。
最近はIoT関連でもお仕事させていただいております。
さて、前回はAWSIoT、Lambda、Firehoseを利用してElasticSearchとS3にセンシングデータを保存することを行いました。
(前回はこちら)
今回は保存したデータを使ってKibana上で会議室の使用状況を可視化します。
データの可視化
センサーの人感検知数を時系列でグラフ化する
時系列表示を行うため、Timelion(タイムライン)を利用します。
「Visualize」⇒「Create new visualization」⇒「Timelion」でTimelionの新規画面を開きます。
とりあえず、条件式を何も表示せずにグラフ表示をしてみます。
はい。なんかでました。
全センサーからあがってきているデータの件数が時系列ですべて表示されています。
以下の条件を入れてみます。
- センサーのMACアドレスを指定(3つのセンサーの内、1つを指定)
- 人感検知したステータスを指定
- なんとなくかっこいいから棒グラフで表示
- グラフに凡例を付ける
⇒出来上がった条件式
.es(index=meeting-room-*,metric=count,q='status:04 AND sensor_mac:24718902B258').bars().label("検知数")
なかなか良いです。
時系列にて検知数をデータ化しました。
会議室の在室有無を可視化する
センサーの仕様上、センサー内で人が動いた場合、何度も検知データが送信されます。
その為、特定の時間範囲で検知数が1以上であった場合に”在室”扱いとします。
単純にデータをただ溜めるだけだと、Kibana側でどうしようもできなかったため、データ変換にひと工夫加えて、以下のようなことを行います。
- 新しい数値型のデータフィールド
exist
を作成 - センサーからあがったデータが人感検知した状態であった場合、
exist
に1
を設定 - 検知していない状態であった場合、
exist
に0
を設定 - Kibana側で時間範囲指定(例:30秒)と数値型フィールドの最大値を取得
⇒時間範囲の中で、一度でも検知していればexist
が1
となる
Lambdaを変更
以下のコードに変更しました。
'use strict';
console.log('Loading function');
const csv = require('csvtojson');
const asyn = require('async');
require('date-utils');
exports.handler = (event, context, callback) => {
// all record convert.
asyn.map (event.records, function (record, callback) {
// need to base64 decode.
let sensor_data = Buffer.from(record.data, 'base64').toString('utf8');
// "$GPRP" is not need.
var sensor_data_non_gprp = sensor_data.replace(/^(\$GPRP,)/g, "");
// split payload.
let payload = sensor_data_non_gprp.match(/^(.{12},.{12},.*,)(.*)/);
let split = payload[2].match(/^(02010612FF0D0082BC)(.{4})(.{2})(.{8})(.{4})(.{2})(.{6})/);
let fix = split[1];
let battery = split[2];
let status = split[3];
let reserve = split[4];
let user = split[5];
let fix2 = split[6];
let reserve2 = split[7];
// make @timestamp
let now = new Date();
// make existFlg
var existFlg = 0;
if (status !== "00") {
existFlg = 1;
}
let sensor_data_split_payload = payload[1]
+ fix + "," + battery + ","
+ status + "," + reserve + ","
+ user + "," + fix2+ ","
+ reserve2 + "," + now.toFormat('YYYY-MM-DDTHH24:MI:SS') + ","
+ existFlg;
csv({
noheader: true,
headers: [
'sensor_mac',
'gw_mac',
'rssi',
'fix',
'battery',
'status',
'reserve',
'user',
'fix2',
'reserve2',
'@timestamp',
'exist'],
colParser:{
"exist":"number"
}
}).fromString(sensor_data_split_payload)
.on('json',(jsonObj)=>{
// Called for the number of rows.
console.log(jsonObj);
let jsonData = Buffer.from(JSON.stringify(jsonObj), 'utf8').toString('base64');
callback (null, {
recordId : record.recordId,
result : 'Ok',
data : jsonData
}
);
});
}, function (err, results) {
if (err) {
throw err;
}
console.log(results);
callback (null, {records: results});
});
};
Kibanaでデータを確認
Kibanaにてindexの作り直しが済んだら、グラフを作成します。
Gauge(ゲージ)を利用します。
「Visualize」⇒「Create new visualization」⇒「Gauge」⇒「From a New Search, Select Index」⇒「meeting-room-*」でGaugeの新規画面を開きます。
Timelionと同様、全データの件数が表示されました。
以下の条件を入れてみます。
- センサーのMACアドレスを指定(3つのセンサーの内、1つを指定)
- existの最大値を指定
- 表示ラベルを修正
- 目盛り線は削除
画面は以下のようになりました。
時間範囲内に人感を検知した場合に赤、それ以外は白となるゲージができました。
うん、微妙です。他にいい方法がないかもう少し研究したいところ。。
全会議室のグラフをDashboardにまとめる
Dashboardにまとめると以下のようになります。
うん、こんなものでしょうか。
左の検知数
と右の在室有無表示
の時間範囲の指定を変えたかったですが、それはKibanaの機能ではできませんでした。
検知数
と在室有無表示
のDashboardをそれぞれ作り、iframe
を取得し、自分で作成したHTMLページにそれぞれのiframe
を埋め込みばいけそうです。
今回はKibanaを利用しての画面表示までが目標でしたので、ここで記事を終了します。
総じての感想は、nodeを触ったことが無かったため、コーディングには苦労しましたが、AWS操作に関しては参考記事も豊富にあり、苦労しませんでした。
ほぼノーコーディングでここまでのことができるのはすごいですね。
ただAWSの謳う
AWS IoT を利用した場合 ~5 分```
は私には無理でした。。今後精進いたします。
それでは、しばらくこの形で運用し、AWS料金が算出できたらまた記事を書こうと思います。