espressif / arduino-esp32

Arduino core for the ESP32
GNU Lesser General Public License v2.1
13.26k stars 7.34k forks source link

Update ESPNOW receive data callback function #9207

Open xiezhoubin opened 7 months ago

xiezhoubin commented 7 months ago

Related area

ESPNOW

Hardware specification

ESP32

Is your feature request related to a problem?

At present, the callback function for ESPNOW receiving data is as follows: From the "ESPNow2BasicsSlave. ino" sample program,The SDK version is 2.0.14 image image

Describe the solution you'd like

I hope that the updated ESPNOW receive data callback function can have an src address and a des address. "Esp now. h" in idf is supported, and it is also explained in the Arduino for esp32 document, but it cannot be compiled.

https://github.com/espressif/esp-idf/blob/master/components/esp_wifi/include/esp_now.h#L111 image

https://espressif-docs.readthedocs-hosted.com/projects/arduino-esp32/en/latest/api/espnow.html image

Describe alternatives you've considered

No response

Additional context

No response

I have checked existing list of Feature requests and the Contribution Guide

lbernstone commented 7 months ago

"Esp now. h" in idf is supported, and it is also explained in the Arduino for esp32 document, but it cannot be compiled.

The header file is not included, or the symbol is missing? Please post the error you get.

xiezhoubin commented 7 months ago

"Esp now. h" in idf is supported, and it is also explained in the Arduino for esp32 document, but it cannot be compiled.

The header file is not included, or the symbol is missing? Please post the error you get.

The following is the result of compiling the built-in example program "ESPNow_Basic_Slave.ino" that I used. The compilation is not a problem, and the SDK version is 2.0.14 image

However, when I used the ESPNOW example program in the Arduino ESP32 document, there was a compilation error. https://espressif-docs.readthedocs-hosted.com/projects/arduino-esp32/en/latest/api/espnow.html#esp-now-slave image

SuGlider commented 6 months ago

@xiezhoubin - The issue seems related to IDF Version versus Arduino Core Version versus Documentation version

typedef void (*esp_now_recv_cb_t)(const esp_now_recv_info_t * esp_now_info, const uint8_t *data, int data_len); from https://github.com/espressif/esp-idf/blob/master/components/esp_wifi/include/esp_now.h#L111 is valid for IDF Master branch, which means IDF 5.2.x

Arduino Core 2.0.14 uses IDF 4.4.x instead. typedef void (*esp_now_recv_cb_t)(const uint8_t *mac_addr, const uint8_t *data, int data_len); https://github.com/espressif/esp-idf/blob/release/v4.4/components/esp_wifi/include/esp_now.h#L89

The documentation is related to Arduino Core 3.0.0, which uses IDF 5.2.x.

dagnall53 commented 6 months ago

I also use esp-now, and Arduino IDE 2.2.1 My recent check of 3.0.0 showed non compatibility in 3.0.0 of Esp-now and also TCP ?? But I did not find anything in the migration guide on these subjects. It would be helpful (essential??) if the migration guide could explain these issues. Thanks

`C:\Users\admin\Documents\Arduino\N2K0183\N2K0183.ino:495:28: error: invalid conversion from 'void ()(const uint8_t, const uint8_t, int)' {aka 'void ()(const unsigned char, const unsigned char, int)'} to 'esp_now_recv_cb_t' {aka 'void ()(const esp_now_recv_info, const unsigned char*, int)'} [-fpermissive] 495 esp_now_register_recv_cb(OnDataRecv); ^~~~~~
void ()(const uint8_t, const uint8_t, int) {aka void ()(const unsigned char, const unsigned char, int)}

In file included from C:\Users\admin\Documents\Arduino\N2K0183\N2K0183.ino:33: C:\Users\admin\AppData\Local\Arduino15\packages\esp32\tools\esp32-arduino-libs\idf-release_v5.1-3662303f31/esp32/include/esp_wifi/include/esp_now.h:156:54: note: initializing argument 1 of 'esp_err_t esp_now_register_recv_cb(esp_now_recv_cb_t)' 156 | esp_err_t esp_now_register_recv_cb(esp_now_recv_cb_t cb); | ~~~~~~^~ C:\Users\admin\Documents\Arduino\N2K0183\N2K0183.ino: In function 'void Self_Test()': C:\Users\admin\Documents\Arduino\N2K0183\N2K0183.ino:1892:3: error: 'gpio_matrix_out' was not declared in this scope; did you mean 'gpio_iomux_out'? 1892 | gpio_matrix_out(TX_PIN_0, 0x100, false, false); | ^~~~~~~ | gpio_iomux_out C:\Users\admin\Documents\Arduino\N2K0183\N2K0183.ino: In function 'boolean Test_T_Connection()': C:\Users\admin\Documents\Arduino\N2K0183\N2K0183.ino:1973:36: warning: 'WiFiClient WiFiServer::available()' is deprecated: Renamed to accept(). [-Wdeprecated-declarations] 1973 | tcpclient = tcpserver.available(); // wait for it to connect `

