2021-01-31

UDP das minimale verbindungslose Netzwerkprotokoll.

Howto

UDP Unicast Multicast Broadcast

Zu jedem Adressierungsschemata gibt es am Ende des Abschnitts ein Beispiel aus der Praxis.

Benötigt:
2 x Esp8266 Board
1 x DS18B20 Temperatursensor
PC-Programm Packet Sender
Optional:
Weitere Esp8266 für Multicast und Broadcast.
Es ist erforderlich die Arduino IDE mehrfach zu öffnen um für jeden Esp8266 einen eigenen seriellen Monitor zur Verfügung zu haben.
Für den UDP Client Sketch kam ein Wemos D1 Mini Pro zum Einsatz und ein Nodemcu für den UDP Server Sketch. Es ist aber unerheblich welches Esp-Board zum Einsatz kommt.
Als zusätzlichen UDP Server/Client verwenden ich den "Packet Sender" auf dem PC. Er ist für gängige Betriebssysteme verfügbar. Dieser ist am einfachsten als Portable Version zu installieren.
Sobald das Fenster des Paketsenders angezeigt wird, gib die folgenden Informationen ein:
* Name des Pakets.
* ASCII- Text der Nachricht, die innerhalb des Pakets gesendet werden soll.
* IP- Adresse, die von deinen ESP angezeigt wird.
* Port, der vom ESP angezeigt wird.
* Wähle UDP aus.
* Speicher deine Eingaben.

UDP Unicast

Der Ablauf soll am Beispiel eines Programmpaares für Client (Sender) und Server (Empfänger) gezeigt werden. Um nicht nur das schnöde "Hello World!" zu verschicken bekommt der Sender einen Temperatursensor an einen Pin spendiert. Als minimale Funktionalität empfängt der Server Pakete und zeigt diese im Seriellen Monitor an.
Unicast
Als Ziel wird die lokale IP-Adresse des Gerätes genommen.

UDP Unicast Sender

In diesem Sketch muss zunächst die IP des Empfängers eingetragen werden. UDP_Unicast_Client.ino

// ****************************************************************
// Sketch Esp8266 UDP Unicast Client
// created: Jens Fleischer, 2021-01-31
// last mod: Jens Fleischer, 2021-01-31
// For more information visit: https://fipsok.de
// ****************************************************************
// Hardware: Esp8266, DS18B20, 4k7 Ohm Widerstand
// D4 = GPIO2  Anschluss DS18B20
// 4k7 Ohm Widerstand von VCC auf GPIO2
// Software: Esp8266 Arduino Core 2.7.0 - 2.7.4
// Getestet auf: Wemos D1 Mini Pro
/******************************************************************
  Copyright (c) 2021 Jens Fleischer. All rights reserved.

  This file is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.
  This file is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.
*******************************************************************/

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#include <OneWire.h>                                     // https://github.com/PaulStoffregen/OneWire Version 2.3.5
#include <DallasTemperature.h>                           // https://github.com/milesburton/Arduino-Temperature-Control-Library Version 3.9.0

const char* ssid = "Netzwerkname";                       // Darf bis zu 32 Zeichen haben.
const char* password = "PasswortvomNetzwerk";            // Mindestens 8 Zeichen jedoch nicht länger als 64 Zeichen.

const byte ONE_WIRE_PIN = D4;                            // Pin für den Temperatursensor Ds18b20 einstellen.

OneWire oneWire(ONE_WIRE_PIN);
DallasTemperature DS18B20(&oneWire);

WiFiUDP Udp;
IPAddress unicastIP(192, 168, 178, 43);                  // Adresse des Esp, welcher als Empfänger der Nachricht dient, eintragen.
constexpr uint16_t PORT = 8266;                          // UDP Port an welchen gesendet wird.

void setup() {
  Serial.begin(115200);
  delay(100);
  Serial.printf("\nSketchname: %s\nBuild: %s\t\tIDE: %d.%d.%d\n%s\n\n",
                (__FILE__), (__TIMESTAMP__), ARDUINO / 10000, ARDUINO % 10000 / 100, ARDUINO % 100 / 10 ? ARDUINO % 100 : ARDUINO % 10, ESP.getFullVersion().c_str());

  DS18B20.begin();
  DS18B20.getDeviceCount() ? printf("Auflösung DS18B20: %d Bit\n", DS18B20.getResolution()) : printf("Kein DS18B20 am Pin %d gefunden.\n", ONE_WIRE_PIN);

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("\nVerbunden mit: " + WiFi.SSID());
}

void loop() {
  static unsigned long previousMillis;
  constexpr unsigned long INTERVAL (2000);                // Aller 2 Sekunden wird die Temperatur gemessen und anschliesend gesendet.
  if (millis() - previousMillis >= INTERVAL) {
    previousMillis += INTERVAL;
    DS18B20.requestTemperatures();                        // Sendet einen Befehl für alle Geräte am Bus, um eine Temperaturumwandlung durchzuführen.
    sendUdp(DS18B20.getTempCByIndex(0));                  // Holt die Temperatur vom Sensor und übergibt diese an die Funktion zum senden.
  }
}

void sendUdp(float tempC) {
  Udp.beginPacket(unicastIP, PORT);
  Udp.printf("Temperatur: %.2f°C", tempC);
  Udp.endPacket();
}
		

UDP Unicast Empfänger

UDP_Unicast_Server.ino

// ****************************************************************
// Sketch Esp8266 UDP Unicast Server
// created: Jens Fleischer, 2021-01-31
// last mod: Jens Fleischer, 2021-01-31
// For more information visit: https://fipsok.de
// ****************************************************************
// Hardware: Esp8266
// Software: Esp8266 Arduino Core 2.7.0 - 2.7.4
// Getestet auf: Nodemcu
/******************************************************************
  Copyright (c) 2021 Jens Fleischer. All rights reserved.

  This file is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.
  This file is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.
*******************************************************************/

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>

const char* ssid = "Netzwerkname";                       // Darf bis zu 32 Zeichen haben.
const char* password = "PasswortvomNetzwerk";            // Mindestens 8 Zeichen jedoch nicht länger als 64 Zeichen.

constexpr uint16_t PORT = 8266;                          // Lokaler UDP Port.
char packetBuffer[21];                                   // Puffer für eingehendes Paket.

WiFiUDP Udp;

