diff --git a/libraries/Network/src/NetworkEvents.cpp b/libraries/Network/src/NetworkEvents.cpp index bb02282e9b3..ceb7c5c29e1 100644 --- a/libraries/Network/src/NetworkEvents.cpp +++ b/libraries/Network/src/NetworkEvents.cpp @@ -8,28 +8,6 @@ #include "esp_task.h" #include "esp32-hal.h" -typedef struct NetworkEventCbList { - static network_event_handle_t current_id; - network_event_handle_t id; - NetworkEventCb cb; - NetworkEventFuncCb fcb; - NetworkEventSysCb scb; - arduino_event_id_t event; - - NetworkEventCbList() : id(current_id++), cb(NULL), fcb(NULL), scb(NULL), event(ARDUINO_EVENT_NONE) {} -} NetworkEventCbList_t; -network_event_handle_t NetworkEventCbList::current_id = 1; - -// arduino dont like std::vectors move static here -static std::vector cbEventList; - -static void _network_event_task(void *arg) { - for (;;) { - ((NetworkEvents *)arg)->checkForEvent(); - } - vTaskDelete(NULL); -} - NetworkEvents::NetworkEvents() : _arduino_event_group(NULL), _arduino_event_queue(NULL), _arduino_event_task_handle(NULL) {} NetworkEvents::~NetworkEvents() { @@ -43,8 +21,9 @@ NetworkEvents::~NetworkEvents() { } if (_arduino_event_queue != NULL) { arduino_event_t *event = NULL; + // consume queue while (xQueueReceive(_arduino_event_queue, &event, 0) == pdTRUE) { - free(event); + delete event; } vQueueDelete(_arduino_event_queue); _arduino_event_queue = NULL; @@ -78,7 +57,13 @@ bool NetworkEvents::initNetworkEvents() { } if (!_arduino_event_task_handle) { - xTaskCreateUniversal(_network_event_task, "arduino_events", 4096, this, ESP_TASKD_EVENT_PRIO - 1, &_arduino_event_task_handle, ARDUINO_EVENT_RUNNING_CORE); + xTaskCreateUniversal( [](void* self){ static_cast(self)->_checkForEvent(); }, + "arduino_events", // label + 4096, // event task's stack size + this, + ESP_TASKD_EVENT_PRIO - 1, + &_arduino_event_task_handle, + ARDUINO_EVENT_RUNNING_CORE); if (!_arduino_event_task_handle) { log_e("Network Event Task Start Failed!"); return false; @@ -88,66 +73,76 @@ bool NetworkEvents::initNetworkEvents() { return true; } -bool NetworkEvents::postEvent(arduino_event_t *data) { +bool NetworkEvents::postEvent(const arduino_event_t *data) { if (data == NULL || _arduino_event_queue == NULL) { return false; } - arduino_event_t *event = (arduino_event_t *)malloc(sizeof(arduino_event_t)); + arduino_event_t *event = new arduino_event_t(); if (event == NULL) { log_e("Arduino Event Malloc Failed!"); return false; } + memcpy(event, data, sizeof(arduino_event_t)); if (xQueueSend(_arduino_event_queue, &event, portMAX_DELAY) != pdPASS) { log_e("Arduino Event Send Failed!"); + delete event; // release mem on error return false; } return true; } -void NetworkEvents::checkForEvent() { - arduino_event_t *event = NULL; +void NetworkEvents::_checkForEvent() { + // this task can't run without the queue if (_arduino_event_queue == NULL) { + _arduino_event_task_handle = NULL; + vTaskDelete(NULL); return; } - if (xQueueReceive(_arduino_event_queue, &event, portMAX_DELAY) != pdTRUE) { - return; - } - if (event == NULL) { - return; - } - log_v("Network Event: %d - %s", event->event_id, eventName(event->event_id)); - for (uint32_t i = 0; i < cbEventList.size(); i++) { - NetworkEventCbList_t entry = cbEventList[i]; - if (entry.cb || entry.fcb || entry.scb) { - if (entry.event == (arduino_event_id_t)event->event_id || entry.event == ARDUINO_EVENT_MAX) { - if (entry.cb) { - entry.cb((arduino_event_id_t)event->event_id); - } else if (entry.fcb) { - entry.fcb((arduino_event_id_t)event->event_id, (arduino_event_info_t)event->event_info); - } else { - entry.scb(event); + + for (;;) { + arduino_event_t *event = NULL; + // wait for an event on a queue + if (xQueueReceive(_arduino_event_queue, &event, portMAX_DELAY) != pdTRUE) { + continue; + } + if (event == NULL) { + continue; + } + log_v("Network Event: %d - %s", event->event_id, eventName(event->event_id)); + +#if defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 + std::unique_lock lock(_mtx); +#endif // defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 + + // iterate over registered callbacks + for (auto &i : _cbEventList){ + if (i.cb || i.fcb || i.scb) { + if (i.event == (arduino_event_id_t)event->event_id || i.event == ARDUINO_EVENT_MAX) { + if (i.cb) { + i.cb((arduino_event_id_t)event->event_id); + continue; + } + + if (i.fcb) { + i.fcb((arduino_event_id_t)event->event_id, (arduino_event_info_t)event->event_info); + continue; + } + + i.scb(event); } } } - } - free(event); -} -uint32_t NetworkEvents::findEvent(NetworkEventCb cbEvent, arduino_event_id_t event) { - uint32_t i; +#if defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 + lock.unlock(); +#endif // defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 - if (!cbEvent) { - return cbEventList.size(); + // release the event object's memory + delete event; } - for (i = 0; i < cbEventList.size(); i++) { - NetworkEventCbList_t entry = cbEventList[i]; - if (entry.cb == cbEvent && entry.event == event) { - break; - } - } - return i; + vTaskDelete(NULL); } template static size_t getStdFunctionAddress(std::function f) { @@ -159,55 +154,17 @@ template static size_t getStdFunctionAddress(std::fun return (size_t)fnPointer; } -uint32_t NetworkEvents::findEvent(NetworkEventFuncCb cbEvent, arduino_event_id_t event) { - uint32_t i; - - if (!cbEvent) { - return cbEventList.size(); - } - - for (i = 0; i < cbEventList.size(); i++) { - NetworkEventCbList_t entry = cbEventList[i]; - if (getStdFunctionAddress(entry.fcb) == getStdFunctionAddress(cbEvent) && entry.event == event) { - break; - } - } - return i; -} - -uint32_t NetworkEvents::findEvent(NetworkEventSysCb cbEvent, arduino_event_id_t event) { - uint32_t i; - - if (!cbEvent) { - return cbEventList.size(); - } - - for (i = 0; i < cbEventList.size(); i++) { - NetworkEventCbList_t entry = cbEventList[i]; - if (entry.scb == cbEvent && entry.event == event) { - break; - } - } - return i; -} - network_event_handle_t NetworkEvents::onEvent(NetworkEventCb cbEvent, arduino_event_id_t event) { if (!cbEvent) { return 0; } - if (findEvent(cbEvent, event) < cbEventList.size()) { - log_w("Attempt to add duplicate event handler!"); - return 0; - } +#if defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 + std::lock_guard lock(_mtx); +#endif // defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 - NetworkEventCbList_t newEventHandler; - newEventHandler.cb = cbEvent; - newEventHandler.fcb = NULL; - newEventHandler.scb = NULL; - newEventHandler.event = event; - cbEventList.push_back(newEventHandler); - return newEventHandler.id; + _cbEventList.emplace_back(++_current_id, cbEvent, nullptr, nullptr, event); + return _cbEventList.back().id; } network_event_handle_t NetworkEvents::onEvent(NetworkEventFuncCb cbEvent, arduino_event_id_t event) { @@ -215,18 +172,12 @@ network_event_handle_t NetworkEvents::onEvent(NetworkEventFuncCb cbEvent, arduin return 0; } - if (findEvent(cbEvent, event) < cbEventList.size()) { - log_w("Attempt to add duplicate event handler!"); - return 0; - } +#if defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 + std::lock_guard lock(_mtx); +#endif // defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 - NetworkEventCbList_t newEventHandler; - newEventHandler.cb = NULL; - newEventHandler.fcb = cbEvent; - newEventHandler.scb = NULL; - newEventHandler.event = event; - cbEventList.push_back(newEventHandler); - return newEventHandler.id; + _cbEventList.emplace_back(++_current_id, nullptr, cbEvent, nullptr, event); + return _cbEventList.back().id; } network_event_handle_t NetworkEvents::onEvent(NetworkEventSysCb cbEvent, arduino_event_id_t event) { @@ -234,18 +185,12 @@ network_event_handle_t NetworkEvents::onEvent(NetworkEventSysCb cbEvent, arduino return 0; } - if (findEvent(cbEvent, event) < cbEventList.size()) { - log_w("Attempt to add duplicate event handler!"); - return 0; - } +#if defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 + std::lock_guard lock(_mtx); +#endif // defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 - NetworkEventCbList_t newEventHandler; - newEventHandler.cb = NULL; - newEventHandler.fcb = NULL; - newEventHandler.scb = cbEvent; - newEventHandler.event = event; - cbEventList.push_back(newEventHandler); - return newEventHandler.id; + _cbEventList.emplace_back(++_current_id, nullptr, nullptr, cbEvent, event); + return _cbEventList.back().id; } network_event_handle_t NetworkEvents::onSysEvent(NetworkEventCb cbEvent, arduino_event_id_t event) { @@ -253,18 +198,12 @@ network_event_handle_t NetworkEvents::onSysEvent(NetworkEventCb cbEvent, arduino return 0; } - if (findEvent(cbEvent, event) < cbEventList.size()) { - log_w("Attempt to add duplicate event handler!"); - return 0; - } +#if defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 + std::lock_guard lock(_mtx); +#endif // defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 - NetworkEventCbList_t newEventHandler; - newEventHandler.cb = cbEvent; - newEventHandler.fcb = NULL; - newEventHandler.scb = NULL; - newEventHandler.event = event; - cbEventList.insert(cbEventList.begin(), newEventHandler); - return newEventHandler.id; + _cbEventList.emplace(_cbEventList.begin(), ++_current_id, cbEvent, nullptr, nullptr, event); + return _cbEventList.front().id; } network_event_handle_t NetworkEvents::onSysEvent(NetworkEventFuncCb cbEvent, arduino_event_id_t event) { @@ -272,18 +211,12 @@ network_event_handle_t NetworkEvents::onSysEvent(NetworkEventFuncCb cbEvent, ard return 0; } - if (findEvent(cbEvent, event) < cbEventList.size()) { - log_w("Attempt to add duplicate event handler!"); - return 0; - } +#if defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 + std::lock_guard lock(_mtx); +#endif // defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 - NetworkEventCbList_t newEventHandler; - newEventHandler.cb = NULL; - newEventHandler.fcb = cbEvent; - newEventHandler.scb = NULL; - newEventHandler.event = event; - cbEventList.insert(cbEventList.begin(), newEventHandler); - return newEventHandler.id; + _cbEventList.emplace(_cbEventList.begin(), ++_current_id, nullptr, cbEvent, nullptr, event); + return _cbEventList.front().id; } network_event_handle_t NetworkEvents::onSysEvent(NetworkEventSysCb cbEvent, arduino_event_id_t event) { @@ -291,77 +224,56 @@ network_event_handle_t NetworkEvents::onSysEvent(NetworkEventSysCb cbEvent, ardu return 0; } - if (findEvent(cbEvent, event) < cbEventList.size()) { - log_w("Attempt to add duplicate event handler!"); - return 0; - } +#if defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 + std::lock_guard lock(_mtx); +#endif // defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 - NetworkEventCbList_t newEventHandler; - newEventHandler.cb = NULL; - newEventHandler.fcb = NULL; - newEventHandler.scb = cbEvent; - newEventHandler.event = event; - cbEventList.insert(cbEventList.begin(), newEventHandler); - return newEventHandler.id; + _cbEventList.emplace(_cbEventList.begin(), ++_current_id, nullptr, nullptr, cbEvent, event); + return _cbEventList.front().id; } void NetworkEvents::removeEvent(NetworkEventCb cbEvent, arduino_event_id_t event) { - uint32_t i; - if (!cbEvent) { return; } - i = findEvent(cbEvent, event); - if (i >= cbEventList.size()) { - log_w("Event handler not found!"); - return; - } +#if defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 + std::lock_guard lock(_mtx); +#endif // defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 - cbEventList.erase(cbEventList.begin() + i); + _cbEventList.erase(std::remove_if(_cbEventList.begin(), _cbEventList.end(), [cbEvent, event](const NetworkEventCbList_t& e) { return e.cb == cbEvent && e.event == event; }), _cbEventList.end()); } void NetworkEvents::removeEvent(NetworkEventFuncCb cbEvent, arduino_event_id_t event) { - uint32_t i; - if (!cbEvent) { return; } - i = findEvent(cbEvent, event); - if (i >= cbEventList.size()) { - log_w("Event handler not found!"); - return; - } +#if defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 + std::lock_guard lock(_mtx); +#endif // defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 - cbEventList.erase(cbEventList.begin() + i); + _cbEventList.erase(std::remove_if(_cbEventList.begin(), _cbEventList.end(), [cbEvent, event](const NetworkEventCbList_t& e) { return getStdFunctionAddress(e.fcb) == getStdFunctionAddress(cbEvent) && e.event == event; }), _cbEventList.end()); } void NetworkEvents::removeEvent(NetworkEventSysCb cbEvent, arduino_event_id_t event) { - uint32_t i; - if (!cbEvent) { return; } - i = findEvent(cbEvent, event); - if (i >= cbEventList.size()) { - log_w("Event handler not found!"); - return; - } +#if defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 + std::lock_guard lock(_mtx); +#endif // defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 - cbEventList.erase(cbEventList.begin() + i); + _cbEventList.erase(std::remove_if(_cbEventList.begin(), _cbEventList.end(), [cbEvent, event](const NetworkEventCbList_t& e) { return e.scb == cbEvent && e.event == event; }), _cbEventList.end()); } void NetworkEvents::removeEvent(network_event_handle_t id) { - for (uint32_t i = 0; i < cbEventList.size(); i++) { - NetworkEventCbList_t entry = cbEventList[i]; - if (entry.id == id) { - cbEventList.erase(cbEventList.begin() + i); - return; - } - } - log_w("Event handler not found!"); +#if defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 + std::lock_guard lock(_mtx); +#endif // defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 + + _cbEventList.erase(std::remove_if(_cbEventList.begin(), _cbEventList.end(), [id](const NetworkEventCbList_t& e) { return e.id == id; }), _cbEventList.end()); } int NetworkEvents::setStatusBits(int bits) { @@ -380,7 +292,7 @@ int NetworkEvents::clearStatusBits(int bits) { return xEventGroupClearBits(_arduino_event_group, bits); } -int NetworkEvents::getStatusBits() { +int NetworkEvents::getStatusBits() const { if (!_arduino_event_group) { return _initial_bits; } diff --git a/libraries/Network/src/NetworkEvents.h b/libraries/Network/src/NetworkEvents.h index ac324d19841..dd03a3bcefc 100644 --- a/libraries/Network/src/NetworkEvents.h +++ b/libraries/Network/src/NetworkEvents.h @@ -16,6 +16,9 @@ #include "freertos/queue.h" #include "freertos/semphr.h" #include "freertos/event_groups.h" +#if defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 +#include +#endif // defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 #if SOC_WIFI_SUPPORTED #include "esp_wifi_types.h" @@ -24,8 +27,8 @@ #endif #if SOC_WIFI_SUPPORTED -static const int WIFI_SCANNING_BIT = BIT0; -static const int WIFI_SCAN_DONE_BIT = BIT1; +constexpr int WIFI_SCANNING_BIT = BIT0; +constexpr int WIFI_SCAN_DONE_BIT = BIT1; #endif #define NET_HAS_IP6_GLOBAL_BIT 0 @@ -33,7 +36,7 @@ static const int WIFI_SCAN_DONE_BIT = BIT1; ESP_EVENT_DECLARE_BASE(ARDUINO_EVENTS); typedef enum { - ARDUINO_EVENT_NONE, + ARDUINO_EVENT_NONE = 0, ARDUINO_EVENT_ETH_START, ARDUINO_EVENT_ETH_STOP, ARDUINO_EVENT_ETH_CONNECTED, @@ -42,10 +45,11 @@ typedef enum { ARDUINO_EVENT_ETH_LOST_IP, ARDUINO_EVENT_ETH_GOT_IP6, #if SOC_WIFI_SUPPORTED - ARDUINO_EVENT_WIFI_OFF, + ARDUINO_EVENT_WIFI_OFF = 100, ARDUINO_EVENT_WIFI_READY, ARDUINO_EVENT_WIFI_SCAN_DONE, - ARDUINO_EVENT_WIFI_STA_START, + ARDUINO_EVENT_WIFI_FTM_REPORT, + ARDUINO_EVENT_WIFI_STA_START = 110, ARDUINO_EVENT_WIFI_STA_STOP, ARDUINO_EVENT_WIFI_STA_CONNECTED, ARDUINO_EVENT_WIFI_STA_DISCONNECTED, @@ -53,24 +57,23 @@ typedef enum { ARDUINO_EVENT_WIFI_STA_GOT_IP, ARDUINO_EVENT_WIFI_STA_GOT_IP6, ARDUINO_EVENT_WIFI_STA_LOST_IP, - ARDUINO_EVENT_WIFI_AP_START, + ARDUINO_EVENT_WIFI_AP_START = 130, ARDUINO_EVENT_WIFI_AP_STOP, ARDUINO_EVENT_WIFI_AP_STACONNECTED, ARDUINO_EVENT_WIFI_AP_STADISCONNECTED, ARDUINO_EVENT_WIFI_AP_STAIPASSIGNED, ARDUINO_EVENT_WIFI_AP_PROBEREQRECVED, ARDUINO_EVENT_WIFI_AP_GOT_IP6, - ARDUINO_EVENT_WIFI_FTM_REPORT, - ARDUINO_EVENT_WPS_ER_SUCCESS, + ARDUINO_EVENT_WPS_ER_SUCCESS = 140, ARDUINO_EVENT_WPS_ER_FAILED, ARDUINO_EVENT_WPS_ER_TIMEOUT, ARDUINO_EVENT_WPS_ER_PIN, ARDUINO_EVENT_WPS_ER_PBC_OVERLAP, - ARDUINO_EVENT_SC_SCAN_DONE, + ARDUINO_EVENT_SC_SCAN_DONE = 150, ARDUINO_EVENT_SC_FOUND_CHANNEL, ARDUINO_EVENT_SC_GOT_SSID_PSWD, ARDUINO_EVENT_SC_SEND_ACK_DONE, - ARDUINO_EVENT_PROV_INIT, + ARDUINO_EVENT_PROV_INIT = 160, ARDUINO_EVENT_PROV_DEINIT, ARDUINO_EVENT_PROV_START, ARDUINO_EVENT_PROV_END, @@ -78,7 +81,7 @@ typedef enum { ARDUINO_EVENT_PROV_CRED_FAIL, ARDUINO_EVENT_PROV_CRED_SUCCESS, #endif - ARDUINO_EVENT_PPP_START, + ARDUINO_EVENT_PPP_START = 200, ARDUINO_EVENT_PPP_STOP, ARDUINO_EVENT_PPP_CONNECTED, ARDUINO_EVENT_PPP_DISCONNECTED, @@ -110,36 +113,122 @@ typedef union { #endif } arduino_event_info_t; -typedef struct { +/** + * @brief struct combines arduino event id and event's data object + * + */ +struct arduino_event_t { arduino_event_id_t event_id; arduino_event_info_t event_info; -} arduino_event_t; - -typedef void (*NetworkEventCb)(arduino_event_id_t event); -typedef std::function NetworkEventFuncCb; -typedef void (*NetworkEventSysCb)(arduino_event_t *event); +}; -typedef size_t network_event_handle_t; +// type aliases +using NetworkEventCb = void(*)(arduino_event_id_t event); +using NetworkEventFuncCb = std::function; +using NetworkEventSysCb = void(*)(arduino_event_t *event); +using network_event_handle_t = size_t; +/** + * @brief Class that provides network events callback handling + * it registers user callback functions for event handling, + * maintans the queue of events and propagates the event amoung subscribed callbacks + * callback are called in the context of a dedicated task consuming the queue + * + */ class NetworkEvents { public: NetworkEvents(); ~NetworkEvents(); + /** + * @brief register callback function to be executed on arduino event(s) + * @note if same handler is registered twice or more than same handler would be called twice or more times + * + * @param cbEvent static callback function + * @param event event to process, any event by default + * @return network_event_handle_t + */ network_event_handle_t onEvent(NetworkEventCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX); + + /** + * @brief register functional callback to be executed on arduino event(s) + * also used for lambda callbacks + * @note if same handler is registered twice or more than same handler would be called twice or more times + * + * @param cbEvent static callback function + * @param event event to process, any event by default + * @return network_event_handle_t + */ network_event_handle_t onEvent(NetworkEventFuncCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX); + + /** + * @brief register static system callback to be executed on arduino event(s) + * callback function would be supplied with a pointer to arduino_event_t structure as an argument + * + * @note if same handler is registered twice or more than same handler would be called twice or more times + * + * @param cbEvent static callback function + * @param event event to process, any event by default + * @return network_event_handle_t + */ network_event_handle_t onEvent(NetworkEventSysCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX); + + /** + * @brief unregister static function callback + * @note a better way to unregister callbacks is to save/unregister via network_event_handle_t + * + * @param cbEvent static callback function + * @param event event to process, any event by default + */ void removeEvent(NetworkEventCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX); - void removeEvent(NetworkEventFuncCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX); + + /** + * @brief unregister functional callback + * @note a better way to unregister callbacks is to save/unregister via network_event_handle_t + * @note this does not work for lambda's! Do unregister via network_event_handle_t + * + * @param cbEvent functional callback + * @param event event to process, any event by default + */ + void removeEvent(NetworkEventFuncCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX) __attribute__((deprecated("removing functional callbacks via pointer is deprecated, use removeEvent(network_event_handle_t) instead"))); + + /** + * @brief unregister static system function callback + * @note a better way to unregister callbacks is to save/unregister via network_event_handle_t + * + * @param cbEvent static callback function + * @param event event to process, any event by default + */ void removeEvent(NetworkEventSysCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX); + + /** + * @brief unregister event callback via handler + * + * @param cbEvent static callback function + * @param event event to process, any event by default + */ void removeEvent(network_event_handle_t event_handle); - const char *eventName(arduino_event_id_t id); + /** + * @brief get a human-readable name of an event by it's id + * + * @param id event id code + * @return const char* event name string + */ + static const char *eventName(arduino_event_id_t id); - void checkForEvent(); - bool postEvent(arduino_event_t *event); + /** + * @brief post an event to the queue + * and propagade and event to subscribed handlers + * @note posting an event will trigger context switch from a lower priority task + * + * @param event a pointer to arduino_event_t struct + * @return true if event was queued susccessfuly + * @return false on memrory allocation error or queue is full + */ + bool postEvent(const arduino_event_t *event); - int getStatusBits(); + int getStatusBits() const; int waitStatusBits(int bits, uint32_t timeout_ms); int setStatusBits(int bits); int clearStatusBits(int bits); @@ -155,15 +244,51 @@ class NetworkEvents { protected: bool initNetworkEvents(); - uint32_t findEvent(NetworkEventCb cbEvent, arduino_event_id_t event); - uint32_t findEvent(NetworkEventFuncCb cbEvent, arduino_event_id_t event); - uint32_t findEvent(NetworkEventSysCb cbEvent, arduino_event_id_t event); + // same as onEvent() but places newly added handler at the begining of registered events list network_event_handle_t onSysEvent(NetworkEventCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX); + // same as onEvent() but places newly added handler at the begining of registered events list network_event_handle_t onSysEvent(NetworkEventFuncCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX); + // same as onEvent() but places newly added handler at the begining of registered events list network_event_handle_t onSysEvent(NetworkEventSysCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX); private: + /** + * @brief an object holds callback's definitions: + * - callback id + * - callback function pointers + * - binded event id + * + */ + struct NetworkEventCbList_t { + network_event_handle_t id; + NetworkEventCb cb; + NetworkEventFuncCb fcb; + NetworkEventSysCb scb; + arduino_event_id_t event; + + explicit NetworkEventCbList_t(network_event_handle_t id, NetworkEventCb cb = nullptr, NetworkEventFuncCb fcb = nullptr, NetworkEventSysCb scb = nullptr, arduino_event_id_t event = ARDUINO_EVENT_MAX) : + id(id), cb(cb), fcb(fcb), scb(scb), event(event) {} + }; + + // define initial id's value + network_event_handle_t _current_id{0}; + EventGroupHandle_t _arduino_event_group; QueueHandle_t _arduino_event_queue; TaskHandle_t _arduino_event_task_handle; + + // registred events callbacks containter + std::vector _cbEventList; + +#if defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 + // containter access mutex + std::mutex _mtx; +#endif // defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1 + + /** + * @brief task function that picks events from an event queue and calls registered callbacks + * + */ + void _checkForEvent(); + };