Node-REDの秘密(2) MQTT編 (センサデータ受信とWebGUI)


清水@ロボット部 (日本Androidの会 秋葉原支部)です。
ロボット部 第81回勉強会 2019/06/30 (日)で本資料の説明を予定しています。https://atnd.org/events/106619

ロボット部 Googleグループ
https://groups.google.com/forum/?hl=ja#!forum/robot-android-group-japan-akb


はじめに

Node-RED上の MQTTサーバ(MQTTブローカー) と ESP32 上の MQTTクライアント(MicroPython )を接続してみました。
MQTT (Message Queuing Telemetry Transport) は、TCP/IPによるPub/Sub型のメッセージキュープロトコルで、IoTでよく使われます。
Node-RED上の MQTTサーバはとても簡単に立上げることができ、実験等にお勧めです。

本資料のポイントは次の点です。

  • Node-RED上で MQTTサーバ(MQTTブローカー)が簡単に起動できる
  • Node-RED上で MQTTの送信と受信 (Publish と Subscribe)が簡単にできる
  • ESP32上の MicroPython と Node-RED で、MQTT接続ができる

ESP32上のセンサーから MQTT でデータを送信し、Node-RED で受信する簡単なアプリの制作を、GUIも含めて説明します。

Node-RED WebGUI

グラフ

つぎの画面は、温度、湿度、気圧、CO2濃度、バッテリ電圧、計測時間の6つのグラフを表示しています。
WebGUIは Node-RED で簡単に作成できます。
各グラフは複数のセンサー値を表示しています。最下段にグラフ表示のクリアボタンがあります。

最新データ

つぎの画面は、センサーの最新値を表示しています。
各値は、データ受信日時、受信データ「センサーID、温度、湿度、気圧、バッテリ電圧、(CO2濃度、)計測時間、状況コード、他」です。
一部のセンサーはCO2濃度も計測します。最下段に表示のクリアーボタンがあります。

受信履歴

つぎの画面は、センサーから受信したデータの履歴を表示しています。
最下段に表示のクリアーボタンがあります。「センサーID」を指定して、表示を絞ることもできます。

Node-RED フロー図

上から順につぎの機能を実装しています。

  • テスト用フロー センサーデータ送信(MQTT Publish)、最新データ取得(HttpRequest版、Curlコマンド版)
  • MQTTサーバ(MQTTブローカー)
  • センサーデータ受信(MQTT Subscribe)(グローバル変数への格納を含む)
  • 最新データ要求への応答(HTTP)
  • GUI 6つのグラフ、各センサー最新データ、データ受信履歴、クリアーボタン、センサー選択リスト
  • CSVファイル生成

MQTTサーバ(MQTTブローカー)作成手順

  • パレット「node-red-contrib-mqtt-broker」をNode-RED上にインストールします。
  • Node-RED上の「入力」でノード 「mosca」を、フローに配置します。ノード表示名は「Mosca MQTT broker」になります。
  • ノードのプロパティ「MQTT port」を設定します。  例:「1883」

MQTTメッセージ送信手順(Node-RED上)

  • Node-RED上の「出力」でノード「mqtt」を、フローに配置します。
  • ノードのプロパティ「サーバ」を設定します。  例:「localhost:1883」
  • ノードのプロパティ「トピック」を設定します。  例:「sensor」

MQTTメッセージ送信手順(ESP32上のMicroPython )

MQTTライブラリは、micropython/micropython-lib にある、simple.py を、「mqtt.py」にリーネムして使います。
https://github.com/micropython/micropython-lib/tree/master/umqtt.simple/umqtt

メインプログラムの例を次に示します。

main.py
from mqtt import MQTTClient
mqc1 = MQTTClient("mqc1","192.168.11.2",1883)
mqc1.connect()
mqc1.publish("sensor","I0303,28.44C,61.98%,1008.00hPa,3.22V,693ppm,1175ms,R0,V001")

MQTTメッセージ受信手順

  • Node-RED上の「入力」でノード「mqtt」を、フローに配置します。
  • ノードのプロパティ「サーバ」を設定します。  例:「localhost:1883」
  • ノードのプロパティ「トピック」を設定します。  例:「sensor」

MQTT最新メッセージ取得(http GET)手順

MQTTメッセージを受信したら、グローバル変数に上書き格納します。
最新メッセージとして、格納済みのグローバル変数の値を渡します。

サーバ側

  • Node-RED上の「入力」でノード「http」を、フローに配置します。
  • ノードのプロパティ「メソッド」を設定します。  例:「GET」
  • ノードのプロパティ「URL」を設定します。  例:「/getSensorValue」
  • Node-RED上の「出力」でノード「http response」を、フローに配置します。

クライアント側(ノード「http request」を使用する場合)

  • Node-RED上の「機能」でノード「http request」を、フローに配置します。
  • ノードのプロパティ「メソッド」を設定します。  例:「GET」
  • ノードのプロパティ「URL」を設定します。  例:「http://localhost:1881/getSensorValue」

クライアント側(curlコマンドを使用する場合)

  • Node-RED上の「その他」でノード「exec」を、フローに配置します。
  • ノードのプロパティ「コマンで」を設定します。  例:「curl http://localhost:1881/getSensorValue」

センサー値グラフ表示のポイント

  • 1つのグラフに複数センサーのデータを表示する場合は、msg.topic に、センサーIDをセットします。
  • グラフ表示をクリアーする場合は、空配列[] をmsg.payload で渡します

functionノードのプログラム例(Node-RED上)

saveSensorValue

saveSensorValue.js
let str = msg.payload;
let id = str.match(/I(\d*)/);

SensorValLatest = global.get("SensorValLatest");
if (SensorValLatest === undefined) { SensorValLatest = {}}

SensorValLatest[id[1]] = str;
global.set("SensorValLatest",SensorValLatest);
msg0 = {};
msg0.payload = id[1];
msg.topic = id[1];
return [ msg0, msg];

参考URL

1分でIoT環境を構築!Node-RED上でMQTTブローカを立ち上げる手順
https://qiita.com/zuhito/items/d8ac0f602e0f09b02eac

micropythonでmqtt - 寝台急行はまなす
http://ken5owata.hatenablog.com/entry/2017/12/05/024545

Node-RED紹介(インストールからWebGUI作成)
https://qiita.com/tshimizu8/items/f71c1a5209cb3a19ce51

LOLIN ESP32 OLED ボードの MicroPython で 温度、湿度、気圧の測定
https://qiita.com/tshimizu8/items/e64e1af656b3b00a92d9