void setup() {
  Serial.begin(115200);
  delay(100);
  Serial.printf("\nSketchname: %s\nBuild: %s\t\tIDE: %d.%d.%d\n%s\n\n",
                (__FILE__), (__TIMESTAMP__), ARDUINO / 10000, ARDUINO % 10000 / 100, ARDUINO % 100 / 10 ? ARDUINO % 100 : ARDUINO % 10, ESP.getFullVersion().c_str());

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print('.');
    delay(500);
  }
  Serial.println("\nVerbunden! Esp8266 IP: " + WiFi.localIP().toString());
  Serial.printf("UDP Server lauscht am Port: %d\n\n", PORT);
  Udp.begin(PORT);
}

void loop() {
  uint16_t packetSize = Udp.parsePacket();              // Eingehende UDP-Pakete empfangen.
  if (packetSize) {                                     // Prüfen ob UDP-Pakete empfangen wurden.
    Udp.read(packetBuffer, sizeof(packetBuffer));       // Einlesen des UDP Paket in den Bufffer.
    packetBuffer[packetSize] = 0;                       // String Ende hinzufügen.
    Serial.println(packetBuffer);                       // Visualisierung des empfangenen Packets.
  }
}
		

Packet Sender UDP Unicast

Auch mit dem "Packet Sender" kann nun eine Temperatur an den Esp8266 mit dem Empfänger Sketch geschickt werden. Trage dazu Name, Temperatur, Adresse des Empfängers und den Port ein.
Ein Klick auf "UDP Server Disabled" macht aus dem "Packet Sender" einen UDP Server. Trägt man nun die IP des PC mit dem "Packet Sender" und den unten angezeigten Port in den Sender Sketch ein, wird der "Packet Sender" zum Empfänger des Unicast Paketes.
Unicast

UDP NTP Client (Network Time Protocol)

Als Beispiel aus der Praxis für Unicast UDP dient der NTP Client, der uns die aktuelle Uhrzeit auf den Esp8266 holt. Genaugenommen handelt es sich um einen SNTP (Simple Network Time Protocol) Client, die vereinfachte Version des NTP. Die Funktionalität des Beispiels ist auf das holen und darstellen der Uhrzeit aller 15 Sekunden beschränkt.
UDP_Unicast_NTP_Client.ino

// ****************************************************************
// Sketch Esp8266 UDP Unicast NTP Client
// created: Jens Fleischer, 2021-01-31
// last mod: Jens Fleischer, 2021-01-31
// For more information visit: https://fipsok.de
// ****************************************************************
// Hardware: Esp8266
// Software: Esp8266 Arduino Core 2.7.0 - 2.7.4
// Getestet auf: Nodemcu, Wemos D1 Mini Pro
/******************************************************************
  Copyright (c) 2021 Jens Fleischer. All rights reserved.

  This file is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.
  This file is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.
*******************************************************************/

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>

const char* ssid = "Netzwerkname";                       // Darf bis zu 32 Zeichen haben.
const char* password = "PasswortvomNetzwerk";            // Mindestens 8 Zeichen jedoch nicht länger als 64 Zeichen.

constexpr uint16_t PORT = 64390;                         // Lokaler UDP Port.
const char* ntpServerName = "de.pool.ntp.org";           // Ntp Server, von welchen die Zeit geholt werden soll.

WiFiUDP Udp;                                             // Eine UDP-Instanz.

void setup() {
  Serial.begin(115200);
  delay(100);
  Serial.printf("\nSketchname: %s\nBuild: %s\t\tIDE: %d.%d.%d\n%s\n\n",
                (__FILE__), (__TIMESTAMP__), ARDUINO / 10000, ARDUINO % 10000 / 100, ARDUINO % 100 / 10 ? ARDUINO % 100 : ARDUINO % 10, ESP.getFullVersion().c_str());

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print('.');
    delay(500);
  }
  Serial.println("\nVerbunden! Esp8266 IP: " + WiFi.localIP().toString());
  Serial.printf("Udp Lokal Port: %d\n\n", PORT);
  Udp.begin(PORT);
}

void loop() {
  constexpr uint32_t INTERVAL (15000);                   // Ntp Serveranfrage nur aller 15 Sekunden (RFC 4330 Best Practices).
  static uint32_t previousMillis {0 - INTERVAL / 2};
  if (millis() - previousMillis >= INTERVAL) {
    previousMillis += INTERVAL;
    sendNtpRequest(ntpServerName);
  }

  uint16_t packetSize = Udp.parsePacket();               // Eingehende UDP-Pakete empfangen.
  if (packetSize) {                                      // Prüfen ob UDP-Pakete empfangen wurden.
    uint8_t packetBuffer[48];                            // Puffer für eingehendes Paket.
    Udp.read(packetBuffer, 48);                          // Paket in den Puffer einlesen.
    union {
      uint32_t timeStamp;                                // Variable für die NTP-Zeit (Sekunden seit dem 1. Januar 1900):
      uint8_t asArray[4];
    } convert;
    convert.asArray[3] = packetBuffer[40];               // Der Zeitstempel beginnt bei Byte 40 des Pakets und beträgt vier Bytes.
    convert.asArray[2] = packetBuffer[41];
    convert.asArray[1] = packetBuffer[42];
    convert.asArray[0] = packetBuffer[43];
    uint32_t epoch = convert.timeStamp - 2208988800UL;   // Die Unix-Zeit beginnt am 1. Januar 1970. In Sekunden sind das 2208988800.
    Serial.printf("UTC: %.2ld:%.2ld:%.2ld\n", epoch % 86400L / 3600, epoch % 3600 / 60, epoch % 60);  // Ausgabe Koordinierte Weltzeit
  }
}

void sendNtpRequest(const char *host) {
  uint8_t requestBuffer[48] = {0xE3};                    // Puffer für Paket mit den erforderlichen Angaben laut RFC 4330 (LI, Version, Mode).
  Udp.beginPacket(host, 123);                            // NTP-Anfragen werden an Port 123 gesendet.
  Udp.write(requestBuffer, 48);                          // Senden einer NTP-Anfrage an einen Zeitserver.
  Udp.endPacket();
}			

UDP Multicast

