Hey folks, I have a project where I read a qwiic sensor from an ESP32, build and serialize a JSON object and publish to an MQTT broker.
I have it 99% working, but with one remaining change that I can't quite wrap my head around. A best practice when working with MQTT is to 'report by exception', or only publish changes that are different from the last transmitted value. I've read the StateChangeDetection
sketch and guide, however I can't quite figure out how to implement that with a JSON object and I find the ArduinoJSON documentation quite obtuse and jargon-y.
#include <Wire.h>
#include "person_sensor.h"
#include <ArduinoJson.h>
#include "EspMQTTClient.h"
EspMQTTClient client(
"WIFI_SSID",
"WIFI_KEY",
"BROKER_IP", // MQTT Broker server ip
"CLIENT_ID", // Client name that uniquely identify your device
1883 // The MQTT port, default to 1883. this line can be omitted
);
const int32_t SAMPLE_DELAY_MS = 1000;
StaticJsonDocument<256> doc;
void setup() {
Wire.begin();
Serial.begin(9600);
client.enableLastWillMessage("esp32/state", "offline", true);
}
void onConnectionEstablished(){
client.publish("esp32/state", "online", true);
}
void loop() {
client.loop();
person_sensor_results_t results = {};
JsonObject object = doc.to<JsonObject>();
char buffer[256];
if (!person_sensor_read(&results)) {
Serial.println("No person sensor results found on the i2c bus");
delay(SAMPLE_DELAY_MS);
return;
}
Serial.println("********************");
object["faces"] = results.num_faces;
for (int i = 0; i < results.num_faces; ++i) {
const person_sensor_face_t* face = &results.faces[i];
JsonObject FACE = object.createNestedObject("Face" + String(i));
FACE["confidence"] = face->box_confidence;
FACE["left"] = face->box_left;
FACE["top"] = face->box_top;
FACE["right"] = face->box_right;
FACE["bottom"] = face->box_bottom;
FACE["facing"] = face->is_facing;
}
serializeJsonPretty(doc, buffer);
client.publish("esp32/faces", buffer, true);
serializeJsonPretty(object, Serial);
Serial.println("");
Serial.println("********************");
delay(SAMPLE_DELAY_MS);
}
I know I need to store a new variable at the end of my loop containing my JSON object, call it previousPayload
and then compare previousPayload
with the outgoing payload, but I can't figure out how to do that.
Many examples seem to declare the currentState
and previousState
variables outside of the loop, but when I did that, I ended up with stickiness, where old nested objects weren't correctly being cleared out.
I'd love some help from you brilliant people.