Broker-Tests

ESP32-MQTT-Verbindung Schritt für Schritt testen

ESP32 verbindet sich nicht mit MQTT? Teste WLAN, DNS, TCP-Port, Client-ID, Zugangsdaten und Puffergröße einzeln – mit Diagnose-Sketch und seriellen Logs.

Aktualisiert · 8 Min. Lesezeit

ESP32-MQTT-Verbindung Schritt für Schritt testen

Wenn ein ESP32 nicht mit einem MQTT-Broker reden will, zeigt der serielle Monitor meist nur eine wenig hilfreiche Zeile: failed, rc=-2 try again in 5 seconds. Am schnellsten kommst du weiter, wenn du die Verbindung Schicht für Schicht testest – WLAN, DNS, TCP-Port, MQTT-Handshake, dann Publish – und bei der ersten Schicht stoppst, die fehlschlägt.

Dieser Guide liefert dir einen Diagnose-Sketch für den Arduino-Core (ESP32-Core 3.x mit PubSubClient 2.8), der genau das tut, erklärt jedes Ergebnis und zeigt, wie du von der Broker-Seite aus bestätigst, dass das Board wirklich da ist.

Die Checkliste im Überblick

SchrittWas schiefgehen kannWoran du es erkennst
1. Serielles LogFalsche Baudrate, gar kein LogZeichensalat oder Stille im Monitor
2. WLANFalsche SSID/Passwort, 5-GHz-Netz, schwaches SignalWiFi.status() erreicht nie WL_CONNECTED (3)
3. DNSKein DNS-Server per DHCP, Tippfehler im HosthostByName schlägt fehl
4. TCP-PortFirewall, falscher Port, TLS-Port mit normalem Clientrc=-2 von PubSubClient
5. MQTT CONNECTDoppelte Client-ID, falsche Zugangsdaten, ACLrc=2, rc=4, rc=5
6. PublishPaket größer als der Pufferpublish() liefert false
7. Verbunden bleibenloop() wird nicht aufgerufen, Keep-Alive zu kurzNach einer Weile rc=-3

Schritt 1: ein lesbares serielles Log

Stelle den Monitor auf dieselbe Geschwindigkeit wie Serial.begin() – 115200 ist üblich. Setze in der Arduino IDE außerdem Tools → Core Debug Level auf Info oder Verbose: Dann gibt der ESP32-Core WLAN-Events und TLS-Fehler aus, die dein eigener Sketch nie sieht. In PlatformIO nutzt du monitor_speed = 115200 und build_flags = -DCORE_DEBUG_LEVEL=4.

Schritte 2–6: der Diagnose-Sketch

Flashe diesen Sketch, bevor du deine eigentliche Firmware anfasst. Er prüft jede Schicht der Reihe nach und gibt genau aus, wo er hängen bleibt.

esp32_mqtt_check.ino
#include <WiFi.h>
#include <PubSubClient.h>

const char* WIFI_SSID = "your-ssid";
const char* WIFI_PASS = "your-wifi-password";
const char* MQTT_HOST = "broker.connectmq.com";
const uint16_t MQTT_PORT = 1883;
const char* MQTT_USER = "username";   // nullptr, wenn der Broker anonymen Zugriff erlaubt
const char* MQTT_PASS = "password";

WiFiClient net;
PubSubClient mqtt(net);
String clientId;

bool check() {
  Serial.println("\n[1] Wi-Fi");
  WiFi.mode(WIFI_STA);
  WiFi.begin(WIFI_SSID, WIFI_PASS);
  unsigned long t0 = millis();
  while (WiFi.status() != WL_CONNECTED && millis() - t0 < 20000) { delay(250); Serial.print('.'); }
  if (WiFi.status() != WL_CONNECTED) {
    Serial.printf("\nWi-Fi failed, status=%d\n", WiFi.status());
    return false;
  }
  Serial.printf("\nIP %s  gateway %s  RSSI %d dBm\n", WiFi.localIP().toString().c_str(),
                WiFi.gatewayIP().toString().c_str(), WiFi.RSSI());

  Serial.println("[2] DNS");
  IPAddress ip;
  if (!WiFi.hostByName(MQTT_HOST, ip)) { Serial.println("DNS lookup failed"); return false; }
  Serial.printf("%s -> %s\n", MQTT_HOST, ip.toString().c_str());

  Serial.println("[3] TCP port");
  if (!net.connect(ip, MQTT_PORT)) { Serial.println("TCP connect failed"); return false; }
  Serial.println("TCP OK");
  net.stop();

  Serial.println("[4] MQTT CONNECT");
  clientId = "esp32-" + WiFi.macAddress();
  clientId.replace(":", "");
  mqtt.setServer(MQTT_HOST, MQTT_PORT);
  mqtt.setBufferSize(1024);
  mqtt.setKeepAlive(30);
  if (!mqtt.connect(clientId.c_str(), MQTT_USER, MQTT_PASS)) {
    Serial.printf("MQTT failed, rc=%d\n", mqtt.state());
    return false;
  }
  Serial.printf("MQTT OK as %s\n", clientId.c_str());

  Serial.println("[5] PUBLISH");
  String topic = "testmqtt/esp32-check/" + clientId + "/hello";
  bool ok = mqtt.publish(topic.c_str(), "ESP32 connection test passed");
  Serial.printf("publish to %s: %s\n", topic.c_str(), ok ? "OK" : "FAILED");
  return ok;
}

void setup() {
  Serial.begin(115200);
  delay(1000);
  Serial.println(check() ? "\nALL CHECKS PASSED" : "\nCHECK FAILED - see the last step above");
}

void loop() {
  mqtt.loop();
}

Die Ergebnisse lesen

WLAN-Statuscodes

statusBedeutungLösung
1 WL_NO_SSID_AVAILNetz nicht gefundenSSID-Schreibweise prüfen; sicherstellen, dass auf 2,4 GHz gesendet wird
4 WL_CONNECT_FAILEDAbgelehnt, meist falsches PasswortPasswort neu eingeben; reine WPA3-Netze brauchen ggf. den WPA2/WPA3-Mischmodus
6 WL_DISCONNECTEDVersucht es noch oder abgebrochenNäher heran; ein RSSI unter etwa -80 dBm ist unzuverlässig

Ein guter RSSI liegt ungefähr zwischen -50 und -70 dBm. Wenn das WLAN verbindet, später aber abbricht, lies ESP32-WLAN- und MQTT-Verbindungsabbrüche.

DNS und TCP

DNS lookup failed bedeutet, dass das Board per DHCP keinen brauchbaren DNS-Server bekommen hat oder der Hostname falsch ist. Prüfe denselben Namen von einem Laptop im gleichen Netz mit nslookup broker.connectmq.com. Als vorübergehender Test kannst du per IP verbinden, aber so solltest du nicht ausliefern.

TCP connect failed (und rc=-2 in deiner eigenen Firmware) bedeutet, dass auf diesem Host und Port nichts geantwortet hat. Häufige Ursachen: ein Gastnetz oder eine Firmen-Firewall, die 1883 blockiert, ein Tippfehler im Port oder Port 8883 mit einem normalen WiFiClient – TLS-Ports brauchen WiFiClientSecure und ein CA-Zertifikat, wie in ESP32 MQTT über TLS gezeigt. Bestätige das von einem Laptop im selben WLAN mit nc -vz broker.connectmq.com 1883.

Rückgabecodes von PubSubClient

rcKonstanteÜbliche Ursache
-4MQTT_CONNECTION_TIMEOUTKein CONNACK rechtzeitig oder Keep-Alive abgelaufen
-3MQTT_CONNECTION_LOSTVerbindung abgebrochen; loop() wird zu selten aufgerufen
-2MQTT_CONNECT_FAILEDTCP-Verbindung fehlgeschlagen (siehe oben)
-1MQTT_DISCONNECTEDSauber getrennt / nie verbunden
1MQTT_CONNECT_BAD_PROTOCOLBroker akzeptiert MQTT 3.1.1 nicht
2MQTT_CONNECT_BAD_CLIENT_IDClient-ID abgelehnt (leer, zu lang, ungültige Zeichen)
3MQTT_CONNECT_UNAVAILABLEBroker nicht verfügbar
4MQTT_CONNECT_BAD_CREDENTIALSFalscher Benutzername oder falsches Passwort
5MQTT_CONNECT_UNAUTHORIZEDNicht autorisiert – Zugangsdaten fehlen oder Client nicht erlaubt

Positive Werte sind die CONNACK-Antwort des Brokers selbst – das Netzwerk funktioniert also, es bleibt nur die Konfiguration. Die Reason-Code-Referenz listet die passenden MQTT-Codes, und PubSubClient verbindet nicht geht auf jeden einzelnen tiefer ein.

publish() liefert false

Der Standardpuffer von PubSubClient hat 256 Bytes und muss das ganze Paket fassen: Header, Topic und Payload. Ein JSON-Payload von 200 Bytes auf einem langen Topic überschreitet das bereits, und publish() gibt einfach false zurück, ohne dass beim Broker etwas ankommt. Rufe setBufferSize() vor dem Verbinden auf; der Paketgrößen-Rechner zeigt dir, wie groß ein Paket wirklich ist.

Schritt 7: verbunden bleiben

mqtt.loop() muss häufig laufen – mindestens mehrmals pro Keep-Alive-Intervall. Ein delay(60000) in loop() oder ein blockierendes Auslesen eines Sensors führt garantiert nach etwa anderthalb Keep-Alive-Perioden zu rc=-3, weil der Broker nie ein PINGREQ erhält. Ersetze lange Delays durch millis()-Timer und verbinde dich mit Backoff neu, statt in einer while (!mqtt.connected())-Schleife zu blockieren.

Von der Broker-Seite bestätigen

Eine serielle Zeile mit „OK“ ist die Meinung des Geräts. Prüfe es unabhängig: Öffne den Online-MQTT-Client, verbinde dich mit demselben Broker und abonniere testmqtt/esp32-check/#. Setze das Board zurück, und die Hello-Nachricht sollte innerhalb weniger Sekunden ankommen. Im Terminal sieht derselbe Check so aus:

Auf die Testnachricht des ESP32 warten
mosquitto_sub -h broker.connectmq.com -p 1883 \
  -u "$MQTT_USER" -P "$MQTT_PASS" \
  -t 'testmqtt/esp32-check/#' -v

Im Browser auf deinen ESP32 warten

Die meisten MQTT-Probleme mit dem ESP32 sind gar keine MQTT-Probleme – es sind WLAN-, DNS- oder Port-Probleme hinter einem einzigen Rückgabecode. Teste eine Schicht nach der anderen, lies den genauen Status- oder rc-Wert und bestätige auf der Broker-Seite, bevor du zu deiner echten Firmware übergehst. Das vollständige Arduino-Setup findest du unter ESP32 MQTT mit Arduino.

Häufig gestellte Fragen

Was bedeutet "failed, rc=-2" auf einem ESP32?

Das ist MQTT_CONNECT_FAILED von PubSubClient: Die TCP-Verbindung zum Broker ließ sich nicht öffnen. Die Ursache liegt unterhalb von MQTT – kein WLAN, falscher Host oder Port, DNS-Fehler, eine Firewall oder ein TLS-Port mit einem normalen WiFiClient.

Warum verbindet sich mein ESP32, aber publish() liefert false?

Meist ist die Nachricht größer als der Puffer von PubSubClient, der standardmäßig 256 Bytes inklusive Topic und Header umfasst. Rufe vor dem Verbinden setBufferSize(1024) oder mehr auf und prüfe den Rückgabewert jedes Publish.

Unterstützt der ESP32 5-GHz-WLAN für MQTT?

Der klassische ESP32, S2, S3 und C3 haben nur 2,4-GHz-Funk und können keinem reinen 5-GHz-Netz beitreten. Neuere Chips wie der ESP32-C5 unterstützen Dualband. Prüfe dein genaues Modul, bevor du MQTT debuggst.