Beim Multicast muss die lokale IP-Adresse der Empfänger nicht bekannt sein. Für Multicast ist in IPv4 der Adress-Bereich 224.0.0.0 bis 239.255.255.255 reserviert. Die Adresse ist frei wählbar, muss aber auf allen Esp Boards welche die Nachricht empfangen sollen gleich sein. Vom Multicast Sender wird der Temperatur-Rohwert an alle Empfänger gesendet und deren Antwort im Seriellen Monitor angezeigt. Von den Multicast Empfängern wird der Rohwert für die Anzeige in Grad Celsius umgewandelt und der Empfang des Pakets dem Sender bestätigt.
Multicast
Als Ziel wird eine IP-Adresse im Bereich 224.0.0.0 bis 239.255.255.255 ausgewählt.

UDP Multicast Sender

UDP_Multicast_Client.ino

// ****************************************************************
// Sketch Esp8266 UDP Multicast Client
// created: Jens Fleischer, 2021-01-31
// last mod: Jens Fleischer, 2021-01-31
// For more information visit: https://fipsok.de
// ****************************************************************
// Hardware: Esp8266, DS18B20, 4k7 Ohm Widerstand
// D4 = GPIO2  Anschluss DS18B20
// 4k7 Ohm Widerstand von VCC auf GPIO2
// Software: Esp8266 Arduino Core 2.7.0 - 2.7.4
// Getestet auf: Wemos D1 Mini Pro
/******************************************************************
  Copyright (c) 2021 Jens Fleischer. All rights reserved.

  This file is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.
  This file is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.
*******************************************************************/

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#include <OneWire.h>                                     // https://github.com/PaulStoffregen/OneWire Version 2.3.5
#include <DallasTemperature.h>                           // https://github.com/milesburton/Arduino-Temperature-Control-Library Version 3.9.0

const char* ssid = "Netzwerkname";                       // Darf bis zu 32 Zeichen haben.
const char* password = "PasswortvomNetzwerk";            // Mindestens 8 Zeichen jedoch nicht länger als 64 Zeichen.

const byte ONE_WIRE_PIN = D4;                            // Pin für Ds18b20 einstellen.
DeviceAddress address;

OneWire oneWire(ONE_WIRE_PIN);
DallasTemperature DS18B20(&oneWire);

IPAddress multicastIP(230, 120, 10, 1);                  // Senden an alle Netzwerkteilnehmer mit dieser Multicastadresse.
constexpr uint16_t PORT = 8266;                          // Lokaler UDP Port
char packetBuffer[255];                                  // Puffer für eingehendes Paket.

WiFiUDP Udp;

void setup() {
  Serial.begin(115200);
  delay(100);
  Serial.printf("\nSketchname: %s\nBuild: %s\t\tIDE: %d.%d.%d\n%s\n\n",
                (__FILE__), (__TIMESTAMP__), ARDUINO / 10000, ARDUINO % 10000 / 100, ARDUINO % 100 / 10 ? ARDUINO % 100 : ARDUINO % 10, ESP.getFullVersion().c_str());
 
  DS18B20.begin();
  DS18B20.getDeviceCount() ? printf("DS18B20 Auflösung: %d Bit\n", DS18B20.getResolution()) : printf("Kein DS18B20 am Pin %d gefunden\n", ONE_WIRE_PIN);
  DS18B20.getAddress(address, 0);                        // Um den Temperatur-Rohwert vom Sensor zu holen wird die Adresse des Sensors benötigt.

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.printf("\nVerbunden mit: %s\n\n", WiFi.SSID().c_str());
  Udp.beginMulticast(WiFi.localIP(), multicastIP, PORT);
}

void loop() {
  static unsigned long previousMillis;
  constexpr unsigned long INTERVAL (5000);               // Aller 5 Sekunden wird die Temperatur gemessen und anschliesend gesendet.
  if (millis() - previousMillis >= INTERVAL) {
    previousMillis += INTERVAL;
    DS18B20.requestTemperatures();                       // Sendet einen Befehl für alle Geräte am Bus, um eine Temperaturumwandlung durchzuführen.
    sendUdp(DS18B20.getTemp(address));                   // Holt den Temperatur-Rohwert vom Sensor und übergibt diese an die Funktion zum senden.
  }
  uint16_t packetSize = Udp.parsePacket();               // Eingehende UDP-Pakete empfangen.
  if (packetSize) {                                      // Prüfen ob UDP-Pakete empfangen wurden.
    Udp.read(packetBuffer, sizeof(packetBuffer));        // Einlesen des UDP Paket in den Bufffer.
    packetBuffer[packetSize] = 0;                        // String Ende hinzufügen.
    Serial.println(packetBuffer);                        // Visualisierung des empfangenen Packets.
  }
}

void sendUdp(int16_t raw) {
  Udp.beginPacketMulticast(multicastIP, PORT, WiFi.localIP());
  Udp.print(raw);                                        // Temperatur-Rohwert als 12-Bit-Ganzzahl senden. 
  Udp.endPacket();
}
		

UDP Multicast Empfänger

Der Empfänger Sketch sollte nun auf mindestens 2 Esp Boards geladen werden.
UDP_Multicast_Server.ino

// ****************************************************************
// Sketch Esp8266 UDP Multicast Server
// created: Jens Fleischer, 2021-01-31
// last mod: Jens Fleischer, 2021-01-31
// For more information visit: https://fipsok.de
// ****************************************************************
// Hardware: Esp8266
// Software: Esp8266 Arduino Core 2.7.0 - 2.7.4
// Getestet auf: Nodemcu
/******************************************************************
  Copyright (c) 2021 Jens Fleischer. All rights reserved.

  This file is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.
  This file is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.
*******************************************************************/

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>

const char* ssid = "Netzwerkname";                       // Darf bis zu 32 Zeichen haben.
const char* password = "PasswortvomNetzwerk";            // Mindestens 8 Zeichen jedoch nicht länger als 64 Zeichen.

IPAddress multicastIP(230, 120, 10, 1);                  // Emfängt auf dieser Multicastadresse.
constexpr uint16_t PORT = 8266;                          // UDP Port
char packetBuffer[7];                                    // Puffer für eingehendes Paket.

WiFiUDP Udp;

