2
2
#include < WiFiUdp.h>
3
3
#include < esp_now.h>
4
4
5
- #include " AudioTools/CoreAudio/BaseStream.h"
6
5
#include " AudioTools/CoreAudio/AudioBasic/StrView.h"
7
- #include " AudioTools/CoreAudio/Buffers .h"
8
-
6
+ #include " AudioTools/CoreAudio/BaseStream .h"
7
+ # include " AudioTools/Concurrency/RTOS.h "
9
8
10
9
namespace audio_tools {
11
10
12
-
13
11
// forward declarations
14
12
class ESPNowStream ;
15
- ESPNowStream *ESPNowStreamSelf = nullptr ;
16
-
17
- /* *
18
- * @brief A simple RIA locking class for the ESP32 using _lock_t
19
- * @author Phil Schatzmann
20
- * @copyright GPLv3
21
- */
22
- class Lock {
23
- public:
24
- Lock (_lock_t &lock) {
25
- this ->p_lock = &lock;
26
- _lock_acquire (p_lock);
27
- }
28
- ~Lock () { _lock_release (p_lock); }
29
-
30
- protected:
31
- _lock_t *p_lock = nullptr ;
32
- };
33
-
34
-
13
+ static ESPNowStream *ESPNowStreamSelf = nullptr ;
35
14
36
15
/* *
37
16
* @brief Configuration for ESP-NOW protocolö.W
@@ -45,11 +24,10 @@ struct ESPNowStreamConfig {
45
24
const char *ssid = nullptr ;
46
25
const char *password = nullptr ;
47
26
bool use_send_ack = true ; // we wait for
48
- uint16_t delay_after_write_ms = 2 ;
49
27
uint16_t delay_after_failed_write_ms = 2000 ;
50
28
uint16_t buffer_size = ESP_NOW_MAX_DATA_LEN;
51
29
uint16_t buffer_count = 400 ;
52
- int write_retry_count = -1 ; // -1 endless
30
+ int write_retry_count = -1 ; // -1 endless
53
31
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
54
32
void (*recveive_cb)(const esp_now_recv_info *info, const uint8_t *data,
55
33
int data_len) = nullptr;
@@ -65,7 +43,7 @@ struct ESPNowStreamConfig {
65
43
};
66
44
67
45
/* *
68
- * @brief ESPNow as Arduino Stream
46
+ * @brief ESPNow as Arduino Stream.
69
47
* @ingroup communications
70
48
* @author Phil Schatzmann
71
49
* @copyright GPLv3
@@ -75,7 +53,7 @@ class ESPNowStream : public BaseStream {
75
53
ESPNowStream () { ESPNowStreamSelf = this ; };
76
54
77
55
~ESPNowStream () {
78
- if (p_buffer != nullptr ) delete p_buffer ;
56
+ if (xSemaphore != nullptr ) vSemaphoreDelete (xSemaphore) ;
79
57
}
80
58
81
59
ESPNowStreamConfig defaultConfig () {
@@ -84,9 +62,9 @@ class ESPNowStream : public BaseStream {
84
62
}
85
63
86
64
// / Returns the mac address of the current ESP32
87
- const char *macAddress () {
88
- static const char * result = WiFi.macAddress ().c_str ();
89
- return result;
65
+ const char *macAddress () {
66
+ static const char * result = WiFi.macAddress ().c_str ();
67
+ return result;
90
68
}
91
69
92
70
// / Defines an alternative send callback
@@ -112,7 +90,8 @@ class ESPNowStream : public BaseStream {
112
90
LOGE (" Could not set mac address" );
113
91
return false ;
114
92
}
115
- delay (500 ); // On some boards calling macAddress to early leads to a race condition.
93
+ delay (500 ); // On some boards calling macAddress to early leads to a race
94
+ // condition.
116
95
// checking if address has been updated
117
96
const char *addr = macAddress ();
118
97
if (strcmp (addr, cfg.mac_address ) != 0 ) {
@@ -132,8 +111,7 @@ class ESPNowStream : public BaseStream {
132
111
133
112
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
134
113
LOGI (" Setting ESP-NEW rate" );
135
- if (esp_wifi_config_espnow_rate (getInterface (), cfg.rate ) !=
136
- ESP_OK) {
114
+ if (esp_wifi_config_espnow_rate (getInterface (), cfg.rate ) != ESP_OK) {
137
115
LOGW (" Could not set rate" );
138
116
}
139
117
#endif
@@ -146,10 +124,13 @@ class ESPNowStream : public BaseStream {
146
124
147
125
// / DeInitialization
148
126
void end () {
149
- if (esp_now_deinit () != ESP_OK) {
150
- LOGE (" esp_now_deinit" );
127
+ if (is_init){
128
+ if (esp_now_deinit () != ESP_OK) {
129
+ LOGE (" esp_now_deinit" );
130
+ }
131
+ if (buffer.size ()>0 ) buffer.resize (0 );
132
+ is_init = false ;
151
133
}
152
- is_init = false ;
153
134
}
154
135
155
136
// / Adds a peer to which we can send info or from which we can receive info
@@ -189,7 +170,7 @@ class ESPNowStream : public BaseStream {
189
170
peer.ifidx = getInterface ();
190
171
peer.encrypt = false ;
191
172
192
- if (StrView (address).equals (cfg.mac_address )){
173
+ if (StrView (address).equals (cfg.mac_address )) {
193
174
LOGW (" Did not add own address as peer" );
194
175
return true ;
195
176
}
@@ -208,42 +189,31 @@ class ESPNowStream : public BaseStream {
208
189
209
190
// / Writes the data - sends it to all the peers
210
191
size_t write (const uint8_t *data, size_t len) override {
192
+ setupSemaphore ();
211
193
int open = len;
212
194
size_t result = 0 ;
213
- int retry_count = 0 ;
195
+ int retry_count = cfg. write_retry_count ;
214
196
while (open > 0 ) {
215
- if (available_to_write > 0 ) {
216
- resetAvailableToWrite ();
217
- size_t send_len = min (open, ESP_NOW_MAX_DATA_LEN);
218
- esp_err_t rc = esp_now_send (nullptr , data + result, send_len);
219
- // wait for confirmation
220
- if (cfg.use_send_ack ) {
221
- while (available_to_write == 0 ) {
222
- delay (1 );
223
- }
224
- } else {
225
- is_write_ok = true ;
226
- }
227
- // check status
228
- if (rc == ESP_OK && is_write_ok) {
229
- open -= send_len;
230
- result += send_len;
231
- } else {
232
- LOGW (" Write failed - retrying again" );
233
- retry_count++;
234
- if (cfg.write_retry_count >0 && retry_count>=cfg.write_retry_count ){
235
- LOGE (" Write error after %d retries" , cfg.write_retry_count );
236
- // break loop
237
- return 0 ;
238
- }
239
- }
240
- // if we do have no partner to write we stall and retry later
241
- } else {
242
- delay (cfg.delay_after_write_ms );
197
+ resetAvailableToWrite ();
198
+ // wait for confirmation
199
+ if (cfg.use_send_ack ) {
200
+ xSemaphoreTake (xSemaphore, portMAX_DELAY);
243
201
}
244
-
245
- // Wait some time before we retry
246
- if (!is_write_ok) {
202
+ size_t send_len = min (open, ESP_NOW_MAX_DATA_LEN);
203
+ esp_err_t rc = esp_now_send (nullptr , data + result, send_len);
204
+ // check status
205
+ if (rc == ESP_OK) {
206
+ open -= send_len;
207
+ result += send_len;
208
+ retry_count = 0 ;
209
+ } else {
210
+ LOGW (" Write failed - retrying again" );
211
+ retry_count++;
212
+ if (retry_count-- < 0 ) {
213
+ LOGE (" Write error after %d retries" , cfg.write_retry_count );
214
+ // break loop
215
+ return 0 ;
216
+ }
247
217
delay (cfg.delay_after_failed_write_ms );
248
218
}
249
219
}
@@ -252,34 +222,51 @@ class ESPNowStream : public BaseStream {
252
222
253
223
// / Reeds the data from the peers
254
224
size_t readBytes (uint8_t *data, size_t len) override {
255
- if (p_buffer == nullptr ) return 0 ;
256
- Lock lock (write_lock);
257
- return p_buffer->readArray (data, len);
225
+ if (buffer.size ()==0 ) return 0 ;
226
+ return buffer.readArray (data, len);
258
227
}
259
228
260
229
int available () override {
261
- return p_buffer == nullptr ? 0 : p_buffer->available ();
230
+ if (!buffer) return 0 ;
231
+ return buffer.size () == 0 ? 0 : buffer.available ();
262
232
}
263
233
264
234
int availableForWrite () override {
235
+ if (!buffer) return 0 ;
265
236
return cfg.use_send_ack ? available_to_write : cfg.buffer_size ;
266
237
}
267
238
239
+ // / provides how much the receive buffer is filled (in percent)
240
+ float getBufferPercent () {
241
+ int size = buffer.size ();
242
+ // prevent div by 0
243
+ if (size==0 ) return 0.0 ;
244
+ // calculate percent
245
+ return 100.0 * buffer.available () / size;
246
+ }
247
+
268
248
protected:
269
249
ESPNowStreamConfig cfg;
270
- BaseBuffer <uint8_t > *p_buffer = nullptr ;
250
+ BufferRTOS <uint8_t > buffer{ 0 } ;
271
251
esp_now_recv_cb_t receive = default_recv_cb;
272
252
esp_now_send_cb_t send = default_send_cb;
273
- volatile size_t available_to_write;
253
+ volatile size_t available_to_write = 0 ;
274
254
bool is_init = false ;
275
- bool is_write_ok = false ;
276
- _lock_t write_lock;
255
+ SemaphoreHandle_t xSemaphore = nullptr ;
277
256
278
- inline void setupReceiveBuffer (){
257
+ inline void setupSemaphore () {
258
+ // use semaphore for confirmations
259
+ if (cfg.use_send_ack && xSemaphore==nullptr ) {
260
+ xSemaphore = xSemaphoreCreateBinary ();
261
+ xSemaphoreGive (xSemaphore);
262
+ }
263
+ }
264
+
265
+ inline void setupReceiveBuffer () {
279
266
// setup receive buffer
280
- if (p_buffer == nullptr && cfg. buffer_count > 0 ) {
281
- // p_buffer = new NBuffer<uint8_t>( cfg.buffer_size , cfg.buffer_count);
282
- p_buffer = new RingBuffer< uint8_t > (cfg.buffer_size * cfg.buffer_count );
267
+ if (!buffer ) {
268
+ LOGI ( " setupReceiveBuffer: %d " , cfg.buffer_size * cfg.buffer_count );
269
+ buffer. resize (cfg.buffer_size * cfg.buffer_count );
283
270
}
284
271
}
285
272
@@ -352,26 +339,24 @@ class ESPNowStream : public BaseStream {
352
339
}
353
340
354
341
static int bufferAvailableForWrite () {
355
- Lock lock (ESPNowStreamSelf->write_lock );
356
- return ESPNowStreamSelf->p_buffer ->availableForWrite ();
342
+ return ESPNowStreamSelf->buffer .availableForWrite ();
357
343
}
358
344
359
345
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
360
- static void default_recv_cb (const esp_now_recv_info *info, const uint8_t *data, int data_len)
346
+ static void default_recv_cb (const esp_now_recv_info *info,
347
+ const uint8_t *data, int data_len)
361
348
#else
362
- static void default_recv_cb (const uint8_t *mac_addr, const uint8_t *data, int data_len)
349
+ static void default_recv_cb (const uint8_t *mac_addr, const uint8_t *data,
350
+ int data_len)
363
351
#endif
364
- {
352
+ {
365
353
LOGD (" rec_cb: %d" , data_len);
366
- // make sure that the receive buffer is available - moved from begin to make sure that it is only allocated when needed
354
+ // make sure that the receive buffer is available - moved from begin to make
355
+ // sure that it is only allocated when needed
367
356
ESPNowStreamSelf->setupReceiveBuffer ();
368
357
// blocking write
369
- while (bufferAvailableForWrite () < data_len) {
370
- delay (2 );
371
- }
372
- Lock lock (ESPNowStreamSelf->write_lock );
373
- size_t result = ESPNowStreamSelf->p_buffer ->writeArray (data, data_len);
374
- if (result!=data_len){
358
+ size_t result = ESPNowStreamSelf->buffer .writeArray (data, data_len);
359
+ if (result != data_len) {
375
360
LOGE (" writeArray %d -> %d" , data_len, result);
376
361
}
377
362
}
@@ -391,12 +376,12 @@ class ESPNowStream : public BaseStream {
391
376
if (strncmp ((char *)mac_addr, (char *)first_mac, ESP_NOW_KEY_LEN) == 0 ) {
392
377
ESPNowStreamSelf->available_to_write = ESPNowStreamSelf->cfg .buffer_size ;
393
378
if (status == ESP_NOW_SEND_SUCCESS) {
394
- ESPNowStreamSelf->is_write_ok = true ;
379
+ xSemaphoreGive ( ESPNowStreamSelf->xSemaphore ) ;
395
380
} else {
396
- ESPNowStreamSelf-> is_write_ok = false ;
381
+ LOGE ( " Send Error! " ) ;
397
382
}
398
383
}
399
384
}
400
385
};
401
386
402
- }
387
+ } // namespace audio_tools
0 commit comments