arduino-audio-tools
Loading...
Searching...
No Matches
ESPNowStream.h
Go to the documentation of this file.
1#pragma once
2#ifdef ARDUINO
3#include <WiFi.h>
4#endif
5#include <esp_now.h>
6#include <esp_wifi.h>
7
11
12// propose max data length based on esp-idf version
13#ifdef ESP_NOW_MAX_DATA_LEN_V2
14// 1470
15#define MY_ESP_NOW_MAX_LEN ESP_NOW_MAX_DATA_LEN_V2
16#else
17// 240
18#define MY_ESP_NOW_MAX_LEN ESP_NOW_MAX_DATA_LEN
19#endif
20
21// calculate buffer count: 96000 bytes should be enough for most use cases and
22// should not cause memory issues on the receiver side. With 240 bytes per
23// packet, this results in 400 packets.
24#define MY_ESP_NOW_BUFFER_SIZE (240 * 400)
25#define MY_ESP_NOW_BUFFER_COUNT (MY_ESP_NOW_BUFFER_SIZE / MY_ESP_NOW_MAX_LEN)
26
27namespace audio_tools {
28
29// forward declarations
30class ESPNowStream;
32static const char* BROADCAST_MAC_STR = "FF:FF:FF:FF:FF:FF";
33static const uint8_t BROADCAST_MAC[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
34
45 const char* mac_address = nullptr;
53 int channel = 0;
55 const char* ssid = nullptr;
57 const char* password = nullptr;
58#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 5, 0)
62#endif
64 bool use_send_ack = true; // we wait for
67 // enable long_range mode: increases range but reduces throughput. Default:
68 // false
69 bool use_long_range = false;
71 int write_retry_count = 1; // -1 endless
72#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
74 void (*recveive_cb)(const esp_now_recv_info* info, const uint8_t* data,
75 int data_len) = nullptr;
76#else
78 void (*recveive_cb)(const uint8_t* mac_addr, const uint8_t* data,
79 int data_len) = nullptr;
80#endif
82 const char* primary_master_key = nullptr;
84 const char* local_master_key = nullptr;
95};
96
110class ESPNowStream : public BaseStream {
111 public:
113
115 if (xSemaphore != nullptr) vSemaphoreDelete(xSemaphore);
116 }
117
119 ESPNowStreamConfig result;
120 return result;
121 }
122
124 const char* macAddress() {
125#ifdef ARDUINO
126 static String mac_str = WiFi.macAddress();
127 return mac_str.c_str();
128#else
129 static char mac_str[18] = {0};
130 uint8_t mac[6];
132 snprintf(mac_str, sizeof(mac_str), "%02X:%02X:%02X:%02X:%02X:%02X",
133 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
134 return mac_str;
135#endif
136 }
137
140
144
146 bool begin() { return begin(cfg); }
147
150 this->cfg = cfg;
151#ifdef ARDUINO
152 if (WiFi.getMode() == WIFI_MODE_NULL) {
153 WiFi.mode(cfg.wifi_mode);
154 } else {
155 cfg.wifi_mode = WiFi.getMode();
156 }
157#else
158 wifi_mode_t mode;
159 esp_err_t ret = esp_wifi_get_mode(&mode);
160 if (ret == ESP_OK) {
161 if (mode == WIFI_MODE_NULL) {
163 } else {
164 cfg.wifi_mode = mode;
165 }
166 } else {
167 if (!initWiFi(cfg.wifi_mode)) return false;
168 }
169#endif
170
171 if (!setupMAC()) return false;
172
173 if (!setupWiFi()) return false;
174
175#ifdef ARDUINO
176 WiFi.enableLongRange(cfg.use_long_range);
177#else
179 if (cfg.use_long_range) {
181 }
183#endif
184
185#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
186 LOGI("Setting ESP-NEW rate");
188 LOGW("Could not set rate");
189 }
190#endif
191 if (cfg.channel > 0) {
193 }
194 LOGI("mac: %s", macAddress());
195 LOGI("channel: %d", getChannel());
196 return setup();
197 }
198
200 virtual void end() {
201 if (is_init) {
202 if (esp_now_deinit() != ESP_OK) {
203 LOGE("esp_now_deinit");
204 }
205 if (buffer.size() > 0) buffer.resize(0);
206 is_init = false;
207 has_peers = false;
208 read_ready = false;
209 is_broadcast = false;
210 }
211 }
212
215#ifdef ARDUINO
216 WiFi.setChannel(ch, WIFI_SECOND_CHAN_NONE);
217#else
219#endif
220 cfg.channel = ch;
221 }
222
225#ifdef ARDUINO
226 uint32_t ch = WiFi.channel();
227 return (uint8_t)ch ^ 0xff;
228#else
232 return primary;
233#endif
234 }
235
238 if (!is_init) {
239 LOGE("addPeer before begin");
240 return false;
241 }
242 if (memcmp(BROADCAST_MAC, peer.peer_addr, 6) == 0) {
243 LOGI("Using broadcast");
244 is_broadcast = true;
245 }
247 if (result == ESP_OK) {
248 LOGI("addPeer: %s", mac2str(peer.peer_addr));
249#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
251 .rate = cfg.rate,
252 .ersu = false,
253 .dcm = false};
254 result = esp_now_set_peer_rate_config(peer.peer_addr, &rate_config);
255 if (result != ESP_OK) {
256 LOGW("Could not set the ESP-NOW PHY rate (%d) %s.", result,
257 esp_err_to_name(result));
258 }
259#endif
260 has_peers = result == ESP_OK;
261 } else {
262 LOGE("addPeer: %d", result);
263 }
264 return result == ESP_OK;
265 }
266
268 bool addPeer(const uint8_t* address) {
270 memcpy(peer.peer_addr, address, ESP_NOW_ETH_ALEN);
271
272 peer.channel = cfg.channel;
273 peer.ifidx = getInterface();
274 peer.encrypt = false;
275
276 if (isEncrypted()) {
277 peer.encrypt = true;
278 strncpy((char*)peer.lmk, cfg.local_master_key, 16);
279 }
280 return addPeer(peer);
281 }
282
284 bool addPeer(const char* address) {
285 if (StrView(address).equals(cfg.mac_address)) {
286 LOGW("Did not add own address as peer");
287 return true;
288 }
289
290 uint8_t mac[] = {0, 0, 0, 0, 0, 0};
291 if (!str2mac(address, (uint8_t*)&mac)) {
292 LOGE("addPeer - Invalid address: %s", address);
293 return false;
294 }
295 return addPeer((const uint8_t*)&mac);
296 }
297
299 template <size_t size>
300 bool addPeers(const char* (&array)[size]) {
301 bool result = true;
302 for (int j = 0; j < size; j++) {
303 const char* peer = array[j];
304 if (peer != nullptr) {
305 if (!addPeer(peer)) {
306 result = false;
307 }
308 }
309 }
310 return result;
311 }
312
314 template <size_t N>
315 bool addPeers(const uint8_t (&array)[N][6]) {
316 bool result = true;
317 for (int j = 0; j < N; j++) {
318 const uint8_t* peer = array[j];
319 if (peer != nullptr) {
320 if (!addPeer(peer)) {
321 result = false;
322 }
323 }
324 }
325 return result;
326 }
327
331
333 bool clearPeers() {
336 while ((esp_now_fetch_peer(true, &peer) == ESP_OK) &&
338 esp_now_del_peer(peer.peer_addr);
340 }
341
343 LOGE("Not all Peers seems to be removed.");
344 }
345 // return true when all peers are removed.
347 }
348
350 size_t write(const uint8_t* data, size_t len) override {
351 // nullptr means send to all registered peers
352 return write((const uint8_t*)nullptr, data, len);
353 }
354
356 size_t write(const char* peer, const uint8_t* data, size_t len) {
357 uint8_t mac[6];
358 if (!str2mac(peer, mac)) {
359 LOGE("write: invalid mac address %s", peer);
360 return 0;
361 }
362 return write(mac, data, len);
363 }
364
366 size_t write(const uint8_t* peer, const uint8_t* data, size_t len) {
367 // initialization: setup semaphore
369
370 // initialization: if no peers registered and peer is nullptr, add broadcast
371 if (!has_peers && peer == nullptr) {
373 }
374
375 size_t total_sent = 0;
376 size_t remaining = len;
377
378 while (remaining > 0) {
379 size_t chunk_size = min(remaining, (size_t)MY_ESP_NOW_MAX_LEN);
380 int retry_count = 0;
381
382 bool success =
383 sendPacket(data + total_sent, chunk_size, retry_count, peer);
384
385 if (success) {
386 // Chunk sent successfully
389 } else {
390 // Max retries exceeded for this chunk
391 LOGE(
392 "write: failed to send chunk after %d attempts (sent %zu/%zu "
393 "bytes)",
394 retry_count, total_sent, len);
395 // Return bytes successfully sent so far (may be 0 if first chunk
396 // failed)
397 return total_sent;
398 }
399 }
400 return total_sent;
401 }
402
404 size_t readBytes(uint8_t* data, size_t len) override {
405 if (!read_ready) return 0;
406 if (buffer.size() == 0) return 0;
407 return buffer.readArray(data, len);
408 }
409
410 int available() override {
411 if (!buffer) return 0;
412 if (!read_ready) return 0;
413 return buffer.size() == 0 ? 0 : buffer.available();
414 }
415
416 int availableForWrite() override {
417 if (!buffer) return 0;
419 }
420
423 int size = buffer.size();
424 // prevent div by 0
425 if (size == 0) return 0.0;
426 // calculate percent
427 return 100.0 * buffer.available() / size;
428 }
429
432
435
436 protected:
441 volatile size_t available_to_write = 0;
442 volatile bool last_send_success = true;
443 bool is_init = false;
445 bool has_peers = false;
446 bool read_ready = false;
447 bool is_broadcast = false;
449
450 bool setupMAC() {
451 // set mac address
452 if (cfg.mac_address != nullptr) {
453 LOGI("setting mac %s", cfg.mac_address);
457 LOGE("Could not set mac address");
458 return false;
459 }
460
461 // On some boards calling macAddress too early leads to a race condition.
463
464 // checking if address has been updated
465 const char* addr = macAddress();
466 if (strcmp(addr, cfg.mac_address) != 0) {
467 LOGE("Wrong mac address: %s", addr);
468 return false;
469 }
470 }
471 return true;
472 }
473
474 bool setupWiFi() {
475#ifdef ARDUINO
476 if (WiFi.status() != WL_CONNECTED) {
477 if (cfg.ssid != nullptr && cfg.password != nullptr) {
478 LOGI("Connecting to WiFi: %s", cfg.ssid);
480 while (WiFi.status() != WL_CONNECTED) {
481 delay(1000);
482 }
483 }
484 }
485 if (WiFi.getMode() == WIFI_MODE_AP && WiFi.status() != WL_CONNECTED) {
486 LOGE("You did not start Wifi or did not provide ssid and password");
487 return false;
488 }
489#else
490 if (cfg.ssid != nullptr && cfg.password != nullptr) {
493 LOGI("Connecting to WiFi: %s", cfg.ssid);
495 strncpy((char*)wifi_config.sta.ssid, cfg.ssid,
496 sizeof(wifi_config.sta.ssid) - 1);
497 strncpy((char*)wifi_config.sta.password, cfg.password,
498 sizeof(wifi_config.sta.password) - 1);
501 for (int i = 0; i < 30; i++) {
503 delay(1000);
504 }
505 }
506 }
507 wifi_mode_t mode;
508 if (esp_wifi_get_mode(&mode) == ESP_OK && mode == WIFI_MODE_AP) {
511 LOGE("You did not start Wifi or did not provide ssid and password");
512 return false;
513 }
514 }
515#endif
516 return true;
517 }
518
519 inline void setupSemaphore() {
520 // use semaphore for confirmations
521 if (cfg.use_send_ack && xSemaphore == nullptr) {
524 }
525 }
526
527 inline void setupReceiveBuffer() {
528 // setup receive buffer
529 if (!buffer) {
530 LOGI("setupReceiveBuffer: %d", cfg.buffer_size * cfg.buffer_count);
532 }
533 }
534
535 inline void resetAvailableToWrite() {
536 if (cfg.use_send_ack) {
538 }
539 }
540
542 virtual bool sendPacket(const uint8_t* data, size_t len, int& retry_count,
543 const uint8_t* destination = nullptr) {
544 TRACED();
545 const uint8_t* target = destination;
546 if (target == nullptr && is_broadcast) {
547 target = BROADCAST_MAC;
548 }
549
550 while (true) {
552
553 // Wait for previous send to complete (if using ACKs)
554 if (cfg.use_send_ack) {
559 // Timeout waiting for previous send - check retry limit BEFORE
560 // incrementing
561 if (cfg.write_retry_count >= 0 &&
562 retry_count >= cfg.write_retry_count) {
563 LOGE("Timeout waiting for ACK semaphore after %d retries",
564 retry_count);
565 return false;
566 }
567 retry_count++;
568 LOGW("ACK semaphore timeout (attempt %d)", retry_count);
570 continue;
571 }
572 }
573
574 // Try to queue the packet
575 esp_err_t rc = esp_now_send(target, data, len);
576
577 if (rc == ESP_OK) {
578 // Packet queued - wait for transmission result
579 if (handleTransmissionResult(retry_count)) {
580 return true; // Success
581 }
582 // Transmission failed - check if we've exceeded the limit
583 // handleTransmissionResult returns false both when limit is reached
584 // and when we should retry, so check the limit here
585 if (cfg.write_retry_count >= 0 &&
586 retry_count >= cfg.write_retry_count) {
587 return false; // Give up - limit reached
588 }
589 // Continue to retry
590 } else {
591 // Failed to queue - callback will NOT be called
592 if (cfg.use_send_ack) {
593 xSemaphoreGive(xSemaphore); // Give back semaphore
594 }
595
596 // Check limit BEFORE incrementing
597 if (cfg.write_retry_count >= 0 &&
598 retry_count >= cfg.write_retry_count) {
599 LOGE("esp_now_send queue error (rc=%d/0x%04X) after %d retries", rc,
600 rc, retry_count);
601 return false;
602 }
603
604 retry_count++;
605 LOGW("esp_now_send failed (rc=%d/0x%04X) - retrying (attempt %d)", rc,
606 rc, retry_count);
608 }
609 }
610 }
611
613 bool handleTransmissionResult(int& retry_count) {
614 TRACED();
615 if (cfg.use_send_ack) {
616 // Wait for callback to signal result
621 // Callback never came - check limit BEFORE incrementing
622 if (cfg.write_retry_count >= 0 &&
623 retry_count >= cfg.write_retry_count) {
624 LOGE("Transmission callback timeout after %d retries", retry_count);
625 return false;
626 }
627 retry_count++;
628 LOGW("Transmission callback timeout (attempt %d)", retry_count);
630 return false; // Retry
631 }
632
633 // Got callback - check result
634 if (last_send_success) {
635 xSemaphoreGive(xSemaphore); // Release for next send
636 return true;
637 } else {
638 xSemaphoreGive(xSemaphore); // Release for retry
639
640 // Check limit BEFORE incrementing
641 if (cfg.write_retry_count >= 0 &&
642 retry_count >= cfg.write_retry_count) {
643 LOGE("Transmission failed after %d retries", retry_count);
644 return false;
645 }
646
647 retry_count++;
648 LOGI("Transmission failed - retrying (attempt %d)", retry_count);
650 return false; // Retry
651 }
652 }
653 return true; // No ACK mode - assume success
654 }
655
657 bool handleQueueError(esp_err_t rc, int& retry_count) {
658 TRACED();
659 // esp_now_send failed to queue - callback will NOT be called
660 // Give back the semaphore we took earlier
661 if (cfg.use_send_ack) {
663 }
664
665 retry_count++;
666 LOGW("esp_now_send failed to queue (rc=%d/0x%04X) - retrying (attempt %d)",
667 rc, rc, retry_count);
668
669 if (cfg.write_retry_count >= 0 && retry_count > cfg.write_retry_count) {
670 LOGE("Send queue error after %d retries", retry_count);
671 return false;
672 }
673
675 return true; // Continue retrying
676 }
677
678 bool isEncrypted() {
679 return cfg.primary_master_key != nullptr && cfg.local_master_key != nullptr;
680 }
681
683 switch (cfg.wifi_mode) {
684 case WIFI_MODE_STA:
685 return WIFI_IF_STA;
686 case WIFI_MODE_AP:
687 return WIFI_IF_AP;
688 default:
689 return WIFI_IF_STA;
690 }
691 }
692
693#ifndef ARDUINO
697 if (ret != ESP_OK) {
698 LOGE("esp_wifi_init: %s (ensure NVS and netif are initialized)",
699 esp_err_to_name(ret));
700 return false;
701 }
702 ret = esp_wifi_set_mode(mode);
703 if (ret != ESP_OK) {
704 LOGE("esp_wifi_set_mode: %s", esp_err_to_name(ret));
705 return false;
706 }
707 ret = esp_wifi_start();
708 if (ret != ESP_OK) {
709 LOGE("esp_wifi_start: %s", esp_err_to_name(ret));
710 return false;
711 }
712 return true;
713 }
714#endif
715
717 bool setup() {
718 esp_err_t result = esp_now_init();
719 if (result == ESP_OK) {
720 LOGI("esp_now_init: %s", macAddress());
721 } else {
722 LOGE("esp_now_init: %d", result);
723 }
724
725#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 5, 0)
726 if (cfg.oui) {
728 }
729#endif
730
731 // encryption is optional
732 if (isEncrypted()) {
734 }
735
736 if (cfg.recveive_cb != nullptr) {
738 } else {
740 }
741 if (cfg.use_send_ack) {
743 }
745 is_init = result == ESP_OK;
746 return is_init;
747 }
748
749 bool str2mac(const char* mac, uint8_t* values) {
750 sscanf(mac, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &values[0], &values[1],
751 &values[2], &values[3], &values[4], &values[5]);
752 return strlen(mac) == 17;
753 }
754
755 const char* mac2str(const uint8_t* array) {
756 static char macStr[18];
757 memset(macStr, 0, 18);
758 snprintf(macStr, 18, "%02x:%02x:%02x:%02x:%02x:%02x", array[0], array[1],
759 array[2], array[3], array[4], array[5]);
760 return (const char*)macStr;
761 }
762
766
767 virtual void handle_recv_cb(const uint8_t* mac_addr, const uint8_t* data,
768 int data_len, bool broadcast, uint8_t rssi) {
769 LOGD("rec_cb: %d", data_len);
770 // make sure that the receive buffer is available - moved from begin to
771 // make sure that it is only allocated when needed
773
774 // update last io time
776
777 // blocking write
778 size_t result = buffer.writeArray(data, data_len);
779 if (result != data_len) {
780 LOGE("writeArray %d -> %d", data_len, result);
781 }
782 // manage ready state
783 if (read_ready == false) {
785 read_ready = true;
786 } else {
788 }
789 }
790 }
791
792#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
793 static void default_recv_cb(const esp_now_recv_info* info,
794 const uint8_t* data, int data_len) {
795 const bool broadcast =
796 memcmp(info->des_addr, BROADCAST_MAC, ESP_NOW_ETH_ALEN) == 0;
797 ESPNowStreamSelf->handle_recv_cb(info->src_addr, data, data_len, broadcast,
798 info->rx_ctrl->rssi);
799 }
800#else
801 static void default_recv_cb(const uint8_t* mac_addr, const uint8_t* data,
802 int data_len) {
804 }
805#endif
806
807 virtual void handle_send_cb(const uint8_t* mac_addr,
808 esp_now_send_status_t status) {
809 static uint8_t first_mac[ESP_NOW_KEY_LEN] = {0};
810 // we use the first confirming mac_addr for further confirmations and
811 // ignore others
812 if (first_mac[0] == 0) {
813 strncpy((char*)first_mac, (char*)mac_addr, ESP_NOW_KEY_LEN);
814 }
815 LOGD("default_send_cb - %s -> %s", this->mac2str(mac_addr),
816 status == ESP_NOW_SEND_SUCCESS ? "+" : "-");
817
818 // ignore others
819 if (strncmp((char*)mac_addr, (char*)first_mac, ESP_NOW_KEY_LEN) == 0) {
820 this->available_to_write = this->cfg.buffer_size;
821
822 // Track send success/failure
823 this->last_send_success = (status == ESP_NOW_SEND_SUCCESS);
824
825 if (status == ESP_NOW_SEND_SUCCESS) {
827 } else {
828 LOGI(
829 "Send Error to %s! Status: %d (Possible causes: out of range, "
830 "receiver busy/offline, channel mismatch, or buffer full)",
831 this->mac2str(mac_addr), status);
832 }
833
834 // Release semaphore to allow write to check status and retry if needed
835 xSemaphoreGive(this->xSemaphore);
836 }
837 }
838
839#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 5, 0)
841 esp_now_send_status_t status) {
842 const uint8_t* mac_addr = tx_info->des_addr;
843#else
844 static void default_send_cb(const uint8_t* mac_addr,
845 esp_now_send_status_t status) {
846#endif
848 }
849};
850
851} // namespace audio_tools
#define LOGW(...)
Definition AudioLoggerIDF.h:29
#define TRACED()
Definition AudioLoggerIDF.h:31
#define LOGI(...)
Definition AudioLoggerIDF.h:28
#define LOGD(...)
Definition AudioLoggerIDF.h:27
#define LOGE(...)
Definition AudioLoggerIDF.h:30
#define MY_ESP_NOW_MAX_LEN
Definition ESPNowStream.h:18
#define MY_ESP_NOW_BUFFER_COUNT
Definition ESPNowStream.h:25
#define portMAX_DELAY
Definition QueueZephyr.h:14
#define pdMS_TO_TICKS(ms)
Definition QueueZephyr.h:17
#define pdTRUE
Definition QueueZephyr.h:20
uint32_t TickType_t
Definition QueueZephyr.h:11
Base class for all Streams. It relies on write(const uint8_t *buffer, size_t size) and readBytes(uint...
Definition BaseStream.h:33
Buffer implementation which is using a FreeRTOS StreamBuffer. The default allocator uses psram is ava...
Definition BufferRTOS.h:33
size_t size()
Definition BufferRTOS.h:168
int available() override
provides the number of entries that are available to read
Definition BufferRTOS.h:151
int availableForWrite() override
provides the number of entries that are available to write
Definition BufferRTOS.h:157
int writeArray(const T data[], int len)
Fills the buffer data.
Definition BufferRTOS.h:100
bool resize(size_t size)
Re-Allocats the memory and the queue.
Definition BufferRTOS.h:54
int readArray(T data[], int len)
reads multiple values
Definition BufferRTOS.h:80
ESPNow as Arduino Stream. When use_send_ack is true we prevent any buffer overflows by blocking write...
Definition ESPNowStream.h:110
SemaphoreHandle_t xSemaphore
Definition ESPNowStream.h:444
const char * mac2str(const uint8_t *array)
Definition ESPNowStream.h:755
bool read_ready
Definition ESPNowStream.h:446
BufferRTOS< uint8_t > & getBuffer()
provides access to the receive buffer
Definition ESPNowStream.h:431
bool handleTransmissionResult(int &retry_count)
Handles the result of packet transmission (after queuing)
Definition ESPNowStream.h:613
bool handleQueueError(esp_err_t rc, int &retry_count)
Handles errors when queuing packets.
Definition ESPNowStream.h:657
bool clearPeers()
Deletes all registered peers.
Definition ESPNowStream.h:333
void setSendCallback(esp_now_send_cb_t cb)
Defines an alternative send callback.
Definition ESPNowStream.h:139
uint32_t last_io_success_time
Definition ESPNowStream.h:448
void setupSemaphore()
Definition ESPNowStream.h:519
bool isEncrypted()
Definition ESPNowStream.h:678
wifi_interface_t getInterface()
Definition ESPNowStream.h:682
bool str2mac(const char *mac, uint8_t *values)
Definition ESPNowStream.h:749
bool addPeers(const uint8_t(&array)[N][6])
Adds an array of peers.
Definition ESPNowStream.h:315
virtual void handle_recv_cb(const uint8_t *mac_addr, const uint8_t *data, int data_len, bool broadcast, uint8_t rssi)
Definition ESPNowStream.h:767
volatile bool last_send_success
Definition ESPNowStream.h:442
virtual void handle_send_cb(const uint8_t *mac_addr, esp_now_send_status_t status)
Definition ESPNowStream.h:807
bool is_broadcast
Definition ESPNowStream.h:447
size_t readBytes(uint8_t *data, size_t len) override
Reeds the data from the peers.
Definition ESPNowStream.h:404
bool begin()
Initialization of ESPNow.
Definition ESPNowStream.h:146
uint32_t getLastIoSuccessTime() const
time when we were able to send or receive the last packet successfully
Definition ESPNowStream.h:434
int available() override
Definition ESPNowStream.h:410
bool addPeer(const char *address)
Adds a peer to which we can send info or from which we can receive info.
Definition ESPNowStream.h:284
volatile size_t available_to_write
Definition ESPNowStream.h:441
void setChannel(uint8_t ch)
Defines the WiFi Channel.
Definition ESPNowStream.h:214
size_t write(const uint8_t *data, size_t len) override
Writes the data - sends it to all registered peers.
Definition ESPNowStream.h:350
void setupReceiveBuffer()
Definition ESPNowStream.h:527
esp_now_send_cb_t send
Definition ESPNowStream.h:440
bool addPeers(const char *(&array)[size])
Adds an array of peers.
Definition ESPNowStream.h:300
int availableForWrite() override
Definition ESPNowStream.h:416
bool has_peers
Definition ESPNowStream.h:445
virtual bool begin(ESPNowStreamConfig cfg)
Initialization of ESPNow incl WIFI.
Definition ESPNowStream.h:149
void setReceiveCallback(esp_now_recv_cb_t cb)
Definition ESPNowStream.h:143
const char * macAddress()
Returns the mac address of the current ESP32.
Definition ESPNowStream.h:124
bool is_init
Definition ESPNowStream.h:443
bool addPeer(const uint8_t *address)
Adds a peer to which we can send info or from which we can receive info.
Definition ESPNowStream.h:268
static int bufferAvailableForWrite()
Definition ESPNowStream.h:763
bool addPeer(esp_now_peer_info_t &peer)
Adds a peer to which we can send info or from which we can receive info.
Definition ESPNowStream.h:237
~ESPNowStream()
Definition ESPNowStream.h:114
uint8_t getChannel()
Provides the WiFi Channel.
Definition ESPNowStream.h:224
virtual bool sendPacket(const uint8_t *data, size_t len, int &retry_count, const uint8_t *destination=nullptr)
Sends a single packet with retry logic.
Definition ESPNowStream.h:542
bool addBroadcastPeer()
Definition ESPNowStream.h:330
BufferRTOS< uint8_t > buffer
Definition ESPNowStream.h:438
size_t write(const char *peer, const uint8_t *data, size_t len)
Writes the data - sends it to all the indicated peer mac address string.
Definition ESPNowStream.h:356
static void default_recv_cb(const esp_now_recv_info *info, const uint8_t *data, int data_len)
Definition ESPNowStream.h:793
static void default_send_cb(const wifi_tx_info_t *tx_info, esp_now_send_status_t status)
Definition ESPNowStream.h:840
float getBufferPercent()
provides how much the receive buffer is filled (in percent)
Definition ESPNowStream.h:422
esp_now_recv_cb_t receive
Definition ESPNowStream.h:439
ESPNowStreamConfig cfg
Definition ESPNowStream.h:437
size_t write(const uint8_t *peer, const uint8_t *data, size_t len)
Writes the data - sends it to all the peers.
Definition ESPNowStream.h:366
ESPNowStream()
Definition ESPNowStream.h:112
ESPNowStreamConfig defaultConfig()
Definition ESPNowStream.h:118
virtual void end()
DeInitialization.
Definition ESPNowStream.h:200
bool setupMAC()
Definition ESPNowStream.h:450
bool initWiFi(wifi_mode_t mode)
Definition ESPNowStream.h:694
bool setup()
Initialization.
Definition ESPNowStream.h:717
bool setupWiFi()
Definition ESPNowStream.h:474
void resetAvailableToWrite()
Definition ESPNowStream.h:535
A simple wrapper to provide string functions on existing allocated char*. If the underlying char* is ...
Definition StrView.h:28
bool begin(const char *ssid, const char *password)
Definition WiFiZephyr.h:51
wifi_status_t status()
Definition WiFiZephyr.h:85
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition AudioCodecsBase.h:10
static ESPNowStream * ESPNowStreamSelf
Definition ESPNowStream.h:31
void delay(uint32_t ms)
Definition Arduino.h:255
static const char * BROADCAST_MAC_STR
Definition ESPNowStream.h:32
@ WL_CONNECTED
Definition WiFiZephyr.h:30
static WiFiZephyr WiFi
Definition WiFiZephyr.h:230
static const uint8_t BROADCAST_MAC[6]
Definition ESPNowStream.h:33
uint32_t millis()
Returns the milliseconds since the start.
Definition Arduino.h:256
size_t writeData(Print *p_out, T *data, int samples, int maxSamples=512)
Definition AudioTypes.h:508
Configuration for ESP-NOW protocolö.W.
Definition ESPNowStream.h:40
const char * mac_address
Definition ESPNowStream.h:45
bool use_long_range
Definition ESPNowStream.h:69
uint16_t delay_after_failed_write_ms
Delay after failed write (ms). Default: 2000.
Definition ESPNowStream.h:66
wifi_mode_t wifi_mode
WiFi mode (station or access point). Default: WIFI_STA.
Definition ESPNowStream.h:42
const char * local_master_key
Local master key for encryption (16 bytes, optional). Default: nullptr.
Definition ESPNowStream.h:84
const char * primary_master_key
Primary master key for encryption (16 bytes, optional). Default: nullptr.
Definition ESPNowStream.h:82
uint32_t ack_semaphore_timeout_ms
Timeout for ACK semaphore (ms). Default: portMAX_DELAY.
Definition ESPNowStream.h:92
uint8_t start_read_threshold_percent
Buffer fill threshold (percent) to start reading. Default: 0.
Definition ESPNowStream.h:90
const char * ssid
WiFi SSID for connection (optional). Default: nullptr.
Definition ESPNowStream.h:55
uint16_t delay_after_updating_mac_ms
Delay after updating mac.
Definition ESPNowStream.h:94
const char * password
WiFi password for connection (optional). Default: nullptr.
Definition ESPNowStream.h:57
uint16_t buffer_count
Definition ESPNowStream.h:51
void(* recveive_cb)(const esp_now_recv_info *info, const uint8_t *data, int data_len)
Receive callback for ESP-NOW (esp-idf >= 5.0.0). Default: nullptr.
Definition ESPNowStream.h:74
uint32_t oui
Definition ESPNowStream.h:61
int write_retry_count
Number of write retries (-1 for endless). Default: 1.
Definition ESPNowStream.h:71
uint16_t buffer_size
Definition ESPNowStream.h:48
bool use_send_ack
Use send acknowledgments to prevent buffer overflow. Default: true.
Definition ESPNowStream.h:64
wifi_phy_rate_t rate
ESP-NOW bit rate. Default: WIFI_PHY_RATE_6M.
Definition ESPNowStream.h:88
int channel
WiFi channel to use (0 for auto). Default: 0.
Definition ESPNowStream.h:53
wifi_phy_mode_t phymode
ESP-NOW PHY mode. Default: WIFI_PHY_MODE_11G.
Definition ESPNowStream.h:86