void setup() {
  Serial.begin(115200);
  delay(100);
  Serial.printf("\nSketchname: %s\nBuild: %s\t\tIDE: %d.%d.%d\n%s\n\n",
                (__FILE__), (__TIMESTAMP__), ARDUINO / 10000, ARDUINO % 10000 / 100, ARDUINO % 100 / 10 ? ARDUINO % 100 : ARDUINO % 10, ESP.getFullVersion().c_str());
 
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print('.');
    delay(500);
  }
  Serial.println("\nVerbunden! Esp8266 IP: " + WiFi.localIP().toString());
  Serial.printf("UDP Server am Port: %d\n", PORT);
  if (!Udp.beginMulticast(WiFi.localIP(), multicastIP, PORT)) {
    Serial.println("Fehler beim Beginn Multicast");
  }
}

void loop() {
  uint16_t packetSize = Udp.parsePacket();               // Eingehende UDP-Pakete empfangen.
  if (packetSize) {                                      // Prüfen ob UDP-Pakete empfangen wurden.
    Udp.read(packetBuffer, sizeof(packetBuffer));        // Einlesen des UDP Paket in den Bufffer.
    packetBuffer[packetSize] = 0;                        // String Ende hinzufügen.
    int16_t raw = atoi(packetBuffer);                    // Konvertieren der Zeichenfolge in eine Ganzzahl.
    Serial.printf("Temperatur: %.2f°C\n", raw * 0.0078125f);

    Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());   // Eine Antwort senden das daß Paket empfangen wurde.
    Udp.printf("Der Esp mit der IP: %s bekam ein %d Bytes Packet!", WiFi.localIP().toString().c_str(), packetSize);
    Udp.endPacket();
  }
}
		

Packet Sender UDP Multicast

Auch der "Packet Sender" kann Multicastnachrichten empfangen. Wähle unter File/Settings "Enable UDP Servers" aus und gib als Port 8266 ein. Klick auf Multicast und trage die Multicastadresse ein. Bestätigung mit "Join" und "OK" sollte die Nachrichten vom Esp8266 Multicast Sender anzeigen.
Mit dem "Packet Sender" können natürlich auch Multicastnachrichten an alle Empfänger gesendet werden. Trage dazu Name, Temperatur-Rohwert, die Multicastadresse und den Port ein.
Multicast

UDP UPnP Server (Universal Plug and Play)

Als Beispiel aus der Praxis für Multicast UDP dient der UPnP Server, der uns den Netzwerkverkehr der UPnP Geräte anzeigt. Sobald ein UPnP-Gerät eine IP-Adresse hat, muss es seine Existenz im Netzwerk an die Kontrollpunkte melden. Das erfolgt via UDP über die Multicast-Adresse 239.255.255.250:1900, im Falle von IPv4, auf der Basis des Simple Service Discovery Protocol (SSDP). Vorausgesetzt UPnP wurde im Router nicht deaktiviert, sollte zumindest der Router ab und zu etwas an vorher genannte Adresse/Port senden.
UDP_Multicast_UPnP_Server.ino

// ****************************************************************
// Sketch Esp8266 UDP Multicast UPnP Server
// created: Jens Fleischer, 2021-01-31
// last mod: Jens Fleischer, 2021-01-31
// For more information visit: https://fipsok.de
// ****************************************************************
// Hardware: Esp8266
// Software: Esp8266 Arduino Core 2.7.0 - 2.7.4
// Getestet auf: Nodemcu, Wemos D1 Mini Pro
/******************************************************************
  Copyright (c) 2021 Jens Fleischer. All rights reserved.

  This file is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.
  This file is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.
*******************************************************************/

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>

const char* ssid = "Netzwerkname";                       // Darf bis zu 32 Zeichen haben.
const char* password = "PasswortvomNetzwerk";            // Mindestens 8 Zeichen jedoch nicht länger als 64 Zeichen.

IPAddress multicastIP(239, 255, 255, 250);               // Multicastadresse für UPnP.
constexpr uint16_t PORT = 1900;                          // UDP Port für UPnP
char packetBuffer[255];                                  // Puffer für eingehendes Paket.

WiFiUDP Udp;

void setup() {
  Serial.begin(115200);
  delay(100);
  Serial.printf("\nSketchname: %s\nBuild: %s\t\tIDE: %d.%d.%d\n%s\n\n",
                (__FILE__), (__TIMESTAMP__), ARDUINO / 10000, ARDUINO % 10000 / 100, ARDUINO % 100 / 10 ? ARDUINO % 100 : ARDUINO % 10, ESP.getFullVersion().c_str());
 
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print('.');
    delay(500);
  }
  Serial.println("\nVerbunden!\nEsp8266 IP: " + WiFi.localIP().toString());
  Serial.printf("UDP Server am Port: %d\n", PORT);
  if (!Udp.beginMulticast(WiFi.localIP(), multicastIP, PORT)) {
    Serial.println("Fehler beim Beginn Multicast");
  }
}

void loop() {
  uint16_t packetSize = Udp.parsePacket();               // Eingehende UDP-Pakete empfangen.
  if (packetSize) {                                      // Prüfen ob UDP-Pakete empfangen wurden.
    Udp.read(packetBuffer, sizeof(packetBuffer));        // Einlesen des UDP Paket in den Bufffer.
    packetBuffer[packetSize] = 0;                        // String Ende hinzufügen
    Serial.printf("\n************ Message from: %s ***********\n%s\n", Udp.remoteIP().toString().c_str(), packetBuffer);
  }
}			

UDP Broadcast

Beim Broadcast unterscheidet man zwischen Limited Broadcast und Directed Broadcast. Vom Sender wird mittels Limited Broadcast die Temperatur in Grad Celsius an alle Empfänger gesendet und deren Antwort im Seriellen Monitor angezeigt. Von den Empfängern wird die Temperatur angezeigt und der Empfang des Pakets mittels Directed Broadcast allen mitgeteilt.
Limited Broadcast
Als Ziel wird die IP-Adresse 255.255.255.255 angegeben.
Dieses Ziel liegt immer im eigenen lokalen Netz und wird direkt in einen Ethernet-Broadcast umgesetzt. Ein Limited Broadcast wird von einem Router nicht weitergeleitet.
Directed Broadcast
Die Adresse für einen Directed Broadcast lautet x.x.x.255.
Das Ziel sind die Teilnehmer eines bestimmten Netzes. Ein Directed Broadcast wird von einem Router weitergeleitet, falls Quell- und Zielnetz unterschiedlich sind.

UDP Broadcast Sender

UDP_Broadcast_Client.ino

