Logo Pico-Framework A web-first embedded framework for C++
Loading...
Searching...
No Matches
TimeManager Class Reference

#include <TimeManager.h>

+ Collaboration diagram for TimeManager:

Public Member Functions

 TimeManager ()=default
 
bool syncTimeWithNtp (int timeoutSeconds=20)
 Initialize the time manager.
 
void setTimeFromEpoch (uint32_t epochSeconds)
 Set the system time from an epoch timestamp (e.g. from SNTP)
 
void fetchAndApplyTimezoneFromOpenMeteo (float lat, float lon, const std::string &tzName)
 Fetch and apply the timezone from OpenMeteo API using latitude and longitude.
 
void detectAndApplyTimezone ()
 Detect and apply the timezone based on the current location or IP address.
 
void applyFixedTimezoneOffset (int offsetSeconds, const char *stdName="UTC", const char *dstName="UTC")
 Apply a fixed timezone offset.
 
int getTimezoneOffset () const
 Get the current timezone offset in seconds.
 
const char * getTimezoneName () const
 Get the name of the current timezone.
 
std::string formatTimeWithZone (time_t rawTime=0) const
 
std::string currentTimeForTrace () const
 Get the current time formatted as a string.
 
void setTime (timespec *ts)
 Set the system time using a timespec structure.
 
bool isTimeSynced () const
 Returns true if system time has been synced with NTP servers.
 
bool isTimeValid ()
 
void start ()
 Start the time manager.
 
void onNetworkReady ()
 hanles network ready event.
 
void onHttpServerStarted ()
 

Private Member Functions

void initNtpClient ()
 
bool getLocationFromIp (std::string &tzName, float &lat, float &lon)
 

Private Attributes

bool timeSynced = false
 
int timezoneOffsetSeconds = 0
 
std::string timezoneName = "UTC"
 

Detailed Description

Definition at line 10 of file TimeManager.h.

Constructor & Destructor Documentation

◆ TimeManager()

TimeManager::TimeManager ( )
default

Member Function Documentation

◆ applyFixedTimezoneOffset()

void TimeManager::applyFixedTimezoneOffset ( int  offsetSeconds,
const char *  stdName = "UTC",
const char *  dstName = "UTC" 
)
Parameters
offsetSecondsOffset in seconds from UTC.
stdNameStandard timezone name (default "UTC").
dstNameDaylight Saving Time name (default "UTC").

Definition at line 148 of file TimeManager.cpp.

149{
150 timezoneOffsetSeconds = offsetSeconds;
151 timezoneName = stdName;
152
154 AppContext::get<EventManager>()->postEvent(e);
155
156 // Log for trace/debug purposes
157 printf("[TimeManager] Timezone set to UTC %+d:00 (%s)\n",
158 offsetSeconds / 3600, stdName);
159}
constexpr uint32_t eventMask(Enum e)
Helper function to create an event mask from an enum value.
static constexpr std::uintptr_t getTypeKey()
Definition AppContext.h:91
int timezoneOffsetSeconds
std::string timezoneName
Represents a framework event, optionally carrying payload data.
Definition Event.h:24

References eventMask(), AppContext::getTypeKey(), LocalTimeValid, timezoneName, and timezoneOffsetSeconds.

Referenced by detectAndApplyTimezone(), fetchAndApplyTimezoneFromOpenMeteo(), and onHttpServerStarted().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ currentTimeForTrace()

std::string TimeManager::currentTimeForTrace ( ) const

This will return the current time timezone information.

Returns
A string representing the current time.

Definition at line 276 of file TimeManager.cpp.

277{
279}
static time_t now()
Get the current epoch time using platform RTC or AON.
Definition PicoTime.cpp:28
std::string formatTimeWithZone(time_t rawTime=0) const

References formatTimeWithZone(), and PicoTime::now().

Referenced by getFormattedTimestamp().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ detectAndApplyTimezone()

void TimeManager::detectAndApplyTimezone ( )

This will attempt to determine the timezone automatically.

Definition at line 239 of file TimeManager.cpp.

240{
241 std::string tzName = "UTC";
242 float lat = 0.0f, lon = 0.0f;
243
244 if (getLocationFromIp(tzName, lat, lon))
245 {
246 printf("[TimeManager] Location detected: lat=%.4f, lon=%.4f\n", lat, lon);
247 fetchAndApplyTimezoneFromOpenMeteo(lat, lon, tzName);
248 }
249 else
250 {
251 printf("[TimeManager] Could not determine location. Using default UTC.\n");
252 applyFixedTimezoneOffset(0, tzName.c_str(), tzName.c_str());
253 }
254}
bool getLocationFromIp(std::string &tzName, float &lat, float &lon)
void applyFixedTimezoneOffset(int offsetSeconds, const char *stdName="UTC", const char *dstName="UTC")
Apply a fixed timezone offset.
void fetchAndApplyTimezoneFromOpenMeteo(float lat, float lon, const std::string &tzName)
Fetch and apply the timezone from OpenMeteo API using latitude and longitude.

