ESP32 AsyncUDP Library – isBroadcast()

Home / References / ESP32 Library / AsyncUDP Library

Description

The isBroadcast() method is used to determine whether a received UDP packet was sent as a broadcast message. This method examines the local IP address of the received packet and checks if it matches broadcast address patterns. A broadcast packet is sent to all devices on the network segment and is typically used for device discovery, network announcements, service advertisements, and group communications.

The method returns true if the packet was sent to a broadcast address such as the limited broadcast address (255.255.255.255), the network broadcast address, or a directed broadcast address. This functionality is essential for implementing protocols like DHCP, ARP, network discovery services, and any application that needs to distinguish between unicast, broadcast, and multicast communications. The method works by analyzing the destination IP address that was used when the packet was received, supporting both IPv4 broadcast detection and handling IPv6 scenarios where broadcast is not applicable.

Syntax and Usage

The isBroadcast() method is called on an AsyncUDPPacket object:

bool isBroadcastPacket = packet.isBroadcast()

Returns true if the received packet was sent as a broadcast.

Arguments

The isBroadcast() method takes no arguments. It operates on the packet data that was already received and stored in the AsyncUDPPacket object.

This page is part of the Comprehensive Guide to the ESP32 Arduino Core Library, accessible on AvantMaker.com.

Return Value

The isBroadcast() method returns a bool value indicating whether the received packet was sent as a broadcast message. It returns true if the packet’s destination address matches any broadcast address pattern: the limited broadcast address (255.255.255.255), a network-specific broadcast address, or a directed broadcast address. It returns false for unicast packets (sent to a specific device), multicast packets (sent to a multicast group), or when working with IPv6 addresses (since IPv6 does not use broadcast addressing). The method helps applications distinguish between different types of network communications and can be used to implement broadcast-specific handling logic, filtering, or routing decisions. This is particularly useful in network discovery protocols, device announcement systems, and distributed applications that need to respond differently to broadcast versus directed communications.

Example Code

Broadcast Network Discovery System with Device Announcement and Response

This example demonstrates how to use the isBroadcast() method to create a comprehensive network discovery system where devices can announce themselves via broadcast messages and respond to broadcast discovery requests. The system distinguishes between broadcast and unicast communications, maintains a registry of discovered devices, and provides automatic network topology mapping.

Multi-Device Testing Setup Instructions

Required Hardware: 2-4 ESP32 development boards on the same WiFi network

Step-by-Step Testing Guide:

  1. Upload Discovery Server Code: Upload the code below to your first ESP32 (this will be the discovery server)
  2. Upload Client Nodes Code: Upload the client code (provided after the main example) to 2-3 additional ESP32 boards
  3. Monitor Serial Outputs: Open Serial Monitor for all devices at 115200 baud
  4. Verify Network Connection: Ensure all devices connect to the same WiFi network
  5. Watch Broadcast Discovery: Observe how devices send broadcast discovery requests and receive responses
  6. Test Device Registry: See how the discovery server maintains a list of all discovered devices
  7. Verify Broadcast Detection: Notice how devices differentiate between broadcast and unicast messages

What You’ll See:

  • Automatic broadcast-based device discovery across the network
  • Distinction between broadcast and unicast packet handling
  • Real-time device registry updates and network topology mapping
  • Broadcast announcement systems with response mechanisms
  • Network monitoring and device status tracking

Testing Scenarios:

  • Discovery Process: Watch devices automatically find each other using broadcast messages
  • Device Announcements: See how new devices announce their presence when joining
  • Broadcast vs Unicast: Observe different handling for broadcast discovery vs direct communication
  • Network Resilience: Test device rejoining after disconnection
