Files
DD3-LoRa-Bridge-MultiSender/src/json_codec.cpp

95 lines
2.4 KiB
C++

#include "json_codec.h"
#include <ArduinoJson.h>
#include <limits.h>
#include <math.h>
static float round2(float value) {
if (isnan(value)) {
return value;
}
return roundf(value * 100.0f) / 100.0f;
}
static int32_t round_to_i32(float value) {
if (isnan(value)) {
return 0;
}
long rounded = lroundf(value);
if (rounded > INT32_MAX) {
return INT32_MAX;
}
if (rounded < INT32_MIN) {
return INT32_MIN;
}
return static_cast<int32_t>(rounded);
}
static const char *short_id_from_device_id(const char *device_id) {
if (!device_id) {
return "";
}
size_t len = strlen(device_id);
if (len >= 4) {
return device_id + (len - 4);
}
return device_id;
}
static void format_float_2(char *buf, size_t buf_len, float value) {
if (!buf || buf_len == 0) {
return;
}
if (isnan(value)) {
snprintf(buf, buf_len, "null");
return;
}
snprintf(buf, buf_len, "%.2f", round2(value));
}
static void set_int_or_null(JsonDocument &doc, const char *key, float value) {
if (!key || key[0] == '\0') {
return;
}
if (isnan(value)) {
doc[key] = nullptr;
return;
}
doc[key] = round_to_i32(value);
}
bool meterDataToJson(const MeterData &data, String &out_json) {
StaticJsonDocument<256> doc;
doc["id"] = short_id_from_device_id(data.device_id);
doc["ts"] = data.ts_utc;
char buf[16];
format_float_2(buf, sizeof(buf), data.energy_total_kwh);
doc["e_kwh"] = serialized(buf);
set_int_or_null(doc, "p_w", data.total_power_w);
set_int_or_null(doc, "p1_w", data.phase_power_w[0]);
set_int_or_null(doc, "p2_w", data.phase_power_w[1]);
set_int_or_null(doc, "p3_w", data.phase_power_w[2]);
format_float_2(buf, sizeof(buf), data.battery_voltage_v);
doc["bat_v"] = serialized(buf);
doc["bat_pct"] = data.battery_percent;
if (data.link_valid) {
doc["rssi"] = data.link_rssi_dbm;
doc["snr"] = data.link_snr_db;
}
if (data.err_meter_read > 0) {
doc["err_m"] = data.err_meter_read;
}
if (data.err_decode > 0) {
doc["err_d"] = data.err_decode;
}
if (data.err_lora_tx > 0) {
doc["err_tx"] = data.err_lora_tx;
}
doc["err_last"] = static_cast<uint8_t>(data.last_error);
doc["rx_reject"] = data.rx_reject_reason;
doc["rx_reject_text"] = rx_reject_reason_text(static_cast<RxRejectReason>(data.rx_reject_reason));
out_json = "";
size_t len = serializeJson(doc, out_json);
return len > 0 && len < 256;
}