ESP32 und Arduino

ESP8266 MQTT Tutorial: NodeMCU mit einem Cloud-Broker verbinden (unverschlüsselt und TLS)

Verbinden Sie einen ESP8266 NodeMCU mit PubSubClient mit einem MQTT-Broker, senden Sie JSON-Telemetrie, steuern Sie die Onboard-LED und ergänzen Sie anschließend TLS mit BearSSL, ohne den knappen Heap zu überfordern.

NodeMCU-ESP8266-Board auf einem Steckbrett, das ESP8266-MQTT-Nachrichten an einen Cloud-Broker sendet
Probieren Sie es auf Ihrem eigenen MQTT-Broker ausHolen Sie sich im Free-Tarif einen privaten, verwalteten MQTT-Broker und starten Sie mit fertigen Codebeispielen.
Kostenlos testen Codebeispiele Keine Kreditkarte erforderlich

Der ESP8266 ist nach wie vor einer der günstigsten Wege, einen Sensor ins WLAN zu bringen, und ESP8266-MQTT-Projekte passen perfekt zu seinem kleinen Ressourcenbedarf. In diesem Tutorial verbinden Sie einen NodeMCU oder Wemos D1 mini mit PubSubClient mit einem Broker, veröffentlichen JSON-Telemetrie, schalten die Onboard-LED von Ihrem Computer aus und steigen danach auf TLS um, ohne dass der Speicher ausgeht.

Was Sie brauchen

  • Einen NodeMCU v2/v3, Wemos D1 mini oder ein beliebiges ESP8266-Board mit USB.
  • Arduino IDE 2.x mit dem Board-Paket "esp8266 by ESP8266 Community" (tragen Sie https://arduino.esp8266.com/stable/package_esp8266com_index.json unter Datei → Einstellungen → Zusätzliche Boardverwalter-URLs ein).
  • Die Bibliothek PubSubClient von Nick O'Leary aus dem Bibliotheksverwalter.
  • Die Mosquitto-Kommandozeilentools auf Ihrem Computer zum Testen.
  • Ein 2,4-GHz-WLAN. Der ESP8266 unterstützt kein 5 GHz.

Für die ersten Schritte verwenden Sie broker.connectmq.com, den von ConnectMQ betriebenen kostenlosen öffentlichen MQTT-Broker. Er akzeptiert anonyme Clients auf Port 1883 mit jeder nicht leeren, eindeutigen Client ID. Betrachten Sie ihn als öffentliches Schwarzes Brett: Alles, was Sie dort veröffentlichen, können andere mitlesen. Der öffentliche MQTT-Broker ist deshalb für Tests und Prototypen gedacht, nicht für Produktionsdaten.

Wichtige Board-Einstellungen

Bevor Sie Code schreiben, legen Sie im Menü Werkzeuge Folgendes fest:

Einstellung Empfohlener Wert Warum
Board NodeMCU 1.0 (ESP-12E Module) oder LOLIN(WEMOS) D1 mini Korrektes Flash-Layout und Pin-Namen
CPU Frequency 160 MHz für TLS, sonst 80 MHz TLS-Handshakes sind bei 160 MHz deutlich schneller
SSL Support All SSL ciphers (Standard) oder Basic SSL ciphers Basic spart Flash und funktioniert trotzdem mit modernen Brokern
lwIP Variant v2 Lower Memory Lässt mehr Heap für Ihren Sketch übrig
Upload Speed 921600 (bei Upload-Fehlern auf 115200 senken) Schnellere Iteration

Schritt 1: Ihr erster ESP8266-MQTT-Sketch

Der folgende Sketch verwendet die Onboard-LED an GPIO2 (LED_BUILTIN), die bei den meisten Modulen active-low ist. Er veröffentlicht alle fünf Sekunden Uptime, Signalstärke und freien Heap und wartet auf die Befehle ON oder OFF.

#include <ESP8266WiFi.h>
#include <PubSubClient.h>

const char* WIFI_SSID     = "YOUR_WIFI";
const char* WIFI_PASSWORD = "YOUR_WIFI_PASSWORD";

const char* MQTT_HOST = "broker.connectmq.com";
const uint16_t MQTT_PORT = 1883;

char deviceId[24];
char topicTelemetry[64];
char topicLedSet[64];
char topicLedState[64];

WiFiClient netClient;
PubSubClient mqtt(netClient);

unsigned long lastPublish = 0;
unsigned long lastAttempt = 0;

void setLed(bool on) {
  digitalWrite(LED_BUILTIN, on ? LOW : HIGH);   // active-low
  mqtt.publish(topicLedState, on ? "ON" : "OFF", true);
}

void onMessage(char* topic, byte* payload, unsigned int length) {
  char msg[16];
  unsigned int n = length < sizeof(msg) - 1 ? length : sizeof(msg) - 1;
  memcpy(msg, payload, n);
  msg[n] = '\0';
  Serial.printf("[%s] %s\n", topic, msg);

  if (strcmp(msg, "ON") == 0)  setLed(true);
  if (strcmp(msg, "OFF") == 0) setLed(false);
}

void connectWifi() {
  WiFi.mode(WIFI_STA);
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  Serial.print("Wi-Fi");
  while (WiFi.status() != WL_CONNECTED) {
    delay(300);
    Serial.print(".");
  }
  Serial.printf(" connected, IP %s\n", WiFi.localIP().toString().c_str());
}

bool connectMqtt() {
  if (mqtt.connect(deviceId, nullptr, nullptr, topicLedState, 1, true, "offline")) {
    Serial.println("MQTT connected");
    mqtt.subscribe(topicLedSet, 1);
    setLed(false);
    return true;
  }
  Serial.printf("MQTT failed, rc=%d\n", mqtt.state());
  return false;
}

void setup() {
  Serial.begin(115200);
  pinMode(LED_BUILTIN, OUTPUT);

  // Eindeutige ID aus der Chip-ID, z. B. esp8266-3f2a1b
  snprintf(deviceId, sizeof(deviceId), "esp8266-%06x", ESP.getChipId());
  snprintf(topicTelemetry, sizeof(topicTelemetry), "connectmq/demo/%s/telemetry", deviceId);
  snprintf(topicLedSet,    sizeof(topicLedSet),    "connectmq/demo/%s/led/set", deviceId);
  snprintf(topicLedState,  sizeof(topicLedState),  "connectmq/demo/%s/led/state", deviceId);
  Serial.printf("\nDevice ID: %s\n", deviceId);

  connectWifi();
  mqtt.setServer(MQTT_HOST, MQTT_PORT);
  mqtt.setCallback(onMessage);
  mqtt.setKeepAlive(30);
}

void loop() {
  if (WiFi.status() != WL_CONNECTED) connectWifi();

  if (!mqtt.connected()) {
    if (millis() - lastAttempt > 5000) {
      lastAttempt = millis();
      connectMqtt();
    }
    return;
  }
  mqtt.loop();

  if (millis() - lastPublish > 5000) {
    lastPublish = millis();
    char payload[96];
    snprintf(payload, sizeof(payload), "{\"uptime\":%lu,\"rssi\":%d,\"heap\":%u}",
             millis() / 1000, WiFi.RSSI(), ESP.getFreeHeap());
    mqtt.publish(topicTelemetry, payload);
  }
}

Öffnen Sie den seriellen Monitor mit 115200 Baud, notieren Sie die Geräte-ID und abonnieren Sie dann von Ihrem Computer aus (ersetzen Sie die ID durch Ihre eigene):

mosquitto_sub -h broker.connectmq.com -p 1883 -i laptop-3f2a1b -t "connectmq/demo/esp8266-3f2a1b/#" -v

Schalten Sie die LED:

mosquitto_pub -h broker.connectmq.com -p 1883 -i ctl-3f2a1b -t "connectmq/demo/esp8266-3f2a1b/led/set" -m ON

Das Topic led/state ist retained, sodass jeder neue Subscriber sofort erfährt, ob die LED an ist, und der Last Will setzt es auf offline, wenn das Board die Stromversorgung verliert.

Schritt 2: Das Speicherbudget des ESP8266 verstehen

Sobald der unverschlüsselte Sketch läuft, prüfen Sie den veröffentlichten heap-Wert. Ein einfacher Sketch lässt in der Regel komfortabel viel Heap frei, doch TLS ändert das Bild. Eine BearSSL-Session mit Standardpuffern benötigt einen großen zusammenhängenden Speicherblock für Empfangs- und Sendepuffer sowie für die Zertifikatsprüfung, und der ESP8266 hat nur einen Bruchteil des RAMs eines ESP32.

Praktische Folgen:

  • Halten Sie den PubSubClient-Puffer so klein, wie Ihre Nachrichten es zulassen. Ein setBufferSize(4096) "für alle Fälle" kann den Unterschied zwischen einem funktionierenden und einem fehlschlagenden Handshake ausmachen.
  • Vermeiden Sie in lange laufenden Sketches den intensiven Einsatz der Klasse String; wiederholte Allokationen fragmentieren den Heap, und der TLS-Handshake kann Tage später scheitern, obwohl der freie Heap gut aussieht. ESP.getMaxFreeBlockSize() zeigt den größten zusammenhängenden Block, und genau diese Zahl zählt.
  • Bauen Sie JSON mit snprintf oder einem ArduinoJson-Dokument fester Größe statt mit String-Verkettung.

Benötigen Sie regelmäßig große Payloads, lesen Sie PubSubClient-Puffergröße für Streaming-Techniken, die ohne große Puffer auskommen.

Schritt 3: ESP8266 MQTT über TLS

Im Produktivbetrieb sollte Ihr Gerät sich über TLS auf Port 8883 mit eigenen Zugangsdaten mit einem privaten Broker verbinden. Bei einem verwalteten MQTT-Broker wie ConnectMQ erhalten Sie Benutzername, Passwort und Client ID aus dem Portal. Das Serverzertifikat wird von Let's Encrypt ausgestellt, Sie vertrauen also dem Root-Zertifikat ISRG Root X1.

Der ESP8266-Core verwendet BearSSL. Anders als beim ESP32 werden die Gültigkeitsdaten des Zertifikats geprüft, daher muss die Uhr vor dem Handshake stimmen.

#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#include <PubSubClient.h>
#include <time.h>

// ISRG Root X1 (Let's-Encrypt-Root), vollständiges PEM einfügen
static const char ROOT_CA[] PROGMEM = R"EOF(
-----BEGIN CERTIFICATE-----
...ISRG Root X1...
-----END CERTIFICATE-----
)EOF";

BearSSL::X509List trustAnchors(ROOT_CA);
BearSSL::WiFiClientSecure tlsClient;
PubSubClient mqtt(tlsClient);

void syncClock() {
  configTime(0, 0, "pool.ntp.org", "time.nist.gov");
  Serial.print("Waiting for NTP");
  time_t now = time(nullptr);
  while (now < 1700000000) {      // ein beliebiger Zeitstempel weit in der Vergangenheit
    delay(250);
    Serial.print(".");
    now = time(nullptr);
  }
  Serial.println(" done");
}

void setupTls() {
  syncClock();
  tlsClient.setTrustAnchors(&trustAnchors);
  // Optional: kleinere Puffer, wenn der Server Max Fragment Length unterstützt
  if (tlsClient.probeMaxFragmentLength("broker.connectmq.com", 8883, 1024)) {
    tlsClient.setBufferSizes(1024, 1024);
  }
  mqtt.setServer("broker.connectmq.com", 8883);
}

bool connectMqtt() {
  return mqtt.connect("YOUR_CLIENT_ID", "YOUR_USERNAME", "YOUR_PASSWORD");
}

Rufen Sie setupTls() in setup() auf, nachdem das WLAN verbunden ist. Stellen Sie die CPU-Frequenz auf 160 MHz; der erste Handshake kann bei 80 MHz spürbar dauern, und Ihr Watchdog mag kein langsames connect() in einer ausgelasteten Schleife.

Schritt 4: Batteriebetriebener ESP8266 mit MQTT und Deep Sleep

Viele ESP8266-Sensoren laufen mit Batterie und müssen nur alle paar Minuten berichten. Das Funkmodul ist mit Abstand der größte Stromverbraucher, daher lautet das erfolgreiche Muster: aufwachen, verbinden, veröffentlichen, trennen, schlafen. Deep Sleep erfordert beim ESP8266 eine Hardwareverbindung zwischen GPIO16 (D0 beim NodeMCU und D1 mini) und dem RST-Pin, weil der Chip durch einen Reset aufwacht. Trennen Sie diese Leitung beim Hochladen, falls Ihr Board sich beim Flashen merkwürdig verhält.

void publishAndSleep() {
  connectWifi();
  mqtt.setServer(MQTT_HOST, MQTT_PORT);
  if (mqtt.connect(deviceId)) {
    char payload[64];
    snprintf(payload, sizeof(payload), "{\"a0\":%d,\"rssi\":%d}", analogRead(A0), WiFi.RSSI());
    mqtt.publish(topicTelemetry, payload);
    // dem Stack kurz Zeit geben, das Paket zu senden, bevor wir das Funkmodul abschalten
    for (int i = 0; i < 10; i++) { mqtt.loop(); delay(10); }
    mqtt.disconnect();
  }
  ESP.deepSleep(5 * 60 * 1000000ULL);   // 5 Minuten, in Mikrosekunden
}

Rufen Sie publishAndSleep() am Ende von setup() auf und lassen Sie loop() leer. Einige praktische Hinweise: Ein TLS-Handshake bei jedem Aufwachen kostet spürbar mehr Zeit und Energie als unverschlüsseltes MQTT. Wägen Sie daher die Sicherheitsanforderung gegen die Akkulaufzeit ab und ziehen Sie mit TLS längere Schlafintervalle in Betracht. Verwenden Sie für den letzten Messwert eine Retained Message, damit Dashboards, die zwischen zwei Aufwachphasen geöffnet werden, trotzdem einen Wert sehen. Und nutzen Sie bei schlafenden Geräten keinen Last Will für die Anwesenheitserkennung; ein sauberes disconnect() löst ihn nie aus, und ein Status "offline" wäre ohnehin irreführend.

Fehlerbehebung bei ESP8266-MQTT-Problemen

  1. rc=-2 bei TLS, aber auf 1883 alles in Ordnung: Uhr nicht synchronisiert, falsches Root-Zertifikat oder nicht genug zusammenhängender Heap. Geben Sie tlsClient.getLastSSLError() aus, um die Ursache von BearSSL zu sehen. Unser Leitfaden zu PubSubClient rc=-2 behandelt jeden Code.
  2. Zufällige Resets (wdt reset): Etwas blockiert zu lange. Setzen Sie nie lange delay()-Aufrufe in den MQTT-Callback und rufen Sie in langen Schleifen yield() auf.
  3. Board tritt dem WLAN nie bei: reines 5-GHz-Netz, falsches Passwort oder ein Captive Portal in einem Gastnetz.
  4. Board trennt sich, sobald sich ein zweites Board verbindet: Beide Boards verwenden dieselbe Client ID. Der obige Ansatz mit der Chip-ID verhindert das.
  5. Nachrichten über ein paar hundert Bytes verschwinden: der Standardpuffer von PubSubClient mit 256 Bytes. Vergrößern Sie ihn maßvoll.
  6. Nachrichten kommen nach Stunden nicht mehr an: Heap-Fragmentierung. Beobachten Sie getMaxFreeBlockSize() über die Zeit.

ESP8266 oder ESP32?

Der ESP8266 ist für Einzelsensor-Knoten, Relais und kleine Displays völlig ausreichend, besonders bei unverschlüsseltem MQTT oder gelegentlichen TLS-Verbindungen. Brauchen Sie viele gleichzeitige TLS-Sessions, Bluetooth, mehr GPIOs oder Platz für OTA-Updates plus große Payloads, wechseln Sie zum ESP32. Das gilt auch für Nachrüstknoten in der Fertigung, wo Werksnetze TLS und Zugangsdaten pro Gerät meist vorschreiben. Unser Vergleich ESP32 vs. ESP8266 geht die Abwägungen durch, und das ESP32-IoT-Tutorial ist der nächste Schritt, wenn Sie diesem Board entwachsen.

Betreiben Sie Ihre ESP8266-Flotte auf ConnectMQ

Sobald der Prototyp funktioniert, ziehen Sie ihn auf einen Cloud-MQTT-Broker mit privaten Zugangsdaten und TLS um. ConnectMQ unterstützt MQTT 3.1.1 und 5.0 über TCP 1883 und TLS 8883, und das Portal enthält einen MQTT-Client im Browser sowie einen Live-Topic-Explorer, mit dem Sie prüfen können, was Ihre Boards veröffentlichen. Erstellen Sie einen kostenlosen Serverless Broker unter app.connectmq.com, ohne Kreditkarte.

Häufig gestellte Fragen

Kann der ESP8266 MQTT über TLS nutzen?

Ja. Der ESP8266-Core bringt BearSSL mit, und PubSubClient funktioniert mit BearSSL::WiFiClientSecure. Synchronisieren Sie zuerst die Uhr, vertrauen Sie dem Root-Zertifikat des Brokers und halten Sie den übrigen Speicherverbrauch moderat.

Welchen Pin nutzt die Onboard-LED des NodeMCU?

Bei den meisten NodeMCU- und Wemos-D1-mini-Boards ist es GPIO2 (LED_BUILTIN, auch mit D4 beschriftet), und die LED ist active-low: Wer LOW schreibt, schaltet sie ein.

Kann ich den ESP8266 mit MQTT 5 nutzen?

PubSubClient unterstützt nur MQTT 3.1.1, was für die meisten Sensoren genügt. Der Broker kann auf denselben Topics trotzdem MQTT-5-Clients wie Dashboards und Backends bedienen.

Warum braucht mein ESP8266 für TLS die Uhrzeit?

BearSSL prüft, ob das Serverzertifikat innerhalb seines Gültigkeitszeitraums liegt. Ohne korrekte Uhr glaubt das Gerät, es sei 1970, und lehnt das Zertifikat ab.

Verwandte Artikel

ESP32 NTP MQTT Zeitstempel: genaue Uhrzeit in jeder Nachricht

Synchronisieren Sie die ESP32-Uhr per NTP, formatieren Sie Zeitstempel in ISO 8601 und Epoch-Millisekunden und hängen Sie sie an MQTT-Payloads, damit Messwerte ihren echten Erfassungszeitpunkt behalten, auch wenn sie verspätet veröffentlicht werden.

8 Min. Lesezeit

Alle Artikel →

Ihr privater MQTT-Broker ist nur wenige Klicks entfernt

Konto anlegen, Broker-Zugangsdaten erhalten und das erste Gerät verbinden — ohne Server, die installiert, gepatcht oder skaliert werden müssen.