6#include "AudioTools/Concurrency/RTOS.h"
7#include "AudioTools/CoreAudio/AudioBasic/StrView.h"
8#include "AudioTools/CoreAudio/BaseStream.h"
11#ifdef ESP_NOW_MAX_DATA_LEN_V2
13#define MY_ESP_NOW_MAX_LEN ESP_NOW_MAX_DATA_LEN_V2
16#define MY_ESP_NOW_MAX_LEN ESP_NOW_MAX_DATA_LEN
22#define MY_ESP_NOW_BUFFER_SIZE (240 * 400)
23#define MY_ESP_NOW_BUFFER_COUNT (MY_ESP_NOW_BUFFER_SIZE / MY_ESP_NOW_MAX_LEN)
29static ESPNowStream* ESPNowStreamSelf =
nullptr;
30static const char* BROADCAST_MAC_STR =
"FF:FF:FF:FF:FF:FF";
31static const uint8_t BROADCAST_MAC[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
53 const char*
ssid =
nullptr;
56#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 5, 0)
67 bool use_long_range =
false;
70#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
72 void (*
recveive_cb)(
const esp_now_recv_info* info,
const uint8_t* data,
73 int data_len) =
nullptr;
76 void (*
recveive_cb)(
const uint8_t* mac_addr,
const uint8_t* data,
77 int data_len) =
nullptr;
84 wifi_phy_mode_t
phymode = WIFI_PHY_MODE_11G;
86 wifi_phy_rate_t
rate = WIFI_PHY_RATE_6M;
113 if (xSemaphore !=
nullptr) vSemaphoreDelete(xSemaphore);
123 static String mac_str = WiFi.macAddress();
124 return mac_str.c_str();
140 if (WiFi.getMode() == WIFI_MODE_NULL) {
146 if (!setupMAC())
return false;
148 if (!setupWiFi())
return false;
150 WiFi.enableLongRange(cfg.use_long_range);
152#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
153 LOGI(
"Setting ESP-NEW rate");
154 if (esp_wifi_config_espnow_rate(getInterface(), cfg.
rate) != ESP_OK) {
155 LOGW(
"Could not set rate");
161 Serial.print(
"mac: ");
162 Serial.println(WiFi.macAddress());
163 Serial.print(
"channel: ");
171 if (esp_now_deinit() != ESP_OK) {
172 LOGE(
"esp_now_deinit");
174 if (buffer.size() > 0) buffer.
resize(0);
178 is_broadcast =
false;
184 WiFi.setChannel(ch, WIFI_SECOND_CHAN_NONE);
190 uint32_t ch = WiFi.channel();
191 return (uint8_t)ch ^ 0xff;
197 LOGE(
"addPeer before begin");
200 if (memcmp(BROADCAST_MAC, peer.peer_addr, 6) == 0) {
201 LOGI(
"Using broadcast");
204 esp_err_t result = esp_now_add_peer(&peer);
205 if (result == ESP_OK) {
206 LOGI(
"addPeer: %s", mac2str(peer.peer_addr));
207#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
208 esp_now_rate_config_t rate_config = {.phymode = cfg.
phymode,
212 result = esp_now_set_peer_rate_config(peer.peer_addr, &rate_config);
213 if (result != ESP_OK) {
214 LOGW(
"Could not set the ESP-NOW PHY rate (%d) %s.", result,
215 esp_err_to_name(result));
218 has_peers = result == ESP_OK;
220 LOGE(
"addPeer: %d", result);
222 return result == ESP_OK;
227 esp_now_peer_info_t peer;
228 memcpy(peer.peer_addr, address, ESP_NOW_ETH_ALEN);
231 peer.ifidx = getInterface();
232 peer.encrypt =
false;
244 LOGW(
"Did not add own address as peer");
248 uint8_t mac[] = {0, 0, 0, 0, 0, 0};
249 if (!str2mac(address, (uint8_t*)&mac)) {
250 LOGE(
"addPeer - Invalid address: %s", address);
253 return addPeer((
const uint8_t*)&mac);
257 template <
size_t size>
260 for (
int j = 0; j < size; j++) {
261 const char* peer = array[j];
262 if (peer !=
nullptr) {
275 for (
int j = 0; j < N; j++) {
276 const uint8_t* peer = array[j];
277 if (peer !=
nullptr) {
292 esp_now_peer_info_t peer;
293 uint8_t breakout_counter = 0;
294 while ((esp_now_fetch_peer(
true, &peer) == ESP_OK) &&
295 (breakout_counter < ESP_NOW_MAX_TOTAL_PEER_NUM + 1)) {
296 esp_now_del_peer(peer.peer_addr);
300 if (breakout_counter == ESP_NOW_MAX_TOTAL_PEER_NUM + 1) {
301 LOGE(
"Not all Peers seems to be removed.");
304 return breakout_counter <= ESP_NOW_MAX_TOTAL_PEER_NUM;
308 size_t write(
const uint8_t* data,
size_t len)
override {
310 return write((
const uint8_t*)
nullptr, data, len);
314 size_t write(
const char* peer,
const uint8_t* data,
size_t len) {
316 if (!str2mac(peer, mac)) {
317 LOGE(
"write: invalid mac address %s", peer);
320 return write(mac, data, len);
324 size_t write(
const uint8_t* peer,
const uint8_t* data,
size_t len) {
329 if (!has_peers && peer ==
nullptr) {
333 size_t total_sent = 0;
334 size_t remaining = len;
336 while (remaining > 0) {
337 size_t chunk_size = min(remaining, (
size_t)MY_ESP_NOW_MAX_LEN);
341 sendPacket(data + total_sent, chunk_size, retry_count, peer);
345 total_sent += chunk_size;
346 remaining -= chunk_size;
350 "write: failed to send chunk after %d attempts (sent %zu/%zu "
352 retry_count, total_sent, len);
363 if (!read_ready)
return 0;
364 if (buffer.size() == 0)
return 0;
368 int available()
override {
369 if (!buffer)
return 0;
370 if (!read_ready)
return 0;
371 return buffer.size() == 0 ? 0 : buffer.
available();
374 int availableForWrite()
override {
375 if (!buffer)
return 0;
381 int size = buffer.size();
383 if (size == 0)
return 0.0;
385 return 100.0 * buffer.
available() / size;
397 esp_now_recv_cb_t receive = default_recv_cb;
398 esp_now_send_cb_t send = default_send_cb;
399 volatile size_t available_to_write = 0;
400 volatile bool last_send_success =
true;
401 bool is_init =
false;
402 SemaphoreHandle_t xSemaphore =
nullptr;
403 bool has_peers =
false;
404 bool read_ready =
false;
405 bool is_broadcast =
false;
406 uint32_t last_io_success_time = 0;
412 byte mac[ESP_NOW_KEY_LEN];
414 if (esp_wifi_set_mac((wifi_interface_t)getInterface(), mac) != ESP_OK) {
415 LOGE(
"Could not set mac address");
425 LOGE(
"Wrong mac address: %s", addr);
433 if (WiFi.status() != WL_CONNECTED) {
436 LOGI(
"Logging into WiFi: %s", cfg.
ssid);
438 while (WiFi.status() != WL_CONNECTED) {
447 if (WiFi.getMode() == WIFI_AP && WiFi.status() != WL_CONNECTED) {
448 LOGE(
"You did not start Wifi or did not provide ssid and password");
455 inline void setupSemaphore() {
458 xSemaphore = xSemaphoreCreateBinary();
459 xSemaphoreGive(xSemaphore);
463 inline void setupReceiveBuffer() {
471 inline void resetAvailableToWrite() {
473 available_to_write = 0;
478 virtual bool sendPacket(
const uint8_t* data,
size_t len,
int& retry_count,
479 const uint8_t* destination =
nullptr) {
481 const uint8_t* target = destination;
482 if (target ==
nullptr && is_broadcast) {
483 target = BROADCAST_MAC;
487 resetAvailableToWrite();
494 if (xSemaphoreTake(xSemaphore, ticks) != pdTRUE) {
499 LOGE(
"Timeout waiting for ACK semaphore after %d retries",
504 LOGW(
"ACK semaphore timeout (attempt %d)", retry_count);
511 esp_err_t rc = esp_now_send(target, data, len);
529 xSemaphoreGive(xSemaphore);
535 LOGE(
"esp_now_send queue error (rc=%d/0x%04X) after %d retries", rc,
541 LOGW(
"esp_now_send failed (rc=%d/0x%04X) - retrying (attempt %d)", rc,
556 if (xSemaphoreTake(xSemaphore, ticks) != pdTRUE) {
560 LOGE(
"Transmission callback timeout after %d retries", retry_count);
564 LOGW(
"Transmission callback timeout (attempt %d)", retry_count);
570 if (last_send_success) {
571 xSemaphoreGive(xSemaphore);
574 xSemaphoreGive(xSemaphore);
579 LOGE(
"Transmission failed after %d retries", retry_count);
584 LOGI(
"Transmission failed - retrying (attempt %d)", retry_count);
598 xSemaphoreGive(xSemaphore);
602 LOGW(
"esp_now_send failed to queue (rc=%d/0x%04X) - retrying (attempt %d)",
603 rc, rc, retry_count);
606 LOGE(
"Send queue error after %d retries", retry_count);
618 wifi_interface_t getInterface() {
620 wifi_interface_t result;
623 result = (wifi_interface_t)ESP_IF_WIFI_STA;
626 result = (wifi_interface_t)ESP_IF_WIFI_AP;
629 result = (wifi_interface_t)0;
637 esp_err_t result = esp_now_init();
638 if (result == ESP_OK) {
641 LOGE(
"esp_now_init: %d", result);
644#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 5, 0)
646 esp_now_set_user_oui((uint8_t*)cfg.
oui);
658 esp_now_register_recv_cb(receive);
661 esp_now_register_send_cb(send);
664 is_init = result == ESP_OK;
668 bool str2mac(
const char* mac, uint8_t* values) {
669 sscanf(mac,
"%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &values[0], &values[1],
670 &values[2], &values[3], &values[4], &values[5]);
671 return strlen(mac) == 17;
674 const char* mac2str(
const uint8_t* array) {
675 static char macStr[18];
676 memset(macStr, 0, 18);
677 snprintf(macStr, 18,
"%02x:%02x:%02x:%02x:%02x:%02x", array[0], array[1],
678 array[2], array[3], array[4], array[5]);
679 return (
const char*)macStr;
682 static int bufferAvailableForWrite() {
686 virtual void handle_recv_cb(
const uint8_t* mac_addr,
const uint8_t* data,
687 int data_len,
bool broadcast, uint8_t rssi) {
688 LOGD(
"rec_cb: %d", data_len);
691 setupReceiveBuffer();
694 last_io_success_time =
millis();
697 size_t result = buffer.
writeArray(data, data_len);
698 if (result != data_len) {
699 LOGE(
"writeArray %d -> %d", data_len, result);
702 if (read_ready ==
false) {
711#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
712 static void default_recv_cb(
const esp_now_recv_info* info,
713 const uint8_t* data,
int data_len) {
714 const bool broadcast =
715 memcmp(info->des_addr, BROADCAST_MAC, ESP_NOW_ETH_ALEN) == 0;
716 ESPNowStreamSelf->handle_recv_cb(info->src_addr, data, data_len, broadcast,
717 info->rx_ctrl->rssi);
720 static void default_recv_cb(
const uint8_t* mac_addr,
const uint8_t* data,
722 ESPNowStreamSelf->handle_recv_cb(mac_addr, data, data_len,
false, 255);
726 virtual void handle_send_cb(
const uint8_t* mac_addr,
727 esp_now_send_status_t status) {
728 static uint8_t first_mac[ESP_NOW_KEY_LEN] = {0};
731 if (first_mac[0] == 0) {
732 strncpy((
char*)first_mac, (
char*)mac_addr, ESP_NOW_KEY_LEN);
734 LOGD(
"default_send_cb - %s -> %s", this->mac2str(mac_addr),
735 status == ESP_NOW_SEND_SUCCESS ?
"+" :
"-");
738 if (strncmp((
char*)mac_addr, (
char*)first_mac, ESP_NOW_KEY_LEN) == 0) {
742 this->last_send_success = (status == ESP_NOW_SEND_SUCCESS);
744 if (status == ESP_NOW_SEND_SUCCESS) {
745 last_io_success_time =
millis();
748 "Send Error to %s! Status: %d (Possible causes: out of range, "
749 "receiver busy/offline, channel mismatch, or buffer full)",
750 this->mac2str(mac_addr), status);
754 xSemaphoreGive(this->xSemaphore);
758#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 5, 0)
759 static void default_send_cb(
const wifi_tx_info_t* tx_info,
760 esp_now_send_status_t status) {
761 const uint8_t* mac_addr = tx_info->des_addr;
763 static void default_send_cb(
const uint8_t* mac_addr,
764 esp_now_send_status_t status) {
766 ESPNowStreamSelf->handle_send_cb(mac_addr, status);