Add LoRa telemetry, fault counters, and time sync status

This commit is contained in:
2026-01-30 13:00:16 +01:00
parent 7e3b537e49
commit 8ba7675a1c
13 changed files with 437 additions and 21 deletions

View File

@@ -33,7 +33,7 @@ static void format_float_2(char *buf, size_t buf_len, float value) {
}
bool meterDataToJson(const MeterData &data, String &out_json) {
StaticJsonDocument<192> doc;
StaticJsonDocument<256> doc;
doc["id"] = short_id_from_device_id(data.device_id);
doc["ts"] = data.ts_utc;
char buf[16];
@@ -55,6 +55,23 @@ bool meterDataToJson(const MeterData &data, String &out_json) {
doc["v3_v"] = serialized(buf);
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;
}
if (data.last_error != FaultType::None) {
doc["err_last"] = static_cast<uint8_t>(data.last_error);
}
out_json = "";
size_t len = serializeJson(doc, out_json);
@@ -69,7 +86,7 @@ static float read_float_or_legacy(JsonDocument &doc, const char *key, const char
}
bool jsonToMeterData(const String &json, MeterData &data) {
StaticJsonDocument<192> doc;
StaticJsonDocument<256> doc;
DeserializationError err = deserializeJson(doc, json);
if (err) {
return false;
@@ -99,6 +116,13 @@ bool jsonToMeterData(const String &json, MeterData &data) {
data.battery_percent = doc["bat_pct"] | 0;
}
data.valid = true;
data.link_valid = false;
data.link_rssi_dbm = 0;
data.link_snr_db = NAN;
data.err_meter_read = doc["err_m"] | 0;
data.err_decode = doc["err_d"] | 0;
data.err_lora_tx = doc["err_tx"] | 0;
data.last_error = static_cast<FaultType>(doc["err_last"] | 0);
if (strlen(data.device_id) >= 8) {
const char *suffix = data.device_id + strlen(data.device_id) - 4;
@@ -108,7 +132,7 @@ bool jsonToMeterData(const String &json, MeterData &data) {
return true;
}
bool meterBatchToJson(const MeterData *samples, size_t count, String &out_json) {
bool meterBatchToJson(const MeterData *samples, size_t count, String &out_json, const FaultCounters *faults, FaultType last_error) {
if (!samples || count == 0) {
return false;
}
@@ -117,6 +141,17 @@ bool meterBatchToJson(const MeterData *samples, size_t count, String &out_json)
doc["id"] = short_id_from_device_id(samples[count - 1].device_id);
doc["bat_v"] = round2(samples[count - 1].battery_voltage_v);
doc["bat_pct"] = samples[count - 1].battery_percent;
if (faults) {
if (faults->meter_read_fail > 0) {
doc["err_m"] = faults->meter_read_fail;
}
if (faults->lora_tx_fail > 0) {
doc["err_tx"] = faults->lora_tx_fail;
}
}
if (last_error != FaultType::None) {
doc["err_last"] = static_cast<uint8_t>(last_error);
}
JsonArray arr = doc.createNestedArray("s");
for (size_t i = 0; i < count; ++i) {
JsonArray row = arr.createNestedArray();
@@ -157,6 +192,9 @@ bool jsonToMeterBatch(const String &json, MeterData *out_samples, size_t max_cou
const char *id = doc["id"] | "";
float bat_v = doc["bat_v"] | NAN;
uint8_t bat_pct = doc["bat_pct"] | 0;
uint32_t err_m = doc["err_m"] | 0;
uint32_t err_tx = doc["err_tx"] | 0;
FaultType last_error = static_cast<FaultType>(doc["err_last"] | 0);
size_t idx = 0;
for (JsonArray row : arr) {
@@ -187,6 +225,13 @@ bool jsonToMeterBatch(const String &json, MeterData *out_samples, size_t max_cou
} else {
data.battery_percent = bat_pct;
}
data.link_valid = false;
data.link_rssi_dbm = 0;
data.link_snr_db = NAN;
data.err_meter_read = err_m;
data.err_decode = 0;
data.err_lora_tx = err_tx;
data.last_error = last_error;
if (strlen(data.device_id) >= 8) {
const char *suffix = data.device_id + strlen(data.device_id) - 4;