Skip to content

Commit 52a178d

Browse files
committed
feat(NetworkEvents lib) reuse ESP IDF's event bus notifications
ESP IDF has very similar implementation of event bus ti propagate messages to subscribers, it consists of same set of componets - a queue and a task to execute subscriber's callbacks. Reusing it for Arduino networking events could give some benefits: - a unified event exchange bus between arduino and IDF components - save resources for extra Task stack and Queue to handle Arduino's own event bus
1 parent bda7c48 commit 52a178d

File tree

3 files changed

+68
-133
lines changed

3 files changed

+68
-133
lines changed

Diff for: libraries/Network/src/NetworkEvents.cpp

+43-104
Original file line numberDiff line numberDiff line change
@@ -3,39 +3,24 @@
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
6+
#include <algorithm>
67
#include "NetworkEvents.h"
7-
#include "NetworkManager.h"
8-
#include "esp_task.h"
98
#include "esp32-hal.h"
109

11-
#ifndef ARDUINO_NETWORK_EVENT_TASK_STACK_SIZE
12-
#define ARDUINO_NETWORK_EVENT_TASK_STACK_SIZE 4096
13-
#endif
14-
15-
NetworkEvents::NetworkEvents() : _arduino_event_group(NULL), _arduino_event_queue(NULL), _arduino_event_task_handle(NULL) {}
10+
ESP_EVENT_DEFINE_BASE(ARDUINO_EVENTS);
1611

