document batching updates and restore bat_v in batches

This commit is contained in:
2026-02-01 20:59:45 +01:00
parent a0080b249d
commit 50436cd0bb
3 changed files with 27 additions and 11 deletions

View File

@@ -59,7 +59,7 @@ void sender_loop() {
read_battery(data); // VBAT + SoC
if (time_to_send_batch()) {
json = meterBatchToJson(samples, batch_id);
json = meterBatchToJson(samples, batch_id); // bat_v per batch, t_first/t_last included
compressed = compressBuffer(json);
lora_send(packet(MeterBatch, compressed));
}
@@ -92,7 +92,7 @@ bool lora_send(const LoraPacket &pkt); // add header + CRC16 and transmit
- Web UI:
- AP mode: status + WiFi/MQTT config.
- STA mode: status + per-sender pages.
- OLED cycles through receiver status and per-sender pages.
- OLED cycles through receiver status and per-sender pages (receiver OLED never sleeps).
**Receiver loop (pseudo-code)**:
```cpp
@@ -106,7 +106,7 @@ void receiver_loop() {
}
} else if (pkt.type == MeterBatch) {
json = reassemble_and_decompress_batch(pkt);
for (sample in jsonToMeterBatch(json)) {
for (sample in jsonToMeterBatch(json)) { // uses t_first/t_last for jittered timestamps
update_sender_status(sample);
mqtt_publish_state(sample);
}
@@ -176,7 +176,7 @@ Packet layout:
LoRa radio settings:
- Frequency: **433 MHz** or **868 MHz** (set by build env via `LORA_FREQUENCY_HZ`)
- SF12, BW 125 kHz, CR 4/5, CRC on, Sync Word 0x34
- SF10, BW 125 kHz, CR 4/5, CRC on, Sync Word 0x34
## Data Format
JSON payload (sender + MQTT):
@@ -203,6 +203,8 @@ MeterBatch JSON (compressed over LoRa) uses per-field arrays with integer units
"sender": "s01",
"batch_id": 1842,
"t0": 1738288000,
"t_first": 1738288000,
"t_last": 1738288030,
"dt_s": 1,
"n": 3,
"energy_wh": [123456700, 123456701, 123456701],
@@ -210,6 +212,7 @@ MeterBatch JSON (compressed over LoRa) uses per-field arrays with integer units
"p1_w": [480, 490, 500],
"p2_w": [450, 450, 450],
"p3_w": [0, 0, 0],
"bat_v": 3.92,
"meta": {
"rssi": -92,
"snr": 7.5,
@@ -221,6 +224,7 @@ MeterBatch JSON (compressed over LoRa) uses per-field arrays with integer units
Notes:
- `sender` maps to `EXPECTED_SENDER_IDS` order (`s01` = first sender).
- `meta` is injected by the receiver after batch reassembly.
- `bat_v` is a single batch-level value (percent is calculated locally).
## Device IDs
- Derived from WiFi STA MAC.
@@ -236,9 +240,7 @@ inline constexpr uint16_t EXPECTED_SENDER_IDS[NUM_SENDERS] = { 0xF19C };
## OLED Behavior
- Sender: OLED stays **ON for 10 seconds** on each wake, then powers down for sleep.
- Receiver: OLED follows the 10-minute auto-off behavior:
- GPIO14 HIGH: OLED forced ON.
- GPIO14 LOW: auto-off after 10 minutes.
- Receiver: OLED is always on (no auto-off).
- Pages rotate every 4s.
## Power & Battery
@@ -283,6 +285,10 @@ Key timing settings in `include/config.h`:
- `METER_SEND_INTERVAL_MS`
- `BATCH_ACK_TIMEOUT_MS`
- `BATCH_MAX_RETRIES`
- `BATCH_QUEUE_DEPTH`
- `BATCH_RETRY_POLICY` (keep or drop on retry exhaustion)
- `SERIAL_DEBUG_MODE` / `SERIAL_DEBUG_DUMP_JSON`
- `LORA_SEND_BYPASS` (debug only)
## Limits & Known Constraints
- **Compression**: uses lightweight RLE (good for JSON but not optimal).

View File

@@ -73,8 +73,8 @@ constexpr uint8_t BATCH_QUEUE_DEPTH = 10;
constexpr BatchRetryPolicy BATCH_RETRY_POLICY = BatchRetryPolicy::Keep;
constexpr uint32_t WATCHDOG_TIMEOUT_SEC = 120;
constexpr bool ENABLE_HA_DISCOVERY = true;
constexpr bool SERIAL_DEBUG_MODE = true;
constexpr bool SERIAL_DEBUG_DUMP_JSON = true;
constexpr bool SERIAL_DEBUG_MODE = false;
constexpr bool SERIAL_DEBUG_DUMP_JSON = false;
constexpr bool LORA_SEND_BYPASS = false;
constexpr uint8_t NUM_SENDERS = 1;

View File

@@ -199,6 +199,11 @@ bool meterBatchToJson(const MeterData *samples, size_t count, uint16_t batch_id,
if (last_error != FaultType::None) {
doc["err_last"] = static_cast<uint8_t>(last_error);
}
if (!isnan(samples[count - 1].battery_voltage_v)) {
char bat_buf[16];
format_float_2(bat_buf, sizeof(bat_buf), samples[count - 1].battery_voltage_v);
doc["bat_v"] = serialized(bat_buf);
}
JsonArray energy = doc.createNestedArray("energy_wh");
JsonArray p_w = doc.createNestedArray("p_w");
@@ -235,6 +240,7 @@ bool jsonToMeterBatch(const String &json, MeterData *out_samples, size_t max_cou
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);
float bat_v = doc["bat_v"] | NAN;
if (!doc["schema"].isNull()) {
if ((doc["schema"] | 0) != 1) {
@@ -284,8 +290,12 @@ bool jsonToMeterBatch(const String &json, MeterData *out_samples, size_t max_cou
data.phase_power_w[0] = static_cast<float>(p1_w[idx] | 0);
data.phase_power_w[1] = static_cast<float>(p2_w[idx] | 0);
data.phase_power_w[2] = static_cast<float>(p3_w[idx] | 0);
data.battery_voltage_v = NAN;
data.battery_percent = 0;
data.battery_voltage_v = bat_v;
if (!isnan(bat_v)) {
data.battery_percent = battery_percent_from_voltage(bat_v);
} else {
data.battery_percent = 0;
}
data.valid = true;
data.link_valid = false;
data.link_rssi_dbm = 0;