From 0a2e4e5a6852bff59ca4c3bc643a9f1376965533 Mon Sep 17 00:00:00 2001 From: acidburns Date: Fri, 13 Feb 2026 23:54:03 +0100 Subject: [PATCH] docs: update README to current lora-refactor state --- README.md | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 9586a76..7a765d7 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,8 @@ Firmware for LilyGO T3 v1.6.1 (`ESP32 + SX1276 + SSD1306`) that runs as either: - LoRa link uses explicit CRC16 frame protection in firmware (`src/lora_transport.cpp`). - Sender batches up to `30` samples and retries on missing ACK (`BATCH_MAX_RETRIES=2`, retry policy `Keep`). - Sender meter parsing is decoupled from LoRa ACK waits using a dedicated FreeRTOS reader task + queue (`src/main.cpp`). +- Batch payload codec is schema v3 and uses a sparse `present_mask` over a 30-second window (no schema v2 compatibility). +- Sender derives epoch timestamps from meter Sekundenindex (`0-0:96.8.0*255`) using an epoch anchor when time is synced. - Receiver uses STA mode when config is valid, otherwise AP fallback with web config. - No debug auto-reboot timer is active in normal firmware loops. @@ -29,11 +31,14 @@ Transport is chunked (`batch_id`, `chunk_index`, `chunk_count`, `total_len`) and Payload codec (`src/payload_codec.cpp`) currently uses: - `kMagic=0xDDB3` -- `kSchema=2` -- metadata: sender, batch, timestamp, interval, battery, fault counters +- `kSchema=3` +- metadata: sender, batch, `t_last`, `present_mask`, battery, fault counters - data arrays: `energy_wh[]`, `p1_w[]`, `p2_w[]`, `p3_w[]` -`n == 0` is valid and used for sync request packets. +`present_mask` is a 30-bit second map in the `[t_last-29, t_last]` window. +Only set bits carry samples, so missing seconds are explicitly represented. + +`n == 0` is valid for sync request packets (`present_mask == 0`). ### `AckDown` (7 bytes) @@ -66,14 +71,21 @@ Implemented in `src/meter_driver.cpp` + sender loop in `src/main.cpp`: - UART: `Serial2`, RX pin `GPIO34` (`PIN_METER_RX`), `9600 7E1` - ESP32 RX buffer is enlarged to `8192` bytes to survive long LoRa blocking sections. -- Frame detection: starts at `'/'`, ends at `'!'`, timeout protection included (`METER_FRAME_TIMEOUT_MS=20000`). +- Frame detection: starts at `'/'`, ends at `'!'`, timeout protection included (`METER_FRAME_TIMEOUT_MS=3000`). - Parsing runs in a dedicated sender task and is handed to the main sender loop via queue. - Parsed OBIS values: + - `0-0:96.8.0*255` (meter Sekundenindex, 4-byte hex) - `1-0:1.8.0` (total energy) - `1-0:16.7.0` (total power) - `1-0:36.7.0`, `56.7.0`, `76.7.0` (phase powers) - `1-0:1.8.0*Wh` is automatically scaled to kWh +Timestamping/validation on sender: +- Anchor when time is valid: `epoch_offset = epoch_now - meter_seconds`. +- Derived sample time: `ts_utc = meter_seconds + epoch_offset`. +- Meter-time checks: monotonicity and `delta_meter_seconds` vs elapsed wall time (with tolerance) plus anchor drift checks. +- On detected jump/drift, sender records meter fault and resulting timestamp discontinuities propagate through `present_mask` to receiver. + Sender samples every second and transmits batches every 30 seconds. ## Receiver Behavior @@ -82,8 +94,9 @@ For valid `BatchUp` decode: 1. Reassemble chunks and decode payload. 2. Send `AckDown` immediately. 3. Drop duplicate batches per sender (`batch_id` tracking). -4. If `n==0`: treat as sync request only. -5. Else convert samples, log to SD, update web UI, publish MQTT. +4. Track duplicate stats per sender: absolute duplicates, total received, duplicate percentage, last duplicate timestamp. +5. If `n==0`: treat as sync request only. +6. Else reconstruct timestamps from `t_last` + `present_mask`, preserving skipped seconds, then log to SD, update web UI, publish MQTT. ## MQTT Topics and Payloads @@ -109,6 +122,8 @@ Home Assistant discovery is enabled (`ENABLE_HA_DISCOVERY=true`) and publishes c - AP fallback SSID prefix: `DD3-Bridge-`. - Default web credentials: `admin/admin`. - SD logging enabled (`ENABLE_SD_LOGGING=true`). +- Sender-specific web status includes duplicate-batch counters and the last duplicate time. +- Sender-specific OLED page shows duplicate rate as `pct (absolute)` and last duplicate as `HH:MM`. ## Build Environments