diff --git a/README.md b/README.md index c9b5b8c..8b6b0b1 100644 --- a/README.md +++ b/README.md @@ -85,11 +85,13 @@ Sender builds sparse 30-slot windows and sends every `METER_SEND_INTERVAL_MS` (` For decoded `BatchUp`: 1. Reassemble and decode. -2. Send `AckDown` immediately. -3. Track duplicates per configured sender (`EXPECTED_SENDER_IDS`). -4. If duplicate: update duplicate counters/time, skip data write/publish. -5. If `n==0`: sync request path only. -6. Else reconstruct each sample timestamp from `t_last + present_mask`, then: +2. Validate sender identity (`EXPECTED_SENDER_IDS` and payload sender ID mapping). +3. Reject unknown/mismatched senders before ACK and before SD/MQTT/web updates. +4. Send `AckDown` promptly for accepted senders. +5. Track duplicates per configured sender. +6. If duplicate: update duplicate counters/time, skip data write/publish. +7. If `n==0`: sync request path only. +8. Else reconstruct each sample timestamp from `t_last + present_mask`, then: - append to SD CSV - publish MQTT state - update web status and last batch table @@ -113,25 +115,33 @@ State JSON (`src/json_codec.cpp`) includes: Home Assistant discovery: - enabled by `ENABLE_HA_DISCOVERY=true` - publishes to `homeassistant/sensor///config` +- `unique_id` format is `_` (example: `dd3-F19C_energy`) +- device metadata: + - `identifiers: [""]` + - `name: ""` + - `model: "DD3-LoRa-Bridge"` + - `manufacturer: "AcidBurns"` ## Web UI, Wi-Fi, SD - Wi-Fi/MQTT/NTP/web-auth config is stored in Preferences. - AP fallback SSID prefix: `DD3-Bridge-`. - Default web credentials: `admin/admin`. -- AP auth requirement is controlled by `WEB_AUTH_REQUIRE_AP` (default `false`). +- AP auth requirement is controlled by `WEB_AUTH_REQUIRE_AP` (default `true`). - STA auth requirement is controlled by `WEB_AUTH_REQUIRE_STA` (default `true`). Web timestamp display: - human-facing timestamps show `epoch (HH:MM:SS TZ)` in local configured timezone. SD CSV logging (`src/sd_logger.cpp`): -- header: `ts_utc,ts_hms_utc,p_w,p1_w,p2_w,p3_w,e_kwh,bat_v,bat_pct,rssi,snr,err_m,err_d,err_tx,err_last` -- `ts_hms_utc` is UTC `HH:MM:SS` +- header: `ts_utc,ts_hms_local,p_w,p1_w,p2_w,p3_w,e_kwh,bat_v,bat_pct,rssi,snr,err_m,err_d,err_tx,err_last` +- `ts_hms_local` is local `HH:MM:SS` derived from `TIMEZONE_TZ` History parser (`src/web_server.cpp`): -- expects the current CSV layout above -- legacy CSV layouts are not parsed (no backward compatibility) +- accepts both: + - current layout (`ts_utc,ts_hms_local,p_w,...`) + - legacy layout (`ts_utc,p_w,...`) +- requires full numeric parse for `ts_utc` and `p_w` (rejects trailing junk) OLED duplicate display: - receiver sender-pages show duplicate rate as `pct (absolute)` and last duplicate as `HH:MM`. diff --git a/Requirements.md b/Requirements.md index 221cabb..e52db15 100644 --- a/Requirements.md +++ b/Requirements.md @@ -34,15 +34,19 @@ Function names below are C++ references. Rust naming/layout may differ, but the - sync-request cadence 15 s while unsynced. - Receiver behavior: - decode/reconstruct sparse timestamps. - - ACK each decoded batch promptly. + - ACK accepted batches promptly. + - reject unknown/mismatched sender identities before ACK and before SD/MQTT/web updates. - update MQTT, web status, SD logging. - Persistence: - Wi-Fi/MQTT/NTP/web credentials in Preferences namespace `dd3cfg`. +- Web auth defaults: + - `WEB_AUTH_REQUIRE_STA=true` + - `WEB_AUTH_REQUIRE_AP=true` - Web and display time rendering: - local timezone from `TIMEZONE_TZ`. - SD logging: - - CSV columns include both `ts_utc` and `ts_hms_utc`. - - history parser expects this current layout. + - CSV columns include both `ts_utc` and `ts_hms_local`. + - history parser supports both current (`ts_utc,ts_hms_local,p_w,...`) and legacy (`ts_utc,p_w,...`) layouts. ## 3. Protocol and Data Contracts @@ -58,7 +62,14 @@ Function names below are C++ references. Rust naming/layout may differ, but the - Timestamp constraints: - receiver rejects decoded data whose timestamps are below `MIN_ACCEPTED_EPOCH_UTC` - CSV header (current required layout): - - `ts_utc,ts_hms_utc,p_w,p1_w,p2_w,p3_w,e_kwh,bat_v,bat_pct,rssi,snr,err_m,err_d,err_tx,err_last` + - `ts_utc,ts_hms_local,p_w,p1_w,p2_w,p3_w,e_kwh,bat_v,bat_pct,rssi,snr,err_m,err_d,err_tx,err_last` +- Home Assistant discovery contract: + - topic: `homeassistant/sensor///config` + - `unique_id`: `_` + - `device.identifiers`: `[""]` + - `device.name`: `` + - `device.model`: `DD3-LoRa-Bridge` + - `device.manufacturer`: `AcidBurns` ## 4. Module and Function Requirements @@ -126,8 +137,9 @@ Function names below are C++ references. Rust naming/layout may differ, but the - configure NTP servers and timezone env. - `uint32_t time_get_utc()` - return epoch or `0` when not plausible. + - updates "clock plausible" state independently from sync state. - `bool time_is_synced()` - - sync status helper. + - true only after explicit sync signals (NTP callback/status or trusted `time_set_utc`). - `void time_set_utc(uint32_t)` - set system time and sync flags. - `void time_get_local_hhmm(char*, size_t)` @@ -136,6 +148,8 @@ Function names below are C++ references. Rust naming/layout may differ, but the - `uint32_t time_get_last_sync_age_sec()` - Internal behavior-critical helpers: - `note_last_sync` + - `mark_synced` + - `ntp_sync_notification_cb` - `ensure_timezone_set` ## `src/lora_transport.cpp` @@ -202,12 +216,14 @@ Function names below are C++ references. Rust naming/layout may differ, but the - `fault_text` - `mqtt_connect` - `publish_discovery_sensor` + - discovery payload uses canonical device identity fields and `manufacturer=AcidBurns` ## `src/wifi_manager.cpp` - `void wifi_manager_init()` - `bool wifi_load_config(WifiMqttConfig&)` - `bool wifi_save_config(const WifiMqttConfig&)` + - returns `false` when any Preferences write/verify fails. - `bool wifi_connect_sta(const WifiMqttConfig&, uint32_t timeout_ms)` - `void wifi_start_ap(const char*, const char*)` - `bool wifi_is_connected()` @@ -223,7 +239,7 @@ Function names below are C++ references. Rust naming/layout may differ, but the - `fault_text` - `ensure_dir` - `format_date_utc` - - `format_hms_utc` + - `format_hms_local` ## `src/display_ui.cpp` @@ -395,6 +411,7 @@ These functions define end-to-end firmware behavior and must have equivalents: - bootstrap guardrail, retry counts, schedule intervals, min accepted epoch. - Preserve CSV output layout exactly: - consumers (history parser and external tooling) depend on it. + - preserve reader compatibility for both current and legacy layouts. - Preserve enum meanings: - `FaultType`, `RxRejectReason`, `LoraMsgKind`. @@ -415,5 +432,5 @@ Suggested Rust primitives: - Duplicate batch handling updates counters and suppresses duplicate publish/log. - Web UI shows `epoch (HH:MM:SS TZ)` local time. - SD CSV header/fields match expected order. -- History endpoint reads only current CSV layout successfully. +- History endpoint reads current and legacy CSV layouts successfully. - MQTT state/fault payload fields match existing names and semantics.