Language: EN

esp-now-enviar-json-esp32

Send a JSON via ESP-NOW on ESP32

In previous tutorials, we covered the basics of ESP-NOW, how to set up 1 to 1 communication to send a simple variable, a data structure (struct), or a string.

In this tutorial, we will delve into the use of ESP-NOW to send a JSON in a 1 to 1 communication. This is an important step for handling structured and complex data in our IoT projects and embedded systems.

In upcoming tutorials, we will explore how to handle 1 to many, many to 1, and many to many communications. But for now, we will focus on how to send a JSON.

Why send a JSON?

JSON (JavaScript Object Notation) is a lightweight and easy-to-read data interchange format for both humans and machines. It is widely used in web applications and IoT to transmit structured data.

{
  "name": "Luis",
  "age": 30,
  "active": true
}

Sending a JSON allows us to send multiple related data in a single message, which is especially useful for configurations, complex commands, or grouped sensor data.

Moreover, a JSON is still a string. So, regarding the previous tutorial, it’s basically that we need to serialize the data in the JSON we want to send and receive. For example:

String payload = "";
StaticJsonDocument<300> jsonDoc;
jsonDoc["name"] = "Luis";
jsonDoc["age"] = 30;
jsonDoc["active"] = true;

serializeJson(jsonDoc, payload);

In this case, we defined a JSON with three fields: "name", "age", and "active".

Similarly, to receive the JSON, we wait for the callback function onDataReceived() to be executed, and we will need to deserialize the JSON:

StaticJsonDocument<300> jsonDoc;
DeserializationError error = deserializeJson(jsonDoc, payload);
if(error) { Serial.print("Error packet."); return; }

const char* receivedName = jsonDoc["name"];
int receivedAge = jsonDoc["age"];
bool receivedActive = jsonDoc["active"];

Important: Remember that ESP-NOW has a limit of 250 bytes per message. In a JSON, you can really exhaust them quickly.

Complete Example

Let’s look at 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 receiver’s MAC address is registered as a “peer” in the ESP-NOW network.
  • Creating the JSON: A JSON is created using the ArduinoJson library. In this case, the JSON contains a single field "data" with a value of 1.
  • Sending the Message: The JSON is serialized to a string and sent to the receiver using esp_now_send.
#include <esp_now.h>
#include <WiFi.h>
#include <ArduinoJson.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 = "";
	StaticJsonDocument<300> jsonDoc;
	jsonDoc["data"] = 1;
	serializeJson(jsonDoc, payload);

	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);
}
  • ESP-NOW Initialization: ESP-NOW is initialized, and a callback is registered to handle received messages.
  • Receiving the Message: When a message is received, the string is reconstructed from the received bytes.
  • Deserializing the JSON: The received string is deserialized using the ArduinoJson library to extract the data from the JSON.
#include <esp_now.h>
#include <WiFi.h>
#include <ArduinoJson.h>

#include "const.h"

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];
	}

	StaticJsonDocument<200> doc;
	DeserializationError error = deserializeJson(doc, payload);
	if(error) { Serial.print("Error packet."); return; }

	int packet_id = doc["data"];
	Serial.println(payload);
	Serial.println(packet_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_RECEIVER_1 };
const uint8_t SENDERS_COUNT = sizeof(SENDERS_MACS) / sizeof(uint8_t*);

const uint8_t* RECEIVERS_MACS[] = { MAC_SENDER_1 };
const uint8_t RECEIVERS_COUNT = sizeof(RECEIVERS_MACS) / sizeof(uint8_t*);