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

Central service for time-driven scheduling of framework events. More...

#include <TimerService.h>

+ Collaboration diagram for TimerService:

Public Member Functions

 TimerService ()
 
 ~TimerService ()=default
 
void withLock (const std::function< void()> &fn)
 
void scheduleAt (time_t unixTime, const Event &event)
 Schedule a one-time event at an absolute UNIX timestamp.
 
void scheduleAt (time_t unixTime, const Event &event, const std::string &jobId)
 
void scheduleEvery (uint32_t intervalMs, const Event &event)
 Schedule a repeating event at fixed intervals.
 
void scheduleEvery (uint32_t intervalMs, const Event &event, const std::string &jobId)
 
void scheduleDailyAt (TimeOfDay time, DaysOfWeek days, const Event &event)
 Schedule a recurring event based on time-of-day and day mask.
 
void scheduleDailyAt (TimeOfDay time, DaysOfWeek days, const Event &event, const std::string &jobId)
 
void scheduleDuration (TimeOfDay start, DaysOfWeek days, uint32_t durationMs, const Event &startEvent, const Event &stopEvent)
 Schedule a start event and stop event with a delay between them.
 
void scheduleDuration (TimeOfDay start, DaysOfWeek days, uint32_t durationMs, const Event &startEvent, const Event &stopEvent, const std::string &baseJobId)
 
void checkMissedEvents (time_t now)
 Detect and fire any missed events after a reboot (TBD).
 
bool cancel (const std::string &jobId)
 
void scheduleCallbackAt (time_t unixTime, std::function< void()> callback)
 Schedule a one-shot callback at a given absolute time.
 

Static Public Member Functions

static TimerServiceinstance ()
 Access the singleton instance.
 

Private Member Functions

void rescheduleDailyJob (const TimerJob &job)
 Placeholder for persistence/rescheduling in the future.
 

Private Attributes

SemaphoreHandle_t lock_
 
std::unordered_map< std::string, TimerHandle_t > scheduledJobs
 Map of job IDs to TimerHandles.
 

Static Private Attributes

static StaticSemaphore_t lockBuffer_
 

Detailed Description

Definition at line 69 of file TimerService.h.

Constructor & Destructor Documentation

◆ TimerService()

TimerService::TimerService ( )

Definition at line 47 of file TimerService.cpp.

47 {
48 lock_ = xSemaphoreCreateMutexStatic(&lockBuffer_);
50}
#define configASSERT(x)
SemaphoreHandle_t lock_
static StaticSemaphore_t lockBuffer_

References configASSERT, lock_, and lockBuffer_.

◆ ~TimerService()

TimerService::~TimerService ( )
default

Member Function Documentation

◆ cancel()

bool TimerService::cancel ( const std::string &  jobId)

Definition at line 261 of file TimerService.cpp.

261 {
262 bool success = false;
263 withLock([&]() {
264 auto it = scheduledJobs.find(jobId);
265 if (it != scheduledJobs.end()) {
266 xTimerStop(it->second, 0);
267 xTimerDelete(it->second, 0);
268 scheduledJobs.erase(it);
269 success = true;
270 }
271 });
272 return success;
273}
void withLock(const std::function< void()> &fn)
std::unordered_map< std::string, TimerHandle_t > scheduledJobs
Map of job IDs to TimerHandles.

References scheduledJobs, and withLock().

+ Here is the call graph for this function:

◆ checkMissedEvents()

void TimerService::checkMissedEvents ( time_t  now)

Detect and fire any missed events after a reboot (TBD).

Parameters
nowCurrent UNIX timestamp.
Parameters
nowCurrent UNIX timestamp.

Definition at line 276 of file TimerService.cpp.

277{
278 // Not implemented in v0.2
279}

◆ instance()

TimerService & TimerService::instance ( )
static

Access the singleton instance.

Definition at line 88 of file TimerService.cpp.

89{
90 static TimerService inst;
91 return inst;
92}
Central service for time-driven scheduling of framework events.

◆ rescheduleDailyJob()

void TimerService::rescheduleDailyJob ( const TimerJob job)
private

Placeholder for persistence/rescheduling in the future.

Definition at line 282 of file TimerService.cpp.

283{
284 // Not implemented in v0.2
285}

Referenced by scheduleDailyAt(), and scheduleDuration().

+ Here is the caller graph for this function:

◆ scheduleAt() [1/2]

