Note that this report was generated by AI however it does describe a real problem I encountered myself.
Summary
On ESP32-based Room Servers without a battery-backed RTC chip (DS3231, RV3028, PCF8563, or RX8130CE), any reboot — including a deliberate reboot command — causes the clock to reset to the hardcoded default of 15 May 2024 20:50 UTC. The Room Server has no mechanism to recover the correct time after this happens, unlike the companion radio which has bootstrapRTCfromContacts().
The server silently runs with the wrong time until a human manually sends clock sync. During this period, post timestamps are wrong and push delivery may be affected via stale post_timestamp comparisons.
Root cause
ESP32RTCClock::begin() overwrites the time unconditionally on power-on reset:
```cpp
void begin() {
esp_reset_reason_t reason = esp_reset_reason();
if (reason == ESP_RST_POWERON) {
struct timeval tv;
tv.tv_sec = 1715770351; // 15 May 2024, 8:50pm
...
}
}
```
On many ESP32 variants, ESP.restart() (triggered by the reboot CLI command) reports as ESP_RST_POWERON rather than ESP_RST_SW, so the condition fires on every reboot.
When AutoDiscoverRTCClock finds no hardware RTC on the I2C bus, it falls through to this ESP32RTCClock fallback, which has no persistent state.
The Room Server's MyMesh::begin() does not call bootstrapRTCfromContacts() and has no other time recovery mechanism:
```cpp
void MyMesh::begin(FILESYSTEM *fs) {
mesh::Mesh::begin();
_fs = fs;
_cli.loadPrefs(_fs);
acl.load(_fs, self_id);
// ... no clock recovery
}
```
Impact
- Post timestamps are wrong. All posts stored while the clock is reset are stamped ~2 years in the past.
- Push delivery may break.
sync_since comparisons against post_timestamp can cause clients to miss posts or receive duplicates.
- Silent failure. There is no indication to users that the server clock is wrong. The server appears to function normally.
- Any reboot triggers it. OTA updates, config changes requiring reboot, watchdog resets, and manual
reboot commands all cause the issue.
Reproduction
- Deploy a Room Server on an ESP32 board with no external RTC chip.
- Sync the clock: send
clock sync from a companion with correct time.
- Verify: send
clock — shows correct date.
- Send
reboot.
- After reboot, send
clock — shows 05:57 - 16/5/2024 UTC (or similar, near the hardcoded default).
Suggested fixes
-
Persist last-known time to flash. Periodically (e.g., every 10–60 minutes, and on graceful reboot) write the current RTC value to a small file. On boot, if no hardware RTC is found, read this file and use it as the starting time instead of the 2024 default.
-
Add bootstrapRTCfromContacts() or equivalent to the Room Server. The Room Server stores client->last_activity (stamped with its own clock). On boot, the most recent last_activity across all ACL entries could be used similarly to how the companion uses lastmod.
-
Save time before reboot. The reboot and clkreboot CLI handlers could persist the current time before calling _board->reboot().
-
Fix the ESP32 reset-reason detection. For boards where ESP.restart() reports as ESP_RST_POWERON, avoid unconditionally overwriting the time — the ESP32's internal RTC peripheral actually survives a software restart on most variants if settimeofday is not called.
Affected devices
Any ESP32-based node running the Room Server (or Repeater) firmware without an external I2C RTC chip. Boards with a working DS3231, RV3028, PCF8563, or RX8130CE are not affected because the hardware RTC retains time across resets.
Related
- The companion radio partially mitigates this via bootstrapRTCfromContacts(), but the Room Server has no equivalent.
- The
clkreboot command intentionally resets the clock as a recovery mechanism for the forward-corruption bug; this is separate from the unintentional reset described here.
Note that this report was generated by AI however it does describe a real problem I encountered myself.
Summary
On ESP32-based Room Servers without a battery-backed RTC chip (DS3231, RV3028, PCF8563, or RX8130CE), any reboot — including a deliberate
rebootcommand — causes the clock to reset to the hardcoded default of 15 May 2024 20:50 UTC. The Room Server has no mechanism to recover the correct time after this happens, unlike the companion radio which has bootstrapRTCfromContacts().The server silently runs with the wrong time until a human manually sends
clock sync. During this period, post timestamps are wrong and push delivery may be affected via stalepost_timestampcomparisons.Root cause
ESP32RTCClock::begin() overwrites the time unconditionally on power-on reset:
On many ESP32 variants,
ESP.restart()(triggered by therebootCLI command) reports asESP_RST_POWERONrather thanESP_RST_SW, so the condition fires on every reboot.When
AutoDiscoverRTCClockfinds no hardware RTC on the I2C bus, it falls through to thisESP32RTCClockfallback, which has no persistent state.The Room Server's MyMesh::begin() does not call bootstrapRTCfromContacts() and has no other time recovery mechanism:
Impact
sync_sincecomparisons againstpost_timestampcan cause clients to miss posts or receive duplicates.rebootcommands all cause the issue.Reproduction
clock syncfrom a companion with correct time.clock— shows correct date.reboot.clock— shows05:57 - 16/5/2024 UTC(or similar, near the hardcoded default).Suggested fixes
Persist last-known time to flash. Periodically (e.g., every 10–60 minutes, and on graceful reboot) write the current RTC value to a small file. On boot, if no hardware RTC is found, read this file and use it as the starting time instead of the 2024 default.
Add bootstrapRTCfromContacts() or equivalent to the Room Server. The Room Server stores
client->last_activity(stamped with its own clock). On boot, the most recentlast_activityacross all ACL entries could be used similarly to how the companion useslastmod.Save time before reboot. The
rebootandclkrebootCLI handlers could persist the current time before calling_board->reboot().Fix the ESP32 reset-reason detection. For boards where
ESP.restart()reports asESP_RST_POWERON, avoid unconditionally overwriting the time — the ESP32's internal RTC peripheral actually survives a software restart on most variants ifsettimeofdayis not called.Affected devices
Any ESP32-based node running the Room Server (or Repeater) firmware without an external I2C RTC chip. Boards with a working DS3231, RV3028, PCF8563, or RX8130CE are not affected because the hardware RTC retains time across resets.
Related
clkrebootcommand intentionally resets the clock as a recovery mechanism for the forward-corruption bug; this is separate from the unintentional reset described here.