/*
 * Author: Avant Maker
 * Date: June 18, 2025
 * Version: 1.0
 * License: MIT 
 * 
 * Description: 
 * This example demonstrates how to use the isBroadcast() method to create a
 * comprehensive network discovery system where devices can announce themselves
 * via broadcast messages and respond to broadcast discovery requests. The system
 * distinguishes between broadcast and unicast communications, maintains a registry
 * of discovered devices, and provides automatic network topology mapping.
 *
 * How to use this example:
 * Upload this code to your ESP32 and replace the WiFi credentials. The system
 * will listen for both broadcast and unicast UDP messages, automatically respond
 * to broadcast discovery requests, maintain a device registry, and provide
 * network monitoring capabilities. Use the isBroadcast() method to differentiate
 * between broadcast discovery messages and direct device communications.
 *
 * 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, 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

// Network discovery configuration
const uint16_t DISCOVERY_PORT = 8888;
const uint16_t RESPONSE_PORT = 8889;
const unsigned long ANNOUNCE_INTERVAL = 30000;  // Announce every 30 seconds
const unsigned long DISCOVERY_REQUEST_INTERVAL = 45000;  // Send discovery requests every 45 seconds
const unsigned long DEVICE_TIMEOUT = 120000;  // Remove devices after 2 minutes of inactivity

// Device information structure
struct DeviceInfo {
  String deviceId;
  String deviceName;
  String deviceType;
  IPAddress ipAddress;
  uint16_t port;
  unsigned long lastSeen;
  unsigned long firstSeen;
  String capabilities;
  float batteryLevel;
  int signalStrength;
  String status;
  bool isOnline;
};

// System configuration
struct DiscoveryConfig {
  String myDeviceId;
  String myDeviceName;
  String myDeviceType;
  String myCapabilities;
  float myBatteryLevel;
  AsyncUDP discoveryUDP;
  AsyncUDP responseUDP;
  std::vector<DeviceInfo> deviceRegistry;
  unsigned long lastAnnouncement;
  unsigned long lastDiscoveryRequest;
  unsigned long systemStartTime;
  unsigned long totalBroadcastsReceived;
  unsigned long totalUnicastsReceived;
  unsigned long totalBroadcastsSent;
  unsigned long totalUnicastsSent;
} discovery;

void setup() {
  Serial.begin(115200);
  Serial.println("Starting ESP32 Broadcast Discovery Server...");
  
  // Initialize device configuration
  discovery.myDeviceId = "ESP32_DISC_" + String((uint32_t)ESP.getEfuseMac(), HEX);
  discovery.myDeviceName = "ESP32 Discovery Server";
  discovery.myDeviceType = "DISCOVERY_SERVER";
  discovery.myCapabilities = "broadcast_discovery,device_registry,network_monitoring";
  discovery.myBatteryLevel = 85.5;  // Simulated battery level
  discovery.systemStartTime = millis();
  
  Serial.print("Device ID: ");
  Serial.println(discovery.myDeviceId);
  Serial.print("Device Name: ");
  Serial.println(discovery.myDeviceName);
  
  // Initialize WiFi
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  
  Serial.print("Connecting to WiFi");
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.print(".");
  }
  Serial.println();
  Serial.println("WiFi connected successfully!");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
  Serial.print("Signal strength: ");
  Serial.print(WiFi.RSSI());
  Serial.println(" dBm");
  
  // Initialize UDP listeners
  setupDiscoveryListeners();
  
  // Send initial device announcement
  delay(2000);
  sendDeviceAnnouncement();
  
  Serial.println("🔍 Discovery Server is ready and listening...");
}

void setupDiscoveryListeners() {
  Serial.println("=== Setting Up Discovery Listeners ===");
  
  // Setup discovery request listener (listens for broadcast discovery requests)
  if (discovery.discoveryUDP.listen(DISCOVERY_PORT)) {
    Serial.print("✅ Discovery listener started on port ");
    Serial.println(DISCOVERY_PORT);
    
    discovery.discoveryUDP.onPacket([](AsyncUDPPacket packet) {
      handleDiscoveryPacket(packet);
    });
  } else {
    Serial.print("❌ Failed to start discovery listener on port ");
    Serial.println(DISCOVERY_PORT);
  }
  
  // Setup response listener (listens for device responses and direct messages)
  if (discovery.responseUDP.listen(RESPONSE_PORT)) {
    Serial.print("✅ Response listener started on port ");
    Serial.println(RESPONSE_PORT);
    
    discovery.responseUDP.onPacket([](AsyncUDPPacket packet) {
      handleResponsePacket(packet);
    });
  } else {
    Serial.print("❌ Failed to start response listener on port ");
    Serial.println(RESPONSE_PORT);
  }
}

void handleDiscoveryPacket(AsyncUDPPacket packet) {
  // Extract message content
  String message = "";
  for (size_t i = 0; i < packet.length(); i++) {
    message += (char)packet.data()[i];
  }
  message.trim();
  
  // Use isBroadcast() to determine if this is a broadcast discovery request
  bool isBroadcastPacket = packet.isBroadcast();
  
  Serial.println("📡 === Discovery Packet Received ===");
  Serial.print("From: ");
  Serial.print(packet.remoteIP());
  Serial.print(":");
  Serial.println(packet.remotePort());
  Serial.print("Message: ");
  Serial.println(message);
  Serial.print("Packet Type: ");
  Serial.println(isBroadcastPacket ? "BROADCAST" : "UNICAST");
  Serial.print("Is Multicast: ");
  Serial.println(packet.isMulticast() ? "YES" : "NO");
  
  // Update statistics
  if (isBroadcastPacket) {
    discovery.totalBroadcastsReceived++;
    Serial.println("📊 Broadcast packet counter incremented");
  } else {
    discovery.totalUnicastsReceived++;
    Serial.println("📊 Unicast packet counter incremented");
  }
  
  // Process different types of discovery messages
  if (message.startsWith("DISCOVER_DEVICES")) {
    if (isBroadcastPacket) {
      Serial.println("🔍 Processing broadcast device discovery request");
      respondToDiscoveryRequest(packet);
    } else {
      Serial.println("🔍 Processing direct device discovery request");
      respondToDiscoveryRequest(packet);
    }
  } 
  else if (message.startsWith("DEVICE_ANNOUNCE")) {
    Serial.println("📢 Processing device announcement");
    processDeviceAnnouncement(message, packet);
  }
  else if (message.startsWith("PING")) {
    Serial.println("🏓 Processing ping request");
    respondToPing(packet);
  }
  else if (message.startsWith("GET_REGISTRY")) {
    Serial.println("📋 Processing registry request");
    sendDeviceRegistry(packet);
  }
  else {
    Serial.println("❓ Unknown discovery message type");
  }
  
  Serial.println("=== End Discovery Packet Processing ===");
}

void handleResponsePacket(AsyncUDPPacket packet) {
  // Extract message content
  String message = "";
  for (size_t i = 0; i < packet.length(); i++) {
    message += (char)packet.data()[i];
  }
  message.trim();
  
  // Use isBroadcast() to check packet type
  bool isBroadcastPacket = packet.isBroadcast();
  
  Serial.println("📨 === Response Packet Received ===");
  Serial.print("From: ");
  Serial.print(packet.remoteIP());
  Serial.print(":");
  Serial.println(packet.remotePort());
  Serial.print("Message Length: ");
  Serial.println(packet.length());
  Serial.print("Packet Type: ");
  Serial.println(isBroadcastPacket ? "BROADCAST" : "UNICAST");
  
  // Update statistics
  if (isBroadcastPacket) {
    discovery.totalBroadcastsReceived++;
  } else {
    discovery.totalUnicastsReceived++;
  }
  
  // Process device information responses
  if (message.startsWith("DEVICE_INFO")) {
    Serial.println("📱 Processing device information response");
    parseAndRegisterDevice(message, packet);
  }
  else if (message.startsWith("PONG")) {
    Serial.println("🏓 Processing pong response");
    updateDeviceStatus(packet.remoteIP(), "ONLINE");
  }
  else if (message.startsWith("STATUS_UPDATE")) {
    Serial.println("📊 Processing status update");
    updateDeviceStatus(packet.remoteIP(), "STATUS_RECEIVED");
  }
  
  Serial.println("=== End Response Packet Processing ===");
}

String createDeviceInfoJSON() {
  String json = "{";
  json += "\"id\":\"" + discovery.myDeviceId + "\",";
  json += "\"name\":\"" + discovery.myDeviceName + "\",";
  json += "\"type\":\"" + discovery.myDeviceType + "\",";
  json += "\"ip\":\"" + WiFi.localIP().toString() + "\",";
  json += "\"port\":" + String(RESPONSE_PORT) + ",";
  json += "\"capabilities\":\"" + discovery.myCapabilities + "\",";
  json += "\"battery\":" + String(discovery.myBatteryLevel, 1) + ",";
  json += "\"signal\":" + String(WiFi.RSSI()) + ",";
  json += "\"uptime\":" + String((millis() - discovery.systemStartTime) / 1000) + ",";
  json += "\"status\":\"ONLINE\"";
  json += "}";
  return json;
}

void respondToDiscoveryRequest(AsyncUDPPacket& packet) {
  Serial.println("📤 === Sending Discovery Response ===");
  
  // Create device information JSON
  String deviceInfo = createDeviceInfoJSON();
  String response = "DEVICE_INFO:" + deviceInfo;
  
  // Send response back to the requesting device (unicast response to broadcast request)
  size_t sentBytes = packet.printf("%s", response.c_str());
  
  if (sentBytes > 0) {
    discovery.totalUnicastsSent++;
    Serial.print("✅ Discovery response sent (");
    Serial.print(sentBytes);
    Serial.println(" bytes)");
    Serial.print("Response sent to: ");
    Serial.print(packet.remoteIP());
    Serial.print(":");
    Serial.println(packet.remotePort());
  } else {
    Serial.println("❌ Failed to send discovery response");
  }
}

void sendDeviceAnnouncement() {
  Serial.println("📢 === Sending Device Announcement ===");
  
  String announcement = "DEVICE_ANNOUNCE:" + createDeviceInfoJSON();
  
  // Send broadcast announcement
  size_t sentBytes = discovery.discoveryUDP.broadcast(announcement.c_str());
  
  if (sentBytes > 0) {
    discovery.totalBroadcastsSent++;
    discovery.lastAnnouncement = millis();
    Serial.print("✅ Device announcement broadcasted (");
    Serial.print(sentBytes);
    Serial.println(" bytes)");
  } else {
    Serial.println("❌ Failed to send device announcement");
  }
}

void parseAndRegisterDevice(const String& message, AsyncUDPPacket& packet) {
  Serial.println("📝 === Registering New Device ===");
  
  // Extract JSON part after "DEVICE_INFO:"
  int colonIndex = message.indexOf(':');
  if (colonIndex == -1) {
    Serial.println("❌ Invalid device info format");
    return;
  }
  
  String jsonData = message.substring(colonIndex + 1);
  Serial.print("JSON Data: ");
  Serial.println(jsonData);
  
  // Parse device information (simplified parsing)
  DeviceInfo newDevice;
  newDevice.ipAddress = packet.remoteIP();
  newDevice.lastSeen = millis();
  newDevice.firstSeen = millis();
  newDevice.isOnline = true;
  newDevice.status = "ONLINE";
  
  // Extract device ID (simplified extraction)
  int idStart = jsonData.indexOf("\"id\":\"") + 6;
  int idEnd = jsonData.indexOf("\"", idStart);
  if (idStart > 5 && idEnd > idStart) {
    newDevice.deviceId = jsonData.substring(idStart, idEnd);
  }
  
  // Extract device name
  int nameStart = jsonData.indexOf("\"name\":\"") + 8;
  int nameEnd = jsonData.indexOf("\"", nameStart);
  if (nameStart > 7 && nameEnd > nameStart) {
    newDevice.deviceName = jsonData.substring(nameStart, nameEnd);
  }
  
  // Extract device type
  int typeStart = jsonData.indexOf("\"type\":\"") + 8;
  int typeEnd = jsonData.indexOf("\"", typeStart);
  if (typeStart > 7 && typeEnd > typeStart) {
    newDevice.deviceType = jsonData.substring(typeStart, typeEnd);
  }
  
  // Check if device already exists in registry
  bool deviceExists = false;
  for (size_t i = 0; i < discovery.deviceRegistry.size(); i++) {
    if (discovery.deviceRegistry[i].deviceId == newDevice.deviceId || 
        discovery.deviceRegistry[i].ipAddress == newDevice.ipAddress) {
      // Update existing device
      discovery.deviceRegistry[i].lastSeen = millis();
      discovery.deviceRegistry[i].isOnline = true;
      discovery.deviceRegistry[i].status = "ONLINE";
      deviceExists = true;
      Serial.print("🔄 Updated existing device: ");
      Serial.println(newDevice.deviceId);
      break;
    }
  }
  
  // Add new device if not exists
  if (!deviceExists) {
    discovery.deviceRegistry.push_back(newDevice);
    Serial.print("➕ Added new device to registry: ");
    Serial.print(newDevice.deviceId);
    Serial.print(" (");
    Serial.print(newDevice.deviceName);
    Serial.print(") at ");
    Serial.println(newDevice.ipAddress);
  }
  
  Serial.print("📊 Total devices in registry: ");
  Serial.println(discovery.deviceRegistry.size());
}

void processDeviceAnnouncement(const String& message, AsyncUDPPacket& packet) {
  parseAndRegisterDevice(message, packet);
}

void respondToPing(AsyncUDPPacket& packet) {
  String response = "PONG:" + discovery.myDeviceId + ":" + String(millis());
  size_t sentBytes = packet.printf("%s", response.c_str());
  
  if (sentBytes > 0) {
    discovery.totalUnicastsSent++;
    Serial.println("🏓 Pong response sent");
  }
}

void sendDeviceRegistry(AsyncUDPPacket& packet) {
  String registryData = "REGISTRY_DATA:" + createRegistryInfoJSON();
  size_t sentBytes = packet.printf("%s", registryData.c_str());
  
  if (sentBytes > 0) {
    discovery.totalUnicastsSent++;
    Serial.println("📋 Device registry sent");
  }
}

String createRegistryInfoJSON() {
  String json = "{\"devices\":[";
  for (size_t i = 0; i < discovery.deviceRegistry.size(); i++) {
    if (i > 0) json += ",";
    DeviceInfo& device = discovery.deviceRegistry[i];
    json += "{";
    json += "\"id\":\"" + device.deviceId + "\",";
    json += "\"name\":\"" + device.deviceName + "\",";
    json += "\"ip\":\"" + device.ipAddress.toString() + "\",";
    json += "\"status\":\"" + device.status + "\",";
    json += "\"lastSeen\":" + String((millis() - device.lastSeen) / 1000);
    json += "}";
  }
  json += "],\"count\":" + String(discovery.deviceRegistry.size()) + "}";
  return json;
}

void updateDeviceStatus(IPAddress ip, const String& status) {
  for (size_t i = 0; i < discovery.deviceRegistry.size(); i++) {
    if (discovery.deviceRegistry[i].ipAddress == ip) {
      discovery.deviceRegistry[i].lastSeen = millis();
      discovery.deviceRegistry[i].status = status;
      discovery.deviceRegistry[i].isOnline = true;
      break;
    }
  }
}

void loop() {
  unsigned long currentTime = millis();
  
  // Send periodic device announcements
  if (currentTime - discovery.lastAnnouncement >= ANNOUNCE_INTERVAL) {
    sendDeviceAnnouncement();
  }
  
  // Send periodic discovery requests
  static unsigned long lastDiscoveryRequest = 0;
  if (currentTime - lastDiscoveryRequest >= DISCOVERY_REQUEST_INTERVAL) {
    lastDiscoveryRequest = currentTime;
    String request = "DISCOVER_DEVICES:REQUEST_FROM:" + discovery.myDeviceId;
    size_t sentBytes = discovery.discoveryUDP.broadcast(request.c_str());
    if (sentBytes > 0) {
      discovery.totalBroadcastsSent++;
      Serial.println("🔍 Discovery request broadcasted");
    }
  }
  
  // Clean up inactive devices every 30 seconds
  static unsigned long lastCleanup = 0;
  if (currentTime - lastCleanup >= 30000) {
    lastCleanup = currentTime;
    for (int i = discovery.deviceRegistry.size() - 1; i >= 0; i--) {
      if (currentTime - discovery.deviceRegistry[i].lastSeen > DEVICE_TIMEOUT) {
        Serial.print("🗑️  Removing inactive device: ");
        Serial.println(discovery.deviceRegistry[i].deviceId);
        discovery.deviceRegistry.erase(discovery.deviceRegistry.begin() + i);
      }
    }
  }
  
  // Print system status every 60 seconds
  static unsigned long lastStatusPrint = 0;
  if (currentTime - lastStatusPrint >= 60000) {
    lastStatusPrint = currentTime;
    Serial.println("📊 === BROADCAST DISCOVERY SYSTEM STATUS ===");
    Serial.print("Device: ");
    Serial.println(discovery.myDeviceName);
    Serial.print("Broadcasts Received: ");
    Serial.println(discovery.totalBroadcastsReceived);
    Serial.print("Unicasts Received: ");
    Serial.println(discovery.totalUnicastsReceived);
    Serial.print("Broadcasts Sent: ");
    Serial.println(discovery.totalBroadcastsSent);
    Serial.print("Unicasts Sent: ");
    Serial.println(discovery.totalUnicastsSent);
    Serial.print("Registered Devices: ");
    Serial.println(discovery.deviceRegistry.size());
    Serial.println("============================================");
  }
  
  // Monitor WiFi connection
  if (WiFi.status() != WL_CONNECTED) {
    Serial.println("⚠️  WiFi connection lost! Attempting reconnection...");
    WiFi.reconnect();
    delay(5000);
  }
  
  delay(100);
}

Broadcast Discovery Client Node Code

Upload this code to 2-3 additional ESP32 devices to create client nodes that will participate in the broadcast discovery network. Each client will send discovery requests, respond to broadcasts, and maintain its own device information.

Client Device Features:

  • Sends broadcast discovery requests to find other devices
  • Responds to broadcast discovery requests from other devices
  • Uses isBroadcast() to differentiate between broadcast and unicast messages
  • Maintains statistics of broadcast vs unicast communications
  • Provides device announcements and status updates
/*
 * Author: Avant Maker
 * Date: June 18, 2025
 * Version: 1.0
 * License: MIT 
 * 
 * Description: 
 * This is the client code for testing broadcast discovery communication with 
 * multiple ESP32 devices. Upload this code to additional ESP32 boards to create 
 * a broadcast discovery network where clients can find each other and communicate.
 * Use this code together with the discovery server code above.
 *
 * Testing Instructions:
 * 1. Upload the main discovery server code to one ESP32
 * 2. Upload this client code to 2-3 additional ESP32 devices
 * 3. All devices will automatically discover each other using broadcast messages
 * 4. Monitor all Serial outputs to see the broadcast vs unicast communication
 * 5. Clients will send discovery requests and respond to broadcasts from other devices
 */