void TimerService::scheduleAt ( time_t  unixTime,
const Event event 
)

Schedule a one-time event at an absolute UNIX timestamp.

Parameters
unixTimeEpoch time in seconds.
eventEvent to trigger.
Parameters
unixTimeEpoch time in seconds.
eventEvent to trigger.

Definition at line 95 of file TimerService.cpp.

96{
97 std::string defaultId = "at_" + std::to_string(unixTime);
98 scheduleAt(unixTime, event, defaultId);
99}
void scheduleAt(time_t unixTime, const Event &event)
Schedule a one-time event at an absolute UNIX timestamp.

References scheduleAt().

Referenced by scheduleAt().

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

◆ scheduleAt() [2/2]

void TimerService::scheduleAt ( time_t  unixTime,
const Event event,
const std::string &  jobId 
)

Definition at line 101 of file TimerService.cpp.

102{
103 time_t now = PicoTime::now();
104 uint32_t delaySeconds = (unixTime > now) ? (unixTime - now) : 0;
105
106 TimerHandle_t handle = xTimerCreate("AtTimer", pdMS_TO_TICKS(delaySeconds * 1000), pdFALSE, new Event(event),
107 [](TimerHandle_t xTimer)
108 {
109 Event *evt = static_cast<Event *>(pvTimerGetTimerID(xTimer));
110 if (evt)
111 {
112 AppContext::get<EventManager>()->postEvent(*evt);
113 delete evt;
114 }
115 xTimerDelete(xTimer, 0);
116 });
117
118 if (handle)
119 {
120 withLock([&]() {
121 // Cancel and delete old timer if it exists
122 auto it = scheduledJobs.find(jobId);
123 if (it != scheduledJobs.end()) {
124 xTimerStop(it->second, 0);
125 xTimerDelete(it->second, 0);
126 scheduledJobs.erase(it);
127 }
128 scheduledJobs[jobId] = handle;
129 });
130 xTimerStart(handle, 0);
131 }
132}
static constexpr std::uintptr_t getTypeKey()
Definition AppContext.h:91
static time_t now()
Get the current epoch time using platform RTC or AON.
Definition PicoTime.cpp:28
Represents a framework event, optionally carrying payload data.
Definition Event.h:24

References AppContext::getTypeKey(), PicoTime::now(), scheduledJobs, and withLock().

+ Here is the call graph for this function:

◆ scheduleCallbackAt()

void TimerService::scheduleCallbackAt ( time_t  unixTime,
std::function< void()>  callback 
)
Parameters
unixTimeThe absolute time to invoke the callback (in seconds).
callbackThe callback to execute.

Definition at line 287 of file TimerService.cpp.

287 {
288 time_t now = PicoTime::now();
289 if (when <= now) {
290 printf("[TimerService] WARNING: scheduled time is in the past (%lld <= %lld)\n", when, now);
291 return;
292 }
293
294 auto* cb = new std::function<void()>(std::move(callback));
295 uint32_t delayMs = static_cast<uint32_t>((when - now) * 1000);
296
297 TimerHandle_t handle = xTimerCreate("CbTimer", pdMS_TO_TICKS(delayMs), pdFALSE, cb,
298 [](TimerHandle_t xTimer) {
299 auto* fn = static_cast<std::function<void()>*>(pvTimerGetTimerID(xTimer));
300 if (fn) {
301 (*fn)(); // 🔥 fire the user callback
302 delete fn; // ✅ clean up
303 }
304 xTimerDelete(xTimer, 0);
305 });
306
307 if (handle) {
308 xTimerStart(handle, 0);
309 } else {
310 printf("[TimerService] ERROR: Failed to create xTimer\n");
311 delete cb;
312 }
313}

References PicoTime::now().

+ Here is the call graph for this function:

◆ scheduleDailyAt() [1/2]

void TimerService::scheduleDailyAt ( TimeOfDay  time,
DaysOfWeek  days,
const Event event 
)

Schedule a recurring event based on time-of-day and day mask.

Parameters
timeTime of day to trigger.
daysDays to run (bitmask).
eventEvent to trigger.
Parameters
timeTime of day to trigger.
daysDays to run (bitmask).
eventEvent to trigger.

Definition at line 163 of file TimerService.cpp.

