Hello!, im using bidirectional ESPNOW and im sending different types of data, for example im sending an structure with sensed data periodically, but in some circunstances i need to send some string information that can be variable in length, the question is how can i know which one is in the reciever part? because the data is all in const Uint8_t* , for the structure is kind of easy, i can know it size and then compare with the size of the incoming data, but how can i know if its variable? To explain better: imagine that i want to send 2 separate things, 1 can be a simple string converted to const uint8_t*, but the other can be a structure, both of them use the same amount of bytes, how can i differenciate them? hope you can get the question, thanks in advance!
the callback function
// callback function that will be executed when data is received
void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) {
indicates the length (parameter len) of the received packet
if you send packets of different lengths this could indicate the packet type
another way is for the first byte of the packet to indicate packet type
uhh how can i do that? its like concatenate a const uint8_t at the beginning of the packet?
You can add a new field to the data structure
Use a union inside the struct:
struct DataStruct1 {
uint8_t x1;
uint32_t x2;
float x3;
};
struct DataStruct2 {
char name[10];
float x1;
float x2;
};
struct TransferStruct {
enum DataType {STRUCT1, STRUCT2, STRING};
DataType type;
union {
DataStruct1 struct1;
DataStruct2 struct2;
char string[20];
};
};
TransferStruct receivedStructure;
void loop() {
//
//
switch (receivedStructure.type) {
case TransferStruct::STRUCT1:
// Process members of receivedStructure.struct1
break;
case TransferStruct::STRUCT2:
//Process members of receivedStructure.struct2
break;
case TransferStruct::STRING:
// Process receivedStructure.string
break;
default:
break;
}
//
//
}
sender
// run on WeMos D1 ESP8266 WiFi Board ESP8266 ESP8266 Board MAC Address: 2C:3A:E8:22:78:DE
/*
Rui Santos
Complete project details at https://RandomNerdTutorials.com/esp-now-esp8266-nodemcu-arduino-ide/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
*/
#include <ESP8266WiFi.h>
#include <espnow.h>
// REPLACE WITH RECEIVER MAC Address
uint8_t broadcastAddress[] = {0x60,0x01,0x94,0x1F,0x7B,0xEE};
// Structure example to send data
// Must match the receiver structure
typedef struct struct_message {
int type;
float c;
} struct_message;
typedef struct struct_message2 {
int type;
String s;
} struct_message2;
// Create a struct_message called myData
struct_message myData;
struct_message2 myData2;
unsigned long lastTime = 0;
unsigned long timerDelay = 2000; // send readings timer
// Callback when data is sent
void OnDataSent(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() {
// Init Serial Monitor
Serial.begin(115200);
// Set device as a Wi-Fi Station
WiFi.mode(WIFI_STA);
Serial.println();
Serial.print("ESP8266 Board MAC Address: ");
Serial.println(WiFi.macAddress());
// Init ESP-NOW
if (esp_now_init() != 0) {
Serial.println("Error initializing ESP-NOW");
return;
}
// Once ESPNow is successfully Init, we will register for Send CB to
// get the status of Trasnmitted packet
esp_now_set_self_role(ESP_NOW_ROLE_CONTROLLER);
esp_now_register_send_cb(OnDataSent);
// Register peer
esp_now_add_peer(broadcastAddress, ESP_NOW_ROLE_SLAVE, 1, NULL, 0);
Serial.setTimeout(1000000L); // set so Serial.readString() won't timeout
}
void loop() {
if ((millis() - lastTime) > timerDelay) {
static int type = 0;
if(type == 0) {
// Set values to send
myData.type = type;
myData.c = 1.2 + random(1,20);
type=1;
// Send message via ESP-NOW
esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData));
}
else {
myData2.type = type;
Serial.print("Enter a string ? ");
myData2.s = Serial.readStringUntil('\n'); // <<<< read string
type=0;
// Send message via ESP-NOW
esp_now_send(broadcastAddress, (uint8_t *) &myData2, sizeof(myData2));
}
lastTime = millis();
}
}
receiver
// run on Wemos Lolin NodeMcu V3 ESP8266 Devkit ESP8266 Board MAC Address: 60:01:94:1F:7B:EE
/*
Rui Santos
Complete project details at https://RandomNerdTutorials.com/esp-now-esp8266-nodemcu-arduino-ide/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
*/
#include <ESP8266WiFi.h>
#include <espnow.h>
// Structure example to receive data
// Must match the sender structure
typedef struct struct_message {
int type;
float c;
} struct_message;
typedef struct struct_message2 {
int type;
String s;
} struct_message2;
// Create a struct_message called myData
struct_message myData;
struct_message2 myData2;
// Callback function that will be executed when data is received
void OnDataRecv(uint8_t * mac, uint8_t *incomingData, uint8_t len) {
Serial.print("Bytes received: ");
Serial.println(len);
int type;
memcpy(&type, incomingData, sizeof(int));
Serial.print("type: ");
Serial.println(type);
if(type == 0){
memcpy(&myData, incomingData, sizeof(myData));
Serial.print("Float: ");
Serial.println(myData.c);
Serial.println();
}
else {
memcpy(&myData2, incomingData, sizeof(myData2));
Serial.print("String: ");
Serial.println(myData2.s);
Serial.println();
}
}
void setup() {
// Initialize Serial Monitor
Serial.begin(115200);
// Set device as a Wi-Fi Station
WiFi.mode(WIFI_STA);
Serial.println();
Serial.print("ESP8266 Board MAC Address: ");
Serial.println(WiFi.macAddress());
// Init ESP-NOW
if (esp_now_init() != 0) {
Serial.println("Error initializing ESP-NOW");
return;
}
Serial.println("ESP-NOW initialised");
// Once ESPNow is successfully Init, we will register for recv CB to
// get recv packer info
esp_now_set_self_role(ESP_NOW_ROLE_SLAVE);
esp_now_register_recv_cb(OnDataRecv);
}
void loop() {
}
sender output
Last Packet Send Status: Delivery success
Enter a string ? Last Packet Send Status: Delivery success
Last Packet Send Status: Delivery success
Enter a string ?
receiver output
ESP8266 Board MAC Address: 60:01:94:1F:7B:EE
ESP-NOW initialised
Bytes received: 8
type: 0
Float: 20.20
Bytes received: 16
type: 1
String: testing
Bytes received: 8
type: 0
Float: 6.20
Union containing structures of the different length? At least you will need a packet length variable....
Nope. The union will constant-sized to accommodate the largest struct. That means the transferred data packet will always be the same size. A little inefficient but a much cleaner approach. See the code I posted.
Oh thank you so much! i will try both ways , totally understood your codes ![]()
This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.