#include <WiFi.h>
#include <AsyncUDP.h>

// WiFi credentials (must match discovery server)
const char* ssid = "your_SSID";          // Replace with your Wi-Fi SSID
const char* password = "your_PASSWORD";  // Replace with your Wi-Fi password

// Network discovery configuration (must match server)
const uint16_t DISCOVERY_PORT = 8888;
const uint16_t RESPONSE_PORT = 8889;
const unsigned long DISCOVERY_INTERVAL = 60000;  // Send discovery every 60 seconds
const unsigned long ANNOUNCE_INTERVAL = 90000;   // Announce every 90 seconds
const unsigned long PING_INTERVAL = 120000;      // Ping every 2 minutes

// Client configuration
struct ClientConfig {
  String deviceId;
  String deviceName;
  String deviceType;
  String capabilities;
  float batteryLevel;
  AsyncUDP discoveryUDP;
  AsyncUDP responseUDP;
  unsigned long systemStartTime;
  unsigned long lastDiscoveryRequest;
  unsigned long lastAnnouncement;
  unsigned long lastPing;
  unsigned long totalBroadcastsReceived;
  unsigned long totalUnicastsReceived;
  unsigned long totalBroadcastsSent;
  unsigned long totalUnicastsSent;
  std::vector<String> discoveredDevices;
} client;