// ****************************************************************
// Sketch Esp8266 UDP Broadcast Client
// created: Jens Fleischer, 2021-01-31
// last mod: Jens Fleischer, 2021-01-31
// For more information visit: https://fipsok.de
// ****************************************************************
// Hardware: Esp8266, DS18B20, 4k7 Ohm Widerstand
// D4 = GPIO2  Anschluss DS18B20
// 4k7 Ohm Widerstand von VCC auf GPIO2
// Software: Esp8266 Arduino Core 2.7.0 - 2.7.4
// Getestet auf: Wemos D1 Mini Pro
/******************************************************************
  Copyright (c) 2021 Jens Fleischer. All rights reserved.

  This file is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.
  This file is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.
*******************************************************************/

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#include <OneWire.h>                                     // https://github.com/PaulStoffregen/OneWire Version 2.3.5
#include <DallasTemperature.h>                           // https://github.com/milesburton/Arduino-Temperature-Control-Library Version 3.9.0

const char* ssid = "Netzwerkname";                       // Darf bis zu 32 Zeichen haben.
const char* password = "PasswortvomNetzwerk";            // Mindestens 8 Zeichen jedoch nicht länger als 64 Zeichen.

const byte ONE_WIRE_PIN = D4;                            // Pin für Ds18b20 einstellen.

OneWire oneWire(ONE_WIRE_PIN);
DallasTemperature DS18B20(&oneWire);

IPAddress broadcastIP(255, 255, 255, 255);               // Senden an alle Netzwerkteilnehmer mit dieser Multicastadresse.
constexpr uint16_t PORT = 8266;                          // Lokaler UDP Port
char packetBuffer[255];                                  // Puffer für eingehendes Paket.

WiFiUDP Udp;

void setup() {
  Serial.begin(115200);
  delay(100);
  Serial.printf("\nSketchname: %s\nBuild: %s\t\tIDE: %d.%d.%d\n%s\n\n",
                (__FILE__), (__TIMESTAMP__), ARDUINO / 10000, ARDUINO % 10000 / 100, ARDUINO % 100 / 10 ? ARDUINO % 100 : ARDUINO % 10, ESP.getFullVersion().c_str());

  DS18B20.begin();
  DS18B20.getDeviceCount() ? printf("DS18B20 Auflösung: %d Bit\n", DS18B20.getResolution()) : printf("Kein DS18B20 am Pin %d gefunden\n", ONE_WIRE_PIN);

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.printf("\nVerbunden mit: %s\n\n", WiFi.SSID().c_str());
  Udp.begin(PORT);
}

void loop() {
  static unsigned long previousMillis;
  constexpr unsigned long INTERVAL (15000);               // Aller 15 Sekunden wird die Temperatur gemessen und anschliesend gesendet.
  if (millis() - previousMillis >= INTERVAL) {
    previousMillis += INTERVAL;
    DS18B20.requestTemperatures();                        // Sendet einen Befehl für alle Geräte am Bus, um eine Temperaturumwandlung durchzuführen.
    sendUdp(DS18B20.getTempCByIndex(0));                  // Holt die Temperatur vom Sensor und übergibt diese an die Funktion zum senden.
  }
  uint16_t packetSize = Udp.parsePacket();                // Eingehende UDP-Pakete empfangen.
  if (packetSize) {                                       // Prüfen ob UDP-Pakete empfangen wurden.
    Udp.read(packetBuffer, sizeof(packetBuffer));         // Einlesen des UDP Paket in den Bufffer.
    packetBuffer[packetSize] = 0;                         // String Ende hinzufügen.
    Serial.printf("Ziel IP: %s\nLog: %s\n",                // Visualisierung des empfangenen Packets.
                  Udp.destinationIP().toString().c_str(), packetBuffer);
  }
}

void sendUdp(float tempC) {
  Udp.beginPacket(broadcastIP, PORT);
  Udp.print(tempC);                                       // Temperatur Wert als senden.
  Udp.endPacket();
}
		

UDP Broadcast Empfänger

Der Empfänger Sketch sollte auf mindestens 2 Esp Boards geladen werden.
UDP_Broadcast_Server.ino

// ****************************************************************
// Sketch Esp8266 UDP Broadcast Server
// created: Jens Fleischer, 2021-01-31
// last mod: Jens Fleischer, 2021-01-31
// For more information visit: https://fipsok.de
// ****************************************************************
// Hardware: Esp8266
// Software: Esp8266 Arduino Core 2.7.0 - 2.7.4
// Getestet auf: Nodemcu
/******************************************************************
  Copyright (c) 2021 Jens Fleischer. All rights reserved.

  This file is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.
  This file is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.
*******************************************************************/

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>

const char* ssid = "Netzwerkname";                       // Darf bis zu 32 Zeichen haben.
const char* password = "PasswortvomNetzwerk";            // Mindestens 8 Zeichen jedoch nicht länger als 64 Zeichen.

constexpr uint16_t PORT = 8266;                          // Lokaler UDP Port.
char packetBuffer[255];                                  // Puffer für eingehendes Paket.

WiFiUDP Udp;

void setup() {
  Serial.begin(115200);
  delay(100);
  Serial.printf("\nSketchname: %s\nBuild: %s\t\tIDE: %d.%d.%d\n%s\n\n",
                (__FILE__), (__TIMESTAMP__), ARDUINO / 10000, ARDUINO % 10000 / 100, ARDUINO % 100 / 10 ? ARDUINO % 100 : ARDUINO % 10, ESP.getFullVersion().c_str());

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print('.');
    delay(500);
  }
  Serial.println("\nVerbunden! Esp8266 IP: " + WiFi.localIP().toString());
  Serial.printf("UDP Server lauscht am Port: %d\n\n", PORT);
  Udp.begin(PORT);
}

