TimeManager in Pico-Framework
TimeManager provides a centralized and consistent way to manage system time, synchronize with NTP, detect timezones automatically, and convert timestamps into formatted strings with timezone awareness. It is a foundational service for any real-time or time-sensitive applications using Pico-Framework.
This guide explains the purpose, architecture, and usage of TimeManager with real examples and design rationale.
Why Use TimeManager?
Time in embedded systems is notoriously error-prone:
- RTC clocks may drift or lose power
- Network clocks (NTP) are asynchronous and may fail
- Timezones are rarely handled correctly
- Timestamps are hard to make human-readable
TimeManager solves these problems by:
- Synchronizing time via SNTP (NTP over UDP)
- Setting the RP2040 Always-On Timer (AON)
- Optionally initializing the hardware RTC (if present)
- Formatting time with timezone labels
- Automatically detecting location-based timezone offsets using Open-Meteo
It provides a single service your app can rely on for accurate, human-readable timestamps.
Core Capabilities
- Start and sync time using SNTP
- Validate system time (sanity checks)
- Broadcast events when time becomes valid or is synced
- Support for timezone-aware formatting
- Use Open-Meteo and IP-based geolocation to detect the timezone offset
- Initialize AON or RTC time depending on platform
- Emit events like
SystemNotification::TimeSync
,TimeValid
, andTimeInvalid
Initialization and Integration
TimeManager is automatically used by the framework and registered into AppContext
at startup. It responds to two key lifecycle events:
onNetworkReady()
: Called once Wi-Fi is up. It starts the SNTP client and syncs time.onHttpServerStarted()
: Called once HTTP server is live. It triggers timezone detection and offset application.
Example: Startup Flow
TimeManager* tm = AppContext::get<TimeManager>();
// Check if time is valid (AON or RTC already running)
if (!tm->isTimeValid()) {
tm->syncTimeWithNtp(10); // Wait up to 10 seconds
}
printf("Time: %s
", tm->currentTimeForTrace().c_str());
NTP Synchronization
TimeManager uses lwIP’s SNTP client. When a response arrives from the NTP server, the framework sets the AON timer using sntp_set_system_time
.
Example output:
[TimeManager] Setting system time from epoch: 1714754891
[TimeManager] System time set to: Tue May 3 18:48:11 2025
Sanity checks ensure that bogus responses (e.g., year 1970) are rejected.
Timezone Detection and Offset
After startup, TimeManager uses http://ip-api.com/json
to get a rough geolocation based on your public IP. It then queries the Open-Meteo forecast API to get the UTC offset in seconds and apply it.
tm->detectAndApplyTimezone();
You can also manually apply a known offset:
tm->applyFixedTimezoneOffset(3600, "CET", "CEST");
This changes the formatted string output for logs and UIs.
Formatting Time for Display
You can request a formatted string of the current time including the local zone:
std::string stamp = tm->currentTimeForTrace();
// Output: [18:48:11 CET]
Handling Failures and Fallback
If NTP fails, TimeManager:
- Falls back to checking the AON timer
- If no valid time source exists, posts
SystemNotification::TimeInvalid
- If only partial time is available (e.g. from RTC), it may still proceed
Apps can subscribe to these events to respond accordingly.
void MyController::onEvent(const Event& event) {
if (event.notification.isSystem(SystemNotification::TimeSync)) {
printf("We now have accurate time!
");
}
}
RTC Support (RP2040)
If RTC hardware is available (e.g. RP2040), TimeManager can initialize it using:
rtc_init();
But the primary time source is the Always-On Timer (AON) for stability and precision.
Summary
TimeManager simplifies time handling by:
- Abstracting away NTP and timer setup
- Supporting timezone-aware formatting
- Automatically syncing time after network availability
- Broadcasting relevant events to the system
It is a plug-and-play service that your controllers, schedulers, and logs can depend on.
Common Use Cases
- Timestamping log messages
- Scheduling events based on local time
- Displaying time in a human-readable way in web UIs
- Adjusting behavior based on time-of-day