From e0d35d49bcac8d749c247bdd5109fc4472190cb0 Mon Sep 17 00:00:00 2001 From: acidburns Date: Wed, 4 Feb 2026 00:31:10 +0100 Subject: [PATCH] Validate RTC epoch before setting time - Reject out-of-range DS3231 epochs and log accept/reject under SERIAL_DEBUG_MODE - Document RTC validation so LoRa TimeSync can recover --- README.md | 1 + src/time_manager.cpp | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/README.md b/README.md index dfc0a42..6007090 100644 --- a/README.md +++ b/README.md @@ -306,6 +306,7 @@ inline constexpr uint16_t EXPECTED_SENDER_IDS[NUM_SENDERS] = { 0xF19C }; - Receiver keeps sending time sync every 60 seconds. - If a sender’s timestamps drift from receiver time by more than `TIME_SYNC_DRIFT_THRESHOLD_SEC`, the receiver enters a burst mode (every `TIME_SYNC_BURST_INTERVAL_MS` for `TIME_SYNC_BURST_DURATION_MS`). - Sender raises a local `TimeSync` error if it has not received a time beacon for `TIME_SYNC_ERROR_TIMEOUT_MS` (default 2 days). This is shown on the sender OLED only and is not sent over LoRa. +- RTC loads are validated (reject out-of-range epochs) so LoRa TimeSync can recover if the RTC is wrong. ## Build Environments - `lilygo-t3-v1-6-1`: production build (debug on) diff --git a/src/time_manager.cpp b/src/time_manager.cpp index f7bf88c..91bcd6a 100644 --- a/src/time_manager.cpp +++ b/src/time_manager.cpp @@ -8,6 +8,8 @@ static bool g_time_synced = false; static bool g_tz_set = false; static bool g_rtc_present = false; static uint32_t g_last_sync_utc = 0; +static constexpr uint32_t kMinValidEpoch = 1672531200UL; // 2023-01-01 +static constexpr uint32_t kMaxValidEpoch = 4102444800UL; // 2100-01-01 static void note_last_sync(uint32_t epoch) { if (epoch == 0) { @@ -142,6 +144,16 @@ bool time_try_load_from_rtc() { } uint32_t epoch = 0; if (!rtc_ds3231_read_epoch(epoch) || epoch == 0) { + if (SERIAL_DEBUG_MODE) { + Serial.println("rtc: read failed"); + } + return false; + } + bool valid = epoch >= kMinValidEpoch && epoch <= kMaxValidEpoch; + if (SERIAL_DEBUG_MODE) { + Serial.printf("rtc: epoch=%lu %s\n", static_cast(epoch), valid ? "accepted" : "rejected"); + } + if (!valid) { return false; } time_set_utc(epoch);