Voir failed, rc=-2 dans le moniteur série est l'erreur PubSubClient la plus courante, et le message seul en dit très peu. PubSubClient rc=-2 signifie que la connexion TCP (ou TLS) vers le broker ne s'est jamais ouverte : le problème vient donc presque toujours du DNS, du port, du réseau ou du certificat, et non de MQTT lui-même. Ce guide décode chaque code d'état de -4 à 5 et vous donne une solution pour chacun.
D'où vient la valeur rc
PubSubClient enregistre le résultat de la dernière tentative de connexion dans une variable d'état interne, que vous lisez avec mqtt.state(). La plupart des sketches d'exemple l'affichent lorsque connect() renvoie false :
if (!mqtt.connect(clientId)) {
Serial.print("failed, rc=");
Serial.println(mqtt.state());
}
Les valeurs sont définies comme constantes dans PubSubClient.h. Les valeurs négatives proviennent de la bibliothèque et de la couche réseau. Les valeurs positives sont les codes de retour que le broker a renvoyés dans son paquet CONNACK, tels que définis par la spécification MQTT 3.1.1.
| rc | Constante | Couche | Signification en clair |
|---|---|---|---|
| -4 | MQTT_CONNECTION_TIMEOUT |
Bibliothèque | Socket ouvert, mais pas de CONNACK (ou pas de réponse au ping) à temps |
| -3 | MQTT_CONNECTION_LOST |
Réseau | Une connexion établie a été coupée |
| -2 | MQTT_CONNECT_FAILED |
Réseau | Impossible d'ouvrir le socket |
| -1 | MQTT_DISCONNECTED |
Bibliothèque | Le client est proprement déconnecté |
| 0 | MQTT_CONNECTED |
Broker | Connecté |
| 1 | MQTT_CONNECT_BAD_PROTOCOL |
Broker | Version du protocole refusée |
| 2 | MQTT_CONNECT_BAD_CLIENT_ID |
Broker | Client ID rejeté |
| 3 | MQTT_CONNECT_UNAVAILABLE |
Broker | Le broker ne peut pas accepter de connexions pour le moment |
| 4 | MQTT_CONNECT_BAD_CREDENTIALS |
Broker | Nom d'utilisateur ou mot de passe incorrect |
| 5 | MQTT_CONNECT_UNAUTHORIZED |
Broker | Connexion non autorisée |
Le point essentiel : avec les codes négatifs, le broker ne vous a jamais vu ou n'a jamais répondu. Avec les codes positifs, le broker a bien reçu votre paquet CONNECT et l'a délibérément refusé.
Corriger PubSubClient rc=-2
Comme rc=-2 est renvoyé chaque fois que client.connect(host, port) échoue sur l'objet réseau sous-jacent, les causes possibles sont nombreuses. Vérifiez-les dans cet ordre.
1. Le Wi-Fi n'est pas réellement connecté
Appeler mqtt.connect() avant que WiFi.status() == WL_CONNECTED renvoie toujours -2. Cela se produit aussi lorsque le point d'accès vous a déconnecté et que votre boucle ne vérifie que MQTT. Vérifiez d'abord le Wi-Fi à chaque itération et reconnectez-le avant de toucher à MQTT.
2. Le DNS échoue ou le nom d'hôte est erroné
Des fautes comme broker.connectmq.com avec une espace finale, mqtt://broker.connectmq.com (une URL au lieu d'un nom d'hôte) ou un préfixe http:// échouent toutes silencieusement. setServer() attend un nom d'hôte nu ou une IPAddress. Testez directement le DNS :
IPAddress ip;
if (WiFi.hostByName("broker.connectmq.com", ip)) {
Serial.print("Resolved to ");
Serial.println(ip);
} else {
Serial.println("DNS lookup failed");
}
Si le DNS échoue, vérifiez que le DHCP vous a bien fourni un serveur DNS, ou définissez-en un explicitement avec WiFi.config().
3. Mauvais port pour le type de client
C'est l'erreur classique. Le port et le client réseau doivent correspondre :
| Port | Transport | Client Arduino à utiliser |
|---|---|---|
| 1883 | MQTT en clair sur TCP | WiFiClient |
| 8883 | MQTT sur TLS | WiFiClientSecure |
| 8083 / 8084 | MQTT sur WebSocket | Non pris en charge par PubSubClient |
Un WiFiClient pointé vers 8883 ouvre un socket TCP, puis se bloque ou échoue parce que le broker attend une poignée de main TLS, ce qui se traduit souvent par -2 ou -4. Un WiFiClientSecure pointé vers 1883 échoue lors de la poignée de main et renvoie -2. PubSubClient ne parle pas du tout WebSocket : les ports 8083 et 8084 sont destinés aux navigateurs et aux outils comme ceux décrits dans MQTT sur WebSocket.
4. Problèmes de certificat TLS
Avec WiFiClientSecure, l'échec de la vérification du certificat est lui aussi signalé par rc=-2. Causes fréquentes :
- Aucun certificat CA défini. Sur ESP32, appelez
setCACert()avec la racine qui a signé le certificat du broker. ConnectMQ utilise Let's Encrypt, la racine est donc ISRG Root X1. - Épinglage d'un certificat feuille ou intermédiaire qui a depuis été renouvelé. Les certificats Let's Encrypt ont une durée de vie courte : épinglez la racine, pas la feuille.
- Heure système incorrecte sur ESP8266. BearSSL vérifie les dates de validité, synchronisez donc l'heure avec
configTime()avant de vous connecter. - Mémoire insuffisante. La poignée de main TLS a besoin d'une bonne partie du heap ; sur ESP8266, un gros buffer MQTT combiné au TLS peut l'épuiser.
Sur ESP32, vous pouvez afficher l'erreur TLS sous-jacente après une tentative échouée :
char err[128];
int code = netClient.lastError(err, sizeof(err));
Serial.printf("TLS error %d: %s\n", code, err);
Pour isoler le problème, appelez temporairement netClient.setInsecure(). Si la connexion réussit, c'est votre configuration de certificat qui est en cause. Ne livrez jamais un firmware avec setInsecure().
5. Le réseau bloque le MQTT sortant
Les réseaux d'entreprise, d'école et certains réseaux invités bloquent les ports sortants 1883 et 8883. Essayez le même sketch sur un partage de connexion de téléphone. Si cela fonctionne, demandez l'ouverture du port ou déplacez l'appareil sur un autre segment réseau.
6. Connexions trop fréquentes
Si le broker voit des tentatives échouées répétées depuis votre adresse IP, il peut refuser temporairement les connexions. ConnectMQ, par exemple, bloque les adresses IP après des échecs d'authentification répétés afin de protéger les tenants. Une boucle de reconnexion sans délai peut transformer un simple mot de passe erroné en blocage qui ressemble ensuite à un rc=-2. Attendez toujours au moins quelques secondes entre les tentatives et espacez-les davantage après plusieurs échecs.
Corriger rc=-4 (délai de connexion dépassé)
Ici, le socket s'est ouvert, mais le CONNACK n'est pas arrivé dans le délai du socket (15 secondes par défaut). Causes typiques :
- Un
WiFiClienten clair sur un port TLS, comme décrit plus haut. - Un signal Wi-Fi faible avec beaucoup de pertes de paquets. Affichez
WiFi.RSSI(): à partir d'environ -80 dBm ou moins, la liaison n'est pas fiable. - Du code bloquant. Si la connexion a été établie auparavant, -4 peut aussi apparaître plus tard lorsque
loop()n'est pas appelé assez souvent pour répondre aux pings keep alive.
Corriger rc=-3 (connexion perdue)
La connexion fonctionnait, puis elle a été coupée. Cherchez :
- Des client ID en double. Quand un second appareil se connecte avec le même ID, le broker déconnecte le premier. Deux cartes flashées avec le même sketch vont se déconnecter à tour de rôle. Générez les ID à partir de l'adresse MAC.
- L'expiration du keep alive. De longs appels à
delay()ou des lectures de capteur lentes priventmqtt.loop()de temps d'exécution. - Des messages trop volumineux ou trop fréquents. Les brokers imposent des limites. Sur le serveur MQTT public gratuit broker.connectmq.com, les clients sont limités à 64 Ko par message et 10 messages par seconde, et le dépassement de ces limites peut fermer la session.
Corriger les codes positifs (1 à 5)
rc=1 : protocole incorrect
PubSubClient envoie MQTT 3.1.1 par défaut. Vous ne voyez ce code que si vous avez compilé avec MQTT_VERSION réglé sur 3.1 face à un broker qui le refuse. Supprimez cette surcharge.
rc=2 : client ID rejeté
Un client ID vide est le coupable habituel. Le serveur MQTT public gratuit de ConnectMQ exige un client ID non vide, même pour les connexions anonymes. Sur un broker ConnectMQ privé, les client ID sont liés aux identifiants émis dans le portail : utilisez exactement le client ID qui vous a été attribué.
rc=3 : serveur indisponible
Le broker fonctionne mais n'accepte pas de connexions, par exemple pendant une maintenance ou lorsqu'un quota de connexions est atteint. Patientez puis réessayez. Si cela persiste sur votre propre broker, vérifiez si vous avez dépassé la limite de connexions de votre offre.
rc=4 : nom d'utilisateur ou mot de passe incorrect
Recopiez les identifiants depuis le portail et méfiez-vous des caractères invisibles. N'oubliez pas que connect(id, user, pass) prend d'abord le client ID ; inverser l'ordre est étonnamment fréquent.
rc=5 : non autorisé
Le broker a compris les identifiants mais refuse ce client, par exemple parce que le nom d'utilisateur et le client ID ne vont pas ensemble. Revérifiez les trois valeurs.
Une fonction de connexion avec diagnostic
Ajoutez ceci à n'importe quel sketch pour obtenir une explication lisible au lieu d'un simple nombre :
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;
}
Liste de vérification rapide
- Votre ordinateur peut-il joindre le broker ? Lancez
mosquitto_sub -h broker.connectmq.com -p 1883 -i test-$RANDOM -t "connectmq/demo/check/#" -v. Si cela échoue, le problème vient de votre réseau, pas de la carte. - La carte résout-elle le nom d'hôte ? Utilisez l'extrait DNS ci-dessus.
- Se connecte-t-elle sur 1883 avec
WiFiClientet un client ID anonyme et unique ? Si oui, le problème vient de votre TLS ou de vos identifiants. - Se connecte-t-elle sur 8883 avec
setInsecure()? Si oui, corrigez le certificat CA. - Se connecte-t-elle avec le CA mais échoue avec les identifiants ? Revérifiez l'utilisateur, le mot de passe et le client ID.
Une fois connecté, le problème suivant que l'on rencontre est la taille des messages ; consultez la taille du buffer PubSubClient. Pour une présentation complète de la bibliothèque, lisez notre tutoriel PubSubClient pour Arduino, et pour un projet complet, consultez le guide de référence du tutoriel IoT ESP32.
Arrêtez de traquer les codes rc avec un broker MQTT managé
De nombreuses erreurs rc=-2 et rc=-4 proviennent de brokers auto-hébergés aux certificats expirés, aux ports de pare-feu fermés ou aux services plantés. Un broker MQTT managé comme ConnectMQ élimine ces variables : TLS sur 8883 avec un certificat Let's Encrypt renouvelé automatiquement, identifiants générés pour vous et client MQTT dans le navigateur, directement dans le portail, pour confirmer que le côté broker fonctionne avant de déboguer l'appareil. Lancez un broker Serverless gratuit sur app.connectmq.com, sans carte bancaire.
Questions fréquentes
Que signifie rc=-2 dans PubSubClient ?
Cela signifie que la connexion réseau vers le broker n'a pas pu être ouverte. Le broker n'a jamais reçu votre paquet CONNECT : vérifiez donc le Wi-Fi, le DNS, le port et, en TLS, le certificat CA.
Pourquoi est-ce que j'obtiens rc=-2 uniquement sur le port 8883 ?
Votre configuration TLS échoue. Assurez-vous d'utiliser WiFiClientSecure, de charger le bon certificat racine (ISRG Root X1 pour les brokers Let's Encrypt) et, sur ESP8266, de régler l'horloge avant de vous connecter.
Ma carte se connecte puis affiche rc=-3 toutes les quelques secondes. Pourquoi ?
Le plus souvent, un autre appareil ou outil utilise le même client ID, si bien que le broker remplace sans cesse une session par l'autre. Donnez à chaque appareil un ID unique, par exemple basé sur son adresse MAC.
rc=5 est-il différent de rc=4 ?
Oui. rc=4 signifie que le nom d'utilisateur ou le mot de passe est incorrect. rc=5 signifie que les identifiants ont été compris mais que ce client n'est pas autorisé à se connecter, souvent parce que le client ID ne correspond pas aux identifiants.