void setup() {
  Serial.begin(115200);
  Serial.println("Starting ESP32 Broadcast Discovery Client...");
  
  // Initialize client configuration
  client.deviceId = "ESP32_CLIENT_" + String((uint32_t)ESP.getEfuseMac(), HEX);
  client.deviceName = "ESP32 Discovery Client " + String((uint32_t)ESP.getEfuseMac() & 0xFFFF, HEX);
  client.deviceType = "DISCOVERY_CLIENT";
  client.capabilities = "broadcast_discovery,device_communication,status_reporting";
  client.batteryLevel = 78.3;  // Simulated battery level
  client.systemStartTime = millis();
  
  Serial.print("Client ID: ");
  Serial.println(client.deviceId);
  Serial.print("Client Name: ");
  Serial.println(client.deviceName);
  
  // Initialize WiFi
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  
  Serial.print("Connecting to WiFi");
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.print(".");
  }
  Serial.println();
  Serial.println("✅ WiFi connected successfully!");
  Serial.print("Client IP address: ");
  Serial.println(WiFi.localIP());
  Serial.print("Signal strength: ");
  Serial.print(WiFi.RSSI());
  Serial.println(" dBm");
  
  // Initialize UDP listeners
  setupClientListeners();
  
  // Send initial discovery request
  delay(3000);
  sendDiscoveryRequest();
  
  // Send initial device announcement
  delay(2000);
  sendDeviceAnnouncement();
  
  Serial.println("🔍 Discovery Client is ready and listening...");
}