void loop() {
  uint16_t packetSize = Udp.parsePacket();                       // Eingehende UDP-Pakete empfangen.
  if (packetSize) {                                              // Prüfen ob UDP-Pakete empfangen wurden.
    Udp.read(packetBuffer, sizeof(packetBuffer));                // Einlesen des UDP Paket in den Bufffer.
    packetBuffer[packetSize] = 0;                                // String Ende hinzufügen.
    if (isdigit(packetBuffer[0]) || isdigit(packetBuffer[1])) {  // Prüfen ob es eine Temperatur ist.
      float tempC = atof(packetBuffer);                          // Das Umwandeln in float ist für die Anzeige nicht erforderlich aber für eventuelle Berechnungen.
      Serial.printf("Ziel IP: %s\nTemperatur: %.2f°C\n\n",       // Visualisierung des empfangenen Packets.
                    Udp.destinationIP().toString().c_str(), tempC);
      IPAddress broadcastDirectedIP = Udp.remoteIP();            // Ermitteln des Netzes für einen Directed Broadcast.
      broadcastDirectedIP[3] = 255;
      Udp.beginPacket(broadcastDirectedIP, Udp.remotePort());    // Antwort senden.
      Udp.printf("An alle, der Esp mit der IP: %s bekam ein %d Bytes Packet!", WiFi.localIP().toString().c_str(), packetSize);
      Udp.endPacket();
    }
    else {
      Serial.printf("Ziel IP: %s\n%s\n\n",                       // Visualisierung des empfangenen Packets.
                    Udp.destinationIP().toString().c_str(), packetBuffer);
    }
  }
}
		

Packet Sender UDP Broadcast

Broadcast, an alle im lokalen Subnetz, empfängt auch der "Packet Sender", wenn er als UDP Server konfiguriert ist. Mit dem "Packet Sender" können ebenso auch Broadcastnachrichten an alle Empfänger gesendet werden. Trage dazu Name, Temperatur, die Broadcastadresse und den Port ein.
Broadcast

UDP DHCP Server (Dynamic Host Configuration Protocol)

Als Beispiel aus der Praxis für Broadcast UDP dient der DHCP Server, erwartet am UDP-Port 67 auf Client-Anfragen. Wenn ein Client erstmals eine IP-Adresse benötigt, schickt er eine DHCPDISCOVER-Nachricht (mit seiner MAC-Adresse) als Netzwerk-Broadcast an die verfügbaren DHCP-Server. Dieser Broadcast hat als Absender-IP-Adresse 0.0.0.0 und als Zieladresse 255.255.255.255, da der Absender noch keine IP-Adresse besitzt und seine Anfrage „an alle“ richtet. Dabei ist der UDP-Quell Port 68 und der UDP-Ziel Port 67. Sollte im Seriellen Monitor gerade nichts zu sehen sein, einfach mal das Wlan vom Handy Aus- und Einschalten. Oder irgendein anderes Wlan-fähiges Gerät (Esp, Raspi, etc.) in Betrieb nehmen.
UDP_Broadcast_DHCP_Server.ino

// ****************************************************************
// Sketch Esp8266 UDP Broadcast DHCP Server
// created: Jens Fleischer, 2021-01-31
// last mod: Jens Fleischer, 2021-01-31
// For more information visit: https://fipsok.de
// ****************************************************************
// Hardware: Esp8266
// Software: Esp8266 Arduino Core 2.7.0 - 2.7.4
// Getestet auf: Nodemcu, Wemos D1 Mini Pro
/******************************************************************
  Copyright (c) 2021 Jens Fleischer. All rights reserved.

  This file is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.
  This file is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.
*******************************************************************/

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>

const char* ssid = "Netzwerkname";                       // Darf bis zu 32 Zeichen haben.
const char* password = "PasswortvomNetzwerk";            // Mindestens 8 Zeichen jedoch nicht länger als 64 Zeichen.

constexpr uint16_t PORT = 67;                            // UDP Port für DHCP Server.

WiFiUDP Udp;

void setup() {
  Serial.begin(115200);
  delay(100);
  Serial.printf("\nSketchname: %s\nBuild: %s\t\tIDE: %d.%d.%d\n%s\n\n",
                (__FILE__), (__TIMESTAMP__), ARDUINO / 10000, ARDUINO % 10000 / 100, ARDUINO % 100 / 10 ? ARDUINO % 100 : ARDUINO % 10, ESP.getFullVersion().c_str());

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print('.');
    delay(500);
  }
  Serial.println("\nVerbunden! Esp8266 IP: " + WiFi.localIP().toString());
  Serial.printf("UDP DHCP Server lauscht am Port: %d\n", PORT);
  Udp.begin(PORT);
}

void loop() {
  uint16_t packetSize = Udp.parsePacket();               // Eingehende UDP-Pakete empfangen.
  if (packetSize) {                                      // Prüfen ob UDP-Pakete empfangen wurden.
    char packetBuffer[packetSize];                       // Puffer für eingehendes Paket.
    Udp.read(packetBuffer, sizeof(packetBuffer));        // Einlesen des UDP Paket in den Bufffer.
    Serial.printf("\n\nDHCP Packet Größe: %d Byte\n", packetSize);
    Serial.println("Ausgabe des empfangenen Packets als HEX:");
    for (auto& c : packetBuffer) Serial.printf("%02X ", c);
    Serial.println("\nAusgabe der druckbaren ASCII Zeichen:");
    for (char& c : packetBuffer) if (c > 0x1F && c < 0x7F) Serial.printf("%c ", c);
  }
}
			

UDP Mixed All

Die Zusammenfassung aller Möglichkeiten am Beispiel eines Programmpaares für Client (Sender) und Server (Empfänger). In beiden Sketchen wird ausgewertet ob das eingehende Paket per Unicast, Multicast oder Broadcast gesendet wurde. Der UDP Client sendet nach dem Neustart aller 15 Sekunden ein Paket an den Server, nach einer Ruhephase von 3,5 Minuten geht es von vorn los. Der UDP Server sendet für jedes empfangene Paket eine Unicast Antwort-Nachricht an den Client. Wodurch dem Client nun die lokale IP des Servers bekannt ist und er auch Unicast Nachrichten zum Server senden kann. In der Ruhephase des UDP Client darf gerne der "Packet Sender" zum Einsatz kommen, um nochmal alle Adressierungsschemata mit diesem durchzugehen.
Unicast
Als Ziel wird die lokale IP-Adresse des Gerätes genommen.
Multicast
Als Ziel wird eine IP-Adresse im Bereich 224.0.0.0 bis 239.255.255.255 ausgewählt.
Limited Broadcast
Als Ziel wird die IP-Adresse 255.255.255.255 angegeben.
Dieses Ziel liegt immer im eigenen lokalen Netz und wird direkt in einen Ethernet-Broadcast umgesetzt. Ein Limited Broadcast wird von einem Router nicht weitergeleitet.
Directed Broadcast
Die Adresse für einen Directed Broadcast lautet x.x.x.255.
Das Ziel sind die Teilnehmer eines bestimmten Netzes. Ein Directed Broadcast wird von einem Router weitergeleitet, falls Quell- und Zielnetz unterschiedlich sind.