QnBarb commented 6 months ago

I'm having similar issue. The program used to compiled until recently. Error: Compilation error: invalid conversion from 'void ()(const uint8_t, const uint8_t, int)' {aka 'void ()(const unsigned char, const unsigned char, int)'} to 'esp_now_recv_cb_t' {aka 'void ()(const esp_now_recv_info, const unsigned char*, int)'} [-fpermissive]

Please advise.

SuGlider commented 6 months ago

I also use esp-now, and Arduino IDE 2.2.1 My recent check of 3.0.0 showed non compatibility in 3.0.0 of Esp-now and also TCP ?? But I did not find anything in the migration guide on these subjects. It would be helpful (essential??) if the migration guide could explain these issues. Thanks

C:\Users\admin\Documents\Arduino\N2K0183\N2K0183.ino:495:28: error: invalid conversion from 'void (*)(const uint8_t*, const uint8_t*, int)' {aka 'void (*)(const unsigned char*, const unsigned char*, int)'} to 'esp_now_recv_cb_t' {aka 'void (*)(const esp_now_recv_info*, const unsigned char*, int)'} [-fpermissive] 495 | esp_now_register_recv_cb(OnDataRecv); | ^~~~~~~~~~ | | | void (*)(const uint8_t*, const uint8_t*, int) {aka void (*)(const unsigned char*, const unsigned char*, int)} In file included from C:\Users\admin\Documents\Arduino\N2K0183\N2K0183.ino:33: C:\Users\admin\AppData\Local\Arduino15\packages\esp32\tools\esp32-arduino-libs\idf-release_v5.1-3662303f31/esp32/include/esp_wifi/include/esp_now.h:156:54: note: initializing argument 1 of 'esp_err_t esp_now_register_recv_cb(esp_now_recv_cb_t)' 156 | esp_err_t esp_now_register_recv_cb(esp_now_recv_cb_t cb); | ~~~~~~~~~~~~~~~~~~^~ C:\Users\admin\Documents\Arduino\N2K0183\N2K0183.ino: In function 'void Self_Test()': C:\Users\admin\Documents\Arduino\N2K0183\N2K0183.ino:1892:3: error: 'gpio_matrix_out' was not declared in this scope; did you mean 'gpio_iomux_out'? 1892 | gpio_matrix_out(TX_PIN_0, 0x100, false, false); | ^~~~~~~~~~~~~~~ | gpio_iomux_out C:\Users\admin\Documents\Arduino\N2K0183\N2K0183.ino: In function 'boolean Test_T_Connection()': C:\Users\admin\Documents\Arduino\N2K0183\N2K0183.ino:1973:36: warning: 'WiFiClient WiFiServer::available()' is deprecated: Renamed to accept(). [-Wdeprecated-declarations] 1973 | tcpclient = tcpserver.available(); // wait for it to connect

Please note that the Migration Guide is about Arduino API changes from 2.0.x to 3.0.0 version. It doesn't talk about IDF API changes from IDF v4.4 (Arduino Core 2.0.x) to IDF v5.1 (Arduino Core 3.0.0) For those changes, please refer to the IDF documentation.

SuGlider commented 6 months ago

I'm having similar issue. The program used to compiled until recently. Error: Compilation error: invalid conversion from 'void (_)(const uint8t, const uint8t*, int)' {aka 'void ()(const unsigned char_, const unsigned char, int)'} to 'esp_now_recv_cbt' {aka 'void ()(const esp_now_recvinfo, const unsigned char, int)'} [-fpermissive]

Please advise.

Arduino Core 2.0.x uses IDF 4.4 and ESP NOW API based on this IDF version. https://docs.espressif.com/projects/esp-idf/en/v4.4.6/esp32/api-reference/network/esp_now.html

Arduino Core 3.0.0 uses IDF 5.1 and the ESP NOW API has changed. https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-reference/network/esp_now.html

Please apply the changes to ESP NOW calls as defined in the IDF documentation.

dagnall53 commented 6 months ago

@SuGlider Could you advise any #defines or similar that we can place in our code so that we can make the code "compatible" with either 4.4.6 or 5.2, depending on which the user compiles with?? WHAT IDF related variable is visible in Arduino so that we can select between two versions of functions.. EG for my example, between: void OnDataRecv(_const uint8_t mac, const uint8_t incomingData, int len) {the OLD version or optionally if compiling with V3... select for : void onDataRecv(const esp_now_recv_info_t recv_info, const uint8_t data, int len_) {the NEW version

SuGlider commented 6 months ago

It is possible to test the IDF version and compile the right ESPNOW signature.

#if ESP_IDF_VERSION_MAJOR == 4 // IDF 4.xxx
// your code here
#endif

This is what you can test (example with IDF4.4.6):

/** Major version number (X.x.x) */
#define ESP_IDF_VERSION_MAJOR   4
/** Minor version number (x.X.x) */
#define ESP_IDF_VERSION_MINOR   4
/** Patch version number (x.x.X) */
#define ESP_IDF_VERSION_PATCH   6
SuGlider commented 6 months ago

it is also possible to test it like this:

// IDF Version higher or equal to v4.4.2
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 4, 2)
// your code
#endif
IOM2021 commented 3 months ago

Users of a project I'm working on have started reporting issues as they have upgraded to version 3.0.0 when using the following code that is taken from the example ESPNow_Basic_Slave example that came with 2.0.17

I'm using Arduino IDE version 2.3.0

esp_now_register_recv_cb(OnDataRecv);

and the function