void setupClientListeners() {
  Serial.println("=== Setting Up Client Listeners ===");
  
  // Setup discovery listener (listens for broadcast messages from other devices)
  if (client.discoveryUDP.listen(DISCOVERY_PORT)) {
    Serial.print("✅ Discovery listener started on port ");
    Serial.println(DISCOVERY_PORT);
    
    client.discoveryUDP.onPacket([](AsyncUDPPacket packet) {
      handleClientDiscoveryPacket(packet);
    });
  } else {
    Serial.print("❌ Failed to start discovery listener on port ");
    Serial.println(DISCOVERY_PORT);
  }
  
  // Setup response listener (listens for responses to our requests)
  if (client.responseUDP.listen(RESPONSE_PORT)) {
    Serial.print("✅ Response listener started on port ");
    Serial.println(RESPONSE_PORT);
    
    client.responseUDP.onPacket([](AsyncUDPPacket packet) {
      handleClientResponsePacket(packet);
    });
  } else {
    Serial.print("❌ Failed to start response listener on port ");
    Serial.println(RESPONSE_PORT);
  }
}

void handleClientDiscoveryPacket(AsyncUDPPacket packet) {
  // Extract message content
  String message = "";
  for (size_t i = 0; i < packet.length(); i++) {
    message += (char)packet.data()[i];
  }
  message.trim();
  
  // Use isBroadcast() to determine packet type - this is the key demonstration
  bool isBroadcastPacket = packet.isBroadcast();
  
  Serial.println("📡 === Client Discovery Packet Received ===");
  Serial.print("From: ");
  Serial.print(packet.remoteIP());
  Serial.print(":");
  Serial.println(packet.remotePort());
  Serial.print("Message: ");
  Serial.println(message);
  Serial.print("🔍 BROADCAST DETECTION: ");
  Serial.println(isBroadcastPacket ? "BROADCAST MESSAGE" : "UNICAST MESSAGE");
  Serial.print("Is Multicast: ");
  Serial.println(packet.isMulticast() ? "YES" : "NO");
  
  // Update statistics based on packet type
  if (isBroadcastPacket) {
    client.totalBroadcastsReceived++;
    Serial.println("📊 Broadcast counter incremented");
  } else {
    client.totalUnicastsReceived++;
    Serial.println("📊 Unicast counter incremented");
  }
  
  // Skip processing our own messages
  if (message.indexOf(client.deviceId) >= 0) {
    Serial.println("⚠️  Ignoring own message");
    return;
  }
  
  // Process different types of discovery messages
  if (message.startsWith("DISCOVER_DEVICES")) {
    if (isBroadcastPacket) {
      Serial.println("🔍 Responding to broadcast discovery request");
      respondToDiscoveryRequest(packet);
    } else {
      Serial.println("🔍 Responding to direct discovery request");
      respondToDiscoveryRequest(packet);
    }
  }
  else if (message.startsWith("DEVICE_ANNOUNCE")) {
    Serial.println("📢 Processing device announcement");
    processDeviceAnnouncement(message, packet);
  }
  else if (message.startsWith("PING")) {
    Serial.println("🏓 Responding to ping request");
    respondToPing(packet);
  }
  else {
    Serial.println("❓ Unknown discovery message type");
  }
  
  Serial.println("=== End Client Discovery Packet Processing ===");
}

