#include <ArduinoJson.h>
#include <TimeLib.h>
// Root document for JSON
// Variable name is stored at the root level. Cannot start with underscore (_).
// `data` subfield stores the actual data
// `ri` subfield stores the refresh interval
// `lr` subfield stores the last refresh timestamp if refresh interval is set
// `d` subfield indicates whether the data is dirty and needs to be flushed
DynamicJsonDocument root(128);
// Add a variable to root ot type int.
// @var: the name of the variable (document)
// @key: the key / name
// @val: the initial value
// @refresh_interval: the frequency, in sec, to force update the value even if value is unchanged
void addValueInt(const String& var, const String& key, const int val, const long refresh_interval = 0) {
JsonObject doc = root.createNestedObject(var);
JsonObject data = doc.createNestedObject("data");
data[key] = val;
doc["ri"] = refresh_interval;
if(refresh_interval) {
doc["lr"] = now();
}
doc["d"] = 1;
}
void updateValueInt(const String& var, const String& key, const int val) {
Serial.println("2.1");
Serial.flush();
JsonObject doc = root[var];
Serial.println("2.2");
JsonObject data = doc["data"];
Serial.println("2.3");
// long t = now();
if(data[key] != val) {
// data["ts"] = t;
Serial.println("2.4");
data[key] = val;
if(doc["ri"]) {
doc["lr"] = now();
}
doc["d"] = 1;
}
Serial.println("2.5");
/* else {
long refresh_interval = doc["ri"];
if (refresh_interval && t >= (long)data["ts"] + refresh_interval) {
data["ts"] = t;
data[key] = val;
doc["d"] = 1;
}
}*/
}
String serializeVar(const String& var, bool add_timestamp = false, bool mark_flushed = false) {
String s;
if(add_timestamp) {
JsonObject data = root[var]["data"];
DynamicJsonDocument d(data.memoryUsage() + 8); // Timestamp occupies 8 spaces.
d = data;
d["ts"] = now();
serializeJson(d, s);
} else {
serializeJson(root[var]["data"], s);
}
if(mark_flushed) {
root[var]["d"] = 0;
}
return s;
}
String poll() {
JsonObject root_ = root.as<JsonObject>(); // Iterator is only defined for JsonObject & Array.
for (JsonPair kv : root_) {
String key = String(kv.key().c_str());
JsonObject doc = root[key];
// Check if refresh is due.
bool update = false;
if(doc["d"]) {
update = true;
} else if (doc["ri"] && (now() >= (long) doc["ri"] + (long) doc["lr"])) {
update = true;
doc["lr"] = now();
}
if(update) {
Serial.println("Send " + key + "=" + serializeVar(key, true, true));
}
}
}
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
while(!Serial);
long t = 1678528333; // Epoch for Mar 11 3:52AM CT
// May be optional depending on WifiNINA implementation.
setTime(t);
Serial.println(now());
// Serial.println(year());
// Serial.println(month());
// Serial.println(day());
// Serial.println(hour());
// Serial.println(minute());
Serial.println(root.memoryUsage());
addValueInt("ktc1", "temp", 1234, 2);
Serial.println(root.memoryUsage());
// serializeJson(root, Serial);
// Serial.println();
poll();
// String data;
// serializeJson(doc, data);
// Serial.println(data);
delay(3000);
updateValueInt("ktc1", "temp", 2345);
// serializeJson(root, Serial);
// Serial.println();
poll();
delay(3000);
Serial.println("1");
// serializeJson(root, Serial);
// Serial.println();
Serial.println("2");
updateValueInt("ktc1", "temp", 2345);
Serial.println("3");
serializeJson(root, Serial);
Serial.println();
Serial.println("4");
poll();
serializeJson(root, Serial);
Serial.println();
Serial.println("5");
/*
JsonObject root_ = root.as<JsonObject>(); // Iterator is only defined for JsonObject & Array.
for (JsonPair kv : root_) {
String key = String(kv.key().c_str());
Serial.println(key + "=" + serializeVar(key, false, true));
}
serializeJson(root, Serial);
Serial.println();
Serial.println(root.memoryUsage());
*/
}
void loop() {
// put your main code here, to run repeatedly:
}