13#ifdef ESP_NOW_MAX_DATA_LEN_V2
15#define MY_ESP_NOW_MAX_LEN ESP_NOW_MAX_DATA_LEN_V2
18#define MY_ESP_NOW_MAX_LEN ESP_NOW_MAX_DATA_LEN
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)
33static const uint8_t
BROADCAST_MAC[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
55 const char*
ssid =
nullptr;
58#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 5, 0)
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;
78 void (*
recveive_cb)(
const uint8_t* mac_addr,
const uint8_t* data,
79 int data_len) =
nullptr;
86 wifi_phy_mode_t
phymode = WIFI_PHY_MODE_11G;
88 wifi_phy_rate_t
rate = WIFI_PHY_RATE_6M;
126 static String mac_str =
WiFi.macAddress();
127 return mac_str.c_str();
129 static char mac_str[18] = {0};
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]);
152 if (
WiFi.getMode() == WIFI_MODE_NULL) {
159 esp_err_t ret = esp_wifi_get_mode(&mode);
161 if (mode == WIFI_MODE_NULL) {
178 uint8_t proto = WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N;
180 proto |= WIFI_PROTOCOL_LR;
185#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
186 LOGI(
"Setting ESP-NEW rate");
188 LOGW(
"Could not set rate");
202 if (esp_now_deinit() != ESP_OK) {
203 LOGE(
"esp_now_deinit");
216 WiFi.setChannel(ch, WIFI_SECOND_CHAN_NONE);
218 esp_wifi_set_channel(ch, WIFI_SECOND_CHAN_NONE);
226 uint32_t ch =
WiFi.channel();
227 return (uint8_t)ch ^ 0xff;
230 wifi_second_chan_t second;
231 esp_wifi_get_channel(&primary, &second);
239 LOGE(
"addPeer before begin");
243 LOGI(
"Using broadcast");
246 esp_err_t result = esp_now_add_peer(&peer);
247 if (result == ESP_OK) {
249#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
250 esp_now_rate_config_t rate_config = {.phymode =
cfg.
phymode,
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));
262 LOGE(
"addPeer: %d", result);
264 return result == ESP_OK;
269 esp_now_peer_info_t peer;
270 memcpy(peer.peer_addr, address, ESP_NOW_ETH_ALEN);
274 peer.encrypt =
false;
286 LOGW(
"Did not add own address as peer");
290 uint8_t mac[] = {0, 0, 0, 0, 0, 0};
291 if (!
str2mac(address, (uint8_t*)&mac)) {
292 LOGE(
"addPeer - Invalid address: %s", address);
295 return addPeer((
const uint8_t*)&mac);
299 template <
size_t size>
302 for (
int j = 0; j < size; j++) {
303 const char* peer = array[j];
304 if (peer !=
nullptr) {
317 for (
int j = 0; j < N; j++) {
318 const uint8_t* peer = array[j];
319 if (peer !=
nullptr) {
334 esp_now_peer_info_t peer;
335 uint8_t breakout_counter = 0;
336 while ((esp_now_fetch_peer(
true, &peer) == ESP_OK) &&
337 (breakout_counter < ESP_NOW_MAX_TOTAL_PEER_NUM + 1)) {
338 esp_now_del_peer(peer.peer_addr);
342 if (breakout_counter == ESP_NOW_MAX_TOTAL_PEER_NUM + 1) {
343 LOGE(
"Not all Peers seems to be removed.");
346 return breakout_counter <= ESP_NOW_MAX_TOTAL_PEER_NUM;
350 size_t write(
const uint8_t* data,
size_t len)
override {
352 return write((
const uint8_t*)
nullptr, data, len);
356 size_t write(
const char* peer,
const uint8_t* data,
size_t len) {
359 LOGE(
"write: invalid mac address %s", peer);
362 return write(mac, data, len);
366 size_t write(
const uint8_t* peer,
const uint8_t* data,
size_t len) {
375 size_t total_sent = 0;
376 size_t remaining = len;
378 while (remaining > 0) {
383 sendPacket(data + total_sent, chunk_size, retry_count, peer);
387 total_sent += chunk_size;
388 remaining -= chunk_size;
392 "write: failed to send chunk after %d attempts (sent %zu/%zu "
394 retry_count, total_sent, len);
425 if (size == 0)
return 0.0;
454 uint8_t mac[ESP_NOW_KEY_LEN];
457 LOGE(
"Could not set mac address");
467 LOGE(
"Wrong mac address: %s", addr);
486 LOGE(
"You did not start Wifi or did not provide ssid and password");
491 wifi_ap_record_t ap_info;
492 if (esp_wifi_sta_get_ap_info(&ap_info) != ESP_OK) {
494 wifi_config_t wifi_config = {};
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++) {
502 if (esp_wifi_sta_get_ap_info(&ap_info) == ESP_OK)
break;
508 if (esp_wifi_get_mode(&mode) == ESP_OK && mode == WIFI_MODE_AP) {
509 wifi_ap_record_t ap_info;
510 if (esp_wifi_sta_get_ap_info(&ap_info) != ESP_OK) {
511 LOGE(
"You did not start Wifi or did not provide ssid and password");
542 virtual bool sendPacket(
const uint8_t* data,
size_t len,
int& retry_count,
543 const uint8_t* destination =
nullptr) {
545 const uint8_t* target = destination;
563 LOGE(
"Timeout waiting for ACK semaphore after %d retries",
568 LOGW(
"ACK semaphore timeout (attempt %d)", retry_count);
575 esp_err_t rc = esp_now_send(target, data, len);
599 LOGE(
"esp_now_send queue error (rc=%d/0x%04X) after %d retries", rc,
605 LOGW(
"esp_now_send failed (rc=%d/0x%04X) - retrying (attempt %d)", rc,
624 LOGE(
"Transmission callback timeout after %d retries", retry_count);
628 LOGW(
"Transmission callback timeout (attempt %d)", retry_count);
643 LOGE(
"Transmission failed after %d retries", retry_count);
648 LOGI(
"Transmission failed - retrying (attempt %d)", retry_count);
666 LOGW(
"esp_now_send failed to queue (rc=%d/0x%04X) - retrying (attempt %d)",
667 rc, rc, retry_count);
670 LOGE(
"Send queue error after %d retries", retry_count);
695 wifi_init_config_t wifi_init_cfg = WIFI_INIT_CONFIG_DEFAULT();
696 esp_err_t ret = esp_wifi_init(&wifi_init_cfg);
698 LOGE(
"esp_wifi_init: %s (ensure NVS and netif are initialized)",
699 esp_err_to_name(ret));
702 ret = esp_wifi_set_mode(mode);
704 LOGE(
"esp_wifi_set_mode: %s", esp_err_to_name(ret));
707 ret = esp_wifi_start();
709 LOGE(
"esp_wifi_start: %s", esp_err_to_name(ret));
718 esp_err_t result = esp_now_init();
719 if (result == ESP_OK) {
722 LOGE(
"esp_now_init: %d", result);
725#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 5, 0)
727 esp_now_set_user_oui((uint8_t*)
cfg.
oui);
739 esp_now_register_recv_cb(
receive);
742 esp_now_register_send_cb(
send);
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;
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;
768 int data_len,
bool broadcast, uint8_t rssi) {
769 LOGD(
"rec_cb: %d", data_len);
779 if (result != data_len) {
780 LOGE(
"writeArray %d -> %d", data_len, result);
792#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
794 const uint8_t* data,
int data_len) {
795 const bool broadcast =
796 memcmp(info->des_addr,
BROADCAST_MAC, ESP_NOW_ETH_ALEN) == 0;
798 info->rx_ctrl->rssi);
801 static void default_recv_cb(
const uint8_t* mac_addr,
const uint8_t* data,
808 esp_now_send_status_t status) {
809 static uint8_t first_mac[ESP_NOW_KEY_LEN] = {0};
812 if (first_mac[0] == 0) {
813 strncpy((
char*)first_mac, (
char*)mac_addr, ESP_NOW_KEY_LEN);
815 LOGD(
"default_send_cb - %s -> %s", this->
mac2str(mac_addr),
816 status == ESP_NOW_SEND_SUCCESS ?
"+" :
"-");
819 if (strncmp((
char*)mac_addr, (
char*)first_mac, ESP_NOW_KEY_LEN) == 0) {
823 this->last_send_success = (status == ESP_NOW_SEND_SUCCESS);
825 if (status == ESP_NOW_SEND_SUCCESS) {
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);
835 xSemaphoreGive(this->xSemaphore);
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;
845 esp_now_send_status_t status) {
#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