void handleClientResponsePacket(AsyncUDPPacket packet) {
  // Extract message content
  String message = "";
  for (size_t i = 0; i < packet.length(); i++) {
    message += (char)packet.data()[i];
  }
  message.trim();
  
  // Check if this is a broadcast response (unusual but possible)
  bool isBroadcastPacket = packet.isBroadcast();
  
  Serial.println("📨 === Client Response Packet Received ===");
  Serial.print("From: ");
  Serial.print(packet.remoteIP());
  Serial.print(":");
  Serial.println(packet.remotePort());
  Serial.print("Message Length: ");
  Serial.println(packet.length());
  Serial.print("🔍 BROADCAST DETECTION: ");
  Serial.println(isBroadcastPacket ? "BROADCAST RESPONSE" : "UNICAST RESPONSE");
  
  // Update statistics
  if (isBroadcastPacket) {
    client.totalBroadcastsReceived++;
  } else {
    client.totalUnicastsReceived++;
  }
  
  // Process responses
  if (message.startsWith("DEVICE_INFO")) {
    Serial.println("📱 Processing device information response");
    addDiscoveredDevice(message, packet);
  }
  else if (message.startsWith("PONG")) {
    Serial.println("🏓 Processing pong response");
    Serial.print("Pong received from: ");
    Serial.println(packet.remoteIP());
  }
  else if (message.startsWith("REGISTRY_DATA")) {
    Serial.println("📋 Processing registry data");
    processRegistryData(message);
  }
  
  Serial.println("=== End Client Response Packet Processing ===");
}

void respondToDiscoveryRequest(AsyncUDPPacket& packet) {
  Serial.println("📤 === Sending Client Discovery Response ===");
  
  // Create client device information
  String deviceInfo = createClientDeviceInfo();
  String response = "DEVICE_INFO:" + deviceInfo;
  
  // Send unicast response back to the requesting device
  size_t sentBytes = packet.printf("%s", response.c_str());
  
  if (sentBytes > 0) {
    client.totalUnicastsSent++;
    Serial.print("✅ Discovery response sent (");
    Serial.print(sentBytes);
    Serial.println(" bytes)");
    Serial.print("Response sent to: ");
    Serial.println(packet.remoteIP());
  } else {
    Serial.println("❌ Failed to send discovery response");
  }
}

void sendDiscoveryRequest() {
  Serial.println("🔍 === Sending Broadcast Discovery Request ===");
  
  String request = "DISCOVER_DEVICES:REQUEST_FROM:" + client.deviceId;
  
  // Send broadcast discovery request
  size_t sentBytes = client.discoveryUDP.broadcast(request.c_str());
  
  if (sentBytes > 0) {
    client.totalBroadcastsSent++;
    client.lastDiscoveryRequest = millis();
    Serial.print("✅ Discovery request broadcasted (");
    Serial.print(sentBytes);
    Serial.println(" bytes)");
    Serial.println("🔍 This broadcast will be detected by isBroadcast() on receiving devices");
  } else {
    Serial.println("❌ Failed to send discovery request");
  }
}

void sendDeviceAnnouncement() {
  Serial.println("📢 === Sending Device Announcement ===");
  
  String announcement = "DEVICE_ANNOUNCE:" + createClientDeviceInfo();
  
  // Send broadcast announcement
  size_t sentBytes = client.discoveryUDP.broadcast(announcement.c_str());
  
  if (sentBytes > 0) {
    client.totalBroadcastsSent++;
    client.lastAnnouncement = millis();
    Serial.print("✅ Device announcement broadcasted (");
    Serial.print(sentBytes);
    Serial.println(" bytes)");
    Serial.println("📡 This broadcast will be detected by isBroadcast() on receiving devices");
  } else {
    Serial.println("❌ Failed to send device announcement");
  }
}

String createClientDeviceInfo() {
  String json = "{";
  json += "\"id\":\"" + client.deviceId + "\",";
  json += "\"name\":\"" + client.deviceName + "\",";
  json += "\"type\":\"" + client.deviceType + "\",";
  json += "\"ip\":\"" + WiFi.localIP().toString() + "\",";
  json += "\"port\":" + String(RESPONSE_PORT) + ",";
  json += "\"capabilities\":\"" + client.capabilities + "\",";
  json += "\"battery\":" + String(client.batteryLevel, 1) + ",";
  json += "\"signal\":" + String(WiFi.RSSI()) + ",";
  json += "\"uptime\":" + String((millis() - client.systemStartTime) / 1000) + ",";
  json += "\"status\":\"ONLINE\"";
  json += "}";
  return json;
}

void addDiscoveredDevice(const String& message, AsyncUDPPacket& packet) {
  String deviceInfo = packet.remoteIP().toString() + " - " + message.substring(0, 50);
  
  // Check if device already discovered
  bool alreadyDiscovered = false;
  for (size_t i = 0; i < client.discoveredDevices.size(); i++) {
    if (client.discoveredDevices[i].indexOf(packet.remoteIP().toString()) >= 0) {
      alreadyDiscovered = true;
      break;
    }
  }
  
  if (!alreadyDiscovered) {
    client.discoveredDevices.push_back(deviceInfo);
    Serial.print("➕ Discovered new device: ");
    Serial.println(packet.remoteIP());
  }
}

void processDeviceAnnouncement(const String& message, AsyncUDPPacket& packet) {
  Serial.println("📝 Processing device announcement");
  addDiscoveredDevice(message, packet);
}

void processRegistryData(const String& message) {
  Serial.println("📋 Registry data received");
  Serial.print("Data: ");
  Serial.println(message.substring(0, 100));
}

void respondToPing(AsyncUDPPacket& packet) {
  String response = "PONG:" + client.deviceId + ":" + String(millis());
  size_t sentBytes = packet.printf("%s", response.c_str());
  
  if (sentBytes > 0) {
    client.totalUnicastsSent++;
    Serial.println("🏓 Pong response sent");
  }
}

void sendPingRequest() {
  Serial.println("🏓 === Sending Ping Request ===");
  
  String ping = "PING:" + client.deviceId + ":" + String(millis());
  
  // Send broadcast ping
  size_t sentBytes = client.discoveryUDP.broadcast(ping.c_str());
  
  if (sentBytes > 0) {
    client.totalBroadcastsSent++;
    client.lastPing = millis();
    Serial.print("✅ Ping request broadcasted (");
    Serial.print(sentBytes);
    Serial.println(" bytes)");
  } else {
    Serial.println("❌ Failed to send ping request");
  }
}