References applyFixedTimezoneOffset(), fetchAndApplyTimezoneFromOpenMeteo(), and getLocationFromIp().

Referenced by onHttpServerStarted().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ fetchAndApplyTimezoneFromOpenMeteo()

void TimeManager::fetchAndApplyTimezoneFromOpenMeteo ( float  lat,
float  lon,
const std::string &  tzName 
)
Parameters
latLatitude of the location.
lonLongitude of the location.
tzNameOptional timezone name to apply if available.

Definition at line 205 of file TimeManager.cpp.

206{
207 char url[256];
208 snprintf(url, sizeof(url),
209 "http://api.open-meteo.com/v1/forecast?latitude=%.4f&longitude=%.4f&current_weather=true&timezone=auto",
210 lat, lon);
211
212 HttpRequest req;
213 HttpResponse res = req.get(url);
214
215 const std::string &body = res.getBody();
216 TRACE("[TimeManager] Open-Meteo response: %s\n", body.c_str());
217 TRACE("Status code: %d\n", res.getStatusCode());
218 if (body.empty())
219 {
220 printf("[TimeManager] Open-Meteo response is empty.\n");
221 applyFixedTimezoneOffset(0, tzName.c_str(), tzName.c_str());
222 return;
223 }
224
225 size_t offsetPos = body.find("\"utc_offset_seconds\":");
226 int offsetSeconds = 0;
227 if (offsetPos != std::string::npos)
228 {
229 offsetPos += strlen("\"utc_offset_seconds\":");
230 size_t end = body.find(',', offsetPos);
231 if (end == std::string::npos)
232 end = body.size();
233 offsetSeconds = std::stoi(body.substr(offsetPos, end - offsetPos));
234 }
235 TRACE("[TimeManager] Timezone: %s, UTC offset: %d sec\n", tzName.c_str(), offsetSeconds);
236 applyFixedTimezoneOffset(offsetSeconds, tzName.c_str(), tzName.c_str());
237}
#define TRACE(...)
Default trace (INFO level).
Definition DebugTrace.h:187
Forward declaration for potential routing needs.
Definition HttpRequest.h:32
HttpResponse get()
Send a GETPOST/PUT/DEL request.
Represents an HTTP response object.
int getStatusCode() const
Get the response status code.
const std::string & getBody() const
Get the response body.

References applyFixedTimezoneOffset(), HttpRequest::get(), HttpResponse::getBody(), HttpResponse::getStatusCode(), and TRACE.

Referenced by detectAndApplyTimezone().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ formatTimeWithZone()

std::string TimeManager::formatTimeWithZone ( time_t  rawTime = 0) const

Definition at line 256 of file TimeManager.cpp.

257{
258 if (utcTime == 0) {
259 utcTime = PicoTime::now(); // Use the system time
260 }
261
262 time_t localTime = utcTime + timezoneOffsetSeconds;
263 struct tm tmBuf;
264 gmtime_r(&localTime, &tmBuf); // Adjusted time treated as UTC
265
266 char timeBuf[16] = {0};
267 strftime(timeBuf, sizeof(timeBuf), "%H:%M:%S", &tmBuf);
268
269 const char *zone = timezoneName.empty() ? "?" : timezoneName.c_str();
270
271 char formatted[48] = {0};
272 snprintf(formatted, sizeof(formatted), "[%s %s]", timeBuf, zone);
273 return std::string(formatted);
274}
struct tm * gmtime_r(const time_t *pxTime, struct tm *tmStruct)

References gmtime_r(), PicoTime::now(), timezoneName, and timezoneOffsetSeconds.

Referenced by currentTimeForTrace().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ getLocationFromIp()

bool TimeManager::getLocationFromIp ( std::string &  tzName,
float &  lat,
float &  lon 
)
private

Definition at line 161 of file TimeManager.cpp.

