diff --git a/docs/engineering/hil-test-matrix.md b/docs/engineering/hil-test-matrix.md index 6deb04d..1ddb5e2 100644 --- a/docs/engineering/hil-test-matrix.md +++ b/docs/engineering/hil-test-matrix.md @@ -3,7 +3,7 @@ | Area | Stimulus | Required evidence | Expected result | |---|---|---|---| | Boot | Flash/start both boards | `boot`, `role`, periodic `health` from each | Exactly one sender and receiver; no reset loop; bounded heap/stack | -| Time | Sender receive window and receiver time-sync | sender request/completion, receiver transmit | Valid UTC completion; misses remain visible | +| Time | Sender receive window and receiver startup time-sync burst | sender request/completion, receiver startup transmit | Valid UTC completion during the 180 s baseline; misses remain visible | | Meter baseline | Real optical meter | `meter_frame`, `meter_sample` | Frame classification and seconds index when present; no secrets/values logged | | Batch | Normal 30 s batching | create, encode, every TX/RX chunk, complete, decode, ACK TX/RX | One batch ID correlates end to end | | Meter timeout | Partial start then >1.5 s pause | `classification=timeout`, health | No reset; next valid fixture recovers | diff --git a/src/main.cpp b/src/main.cpp index cad592e..b78b2fe 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -34,6 +34,7 @@ static SenderStatus g_sender_statuses[NUM_SENDERS]; static bool g_ap_mode = false; static WifiMqttConfig g_cfg; static uint32_t g_last_timesync_ms = 0; +static uint32_t g_receiver_startup_timesync_last_ms = 0; static constexpr uint32_t TIME_SYNC_OFFSET_MS = 15000; static uint32_t g_boot_ms = 0; static FaultCounters g_sender_faults = {}; @@ -1338,6 +1339,14 @@ static void receiver_loop() { uint32_t now_ms = millis(); if (!g_ap_mode) { bool burst_sent = false; + const char *burst_mode = "burst"; + if (time_is_synced() && now_ms - g_boot_ms < TIME_SYNC_BURST_DURATION_MS && + (g_receiver_startup_timesync_last_ms == 0 || + now_ms - g_receiver_startup_timesync_last_ms >= TIME_SYNC_BURST_INTERVAL_MS)) { + g_receiver_startup_timesync_last_ms = now_ms; + burst_sent = true; + burst_mode = "startup"; + } for (uint8_t i = 0; i < NUM_SENDERS; ++i) { TimeSyncBurstState &state = g_timesync_burst[i]; if (state.active) { @@ -1356,10 +1365,10 @@ static void receiver_loop() { display_set_last_error(g_receiver_last_error, g_receiver_last_error_utc, g_receiver_last_error_ms); } if (SERIAL_DEBUG_MODE) { - serial_debug_printf("timesync: tx burst"); + serial_debug_printf("timesync: tx %s", burst_mode); } - hil_trace_eventf("time_bootstrap", "\"stage\":\"transmit\",\"mode\":\"burst\",\"ok\":%s,\"utc\":%lu", - time_sent ? "true" : "false", static_cast(time_get_utc())); + hil_trace_eventf("time_bootstrap", "\"stage\":\"transmit\",\"mode\":\"%s\",\"ok\":%s,\"utc\":%lu", + burst_mode, time_sent ? "true" : "false", static_cast(time_get_utc())); g_last_timesync_ms = now_ms; } else if (now_ms - g_last_timesync_ms > interval_sec * 1000UL) { g_last_timesync_ms = now_ms;