void printClientStatus() {
  Serial.println("📊 === CLIENT STATUS REPORT ===");
  Serial.print("Client: ");
  Serial.print(client.deviceName);
  Serial.print(" (");
  Serial.print(client.deviceId);
  Serial.println(")");
  Serial.print("IP: ");
  Serial.println(WiFi.localIP());
  Serial.print("Uptime: ");
  Serial.print((millis() - client.systemStartTime) / 1000);
  Serial.println(" seconds");
  
  Serial.println("=== BROADCAST vs UNICAST STATISTICS ===");
  Serial.print("📡 Broadcasts Received: ");
  Serial.println(client.totalBroadcastsReceived);
  Serial.print("📨 Unicasts Received: ");
  Serial.println(client.totalUnicastsReceived);
  Serial.print("📡 Broadcasts Sent: ");
  Serial.println(client.totalBroadcastsSent);
  Serial.print("📨 Unicasts Sent: ");
  Serial.println(client.totalUnicastsSent);
  
  Serial.println("=== DISCOVERED DEVICES ===");
  Serial.print("Total Discovered: ");
  Serial.println(client.discoveredDevices.size());
  for (size_t i = 0; i < client.discoveredDevices.size(); i++) {
    Serial.print("  ");
    Serial.print(i + 1);
    Serial.print(". ");
    Serial.println(client.discoveredDevices[i]);
  }
  
  Serial.print("WiFi Signal: ");
  Serial.print(WiFi.RSSI());
  Serial.println(" dBm");
  Serial.print("Free Heap: ");
  Serial.print(ESP.getFreeHeap());
  Serial.println(" bytes");
  Serial.println("===============================");
}

void loop() {
  unsigned long currentTime = millis();
  
  // Send periodic discovery requests
  if (currentTime - client.lastDiscoveryRequest >= DISCOVERY_INTERVAL) {
    sendDiscoveryRequest();
  }
  
  // Send periodic device announcements
  if (currentTime - client.lastAnnouncement >= ANNOUNCE_INTERVAL) {
    sendDeviceAnnouncement();
  }
  
  // Send periodic ping requests
  if (currentTime - client.lastPing >= PING_INTERVAL) {
    sendPingRequest();
  }
  
  // Print client status every 60 seconds
  static unsigned long lastStatusPrint = 0;
  if (currentTime - lastStatusPrint >= 60000) {
    lastStatusPrint = currentTime;
    printClientStatus();
  }
  
  // Monitor WiFi connection
  if (WiFi.status() != WL_CONNECTED) {
    Serial.println("⚠️  WiFi connection lost! Attempting reconnection...");
    WiFi.reconnect();
    delay(5000);
  }
  
  delay(100);
}

Expected Output and Testing Results

On the Discovery Server (Main Device), you should see:

  • Detection of broadcast packets using isBroadcast() method
  • Distinction between broadcast discovery requests and unicast responses
  • Device registry updates as new clients join the network
  • Statistics showing broadcast vs unicast packet counts
  • Automatic response to broadcast discovery requests

On the Client Devices, you should see:

  • Successful broadcasting of discovery requests and announcements
  • Reception and identification of broadcast packets from other devices
  • Unicast responses to broadcast requests
  • Discovery of other devices on the network
  • Clear differentiation between broadcast and unicast communications

Key isBroadcast() Testing Points:

  • Broadcast Detection: Verify that isBroadcast() correctly identifies broadcast packets as true
  • Unicast Detection: Confirm that isBroadcast() returns false for unicast responses
  • Packet Statistics: Check that broadcast and unicast counters are accurately maintained
  • Response Behavior: Observe how devices respond differently to broadcast vs unicast messages
  • Network Discovery: See how broadcast packets enable automatic device discovery

Simple Broadcast Detection Example

This simpler example demonstrates the basic usage of the isBroadcast() method for identifying broadcast packets in a minimal setup.

 /*
 * Author: Avant Maker
 * Date: June 18, 2025
 * Version: 1.0
 * License: MIT 
 * 
 * Description: 
 * This example shows basic usage of the isBroadcast() method
 * to detect and handle broadcast UDP packets differently from unicast packets.
 * 
 * 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, 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>

const char* ssid = "your_wifi_ssid";
const char* password = "your_wifi_password";

AsyncUDP udp;

void setup() {
  Serial.begin(115200);
  WiFi.begin(ssid, password);
  
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.print(".");
  }
  
  Serial.println("WiFi connected");
  Serial.println(WiFi.localIP());
  
  // Listen on port 8888 for any UDP packets
  if (udp.listen(8888)) {
    Serial.println("UDP Listening on port 8888");
    
    udp.onPacket([](AsyncUDPPacket packet) {
      // Extract message
      String message = "";
      for (size_t i = 0; i < packet.length(); i++) {
        message += (char)packet.data()[i];
      }
      
      // Use isBroadcast() to check packet type
      if (packet.isBroadcast()) {
        Serial.println("📡 BROADCAST packet received:");
        Serial.print("  From: ");
        Serial.println(packet.remoteIP());
        Serial.print("  Message: ");
        Serial.println(message);
        Serial.println("  → This is a broadcast message sent to all devices");
        
        // Send acknowledgment back (unicast response)
        packet.printf("ACK: Broadcast received from %s", WiFi.localIP().toString().c_str());
        
      } else {
        Serial.println("📨 UNICAST packet received:");
        Serial.print("  From: ");
        Serial.println(packet.remoteIP());
        Serial.print("  Message: ");
        Serial.println(message);
        Serial.println("  → This is a direct message sent specifically to this device");
      }
    });
  }
}

void loop() {
  delay(1000);
}

ESP32 Library Index

ESP32 Arduino Core Library


FAQ

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!

error: Content is protected !!