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
This commit is contained in:
@@ -306,6 +306,7 @@ inline constexpr uint16_t EXPECTED_SENDER_IDS[NUM_SENDERS] = { 0xF19C };
|
|||||||
- Receiver keeps sending time sync every 60 seconds.
|
- 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`).
|
- 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.
|
- 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
|
## Build Environments
|
||||||
- `lilygo-t3-v1-6-1`: production build (debug on)
|
- `lilygo-t3-v1-6-1`: production build (debug on)
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ static bool g_time_synced = false;
|
|||||||
static bool g_tz_set = false;
|
static bool g_tz_set = false;
|
||||||
static bool g_rtc_present = false;
|
static bool g_rtc_present = false;
|
||||||
static uint32_t g_last_sync_utc = 0;
|
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) {
|
static void note_last_sync(uint32_t epoch) {
|
||||||
if (epoch == 0) {
|
if (epoch == 0) {
|
||||||
@@ -142,6 +144,16 @@ bool time_try_load_from_rtc() {
|
|||||||
}
|
}
|
||||||
uint32_t epoch = 0;
|
uint32_t epoch = 0;
|
||||||
if (!rtc_ds3231_read_epoch(epoch) || 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<unsigned long>(epoch), valid ? "accepted" : "rejected");
|
||||||
|
}
|
||||||
|
if (!valid) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
time_set_utc(epoch);
|
time_set_utc(epoch);
|
||||||
|
|||||||
Reference in New Issue
Block a user