Testes de brokers

Testar a conexão MQTT de um ESP32 passo a passo

ESP32 não conecta ao MQTT? Teste Wi-Fi, DNS, porta TCP, client ID, credenciais e tamanho do buffer um a um com um sketch de diagnóstico e logs seriais.

Atualizado · 8 min de leitura

Testar a conexão MQTT de um ESP32 passo a passo

Quando um ESP32 se recusa a falar com um broker MQTT, o monitor serial costuma mostrar uma única linha pouco útil: failed, rc=-2 try again in 5 seconds. O caminho mais rápido é testar a conexão camada por camada (Wi-Fi, DNS, porta TCP, handshake MQTT e publicação) e parar na primeira camada que falhar.

Este guia traz um sketch de diagnóstico para o core Arduino (core ESP32 3.x com PubSubClient 2.8) que faz exatamente isso, explica cada resultado e mostra como confirmar, do lado do broker, que a placa está realmente lá.

O checklist em resumo

PassoO que pode dar erradoComo aparece
1. Log serialBaud rate errado, nenhum logLixo ou silêncio no monitor
2. Wi-FiSSID/senha errados, rede de 5 GHz, sinal fracoWiFi.status() nunca chega a WL_CONNECTED (3)
3. DNSDHCP sem servidor DNS, erro de digitação no hosthostByName falha
4. Porta TCPFirewall, porta errada, porta TLS com cliente sem TLSrc=-2 do PubSubClient
5. MQTT CONNECTClient ID duplicado, credenciais erradas, ACLrc=2, rc=4, rc=5
6. PublicaçãoPacote maior que o bufferpublish() retorna false
7. Manter a conexãoloop() não é chamado, keep alive curto demaisrc=-3 depois de um tempo

Passo 1: tenha um log serial legível

Configure o monitor na mesma velocidade do Serial.begin(); 115200 é a convenção. No Arduino IDE, ajuste também Tools → Core Debug Level para Info ou Verbose: assim o core do ESP32 imprime eventos de Wi-Fi e erros de TLS que o seu sketch nunca vê. No PlatformIO, use monitor_speed = 115200 e build_flags = -DCORE_DEBUG_LEVEL=4.

Passos 2–6: o sketch de diagnóstico

Grave este sketch antes de mexer no seu firmware real. Ele verifica cada camada em ordem e imprime exatamente onde parou.

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 se o broker permitir acesso anônimo
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();
}

Lendo os resultados

Códigos de status do Wi-Fi

statusSignificadoCorreção
1 WL_NO_SSID_AVAILRede não encontradaConfira a grafia do SSID; garanta que ele transmite em 2,4 GHz
4 WL_CONNECT_FAILEDRejeitado, geralmente senha erradaDigite a senha de novo; redes só WPA3 podem exigir o modo misto WPA2/WPA3
6 WL_DISCONNECTEDAinda tentando ou caiuAproxime a placa; RSSI abaixo de cerca de -80 dBm não é confiável

Um bom RSSI fica mais ou menos entre -50 e -70 dBm. Se o Wi-Fi conecta, mas cai depois, veja desconexões de Wi-Fi e MQTT no ESP32.

DNS e TCP

DNS lookup failed significa que a placa não recebeu um servidor DNS utilizável do DHCP ou que o nome do host está errado. Verifique o mesmo nome a partir de um notebook na mesma rede com nslookup broker.connectmq.com. Como teste temporário você pode conectar pelo IP, mas não coloque isso em produção.

TCP connect failed (e rc=-2 no seu próprio firmware) significa que nada respondeu naquele host e porta. Causas comuns: rede de convidados ou firewall corporativo bloqueando a 1883, erro de digitação na porta ou uso da porta 8883 com um WiFiClient comum; portas TLS exigem WiFiClientSecure e um certificado de CA, como mostrado em MQTT sobre TLS no ESP32. Confirme a partir de um notebook no mesmo Wi-Fi com nc -vz broker.connectmq.com 1883.

Códigos de retorno do PubSubClient