164{
165 std::string defaultId = "daily_" + std::to_string((uint32_t)event.notification.code()) + "_" + std::to_string(toSeconds(time));
166 scheduleDailyAt(time, days, event, defaultId);
167}
static uint32_t toSeconds(const TimeOfDay &tod)
void scheduleDailyAt(TimeOfDay time, DaysOfWeek days, const Event &event)
Schedule a recurring event based on time-of-day and day mask.
Notification notification
Notification identifier (system or user)
Definition Event.h:25
uint8_t code() const
Get the notification code.

References Notification::code(), Event::notification, scheduleDailyAt(), and toSeconds().

Referenced by scheduleDailyAt().

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

◆ scheduleDailyAt() [2/2]

void TimerService::scheduleDailyAt ( TimeOfDay  time,
DaysOfWeek  days,
const Event event,
const std::string &  jobId 
)

Definition at line 169 of file TimerService.cpp.

170{
171 time_t now = PicoTime::now();
172 uint32_t delaySeconds = secondsUntilNextMatch(time, days, now);
173
174 TimerHandle_t handle = xTimerCreate("DailyJob", pdMS_TO_TICKS(delaySeconds * 1000), pdFALSE, new Event(event),
175 [](TimerHandle_t xTimer)
176 {
177 Event *evt = static_cast<Event *>(pvTimerGetTimerID(xTimer));
178 if (evt)
179 {
180 AppContext::get<EventManager>()->postEvent(*evt);
181 delete evt;
182 }
183 xTimerDelete(xTimer, 0);
184 });
185
186 if (handle)
187 {
188 withLock([&]() {
189 scheduledJobs[jobId] = handle;
190 });
191 xTimerStart(handle, 0);
192 TimerJob job{time, days, 0, event, {}, true};
194 }
195}
static uint32_t secondsUntilNextMatch(const TimeOfDay &tod, DaysOfWeek mask, time_t currentTime)
void rescheduleDailyJob(const TimerJob &job)
Placeholder for persistence/rescheduling in the future.
Represents a job scheduled by the TimerService.

References AppContext::getTypeKey(), PicoTime::now(), rescheduleDailyJob(), scheduledJobs, secondsUntilNextMatch(), and withLock().

+ Here is the call graph for this function:

◆ scheduleDuration() [1/2]

void TimerService::scheduleDuration ( TimeOfDay  start,
DaysOfWeek  days,
uint32_t  durationMs,
const Event startEvent,
const Event stopEvent 
)

Schedule a start event and stop event with a delay between them.

Parameters
startStart time of day.
daysDays to run.
durationMsDuration after start to trigger stop.
startEventEvent to post at start.
stopEventEvent to post after duration.
Parameters
startStart time of day.
daysDays to run.
durationMsDuration after start to trigger stop.
startEventEvent to post at start.
stopEventEvent to post after duration.

Definition at line 198 of file TimerService.cpp.

200{
201 std::string baseId = "duration_" + std::to_string((uint32_t)startEvent.notification.code());
202 scheduleDuration(start, days, durationMs, startEvent, stopEvent, baseId);
203}
void scheduleDuration(TimeOfDay start, DaysOfWeek days, uint32_t durationMs, const Event &startEvent, const Event &stopEvent)
Schedule a start event and stop event with a delay between them.

References Notification::code(), Event::notification, and scheduleDuration().

Referenced by scheduleDuration().

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

◆ scheduleDuration() [2/2]

void TimerService::scheduleDuration ( TimeOfDay  start,
DaysOfWeek  days,
uint32_t  durationMs,
const Event startEvent,
const Event stopEvent,
const std::string &  baseJobId 
)

Definition at line 205 of file TimerService.cpp.

207{
208 time_t now = PicoTime::now();
209 uint32_t startDelay = secondsUntilNextMatch(start, days, now);
210
211 std::string startId = baseId + "_start";
212 std::string stopId = baseId + "_stop";
213
214 TimerHandle_t startHandle = xTimerCreate("StartJob", pdMS_TO_TICKS(startDelay * 1000), pdFALSE, new Event(startEvent),
215 [](TimerHandle_t xTimer)
216 {
217 Event *evt = static_cast<Event *>(pvTimerGetTimerID(xTimer));
218 if (evt)
219 {
220 AppContext::get<EventManager>()->postEvent(*evt);
221 delete evt;
222 }
223 xTimerDelete(xTimer, 0);
224 });
225
226 if (startHandle)
227 {
228 withLock([&]() {
229 scheduledJobs[startId] = startHandle;
230 });
231 xTimerStart(startHandle, 0);
232 }
233
234 uint32_t stopDelay = startDelay + durationMs / 1000;
235
236 TimerHandle_t stopHandle = xTimerCreate("StopJob", pdMS_TO_TICKS(stopDelay * 1000), pdFALSE, new Event(stopEvent),
237 [](TimerHandle_t xTimer)
238 {
239 Event *evt = static_cast<Event *>(pvTimerGetTimerID(xTimer));
240 if (evt)
241 {
242 AppContext::get<EventManager>()->postEvent(*evt);
243 delete evt;
244 }
245 xTimerDelete(xTimer, 0);
246 });
247
248 if (stopHandle)
249 {
250 withLock([&]() {
251 scheduledJobs[stopId] = stopHandle;
252 });
253 xTimerStart(stopHandle, 0);
254 }
255
256 TimerJob job{start, days, durationMs, startEvent, stopEvent, true};
258}

