Uniot Core
0.8.1
Loading...
Searching...
No Matches
Uniot.h
Go to the documentation of this file.
1/*
2 * This is a part of the Uniot project.
3 * Copyright (C) 2016-2025 Uniot <contact@uniot.io>
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#pragma once
20
21#include <AppKit.h>
22#include <Arduino.h>
23#include <Credentials.h>
24#include <Date.h>
25#include <EventBus.h>
26#include <Logger.h>
27#include <TaskScheduler.h>
28
71
90class UniotCore {
91 public:
92 using TimerId = uint32_t;
93 using ListenerId = uint32_t;
94
95 static constexpr TimerId INVALID_TIMER_ID = 0;
96 static constexpr ListenerId INVALID_LISTENER_ID = 0;
97
105 UniotCore() : mScheduler(), mEventBus(FOURCC(main)), mpNetworkControllerConfig(nullptr) {}
106
117 void configWiFiResetButton(uint8_t pinBtn, uint8_t activeLevelBtn = LOW, bool registerLispBtn = true) {
118 _createNetworkControllerConfig();
119 mpNetworkControllerConfig->pinBtn = pinBtn;
120 mpNetworkControllerConfig->activeLevelBtn = activeLevelBtn;
121 mpNetworkControllerConfig->registerLispBtn = registerLispBtn;
122 }
123
136 void configWiFiStatusLed(uint8_t pinLed, uint8_t activeLevelLed = HIGH) {
137 _createNetworkControllerConfig();
138 mpNetworkControllerConfig->pinLed = pinLed;
139 mpNetworkControllerConfig->activeLevelLed = activeLevelLed;
140 }
141
151 void configWiFiResetOnReboot(uint8_t maxRebootCount, uint32_t rebootWindowMs = 10000) {
152 _createNetworkControllerConfig();
153 mpNetworkControllerConfig->maxRebootCount = maxRebootCount;
154 mpNetworkControllerConfig->rebootWindowMs = rebootWindowMs;
155 }
156
165 void configWiFiCredentials(const String& ssid, const String& password = "") {
166 auto success = getAppKit().setWiFiCredentials(ssid, password);
167 UNIOT_LOG_ERROR_IF(!success, "Failed to set WiFi credentials");
168 }
169
178 void configUser(const String& user) {
179 auto success = getAppKit().setUserId(user);
180 UNIOT_LOG_ERROR_IF(!success, "Failed to set user ID");
181 }
182
191 void enablePeriodicDateSave(uint32_t periodSeconds = 5 * 60) {
192 if (periodSeconds > 0) {
194 mScheduler.push("store_date", taskStoreDate);
195 taskStoreDate->attach(periodSeconds * 1000L);
196 }
197 }
198
207 void addLispPrimitive(Primitive* primitive) {
208 getAppKit().getLisp().pushPrimitive(primitive);
209 }
210
222
232 void publishLispEvent(const String& eventID, int32_t value) {
233 getAppKit().publishLispEvent(eventID, value);
234 }
235
244 template <typename... Pins>
245 void registerLispDigitalOutput(uint8_t first, Pins... pins) {
247 }
248
257 template <typename... Pins>
258 void registerLispDigitalInput(uint8_t first, Pins... pins) {
260 }
261
270 template <typename... Pins>
271 void registerLispAnalogInput(uint8_t first, Pins... pins) {
273 }
274
283 template <typename... Pins>
284 void registerLispAnalogOutput(uint8_t first, Pins... pins) {
286 }
287
300
311 bool registerLispObject(const String& primitiveName, uniot::RecordPtr link, uint32_t id = FOURCC(____)) {
312 return uniot::PrimitiveExpeditor::getRegisterManager().link(primitiveName, link, id);
313 }
314
325 TimerId setInterval(std::function<void()> callback, uint32_t intervalMs, short times = 0) {
326 if (!callback) {
327 return INVALID_TIMER_ID;
328 }
329
330 auto id = _generateTimerId();
331 auto task = uniot::TaskScheduler::make([this, id, callback = std::move(callback)](uniot::SchedulerTask&, short remainingTimes) {
332 callback();
333
334 if (!remainingTimes) {
335 mActiveTimers.remove(id);
336 }
337 });
338
339 mActiveTimers.put(id, task);
340 mScheduler.push(nullptr, task);
341 task->attach(intervalMs, times);
342 return id;
343 }
344
354 TimerId setTimeout(std::function<void()> callback, uint32_t timeoutMs) {
355 return setInterval(std::move(callback), timeoutMs, 1);
356 }
357
366 TimerId setImmediate(std::function<void()> callback) {
367 return setTimeout(std::move(callback), 1);
368 }
369
379 if (id == INVALID_TIMER_ID) {
380 return false;
381 }
382
383 auto task = mActiveTimers.get(id, nullptr);
384 if (task) {
385 task->detach();
386 return mActiveTimers.remove(id);
387 }
388 return false;
389 }
390
399 if (id == INVALID_TIMER_ID) {
400 return false;
401 }
402
403 auto task = mActiveTimers.get(id, nullptr);
404 return task && task->isAttached();
405 }
406
415 return mActiveTimers.calcSize();
416 }
417
429 auto task = uniot::TaskScheduler::make(std::move(callback));
430 mScheduler.push(name, task);
431 return task;
432 }
433
444 template <typename... Topics>
445 ListenerId addSystemListener(std::function<void(unsigned int, int)> callback, unsigned int firstTopic, Topics... otherTopics) {
446 if (!callback) {
447 return INVALID_LISTENER_ID;
448 }
449
450 unsigned int topics[] = {firstTopic, static_cast<unsigned int>(otherTopics)...};
451 size_t count = sizeof...(otherTopics) + 1;
452
454 for (size_t i = 0; i < count; ++i) {
455 listener->listenToEvent(topics[i]);
456 }
457
458 if (mEventBus.registerEntity(listener.get())) {
459 auto id = _generateListenerId();
460 mActiveListeners.put(id, listener);
461 return id;
462 }
463
464 return INVALID_LISTENER_ID;
465 }
466
475 if (id == INVALID_LISTENER_ID) {
476 return false;
477 }
478
479 auto listener = mActiveListeners.get(id, nullptr);
480 if (listener) {
481 mEventBus.unregisterEntity(listener.get());
482 return mActiveListeners.remove(id);
483 }
484 return false;
485 }
486
496 template <typename... Topics>
497 size_t removeSystemListeners(unsigned int firstTopic, Topics... otherTopics) {
498 unsigned int topics[] = {firstTopic, static_cast<unsigned int>(otherTopics)...};
499 size_t topicCount = sizeof...(otherTopics) + 1;
500 size_t removedCount = 0;
501
502 mActiveListeners.begin();
503 while (!mActiveListeners.isEnd()) {
504 auto listener = mActiveListeners.current().second;
505 bool shouldRemove = false;
506
507 if (listener) {
508 for (size_t i = 0; i < topicCount; ++i) {
509 if (listener->isListeningToEvent(topics[i])) {
510 shouldRemove = true;
511 break;
512 }
513 }
514 }
515
516 if (shouldRemove) {
517 mEventBus.unregisterEntity(listener.get());
518 mActiveListeners.deleteCurrent();
519 removedCount++;
520 } else {
521 mActiveListeners.next();
522 }
523 }
524
525 return removedCount;
526 }
527
537 if (id == INVALID_LISTENER_ID) {
538 return false;
539 }
540
541 return mActiveListeners.exist(id);
542 }
543
552 return mActiveListeners.calcSize();
553 }
554
563 void emitSystemEvent(unsigned int topic, int message) {
564 mEventBus.emitEvent(topic, message);
565 }
566
575 ListenerId addWifiStatusLedListener(std::function<void(bool)> callback) {
576 if (!callback) {
577 return INVALID_LISTENER_ID;
578 }
579
580 return addSystemListener(
581 [callback = std::move(callback)](unsigned int topic, int message) {
583 callback(message != 0);
584 }
585 },
587 }
588
596 void begin(uint32_t eventBusTaskPeriod = 10) {
598
599 auto& app = uniot::AppKit::getInstance();
600
601 if (mpNetworkControllerConfig) {
602 app.configureNetworkController(*mpNetworkControllerConfig);
603 _deleteNetworkControllerConfig();
604 }
605
606 mEventBus.registerKit(app);
607
608 auto taskHandleEventBus = uniot::TaskScheduler::make(mEventBus);
609 mScheduler.push("event_bus", taskHandleEventBus);
610 taskHandleEventBus->attach(eventBusTaskPeriod);
611
612 mScheduler.push(app);
613 app.attach();
614 }
615
623 void loop() {
624 mScheduler.loop();
625 }
626
637
646 return mEventBus;
647 }
648
657 return mScheduler;
658 }
659
660 private:
667 void _createNetworkControllerConfig() {
668 if (!mpNetworkControllerConfig) {
670 mpNetworkControllerConfig->pinBtn = UINT8_MAX; // Not used by default
671 mpNetworkControllerConfig->activeLevelBtn = LOW;
672 mpNetworkControllerConfig->pinLed = UINT8_MAX; // Not used by default
673 mpNetworkControllerConfig->activeLevelLed = HIGH;
674 mpNetworkControllerConfig->maxRebootCount = 5;
675 mpNetworkControllerConfig->rebootWindowMs = 10000;
676 mpNetworkControllerConfig->registerLispBtn = true;
677 }
678 }
679
686 void _deleteNetworkControllerConfig() {
687 if (mpNetworkControllerConfig) {
688 mpNetworkControllerConfig.reset(nullptr);
689 }
690 }
691
699 TimerId _generateTimerId() {
700 static TimerId nextId = 1;
701 return nextId++;
702 }
703
711 ListenerId _generateListenerId() {
712 static ListenerId nextId = 1;
713 return nextId++;
714 }
715
716 uniot::TaskScheduler mScheduler;
717 uniot::CoreEventBus mEventBus;
718 uniot::Map<TimerId, uniot::TaskScheduler::TaskPtr> mActiveTimers;
719 uniot::Map<ListenerId, uniot::SharedPointer<uniot::CoreCallbackEventListener>> mActiveListeners;
721};
722
730extern UniotCore Uniot;
731
Main API class for the Uniot IoT platform.
Definition Uniot.h:90
TimerId setImmediate(std::function< void()> callback)
Execute a callback on the next scheduler cycle.
Definition Uniot.h:366
bool cancelTimer(TimerId id)
Cancel an active timer.
Definition Uniot.h:378
void loop()
Process scheduled tasks and events.
Definition Uniot.h:623
int getActiveListenersCount() const
Get the number of active event listeners.
Definition Uniot.h:551
void configUser(const String &user)
Configure user identification.
Definition Uniot.h:178
ListenerId addWifiStatusLedListener(std::function< void(bool)> callback)
Add a WiFi status LED listener.
Definition Uniot.h:575
ListenerId addSystemListener(std::function< void(unsigned int, int)> callback, unsigned int firstTopic, Topics... otherTopics)
Add a system event listener.
Definition Uniot.h:445
void setLispEventInterceptor(uniot::LispEventInterceptor interceptor)
Set event interceptor for Lisp interpreter.
Definition Uniot.h:219
uniot::CoreEventBus & getEventBus()
Get access to the event bus.
Definition Uniot.h:645
TimerId setInterval(std::function< void()> callback, uint32_t intervalMs, short times=0)
Create a repeating timer.
Definition Uniot.h:325
UniotCore()
Construct a new UniotCore instance.
Definition Uniot.h:105
bool isTimerActive(TimerId id)
Check if a timer is currently active.
Definition Uniot.h:398
void registerLispAnalogOutput(uint8_t first, Pins... pins)
Register GPIO pins as analog outputs for Lisp access.
Definition Uniot.h:284
static constexpr TimerId INVALID_TIMER_ID
Invalid timer ID constant.
Definition Uniot.h:95
void registerLispDigitalOutput(uint8_t first, Pins... pins)
Register GPIO pins as digital outputs for Lisp access.
Definition Uniot.h:245
static constexpr ListenerId INVALID_LISTENER_ID
Invalid listener ID constant.
Definition Uniot.h:96
uint32_t ListenerId
Type for event listener identifiers.
Definition Uniot.h:93
uniot::TaskScheduler::TaskPtr createTask(const char *name, uniot::SchedulerTask::SchedulerTaskCallback callback)
Create a named task for custom scheduling.
Definition Uniot.h:428
bool removeSystemListener(ListenerId id)
Remove a system event listener.
Definition Uniot.h:474
void addLispPrimitive(Primitive *primitive)
Add a custom primitive to the Lisp interpreter.
Definition Uniot.h:207
void registerLispAnalogInput(uint8_t first, Pins... pins)
Register GPIO pins as analog inputs for Lisp access.
Definition Uniot.h:271
void configWiFiCredentials(const String &ssid, const String &password="")
Configure WiFi network credentials.
Definition Uniot.h:165
void begin(uint32_t eventBusTaskPeriod=10)
Initialize and start the Uniot platform.
Definition Uniot.h:596
uniot::AppKit & getAppKit()
Get access to the application kit.
Definition Uniot.h:634
bool registerLispObject(const String &primitiveName, uniot::RecordPtr link, uint32_t id=FOURCC(____))
Register a generic object with the Lisp interpreter.
Definition Uniot.h:311
bool isSystemListenerActive(ListenerId id)
Check if a system listener is active.
Definition Uniot.h:536
void emitSystemEvent(unsigned int topic, int message)
Emit a system event.
Definition Uniot.h:563
uniot::TaskScheduler & getScheduler()
Get access to the task scheduler.
Definition Uniot.h:656
void publishLispEvent(const String &eventID, int32_t value)
Publish an event to the Lisp interpreter.
Definition Uniot.h:232
void configWiFiResetOnReboot(uint8_t maxRebootCount, uint32_t rebootWindowMs=10000)
Configure automatic WiFi reset on repeated reboots.
Definition Uniot.h:151
void configWiFiResetButton(uint8_t pinBtn, uint8_t activeLevelBtn=LOW, bool registerLispBtn=true)
Configure WiFi reset button.
Definition Uniot.h:117
size_t removeSystemListeners(unsigned int firstTopic, Topics... otherTopics)
Remove all listeners for specific topics.
Definition Uniot.h:497
int getActiveTimersCount() const
Get the number of active timers.
Definition Uniot.h:414
uint32_t TimerId
Type for timer identifiers.
Definition Uniot.h:92
void configWiFiStatusLed(uint8_t pinLed, uint8_t activeLevelLed=HIGH)
Configure WiFi status LED.
Definition Uniot.h:136
void registerLispDigitalInput(uint8_t first, Pins... pins)
Register GPIO pins as digital inputs for Lisp access.
Definition Uniot.h:258
TimerId setTimeout(std::function< void()> callback, uint32_t timeoutMs)
Create a one-shot timer.
Definition Uniot.h:354
bool registerLispButton(uniot::Button *button, uint32_t id=FOURCC(_btn))
Register a button object with the Lisp interpreter.
Definition Uniot.h:297
void enablePeriodicDateSave(uint32_t periodSeconds=5 *60)
Enable periodic saving of date/time information.
Definition Uniot.h:191
Definition AppKit.h:80
bool setUserId(const String &userId)
Set the user identifier for device association.
Definition AppKit.h:147
bool setWiFiCredentials(const String &ssid, const String &password)
Set WiFi network credentials.
Definition AppKit.h:134
void setLispEventInterceptor(LispEventInterceptor interceptor)
Set event interceptor for Lisp interpreter.
Definition AppKit.h:322
void publishLispEvent(const String &eventID, int32_t value)
Publish an event to the Lisp interpreter.
Definition AppKit.h:335
unLisp & getLisp()
Get the Lisp interpreter instance.
Definition AppKit.h:105
Definition Button.h:54
static RegisterManager & getRegisterManager()
Gets the static register manager instance.
Definition PrimitiveExpeditor.h:71
void setDigitalOutput(uint8_t first, Args... args)
Sets one or more pins as digital outputs.
Definition RegisterManager.h:74
void setAnalogInput(uint8_t first, Args... args)
Sets one or more pins as analog inputs.
Definition RegisterManager.h:86
void setDigitalInput(uint8_t first, Args... args)
Sets one or more pins as digital inputs.
Definition RegisterManager.h:62
void setAnalogOutput(uint8_t first, Args... args)
Sets one or more pins as analog outputs.
Definition RegisterManager.h:98
bool link(const String &name, RecordPtr link, uint32_t id=FOURCC(____))
Links an object to a named register.
Definition RegisterManager.h:111
Definition TaskScheduler.h:67
std::function< void(SchedulerTask &, short)> SchedulerTaskCallback
Callback function signature for scheduled tasks.
Definition TaskScheduler.h:75
static Date & getInstance()
Definition Singleton.h:73
Definition TaskScheduler.h:164
unLisp * pushPrimitive(Primitive *primitive)
Add a new primitive function to the Lisp environment.
Definition unLisp.h:295
std::unique_ptr< T > UniquePointer
Type alias for std::unique_ptr with cleaner syntax.
Definition Common.h:152
auto MakeUnique(Args &&...args) -> decltype(std::make_unique< T >(std::forward< Args >(args)...))
Creates a unique pointer instance, alias for std::make_unique.
Definition Common.h:179
#define FOURCC(name)
Creates a FourCC constant from a string literal.
Definition Common.h:107
auto MakeShared(Args &&...args) -> decltype(std::make_shared< T >(std::forward< Args >(args)...))
Creates a shared pointer instance, alias for std::make_shared.
Definition Common.h:174
EventBus< unsigned int, int, Bytes > CoreEventBus
Standard EventBus configuration used throughout the core system.
Definition EventBus.h:211
#define UNIOT_LOG_SET_READY()
Initialize the logging system.
Definition Logger.h:122
#define UNIOT_LOG_ERROR_IF(log_cond, log...)
Conditionally log an ERROR level message Used for critical errors that may prevent normal operation....
Definition Logger.h:234
ObjectRegisterRecord * RecordPtr
Type alias for ObjectRegisterRecord pointers for better readability.
Definition ObjectRegister.h:33
SharedPointer< SchedulerTask > TaskPtr
Shared pointer type for scheduler tasks.
Definition TaskScheduler.h:171
static TaskPtr make(SchedulerTask::SchedulerTaskCallback callback)
Static factory method to create a task with a callback.
Definition TaskScheduler.h:193
constexpr const char * bclicked
Primitive for detecting button click events.
Definition DefaultPrimitives.h:80
UniotCore Uniot
Global Uniot platform instance.
Definition Uniot.cpp:23
@ WIFI_STATUS_LED
LED status indicators for network state.
Definition NetworkEvents.h:75
std::function< bool(const LispEvent &event)> LispEventInterceptor
Definition LispDevice.h:41