Skip to content

Allow setting RTC clock backwards and fix elapsed-time underflow#1349

Open
weebl2000 wants to merge 1 commit intomeshcore-dev:devfrom
weebl2000:allow-older-time
Open

Allow setting RTC clock backwards and fix elapsed-time underflow#1349
weebl2000 wants to merge 1 commit intomeshcore-dev:devfrom
weebl2000:allow-older-time

Conversation

@weebl2000
Copy link
Contributor

@weebl2000 weebl2000 commented Jan 9, 2026

Build firmware: Build from this branch

Problem

The ESP32-S3 RTC drifts 5-10% during deep sleep. After a few days with powersaving ON, the clock can run hours ahead. Previously it was impossible to correct this — all set-time paths rejected timestamps older than the current time with "clock cannot go backwards".

Additionally, when the clock is corrected backwards (e.g. via GPS sync), stored timestamps appear to be in the future, causing unsigned subtraction underflow (wrapping to ~4 billion seconds / 136 years).

Changes

1. Remove forward-only clock restriction

All set-time paths now accept any timestamp:

  • CLI time <epoch> and clock sync commands (CommonCLI.cpp)
  • Companion radio CMD_SET_DEVICE_TIME (companion_radio/MyMesh.cpp)
  • simple_secure_chat setClock()

Only admins/owners can set the time, so replay risk is minimal.

2. Add safeElapsedSecs() helper

New inline function in ArduinoHelpers.h that clamps elapsed time to 0 when a stored timestamp is in the future (i.e. clock was corrected backwards). Applied to:

  • Neighbor "heard X ago" display in simple_repeater
  • UI "received X ago" display in companion_radio
  • TimeSeriesData age calculations in simple_sensor

3. Switch connection expiry to monotonic time

BaseChatMesh connection expiry now uses millis() instead of RTC timestamps, making it immune to clock adjustments from GPS, NTP, or manual sync. Field renamed from last_activity to last_activity_ms to reflect the semantic change.

This assumes light sleep mode where millis() continues to increment (deep sleep resets it, but BaseChatMesh is only used by companion_radio which uses light sleep).

Trade-offs

  • Removing the forward-only guard means a client with a wildly wrong clock could set the node's time to nonsense via clock sync. However, only authenticated admins/owners can issue these commands.
  • safeElapsedSecs() clamps to 0 ("just now") rather than preserving relative ordering — acceptable for display purposes.

@weebl2000 weebl2000 force-pushed the allow-older-time branch 2 times, most recently from 4d9e093 to 1cc133b Compare February 6, 2026 02:32
@weebl2000 weebl2000 changed the title Allow setting time in the past Allow setting RTC clock backwards and fix elapsed-time underflow Feb 6, 2026
Remove the "clock cannot go backwards" restriction from all set-time
paths (CLI `time`, `clock sync`, companion radio CMD_SET_DEVICE_TIME,
and simple_secure_chat). The ESP32-S3 RTC drifts 5-10% during deep
sleep, making backwards correction necessary after even a few days.

Add safeElapsedSecs() helper in ArduinoHelpers.h that clamps elapsed
time to 0 when a stored timestamp appears to be in the future after a
clock correction. Applied to:
- Neighbor "heard X ago" displays in simple_repeater
- UI time displays in companion_radio
- TimeSeriesData calculations in simple_sensor

Switch BaseChatMesh connection expiry from RTC timestamps to monotonic
millis(), making it immune to RTC adjustments from GPS, NTP, or manual
sync. Rename last_activity to last_activity_ms to reflect the change.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant