esp-now-enviar-struct-con-esp32

Send a struct with ESP-NOW on ESP32

  • 3 min

In previous posts, we have seen what ESP-NOW is and how to set up basic communication between two ESP32 devices to send a simple variable.

In this post, we will delve into the use of ESP-NOW to send a data structure (struct) in a one-to-one communication.

In advanced projects, it is not always sufficient to send a single variable. Often, we need to send multiple related data (such as a text message, an integer, a decimal value, and a boolean).

A very convenient option to do this is to group them in a data structure (struct). This simplifies the code and also improves communication efficiency (which is not a bad thing)

In the upcoming posts, we will explore how to send strings, JSON, and how to handle one-to-many, many-to-one, and many-to-many communications.

Send a struct

Let’s assume we have a structure Message, which defines a set of data we want to send:

  • text[20]: A character array to store a text message.
  • integer: An integer number.
  • decimal: A decimal number (float).
  • boolean: A boolean value (true/false).

This structure is serialized and sent as a block of bytes over ESP-NOW.

The operation is very similar to what we saw in the previous post for sending a simple data. The difference is that now we are going to send the entire struct (instead of a primitive variable)

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));

Similarly, upon receiving it, we will need to cast to Message*.

auto payload = (Message*)(data);

As we can see, it is not much more complicated to send the structure than a primitive type.

Complete Example

Let’s see the complete example 👇

  • ESP-NOW Initialization: ESP-NOW is initialized and a callback is registered to know if the message was sent successfully.
  • Peer Registration: The MAC address of the receiver is registered as a “peer” in the ESP-NOW network.
  • Message Sending: An instance of the Message structure is created, filled with data, and sent to the receiver using esp_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);
}
  • ESP-NOW Initialization: ESP-NOW is initialized and a callback is registered to handle received messages.
  • Message Reception: When a message is received, the Message structure is deserialized and its values are printed to the serial monitor.
#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 };