ESP32 does not transmit in ESP NOW protocol

Hello, everybody,
First, I want to thank you, the experts, for supporting us in our struggle with our projects.
In my project a single server collects data through its local resources and distributes it to some peripheral units. The requests for the data are coming from every perihheral unit on its own time. There is no need to register the remote units. This is not a typical implementation of ESP NOW protocol, and I had to construct a dedicated protocol based on tested examples. The included code represents a shrunk version of the original code where the “wifiConnect” method is the original one.
The wifi station is working, and I prove it by getting UTP time. However, “esp_now_send” method returns error 0x3069 (?), and the callback method “OnDataSent” is not beeing triggered. This means that the test message is not transmitted. The monitor output is as designed. I assume that I missed something on my way, but I don’t see what it is. I’d appreciate any clue that you may send.
I’d further appreciate pointing to a source of explanation on the callback mechanism, especially on how it is triggered (interrupt? Polling?) and where the registered methods get their parameters from (“OnDataRecv“ gets 3 parameters, “OnDataSend” gets 2 parameters – none of them is indicated during the registration).
Project details: Seeed ESP32C3, Arduino IDE Version: 2.3.5, Date: 2025-04-02T13:16:49.885Z, CLI Version: 1.2.0, Windows 10 Pro build 19045.5737.
The monitor output is:

Loop #0; status = NO ERROR
Loop #1; status = WL IDLE STATUS
Loop #2; status = WL IDLE STATUS
Final status - WL CONNECTED
Server mac address: ff:ff:ff:ff:ff:ff
Server SOFT AP MAC Address:  64:E8:33:84:1C:11
Station IP Address: 10.0.0.34; Wi-Fi Channel: 2
wireless setting status - NO ERROR

Synchronizing RTC with NTP server...
Time synchronized!
Total setup time - 12357 milliseconds

Begin main loop 
Tx result - NOK (error 0x3069)

The code:

> #include <Arduino.h>
> #include <WiFi.h>
> #include <esp_now.h>
> #include <esp_wifi.h>
> 
> #include "rtc.h"
> 
> #define VERBOSE
> 
> uint8_t macAddress[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
> const char *ssid = "Oferco";
> const char *password = "AslanGY82";
> 
> enum wifiStatusEnum { NO_ERROR,
>                       WIFI_NOT_CONNECTED,
>                       ESP_NOW_INIT_ERR,
>                       NO_MAC_ADDRESS };
> const String wifiErrors[] = { "NO ERROR", "WIFI NOT CONNECTED", "ESP NOW INIT ERR", "NO MAC ADDRESS" };
> const String wifiStatusCodes[6] = { "WL IDLE STATUS", "WL NO SSID AVAIL", "WL SCAN COMPLETED",
>                                     "WL CONNECTED", "WL CONNECT FAILED", "WL CONNECTION LOST" };
> 
> /*****************************************/
> void OnDataSent(const uint8_t *macAddress, esp_now_send_status_t status) {
> #ifdef VERBOSE
>   Serial.print("Packet Send Status:\tDelivery ");
>   Serial.println((status == ESP_NOW_SEND_SUCCESS) ? "Success" : "Fail");
> #endif
> }
> /*****************************************/
> wifiStatusEnum wifiConnect() {
>   WiFi.persistent(false);
>   WiFi.mode(WIFI_AP_STA);
>   WiFi.begin(ssid, password);
>   uint8_t loops = 0;
>   int st = WiFi.status();
>   while (st != WL_CONNECTED) {
> #ifdef VERBOSE
>     Serial.println("Loop #" + String(loops) + "; status = " + wifiStatusCodes[(uint8_t)st]);
> #endif
>     if (++loops > 120) {
> #ifdef VERBOSE
>       Serial.println("Sync error. Processing halted.");
> #endif
>       return WIFI_NOT_CONNECTED;
>     }
>     delay(500);
>     st = WiFi.status();
>   }
> #ifdef VERBOSE
>   Serial.println("Final status - " + wifiStatusCodes[(uint8_t)st]);
>   Serial.print("Server mac address: ");
>   Serial.printf("%02x:%02x:%02x:%02x:%02x:%02x\n",
>                 macAddress[0], macAddress[1], macAddress[2], macAddress[3], macAddress[4], macAddress[5]);
>   Serial.print("Server SOFT AP MAC Address:  ");
>   Serial.println(WiFi.softAPmacAddress());
>   Serial.print("Station IP Address: ");
>   Serial.print(WiFi.localIP());
>   Serial.print("; Wi-Fi Channel: ");
>   Serial.println(WiFi.channel());
> #endif
> 
>   // ESPNOW
>   if (esp_now_init() != ESP_OK) {
> #ifdef VERBOSE
>     Serial.println("Error initializing ESP-NOW");
> #endif
>     return ESP_NOW_INIT_ERR;
>   }
>   if (!esp_wifi_get_mac(WIFI_IF_STA, macAddress) == ESP_OK) {
> #ifdef VERBOSE
>     Serial.println("Error reading mac address");
> #endif
>     return NO_MAC_ADDRESS;
>   }
>   esp_now_register_send_cb(OnDataSent);
>   esp_now_register_recv_cb(esp_now_recv_cb_t(OnDataRecv));
>   return NO_ERROR;
> }
> /*****************************************/
> void setup() {
>   unsigned long setupTime = millis();
>   Serial.begin(9600);
>   while (!Serial)    ;
>   Serial.println("wireless init result - " + wifiErrors[(uint8_t)wifiConnect()]);
> 
>   Serial.println();
>   rtc.syncTime();  // Time sync bewtween local RTC and NTP
>   Serial.flush();
>   Serial.println("Total setup run time - " + String(millis() - setupTime) + " milliseconds");
> }
> /*****************************************/
> void loop() {
>   Serial.println("\nBegin main loop ");
>   char testData[] = "test tx";
>   esp_err_t er = esp_now_send(macAddress, (uint8_t *)&testData, sizeof(testData));
>   Serial.print("Tx result - ");
>   Serial.println((er == ESP_OK) ? "OK" : "NOK (error 0x" + String(er, HEX) + ")");
>   while (1)
>     ;

Have you looked at the sample sketches? What is different between yours and the working samples?

It's in the header file, esp_now.h (hover over the file name in the #include statement, right-click, and choose Go to Definition)

#define ESP_ERR_ESPNOW_BASE         (ESP_ERR_WIFI_BASE + 100) /*!< ESPNOW error number base. */
#define ESP_ERR_ESPNOW_NOT_INIT     (ESP_ERR_ESPNOW_BASE + 1) /*!< ESPNOW is not initialized. */
#define ESP_ERR_ESPNOW_ARG          (ESP_ERR_ESPNOW_BASE + 2) /*!< Invalid argument */
#define ESP_ERR_ESPNOW_NO_MEM       (ESP_ERR_ESPNOW_BASE + 3) /*!< Out of memory */
#define ESP_ERR_ESPNOW_FULL         (ESP_ERR_ESPNOW_BASE + 4) /*!< ESPNOW peer list is full */
#define ESP_ERR_ESPNOW_NOT_FOUND    (ESP_ERR_ESPNOW_BASE + 5) /*!< ESPNOW peer is not found */
#define ESP_ERR_ESPNOW_INTERNAL     (ESP_ERR_ESPNOW_BASE + 6) /*!< Internal error */
#define ESP_ERR_ESPNOW_EXIST        (ESP_ERR_ESPNOW_BASE + 7) /*!< ESPNOW peer has existed */
#define ESP_ERR_ESPNOW_IF           (ESP_ERR_ESPNOW_BASE + 8) /*!< Interface error */

You can find the value of ESP_ERR_WIFI_BASE the same way. Then:

Hint 1: 100 in hex is 0x64.

Hint 2: no esp_now_add_peer calls in your sketch.

The Nano ESP32 section of the forum is specifically for problems with the Arduino Nano ESP32, not for other ESP32 based boards. Hence your topic has been moved.

Dear Ken4,
Thank you so much! Your answer indeed solved the problem. All I had to do is to add conditional registration of the peer and the sending method returned successfully.

Now I get a meaningless error message from the callback method. Is it because I still have no receiver? Lack of understanding the ESP NOW methods makes the debugging more difficult.

Does there any in-depth ecplanation of the ESP NOW module?

Regards

I sure did. Having implemented Kenb4 suggestion I can find no difference. The error message comes now from the callback method. Still digging.

Minor point: the all-FF MAC address is also the ESP-Now broadcast address. Looks like you're just using it as the default value before calling esp_wifi_get_mac. But you should do that before you print the "Server mac address". What you have now is misleading.

ESP-Now requires that everyone is on the same WiFi channel -- 11 of those. One way to ensure this is to join the same AP; you'll end up on its channel. It also initializes the WiFi stack, which is required by ESP-Now. (There's another ESP-specific way of doing that, IIRC.)

However, ESP-Now does not work very well while you are connected to an AP for normal WiFi. Only some portion of sent messages will be received. (Depending on what you're doing, this might be acceptable.) So if you join an AP, you should then disconnect from it after everything is "warmed up".

Dear Kenb4,
Thank you very much. I corrected the first note and the printout is clearer.

Regarding the other point: Do you mean that all the stations - server and peers alike - shoulf log to the AP and be disconnected after the initiation, to continue the ESP-NOW communication with disconnected AP?

Regards

Yes, that's the easiest thing to try.

Otherwise, you can use the ESP-IDF functions (they all start with esp_)

  • as mentioned, need to start the WiFi stack
  • pretty sure all the devices default to channel 1 on restart, but you can print the current channel to be sure

If it doesn't work, be sure to post updated code for the sender and receiver, and any error messages, if if they don't make any sense to you. Since it is ESP32, under the Tools menu, set Core Debug Level to Verbose (instead of None) before compiling and uploading. That will show even more.

Hello, Kenb4,
During the last days I tried to research the ESP-NOW and correct the algorithms. As of now I removed some errors, but the TX callback still does not acknowledge on packet transmission. I'd appreciate your patient guidance.

Some explanations: due to configuration management considerations I prefer to maintain one SW package for all stations. The decision how to act is being done in real time based on the localId variable, which is being read from HW jumpers (0 for server, something else for ay other station). The code contains process for every station type.

The algorithms are distributed between between the following methods:

  • "wifiConnect" presets the WiFi network and the ESP-NOW initiation. It is being called by the "setup" method, that has some other tasks and will have more as soon as I'll integrate the operational data processes.

  • "OnDataRecv" is the callback method that responds to packet reception. Mainly it sets a flag, and the main loop will call the "DataReceive" method.

  • The "DataReceive" method checks the received packet and decides how to behave according to its own ID, the ID of the packet sender, and the message type.

  • The "transmitData" gets the packet that should be transmitted, adds some some generic data and transmits it.

  • "OnDataSent" is debug-oriented callback method that acknowledge the packet transmission.

  • "crc" and "loop" are self explanatory methods.

Here is the resulted code.

#include <Arduino.h>
#include <WiFi.h>
#include <esp_now.h>
#include <esp_wifi.h>

#include "rtc.h"

#define ESP_VERBOSE

#define SERVER_ID 0 
#define MAX_DATA_LEN 6
#define macAddrLen 6
#define maxStationsCount 6

const uint8_t localId = 0; // Consider replacing by HW read
uint8_t commandData[MAX_DATA_LEN];
uint8_t statusData[MAX_DATA_LEN];

  typedef struct MessageStructure {
    uint8_t targetId = 0;  // The position of this parameter in the structure is hardcoded
    uint8_t senderId = 0;  // The position of this parameter in the structure is hardcoded
    uint8_t msgType = 0;
    uint8_t msgNumber = 0;
    uint8_t senderMacAddr[macAddrLen] = { 0 };
    uint8_t data[MAX_DATA_LEN] = { 0 };
    uint8_t timeDeviation = 0;
    uint8_t crc = 0; // The position of this parameter in the structure is hardcoded
  } messageStructure;
  messageStructure rxData, txData;
  #define targetIddPosition 0
  #define senderIdPosition  1

  const char *ssid = "Oferco";
  const char *password = "AslanGY82";

  uint8_t localMacAddress[macAddrLen];
  uint32_t errorCounter[maxStationsCount];
  uint8_t activeStations[maxStationsCount];
  uint8_t feedbackData[maxStationsCount];
  uint8_t channel;
  uint8_t peerId;
  bool packetReceived = LOW;

  const String wifiStatusCodes[6] = { "WL IDLE STATUS", "WL NO SSID AVAIL", "WL SCAN COMPLETED",
                                   "WL CONNECTED", "WL CONNECT FAILED", "WL CONNECTION LOST" };
  enum MessageType { REQUEST, ACKNOWLEDGE, CONFIRM, };
  const String MessageTypeNames[3] = {"REQUEST", "ACKNOWLEDGE", "CONFIRM"};
  enum wifiStatusEnum { NO_ERROR,
                        WIFI_NOT_CONNECTED,
                        ESP_NOW_INIT_ERR,
                        NO_MAC_ADDRESS, };
  const String wifiErrors[4] = { "OK", "WIFI NOT CONNECTED", "ESP NOW INIT ERR", "NO MAC ADDRESS" };

/**********************************************************************************
The communications process is a derivative of ESP-Now. 3 of its 4 steps are implemented in the OnDataRecv as
responses to data packages. It is built from four steps: 
* The GPIO controller initiates a REQUEST transmission to the server.
    Implemented in the main loop based on timer.* 
* The server reponds with an ACKNOWLEDGE package, that contains the command and the server mac address.
    Implemented in the onDataRec method.
* The GPIO controller receives the ACKNOWLEDGE package, processes the command and returns a CONFIRM package 
  that contains the feedback.
    Implemented in the onDataRec method.
* The server receives the ACKNOWLEDGE package, checks the feedback and closes the communication.
    Implemented in the onDataRec method.
 **********************************************************************************/
void OnDataRecv(const uint8_t *mac_addr, const uint8_t *incomingData, int len) {
  Serial.print("Packet received (" + String(len) + " bytes) for data ");
  if ((incomingData[targetIddPosition] != localId) || (incomingData[senderIdPosition] >= maxStationsCount))
    return;  // The message is not addressed to this station
#ifdef ESP_VERBOSE
#endif
  memcpy(&rxData, incomingData, len);
  peerId = rxData.senderId;
  packetReceived = HIGH;
}

void DataReceive(){
  packetReceived = LOW;
  if (localId == SERVER_ID) {  // Server responds to data REQUEST from the IO controller
    if (rxData.msgType == REQUEST) {
      txData.msgType = ACKNOWLEDGE;
      txData.targetId = SERVER_ID;
      txData.data[0] = feedbackData[localId];
      transmitData();
    } else if (rxData.msgType == CONFIRM) {
// The server services data acknowledge package by verifying the feedback and closing the communication
#ifdef ESP_VERBOSE
      Serial.print("CONFIRM");
#endif
      if (feedbackData[peerId] == rxData.data[0])  // <<<<< to improve
        errorCounter[peerId] = 0;
      else
        errorCounter[peerId]++;
      activeStations[peerId] = 0;
    }
  }
  //// Start processing the IO controller processes.
  else {
    if (rxData.msgType == ACKNOWLEDGE) {
// The server handles data request by transmitting ACKNOWLEDGE package with the data
#ifdef ESP_VERBOSE
      Serial.print("REQUEST");
#endif
      // Servicing request of pairing and data by transmitting the command and the server mac address
      activeStations[peerId] = millis();
      txData.msgType = ACKNOWLEDGE;
      rxData.targetId = SERVER_ID;
      transmitData();
    }
  }
}
/**********************************************************************************/
void OnDataSent(const uint8_t *macAddress, esp_now_send_status_t status) {
//#ifdef ESP_VERBOSE
  Serial.print("Packet Send Status:\tDelivery ");
  Serial.println((status == ESP_NOW_SEND_SUCCESS) ? "Success" : "Fail");
//#endif
}
/**********************************************************************************/
void transmitData(){
  esp_now_peer_info_t peer;
  memset(&peer, 0, sizeof(peer));
  peer.channel = channel;
  esp_err_t st;
  if (!esp_now_is_peer_exist(rxData.senderMacAddr)){
    memcpy(peer.peer_addr, rxData.senderMacAddr, macAddrLen);
    st = esp_now_add_peer(&peer);
#ifdef ESP_VERBOSE
    if (st != ESP_OK){
      Serial.println("The peer registration failed");
      return;
    }
    Serial.println("message type=" + MessageTypeNames[txData.msgType] + "; data=" + String(txData.data[0]));
    Serial.println("Sender id=" + String(txData.senderId) + "; target id=" + String(txData.targetId));
    Serial.print("Sender mac address: ");
    Serial.printf("%02x:%02x:%02x:%02x:%02x:%02x\n",
                  txData.senderMacAddr[0], txData.senderMacAddr[1], txData.senderMacAddr[2], 
                  txData.senderMacAddr[3], txData.senderMacAddr[4], txData.senderMacAddr[5]);
    Serial.flush();
#endif
  }
  txData.msgNumber++;
  txData.crc = crc((const uint8_t *)&txData, sizeof(txData) - 1);
  st = esp_now_send(rxData.senderMacAddr, (uint8_t *)&txData, sizeof(txData));
#ifdef ESP_VERBOSE
  Serial.print("Tx result - ");
  Serial.println((st == ESP_OK) ? "OK" : "NOK (error 0x" + String(st - ESP_ERR_ESPNOW_BASE, HEX) + ")");
  Serial.flush();
#endif
}
/**********************************************************************************/
uint8_t wifiConnect() {
  WiFi.persistent(false);
  WiFi.mode(WIFI_AP_STA);
  WiFi.begin(ssid, password);
  uint8_t loops = 0;
  uint8_t st = WiFi.status();
  while (st != WL_CONNECTED) {
#ifdef ESP_VERBOSE
    Serial.println("Loop #" + String(loops) + "; status = " + wifiStatusCodes[(uint8_t)st]);
#endif
    if (++loops > 120) {
#ifdef ESP_VERBOSE
      Serial.println("Sync error. Processing halted.");
#endif
      return WIFI_NOT_CONNECTED;
    }
    delay(500);
    st = WiFi.status();
  }
  esp_now_register_send_cb(OnDataSent);
  esp_now_register_recv_cb(esp_now_recv_cb_t(OnDataRecv));
#ifdef ESP_VERBOSE
  Serial.print("Callback methods were registered. ");
  Serial.println("Final status - " + wifiStatusCodes[(uint8_t)st]);
  Serial.print("Station IP Address: ");
  Serial.print(WiFi.localIP());
  Serial.print("; Wi-Fi Channel: ");
  channel = WiFi.channel();
  Serial.println(channel);
#endif

  // ESPNOW
  if (esp_now_init() != ESP_OK) {
#ifdef ESP_VERBOSE
    Serial.println("Error initializing ESP-NOW");
#endif
    return ESP_NOW_INIT_ERR;
  }
  if (!esp_wifi_get_mac(WIFI_IF_STA, localMacAddress) == ESP_OK) {
#ifdef ESP_VERBOSE
    Serial.println("Error reading mac address");
#endif
    return NO_MAC_ADDRESS;
  }
#ifdef ESP_VERBOSE
  Serial.print("Server mac address: ");
  Serial.printf("%02x:%02x:%02x:%02x:%02x:%02x\n",
                localMacAddress[0], localMacAddress[1], localMacAddress[2], 
                localMacAddress[3], localMacAddress[4], localMacAddress[5]);
#endif
  return NO_ERROR;
}
/*****************************************/
byte crc(const byte *data, size_t dataLength) {
  byte crc8 = 0x00;
  while (dataLength--) {
    byte extract = *data++;
    for (byte tempI = 8; tempI; tempI--) {
      byte sum = (crc8 ^ extract) & 0x01;
      crc8 >>= 1;
      if (sum) {
        crc8 ^= 0x8C;
      }
      extract >>= 1;
    }
  }
  return crc8;
}
/**********************************************************************************/
void setup() {
  unsigned long setupTime = millis();
  Serial.begin(9600);
  while (!Serial)    ;
  Serial.println("Begin setup. ");
  uint8_t st = wifiConnect();
  Serial.println("wireless init result - " + wifiErrors[(uint8_t)st]);
  if(localId == SERVER_ID)
//    rtc.syncTime();  // Time sync bewtween local RTC and NTP
  {;}
  memcpy(txData.senderMacAddr, localMacAddress, macAddrLen);
  txData.senderId = localId;
  packetReceived = LOW;

//  WiFi.disconnect();
  Serial.println("\nTotal setup run time - " + String(millis() - setupTime) + " milliseconds");
}
/**********************************************************************************/
void loop() {
  Serial.println("\nBegin main loop ");
  uint32_t timing = millis();
  while (!packetReceived && ((millis() - timing) < 2000))
    ;
  if(packetReceived)
    DataReceive();
  else if(localId != SERVER_ID){             // Initiate a REQUEST packet
    rxData.msgType = REQUEST;
    rxData.targetId = SERVER_ID;
    transmitData();
  }
  delay(2000) ;

}

For the initial output, I got

E (1106) ESPNOW: esp now not init!
Callback methods were registered. Final status - WL CONNECTED

because here

those two calls happen before calling esp_now_init(), and each actually returns ESP_ERR_ESPNOW_NOT_INIT instead of ESP_OK. Check the return values. So neither callback is registered.

And for that second one, the fact that you need a cast means something is wrong. The function signature of OnDataRecv is for the old v2 of the arduino-esp32 core, where the first argument is const uint8_t *mac_addr. For the current v3, the first argument is a const esp_now_recv_info *info. The first member of that struct is the source MAC address, so the pointer is effectively the same. But the signature is different. You're not using that argument anyway, so the fix is easy.

A few more general comments:

C++ automatically elevates the struct name as a type. You only have these two instances. Plus, instead of manually defining the offsets, which can get out of sync, the compiler can figure it out for you

struct MessageStructure {
  uint8_t targetId = 0;  // The position of this parameter in the structure is hardcoded
  uint8_t senderId = 0;  // The position of this parameter in the structure is hardcoded
  //
  // ...
} rxData, txData;
constexpr auto targetIdPosition = offsetof(MessageStructure, targetId);
#define senderIdPosition offsetof(MessageStructure, senderId)

offsetof is similar to sizeof. You could use it in-place; save some typing with a macro; or have it assigned to a constant. One benefit of a constant is that if you hover, the IDE will tell you the computed value, if you want to check it. And better to use a constant instead of macros where possible.

In the loop

That's a hot loop waiting for the flag value to change. If you didn't know that ESP32 runs a preemptive RTOS on a dual-core (usually), who is going to change that flag? You probably want to avoid thinking about the memory model guarantees when changing primitives with different cores. At a minimum, you would change it to

  while (!packetReceived && ((millis() - timing) < 2000))
    delay(20);

so that the main task can yield and let some other task flip that flag. But you might be better off using an appropriate multi-threading primitive like a queue.

Note that the main loop runs on the core 1, the "app" core

  Serial.printf("loop: (core %d)\n", xPortGetCoreID());

while the send and receive callbacks are on core 0, the "protocol" core

  Serial.printf("sent: (core %d)\n", xPortGetCoreID());

Dear kenb4,

Thank you so much for your patient support! At last it works, and I can proceed to the next integration level.

It was a frustrating task: coding the application while being blind to the internal dependencies (such as the esp-now init prior to the CB registration) and lack of understanding the internal decision (for instance - should I know the condition to the status parameter of the on DataSend I'd put a small delay before it).

  • Regarding the registration being done before the esp_now_init() - corrected.
  • Regarding the struct declaration - I moved the variables declaration to the struc declaration; however, I received over 30 error messages of misunderstanding the struct. Without further investigation I returned to the original status.
  • Per your recommendation, I added the 20 mS delay to the waiting loop in the main loop method.

Most of the changes were made in the onDataRec and dataTransmit methods, so I bring only them:

/**********************************************************************************
The communications process is a derivative of ESP-Now. 3 of its 4 steps are implemented in the OnDataRecv as
responses to data packages. It is built from four steps: 
* The GPIO controller initiates a REQUEST transmission to the server.
    Implemented in the main loop based on timer.* 
* The server reponds with an ACKNOWLEDGE package, that contains the command and the server mac address.
    Implemented in the onDataRec method.
* The GPIO controller receives the ACKNOWLEDGE package, processes the command and returns a CONFIRM package 
  that contains the feedback.
    Implemented in the onDataRec method.
* The server receives the ACKNOWLEDGE package, checks the feedback and closes the communication.
    Implemented in the onDataRec method.
 **********************************************************************************/
void OnDataRecv(const esp_now_recv_info *info, const uint8_t *incomingData, int len) {
  memcpy(&rxData, incomingData, len);
  if ((rxData.targetId != localId) || (rxData.senderId > maxStationsCount))
    return;  // The message is not addressed to this station
  memcpy(peerMacAddress, rxData.senderMacAddr, macAddrLen);
  peerId = rxData.senderId;
  if (localId == SERVER_ID) {  
    if (rxData.msgType == REQUEST){  // The server responds to data REQUEST
      transmitData(ACKNOWLEDGE, peerId, HIGH, rxData.msgNumber);
    } else if (rxData.msgType == CONFIRM) {  // The server responds to CONFIRM message 
    }
  } else if (rxData.msgType == ACKNOWLEDGE){      // GPIOC responds to ACKNOWLEDGE message by Ssrvicing both pairing and data
    activeStations[peerId] = millis();
    transmitData(ACKNOWLEDGE, SERVER_ID, LOW, rxData.msgNumber);
  }
}
/**********************************************************************************/
void transmitData(uint8_t packageType, uint8_t targetId, bool loadData, uint8_t msgNumber){
  esp_err_t st;
  if (!esp_now_is_peer_exist(peerMacAddress)) {
    esp_now_peer_info_t peer;
    memset(&peer, 0, sizeof(peer));
//    peer.lmk ;
    peer.encrypt = LOW;
    peer.channel = channel;
    memcpy(peer.peer_addr, peerMacAddress, macAddrLen);
    if (esp_now_add_peer(&peer) != ESP_OK) {
      Serial.println("The peer registration failed");
      return;
    }
    Serial.println("The peer was added successfully");
  }
  messageStructure txData;
  txData.senderId = localId;
  txData.targetId = targetId;
  txData.msgType = packageType;
  memcpy(txData.senderMacAddr, localMacAddress, macAddrLen);
  txData.msgNumber = msgNumber;
  if(loadData)
    memcpy(txData.feedbackData, feedbackData[targetId], MAX_DATA_LEN);
  txData.crc = crc((const uint8_t *)&txData, sizeof(txData) - 1);
  st = esp_now_send(peerMacAddress, (uint8_t *)&txData, sizeof(txData));
}
1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.