ESP-NOW multiple senders

Hi,

i'm working now with nodeMCU as a sender and ESP32 as receiver , I will add another 3 nodemcus that will send data to ESP32

The case is each NodeMCU packet will be different , but in the same time I need in the receiver to define the message that will arrive from the sender, and every tutorial I saw works with same message structure,

is there a way to be somewhat dynamic?

these are example for the first sender and the receiver

I want to add another nodeMCU sender which will send

typedef struct message {
    char peerId;
    int mositure; // must be unique for each sender board
    int EC;
};

receiver :

#include <Arduino.h>
#include <WiFi.h>
#include <esp_now.h>
 
typedef struct message {
    char peerId;
    int flowRate; // must be unique for each sender board
    int totalLitres;
};

typedef struct flow_meter {
    char peerId;
    int flowRate; // must be unique for each sender board
    int totalLitres;
} flow_meter;
 
struct flow_meter myMessage;
 
void onDataReceiver(const uint8_t * mac, const uint8_t *incomingData, int len) {
  Serial.println("Message received.");
  // We don't use mac to verify the sender
  // Let us transform the incomingData into our message structure
 memcpy(&myMessage, incomingData, sizeof(myMessage));
 Serial.println("=== Data ===");
 Serial.print("Mac address: ");
 for (int i = 0; i < 6; i++) {
     Serial.print("0x");
     Serial.print(mac[i], HEX);
     Serial.print(":");
 }
 /*Serial.println("*******");
    Serial.print(incomingData.peerId);
    Serial.println("*********");*/
 Serial.print("\n\npeerId: ");
 Serial.print(myMessage.peerId);
 Serial.println();
 Serial.print("\n\nflowRate: ");
 Serial.println(myMessage.flowRate);
 Serial.print("\n\ntotalLitres: ");
 Serial.println(myMessage.totalLitres);
 Serial.println();
}
 
void setup() {
 Serial.begin(115200);
 WiFi.mode(WIFI_STA);
 
 // Get Mac Add
 Serial.print("Mac Address: ");
 Serial.print(WiFi.macAddress());
 Serial.println("ESP32 ESP-Now Broadcast");
 
 // Initializing the ESP-NOW
 if (esp_now_init() != 0) {
   Serial.println("Problem during ESP-NOW init");
   return;
 }
 esp_now_register_recv_cb(onDataReceiver);
}
 
void loop() {
 // put your main code here, to run repeatedly:
}

sender :

/**
* ESP-NOW
*
* Sender
*/
 
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <espnow.h>
#include <SPI.h>
 
uint8_t peer1[] = {0x24, 0x62, 0xAB, 0xFF, 0x2C, 0x5C};
 
typedef struct struct_message {
    char peerId;
    int flowRate; // must be unique for each sender board
    int totalLitres;
} struct_message;
 
struct struct_message myMessage;
 
// Initialize DHT sensor.
 
void onSent(uint8_t *mac_addr, uint8_t sendStatus) {
 Serial.print("Last Packet Send Status: ");
  if (sendStatus == 0){
    Serial.println("Delivery success");
  }
  else{
    Serial.println("Delivery fail");
  }
}
 
void setup() {
 Serial.begin(115200);
 
 myMessage.peerId = 'w';
 
 WiFi.mode(WIFI_STA);
 
 // Get Mac Add
 Serial.print("Mac Address: ");
 Serial.print(WiFi.macAddress());
 Serial.println("ESP-Now Sender");
 
 // Initializing the ESP-NOW
 if (esp_now_init() != 0) {
   Serial.println("Problem during ESP-NOW init");
   return;
 }
 
 esp_now_set_self_role(ESP_NOW_ROLE_CONTROLLER);
 // Register the peer
 Serial.println("Registering a peer");
 esp_now_add_peer(peer1, ESP_NOW_ROLE_SLAVE, 1, NULL, 0);
 Serial.println("Registering send callback function");
 esp_now_register_send_cb(onSent);
}
 
void loop() {
 
 myMessage.flowRate = 33;
 myMessage.totalLitres = 90000/1000;
 Serial.println("Send a new message");
 esp_now_send(NULL, (uint8_t *) &myMessage, sizeof(myMessage));
 
 delay(3000);
}

Can you examine the first byte if incomingData and determine which sender the message came from and hence which struct to copy the data to ?

another approach is to use the mac-adress that is received as the first parameter in the call-back-function

void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int NoOfBytesRcv) {

depending on the mac-adress you can call different lines of code that do the memcpy from incomingData into the structured variable

if (mac == MyMac1) {
    memcpy(&my_received_ESP_NOW_Data1, incomingData, sizeof(my_received_ESP_NOW_Data1));
}

if (mac == MyMac2) {
    memcpy(&my_received_ESP_NOW_Data2, incomingData, sizeof(my_received_ESP_NOW_Data2));
}

best regards Stefan

Have a look on randomnerd tutorial, they have some great help with these types of systems.

If this was my project I would ensure that every message contains the same type of data - for example a char followed by two ints.

Then regardless of where the message comes from you can read it into a standard struct. Then you can examine the value of peerId to decide what to do with the data - perhaps copy it to another struct that has variable names appropriate for the data from that peer.

...R