From 505e9c3882b9fcc0ca6f19a53736a1f2a566d071 Mon Sep 17 00:00:00 2001 From: Lucas Saavedra Vaz <32426024+lucasssvaz@users.noreply.github.com> Date: Fri, 5 Dec 2025 15:45:09 -0300 Subject: [PATCH 1/2] feat(espnow): Add PHY configuration for ESP-NOW packets --- libraries/ESP_NOW/src/ESP32_NOW.cpp | 89 +++++++++++++++++++++++++++-- libraries/ESP_NOW/src/ESP32_NOW.h | 17 +++++- 2 files changed, 99 insertions(+), 7 deletions(-) diff --git a/libraries/ESP_NOW/src/ESP32_NOW.cpp b/libraries/ESP_NOW/src/ESP32_NOW.cpp index e61160a16dd..0e07342f316 100644 --- a/libraries/ESP_NOW/src/ESP32_NOW.cpp +++ b/libraries/ESP_NOW/src/ESP32_NOW.cpp @@ -18,8 +18,8 @@ static void *new_arg = nullptr; // * tx_arg = nullptr, * rx_arg = nullptr, static bool _esp_now_has_begun = false; static ESP_NOW_Peer *_esp_now_peers[ESP_NOW_MAX_TOTAL_PEER_NUM]; -static esp_err_t _esp_now_add_peer(const uint8_t *mac_addr, uint8_t channel, wifi_interface_t iface, const uint8_t *lmk, ESP_NOW_Peer *_peer = nullptr) { - log_v(MACSTR, MAC2STR(mac_addr)); +static esp_err_t _esp_now_add_peer(const uint8_t *mac_addr, uint8_t channel, wifi_interface_t iface, const uint8_t *lmk, esp_now_rate_config_t *rate_config, ESP_NOW_Peer *_peer = nullptr) { + log_i("Adding peer " MACSTR, MAC2STR(mac_addr)); if (esp_now_is_peer_exist(mac_addr)) { log_e("Peer Already Exists"); return ESP_ERR_ESPNOW_EXIST; @@ -41,9 +41,17 @@ static esp_err_t _esp_now_add_peer(const uint8_t *mac_addr, uint8_t channel, wif for (uint8_t i = 0; i < ESP_NOW_MAX_TOTAL_PEER_NUM; i++) { if (_esp_now_peers[i] == nullptr) { _esp_now_peers[i] = _peer; + if (_esp_now_has_begun && rate_config != nullptr) { + log_i("ESP-NOW already running. Setting PHY rate for peer " MACSTR, MAC2STR(_peer->addr())); + result = esp_now_set_peer_rate_config(_peer->addr(), rate_config); + if (result != ESP_OK) { + log_w("Could not set the ESP-NOW PHY rate for peer " MACSTR, MAC2STR(_peer->addr())); + } + } return ESP_OK; } } + log_e("Library Peer list full"); return ESP_FAIL; } } else if (result == ESP_ERR_ESPNOW_NOT_INIT) { @@ -51,7 +59,7 @@ static esp_err_t _esp_now_add_peer(const uint8_t *mac_addr, uint8_t channel, wif } else if (result == ESP_ERR_ESPNOW_ARG) { log_e("Invalid Argument"); } else if (result == ESP_ERR_ESPNOW_FULL) { - log_e("Peer list full"); + log_e("ESP-NOW Peer list full"); } else if (result == ESP_ERR_ESPNOW_NO_MEM) { log_e("Out of memory"); } else if (result == ESP_ERR_ESPNOW_EXIST) { @@ -149,6 +157,21 @@ static void _esp_now_tx_cb(const uint8_t *mac_addr, esp_now_send_status_t status } } +esp_err_t _esp_now_set_all_peers_rate() { + for (uint8_t i = 0; i < ESP_NOW_MAX_TOTAL_PEER_NUM; i++) { + if (_esp_now_peers[i] != nullptr) { + log_v("Setting PHY rate for peer " MACSTR, MAC2STR(_esp_now_peers[i]->addr())); + esp_now_rate_config_t rate = _esp_now_peers[i]->getRate(); + esp_err_t err = esp_now_set_peer_rate_config(_esp_now_peers[i]->addr(), &rate); + if (err != ESP_OK) { + log_e("Failed to set rate for peer " MACSTR, MAC2STR(_esp_now_peers[i]->addr())); + return err; + } + } + } + return ESP_OK; +} + ESP_NOW_Class::ESP_NOW_Class() { max_data_len = 0; version = 0; @@ -195,6 +218,14 @@ bool ESP_NOW_Class::begin(const uint8_t *pmk) { return false; } + // Set the peers PHY rate after initializing ESP-NOW. + err = _esp_now_set_all_peers_rate(); + if (err != ESP_OK) { + log_e("Failed to set PHY rate for peers! 0x%x", err); + _esp_now_has_begun = false; + return false; + } + if (pmk) { err = esp_now_set_pmk(pmk); if (err != ESP_OK) { @@ -243,6 +274,7 @@ bool ESP_NOW_Class::end() { int ESP_NOW_Class::getTotalPeerCount() const { if (!_esp_now_has_begun) { + log_e("ESP-NOW not initialized"); return -1; } esp_now_peer_num_t num; @@ -256,6 +288,7 @@ int ESP_NOW_Class::getTotalPeerCount() const { int ESP_NOW_Class::getEncryptedPeerCount() const { if (!_esp_now_has_begun) { + log_e("ESP-NOW not initialized"); return -1; } esp_now_peer_num_t num; @@ -295,6 +328,7 @@ int ESP_NOW_Class::availableForWrite() { size_t ESP_NOW_Class::write(const uint8_t *data, size_t len) { if (!_esp_now_has_begun) { + log_e("ESP-NOW not initialized. Please call begin() first to send data."); return 0; } if (len > max_data_len) { @@ -336,7 +370,7 @@ ESP_NOW_Class ESP_NOW; * */ -ESP_NOW_Peer::ESP_NOW_Peer(const uint8_t *mac_addr, uint8_t channel, wifi_interface_t iface, const uint8_t *lmk) { +ESP_NOW_Peer::ESP_NOW_Peer(const uint8_t *mac_addr, uint8_t channel, wifi_interface_t iface, const uint8_t *lmk, esp_now_rate_config_t *rate_config) { added = false; if (mac_addr) { memcpy(mac, mac_addr, 6); @@ -347,6 +381,11 @@ ESP_NOW_Peer::ESP_NOW_Peer(const uint8_t *mac_addr, uint8_t channel, wifi_interf if (encrypt) { memcpy(key, lmk, 16); } + if (rate_config) { + rate = *rate_config; + } else { + rate = DEFAULT_ESPNOW_RATE_CONFIG; + } } bool ESP_NOW_Peer::add() { @@ -356,7 +395,8 @@ bool ESP_NOW_Peer::add() { if (added) { return true; } - if (_esp_now_add_peer(mac, chan, ifc, encrypt ? key : nullptr, this) != ESP_OK) { + if (_esp_now_add_peer(mac, chan, ifc, encrypt ? key : nullptr, &rate, this) != ESP_OK) { + log_e("Failed to add peer " MACSTR, MAC2STR(mac)); return false; } log_v("Peer added - " MACSTR, MAC2STR(mac)); @@ -371,12 +411,15 @@ bool ESP_NOW_Peer::remove() { if (!added) { return true; } - log_v("Peer removed - " MACSTR, MAC2STR(mac)); + log_i("Removing peer - " MACSTR, MAC2STR(mac)); esp_err_t err = _esp_now_del_peer(mac); if (err == ESP_OK) { added = false; + log_i("Peer removed - " MACSTR, MAC2STR(mac)); return true; } + + log_e("Failed to remove peer " MACSTR, MAC2STR(mac)); return false; } @@ -389,6 +432,8 @@ bool ESP_NOW_Peer::addr(const uint8_t *mac_addr) { memcpy(mac, mac_addr, 6); return true; } + log_e("Peer already added and ESP-NOW is already running. Cannot change the MAC address."); + log_e("Please call addr() before adding the peer or before starting ESP-NOW."); return false; } @@ -416,6 +461,38 @@ bool ESP_NOW_Peer::setInterface(wifi_interface_t iface) { return _esp_now_modify_peer(mac, chan, ifc, encrypt ? key : nullptr) == ESP_OK; } +/** + * @brief Set the rate configuration for the peer. + * + * @param rate_config Pointer to the rate configuration to set. Nullptr to reset to default rate configuration. + * @return true if the rate configuration was set successfully, false otherwise. + */ +bool ESP_NOW_Peer::setRate(const esp_now_rate_config_t *rate_config) { + if (added && _esp_now_has_begun) { + log_e("Peer already added and ESP-NOW is already running. Cannot set rate configuration."); + log_e("Please call setRate() before adding the peer or before starting ESP-NOW."); + return false; + } + + if (rate_config == nullptr) { + log_i("Resetting rate configuration to default."); + rate = DEFAULT_ESPNOW_RATE_CONFIG; + } else { + rate = *rate_config; + } + + return true; +} + +/** + * @brief Get the rate configuration for the peer. + * + * @return esp_now_rate_config_t The rate configuration for the peer. + */ +esp_now_rate_config_t ESP_NOW_Peer::getRate() const { + return rate; +} + bool ESP_NOW_Peer::isEncrypted() const { return encrypt; } diff --git a/libraries/ESP_NOW/src/ESP32_NOW.h b/libraries/ESP_NOW/src/ESP32_NOW.h index 6bf612a1263..c069b5fa531 100644 --- a/libraries/ESP_NOW/src/ESP32_NOW.h +++ b/libraries/ESP_NOW/src/ESP32_NOW.h @@ -11,6 +11,15 @@ #include "esp32-hal-log.h" #include "esp_mac.h" +// clang-format off +#define DEFAULT_ESPNOW_RATE_CONFIG { \ + .phymode = WIFI_PHY_MODE_11G, \ + .rate = WIFI_PHY_RATE_1M_L, \ + .ersu = false, \ + .dcm = false \ +} +// clang-format on + class ESP_NOW_Peer; //forward declaration for friend function class ESP_NOW_Class : public Print { @@ -29,6 +38,8 @@ class ESP_NOW_Class : public Print { int getVersion() const; int availableForWrite(); + + // You can directly send data to all peers without broadcasting using ESP_NOW.write(data, len) size_t write(const uint8_t *data, size_t len); size_t write(uint8_t data) { return write(&data, 1); @@ -47,6 +58,7 @@ class ESP_NOW_Peer { uint8_t mac[6]; uint8_t chan; wifi_interface_t ifc; + esp_now_rate_config_t rate; bool encrypt; uint8_t key[16]; @@ -56,7 +68,7 @@ class ESP_NOW_Peer { bool remove(); size_t send(const uint8_t *data, int len); - ESP_NOW_Peer(const uint8_t *mac_addr, uint8_t channel = 0, wifi_interface_t iface = WIFI_IF_AP, const uint8_t *lmk = nullptr); + ESP_NOW_Peer(const uint8_t *mac_addr, uint8_t channel = 0, wifi_interface_t iface = WIFI_IF_AP, const uint8_t *lmk = nullptr, esp_now_rate_config_t *rate_config = nullptr); public: virtual ~ESP_NOW_Peer() {} @@ -70,6 +82,9 @@ class ESP_NOW_Peer { wifi_interface_t getInterface() const; bool setInterface(wifi_interface_t iface); + bool setRate(const esp_now_rate_config_t *rate_config); + esp_now_rate_config_t getRate() const; + bool isEncrypted() const; bool setKey(const uint8_t *lmk); From 0f9035a759c911d6bd21783c023d7aed07c4121b Mon Sep 17 00:00:00 2001 From: "pre-commit-ci-lite[bot]" <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Date: Mon, 8 Dec 2025 12:15:10 +0000 Subject: [PATCH 2/2] ci(pre-commit): Apply automatic fixes --- libraries/ESP_NOW/src/ESP32_NOW.cpp | 4 +++- libraries/ESP_NOW/src/ESP32_NOW.h | 5 ++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/libraries/ESP_NOW/src/ESP32_NOW.cpp b/libraries/ESP_NOW/src/ESP32_NOW.cpp index 0e07342f316..3fb96277dbb 100644 --- a/libraries/ESP_NOW/src/ESP32_NOW.cpp +++ b/libraries/ESP_NOW/src/ESP32_NOW.cpp @@ -18,7 +18,9 @@ static void *new_arg = nullptr; // * tx_arg = nullptr, * rx_arg = nullptr, static bool _esp_now_has_begun = false; static ESP_NOW_Peer *_esp_now_peers[ESP_NOW_MAX_TOTAL_PEER_NUM]; -static esp_err_t _esp_now_add_peer(const uint8_t *mac_addr, uint8_t channel, wifi_interface_t iface, const uint8_t *lmk, esp_now_rate_config_t *rate_config, ESP_NOW_Peer *_peer = nullptr) { +static esp_err_t _esp_now_add_peer( + const uint8_t *mac_addr, uint8_t channel, wifi_interface_t iface, const uint8_t *lmk, esp_now_rate_config_t *rate_config, ESP_NOW_Peer *_peer = nullptr +) { log_i("Adding peer " MACSTR, MAC2STR(mac_addr)); if (esp_now_is_peer_exist(mac_addr)) { log_e("Peer Already Exists"); diff --git a/libraries/ESP_NOW/src/ESP32_NOW.h b/libraries/ESP_NOW/src/ESP32_NOW.h index c069b5fa531..42a24aa84d9 100644 --- a/libraries/ESP_NOW/src/ESP32_NOW.h +++ b/libraries/ESP_NOW/src/ESP32_NOW.h @@ -68,7 +68,10 @@ class ESP_NOW_Peer { bool remove(); size_t send(const uint8_t *data, int len); - ESP_NOW_Peer(const uint8_t *mac_addr, uint8_t channel = 0, wifi_interface_t iface = WIFI_IF_AP, const uint8_t *lmk = nullptr, esp_now_rate_config_t *rate_config = nullptr); + ESP_NOW_Peer( + const uint8_t *mac_addr, uint8_t channel = 0, wifi_interface_t iface = WIFI_IF_AP, const uint8_t *lmk = nullptr, + esp_now_rate_config_t *rate_config = nullptr + ); public: virtual ~ESP_NOW_Peer() {}