void OnDataRecv(const uint8_t mac_addr, const uint8_t data, int data_len) { char macStr[18]; snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x", mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]); Serial.print("Last Packet Recv from: "); Serial.println(macStr); Serial.print("Last Packet Recv Data: "); Serial.println(*data); Serial.println(""); }

The error is

K:\MyArduinoSketches\ESP_NOW\2017 examples\ESPNow_Basic_Slave\ESPNow_Basic_Slave.ino: In function 'void setup()': K:\MyArduinoSketches\ESP_NOW\2017 examples\ESPNow_Basic_Slave\ESPNow_Basic_Slave.ino:77:28: error: invalid conversion from 'void ()(const uint8_t, const uint8_t, int)' {aka 'void ()(const unsigned char, const unsigned char, int)'} to 'esp_now_recv_cb_t' {aka 'void ()(const esp_now_recv_info, const unsigned char*, int)'} [-fpermissive] 77 esp_now_register_recv_cb(OnDataRecv); ^~~~~~
void ()(const uint8_t, const uint8_t, int) {aka void ()(const unsigned char, const unsigned char, int)}

In file included from K:\MyArduinoSketches\ESP_NOW\2017 examples\ESPNow_Basic_Slave\ESPNow_Basic_Slave.ino:32: C:\Users\info\AppData\Local\Arduino15\packages\esp32\tools\esp32-arduino-libs\idf-release_v5.1-442a798083/esp32/include/esp_wifi/include/esp_now.h:157:54: note: initializing argument 1 of 'esp_err_t esp_now_register_recv_cb(esp_now_recv_cb_t)' 157 | esp_err_t esp_now_register_recv_cb(esp_now_recv_cb_t cb); | ~~~~~~^~

exit status 1

Compilation error: invalid conversion from 'void ()(const uint8_t, const uint8_t, int)' {aka 'void ()(const unsigned char, const unsigned char, int)'} to 'esp_now_recv_cb_t' {aka 'void ()(const esp_now_recv_info, const unsigned char*, int)'} [-fpermissive]

I have also tried swapping out the OnDataRecv() code for the onReceive() in the example ESP_NOW_Broadcast_Slave but that gives the same error.

I have also tried numerous other manipulations but all give the same error.

No idea what I am missing

me-no-dev commented 3 months ago

Underlying IDF APIs have changed. We have rolled out our own library for ESP-NOW in v3.0.0. You can give that a shot

IOM2021 commented 3 months ago

Underlying IDF APIs have changed. We have rolled out our own library for ESP-NOW in v3.0.0. You can give that a shot

I have been trying to modify the exaples in the new ESP-NOW libray in v3.0.0 for a couple of days and have got nowhere. They are nowhere near as clearly explained as the 2.0.17 examples.... unless I've missed some documentation somewhere.

In the set up I am using all communication is via broadcast mode as I have more than 20 ESP32's on trhe network. The first 10 bytes of the message contain mac addresses and system ID codes as I need to avoid the 20 peer limit and broadcast mode is ideal for that.

The examples feel like they have been written in a way that the author assumed uses would want to use ESP-NOW and that causes issues when you try to do something different.

me-no-dev commented 3 months ago

@P-R-O-C-H-Y can you help with some example code please.

@IOM2021 you can use broadcasts that is fine. You just define a peer with the broadcast address and write to it.

dagnall53 commented 3 months ago

By pure chance I managed to get my ESP-NOW codes working in Compiler 3 yesterday. I do agree that the new ESP-NOW examples are unhelpful for anyone who is trying to convert. I spent hours trying to see the similarities with the older examples to help me understand the "upgrade" and failed.

On Broadcast: We use transmission to FF:FF:FF:FF:FF:FF to "broadcast" ad it seems to work well. If we want to send only to a single other device, we only then specify their address.

Apart from other changes (like how Binary numbers are now written ..(now ..0b00000000 instead of B00000000)), in the end, the ONLY ESP_NOW change that was critical for me was the difference in how the onReceived() call is formulated in Compiler 3 from Compiler 2.. In the older compiler it was formulated (const uint8_t* mac, const uint8_t* incomingData, int len) In the revised code, it is (const esp_now_recv_info_t *info, const uint8_t *data, int len) When you therefore set your on receive call back, you will get a compile error with the older onReceive(). (The compiler error codes do explain the problem!)

IF you were using the mac address in your original receive function, you will need to extract it from the new "info" (esp_now_recv_info_t structure/variable). Otherwise the code worked fine.

(PS for @P-R-O-C-H-Y Changing/updating the timer functions was more complex, but I can see benefits in the new simpler approach. )

IOM2021 commented 3 months ago

In the older compiler it was formulated (const uint8_t* mac, const uint8_t* incomingData, int len) In the revised code, it is (const esp_now_recv_info_t *info, const uint8_t *data, int len) When you therefore set your on receive call back, you will get a compile error with the older onReceive(). (The compiler error codes do explain the problem!)

Wow thanks for that, made the mods and everything is working, thankfully the mac address has always been passed in the data so no need to get it from info.

I would suggest that the old 2.0.17 slave/master sketches are reproduced in the new examples with the simple change above to the OnDataRecv made to them as well as how to get the mac address out from the info. That would make the upgrade path far easier for most users.

roetske commented 2 months ago

update from idf 4 to 5 cause of the change if i understand. i have the same compile error. thx surfed for hours to find the cause of this error on receive. can somebody provide code snippet how to have good on receive callback with v5 idf? would be appreciated for many users.

me-no-dev commented 2 months ago

@roetske maybe look into the ESP-NOW library that we now provide in Arduino?

roetske commented 2 months ago

Ah found it how. Replace line with line iom2021suggested. Jeezes the problems with these commands. Very little doc. You have to start with code snippet. Espressif should provide code snippets specific for arduino ide.

me-no-dev commented 2 months ago

Espressif should provide code snippets specific for arduino ide.

We provide a whole library with examples for Arduino

IOM2021 commented 2 months ago

I made a video with code samples at https://www.youtube.com/watch?v=2WN4O3jtBfI and a 2nd to do with setting a custom mac address at https://www.youtube.com/watch?v=WWvOgWcHpd8

Thought I'd share the info once I finally got it working. Tried to write the code similar to the old version I was using.

roetske commented 2 months ago

Thx for fast responses. Got it working. Two way com. Thx to remark iom2021 which was a great help. I watched the video iom suggested big thumbs up. The use of the flag in the onreceive i found was a great tip. Also i experienced the resetting of esp32 on boot. waiting for wifi sta mode was a second great tip.