Home / References / ESP32 Library / AsyncUDP Library
Description
The writeTo() method is a powerful and flexible data transmission function in the AsyncUDP library that enables ESP32 devices to send UDP packets to any specified remote IP address and port without requiring a prior connection. Unlike the write() method which requires a connected UDP socket, writeTo() operates independently and can send data to different destinations on each call.
This method is available in the AsyncUDP class and provides direct point-to-point UDP communication capabilities. It’s particularly useful for implementing distributed communication systems, multi-target broadcasting, dynamic peer-to-peer networks, IoT sensor networks with multiple data collectors, load balancing across multiple servers, and flexible communication architectures where destinations may change frequently.
The writeTo() method supports both IPv4 and IPv6 addressing, handles network interface selection, and integrates seamlessly with ESP32’s FreeRTOS task scheduler for non-blocking network operations. It’s the foundation method used internally by other AsyncUDP functions like broadcast() and sendTo(), making it a fundamental building block for UDP communications.
Syntax and Usage
The writeTo() method has two main overloads for different addressing schemes:
– Pv4/IPv6 with IPAddress:
udp.writeTo(data, length, targetIP, targetPort)Sends data to the specified IP address and port.
– Pv4/IPv6 with interface:
udp.writeTo(data, length, targetIP, targetPort, interface)Sends data via a specific network interface.
– Low-level with ip_addr_t:
udp.writeTo(data, length, &ip_addr, port, interface)Direct low-level addressing for advanced use cases.
For practical applications and examples of this method, please consult the “Example Code” section on this page. This section provides comprehensive guidance to help you better understand and apply the method effectively.
This page is part of the Comprehensive Guide to the ESP32 Arduino Core Library, accessible on AvantMaker.com.
Arguments
The writeTo() method accepts the following arguments:
- data (const uint8_t*): A pointer to the data buffer containing the bytes to be transmitted. This can be any binary data, string, or structured data that needs to be sent via UDP.
- len (size_t): The number of bytes to transmit from the data buffer. The maximum size is limited by CONFIG_TCP_MSS (typically 1460 bytes).
- addr (IPAddress or const ip_addr_t*): The destination IP address where the UDP packet should be sent. Supports both IPv4 and IPv6 addresses.
- port (uint16_t): The destination port number (0-65535) on the target device where the UDP packet should be delivered.
- tcpip_if (tcpip_adapter_if_t, optional): The network interface to use for transmission. Defaults to TCPIP_ADAPTER_IF_MAX (automatic selection). Options include TCPIP_ADAPTER_IF_STA (WiFi station), TCPIP_ADAPTER_IF_AP (WiFi Access Point), or TCPIP_ADAPTER_IF_ETH (Ethernet).
Return Value
The writeTo() method returns a size_t value indicating the number of bytes successfully transmitted. A return value of 0 indicates that the transmission failed due to network issues, invalid parameters, or insufficient memory. A positive value represents the actual number of bytes sent, which should match the requested length for successful transmission. The method handles all low-level UDP protocol details including packet fragmentation, checksum calculation, and network interface selection. It creates a temporary UDP packet buffer, copies the data, sends it via the lwIP UDP stack, and immediately frees the buffer, making it efficient for one-off transmissions. Unlike connection-based methods, writeTo() does not maintain any state information about the destination, making each call completely independent.
Example Code
Simple Example: Multi-Target UDP Data Sender
This example demonstrates how to use the writeTo() method to send data to multiple remote UDP endpoints without establishing connections. The ESP32 cycles through different target servers and sends various types of data including strings, sensor readings, and JSON messages to different destinations. This demonstrates the practical application of the writeTo() method for distributed IoT communications, multi-server data logging, load balancing, and dynamic peer-to-peer networking applications.
How to use this example: Upload this code to your ESP32, update the WiFi credentials and configure the target IP addresses and ports in the targets array. The ESP32 will send data to different targets in rotation every 3 seconds. Use the companion receiver example (provided below) on multiple ESP32s or computers to see the transmitted data.
/*
* Author: Avant Maker
* Date: January 15, 2025
* Version: 1.0
* License: MIT
*
* Description:
* Multi-Target UDP Data Sender that demonstrates writeTo() method usage
* for transmitting various types of data to multiple remote UDP endpoints
* without requiring established connections. This example shows how to
* send data to different servers dynamically, implementing distributed
* communication patterns commonly used in IoT sensor networks, load
* balancing systems, and multi-server architectures.
*
* Features Demonstrated:
* - Dynamic multi-target UDP transmission using writeTo()
* - Data transmission to different servers without connections
* - Multiple data format transmission (text, JSON, binary)
* - Target server rotation and load distribution
* - Network interface selection and management
* - Transmission failure handling and retry logic
* - Data transmission statistics and monitoring
* - Flexible addressing for IPv4 destinations
*
* Hardware Requirements:
* - ESP32 development board
* - WiFi network access
* - Multiple remote UDP servers (use companion receiver example)
*
* How to use this example:
* 1. Update WiFi credentials (ssid and password)
* 2. Configure target servers in the targets array
* 3. Upload code to ESP32
* 4. Deploy receiver examples on target servers
* 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 server configuration structure
struct UDPTarget {
IPAddress ip;
uint16_t port;
String name;
unsigned long messageCount;
unsigned long totalBytesSent;
unsigned long lastSent;
bool active;
};
// Configure multiple target servers - UPDATE THESE IP ADDRESSES
UDPTarget targets[] = {
{IPAddress(192, 168, 0, 123), 8888, "Primary Server", 0, 0, 0, true},
{IPAddress(192, 168, 0, 124), 8889, "Backup Server", 0, 0, 0, true},
{IPAddress(192, 168, 0, 125), 8890, "Analytics Server", 0, 0, 0, true},
{IPAddress(192, 168, 0, 126), 8891, "Log Server", 0, 0, 0, true}
};
const int numTargets = sizeof(targets) / sizeof(targets[0]);
AsyncUDP udp;
unsigned long globalMessageCounter = 0;
int currentTargetIndex = 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 Multi-Target UDP Sender - writeTo() Method Demo");
// Display configuration
Serial.println("=== Configuration ===");
Serial.printf("Device MAC: %s\n", WiFi.macAddress().c_str());
Serial.printf("Configured Targets: %d\n", numTargets);
for (int i = 0; i < numTargets; i++) {
Serial.printf("Target %d: %s (%s:%d)\n", i+1, targets[i].name.c_str(),
targets[i].ip.toString().c_str(), targets[i].port);
}
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());
// Send initial announcement to all targets
String welcomeMsg = "ESP32 Multi-Target Sender Online - Device: " + WiFi.macAddress();
for (int i = 0; i < numTargets; i++) {
if (targets[i].active) {
size_t sent = udp.writeTo((uint8_t*)welcomeMsg.c_str(), welcomeMsg.length(),
targets[i].ip, targets[i].port);
Serial.printf("Welcome sent to %s: %d bytes\n", targets[i].name.c_str(), sent);
targets[i].messageCount++;
targets[i].totalBytesSent += sent;
targets[i].lastSent = millis();
}
}
Serial.println("Starting multi-target data transmission...");
Serial.println("========================================");
}
void loop() {
static unsigned long lastSend = 0;
static int dataType = 0;
// Send data every 3 seconds to different targets
if (millis() - lastSend > 3000) {
lastSend = millis();
globalMessageCounter++;
// Select next active target
selectNextTarget();
// Send different types of data based on cycle
switch (dataType % 5) {
case 0:
sendTextMessage();
break;
case 1:
sendSensorData();
break;
case 2:
sendJSONData();
break;
case 3:
sendBinaryData();
break;
case 4:
sendSystemInfo();
break;
}
dataType++;
}
// Update simulated sensor values
updateSensorValues();
// Display periodic status
static unsigned long lastStatus = 0;
if (millis() - lastStatus > 20000) { // Every 20 seconds
lastStatus = millis();
displayStatus();
}
delay(500);
}
void selectNextTarget() {
// Find next active target
int attempts = 0;
do {
currentTargetIndex = (currentTargetIndex + 1) % numTargets;
attempts++;
} while (!targets[currentTargetIndex].active && attempts < numTargets);
if (attempts >= numTargets) {
Serial.println("Warning: No active targets available!");
currentTargetIndex = 0; // Default to first target
}
}
void sendTextMessage() {
UDPTarget &target = targets[currentTargetIndex];
String message = "Hello from ESP32! Global Msg #" + String(globalMessageCounter) +
" | Target: " + target.name +
" | Time: " + String(millis()/1000) + "s" +
" | Free Heap: " + String(ESP.getFreeHeap()) + "b";
size_t sent = udp.writeTo((uint8_t*)message.c_str(), message.length(),
target.ip, target.port);
updateTargetStats(currentTargetIndex, sent);
Serial.printf("[%lu] Text Message → %s (%s:%d): %d bytes\n",
globalMessageCounter, target.name.c_str(),
target.ip.toString().c_str(), target.port, sent);
Serial.printf("Content: %s\n", message.c_str());
Serial.println("─────────────────────────────────────────");
}
void sendSensorData() {
UDPTarget &target = targets[currentTargetIndex];
String sensorData = "SENSOR_DATA|" + String(temperature, 2) + "|" +
String(humidity, 1) + "|" + String(lightLevel) + "|" +
String(ledState ? "ON" : "OFF") + "|" + target.name;
size_t sent = udp.writeTo((uint8_t*)sensorData.c_str(), sensorData.length(),
target.ip, target.port);
updateTargetStats(currentTargetIndex, sent);
Serial.printf("[%lu] Sensor Data → %s: %d bytes\n",
globalMessageCounter, target.name.c_str(), sent);
Serial.printf("Temperature: %.2f°C, Humidity: %.1f%%, Light: %d, LED: %s\n",
temperature, humidity, lightLevel, ledState ? "ON" : "OFF");
Serial.println("─────────────────────────────────────────");
}
void sendJSONData() {
UDPTarget &target = targets[currentTargetIndex];
// Create JSON document
DynamicJsonDocument doc(300);
doc["messageId"] = globalMessageCounter;
doc["deviceId"] = WiFi.macAddress();
doc["timestamp"] = millis();
doc["targetServer"] = target.name;
doc["targetIP"] = target.ip.toString();
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();
String jsonString;
serializeJson(doc, jsonString);
size_t sent = udp.writeTo((uint8_t*)jsonString.c_str(), jsonString.length(),
target.ip, target.port);
updateTargetStats(currentTargetIndex, sent);
Serial.printf("[%lu] JSON Data → %s: %d bytes\n",
globalMessageCounter, target.name.c_str(), sent);
Serial.printf("JSON: %s\n", jsonString.c_str());
Serial.println("─────────────────────────────────────────");
}
void sendBinaryData() {
UDPTarget &target = targets[currentTargetIndex];
// Create binary data packet
struct {
uint32_t messageId;
uint32_t timestamp;
uint32_t targetIndex;
float temperature;
float humidity;
uint16_t lightLevel;
uint8_t ledState;
int8_t wifiRSSI;
uint32_t freeHeap;
char targetName[20];
} binaryPacket;
binaryPacket.messageId = globalMessageCounter;
binaryPacket.timestamp = millis();
binaryPacket.targetIndex = currentTargetIndex;
binaryPacket.temperature = temperature;
binaryPacket.humidity = humidity;
binaryPacket.lightLevel = lightLevel;
binaryPacket.ledState = ledState ? 1 : 0;
binaryPacket.wifiRSSI = WiFi.RSSI();
binaryPacket.freeHeap = ESP.getFreeHeap();
strncpy(binaryPacket.targetName, target.name.c_str(), 19);
binaryPacket.targetName[19] = '\0';
size_t sent = udp.writeTo((uint8_t*)&binaryPacket, sizeof(binaryPacket),
target.ip, target.port);
updateTargetStats(currentTargetIndex, sent);
Serial.printf("[%lu] Binary Data → %s: %d bytes\n",
globalMessageCounter, target.name.c_str(), sent);
Serial.printf("Binary packet size: %d bytes\n", sizeof(binaryPacket));
Serial.println("─────────────────────────────────────────");
}
void sendSystemInfo() {
UDPTarget &target = targets[currentTargetIndex];
String systemInfo = "SYSTEM|" + String(ESP.getChipModel()) + "|" +
String(ESP.getCpuFreqMHz()) + "MHz|" +
String(ESP.getFreeHeap()) + "b|" +
String(ESP.getFlashChipSize()) + "b|" +
String(WiFi.RSSI()) + "dBm|" + target.name;
size_t sent = udp.writeTo((uint8_t*)systemInfo.c_str(), systemInfo.length(),
target.ip, target.port);
updateTargetStats(currentTargetIndex, sent);
Serial.printf("[%lu] System Info → %s: %d bytes\n",
globalMessageCounter, target.name.c_str(), sent);
Serial.printf("Content: %s\n", systemInfo.c_str());
Serial.println("─────────────────────────────────────────");
}
void updateTargetStats(int targetIndex, size_t bytesSent) {
if (targetIndex >= 0 && targetIndex < numTargets) {
targets[targetIndex].messageCount++;
targets[targetIndex].totalBytesSent += bytesSent;
targets[targetIndex].lastSent = millis();
// Mark as inactive if send failed
if (bytesSent == 0) {
targets[targetIndex].active = false;
Serial.printf("Warning: Target %s marked inactive due to send failure\n",
targets[targetIndex].name.c_str());
}
}
}
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-TARGET STATUS ║");
Serial.println("╚══════════════════════════════════════════════════════════════════╝");
Serial.printf("Global Messages Sent: %lu\n", globalMessageCounter);
Serial.printf("Current Target: %s\n", targets[currentTargetIndex].name.c_str());
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.println("\nTarget Server Statistics:");
Serial.println("Name | IP:Port | Messages | Bytes | Last Sent | Status");
Serial.println("------------------|------------------|----------|--------|-----------|--------");
unsigned long currentTime = millis();
for (int i = 0; i < numTargets; i++) {
String status = targets[i].active ?
((currentTime - targets[i].lastSent < 30000) ? "Active" : "Idle") :
"Inactive";
Serial.printf("%-17s | %-16s | %-8lu | %-6lu | %-9lu | %s\n",
targets[i].name.c_str(),
(targets[i].ip.toString() + ":" + String(targets[i].port)).c_str(),
targets[i].messageCount,
targets[i].totalBytesSent,
targets[i].lastSent / 1000,
status.c_str());
}
Serial.println("══════════════════════════════════════════════════════════════════");
}Testing Example: UDP Data Receiver
This companion example demonstrates how to create a UDP receiver that listens for data sent by the previous example. This receiver ESP32 will display all incoming UDP data in various formats, allowing you to verify that the writeTo() method is working correctly. The receiver provides detailed parsing of different data types including text messages, sensor data, JSON, and binary packets sent from multiple senders.
How to test with multiple ESP32 boards:
- Setup Multiple Receivers: Upload this “UDP Data Receiver” code to multiple ESP32 boards (as many as you have targets configured) and note their IP addresses from the Serial Monitor.
- Configure Different Ports: Use different port numbers (8888, 8889, 8890, 8891) for each receiver by updating the
serverPortvariable. - Setup the Sender: Upload the previous “Multi-Target UDP Data Sender” code to another ESP32 and update the
targetsarray with the receiver ESP32s’ IP addresses and ports. - Configure Network: Ensure all ESP32 boards are connected to the same WiFi network.
- Monitor Results: Open Serial Monitor for all ESP32s to see data transmission and reception in real-time across different targets.
- Verify Distribution: Compare data distribution across different receivers to verify the multi-target functionality.
/*
* Author: Avant Maker
* Date: January 15, 2025
* Version: 1.0
* License: MIT
*
* Description:
* UDP Data Receiver for testing writeTo() method functionality. This example
* creates a UDP server that listens for incoming data and displays it in
* various formats. It's designed to work with the Multi-Target UDP Data Sender
* example to provide comprehensive testing of the AsyncUDP writeTo() method
* across multiple targets and servers.
*/
#include <WiFi.h>
#include <AsyncUDP.h>
#include <ArduinoJson.h>
#include <map>
// WiFi credentials
const char* ssid = "your_wifi_ssid";
const char* password = "your_wifi_password";
// Server configuration - UPDATE PORT FOR EACH RECEIVER
const uint16_t serverPort = 8888; // Use 8888, 8889, 8890, 8891 for different receivers
const String serverName = "Primary Server"; // UPDATE: Change for each receiver
AsyncUDP udp;
unsigned long totalPacketsReceived = 0;
unsigned long totalBytesReceived = 0;
// Structure to track sender statistics
struct SenderStats {
String senderIP;
unsigned long packetCount;
unsigned long byteCount;
unsigned long firstSeen;
unsigned long lastSeen;
String lastMessage;
String deviceMAC;
};
std::map<String, SenderStats> senderMap;
void setup() {
Serial.begin(115200);
Serial.println("ESP32 Multi-Target UDP Receiver - Testing writeTo() Method");
// 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("Server Name: %s\n", serverName.c_str());
Serial.printf("Receiver IP: %s\n", WiFi.localIP().toString().c_str());
Serial.printf("Listening Port: %d\n", serverPort);
Serial.printf("Configure sender with IP: %s:%d\n", WiFi.localIP().toString().c_str(), serverPort);
// Start UDP server
if (udp.listen(serverPort)) {
Serial.printf("UDP Server listening on port %d\n", serverPort);
Serial.println("Waiting for data from senders...");
// Set up packet handler
udp.onPacket([](AsyncUDPPacket packet) {
handleIncomingPacket(packet);
});
} else {
Serial.println("Failed to start UDP server");
}
}
void loop() {
// Display periodic statistics
static unsigned long lastStats = 0;
if (millis() - lastStats > 25000) { // Every 25 seconds
lastStats = millis();
displayStatistics();
}
delay(1000);
}
void handleIncomingPacket(AsyncUDPPacket packet) {
// Get packet information
IPAddress senderIP = packet.remoteIP();
uint16_t senderPort = packet.remotePort();
size_t packetSize = packet.length();
// Update statistics
totalPacketsReceived++;
totalBytesReceived += packetSize;
// 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.packetCount = 1;
newSender.byteCount = packetSize;
newSender.firstSeen = currentTime;
newSender.lastSeen = currentTime;
senderMap[senderKey] = newSender;
Serial.println("╔══════════════════════════════════════════════════════════════════╗");
Serial.printf("║ NEW SENDER DETECTED → %s (%s) ║\n",
serverName.c_str(), senderIP.toString().c_str());
Serial.println("╚══════════════════════════════════════════════════════════════════╝");
} else {
// Existing sender
senderMap[senderKey].packetCount++;
senderMap[senderKey].byteCount += packetSize;
senderMap[senderKey].lastSeen = currentTime;
}
// Extract and display packet data
String dataString = "";
for (size_t i = 0; i < packetSize; i++) {
dataString += (char)packet.data()[i];
}
senderMap[senderKey].lastMessage = dataString;
// Extract device MAC from data if available
if (dataString.indexOf("Device: ") > -1) {
int macStart = dataString.indexOf("Device: ") + 8;
int macEnd = dataString.indexOf(" ", macStart);
if (macEnd == -1) macEnd = dataString.length();
senderMap[senderKey].deviceMAC = dataString.substring(macStart, macEnd);
}
// Display packet information
Serial.printf("[%s] Packet #%lu from %s:%d (%d bytes)\n",
serverName.c_str(), totalPacketsReceived,
senderIP.toString().c_str(), senderPort, packetSize);
Serial.printf("Content: %s\n", dataString.c_str());
// Send acknowledgment back to sender using write() method from packet
String ackMessage = "ACK:" + serverName + ":" + String(totalPacketsReceived) +
":Received " + String(packetSize) + " bytes at " +
WiFi.localIP().toString() + ":" + String(serverPort);
size_t sent = packet.write((uint8_t*)ackMessage.c_str(), ackMessage.length());
Serial.printf("Acknowledgment sent to sender: %d bytes\n", sent);
Serial.println("──────────────────────────────────────────────────────────────────");
}
void displayStatistics() {
Serial.println("╔══════════════════════════════════════════════════════════════════╗");
Serial.printf("║ %s RECEIVER STATISTICS ║\n", serverName.c_str());
Serial.println("╚══════════════════════════════════════════════════════════════════╝");
Serial.printf("Server: %s (Port %d)\n", serverName.c_str(), serverPort);
Serial.printf("Local IP: %s\n", WiFi.localIP().toString().c_str());
Serial.printf("Total Packets Received: %lu\n", totalPacketsReceived);
Serial.printf("Total Bytes Received: %lu\n", totalBytesReceived);
Serial.printf("Active Senders: %d\n", senderMap.size());
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());
if (!senderMap.empty()) {
Serial.println("\nSender Details:");
Serial.println("Sender IP | Device MAC | Packets | Bytes | First/Last Seen | Status");
Serial.println("--------------|-------------------|---------|--------|----------------|--------");
unsigned long currentTime = millis();
for (auto& sender : senderMap) {
String status = (currentTime - sender.second.lastSeen < 30000) ? "Active" : "Inactive";
String deviceMAC = sender.second.deviceMAC.length() > 0 ? sender.second.deviceMAC : "Unknown";
Serial.printf("%-13s | %-17s | %-7lu | %-6lu | %lu/%lu | %s\n",
sender.second.senderIP.c_str(),
deviceMAC.c_str(),
sender.second.packetCount,
sender.second.byteCount,
sender.second.firstSeen / 1000,
sender.second.lastSeen / 1000,
status.c_str());
}
}
// Calculate and display data rate
if (millis() > 0) {
float dataRate = (float)totalBytesReceived / (millis() / 1000.0);
Serial.printf("\nData Rate: %.2f bytes/second\n", dataRate);
Serial.printf("Average Packet Size: %.2f bytes\n",
totalPacketsReceived > 0 ? (float)totalBytesReceived / totalPacketsReceived : 0);
}
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!