IoT何をいまさら(111) Xiao ESP32C3、JSONオブジェクトをパブリッシュ

Joseph Halfmoon

前回Seeed社XiaoシリーズのRISC-VコアESP32C3搭載機で取得したアナログデータをNodeREDサーバのレベルゲージに表示。しかし不満もあり。機能追加のたびにMQTTブローカのトピックを追加、送るデータも文字列。この際「統一的に」JSONオブジェクトを送ることにしたいです。今回はその第一歩とな。

※「IoT何をいまさら」投稿順Indexはこちら

※XiaoESP32C3機のファームウエア開発には、バージョン2.0.3のArduino IDEを使わせていただいております。

XiaoESP32C3機からのJSONオブジェクトの送出

さてArduino開発環境には多数のライブラリが存在します。JSONオブジェクトを作成し、シリアライズ、デシリアライズできるライブラリも多数あるようです。

しかしま、旧パソコンのArduino IDE1.0環境でやっていたときにもJSONオブジェクト用のライブラリを使わせていただいておりました。その当時の記事が以下に。ターゲット機は同じESP32でもXtensaコア搭載のM5StickCでした。

IoT何をいまさら(75) ありがちなM5StickCからNode-REDに温度報告

今回は、新パソコンのArduino IDE2.0環境にそのとき使用したものと同じライブラリを導入させていただきます。ライブラリのホームページが以下に。なんだか以前より「充実」しているんでないかい?

ArduinoJson

Arduino IDE2.0のライブラリマネージャからインストールしているところが以下に。ArduinoJson

例によってソースコードのチョイ変

実験に使用したソースコードの全文は末尾に置きましたです。前回のソースのチョイ直しです。変更部分が以下に。

まず忘れちゃいけないヘッダファイルをインクルード

#include <ArduinoJson.h>

そのあと、JSONオブジェクトを構築するためのオブジェクトの確保、および作成したオブジェクトをシリアライズしてWiFi経由でMQTTするためのバッファの確保が以下に。

#define JSONBUFSIZE (400)
const int jsonCapacity = JSON_OBJECT_SIZE(3);
StaticJsonDocument<jsonCapacity> doc;
char serializedDoc[JSONBUFSIZE];

今回は、控えめに前回文字列に変換して送信していたボリュームデータの測定とパブリッシュを行う関数 reportAnalog()内で、JSONプロパティ adPer に数値データを載せるようにしてあります。直後にメモリ上のJSONオブジェクトをシリアライズしてWiFi経由でMQTTパブリッシュしてます。

JSON送信用に新たなMQTTトピックを作ってしまいましたが、他のトピックはおいおいJSONに取り込んで廃止していきたいと思います。

void reportAnalog() {
  int adval = analogRead(analogPin);
  int adPer = map(adval, 0, 4095, 0, 100);
  Serial.println(adval);
  doc["adPer"] = adPer;
  serializeJson(doc, serializedDoc);
  sendMessage(jsonTPC, (const char*)serializedDoc);
}
Node-REDサーバ側のJSON受け取りフロー(仮)

今回は、JSONオブジェクトとしてNode-RED側で受け取れていることを確認するだけであります。MQTT in ノードで、ESP32C3からのシリアライズされたJSONを受け取って、msg.payloadにはJSONオブジェクトとして載せてみると。結果はダイレクトにデバッグWindowで確認してみます。

Node-REDフローが以下に。

JSON_RECEIVE_FLOW0

MQTT in ノードの設定が以下に。出力のところ、JSONオブジェクトになっておりますよ。MQTT_IN_setting

Node-RED側での受信結果

デバッグウインドウで監視した msg.payloadの様子が以下に。ちゃんと object そしてプロパティ adPer に数値 67 が載ってます。

JSON_RECEIVE_Debug

単にJSON化しただけだけれども以降のデータのやりとりはカッコよくなるはず。ホントか?

IoT何をいまさら(110) Xiao ESP32C3、アナログ測定値でレベルゲージ表示 へ戻る

IoT何をいまさら(112) SAMD21版XiaoからNode-REDへJSON へ進む

今回使用したArduino .ino 形式ソース全文
// ESP32C3 MQTT Json test
#include <WiFi.h>
#include <ArduinoMqttClient.h>
#include <ArduinoJson.h>

int led = D0;
int analogPin = A1;
int adval = 0;
char *ssid = "Your SSID";
char *password = "Your Password";
const char broker[] = "Your broker address";
const int  brokerPort = 1883;
const char topic[] = "XiaoESP32C3/Status";
const char subtopic[] = "XiaoESP32C3/LED";
const char gaugeTPC[] = "XiaoESP32C3/GAUGE";
const char jsonTPC[] = "XiaoESP32C3/JSON";

#define JSONBUFSIZE (400)
const int jsonCapacity = JSON_OBJECT_SIZE(3);
StaticJsonDocument<jsonCapacity> doc;
char serializedDoc[JSONBUFSIZE];

WiFiClient wifiClient;
MqttClient mqttClient(wifiClient);

void sendMessage(const char* topic, const char* mes) {
  mqttClient.beginMessage(topic);
  mqttClient.print(mes);
  mqttClient.endMessage();
}

void reportAnalog() {
  int adval = analogRead(analogPin);
  int adPer = map(adval, 0, 4095, 0, 100);
  Serial.println(adval);
  doc["adPer"] = adPer;
  serializeJson(doc, serializedDoc);
  sendMessage(jsonTPC, (const char*)serializedDoc);
}

void setup() {
  pinMode(led, OUTPUT);
  digitalWrite(led, HIGH); 
  Serial.begin(9600);
  while (!Serial) {
    ;
  }
  
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
  }
  if (!mqttClient.connect(broker, brokerPort)) {
    while (1);
  };
  sendMessage(topic, "ESP32C3 waiting for message.");
  mqttClient.subscribe(subtopic);
}

void loop() {
  int messageSize = mqttClient.parseMessage();
  if (messageSize) {
    while (mqttClient.available()) {
      char mesC = (char)mqttClient.read(); 
      if ( mesC == '1') {      
        digitalWrite(led, HIGH); 
      } else if ( mesC == '0') {
        digitalWrite(led, LOW);
      }
    }
  }
  reportAnalog();
  delay(5000);
}