# Clock Bug Fix, NTP Auto-Sync, and Sleep Persistence **Date**: 2026-02-17 ## Task Description Three clock-related improvements: 1. Fix SetTimeActivity immediately dismissing when opened 2. Add automatic NTP time sync on WiFi connection 3. Verify time persistence across deep sleep modes ## Changes Made ### 1. Bug Fix: SetTimeActivity immediate dismiss (`src/activities/settings/SetTimeActivity.cpp`) - **Root cause**: `loop()` used `wasReleased()` for Back, Confirm, Left, and Right buttons. The parent `SettingsActivity` enters this subactivity on a `wasPressed()` event, so the button release from the original press immediately triggered the exit path. - **Fix**: Changed all four `wasReleased()` calls to `wasPressed()`, matching the pattern used by all other subactivities (e.g., `LanguageSelectActivity`). ### 2. Shared NTP Utility (`src/util/TimeSync.h`, `src/util/TimeSync.cpp`) - Created `TimeSync` namespace with three functions: - `startNtpSync()` -- non-blocking: configures and starts SNTP service - `waitForNtpSync(int timeoutMs = 5000)` -- blocking: starts SNTP and polls until sync completes or timeout - `stopNtpSync()` -- stops the SNTP service ### 3. NTP on WiFi Connection (`src/activities/network/WifiSelectionActivity.cpp`) - Added `#include "util/TimeSync.h"` and call to `TimeSync::startNtpSync()` in `checkConnectionStatus()` right after `WL_CONNECTED` is detected. This is non-blocking so it doesn't delay the UI flow. ### 4. KOReaderSync refactor (`src/activities/reader/KOReaderSyncActivity.cpp`) - Removed the local `syncTimeWithNTP()` anonymous namespace function and `#include ` - Replaced both call sites with `TimeSync::waitForNtpSync()` (blocking, since KOReader needs accurate time for API requests) - Added `#include "util/TimeSync.h"` ### 5. Boot time debug log (`src/main.cpp`) - Added `#include ` and a debug log in `setup()` that prints the current RTC time on boot (or "not set" if epoch). This helps verify time persistence across deep sleep during testing. ## Sleep Persistence Notes - ESP32-C3's default ESP-IDF config uses both RTC and high-resolution timers for timekeeping - The RTC timer continues during deep sleep, so `time()` / `gettimeofday()` return correct wall-clock time after wake (with drift from the internal ~150kHz RC oscillator) - Time does NOT survive a full power-on reset (RTC timer resets) - NTP auto-sync on WiFi connection handles drift correction ## Build Verification - `pio run -e mod` -- SUCCESS (RAM: 31.0%, Flash: 78.8%) ## Follow-up Items - Test on hardware: set time manually, sleep, wake, verify time in serial log - Test NTP: connect to WiFi from Settings, verify time updates automatically - Consider adding `TimeSync::stopNtpSync()` call when WiFi is disconnected (currently SNTP just stops getting responses, which is harmless)