UDP Mixed Sender

UDP_Mixed_All_Client.ino

// ****************************************************************
// Sketch Esp8266 UDP Mixed All Client
// created: Jens Fleischer, 2021-01-31
// last mod: Jens Fleischer, 2021-01-31
// For more information visit: https://fipsok.de
// ****************************************************************
// Hardware: Esp8266
// Software: Esp8266 Arduino Core 2.7.0 - 2.7.4
// Getestet auf: Nodemcu, Wemos D1 Mini Pro
/******************************************************************
  Copyright (c) 2021 Jens Fleischer. All rights reserved.

  This file is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.
  This file is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.
*******************************************************************/

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>

const char* ssid = "Netzwerkname";                       // Darf bis zu 32 Zeichen haben.
const char* password = "PasswortvomNetzwerk";            // Mindestens 8 Zeichen jedoch nicht länger als 64 Zeichen.

WiFiUDP Udp;

IPAddress multicastIP(230, 120, 10, 1);
IPAddress broadcastDirectedIP;
IPAddress broadcastLimitedIP(255, 255, 255, 255);
constexpr uint16_t PORT = 8266;                          // lokaler UDP Port
char packetBuffer[UDP_TX_PACKET_MAX_SIZE + 1];           // Puffer für eingehendes Paket.

void setup() {
  Serial.begin(115200);
  delay(100);
  Serial.printf("\nSketchname: %s\nBuild: %s\t\tIDE: %d.%d.%d\n%s\n\n",
                (__FILE__), (__TIMESTAMP__), ARDUINO / 10000, ARDUINO % 10000 / 100, ARDUINO % 100 / 10 ? ARDUINO % 100 : ARDUINO % 10, ESP.getFullVersion().c_str());

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.printf("\nVerbunden mit: %s\n\n", WiFi.SSID().c_str());

  if (Udp.beginMulticast(WiFi.localIP(), multicastIP, PORT)) {
    broadcastDirectedIP = WiFi.localIP();
    broadcastDirectedIP[3] = 255;
    Serial.printf("Unicast Nachricht bei Ziel IP: %s:%d\n", WiFi.localIP().toString().c_str(), PORT);
    Serial.printf("Multicast Nachricht bei Ziel IP: %s:%d\n", multicastIP.toString().c_str(), PORT);
    Serial.printf("Broadcast Nachricht bei Ziel IP: %s:%d\n", broadcastDirectedIP.toString().c_str(), PORT);
    Serial.printf("Broadcast Nachricht bei Ziel IP: %s:%d\n", broadcastLimitedIP.toString().c_str(), PORT);
  }
  else {
    Serial.println("Fehler beim Beginn Multicast!");
  }
}

void loop() {
  sendUdp();
  readUdp();
}

void sendUdp() {
  static uint8_t secCounter;
  static uint32_t previousMillis;
  constexpr uint32_t INTERVAL (1000);
  if (millis() - previousMillis >= INTERVAL) {
    previousMillis += INTERVAL;
    switch (++secCounter) {
      case 15:
        Udp.beginPacketMulticast(multicastIP, PORT, WiFi.localIP(), 1);
        Udp.print("D1 Mini Pro sendet UDP Multicast!");
        Udp.endPacket();
        break;
      case 30:
        Udp.beginPacket(Udp.remoteIP(), PORT);
        Udp.print("D1 Mini Pro sendet UDP Unicast!");
        Udp.endPacket();
        break;        
      case 45:
        Udp.beginPacketMulticast(broadcastDirectedIP, PORT, WiFi.localIP(), 1);
        Udp.print("D1 Mini Pro sendet UDP Directed Broadcast!");
        Udp.endPacket();
        break;
      case 60:
        Udp.beginPacketMulticast(broadcastLimitedIP, PORT, WiFi.localIP(), 1);
        Udp.print("D1 Mini Pro sendet UDP Limited Broadcast!");
        Udp.endPacket();
        break;
      default:
        break;
    }
  }
}

void readUdp() {
  uint16_t packetSize = Udp.parsePacket();               // Eingehende UDP-Pakete empfangen.
  if (packetSize) {                                      // Prüfen ob UDP-Pakete empfangen wurden.
    Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE);      // Einlesen des UDP Paket in den Bufffer.
    packetBuffer[packetSize] = 0;                        // String Ende hinzufügen
    IPAddress destIP = Udp.destinationIP();              // Ziel IP speichern zum ermitteln des Typ der Übertragung.
    char str[19] = "Unicast";                            // Standard Typ Unicast
    if (destIP[0] >= 224 && destIP[0] <= 239) strcpy(str, "MultiCast");
    else if (destIP[0] == 255) strcpy(str, "Limited Broadcast");
    else if (destIP[3] == 255) strcpy(str, "Directed Broadcast");
    Serial.printf("\n********************************************************\nReceived %s to %s:%d from %s:%d\nSize: %d Bytes  Contents: %s\n",
                  str, Udp.destinationIP().toString().c_str(), Udp.localPort(), Udp.remoteIP().toString().c_str(), Udp.remotePort(), packetSize, packetBuffer);
  }
}
		

UDP Mixed Empfänger

UDP_Mixed_All_Server.ino

// ****************************************************************
// Sketch Esp8266 UDP Mixed All Server
// created: Jens Fleischer, 2021-01-31
// last mod: Jens Fleischer, 2021-01-31
// For more information visit: https://fipsok.de
// ****************************************************************
// Hardware: Esp8266
// Software: Esp8266 Arduino Core 2.7.0 - 2.7.4
// Getestet auf: Nodemcu, Wemos D1 Mini Pro
/******************************************************************
  Copyright (c) 2021 Jens Fleischer. All rights reserved.

  This file is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.
  This file is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.
*******************************************************************/

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>

const char* ssid = "Netzwerkname";                       // Darf bis zu 32 Zeichen haben.
const char* password = "PasswortvomNetzwerk";            // Mindestens 8 Zeichen jedoch nicht länger als 64 Zeichen.

WiFiUDP Udp;