162{
163 HttpRequest req;
164 HttpResponse res = req.get("http://ip-api.com/json");
165
166 const std::string &body = res.getBody();
167 if (body.empty())
168 {
169 printf("[TimeManager] Failed to get IP geolocation.\n");
170 return false;
171 }
172
173 // Parse timezone
174 size_t tzPos = body.find("\"timezone\":\"");
175 if (tzPos != std::string::npos)
176 {
177 tzPos += strlen("\"timezone\":\"");
178 size_t end = body.find('"', tzPos);
179 if (end != std::string::npos)
180 {
181 tzName = body.substr(tzPos, end - tzPos);
182 }
183 }
184 else
185 {
186 tzName = "UTC";
187 }
188
189 // Parse lat/lon
190 size_t latPos = body.find("\"lat\":");
191 size_t lonPos = body.find("\"lon\":");
192 if (latPos == std::string::npos || lonPos == std::string::npos)
193 {
194 printf("[TimeManager] lat/lon not found. Using defaults.\n");
195 lat = 0.0f;
196 lon = 0.0f;
197 return false;
198 }
199
200 lat = std::stof(body.substr(latPos + 6));
201 lon = std::stof(body.substr(lonPos + 6));
202 return true;
203}

References HttpRequest::get(), and HttpResponse::getBody().

Referenced by detectAndApplyTimezone().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ getTimezoneName()

const char * TimeManager::getTimezoneName ( ) const
inline
Returns
The name of the timezone as a string.

Definition at line 58 of file TimeManager.h.

58{ return timezoneName.c_str(); }

References timezoneName.

◆ getTimezoneOffset()

int TimeManager::getTimezoneOffset ( ) const
inline
Returns
The timezone offset in seconds from UTC.

Definition at line 52 of file TimeManager.h.

52{ return timezoneOffsetSeconds; }

References timezoneOffsetSeconds.

◆ initNtpClient()

void TimeManager::initNtpClient ( )
private

Definition at line 39 of file TimeManager.cpp.

40{
41 if (!sntp_enabled())
42 {
43 //TRACE("[Time Manager] Initializing SNTP client...\n");
44 sntp_setoperatingmode(SNTP_OPMODE_POLL);
45 sntp_setservername(0, "pool.ntp.org");
46 sntp_init();
47 }
48}

Referenced by onNetworkReady().

+ Here is the caller graph for this function:

◆ isTimeSynced()

bool TimeManager::isTimeSynced ( ) const
inline

Note that sntp syncing is setup for every hour by default - this can be changed in framework_config.h This retrieves the current time in a timespec format.

Returns
A timespec structure containing the current time.

Definition at line 82 of file TimeManager.h.

82{ return timeSynced; }

References timeSynced.

◆ isTimeValid()

bool TimeManager::isTimeValid ( )
inline

Definition at line 84 of file TimeManager.h.

84 {
85 return aon_timer_is_running(); // Direct real system call, no private bool
86 }

Referenced by onNetworkReady(), start(), and syncTimeWithNtp().

+ Here is the caller graph for this function:

◆ onHttpServerStarted()

void TimeManager::onHttpServerStarted ( )

Definition at line 297 of file TimeManager.cpp.

297 {
299 {
301 }
302 else
303 {
304 applyFixedTimezoneOffset(0, "UTC", "UTC");
305 }
306}
void detectAndApplyTimezone()
Detect and apply the timezone based on the current location or IP address.
#define DETECT_LOCAL_TIMEZONE

References applyFixedTimezoneOffset(), DETECT_LOCAL_TIMEZONE, and detectAndApplyTimezone().

+ Here is the call graph for this function:

◆ onNetworkReady()

void TimeManager::onNetworkReady ( )

This is called when the network is ready and the time manager can start syncing time.

Definition at line 287 of file TimeManager.cpp.

288{
289 initNtpClient(); // Initialize SNTP client - this will automatically cause a timesync event when that happens
290 if (!isTimeValid())
291 {
293 }
294
295}
void initNtpClient()
bool isTimeValid()
Definition TimeManager.h:84
bool syncTimeWithNtp(int timeoutSeconds=20)
Initialize the time manager.
#define NTP_TIMEOUT_SECONDS
This setting defines the retry timeout The default SNTP retry time is 15 seconds, we set it to 5 in l...

References initNtpClient(), isTimeValid(), NTP_TIMEOUT_SECONDS, and syncTimeWithNtp().

Referenced by FrameworkManager::onStart().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ setTime()

void TimeManager::setTime ( timespec *  ts)

This is useful for setting the time directly from a timespec object.

Parameters
tsPointer to a timespec structure containing the time to set.

This function sets the system time using the provided timespec structure. It initializes the RTC if available and sets the always-on timer to the specified time. If the always-on timer is already running, it does nothing.

Parameters
tsPointer to a timespec structure containing the time to set.