References AppContext::getTypeKey(), PicoTime::now(), rescheduleDailyJob(), scheduledJobs, secondsUntilNextMatch(), and withLock().

+ Here is the call graph for this function:

◆ scheduleEvery() [1/2]

void TimerService::scheduleEvery ( uint32_t  intervalMs,
const Event event 
)

Schedule a repeating event at fixed intervals.

Parameters
intervalMsInterval in milliseconds.
eventEvent to trigger repeatedly.
Parameters
intervalMsInterval in milliseconds.
eventEvent to trigger repeatedly.

Definition at line 135 of file TimerService.cpp.

136{
137 std::string defaultId = "interval_" + std::to_string((uint32_t)event.notification.code());
138 scheduleEvery(intervalMs, event, defaultId);
139}
void scheduleEvery(uint32_t intervalMs, const Event &event)
Schedule a repeating event at fixed intervals.

References Notification::code(), Event::notification, and scheduleEvery().

Referenced by scheduleEvery().

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

◆ scheduleEvery() [2/2]

void TimerService::scheduleEvery ( uint32_t  intervalMs,
const Event event,
const std::string &  jobId 
)

Definition at line 141 of file TimerService.cpp.

142{
143 TimerHandle_t handle = xTimerCreate("EveryTimer", pdMS_TO_TICKS(intervalMs), pdTRUE, new Event(event),
144 [](TimerHandle_t xTimer)
145 {
146 Event *evt = static_cast<Event *>(pvTimerGetTimerID(xTimer));
147 if (evt)
148 {
149 AppContext::get<EventManager>()->postEvent(*evt);
150 }
151 });
152
153 if (handle)
154 {
155 withLock([&]() {
156 scheduledJobs[jobId] = handle;
157 });
158 xTimerStart(handle, 0);
159 }
160}

References AppContext::getTypeKey(), scheduledJobs, and withLock().

+ Here is the call graph for this function:

◆ withLock()

void TimerService::withLock ( const std::function< void()> &  fn)

Definition at line 52 of file TimerService.cpp.

52 {
53 xSemaphoreTake(lock_, portMAX_DELAY);
54 fn();
55 xSemaphoreGive(lock_);
56}

References lock_.

Referenced by cancel(), scheduleAt(), scheduleDailyAt(), scheduleDuration(), and scheduleEvery().

+ Here is the caller graph for this function:

Member Data Documentation

◆ lock_

SemaphoreHandle_t TimerService::lock_
private

Definition at line 144 of file TimerService.h.

Referenced by TimerService(), and withLock().

◆ lockBuffer_

StaticSemaphore_t TimerService::lockBuffer_
staticprivate
Note
Memory & Timer Lifetime (v0.1):
  • One-shot timers (scheduleAt, scheduleDailyAt, scheduleDuration) dynamically allocate an Event using new and clean it up automatically after posting (inside the timer callback).
  • Repeating timers (scheduleEvery) also allocate an Event, which is reused on each invocation. It is not deleted automatically and is assumed to remain valid for the lifetime of the timer.

    It is now possible to cancel scheduled jobs using a job ID which will delete the timer and free the associated event.

    Todo:
    Planned for v0.2+:

Definition at line 145 of file TimerService.h.

Referenced by TimerService().

◆ scheduledJobs

std::unordered_map<std::string, TimerHandle_t> TimerService::scheduledJobs
private

Definition at line 147 of file TimerService.h.

Referenced by cancel(), scheduleAt(), scheduleDailyAt(), scheduleDuration(), and scheduleEvery().


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