En entradas anteriores, hemos cubierto los conceptos básicos de ESP-NOW, cómo configurar una comunicación 1 a 1 y cómo manejar una comunicación 1 a muchos.
En esta entrada, vamos a profundizar en el uso de ESP-NOW para implementar una comunicación muchos a 1.
Nuevamente me voy a centrar en enviar un string (porque algo hay que enviar). Pero es fácilmente extrapolable a enviar un JSON, un struct, o cualquier otra cosa.
En las próximas entradas, exploraremos cómo manejar una comunicación muchos a muchos.
¿Qué es una comunicación muchos a 1?
En una comunicación muchos a 1, múltiples dispositivos (emisores) envían datos a un único dispositivo (receptor).
Este tipo de comunicación es útil en aplicaciones donde varios sensores o nodos deben reportar datos a un nodo central (como en sistemas de monitoreo ambiental, control industrial, o redes de sensores inalámbricos).
Respecto al caso de 1 a 1, en esta caso igualmente vamos a tener muchas MAC de emisores.
const uint8_t* SENDERS_MACS[] = { /* ... */ };
const uint8_t SENDERS_COUNT = sizeof(SENDERS_MACS) / sizeof(uint8_t*);
En este caso, el registro de receptores de los emisores no varia. Únicamente tienen que registrar uno en RegisterPeeks
.
Pero ahora el receptor va a tener que discriminar quién (narices) le manda la información. Para eso en el callback del receptor va a tener que buscar entre las MAC que conoce.
int SearchSender(const uint8_t* mac)
{
for(auto sender_id = 0; sender_id < SENDERS_COUNT; sender_id++)
{
if(AreMacEquals(mac, SENDERS_MACS[sender_id])) return sender_id;
}
return -1;
}
void OnMessageReceived(const uint8_t* mac, const uint8_t* data, int len)
{
/* ... */
auto sender_id = SearchSender(mac);
Serial.printf("Sender id: %d\n", sender_id);
}
Ejemplo completo
Vamos a ver cómo quedaría todo esto junto 👇
- 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” en la red ESP-NOW.
- Envío del mensaje: Se envía un string al receptor utilizando
esp_now_send
. El string se convierte a un array de bytes utilizandopayload.c_str()
.
#include <esp_now.h>
#include <WiFi.h>
#include "const.h"
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()
{
String payload = "MY STRING";
esp_err_t result = esp_now_send(MAC_RECEIVER_1, (uint8_t*)payload.c_str(), payload.length());
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 reconstruye el string a partir de los bytes recibidos y se imprime en el monitor serial.
- Identificación del emisor: Se utiliza la dirección MAC del emisor para identificar qué dispositivo envió el mensaje.
#include <esp_now.h>
#include <WiFi.h>
#include "const.h"
bool AreMacEquals(const uint8_t* src, const uint8_t* dst)
{
for(auto i = 0; i < 6; i++)
{
if(src[i] != dst[i]) return false;
}
return true;
}
int SearchSender(const uint8_t* mac)
{
for(auto sender_id = 0; sender_id < SENDERS_COUNT; sender_id++)
{
if(AreMacEquals(mac, SENDERS_MACS[sender_id])) return sender_id;
}
return -1;
}
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);
String payload;
payload.reserve(len);
for(auto i = 0; i < len; i++)
{
payload += (char)data[i];
}
Serial.println(payload);
auto sender_id = SearchSender(mac);
Serial.printf("Sender id: %d\n", sender_id);
}
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()
{
}
const uint8_t MAC_SENDER_1[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
const uint8_t MAC_RECEIVER_1[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
const uint8_t* SENDERS_MACS[] = { MAC_SENDER_1 };
const uint8_t SENDERS_COUNT = sizeof(SENDERS_MACS) / sizeof(uint8_t*);
const uint8_t* RECEIVERS_MACS[] = { MAC_RECEIVER_1 };
const uint8_t RECEIVERS_COUNT = sizeof(RECEIVERS_MACS) / sizeof(uint8_t*);