En entradas anteriores, hemos visto qué es ESP-NOW y cómo configurar una comunicación básica entre dos dispositivos ESP32 para enviar una variable simple.
En esta entrada, vamos a profundizar en el uso de ESP-NOW para enviar una estructura de datos (struct) en una comunicación 1 a 1.
En proyectos avanzados, no siempre es suficiente enviar una sola variable. A menudo, necesitamos enviar múltiples datos relacionados entre sí (como un mensaje de texto, un número entero, un valor decimal y un booleano).
Una opción muy cómoda para hacer esto es enviarlos agruparlos en una estructura de datos (struct). Esto simplifica el código y además incluso mejora la eficiencia de la comunicación (que mal no hace)
En las próximas entradas, exploraremos cómo enviar strings, JSON, y cómo manejar comunicaciones 1 a muchos, muchos a 1, y muchos a muchos.
Enviar un struct
Supongamos que tenemos una estructura Message
, que define un conjunto de datos que queremos enviar:
- text[20]: Un array de caracteres para almacenar un mensaje de texto.
- integer: Un número entero.
- decimal: Un número decimal (float).
- boolean: Un valor booleano (true/false).
Esta estructura se serializa y se envía como un bloque de bytes a través de ESP-NOW.
El funcionamiento es muy similar al que vimos en la entrada anterior para mandar un simple dato. La diferencia es que ahora vamos a mandar todo el struct (en lugar de una variable primitiva)
Message payload;
strcpy(payload.text, "MESSAGE TEXT");
payload.integer = random(1, 100);
payload.decimal = 2.1;
payload.boolean = false;
esp_err_t result = esp_now_send(MAC_RECEIVER_1, (uint8_t*)&payload, sizeof(Message));
De igual forma, al recibirlo, tendremos que castear a Message*
.
auto payload = (Message*)(data);
Como vemos, en realidad no es mucho más complicado mandar la estructura que un tipo primitivo.
Ejemplo completo
Vamos a ver el ejemplo completo 👇
- Inicialización de ESP-NOW: Se inicializa ESP-NOW y se registra un callback para saber si el mensaje se envió correctamente.
- Registro del peer: Se registra la dirección MAC del receptor como un “peer” (par) en la red ESP-NOW.
- Envío del mensaje: Se crea una instancia de la estructura
Message
, se llena con datos y se envía al receptor utilizandoesp_now_send
.
#include <esp_now.h>
#include <WiFi.h>
#include "const.h"
#include "message.hpp"
void OnDataSent(const uint8_t* mac_addr, esp_now_send_status_t status)
{
Serial.print("\r\nLast Packet Send Status:\t");
Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
}
void SendMessage()
{
Message payload;
strcpy(payload.text, "MESSAGE TEXT");
payload.integer = random(1, 100);
payload.decimal = 2.1;
payload.boolean = false;
esp_err_t result = esp_now_send(MAC_RECEIVER_1, (uint8_t*)&payload, sizeof(Message));
if(result == ESP_OK)
{
Serial.println("Sent with success");
}
else
{
Serial.println("Error sending the data");
}
}
void static RegisterPeeks()
{
esp_now_peer_info_t peerInfo;
memcpy(peerInfo.peer_addr, MAC_RECEIVER_1, 6);
peerInfo.channel = 0;
peerInfo.encrypt = false;
if(esp_now_add_peer(&peerInfo) != ESP_OK)
{
Serial.println("Failed to add peer");
}
else
{
Serial.print("Registered peer ");
}
}
void static InitEspNow()
{
if(esp_now_init() != ESP_OK)
{
Serial.println("Error initializing ESP-NOW");
}
else
{
esp_now_register_send_cb(OnDataSent);
RegisterPeeks();
}
}
void setup()
{
Serial.begin(115200);
delay(2000);
WiFi.mode(WIFI_STA);
InitEspNow();
}
void loop()
{
SendMessage();
delay(2000);
}
- Inicialización de ESP-NOW: Se inicializa ESP-NOW y se registra un callback para manejar los mensajes recibidos.
- Recepción del mensaje: Cuando se recibe un mensaje, se deserializa la estructura
Message
y se imprimen sus valores en el monitor serial.
#include <esp_now.h>
#include <WiFi.h>
#include "const.h"
#include "message.hpp"
void OnMessageReceived(const uint8_t* mac, const uint8_t* data, int len)
{
Serial.printf("Packet received from: %02X:%02X:%02X:%02X:%02X:%02X\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
Serial.printf("Bytes received: %d\n", len);
auto payload = (Message*)(data);
Serial.print("Char: ");
Serial.println(payload->text);
Serial.print("Int: ");
Serial.println(payload->integer);
Serial.print("Float: ");
Serial.println(payload->decimal);
Serial.print("Bool: ");
Serial.println(payload->boolean);
Serial.println();
}
void initEspNow()
{
if(esp_now_init() != ESP_OK)
{
Serial.println("Error initializing ESP-NOW");
return;
}
else
{
esp_now_register_recv_cb(OnMessageReceived);
}
}
void setup()
{
Serial.begin(115200);
WiFi.mode(WIFI_STA);
initEspNow();
}
void loop()
{
}
typedef struct Message
{
char text[20];
int integer;
float decimal;
bool boolean;
} Message;
const uint8_t MAC_SENDER_1[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
const uint8_t MAC_RECEIVER_1[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };