failed, rc=-2 im seriellen Monitor ist der häufigste PubSubClient-Fehler, und die Meldung allein verrät sehr wenig. PubSubClient rc=-2 bedeutet, dass die TCP- (oder TLS-)Verbindung zum Broker nie aufgebaut wurde. Das Problem liegt daher fast immer bei DNS, Port, Netzwerk oder Zertifikat, nicht bei MQTT selbst. Diese Anleitung entschlüsselt jeden State-Code von -4 bis 5 und liefert für jeden eine Lösung.
Woher der rc-Wert stammt
PubSubClient speichert das Ergebnis des letzten Verbindungsversuchs in einer internen Statusvariable, die Sie mit mqtt.state() auslesen. Die meisten Beispiel-Sketches geben sie aus, wenn connect() den Wert false zurückliefert:
if (!mqtt.connect(clientId)) {
Serial.print("failed, rc=");
Serial.println(mqtt.state());
}
Die Werte sind als Konstanten in PubSubClient.h definiert. Negative Werte stammen aus der Bibliothek und der Netzwerkschicht. Positive Werte sind die Return Codes, die der Broker in seinem CONNACK-Paket zurückgeschickt hat, wie in der MQTT-3.1.1-Spezifikation festgelegt.
| rc | Konstante | Schicht | Bedeutung im Klartext |
|---|---|---|---|
| -4 | MQTT_CONNECTION_TIMEOUT |
Bibliothek | Socket geöffnet, aber kein CONNACK (oder keine Ping-Antwort) rechtzeitig |
| -3 | MQTT_CONNECTION_LOST |
Netzwerk | Eine bestehende Verbindung ist abgebrochen |
| -2 | MQTT_CONNECT_FAILED |
Netzwerk | Socket konnte gar nicht geöffnet werden |
| -1 | MQTT_DISCONNECTED |
Bibliothek | Client ist sauber getrennt |
| 0 | MQTT_CONNECTED |
Broker | Verbunden |
| 1 | MQTT_CONNECT_BAD_PROTOCOL |
Broker | Protokollversion nicht akzeptiert |
| 2 | MQTT_CONNECT_BAD_CLIENT_ID |
Broker | Client ID abgelehnt |
| 3 | MQTT_CONNECT_UNAVAILABLE |
Broker | Broker kann derzeit keine Verbindungen annehmen |
| 4 | MQTT_CONNECT_BAD_CREDENTIALS |
Broker | Benutzername oder Passwort falsch |
| 5 | MQTT_CONNECT_UNAUTHORIZED |
Broker | Keine Berechtigung zum Verbinden |
Die zentrale Erkenntnis: Bei negativen Codes hat der Broker Sie entweder nie gesehen oder nie geantwortet. Bei positiven Codes hat der Broker Ihr CONNECT-Paket empfangen und bewusst abgelehnt.
PubSubClient rc=-2 beheben
Da rc=-2 immer dann gemeldet wird, wenn client.connect(host, port) auf dem zugrunde liegenden Netzwerkobjekt fehlschlägt, gibt es viele mögliche Ursachen. Gehen Sie sie in dieser Reihenfolge durch.
1. Das WLAN ist gar nicht verbunden
Ein Aufruf von mqtt.connect(), bevor WiFi.status() == WL_CONNECTED gilt, liefert immer -2. Das passiert auch, wenn der Access Point Sie getrennt hat und Ihre Schleife nur MQTT prüft. Prüfen Sie in jedem Durchlauf zuerst das WLAN und verbinden Sie es neu, bevor Sie MQTT anfassen.
2. DNS schlägt fehl oder der Hostname ist falsch
Tippfehler wie broker.connectmq.com mit Leerzeichen am Ende, mqtt://broker.connectmq.com (eine URL statt eines Hostnamens) oder ein http://-Präfix scheitern allesamt stillschweigend. setServer() erwartet einen reinen Hostnamen oder eine IPAddress. Testen Sie DNS direkt:
IPAddress ip;
if (WiFi.hostByName("broker.connectmq.com", ip)) {
Serial.print("Resolved to ");
Serial.println(ip);
} else {
Serial.println("DNS lookup failed");
}
Schlägt DNS fehl, prüfen Sie, ob DHCP Ihnen einen DNS-Server zugewiesen hat, oder legen Sie einen explizit mit WiFi.config() fest.
3. Falscher Port für den Client-Typ
Das ist der klassische Fehler. Port und Netzwerk-Client müssen zusammenpassen:
| Port | Transport | Zu verwendender Arduino-Client |
|---|---|---|
| 1883 | Reines MQTT über TCP | WiFiClient |
| 8883 | MQTT über TLS | WiFiClientSecure |
| 8083 / 8084 | MQTT über WebSocket | Von PubSubClient nicht unterstützt |
Ein WiFiClient, der auf 8883 zeigt, öffnet einen TCP-Socket und hängt dann oder scheitert, weil der Broker einen TLS-Handshake erwartet. Das zeigt sich oft als -2 oder -4. Ein WiFiClientSecure, der auf 1883 zeigt, scheitert am Handshake und liefert -2. PubSubClient beherrscht überhaupt keine WebSockets, daher sind die Ports 8083 und 8084 für Browser und Tools gedacht, wie sie in MQTT über WebSocket beschrieben werden.
4. Probleme mit dem TLS-Zertifikat
Mit WiFiClientSecure wird auch eine fehlgeschlagene Zertifikatsprüfung als rc=-2 gemeldet. Häufige Ursachen:
- Kein CA-Zertifikat gesetzt. Rufen Sie auf dem ESP32
setCACert()mit dem Root-Zertifikat auf, das das Broker-Zertifikat signiert hat. ConnectMQ verwendet Let's Encrypt, das Root-Zertifikat ist also ISRG Root X1. - Pinning eines Leaf- oder Zwischenzertifikats, das inzwischen erneuert wurde. Let's-Encrypt-Zertifikate sind kurzlebig; pinnen Sie das Root-Zertifikat, nicht das Leaf.
- Falsche Systemzeit auf dem ESP8266. BearSSL prüft die Gültigkeitsdaten, synchronisieren Sie die Zeit daher vor dem Verbinden mit
configTime(). - Zu wenig Speicher. Der TLS-Handshake braucht einen ordentlichen Teil des Heaps; auf dem ESP8266 kann ein großer MQTT-Puffer zusammen mit TLS ihn erschöpfen.
Auf dem ESP32 können Sie nach einem fehlgeschlagenen Versuch den zugrunde liegenden TLS-Fehler ausgeben:
char err[128];
int code = netClient.lastError(err, sizeof(err));
Serial.printf("TLS error %d: %s\n", code, err);
Um das Problem einzugrenzen, rufen Sie vorübergehend netClient.setInsecure() auf. Verbindet es sich dann, liegt das Problem in Ihrer Zertifikatskonfiguration. Liefern Sie niemals Firmware mit setInsecure() aus.
5. Das Netzwerk blockiert ausgehendes MQTT
Firmen-, Schul- und manche Gastnetzwerke blockieren die ausgehenden Ports 1883 und 8883, ebenso viele Produktionsnetze, die nach Zonen und Conduits gemäß IEC 62443 segmentiert sind. Testen Sie denselben Sketch an einem Handy-Hotspot. Funktioniert er dort, lassen Sie den Port freigeben oder verlegen Sie das Gerät in ein anderes Netzwerksegment; in der Fabrik stimmen Sie das mit der OT-Sicherheit ab.
6. Zu häufige Verbindungsversuche
Sieht der Broker wiederholte fehlgeschlagene Versuche von Ihrer IP-Adresse, lehnt er Verbindungen möglicherweise vorübergehend ab. ConnectMQ sperrt zum Beispiel IP-Adressen nach wiederholten fehlgeschlagenen Logins, um seine Mandanten zu schützen. Eine Reconnect-Schleife ohne Pause kann aus einem einzigen falschen Passwort eine Sperre machen, die dann wie rc=-2 aussieht. Warten Sie zwischen den Versuchen immer mindestens einige Sekunden und verlängern Sie die Wartezeit nach mehreren Fehlschlägen weiter.
rc=-4 beheben (Verbindungs-Timeout)
Hier wurde der Socket geöffnet, aber das CONNACK traf nicht innerhalb des Socket-Timeouts (standardmäßig 15 Sekunden) ein. Typische Ursachen:
- Ein einfacher
WiFiClientauf einem TLS-Port, wie oben beschrieben. - Schwaches WLAN-Signal mit hohem Paketverlust. Geben Sie
WiFi.RSSI()aus; alles um -80 dBm oder schwächer ist unzuverlässig. - Blockierender Code. War die Verbindung bereits aufgebaut, kann -4 auch später auftreten, wenn
loop()nicht oft genug aufgerufen wird, um Keep-Alive-Pings zu beantworten.
rc=-3 beheben (Verbindung verloren)
Die Verbindung hat funktioniert und ist dann abgebrochen. Achten Sie auf:
- Doppelte Client IDs. Verbindet sich ein zweites Gerät mit derselben ID, trennt der Broker das erste. Zwei Boards mit demselben Sketch werfen sich abwechselnd gegenseitig hinaus. Erzeugen Sie die IDs aus der MAC-Adresse.
- Abgelaufenes Keep Alive. Lange
delay()-Aufrufe oder langsame Sensorabfragen lassenmqtt.loop()verhungern. - Zu große oder zu häufige Nachrichten. Broker setzen Limits durch. Auf dem öffentlichen MQTT-Broker unter broker.connectmq.com, der nur für Tests und Prototypen gedacht ist, sind Clients auf 64 KB pro Nachricht und 10 Nachrichten pro Sekunde begrenzt, und Überschreitungen können die Sitzung beenden.
Die positiven Codes beheben (1 bis 5)
rc=1: Falsches Protokoll
PubSubClient sendet standardmäßig MQTT 3.1.1. Diesen Code sehen Sie nur, wenn Sie mit MQTT_VERSION auf 3.1 kompiliert haben und der Broker das ablehnt. Entfernen Sie die Überschreibung.
rc=2: Client ID abgelehnt
Meist ist eine leere Client ID schuld. Der öffentliche MQTT-Broker von ConnectMQ verlangt auch bei anonymen Verbindungen eine nicht leere Client ID. Auf einem privaten ConnectMQ Broker sind Client IDs an die im Portal ausgestellten Zugangsdaten gebunden, verwenden Sie also genau die Client ID, die Sie erhalten haben.
rc=3: Server nicht verfügbar
Der Broker läuft, nimmt aber keine Verbindungen an, etwa während einer Wartung oder wenn ein Verbindungskontingent erreicht ist. Warten Sie und versuchen Sie es erneut. Bleibt der Fehler bei Ihrem eigenen Broker bestehen, prüfen Sie, ob Sie das Verbindungslimit Ihres Plans überschritten haben.
rc=4: Falscher Benutzername oder falsches Passwort
Kopieren Sie die Zugangsdaten erneut aus dem Portal und achten Sie auf unsichtbare Zeichen. Denken Sie daran, dass connect(id, user, pass) die Client ID zuerst erwartet; vertauschte Parameter sind überraschend häufig.
rc=5: Nicht autorisiert
Der Broker hat die Zugangsdaten verstanden, lehnt diesen Client aber ab, zum Beispiel weil Benutzername und Client ID nicht zusammengehören. Prüfen Sie alle drei Werte erneut.
Eine Connect-Funktion mit Diagnose
Fügen Sie dies in einen beliebigen Sketch ein, um statt einer bloßen Zahl eine lesbare Ursache zu erhalten:
const char* mqttStateText(int s) {
switch (s) {
case -4: return "timeout (no CONNACK) - check port/TLS match and signal";
case -3: return "connection lost - duplicate client ID or keep alive";
case -2: return "socket failed - Wi-Fi, DNS, port, firewall or TLS cert";
case -1: return "disconnected";
case 0: return "connected";
case 1: return "bad protocol version";
case 2: return "client ID rejected - empty or not allowed";
case 3: return "server unavailable - retry later";
case 4: return "bad username or password";
case 5: return "not authorised";
default: return "unknown";
}
}
bool connectWithDiagnostics() {
if (WiFi.status() != WL_CONNECTED) {
Serial.println("Wi-Fi not connected, skipping MQTT");
return false;
}
if (mqtt.connect(DEVICE_ID)) {
Serial.println("MQTT connected");
return true;
}
int s = mqtt.state();
Serial.printf("MQTT failed rc=%d: %s\n", s, mqttStateText(s));
return false;
}
Checkliste zur schnellen Eingrenzung
- Erreicht Ihr Computer den Broker? Führen Sie
mosquitto_sub -h broker.connectmq.com -p 1883 -i test-$RANDOM -t "connectmq/demo/check/#" -vaus. Schlägt das fehl, liegt das Problem an Ihrem Netzwerk, nicht am Board. - Löst das Board den Hostnamen auf? Verwenden Sie das DNS-Snippet von oben.
- Verbindet es sich auf 1883 mit
WiFiClientund einer anonymen, eindeutigen Client ID? Wenn ja, liegt das Problem bei TLS oder den Zugangsdaten. - Verbindet es sich auf 8883 mit
setInsecure()? Wenn ja, korrigieren Sie das CA-Zertifikat. - Verbindet es sich mit dem CA-Zertifikat, scheitert aber an den Zugangsdaten? Prüfen Sie Benutzer, Passwort und Client ID erneut.
Ist die Verbindung erst einmal da, stoßen viele als Nächstes auf die Nachrichtengröße; siehe PubSubClient-Puffergröße. Eine vollständige Einführung in die Bibliothek bietet unser PubSubClient-Arduino-Tutorial, und ein komplettes Projekt finden Sie im ESP32-IoT-Leitfaden.
Schluss mit der Jagd nach rc-Codes dank verwaltetem MQTT-Broker
Viele rc=-2- und rc=-4-Fehler stammen von selbst gehosteten Brokern mit abgelaufenen Zertifikaten, geschlossenen Firewall-Ports oder abgestürzten Diensten. Ein verwalteter MQTT-Broker wie ConnectMQ nimmt Ihnen diese Variablen ab: TLS auf 8883 mit automatisch erneuertem Let's-Encrypt-Zertifikat, für Sie generierte Zugangsdaten und ein MQTT-Client im Browser direkt im Portal, mit dem Sie prüfen können, ob die Broker-Seite funktioniert, bevor Sie das Gerät debuggen. Starten Sie einen kostenlosen Serverless Broker unter app.connectmq.com, ohne Kreditkarte.
Häufig gestellte Fragen
Was bedeutet rc=-2 bei PubSubClient?
Es bedeutet, dass die Netzwerkverbindung zum Broker nicht geöffnet werden konnte. Der Broker hat Ihr CONNECT-Paket nie erhalten, prüfen Sie also WLAN, DNS, den Port und bei TLS das CA-Zertifikat.
Warum erhalte ich rc=-2 nur auf Port 8883?
Ihr TLS-Setup schlägt fehl. Stellen Sie sicher, dass Sie WiFiClientSecure verwenden, das richtige Root-Zertifikat laden (ISRG Root X1 bei Let's-Encrypt-Brokern) und auf dem ESP8266 die Uhrzeit vor dem Verbinden setzen.
Mein Board verbindet sich und zeigt dann alle paar Sekunden rc=-3. Warum?
Meistens verwendet ein anderes Gerät oder Tool dieselbe Client ID, sodass der Broker eine Sitzung ständig durch die andere ersetzt. Geben Sie jedem Gerät eine eindeutige ID, zum Beispiel auf Basis seiner MAC-Adresse.
Ist rc=5 etwas anderes als rc=4?
Ja. rc=4 bedeutet, dass Benutzername oder Passwort falsch sind. rc=5 bedeutet, dass die Zugangsdaten verstanden wurden, dieser Client sich aber nicht verbinden darf, oft weil die Client ID nicht zu den Zugangsdaten passt.



