diff --git a/libraries/ESP_NOW/examples/ESP_NOW_Broadcast_Master/ESP_NOW_Broadcast_Master.ino b/libraries/ESP_NOW/examples/ESP_NOW_Broadcast_Master/ESP_NOW_Broadcast_Master.ino index 025a53c913b..7b71c0e432d 100644 --- a/libraries/ESP_NOW/examples/ESP_NOW_Broadcast_Master/ESP_NOW_Broadcast_Master.ino +++ b/libraries/ESP_NOW/examples/ESP_NOW_Broadcast_Master/ESP_NOW_Broadcast_Master.ino @@ -86,6 +86,8 @@ void setup() { ESP.restart(); } + Serial.printf("ESP-NOW version: %d, max data length: %d\n", ESP_NOW.getVersion(), ESP_NOW.getMaxDataLen()); + Serial.println("Setup complete. Broadcasting messages every 5 seconds."); } diff --git a/libraries/ESP_NOW/examples/ESP_NOW_Broadcast_Slave/ESP_NOW_Broadcast_Slave.ino b/libraries/ESP_NOW/examples/ESP_NOW_Broadcast_Slave/ESP_NOW_Broadcast_Slave.ino index e61524b64f9..ca0ece2fff8 100644 --- a/libraries/ESP_NOW/examples/ESP_NOW_Broadcast_Slave/ESP_NOW_Broadcast_Slave.ino +++ b/libraries/ESP_NOW/examples/ESP_NOW_Broadcast_Slave/ESP_NOW_Broadcast_Slave.ino @@ -104,6 +104,8 @@ void setup() { ESP.restart(); } + Serial.printf("ESP-NOW version: %d, max data length: %d\n", ESP_NOW.getVersion(), ESP_NOW.getMaxDataLen()); + // Register the new peer callback ESP_NOW.onNewPeer(register_new_master, nullptr); diff --git a/libraries/ESP_NOW/examples/ESP_NOW_Network/ESP_NOW_Network.ino b/libraries/ESP_NOW/examples/ESP_NOW_Network/ESP_NOW_Network.ino index 6731340c922..d30d6cd40cf 100644 --- a/libraries/ESP_NOW/examples/ESP_NOW_Network/ESP_NOW_Network.ino +++ b/libraries/ESP_NOW/examples/ESP_NOW_Network/ESP_NOW_Network.ino @@ -75,7 +75,12 @@ // The following struct is used to send data to the peer device. // We use the attribute "packed" to ensure that the struct is not padded (all data // is contiguous in the memory and without gaps). -// The maximum size of the complete message is 250 bytes (ESP_NOW_MAX_DATA_LEN). +// The maximum size of the payload is 250 bytes (ESP_NOW_MAX_DATA_LEN) for ESP-NOW v1.0. +// For ESP-NOW v2.0, the maximum size of the payload is 1470 bytes (ESP_NOW_MAX_DATA_LEN_V2). +// You can use ESP_NOW.getMaxDataLen() after calling ESP_NOW.begin() to get the maximum size +// of the data that can be sent. +// Read about the compatibility between ESP-NOW v1.0 and v2.0 in the ESP-IDF documentation: +// https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/network/esp_now.html#frame-format typedef struct { uint32_t count; @@ -276,6 +281,8 @@ void setup() { fail_reboot(); } + Serial.printf("ESP-NOW version: %d, max data length: %d\n", ESP_NOW.getVersion(), ESP_NOW.getMaxDataLen()); + if (!broadcast_peer.begin()) { Serial.println("Failed to initialize broadcast peer"); fail_reboot(); diff --git a/libraries/ESP_NOW/examples/ESP_NOW_Serial/ESP_NOW_Serial.ino b/libraries/ESP_NOW/examples/ESP_NOW_Serial/ESP_NOW_Serial.ino index e1f28382fe2..2a5406cd844 100644 --- a/libraries/ESP_NOW/examples/ESP_NOW_Serial/ESP_NOW_Serial.ino +++ b/libraries/ESP_NOW/examples/ESP_NOW_Serial/ESP_NOW_Serial.ino @@ -64,6 +64,7 @@ void setup() { // Start the ESP-NOW communication Serial.println("ESP-NOW communication starting..."); NowSerial.begin(115200); + Serial.printf("ESP-NOW version: %d, max data length: %d\n", ESP_NOW.getVersion(), ESP_NOW.getMaxDataLen()); Serial.println("You can now send data to the peer device using the Serial Monitor.\n"); } diff --git a/libraries/ESP_NOW/src/ESP32_NOW.cpp b/libraries/ESP_NOW/src/ESP32_NOW.cpp index 25a5609e8db..b5cdc3f3da7 100644 --- a/libraries/ESP_NOW/src/ESP32_NOW.cpp +++ b/libraries/ESP_NOW/src/ESP32_NOW.cpp @@ -140,7 +140,10 @@ static void _esp_now_tx_cb(const uint8_t *mac_addr, esp_now_send_status_t status } } -ESP_NOW_Class::ESP_NOW_Class() {} +ESP_NOW_Class::ESP_NOW_Class() { + max_data_len = 0; + version = 0; +} ESP_NOW_Class::~ESP_NOW_Class() {} @@ -155,6 +158,23 @@ bool ESP_NOW_Class::begin(const uint8_t *pmk) { return false; } + // Unfortunately we can't get the ESP-NOW version before initializing the Wi-Fi + uint32_t esp_now_version; + err = esp_now_get_version(&esp_now_version); + if (err != ESP_OK) { + log_w("esp_now_get_version failed! Assuming ESP-NOW v1.0"); + esp_now_version = 1; + } + + if (esp_now_version == 1) { + max_data_len = ESP_NOW_MAX_DATA_LEN; + } else { + max_data_len = ESP_NOW_MAX_DATA_LEN_V2; + } + + version = esp_now_version; + log_i("ESP-NOW version: %lu, max_data_len: %lu", version, max_data_len); + _esp_now_has_begun = true; memset(_esp_now_peers, 0, sizeof(ESP_NOW_Peer *) * ESP_NOW_MAX_TOTAL_PEER_NUM); @@ -212,7 +232,7 @@ bool ESP_NOW_Class::end() { return true; } -int ESP_NOW_Class::getTotalPeerCount() { +int ESP_NOW_Class::getTotalPeerCount() const { if (!_esp_now_has_begun) { return -1; } @@ -225,7 +245,7 @@ int ESP_NOW_Class::getTotalPeerCount() { return num.total_num; } -int ESP_NOW_Class::getEncryptedPeerCount() { +int ESP_NOW_Class::getEncryptedPeerCount() const { if (!_esp_now_has_begun) { return -1; } @@ -238,16 +258,38 @@ int ESP_NOW_Class::getEncryptedPeerCount() { return num.encrypt_num; } +int ESP_NOW_Class::getMaxDataLen() const { + if (max_data_len == 0) { + log_e("ESP-NOW not initialized. Please call begin() first to get the max data length."); + return -1; + } + + return max_data_len; +} + +int ESP_NOW_Class::getVersion() const { + if (version == 0) { + log_e("ESP-NOW not initialized. Please call begin() first to get the version."); + return -1; + } + + return version; +} + int ESP_NOW_Class::availableForWrite() { - return ESP_NOW_MAX_DATA_LEN; + int available = getMaxDataLen(); + if (available < 0) { + return 0; + } + return available; } size_t ESP_NOW_Class::write(const uint8_t *data, size_t len) { if (!_esp_now_has_begun) { return 0; } - if (len > ESP_NOW_MAX_DATA_LEN) { - len = ESP_NOW_MAX_DATA_LEN; + if (len > max_data_len) { + len = max_data_len; } esp_err_t result = esp_now_send(nullptr, data, len); if (result == ESP_OK) { @@ -386,8 +428,15 @@ size_t ESP_NOW_Peer::send(const uint8_t *data, int len) { log_e("Peer not added."); return 0; } - if (len > ESP_NOW_MAX_DATA_LEN) { - len = ESP_NOW_MAX_DATA_LEN; + + int max_data_len = ESP_NOW.getMaxDataLen(); + if (max_data_len < 0) { + log_e("Error getting max data length."); + return 0; + } + + if (len > max_data_len) { + len = max_data_len; } esp_err_t result = esp_now_send(mac, data, len); if (result == ESP_OK) { diff --git a/libraries/ESP_NOW/src/ESP32_NOW.h b/libraries/ESP_NOW/src/ESP32_NOW.h index 5940cfa2221..5b5bbe72673 100644 --- a/libraries/ESP_NOW/src/ESP32_NOW.h +++ b/libraries/ESP_NOW/src/ESP32_NOW.h @@ -23,8 +23,10 @@ class ESP_NOW_Class : public Print { bool begin(const uint8_t *pmk = nullptr /* 16 bytes */); bool end(); - int getTotalPeerCount(); - int getEncryptedPeerCount(); + int getTotalPeerCount() const; + int getEncryptedPeerCount() const; + int getMaxDataLen() const; + int getVersion() const; int availableForWrite(); size_t write(const uint8_t *data, size_t len); @@ -34,6 +36,10 @@ class ESP_NOW_Class : public Print { void onNewPeer(void (*cb)(const esp_now_recv_info_t *info, const uint8_t *data, int len, void *arg), void *arg); bool removePeer(ESP_NOW_Peer &peer); + +protected: + size_t max_data_len; + uint32_t version; }; class ESP_NOW_Peer { diff --git a/libraries/ESP_NOW/src/ESP32_NOW_Serial.cpp b/libraries/ESP_NOW/src/ESP32_NOW_Serial.cpp index edd6e32aacc..c86c8546c5b 100644 --- a/libraries/ESP_NOW/src/ESP32_NOW_Serial.cpp +++ b/libraries/ESP_NOW/src/ESP32_NOW_Serial.cpp @@ -70,8 +70,25 @@ bool ESP_NOW_Serial_Class::begin(unsigned long baud) { //xSemaphoreTake(tx_sem, 0); xSemaphoreGive(tx_sem); } - setRxBufferSize(1024); //default if not preset - setTxBufferSize(1024); //default if not preset + + size_t buf_size = 0; + if (ESP_NOW.getVersion() == 2) { + // ESP-NOW v2.0 has a larger maximum data length, so we need to increase the buffer sizes + // to hold around 3-4 packets + buf_size = setRxBufferSize(4096); + buf_size &= setTxBufferSize(4096); + } else { + // ESP-NOW v1.0 has a smaller maximum data length, so we can use the default buffer sizes + // to hold around 3-4 packets + buf_size = setRxBufferSize(1024); + buf_size &= setTxBufferSize(1024); + } + + if (buf_size == 0) { + log_e("Failed to set buffer size"); + return false; + } + return true; } @@ -164,7 +181,6 @@ void ESP_NOW_Serial_Class::onReceive(const uint8_t *data, size_t len, bool broad //Print int ESP_NOW_Serial_Class::availableForWrite() { - //return ESP_NOW_MAX_DATA_LEN; if (tx_ring_buf == nullptr) { return 0; } @@ -189,7 +205,7 @@ bool ESP_NOW_Serial_Class::checkForTxData() { //do we have something that failed the last time? resend_count = 0; if (queued_buff == nullptr) { - queued_buff = (uint8_t *)xRingbufferReceiveUpTo(tx_ring_buf, &queued_size, 0, ESP_NOW_MAX_DATA_LEN); + queued_buff = (uint8_t *)xRingbufferReceiveUpTo(tx_ring_buf, &queued_size, 0, ESP_NOW.getMaxDataLen()); } else { log_d(MACSTR " : PREVIOUS", MAC2STR(addr())); }