rcConstanteCausa comum
-4MQTT_CONNECTION_TIMEOUTCONNACK não chegou a tempo ou o keep alive expirou
-3MQTT_CONNECTION_LOSTConexão caiu; loop() não é chamado com frequência suficiente
-2MQTT_CONNECT_FAILEDFalha na conexão TCP (veja acima)
-1MQTT_DISCONNECTEDDesconexão limpa / nunca conectou
1MQTT_CONNECT_BAD_PROTOCOLO broker não aceita MQTT 3.1.1
2MQTT_CONNECT_BAD_CLIENT_IDClient ID rejeitado (vazio, longo demais, caracteres inválidos)
3MQTT_CONNECT_UNAVAILABLEBroker indisponível
4MQTT_CONNECT_BAD_CREDENTIALSUsuário ou senha errados
5MQTT_CONNECT_UNAUTHORIZEDNão autorizado: faltam credenciais ou o cliente não tem permissão

Valores positivos são a resposta CONNACK do próprio broker, ou seja, a rede está ok e só resta a configuração. A referência de reason codes lista os códigos MQTT correspondentes, e PubSubClient não conecta aprofunda cada um deles.

publish() retorna false

O buffer padrão do PubSubClient tem 256 bytes e precisa comportar o pacote inteiro: cabeçalho, topic e payload. Um payload JSON de 200 bytes em um topic longo já passa disso, e publish() simplesmente retorna false sem nada chegar ao broker. Chame setBufferSize() antes de conectar; a calculadora de tamanho de pacote mostra o tamanho real de um pacote.

Passo 7: manter a conexão

mqtt.loop() precisa rodar com frequência, pelo menos várias vezes por intervalo de keep alive. Um delay(60000) no loop() ou uma leitura de sensor bloqueante garantem um rc=-3 depois de cerca de um período e meio de keep alive, porque o broker nunca recebe um PINGREQ. Troque delays longos por timers com millis() e reconecte com backoff em vez de travar em um loop while (!mqtt.connected()).

Confirme do lado do broker

Uma linha serial dizendo "OK" é a opinião do dispositivo. Verifique de forma independente: abra o cliente MQTT online, conecte-se ao mesmo broker e assine testmqtt/esp32-check/#. Reinicie a placa e a mensagem hello deve chegar em poucos segundos. No terminal, a mesma verificação é:

Aguardar a mensagem de teste do ESP32
mosquitto_sub -h broker.connectmq.com -p 1883 \
  -u "$MQTT_USER" -P "$MQTT_PASS" \
  -t 'testmqtt/esp32-check/#' -v

Aguarde o seu ESP32 no navegador

A maioria dos problemas de MQTT no ESP32 nem são problemas de MQTT: são questões de Wi-Fi, DNS ou porta escondidas atrás de um único código de retorno. Teste uma camada por vez, leia o valor exato de status ou rc e confirme do lado do broker antes de passar para o seu firmware real. Para a configuração completa no Arduino, continue com MQTT no ESP32 com Arduino.

Perguntas frequentes

O que significa "failed, rc=-2" no ESP32?

É o MQTT_CONNECT_FAILED do PubSubClient: não foi possível abrir a conexão TCP com o broker. A causa está abaixo do MQTT: sem Wi-Fi, host ou porta errados, falha de DNS, firewall ou uma porta TLS usada com um WiFiClient comum.

Por que meu ESP32 conecta, mas publish() retorna false?

Na maioria das vezes a mensagem é maior que o buffer do PubSubClient, que por padrão tem 256 bytes incluindo topic e cabeçalho. Chame setBufferSize(1024) ou mais antes de conectar e verifique o retorno de cada publish.

O ESP32 suporta Wi-Fi de 5 GHz para MQTT?

O ESP32 clássico, o S2, o S3 e o C3 só têm rádio de 2,4 GHz, então não entram em uma rede só de 5 GHz. Chips mais novos, como o ESP32-C5, são dual band. Confira o seu módulo exato antes de depurar o MQTT.