はじめに
今回は「EnOcean IoTマルチセンサー EMSIJ」からデータを取得させているNode-REDの作成済みのフローの解析・解説と、そこから取得したデータをInfluxDBに格納後、Grafanaで可視化させる方法を紹介する。
使用デバイス
・EnOcean IoTマルチセンサーEMSIJ

製品情報:https://www.enocean-alliance.org/ja/product/emsij-iot-multisensor-928-mhz/
当社商品紹介サイト:https://smartlight.co.jp/product/enocean-iot-multi-sensor-emsij/
EMSIJはEnOcean(928MHz)無線規格に基づいて通信する太陽電池発電による無線IoTセンサー。主なアプリケーションは、「温度、湿度、照度、加速度/姿勢の測定」のための壁掛け型または機器取り付け型のセンサー。iOSやAndroid用のNFCアプリEnOceanToolで設定をすることが可能。
・EnOcean USBゲートウェイ USB400J

製品情報:https://www.switch-science.com/products/1845
USB400Jは、EnOceanの無線通信をPCやゲートウェイに簡単に接続するためのUSBデバイスである。このデバイスを使用することで、EnOcean対応のセンサーやスイッチからのデータを受信し、それをPCや他のデバイスに転送することができる。
準備
① セットアップ
Node-RED、InfluxDB、Grafanaのセットアップと起動に関しては過去のブログを参照

➁ USBドングル挿入
「EnOcean IoTマルチセンサーEMSIJ」センサーを使用するために、PCにUSBドングルを挿入する。

フロー解説

① 「シリアル」ノード
・EnOceanデバイスからのシリアルデータをUSB400Jモジュールから受信するために使用される
➁「Function」ノード(変換用)
・このノードの目的は、受信した複雑なバイナリデータを人間やシステムが扱いやすい形式に変換すること。これにより、次のノードが必要な情報に簡単にアクセス可能となる。
// データそのもの
var buf = msg.payload;
// データのコピー(検証用)
var rawData = buf.slice(0, buf.length);
// 取り出しやすいようにhex変換したもの
var rawByte = buf.toString("hex");
// ESP3仕様のdataLengthを拾う
var dataLength = 255 * buf + buf;
// ESP3仕様のoptionalLengthを拾う
var optionalLength = buf;
// packetType
var packetType = buf;
// headerCRC
var headerCRC = buf[5];
// dataLengthに基づいたデータ部分の切り出し
var rawDataByte = buf.slice(7, 7 + dataLength + 2);
var id = rawDataByte.slice(0, 4).toString("hex");
// payloadに格納
msg.payload = {
rawData: rawData,
rawByte: rawByte,
dataLength: dataLength,
optionalLength: optionalLength,
packetType: packetType,
headerCRC: headerCRC,
rawDataByte: rawDataByte,
ID: id
}
return msg;
➂ 「Switch」ノード
・受信したメッセージのIDに基づいてメッセージを異なる出力ポートに振り分ける役割を果たす。具体的には、メッセージのIDが特定の値に一致するかどうかをチェックし、一致する場合は対応する出力ポートにメッセージを送る。

➃ 「Function」ノード(解析用)
・センサーから受信したデータを解析し、各種センサー値(温度、磁力、照度、湿度)を抽出してメッセージに格納する。また、グローバル変数を使って照度の最大値と最小値を追跡する。
const rawData = msg.payload.rawDataByte;
// Extract basic information
msg.id = rawData.slice(0, 4).toString('hex');
msg.dbm = rawData[15] * -1;
msg.stm550count = 1;
msg.type = 'STM550';
// Extract data bytes
const d0 = 4;
const data = Array.from({ length: 9 }, (_, i) => rawData[d0 + i].toString(2).padStart(8, '0'));
msg.data = {
data_8: data[0],
data_7: data,
data_6: data,
data_5: data,
data_4: data,
data_3: data[5],
data_2: data[6],
data_1: data[7],
data_0: data[8]
};
// Calculate temperature
const temp = data[0] + data.slice(0, 2);
msg.temperature = Math.round((parseInt(temp, 2) / 10 - 40) * 100) / 100;
// Calculate magnet
msg.magnet = parseInt(data[8].slice(3, 4), 2);
// Calculate illumination
const illumination = data.slice(2) + data + data.slice(0, 3);
msg.illumination = parseInt(illumination, 2);
const IllValue = msg.illumination;
let IllmaxValue = global.get('maxIll2') || 0;
let IllminValue = global.get('minIll2') || 1000;
if (IllmaxValue < IllValue) {
IllmaxValue = IllValue;
global.set('maxIll2', IllmaxValue);
}
if (IllminValue > IllValue) {
IllminValue = IllValue;
global.set('minIll2', IllminValue);
}
global.set('Ill', IllValue);
// Calculate humidity
const humidity = data.slice(2, 6) + data.slice(0, 2);
msg.humidity = Math.round(parseInt(humidity, 2) * 20) / 10;
// Aggregate data
msg.payload = {
id: msg.id,
dbm: msg.dbm,
stm550count: msg.stm550count,
type: msg.type,
temperature: msg.temperature,
magnet: msg.magnet,
illumination: msg.illumination,
humidity: msg.humidity,
time: Date.now()
};
return msg;
➄ 「MQTTブローカー」ノード
・指定されたMQTTブローカーに対して安全にデータを送信するように構成されている。これにより、解析されたEnOceanデータがリアルタイムで他のシステムやデバイスに配信される。
➄ 「デバッグ」ノード
・センサーのデータを正常に取得できているか確認するために使用

・以下の内容が取得、デバッグで表示される
1. dbm = 信号強度(値が低いほど信号が弱い)
2. temperature = 温度
3. magnet = 磁力
4. illumination = 照度(ルーメン(照度の値))
5. humidity = 湿度(%)
6. time = データが記録された時間
InfluxDBでデータを格納
① Node-REDのフロー変更
「MQTT-OUT」ノード →「Influxdb out」ノード

➁ 「Influxdb out」ノード を編集(設定した内容を入力)
1. Organization ・・・ 組織名
2. Bucket ・・・ バケット名
3. Measurement ・・・ 自身で指定
4. URL ・・・ http://localhost:8086
5. Token ・・・APIトークン

➂ InfluxDBのDataExplorerでデータの確認
「フィールド」を変更することで確認したいデータ(照度・温度・湿度等)を確認することが可能

Grafanaでデータの可視化
① 左上のメニューから「Connections」→「Data Sources」→「influxdb」
バケットやAPIトークンを変更した場合はここで編集する

➁ 左上のメニューから「Dashboards」→「+ Create Dashboard」 → 「ADD Visualization」 → 「influxdb」を選択
➂ 下記のコードをクエリに入力 → 「Apply」
from(bucket: "mqtt")
|> range(start: -30d) // 過去30日のデータを取得
|> filter(fn: (r) => r._measurement == "mqtt_influx")
|> filter(fn: (r) => r._field == "temperature" or r._field == "illumination" or r._field == "humidity" or r._field == "dbm" or r._field == "magnet")
|> limit(n: 100) // 直近の100件を表示

→ このようなグラフが表示されれば可視化成功