1712
NetworkEvents::~NetworkEvents() {
18-
if (_arduino_event_task_handle != NULL) {
19-
vTaskDelete(_arduino_event_task_handle);
20-
_arduino_event_task_handle = NULL;
21-
}
2213
if (_arduino_event_group != NULL) {
2314
vEventGroupDelete(_arduino_event_group);
2415
_arduino_event_group = NULL;
2516
}
26-
if (_arduino_event_queue != NULL) {
27-
arduino_event_t *event = NULL;
28-
// consume queue
29-
while (xQueueReceive(_arduino_event_queue, &event, 0) == pdTRUE) {
30-
delete event;
31-
}
32-
vQueueDelete(_arduino_event_queue);
33-
_arduino_event_queue = NULL;
17+
// unregister event bus handler
18+
if (_evt_handler){
19+
esp_event_handler_instance_unregister(ARDUINO_EVENTS, ESP_EVENT_ANY_ID, _evt_handler);
20+
_evt_handler = nullptr;
3421
}
3522
}
3623

37-
static uint32_t _initial_bits = 0;
38-
3924
bool NetworkEvents::initNetworkEvents() {
4025
if (!_arduino_event_group) {
4126
_arduino_event_group = xEventGroupCreate();
@@ -46,108 +31,63 @@ bool NetworkEvents::initNetworkEvents() {
4631
xEventGroupSetBits(_arduino_event_group, _initial_bits);
4732
}
4833

49-
if (!_arduino_event_queue) {
50-
_arduino_event_queue = xQueueCreate(32, sizeof(arduino_event_t *));
51-
if (!_arduino_event_queue) {
52-
log_e("Network Event Queue Create Failed!");
53-
return false;
54-
}
55-
}
56-
34+
// create default ESP event loop
5735
esp_err_t err = esp_event_loop_create_default();
5836
if (err != ESP_OK && err != ESP_ERR_INVALID_STATE) {
5937
log_e("esp_event_loop_create_default failed!");
60-
return err;
38+
return false;
6139
}
6240

63-
if (!_arduino_event_task_handle) {
64-
xTaskCreateUniversal(
65-
[](void *self) {
66-
static_cast<NetworkEvents *>(self)->_checkForEvent();
67-
},
68-
"arduino_events", // label
69-
ARDUINO_NETWORK_EVENT_TASK_STACK_SIZE, // event task's stack size
70-
this, ESP_TASKD_EVENT_PRIO - 1, &_arduino_event_task_handle, ARDUINO_EVENT_RUNNING_CORE
41+
// subscribe to default ESP event bus
42+
if (!_evt_handler){
43+
ESP_ERROR_CHECK(
44+
esp_event_handler_instance_register(
45+
ARDUINO_EVENTS, ESP_EVENT_ANY_ID,
46+
[](void* self, esp_event_base_t base, int32_t id, void* data) { static_cast<NetworkEvents*>(self)->_evt_picker(id, reinterpret_cast<arduino_event_info_t*>(data)); },
47+
this,
48+
&_evt_handler
49+
)
7150
);
72-
if (!_arduino_event_task_handle) {
73-
log_e("Network Event Task Start Failed!");
74-
return false;
75-
}
7651
}
77-
7852
return true;
7953
}
8054

81-
bool NetworkEvents::postEvent(const arduino_event_t *data) {
82-
if (data == NULL || _arduino_event_queue == NULL) {
83-
return false;
84-
}
85-
arduino_event_t *event = new arduino_event_t();
86-
if (event == NULL) {
87-
log_e("Arduino Event Malloc Failed!");
88-
return false;
89-
}
55+
bool NetworkEvents::postEvent(const arduino_event_t *data, TickType_t timeout) {
56+
if (!data) return false;
57+
esp_err_t err = esp_event_post(ARDUINO_EVENTS, static_cast<int32_t>(data->event_id), &data->event_info, sizeof(data->event_info), timeout);
58+
if (err == pdTRUE)
59+
return true;
9060

91-
memcpy(event, data, sizeof(arduino_event_t));
92-
if (xQueueSend(_arduino_event_queue, &event, portMAX_DELAY) != pdPASS) {
93-
log_e("Arduino Event Send Failed!");
94-
delete event; // release mem on error
95-
return false;
96-
}
97-
return true;
61+
log_e("Arduino Event Send Failed!");
62+
return false;
9863
}
9964

100-
void NetworkEvents::_checkForEvent() {
101-
// this task can't run without the queue
102-
if (_arduino_event_queue == NULL) {
103-
_arduino_event_task_handle = NULL;
104-
vTaskDelete(NULL);
105-
return;
106-
}
107-
108-
for (;;) {
109-
arduino_event_t *event = NULL;
110-
// wait for an event on a queue
111-
if (xQueueReceive(_arduino_event_queue, &event, portMAX_DELAY) != pdTRUE) {
112-
continue;
113-
}
114-
if (event == NULL) {
115-
continue;
116-
}
117-
log_v("Network Event: %d - %s", event->event_id, eventName(event->event_id));
118-
65+
void NetworkEvents::_evt_picker(int32_t id, arduino_event_info_t *info){
11966
#if defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1
120-
std::unique_lock<std::mutex> lock(_mtx);
67+
std::lock_guard<std::mutex> lock(_mtx);
12168
#endif // defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1
12269

123-
// iterate over registered callbacks
124-
for (auto &i : _cbEventList) {
125-
if (i.cb || i.fcb || i.scb) {
126-
if (i.event == (arduino_event_id_t)event->event_id || i.event == ARDUINO_EVENT_MAX) {
127-
if (i.cb) {
128-
i.cb((arduino_event_id_t)event->event_id);
129-
continue;
130-
}
131-
132-
if (i.fcb) {
133-
i.fcb((arduino_event_id_t)event->event_id, (arduino_event_info_t)event->event_info);
134-
continue;
135-
}
136-
137-
i.scb(event);
138-
}
70+
// iterate over registered callbacks
71+
for (auto &i : _cbEventList) {
72+
if (i.event == static_cast<arduino_event_id_t>(id) || i.event == ARDUINO_EVENT_ANY) {
73+
if (i.cb) {
74+
i.cb(static_cast<arduino_event_id_t>(id));
75+
continue;
13976
}
140-
}
14177

142-
#if defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1
143-
lock.unlock();
144-
#endif // defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1
78+
if (i.fcb) {
79+
i.fcb(static_cast<arduino_event_id_t>(id), *info);
80+
continue;
81+
}
14582

146-
// release the event object's memory
147-
delete event;
83+
if (i.scb && info){
84+
// system event callback needs a ptr to struct
85+
arduino_event_t event{static_cast<arduino_event_id_t>(id), {}};
86+
memcpy(&event.event_info, info, sizeof(arduino_event_info_t));
87+
i.scb(&event);
88+
}
89+
}
14890
}
149-
150-
vTaskDelete(NULL);
15191
}
15292

15393
template<typename T, typename... U> static size_t getStdFunctionAddress(std::function<T(U...)> f) {
@@ -354,7 +294,6 @@ int NetworkEvents::waitStatusBits(int bits, uint32_t timeout_ms) {
354294
* @brief Convert arduino_event_id_t to a C string.
355295
* @param [in] id The event id to be converted.
356296
* @return A string representation of the event id.
357-
* @note: arduino_event_id_t values as of Mar 2023 (arduino-esp32 r2.0.7) are: 0-39 (ARDUINO_EVENT_MAX=40) and are defined in WiFiGeneric.h.
358297
*/
359298
const char *NetworkEvents::eventName(arduino_event_id_t id) {
360299
switch (id) {

Diff for: libraries/Network/src/NetworkEvents.h

+25-27
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,6 @@
1515
#endif
1616
#include <functional>
1717
#include "freertos/FreeRTOS.h"
18-
#include "freertos/task.h"
19-
#include "freertos/queue.h"
20-
#include "freertos/semphr.h"
2118
#include "freertos/event_groups.h"
2219
#if defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1
2320
#include <mutex>
@@ -39,8 +36,11 @@ constexpr int WIFI_SCAN_DONE_BIT = BIT1;
3936
#define NET_HAS_IP6_GLOBAL_BIT 0
4037

4138
ESP_EVENT_DECLARE_BASE(ARDUINO_EVENTS);
39+
// backward compatibility
40+
#define ARDUINO_EVENT_MAX ARDUINO_EVENT_ANY
4241

4342
typedef enum {
43+
ARDUINO_EVENT_ANY = ESP_EVENT_ANY_ID, // make all ARDUINO events compatibile with ANY ESP_EVENT
4444
ARDUINO_EVENT_NONE = 0,
4545
ARDUINO_EVENT_ETH_START,
4646
ARDUINO_EVENT_ETH_STOP,
@@ -93,9 +93,9 @@ typedef enum {
9393
ARDUINO_EVENT_PPP_GOT_IP,
9494
ARDUINO_EVENT_PPP_LOST_IP,
9595
ARDUINO_EVENT_PPP_GOT_IP6,
96-
ARDUINO_EVENT_MAX
9796
} arduino_event_id_t;
9897

98+
9999
typedef union {
100100
ip_event_ap_staipassigned_t wifi_ap_staipassigned;
101101
ip_event_got_ip_t got_ip;
@@ -148,7 +148,7 @@ using network_event_handle_t = size_t;
148148
*/
149149
class NetworkEvents {
150150
public:
151-
NetworkEvents();
151+
NetworkEvents(){};
152152
~NetworkEvents();
153153

154154
/**
@@ -159,7 +159,7 @@ class NetworkEvents {
159159
* @param event event to process, any event by default
160160
* @return network_event_handle_t
161161
*/
162-
network_event_handle_t onEvent(NetworkEventCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX);
162+
network_event_handle_t onEvent(NetworkEventCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_ANY);
163163

164164
/**
165165
* @brief register functional callback to be executed on arduino event(s)
@@ -170,7 +170,7 @@ class NetworkEvents {
170170
* @param event event to process, any event by default
171171
* @return network_event_handle_t
172172
*/
173-
network_event_handle_t onEvent(NetworkEventFuncCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX);
173+
network_event_handle_t onEvent(NetworkEventFuncCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_ANY);
174174

175175
/**
176176
* @brief register static system callback to be executed on arduino event(s)
@@ -182,7 +182,7 @@ class NetworkEvents {
182182
* @param event event to process, any event by default
183183
* @return network_event_handle_t
184184
*/
185-
network_event_handle_t onEvent(NetworkEventSysCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX);
185+
network_event_handle_t onEvent(NetworkEventSysCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_ANY);
186186

187187
/**
188188
* @brief unregister static function callback
@@ -191,7 +191,7 @@ class NetworkEvents {
191191
* @param cbEvent static callback function
192192
* @param event event to process, any event by default
193193
*/
194-
void removeEvent(NetworkEventCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX);
194+
void removeEvent(NetworkEventCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_ANY);
195195

196196
/**
197197
* @brief unregister functional callback
@@ -201,7 +201,7 @@ class NetworkEvents {
201201
* @param cbEvent functional callback
202202
* @param event event to process, any event by default
203203
*/
204-
void removeEvent(NetworkEventFuncCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX)
204+
void removeEvent(NetworkEventFuncCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_ANY)
205205
__attribute__((deprecated("removing functional callbacks via pointer is deprecated, use removeEvent(network_event_handle_t) instead")));
206206

207207
/**
@@ -211,21 +211,19 @@ class NetworkEvents {
211211
* @param cbEvent static callback function
212212
* @param event event to process, any event by default
213213
*/
214-
void removeEvent(NetworkEventSysCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX);
214+
void removeEvent(NetworkEventSysCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_ANY);
215215

216216
/**
217217
* @brief unregister event callback via handler
218218
*
219-
* @param cbEvent static callback function
220-
* @param event event to process, any event by default
219+
* @param event_handle a handler to remove
221220
*/
222221
void removeEvent(network_event_handle_t event_handle);
223222

224223
/**
225224
* @brief get a human-readable name of an event by it's id
226225
*
227226
* @param id event id code
228-
* @return const char* event name string
229227
*/
230228
static const char *eventName(arduino_event_id_t id);
231229

@@ -238,7 +236,7 @@ class NetworkEvents {
238236
* @return true if event was queued susccessfuly
239237
* @return false on memrory allocation error or queue is full
240238
*/
241-
bool postEvent(const arduino_event_t *event);
239+
bool postEvent(const arduino_event_t *event, TickType_t timeout = portMAX_DELAY);
242240

243241
int getStatusBits() const;
244242
int waitStatusBits(int bits, uint32_t timeout_ms);
@@ -257,11 +255,11 @@ class NetworkEvents {
257255
protected:
258256
bool initNetworkEvents();
259257
// same as onEvent() but places newly added handler at the beginning of registered events list
260-
network_event_handle_t onSysEvent(NetworkEventCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX);
258+
network_event_handle_t onSysEvent(NetworkEventCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_ANY);
261259
// same as onEvent() but places newly added handler at the beginning of registered events list
262-
network_event_handle_t onSysEvent(NetworkEventFuncCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX);
260+
network_event_handle_t onSysEvent(NetworkEventFuncCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_ANY);
263261
// same as onEvent() but places newly added handler at the beginning of registered events list
264-
network_event_handle_t onSysEvent(NetworkEventSysCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX);
262+
network_event_handle_t onSysEvent(NetworkEventSysCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_ANY);
265263

266264
private:
267265
/**
@@ -280,17 +278,20 @@ class NetworkEvents {
280278

281279
explicit NetworkEventCbList_t(
282280
network_event_handle_t id, NetworkEventCb cb = nullptr, NetworkEventFuncCb fcb = nullptr, NetworkEventSysCb scb = nullptr,
283-
arduino_event_id_t event = ARDUINO_EVENT_MAX
281+
arduino_event_id_t event = ARDUINO_EVENT_ANY
284282
)
285283
: id(id), cb(cb), fcb(fcb), scb(scb), event(event) {}
286284
};
287285

288286
// define initial id's value
289287
network_event_handle_t _current_id{0};
288+
// EventGroup i.c.
289+
uint32_t _initial_bits{0};
290+
291+
// ESP event bus handler
292+
esp_event_handler_instance_t _evt_handler{nullptr};
290293

291-
EventGroupHandle_t _arduino_event_group;
292-
QueueHandle_t _arduino_event_queue;
293-
TaskHandle_t _arduino_event_task_handle;
294+
EventGroupHandle_t _arduino_event_group{nullptr};
294295

295296
// registered events callbacks container
296297
std::vector<NetworkEventCbList_t> _cbEventList;
@@ -300,9 +301,6 @@ class NetworkEvents {
300301
std::mutex _mtx;
301302
#endif // defined NETWORK_EVENTS_MUTEX && SOC_CPU_CORES_NUM > 1
302303

303-
/**
304-
* @brief task function that picks events from an event queue and calls registered callbacks
305-
*
306-
*/
307-
void _checkForEvent();
304+
// ESP event bus callback function, picks events from an event queue and calls registered callbacks
305+
void _evt_picker(int32_t id, arduino_event_info_t *info);
308306
};

Diff for: libraries/WiFi/src/WiFiGeneric.cpp

-2
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,6 @@ extern "C" {
5656
#include <vector>
5757
#include "sdkconfig.h"
5858

59-
ESP_EVENT_DEFINE_BASE(ARDUINO_EVENTS);
60-
6159
static esp_netif_t *esp_netifs[ESP_IF_MAX] = {NULL, NULL, NULL};
6260

6361
esp_netif_t *get_esp_interface_netif(esp_interface_t interface) {

0 commit comments

Comments
 (0)