Definition at line 119 of file TimeManager.cpp.

120{
121 if (ts == nullptr)
122 {
123 printf("[TimeManager] Invalid timespec provided.\n");
124 return;
125 }
126
127 // if the AON timer is not running, start it
128 if (!aon_timer_is_running()){
129 printf("[TimeManager] AON timer is not running, starting it...\n");
130 aon_timer_start(ts);
131 }
132 else{
133 // if the AON timer is running, set the time
134 printf("[TimeManager] AON timer is running, syncing time...\n");
135 aon_timer_set_time(ts);
136 }
137 timespec currentTime;
138 if(!aon_timer_get_time(&currentTime))
139 {
140 printf("[TimeManager] Failed to get system time from AON timer.\n");
141 return;
142 }
143 else{
145 }
146}

References AppContext::getTypeKey(), and TimeValid.

Referenced by setTimeFromEpoch().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ setTimeFromEpoch()

void TimeManager::setTimeFromEpoch ( uint32_t  epochSeconds)

Definition at line 96 of file TimeManager.cpp.

97{
98 printf("[TimeManager] Setting system time from epoch: %u\n", epoch);
99 timespec ts = {
100 .tv_sec = epoch,
101 .tv_nsec = 0};
102 setTime(&ts);
103 timeSynced = true;
104 Event event;
106 AppContext::get<EventManager>()->postEvent(event);
107 printf("[TimeManager] System time set to: %s\n", ctime(&ts.tv_sec));
108}
void setTime(timespec *ts)
Set the system time using a timespec structure.
Notification notification
Notification identifier (system or user)
Definition Event.h:25

References AppContext::getTypeKey(), Event::notification, setTime(), TimeSync, and timeSynced.

+ Here is the call graph for this function:

◆ start()

void TimeManager::start ( )

It will check if time is valid and post event if it is

Definition at line 281 of file TimeManager.cpp.

281 {
282 if (isTimeValid()) {
284 }
285}

References AppContext::getTypeKey(), isTimeValid(), and TimeValid.

Referenced by FrameworkManager::onStart().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ syncTimeWithNtp()

bool TimeManager::syncTimeWithNtp ( int  timeoutSeconds = 20)

This sets up the SNTP client and attempts to sync time with NTP servers.

Returns
true if initialization was successful, false otherwise.

Definition at line 50 of file TimeManager.cpp.

51{
52 printf("[Time Manager] Waiting for NTP time sync...\n");
53
54 // Wait up to timeoutSeconds for time to be set
55 int waited = 0;
56 while (waited < timeoutSeconds)
57 {
58 if(timeSynced)
59 {
60 timespec ts;
61 if(aon_timer_get_time(&ts)){
62 if (ts.tv_sec > 1735689600)
63 { // sanity check: after Jan 1 2025
64 printf("[Time Manager] NTP time acquired successfuly\n");
65 return true;
66 }
67 else
68 {
69 printf("[Time Manager] System time epoch is invalid: %ld\n", ts.tv_sec);
70 return false;
71 }
72 }
73 else
74 {
75 printf("[Time Manager] Failed to get system time from AON timer.\n");
76 return false;
77 }
78 }
79 vTaskDelay(pdMS_TO_TICKS(1000));
80 waited++;
81 }
82
83 // Timeout occurred
84 if (!isTimeValid()) {
85 printf("[Time Manager] NTP sync failed and no valid time source available.\n");
86 Event event;
88 AppContext::get<EventManager>()->postEvent(event);
89 }
90 else {
91 printf("[Time Manager] NTP sync failed, but AON timer is running — time still valid.\n");
92 }
93 return false;
94}

References AppContext::getTypeKey(), isTimeValid(), Event::notification, TimeInvalid, and timeSynced.

Referenced by onNetworkReady().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Member Data Documentation

◆ timeSynced

bool TimeManager::timeSynced = false
private

Definition at line 102 of file TimeManager.h.

Referenced by isTimeSynced(), setTimeFromEpoch(), and syncTimeWithNtp().

◆ timezoneName

std::string TimeManager::timezoneName = "UTC"
private

Definition at line 106 of file TimeManager.h.

Referenced by applyFixedTimezoneOffset(), formatTimeWithZone(), and getTimezoneName().

◆ timezoneOffsetSeconds

int TimeManager::timezoneOffsetSeconds = 0
private

Definition at line 105 of file TimeManager.h.

Referenced by applyFixedTimezoneOffset(), formatTimeWithZone(), and getTimezoneOffset().


The documentation for this class was generated from the following files: