Skip to content

Commit 2fc25d7

Browse files
feat(espnow): Add PHY configuration for ESP-NOW packets (#12108)
* feat(espnow): Add PHY configuration for ESP-NOW packets * ci(pre-commit): Apply automatic fixes --------- Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
1 parent 0cc800e commit 2fc25d7

File tree

2 files changed

+104
-7
lines changed

2 files changed

+104
-7
lines changed

libraries/ESP_NOW/src/ESP32_NOW.cpp

Lines changed: 85 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,10 @@ static void *new_arg = nullptr; // * tx_arg = nullptr, * rx_arg = nullptr,
1818
static bool _esp_now_has_begun = false;
1919
static ESP_NOW_Peer *_esp_now_peers[ESP_NOW_MAX_TOTAL_PEER_NUM];
2020

21-
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) {
22-
log_v(MACSTR, MAC2STR(mac_addr));
21+
static esp_err_t _esp_now_add_peer(
22+
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
23+
) {
24+
log_i("Adding peer " MACSTR, MAC2STR(mac_addr));
2325
if (esp_now_is_peer_exist(mac_addr)) {
2426
log_e("Peer Already Exists");
2527
return ESP_ERR_ESPNOW_EXIST;
@@ -41,17 +43,25 @@ static esp_err_t _esp_now_add_peer(const uint8_t *mac_addr, uint8_t channel, wif
4143
for (uint8_t i = 0; i < ESP_NOW_MAX_TOTAL_PEER_NUM; i++) {
4244
if (_esp_now_peers[i] == nullptr) {
4345
_esp_now_peers[i] = _peer;
46+
if (_esp_now_has_begun && rate_config != nullptr) {
47+
log_i("ESP-NOW already running. Setting PHY rate for peer " MACSTR, MAC2STR(_peer->addr()));
48+
result = esp_now_set_peer_rate_config(_peer->addr(), rate_config);
49+
if (result != ESP_OK) {
50+
log_w("Could not set the ESP-NOW PHY rate for peer " MACSTR, MAC2STR(_peer->addr()));
51+
}
52+
}
4453
return ESP_OK;
4554
}
4655
}
56+
log_e("Library Peer list full");
4757
return ESP_FAIL;
4858
}
4959
} else if (result == ESP_ERR_ESPNOW_NOT_INIT) {
5060
log_e("ESPNOW Not Init");
5161
} else if (result == ESP_ERR_ESPNOW_ARG) {
5262
log_e("Invalid Argument");
5363
} else if (result == ESP_ERR_ESPNOW_FULL) {
54-
log_e("Peer list full");
64+
log_e("ESP-NOW Peer list full");
5565
} else if (result == ESP_ERR_ESPNOW_NO_MEM) {
5666
log_e("Out of memory");
5767
} else if (result == ESP_ERR_ESPNOW_EXIST) {
@@ -149,6 +159,21 @@ static void _esp_now_tx_cb(const uint8_t *mac_addr, esp_now_send_status_t status
149159
}
150160
}
151161

162+
esp_err_t _esp_now_set_all_peers_rate() {
163+
for (uint8_t i = 0; i < ESP_NOW_MAX_TOTAL_PEER_NUM; i++) {
164+
if (_esp_now_peers[i] != nullptr) {
165+
log_v("Setting PHY rate for peer " MACSTR, MAC2STR(_esp_now_peers[i]->addr()));
166+
esp_now_rate_config_t rate = _esp_now_peers[i]->getRate();
167+
esp_err_t err = esp_now_set_peer_rate_config(_esp_now_peers[i]->addr(), &rate);
168+
if (err != ESP_OK) {
169+
log_e("Failed to set rate for peer " MACSTR, MAC2STR(_esp_now_peers[i]->addr()));
170+
return err;
171+
}
172+
}
173+
}
174+
return ESP_OK;
175+
}
176+
152177
ESP_NOW_Class::ESP_NOW_Class() {
153178
max_data_len = 0;
154179
version = 0;
@@ -195,6 +220,14 @@ bool ESP_NOW_Class::begin(const uint8_t *pmk) {
195220
return false;
196221
}
197222

223+
// Set the peers PHY rate after initializing ESP-NOW.
224+
err = _esp_now_set_all_peers_rate();
225+
if (err != ESP_OK) {
226+
log_e("Failed to set PHY rate for peers! 0x%x", err);
227+
_esp_now_has_begun = false;
228+
return false;
229+
}
230+
198231
if (pmk) {
199232
err = esp_now_set_pmk(pmk);
200233
if (err != ESP_OK) {
@@ -243,6 +276,7 @@ bool ESP_NOW_Class::end() {
243276

244277
int ESP_NOW_Class::getTotalPeerCount() const {
245278
if (!_esp_now_has_begun) {
279+
log_e("ESP-NOW not initialized");
246280
return -1;
247281
}
248282
esp_now_peer_num_t num;
@@ -256,6 +290,7 @@ int ESP_NOW_Class::getTotalPeerCount() const {
256290

257291
int ESP_NOW_Class::getEncryptedPeerCount() const {
258292
if (!_esp_now_has_begun) {
293+
log_e("ESP-NOW not initialized");
259294
return -1;
260295
}
261296
esp_now_peer_num_t num;
@@ -295,6 +330,7 @@ int ESP_NOW_Class::availableForWrite() {
295330

296331
size_t ESP_NOW_Class::write(const uint8_t *data, size_t len) {
297332
if (!_esp_now_has_begun) {
333+
log_e("ESP-NOW not initialized. Please call begin() first to send data.");
298334
return 0;
299335
}
300336
if (len > max_data_len) {
@@ -336,7 +372,7 @@ ESP_NOW_Class ESP_NOW;
336372
*
337373
*/
338374

339-
ESP_NOW_Peer::ESP_NOW_Peer(const uint8_t *mac_addr, uint8_t channel, wifi_interface_t iface, const uint8_t *lmk) {
375+
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) {
340376
added = false;
341377
if (mac_addr) {
342378
memcpy(mac, mac_addr, 6);
@@ -347,6 +383,11 @@ ESP_NOW_Peer::ESP_NOW_Peer(const uint8_t *mac_addr, uint8_t channel, wifi_interf
347383
if (encrypt) {
348384
memcpy(key, lmk, 16);
349385
}
386+
if (rate_config) {
387+
rate = *rate_config;
388+
} else {
389+
rate = DEFAULT_ESPNOW_RATE_CONFIG;
390+
}
350391
}
351392

352393
bool ESP_NOW_Peer::add() {
@@ -356,7 +397,8 @@ bool ESP_NOW_Peer::add() {
356397
if (added) {
357398
return true;
358399
}
359-
if (_esp_now_add_peer(mac, chan, ifc, encrypt ? key : nullptr, this) != ESP_OK) {
400+
if (_esp_now_add_peer(mac, chan, ifc, encrypt ? key : nullptr, &rate, this) != ESP_OK) {
401+
log_e("Failed to add peer " MACSTR, MAC2STR(mac));
360402
return false;
361403
}
362404
log_v("Peer added - " MACSTR, MAC2STR(mac));
@@ -371,12 +413,15 @@ bool ESP_NOW_Peer::remove() {
371413
if (!added) {
372414
return true;
373415
}
374-
log_v("Peer removed - " MACSTR, MAC2STR(mac));
416+
log_i("Removing peer - " MACSTR, MAC2STR(mac));
375417
esp_err_t err = _esp_now_del_peer(mac);
376418
if (err == ESP_OK) {
377419
added = false;
420+
log_i("Peer removed - " MACSTR, MAC2STR(mac));
378421
return true;
379422
}
423+
424+
log_e("Failed to remove peer " MACSTR, MAC2STR(mac));
380425
return false;
381426
}
382427

@@ -389,6 +434,8 @@ bool ESP_NOW_Peer::addr(const uint8_t *mac_addr) {
389434
memcpy(mac, mac_addr, 6);
390435
return true;
391436
}
437+
log_e("Peer already added and ESP-NOW is already running. Cannot change the MAC address.");
438+
log_e("Please call addr() before adding the peer or before starting ESP-NOW.");
392439
return false;
393440
}
394441

@@ -416,6 +463,38 @@ bool ESP_NOW_Peer::setInterface(wifi_interface_t iface) {
416463
return _esp_now_modify_peer(mac, chan, ifc, encrypt ? key : nullptr) == ESP_OK;
417464
}
418465

466+
/**
467+
* @brief Set the rate configuration for the peer.
468+
*
469+
* @param rate_config Pointer to the rate configuration to set. Nullptr to reset to default rate configuration.
470+
* @return true if the rate configuration was set successfully, false otherwise.
471+
*/
472+
bool ESP_NOW_Peer::setRate(const esp_now_rate_config_t *rate_config) {
473+
if (added && _esp_now_has_begun) {
474+
log_e("Peer already added and ESP-NOW is already running. Cannot set rate configuration.");
475+
log_e("Please call setRate() before adding the peer or before starting ESP-NOW.");
476+
return false;
477+
}
478+
479+
if (rate_config == nullptr) {
480+
log_i("Resetting rate configuration to default.");
481+
rate = DEFAULT_ESPNOW_RATE_CONFIG;
482+
} else {
483+
rate = *rate_config;
484+
}
485+
486+
return true;
487+
}
488+
489+
/**
490+
* @brief Get the rate configuration for the peer.
491+
*
492+
* @return esp_now_rate_config_t The rate configuration for the peer.
493+
*/
494+
esp_now_rate_config_t ESP_NOW_Peer::getRate() const {
495+
return rate;
496+
}
497+
419498
bool ESP_NOW_Peer::isEncrypted() const {
420499
return encrypt;
421500
}

libraries/ESP_NOW/src/ESP32_NOW.h

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,15 @@
1111
#include "esp32-hal-log.h"
1212
#include "esp_mac.h"
1313

14+
// clang-format off
15+
#define DEFAULT_ESPNOW_RATE_CONFIG { \
16+
.phymode = WIFI_PHY_MODE_11G, \
17+
.rate = WIFI_PHY_RATE_1M_L, \
18+
.ersu = false, \
19+
.dcm = false \
20+
}
21+
// clang-format on
22+
1423
class ESP_NOW_Peer; //forward declaration for friend function
1524

1625
class ESP_NOW_Class : public Print {
@@ -29,6 +38,8 @@ class ESP_NOW_Class : public Print {
2938
int getVersion() const;
3039

3140
int availableForWrite();
41+
42+
// You can directly send data to all peers without broadcasting using ESP_NOW.write(data, len)
3243
size_t write(const uint8_t *data, size_t len);
3344
size_t write(uint8_t data) {
3445
return write(&data, 1);
@@ -47,6 +58,7 @@ class ESP_NOW_Peer {
4758
uint8_t mac[6];
4859
uint8_t chan;
4960
wifi_interface_t ifc;
61+
esp_now_rate_config_t rate;
5062
bool encrypt;
5163
uint8_t key[16];
5264

@@ -56,7 +68,10 @@ class ESP_NOW_Peer {
5668
bool remove();
5769
size_t send(const uint8_t *data, int len);
5870

59-
ESP_NOW_Peer(const uint8_t *mac_addr, uint8_t channel = 0, wifi_interface_t iface = WIFI_IF_AP, const uint8_t *lmk = nullptr);
71+
ESP_NOW_Peer(
72+
const uint8_t *mac_addr, uint8_t channel = 0, wifi_interface_t iface = WIFI_IF_AP, const uint8_t *lmk = nullptr,
73+
esp_now_rate_config_t *rate_config = nullptr
74+
);
6075

6176
public:
6277
virtual ~ESP_NOW_Peer() {}
@@ -70,6 +85,9 @@ class ESP_NOW_Peer {
7085
wifi_interface_t getInterface() const;
7186
bool setInterface(wifi_interface_t iface);
7287

88+
bool setRate(const esp_now_rate_config_t *rate_config);
89+
esp_now_rate_config_t getRate() const;
90+
7391
bool isEncrypted() const;
7492
bool setKey(const uint8_t *lmk);
7593

0 commit comments

Comments
 (0)