Home / References / ESP32 Library / AsyncUDP Library
Description
The sendTo() method is a versatile data transmission function in the AsyncUDP library that enables ESP32 devices to send UDP packets using the AsyncUDPMessage buffer system to any specified IP address and port. Unlike the send() method which requires a pre-established connection, sendTo() provides the flexibility to transmit data to any network endpoint without needing to call connect() first.
This method is available in the AsyncUDP class and accepts both IPv4 and IPv6 addresses, making it perfect for one-shot transmissions, broadcast scenarios, multi-destination messaging, and dynamic target communications. The method works with pre-constructed AsyncUDPMessage objects that contain the data to be transmitted, offering efficient buffer management and structured data organization. It’s particularly useful for implementing peer-to-peer communications, IoT sensor networks, distributed systems, discovery protocols, and applications requiring direct point-to-point messaging without maintaining persistent connections.
The sendTo() method operates asynchronously and integrates seamlessly with ESP32’s networking stack, ensuring efficient data transmission while providing precise control over destination addressing and network interface selection.
This page is part of the Comprehensive Guide to the ESP32 Arduino Core Library, accessible on AvantMaker.com.
Syntax and Usage
The sendTo() method has two main overloaded forms for different address types:
- IPv4/IPAddress version:
udp.sendTo(message, IPAddress, port [, interface])- Low-level ip_addr_t version:
udp.sendTo(message, &ip_addr, port [, interface])Arguments
The sendTo() method accepts the following arguments:
- message (AsyncUDPMessage&): A reference to an AsyncUDPMessage object containing the data to be transmitted. The message buffer must be properly constructed and contain valid data before calling sendTo().
- addr (IPAddress or ip_addr_t*): The destination IP address where the message should be sent. Can be IPv4 or IPv6 address, unicast, multicast, or broadcast address.
- port (uint16_t): The destination port number on the target device (1-65535).
- tcpip_if (tcpip_adapter_if_t, optional): Network interface to use for transmission. Defaults to TCPIP_ADAPTER_IF_MAX (automatic interface selection). Available options include TCPIP_ADAPTER_IF_STA (WiFi Station), TCPIP_ADAPTER_IF_AP (WiFi Access Point), and TCPIP_ADAPTER_IF_ETH (Ethernet).
Return Value
The sendTo() method returns a size_t value indicating the number of bytes successfully transmitted to the specified destination. A return value of 0 indicates that the transmission failed (possibly due to network errors, invalid addresses, or insufficient memory), while a positive value represents the actual number of bytes sent from the message buffer to the target endpoint. The method performs immediate transmission without requiring a pre-established connection, making it ideal for stateless UDP communications. Internally, the method validates the message buffer, converts address formats as needed, and calls the underlying writeTo() function with the message data and specified destination parameters. The method ensures reliable transmission by utilizing the lwIP UDP stack and provides immediate feedback about transmission success through its return value. Unlike the send() method, sendTo() does not depend on connection state and can target any reachable network endpoint, providing maximum flexibility for UDP communications.
Example Code
Simple Example: Multi-Destination Message Sender
This example demonstrates how to use the sendTo() method to transmit data using AsyncUDPMessage buffers to multiple specific destinations without requiring pre-established connections. The ESP32 sends various types of structured messages including text, JSON, binary data, and sensor readings to different target endpoints. This demonstrates the practical application of the sendTo() method for distributed systems, peer-to-peer communications, multi-node IoT networks, and flexible messaging systems that require dynamic destination addressing.
How to use this example: Upload this code to your ESP32, update the WiFi credentials and configure target IP addresses in the destinations array. The ESP32 will start sending structured messages to different endpoints in a round-robin fashion. Use the companion receiver example (provided below) on other ESP32 devices or computers to receive the transmitted data.
/*
* Author: Avant Maker
* Date: January 15, 2025
* Version: 1.0
* License: MIT
*
* Description:
* Multi-Destination Message Sender that demonstrates sendTo() method usage for transmitting
* structured data using AsyncUDPMessage buffers to multiple specific UDP endpoints without
* requiring pre-established connections. This example shows how to create, populate, and
* send message buffers containing different data types to various network destinations,
* demonstrating practical distributed communication patterns and peer-to-peer messaging
* applications using the AsyncUDP library's sendTo() functionality.
*
* Features Demonstrated:
* - AsyncUDPMessage buffer creation and management for sendTo() operations
* - Multi-destination structured data transmission using sendTo() method
* - Dynamic target addressing without connection requirements
* - Multiple message format transmission (text, JSON, binary, sensor data)
* - Round-robin destination cycling and load distribution
* - Network interface selection and optimization
* - Transmission statistics and error handling
* - Memory efficient message handling across multiple targets
* - Broadcast and multicast capabilities using sendTo()
*
* Hardware Requirements:
* - ESP32 development board
* - WiFi network access
* - Multiple UDP servers/receivers (use companion receiver example)
*
* How to use this example:
* 1. Update WiFi credentials (ssid and password)
* 2. Configure target destinations in the destinations array
* 3. Upload code to ESP32
* 4. Deploy companion receiver examples on target devices
* 5. Monitor Serial output for transmission status and statistics
*
* Code Source:
* This example code is sourced from the Comprehensive Guide
* to the ESP32 Arduino Core Library, accessible on AvantMaker.com.
* For additional code examples and in-depth documentation related to
* the ESP32 Arduino Core Library, please visit:
*
* https://avantmaker.com/home/all-about-esp32-arduino-core-library/
*
* AvantMaker.com, your premier destination for all things
* DIY, AI, IoT, Smart Home, and STEM projects. We are dedicated
* to empowering makers, learners, and enthusiasts with
* the resources they need to bring their innovative ideas to life.
*/
#include <WiFi.h>
#include <AsyncUDP.h>
#include <ArduinoJson.h>
// WiFi credentials
const char* ssid = "your_SSID"; // Replace with your Wi-Fi SSID
const char* password = "your_PASSWORD"; // Replace with your Wi-Fi password
// Target destination configuration
struct Destination {
IPAddress ip;
uint16_t port;
String name;
unsigned long messageCount;
unsigned long byteCount;
unsigned long lastSent;
bool active;
};
// Configure your target destinations here
Destination destinations[] = {
{IPAddress(192, 168, 0, 123), 8888, "Server-1", 0, 0, 0, true},
{IPAddress(192, 168, 0, 101), 8889, "Server-2", 0, 0, 0, true},
{IPAddress(192, 168, 0, 102), 8890, "Server-3", 0, 0, 0, true},
{IPAddress(255, 255, 255, 255), 8891, "Broadcast", 0, 0, 0, true} // Broadcast address
};
const int numDestinations = sizeof(destinations) / sizeof(destinations[0]);
AsyncUDP udp;
AsyncUDPMessage message(1024); // Create message buffer with 1024 bytes capacity
unsigned long totalMessageCounter = 0;
int currentDestination = 0;
// Simulation variables for sensor data
float temperature = 25.0;
float humidity = 60.0;
int lightLevel = 512;
bool ledState = false;
void setup() {
Serial.begin(115200);
Serial.println("ESP32 UDP Multi-Destination Sender - sendTo() Method Demo");
// Display configuration
Serial.println("=== Configuration ===");
Serial.printf("Device MAC: %s\n", WiFi.macAddress().c_str());
Serial.printf("Message Buffer Size: %d bytes\n", 1024);
Serial.printf("Number of Destinations: %d\n", numDestinations);
Serial.println("Target Destinations:");
for (int i = 0; i < numDestinations; i++) {
Serial.printf(" %d: %s (%s:%d) - %s\n",
i + 1,
destinations[i].name.c_str(),
destinations[i].ip.toString().c_str(),
destinations[i].port,
destinations[i].active ? "Active" : "Inactive");
}
Serial.println("====================");
// Connect to WiFi
WiFi.begin(ssid, password);
Serial.printf("Connecting to WiFi: %s", ssid);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.print(".");
}
Serial.println("\nWiFi connected successfully!");
Serial.printf("Local IP: %s\n", WiFi.localIP().toString().c_str());
Serial.printf("Gateway: %s\n", WiFi.gatewayIP().toString().c_str());
Serial.printf("DNS: %s\n", WiFi.dnsIP().toString().c_str());
Serial.printf("Signal Strength: %d dBm\n", WiFi.RSSI());
// Initialize UDP (no need to connect since we're using sendTo)
Serial.println("UDP initialized for sendTo() operations");
// Send initial announcement to all destinations
sendAnnouncementToAll();
Serial.println("Starting multi-destination message transmission...");
Serial.println("================================================");
}
void loop() {
static unsigned long lastSend = 0;
static int messageType = 0;
// Send messages every 3 seconds
if (millis() - lastSend > 3000) {
lastSend = millis();
totalMessageCounter++;
// Send different types of messages based on cycle
switch (messageType % 5) {
case 0:
sendTextMessage();
break;
case 1:
sendSensorMessage();
break;
case 2:
sendJSONMessage();
break;
case 3:
sendBinaryMessage();
break;
case 4:
sendSystemMessage();
break;
}
messageType++;
// Cycle to next destination
do {
currentDestination = (currentDestination + 1) % numDestinations;
} while (!destinations[currentDestination].active && currentDestination != 0);
}
// Update simulated sensor values
updateSensorValues();
// Display periodic status
static unsigned long lastStatus = 0;
if (millis() - lastStatus > 30000) { // Every 30 seconds
lastStatus = millis();
displayStatus();
}
delay(1000);
}
void sendAnnouncementToAll() {
message.flush();
String announcement = "ESP32 Multi-Destination Sender Online - Device: " + WiFi.macAddress() + " IP: " + WiFi.localIP().toString();
message.print(announcement);
Serial.println("Sending announcement to all destinations:");
for (int i = 0; i < numDestinations; i++) {
if (destinations[i].active) {
size_t sent = udp.sendTo(message, destinations[i].ip, destinations[i].port);
Serial.printf(" %s (%s:%d): %d bytes\n",
destinations[i].name.c_str(),
destinations[i].ip.toString().c_str(),
destinations[i].port,
sent);
destinations[i].messageCount++;
destinations[i].byteCount += sent;
destinations[i].lastSent = millis();
}
}
Serial.println("---------------------------------------------");
}
void sendTextMessage() {
// Clear message buffer and construct text message
message.flush();
message.printf("HELLO|%lu|%s|%s|%lu|%d|%s",
totalMessageCounter,
WiFi.macAddress().c_str(),
WiFi.localIP().toString().c_str(),
millis()/1000,
ESP.getFreeHeap(),
destinations[currentDestination].name.c_str());
size_t sent = udp.sendTo(message, destinations[currentDestination].ip, destinations[currentDestination].port);
// Update destination statistics
destinations[currentDestination].messageCount++;
destinations[currentDestination].byteCount += sent;
destinations[currentDestination].lastSent = millis();
Serial.printf("[%lu] Text Message -> %s (%s:%d): %d bytes\n",
totalMessageCounter,
destinations[currentDestination].name.c_str(),
destinations[currentDestination].ip.toString().c_str(),
destinations[currentDestination].port,
sent);
Serial.printf("Content: %s\n", (char*)message.data());
Serial.printf("Buffer Utilization: %d/%d bytes\n", message.length(), message.space() + message.length());
Serial.println("---------------------------------------------");
}
void sendSensorMessage() {
// Clear message buffer and construct sensor data message
message.flush();
message.printf("SENSOR|%lu|%.2f|%.1f|%d|%s|%d|%lu|%s",
totalMessageCounter,
temperature,
humidity,
lightLevel,
ledState ? "ON" : "OFF",
WiFi.RSSI(),
millis(),
destinations[currentDestination].name.c_str());
size_t sent = udp.sendTo(message, destinations[currentDestination].ip, destinations[currentDestination].port);
// Update destination statistics
destinations[currentDestination].messageCount++;
destinations[currentDestination].byteCount += sent;
destinations[currentDestination].lastSent = millis();
Serial.printf("[%lu] Sensor Message -> %s (%s:%d): %d bytes\n",
totalMessageCounter,
destinations[currentDestination].name.c_str(),
destinations[currentDestination].ip.toString().c_str(),
destinations[currentDestination].port,
sent);
Serial.printf("Temperature: %.2f°C, Humidity: %.1f%%, Light: %d, LED: %s\n",
temperature, humidity, lightLevel, ledState ? "ON" : "OFF");
Serial.printf("Buffer Utilization: %d/%d bytes\n", message.length(), message.space() + message.length());
Serial.println("---------------------------------------------");
}
void sendJSONMessage() {
// Clear message buffer and construct JSON message
message.flush();
// Use message buffer as JSON document
DynamicJsonDocument doc(512);
doc["type"] = "json_data";
doc["messageId"] = totalMessageCounter;
doc["deviceId"] = WiFi.macAddress();
doc["sourceIP"] = WiFi.localIP().toString();
doc["targetName"] = destinations[currentDestination].name;
doc["timestamp"] = millis();
doc["sensors"]["temperature"] = temperature;
doc["sensors"]["humidity"] = humidity;
doc["sensors"]["light"] = lightLevel;
doc["status"]["led"] = ledState;
doc["status"]["wifi_rssi"] = WiFi.RSSI();
doc["status"]["free_heap"] = ESP.getFreeHeap();
doc["status"]["uptime"] = millis() / 1000;
// Serialize JSON to message buffer
String jsonString;
serializeJson(doc, jsonString);
message.print(jsonString);
size_t sent = udp.sendTo(message, destinations[currentDestination].ip, destinations[currentDestination].port);
// Update destination statistics
destinations[currentDestination].messageCount++;
destinations[currentDestination].byteCount += sent;
destinations[currentDestination].lastSent = millis();
Serial.printf("[%lu] JSON Message -> %s (%s:%d): %d bytes\n",
totalMessageCounter,
destinations[currentDestination].name.c_str(),
destinations[currentDestination].ip.toString().c_str(),
destinations[currentDestination].port,
sent);
Serial.printf("JSON Content: %s\n", jsonString.c_str());
Serial.printf("Buffer Utilization: %d/%d bytes\n", message.length(), message.space() + message.length());
Serial.println("---------------------------------------------");
}
void sendBinaryMessage() {
// Clear message buffer and construct binary message
message.flush();
// Add binary header
message.write('S'); // SendTo message identifier
message.write('T');
message.write('O');
message.write(0x00); // Null terminator
// Add binary data structure
uint32_t msgId = totalMessageCounter;
uint32_t timestamp = millis();
float temp = temperature;
float hum = humidity;
uint16_t light = lightLevel;
uint8_t led = ledState ? 1 : 0;
int8_t rssi = WiFi.RSSI();
uint32_t heap = ESP.getFreeHeap();
uint8_t destIndex = currentDestination;
// Write binary data to message buffer
message.write((uint8_t*)&msgId, sizeof(msgId));
message.write((uint8_t*)×tamp, sizeof(timestamp));
message.write((uint8_t*)&temp, sizeof(temp));
message.write((uint8_t*)&hum, sizeof(hum));
message.write((uint8_t*)&light, sizeof(light));
message.write((uint8_t*)&led, sizeof(led));
message.write((uint8_t*)&rssi, sizeof(rssi));
message.write((uint8_t*)&heap, sizeof(heap));
message.write((uint8_t*)&destIndex, sizeof(destIndex));
size_t sent = udp.sendTo(message, destinations[currentDestination].ip, destinations[currentDestination].port);
// Update destination statistics
destinations[currentDestination].messageCount++;
destinations[currentDestination].byteCount += sent;
destinations[currentDestination].lastSent = millis();
Serial.printf("[%lu] Binary Message -> %s (%s:%d): %d bytes\n",
totalMessageCounter,
destinations[currentDestination].name.c_str(),
destinations[currentDestination].ip.toString().c_str(),
destinations[currentDestination].port,
sent);
Serial.printf("Binary Data: Header + %d data bytes\n", message.length() - 4);
Serial.printf("Buffer Utilization: %d/%d bytes\n", message.length(), message.space() + message.length());
Serial.println("---------------------------------------------");
}
void sendSystemMessage() {
// Clear message buffer and construct system information message
message.flush();
message.printf("SYSTEM|%lu|%s|%dMHz|%db|%db|%ddBm|%lus|%s|%s",
totalMessageCounter,
ESP.getChipModel(),
ESP.getCpuFreqMHz(),
ESP.getFreeHeap(),
ESP.getFlashChipSize(),
WiFi.RSSI(),
millis() / 1000,
ESP.getSdkVersion(),
destinations[currentDestination].name.c_str());
size_t sent = udp.sendTo(message, destinations[currentDestination].ip, destinations[currentDestination].port);
// Update destination statistics
destinations[currentDestination].messageCount++;
destinations[currentDestination].byteCount += sent;
destinations[currentDestination].lastSent = millis();
Serial.printf("[%lu] System Message -> %s (%s:%d): %d bytes\n",
totalMessageCounter,
destinations[currentDestination].name.c_str(),
destinations[currentDestination].ip.toString().c_str(),
destinations[currentDestination].port,
sent);
Serial.printf("System: %s @ %dMHz, Heap: %d bytes\n",
ESP.getChipModel(), ESP.getCpuFreqMHz(), ESP.getFreeHeap());
Serial.printf("Buffer Utilization: %d/%d bytes\n", message.length(), message.space() + message.length());
Serial.println("---------------------------------------------");
}
void updateSensorValues() {
// Simulate changing sensor values
static unsigned long lastUpdate = 0;
if (millis() - lastUpdate > 2000) {
lastUpdate = millis();
// Simulate temperature variation
temperature += (random(-20, 21) / 10.0);
if (temperature < 20.0) temperature = 20.0;
if (temperature > 30.0) temperature = 30.0;
// Simulate humidity variation
humidity += (random(-50, 51) / 10.0);
if (humidity < 40.0) humidity = 40.0;
if (humidity > 80.0) humidity = 80.0;
// Simulate light level variation
lightLevel += random(-50, 51);
if (lightLevel < 0) lightLevel = 0;
if (lightLevel > 1023) lightLevel = 1023;
// Toggle LED state occasionally
if (random(0, 10) > 7) {
ledState = !ledState;
}
}
}
void displayStatus() {
Serial.println("======================================================================");
Serial.println(" MULTI-DESTINATION TRANSMISSION STATUS ");
Serial.println("======================================================================");
Serial.printf("Total Messages Sent: %lu\n", totalMessageCounter);
Serial.printf("Active Destinations: %d/%d\n", countActiveDestinations(), numDestinations);
Serial.printf("Current Target: %s (%s:%d)\n",
destinations[currentDestination].name.c_str(),
destinations[currentDestination].ip.toString().c_str(),
destinations[currentDestination].port);
Serial.printf("Local IP: %s\n", WiFi.localIP().toString().c_str());
Serial.printf("WiFi Signal: %d dBm\n", WiFi.RSSI());
Serial.printf("Uptime: %lu seconds\n", millis() / 1000);
Serial.printf("Free Heap: %d bytes\n", ESP.getFreeHeap());
Serial.printf("Message Buffer: %d bytes capacity\n", message.space() + message.length());
Serial.println("\nDestination Statistics:");
Serial.println("Name | IP Address | Port | Messages | Bytes | Last Sent | Status");
Serial.println("-----------|---------------|------|----------|--------|-----------|--------");
unsigned long currentTime = millis();
for (int i = 0; i < numDestinations; i++) {
String status = destinations[i].active ?
((currentTime - destinations[i].lastSent < 60000) ? "Recent" : "Old") :
"Inactive";
Serial.printf("%-10s | %-13s | %-4d | %-8lu | %-6lu | %-9lu | %s\n",
destinations[i].name.c_str(),
destinations[i].ip.toString().c_str(),
destinations[i].port,
destinations[i].messageCount,
destinations[i].byteCount,
destinations[i].lastSent / 1000,
status.c_str());
}
Serial.println("======================================================================");
}
int countActiveDestinations() {
int count = 0;
for (int i = 0; i < numDestinations; i++) {
if (destinations[i].active) count++;
}
return count;
}Testing Example: UDP Message Receiver
This companion example demonstrates how to create a UDP receiver that listens for messages sent by the previous example. This receiver ESP32 will display all incoming UDP messages in various formats, allowing you to verify that the sendTo() method is working correctly. The receiver provides detailed parsing of different message types including text, sensor data, JSON, binary packets, and system information.
How to test with multiple ESP32 boards:
- Setup Multiple Receivers: Upload this “UDP Message Receiver” code to your receiver ESP32s and note their IP addresses from the Serial Monitor.
- Setup the Sender: Upload the previous “Multi-Destination Message Sender” code to your sender ESP32 and update the
destinationsarray with the receiver ESP32s’ IP addresses. - Configure Network: Ensure all ESP32 boards are connected to the same WiFi network.
- Monitor Results: Open Serial Monitor for all ESP32s to see message transmission and reception in real-time.
- Verify sendTo() Operation: Observe how messages are sent to different destinations without requiring connection establishment.
/*
* Author: Avant Maker
* Date: January 15, 2025
* Version: 1.0
* License: MIT
*
* Description:
* UDP Message Receiver for testing sendTo() method functionality. This example
* creates a UDP server that listens for incoming messages and displays them in
* various formats. It's designed to work with the Multi-Destination Message Sender example
* to provide comprehensive testing of the AsyncUDP sendTo() method with
* AsyncUDPMessage buffers.
*/
#include <WiFi.h>
#include <AsyncUDP.h>
#include <ArduinoJson.h>
#include <map>
// WiFi credentials
const char* ssid = "your_SSID"; // Replace with your Wi-Fi SSID
const char* password = "your_PASSWORD"; // Replace with your Wi-Fi password
// Server configuration
const uint16_t serverPort = 8888; // Port to listen on - UPDATE THIS FOR DIFFERENT RECEIVERS
AsyncUDP udp;
AsyncUDPMessage responseMessage(512); // Create response message buffer
unsigned long totalMessagesReceived = 0;
unsigned long totalBytesReceived = 0;
// Structure to track sender statistics
struct SenderStats {
String senderIP;
unsigned long messageCount;
unsigned long byteCount;
unsigned long firstSeen;
unsigned long lastSeen;
String lastMessageType;
String lastContent;
};
std::map<String, SenderStats> senderMap;
void setup() {
Serial.begin(115200);
Serial.println("ESP32 UDP Message Receiver - Testing sendTo() Method");
Serial.printf("Receiver Port: %d (Configure this port in sender's destinations array)\n", serverPort);
// Connect to WiFi
WiFi.begin(ssid, password);
Serial.printf("Connecting to WiFi: %s", ssid);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.print(".");
}
Serial.println("\nWiFi connected successfully!");
Serial.printf("Receiver IP: %s\n", WiFi.localIP().toString().c_str());
Serial.printf("Update sender ESP32 destinations array with: {IPAddress(%d, %d, %d, %d), %d, \"YourName\", 0, 0, 0, true}\n",
WiFi.localIP()[0], WiFi.localIP()[1], WiFi.localIP()[2], WiFi.localIP()[3], serverPort);
Serial.printf("Response Buffer Size: %d bytes\n", 512);
// Start UDP server
if (udp.listen(serverPort)) {
Serial.printf("UDP Server listening on port %d\n", serverPort);
Serial.println("Waiting for sendTo() messages from sender...");
// Set up packet handler
udp.onPacket([](AsyncUDPPacket packet) {
handleIncomingMessage(packet);
});
} else {
Serial.println("Failed to start UDP server");
}
}
void loop() {
// Display periodic statistics
static unsigned long lastStats = 0;
if (millis() - lastStats > 30000) { // Every 30 seconds
lastStats = millis();
displayStatistics();
}
delay(1000);
}
void handleIncomingMessage(AsyncUDPPacket packet) {
// Get packet information
IPAddress senderIP = packet.remoteIP();
uint16_t senderPort = packet.remotePort();
size_t messageSize = packet.length();
// Update statistics
totalMessagesReceived++;
totalBytesReceived += messageSize;
// Update sender statistics
String senderKey = senderIP.toString() + ":" + String(senderPort);
unsigned long currentTime = millis();
if (senderMap.find(senderKey) == senderMap.end()) {
// New sender
SenderStats newSender;
newSender.senderIP = senderIP.toString();
newSender.messageCount = 1;
newSender.byteCount = messageSize;
newSender.firstSeen = currentTime;
newSender.lastSeen = currentTime;
senderMap[senderKey] = newSender;
Serial.println("======================================================================");
Serial.println(" NEW SENDTO() SENDER DETECTED ");
Serial.println("======================================================================");
} else {
// Existing sender
senderMap[senderKey].messageCount++;
senderMap[senderKey].byteCount += messageSize;
senderMap[senderKey].lastSeen = currentTime;
}
// Extract message data
String messageData = "";
for (size_t i = 0; i < messageSize; i++) {
messageData += (char)packet.data()[i];
}
senderMap[senderKey].lastContent = messageData;
// Parse and display message based on type
String messageType = parseMessageType(messageData, packet.data(), messageSize);
senderMap[senderKey].lastMessageType = messageType;
Serial.printf("sendTo() Message #%lu from %s:%d (%d bytes) - Type: %s\n",
totalMessagesReceived, senderIP.toString().c_str(), senderPort, messageSize, messageType.c_str());
// Send acknowledgment using sendTo() method back to sender
responseMessage.flush();
responseMessage.printf("ACK_SENDTO|%lu|%s|%d|%lu|%s",
totalMessagesReceived,
messageType.c_str(),
messageSize,
millis(),
WiFi.localIP().toString().c_str());
size_t sent = packet.send(responseMessage);
Serial.printf("Acknowledgment sent back: %d bytes\n", sent);
Serial.println("----------------------------------------------------------------------");
}
String parseMessageType(const String& messageData, const uint8_t* rawData, size_t size) {
// Determine message type and display accordingly
if (messageData.startsWith("HELLO|")) {
Serial.printf("📝 TEXT MESSAGE: %s\n", messageData.c_str());
return "TEXT";
}
else if (messageData.startsWith("SENSOR|")) {
Serial.printf("🌡️ SENSOR DATA: %s\n", messageData.c_str());
parseSensorData(messageData);
return "SENSOR";
}
else if (messageData.startsWith("{") && messageData.endsWith("}")) {
Serial.printf("📋 JSON MESSAGE: %s\n", messageData.c_str());
parseJSONData(messageData);
return "JSON";
}
else if (size > 4 && rawData[0] == 'S' && rawData[1] == 'T' && rawData[2] == 'O' && rawData[3] == 0x00) {
Serial.printf("💾 SENDTO BINARY MESSAGE: %d bytes\n", size);
parseBinaryData(rawData, size);
return "BINARY";
}
else if (messageData.startsWith("SYSTEM|")) {
Serial.printf("🖥️ SYSTEM INFO: %s\n", messageData.c_str());
parseSystemData(messageData);
return "SYSTEM";
}
else if (messageData.indexOf("Multi-Destination Sender Online") >= 0) {
Serial.printf("📢 ANNOUNCEMENT: %s\n", messageData.c_str());
return "ANNOUNCEMENT";
}
else {
Serial.printf("❓ UNKNOWN MESSAGE: %s\n", messageData.c_str());
return "UNKNOWN";
}
}
void parseSensorData(const String& data) {
// Parse sensor data format: SENSOR|msgId|temp|humidity|light|led|rssi|timestamp|target
String values[9];
int fieldIndex = 0;
int startIndex = 7; // Skip "SENSOR|"
for (int i = startIndex; i < data.length() && fieldIndex < 9; i++) {
if (data.charAt(i) == '|' || i == data.length() - 1) {
values[fieldIndex] = data.substring(startIndex, i == data.length() - 1 ? i + 1 : i);
startIndex = i + 1;
fieldIndex++;
}
}
if (fieldIndex >= 7) {
Serial.printf(" 📊 Msg ID: %s, Temp: %s°C, Humidity: %s%%, Light: %s\n",
values[0].c_str(), values[1].c_str(), values[2].c_str(), values[3].c_str());
Serial.printf(" 📡 LED: %s, RSSI: %sdBm, Time: %sms\n",
values[4].c_str(), values[5].c_str(), values[6].c_str());
if (fieldIndex > 7) {
Serial.printf(" 🎯 Target: %s\n", values[7].c_str());
}
}
}
void parseJSONData(const String& jsonData) {
DynamicJsonDocument doc(512);
DeserializationError error = deserializeJson(doc, jsonData);
if (!error) {
Serial.printf(" 📋 Type: %s, Msg ID: %d, Device: %s\n",
doc["type"].as<String>().c_str(),
doc["messageId"].as<int>(),
doc["deviceId"].as<String>().c_str());
Serial.printf(" 🌐 Source IP: %s, Target: %s\n",
doc["sourceIP"].as<String>().c_str(),
doc["targetName"].as<String>().c_str());
Serial.printf(" 🌡️ Temp: %.1f°C, Humidity: %.1f%%, Light: %d\n",
doc["sensors"]["temperature"].as<float>(),
doc["sensors"]["humidity"].as<float>(),
doc["sensors"]["light"].as<int>());
Serial.printf(" 📡 LED: %s, RSSI: %ddBm, Heap: %d bytes\n",
doc["status"]["led"].as<bool>() ? "ON" : "OFF",
doc["status"]["wifi_rssi"].as<int>(),
doc["status"]["free_heap"].as<int>());
} else {
Serial.printf(" ❌ JSON Parse Error: %s\n", error.c_str());
}
}
void parseBinaryData(const uint8_t* data, size_t size) {
if (size >= 37) { // Minimum expected binary data size for sendTo format
const uint8_t* ptr = data + 4; // Skip "STO\0" header
uint32_t msgId = *(uint32_t*)ptr; ptr += 4;
uint32_t timestamp = *(uint32_t*)ptr; ptr += 4;
float temperature = *(float*)ptr; ptr += 4;
float humidity = *(float*)ptr; ptr += 4;
uint16_t light = *(uint16_t*)ptr; ptr += 2;
uint8_t led = *(uint8_t*)ptr; ptr += 1;
int8_t rssi = *(int8_t*)ptr; ptr += 1;
uint32_t heap = *(uint32_t*)ptr; ptr += 4;
uint8_t destIndex = *(uint8_t*)ptr; ptr += 1;
Serial.printf(" 💾 Msg ID: %u, Time: %ums, Temp: %.2f°C\n", msgId, timestamp, temperature);
Serial.printf(" 📊 Humidity: %.1f%%, Light: %u, LED: %s\n", humidity, light, led ? "ON" : "OFF");
Serial.printf(" 📡 RSSI: %ddBm, Heap: %u bytes, Dest Index: %u\n", rssi, heap, destIndex);
} else {
Serial.printf(" ❌ Binary data too small: %d bytes\n", size);
}
}
void parseSystemData(const String& data) {
// Parse system data format: SYSTEM|msgId|chip|freq|heap|flash|rssi|uptime|sdk|target
String values[10];
int fieldIndex = 0;
int startIndex = 7; // Skip "SYSTEM|"
for (int i = startIndex; i < data.length() && fieldIndex < 10; i++) {
if (data.charAt(i) == '|' || i == data.length() - 1) {
values[fieldIndex] = data.substring(startIndex, i == data.length() - 1 ? i + 1 : i);
startIndex = i + 1;
fieldIndex++;
}
}
if (fieldIndex >= 8) {
Serial.printf(" 🖥️ Chip: %s @ %s, Heap: %s, Flash: %s\n",
values[1].c_str(), values[2].c_str(), values[3].c_str(), values[4].c_str());
Serial.printf(" 📡 RSSI: %s, Uptime: %s, SDK: %s\n",
values[5].c_str(), values[6].c_str(), values[7].c_str());
if (fieldIndex > 8) {
Serial.printf(" 🎯 Target: %s\n", values[8].c_str());
}
}
}
void displayStatistics() {
Serial.println("======================================================================");
Serial.println(" SENDTO() MESSAGE RECEIVER STATISTICS ");
Serial.println("======================================================================");
Serial.printf("Total sendTo() Messages Received: %lu\n", totalMessagesReceived);
Serial.printf("Total Bytes Received: %lu\n", totalBytesReceived);
Serial.printf("Active Senders: %d\n", senderMap.size());
Serial.printf("Server Port: %d\n", serverPort);
Serial.printf("Server Uptime: %lu seconds\n", millis() / 1000);
Serial.printf("Free Heap: %d bytes\n", ESP.getFreeHeap());
Serial.printf("WiFi Signal: %d dBm\n", WiFi.RSSI());
Serial.printf("Response Buffer: %d bytes capacity\n", responseMessage.space() + responseMessage.length());
if (!senderMap.empty()) {
Serial.println("\nSender Details:");
Serial.println("IP Address | Messages | Bytes | Last Type | Status | Last Seen");
Serial.println("--------------|----------|--------|--------------|----------|----------");
unsigned long currentTime = millis();
for (auto& sender : senderMap) {
String status = (currentTime - sender.second.lastSeen < 30000) ? "Active" : "Inactive";
Serial.printf("%-13s | %-8lu | %-6lu | %-12s | %-8s | %lu\n",
sender.second.senderIP.c_str(),
sender.second.messageCount,
sender.second.byteCount,
sender.second.lastMessageType.c_str(),
status.c_str(),
sender.second.lastSeen / 1000);
}
}
Serial.println("======================================================================");
}For more ESP32 development resources and tutorials, visit the All About ESP32 Resources Hub on AvantMaker.com
ESP32 Library Index
- ESP32 WiFi Library
- ESP32 WiFiClient Library
- ESP32 HTTPClient Library
- ESP32 WiFiClientSecure Library
- ESP32 WebServer Library
- ESP32 AsyncUDP Librarry
- Connection Management
- Data Transimission
- Broadcast Multicast
- Network Information
- Which ESP32 Boards are Recommended for Learners
- How to Copy Codes from AvantMaker.com
- What is SPIFFS and how to upload files to it?
- What is LIttleFS and how to upload files to it?
Ready to experiment and explore more about ESP32? Visit our website’s All About ESP32 Resources Hub, packed with tutorials, guides, and tools to inspire your maker journey. Experiment, explore, and elevate your skills with everything you need to master this powerful microcontroller platform!