IPAddress multicastIP(230, 120, 10, 1);
IPAddress broadcastDirectedIP;
IPAddress broadcastLimitedIP(255, 255, 255, 255);
constexpr uint16_t PORT = 8266;                          // lokaler UDP Port
char packetBuffer[UDP_TX_PACKET_MAX_SIZE + 1];           // Puffer für eingehendes Paket.

void setup() {
  Serial.begin(115200);
  delay(100);
  Serial.printf("\nSketchname: %s\nBuild: %s\t\tIDE: %d.%d.%d\n%s\n\n",
                (__FILE__), (__TIMESTAMP__), ARDUINO / 10000, ARDUINO % 10000 / 100, ARDUINO % 100 / 10 ? ARDUINO % 100 : ARDUINO % 10, ESP.getFullVersion().c_str());
  
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.printf("\nVerbunden mit: %s\n\n", WiFi.SSID().c_str());

  if (Udp.beginMulticast(WiFi.localIP(), multicastIP, PORT)) {
    broadcastDirectedIP = WiFi.localIP();
    broadcastDirectedIP[3] = 255;
    Serial.printf("Unicast Nachricht bei Ziel IP: %s:%d\n", WiFi.localIP().toString().c_str(), PORT);
    Serial.printf("Multicast Nachricht bei Ziel IP: %s:%d\n", multicastIP.toString().c_str(), PORT);
    Serial.printf("Broadcast Nachricht bei Ziel IP: %s:%d\n", broadcastDirectedIP.toString().c_str(), PORT);
    Serial.printf("Broadcast Nachricht bei Ziel IP: %s:%d\n", broadcastLimitedIP.toString().c_str(), PORT);
    Serial.println("\nSende eine Nachricht an alle mit der Multicast Ip!");
    Udp.beginPacketMulticast(multicastIP, PORT, WiFi.localIP(), 1);
    Udp.print("Nodemcu ist gestartet!");
    Udp.endPacket();
  }
  else {
    Serial.println("Fehler beim Beginn Multicast!");
  }
}

void loop() {
  uint16_t packetSize = Udp.parsePacket();               // Eingehende UDP-Pakete empfangen.
  if (packetSize) {                                      // Prüfen ob UDP-Pakete empfangen wurden.
    Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE);      // Einlesen des UDP Paket in den Bufffer.
    packetBuffer[packetSize] = 0;                        // String Ende hinzufügen.
    IPAddress destIP = Udp.destinationIP();              // Ziel IP speichern zum ermitteln des Typ der Übertragung.
    char str[19] = "Unicast";                            // Standard Typ Unicast
    if (destIP[0] >= 224 && destIP[0] <= 239) strcpy(str, "MultiCast");
    else if (destIP[0] == 255) strcpy(str, "Limited Broadcast");
    else if (destIP[3] == 255) strcpy(str, "Directed Broadcast");
    Serial.printf("\n********************************************************\nReceived %s to %s:%d from %s:%d\nSize: %d Bytes  Contents: %s\n",
                  str, Udp.destinationIP().toString().c_str(), Udp.localPort(), Udp.remoteIP().toString().c_str(), Udp.remotePort(), packetSize, packetBuffer);
    Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());   // Antwort an den Client senden.
    Udp.printf("Nodemcu bekam %d Bytes Paket", packetSize);
    Udp.endPacket();
  }
}
		

Anmerkung

Ich habe das Thema UDP lange vor mir her geschoben gar stiefmütterlich behandelt. Nun wurde es aber mal Zeit es mit der erforderlichen tiefe anzugehen. Diese Webseite, hat wieder zu wenig Text um als Tutorial durchzugehen, dient mir als Nachschlagewerk, welches ich gerne mit euch teilen möchte. Es würde mich freuen, wenn es den ein- oder anderen hilft das „User Datagram Protocol“ erfolgreich in eigene Projekte zu Integrieren.
5 Kommentare - Kommentar eintragen
DL2ZAP ✪ ✪ ✪ 03.12.2023
DANKE für die Erklärung.
endlich verstehe ich, was es mit den verschiedenen Ip-Adressen bei Unicast / Multicast /Broadcast auf sich hat.
Mike

Antwort:
Danke, für dein Feedback.

Gruß Fips
Martin W. ✪ ✪ ✪ 03.11.2023
Hallo. Super auf den Punkt gebracht. eine sehr feine Anleitung um die ESP8266 und UDP kombinieren zu können. Danke sehr

Antwort:
Danke, für dein Feedback.

Gruß Fips
andreas ✪ ✪ ✪ 30.03.2023
hallo, gute zusammenfassung und die hat sicher noch länger gültigkeit ich arbeite mit einem ESP32 und frage mich, ob "WiFiUdp" oder "AsyncUDP" die bessere wahl ist. bei der async variante habe ich lange versucht einen struct über UDP zu übertragen, was mir aber nicht gelungen ist. letztendlich mache ich es mit einem JSON stream, was auch funktioniert. wie siehst du das? sg andreas

Antwort:
Mit dem Esp32 "AsyncUDP" habe ich noch nicht gearbeitet.

Gruß Fips
Klaus ✪ ✪ ✪ 19.06.2021
Hallo, ich bin auf der Suche zum Thema "Puschbullet über ESP8266" auf deine Seite gekommen und muss dir ein Kompliment machen. Sehr schöne Homepage mit tollem Code und prima Erklärungen.
Vielen Dank für deine Mühe und schöne Grüße aus Recklinghausen

Antwort:
Danke, für dein Feedback.

Gruß Fips
Konrad ❘ 21.03.2021
Hi,

Mit Interesse habe ich diesen Ansatz mit UDP gelesen, wenn auch noch nicht umgesetzt.

Bisher habe ich mit meinen ESPs für einen direkten Versand von "kleinen" Informationen (wie z.B. Temperaturen, etc.) an andere ESPs eher ESP NOW für so was verwendet. Allerdings stelle ich immer wieder fest, dass es manchmal nicht so "solide" läuft, wie ich mir es wünschen würde; - was aber auch an mir selbst liegen kann.

Was ist nun der grundsätzliche Vor- bzw. Nachteil von UDP zu ESP NOW? Danke schon mal Vorab.

Von einem ziemlichen Laien im Süden der Republik

Konrad


Antwort:
Zu ESP-NOW kann ich nichts sagen.
Mit UDP bleibst du im Standart und kannst auch mit Geräten ausserhalb des Esp-Kosmos kommunizieren.

Gruß Fips
Kommentar eintragen

*