53 xSemaphoreTake(
lock_, portMAX_DELAY);
55 xSemaphoreGive(
lock_);
68 localtime_r(¤tTime, &now);
69 uint8_t today = now.tm_wday;
70 uint32_t nowSec =
toSeconds({(uint8_t)now.tm_hour, (uint8_t)now.tm_min, (uint8_t)now.tm_sec});
73 for (
int offset = 0; offset < 7; ++offset)
75 uint8_t checkDay = (today + offset) % 7;
76 if (mask & (1 << checkDay))
78 if (offset == 0 && targetSec <= nowSec)
80 return offset * 86400 + ((offset == 0) ? (targetSec - nowSec) : (targetSec + 86400 - nowSec));
97 std::string defaultId =
"at_" + std::to_string(unixTime);
104 uint32_t delaySeconds = (unixTime > now) ? (unixTime - now) : 0;
106 TimerHandle_t handle = xTimerCreate(
"AtTimer", pdMS_TO_TICKS(delaySeconds * 1000), pdFALSE,
new Event(event),
107 [](TimerHandle_t xTimer)
109 Event *evt =
static_cast<Event *
>(pvTimerGetTimerID(xTimer));
115 xTimerDelete(xTimer, 0);
124 xTimerStop(it->second, 0);
125 xTimerDelete(it->second, 0);
126 scheduledJobs.erase(it);
130 xTimerStart(handle, 0);
137 std::string defaultId =
"interval_" + std::to_string((uint32_t)event.
notification.
code());
143 TimerHandle_t handle = xTimerCreate(
"EveryTimer", pdMS_TO_TICKS(intervalMs), pdTRUE,
new Event(event),
144 [](TimerHandle_t xTimer)
146 Event *evt =
static_cast<Event *
>(pvTimerGetTimerID(xTimer));
158 xTimerStart(handle, 0);
165 std::string defaultId =
"daily_" + std::to_string((uint32_t)event.
notification.
code()) +
"_" + std::to_string(
toSeconds(time));
174 TimerHandle_t handle = xTimerCreate(
"DailyJob", pdMS_TO_TICKS(delaySeconds * 1000), pdFALSE,
new Event(event),
175 [](TimerHandle_t xTimer)
177 Event *evt =
static_cast<Event *
>(pvTimerGetTimerID(xTimer));
183 xTimerDelete(xTimer, 0);
191 xTimerStart(handle, 0);
192 TimerJob job{time, days, 0, event, {},
true};
199 const Event &startEvent,
const Event &stopEvent)
201 std::string baseId =
"duration_" + std::to_string((uint32_t)startEvent.
notification.
code());
206 const Event &startEvent,
const Event &stopEvent,
const std::string &baseId)
211 std::string startId = baseId +
"_start";
212 std::string stopId = baseId +
"_stop";
214 TimerHandle_t startHandle = xTimerCreate(
"StartJob", pdMS_TO_TICKS(startDelay * 1000), pdFALSE,
new Event(startEvent),
215 [](TimerHandle_t xTimer)
217 Event *evt =
static_cast<Event *
>(pvTimerGetTimerID(xTimer));
223 xTimerDelete(xTimer, 0);
231 xTimerStart(startHandle, 0);
234 uint32_t stopDelay = startDelay + durationMs / 1000;
236 TimerHandle_t stopHandle = xTimerCreate(
"StopJob", pdMS_TO_TICKS(stopDelay * 1000), pdFALSE,
new Event(stopEvent),
237 [](TimerHandle_t xTimer)
239 Event *evt =
static_cast<Event *
>(pvTimerGetTimerID(xTimer));
245 xTimerDelete(xTimer, 0);
253 xTimerStart(stopHandle, 0);
256 TimerJob job{start, days, durationMs, startEvent, stopEvent,
true};
262 bool success =
false;
266 xTimerStop(it->second, 0);
267 xTimerDelete(it->second, 0);
268 scheduledJobs.erase(it);
290 printf(
"[TimerService] WARNING: scheduled time is in the past (%lld <= %lld)\n", when, now);
294 auto* cb =
new std::function<void()>(std::move(callback));
295 uint32_t delayMs =
static_cast<uint32_t
>((when - now) * 1000);
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));
304 xTimerDelete(xTimer, 0);
308 xTimerStart(handle, 0);
310 printf(
"[TimerService] ERROR: Failed to create xTimer\n");
uint8_t DaysOfWeek
Type alias for a set of days (bitmask).
Event pub/sub manager for embedded applications using FreeRTOS.
Time utility functions for the Pico platform (RP2040/RP2350).
static uint32_t secondsUntilNextMatch(const TimeOfDay &tod, DaysOfWeek mask, time_t currentTime)
static uint32_t toSeconds(const TimeOfDay &tod)
Time-of-day and interval-based scheduler for embedded events.
static constexpr std::uintptr_t getTypeKey()
static time_t now()
Get the current epoch time using platform RTC or AON.
Central service for time-driven scheduling of framework events.
void scheduleAt(time_t unixTime, const Event &event)
Schedule a one-time event at an absolute UNIX timestamp.
void rescheduleDailyJob(const TimerJob &job)
Placeholder for persistence/rescheduling in the future.
void scheduleDailyAt(TimeOfDay time, DaysOfWeek days, const Event &event)
Schedule a recurring event based on time-of-day and day mask.
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.
void withLock(const std::function< void()> &fn)
std::unordered_map< std::string, TimerHandle_t > scheduledJobs
Map of job IDs to TimerHandles.
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 checkMissedEvents(time_t now)
Detect and fire any missed events after a reboot (TBD).
void scheduleEvery(uint32_t intervalMs, const Event &event)
Schedule a repeating event at fixed intervals.
static StaticSemaphore_t lockBuffer_
static TimerService & instance()
Access the singleton instance.
Represents a framework event, optionally carrying payload data.
Notification notification
Notification identifier (system or user)
uint8_t code() const
Get the notification code.
A simple value type representing a time of day (hour, minute, second).
Represents a job scheduled by the TimerService.