ESP32 e Arduino

PubSubClient rc=-2 e Outros Códigos de Estado Explicados (Com Soluções)

O PubSubClient mostra "failed, rc=-2" e nada mais? Este guia decifra cada código de estado de -4 a 5 e traz soluções testadas para problemas de DNS, porta, TLS, client ID e credenciais.

Monitor serial exibindo um erro de conexão PubSubClient rc=-2 ao lado de uma placa ESP32
Rode isso no seu próprio broker MQTTTenha um broker MQTT privado e gerenciado no plano Free e comece com exemplos de código prontos.
Teste grátis Exemplos de código Sem cartão de crédito

Ver failed, rc=-2 no monitor serial é o erro mais comum do PubSubClient, e a mensagem sozinha diz muito pouco. O PubSubClient rc=-2 significa que a conexão TCP (ou TLS) com o broker nunca chegou a ser aberta, então o problema quase sempre está no DNS, na porta, na rede ou no certificado, e não no MQTT em si. Este guia decifra cada código de estado de -4 a 5 e traz uma solução para cada um.

De Onde Vem o Valor rc

O PubSubClient armazena o resultado da última tentativa de conexão em uma variável de estado interna, que você lê com mqtt.state(). A maioria dos sketches de exemplo a imprime quando connect() retorna false:

if (!mqtt.connect(clientId)) {
  Serial.print("failed, rc=");
  Serial.println(mqtt.state());
}

Os valores são definidos como constantes em PubSubClient.h. Os valores negativos vêm da biblioteca e da camada de rede. Os positivos são os códigos de retorno que o broker enviou no pacote CONNACK, conforme definido pela especificação MQTT 3.1.1.

rc Constante Camada Significado em linguagem simples
-4 MQTT_CONNECTION_TIMEOUT Biblioteca Socket aberto, mas sem CONNACK (ou sem resposta ao ping) a tempo
-3 MQTT_CONNECTION_LOST Rede Uma conexão estabelecida caiu
-2 MQTT_CONNECT_FAILED Rede Não foi possível abrir o socket
-1 MQTT_DISCONNECTED Biblioteca Cliente desconectado normalmente
0 MQTT_CONNECTED Broker Conectado
1 MQTT_CONNECT_BAD_PROTOCOL Broker Versão do protocolo não aceita
2 MQTT_CONNECT_BAD_CLIENT_ID Broker Client ID rejeitado
3 MQTT_CONNECT_UNAVAILABLE Broker O broker não pode aceitar conexões agora
4 MQTT_CONNECT_BAD_CREDENTIALS Broker Usuário ou senha incorretos
5 MQTT_CONNECT_UNAUTHORIZED Broker Sem autorização para conectar

O ponto-chave: com códigos negativos, o broker nunca viu você ou nunca respondeu. Com códigos positivos, o broker recebeu seu pacote CONNECT e o recusou deliberadamente.

Como Resolver o PubSubClient rc=-2

Como o rc=-2 é informado sempre que client.connect(host, port) falha no objeto de rede subjacente, ele tem muitas causas possíveis. Verifique-as nesta ordem.

1. O Wi-Fi Não Está Realmente Conectado

Chamar mqtt.connect() antes de WiFi.status() == WL_CONNECTED sempre retorna -2. Isso também acontece quando o access point derruba você e o seu loop verifica apenas o MQTT. Verifique o Wi-Fi primeiro em cada iteração e reconecte-o antes de mexer no MQTT.

2. O DNS Falha ou o Nome do Host Está Errado

Erros de digitação como broker.connectmq.com com um espaço no final, mqtt://broker.connectmq.com (uma URL em vez de um nome de host) ou prefixos http:// falham silenciosamente. O setServer() espera um nome de host puro ou um IPAddress. Teste o DNS diretamente:

IPAddress ip;
if (WiFi.hostByName("broker.connectmq.com", ip)) {
  Serial.print("Resolved to ");
  Serial.println(ip);
} else {
  Serial.println("DNS lookup failed");
}

Se o DNS falhar, verifique se o DHCP forneceu um servidor DNS ou defina um explicitamente com WiFi.config().

3. Porta Errada para o Tipo de Cliente

Este é o erro clássico. A porta e o cliente de rede precisam combinar:

Porta Transporte Cliente Arduino a usar
1883 MQTT puro sobre TCP WiFiClient
8883 MQTT sobre TLS WiFiClientSecure
8083 / 8084 MQTT sobre WebSocket Não suportado pelo PubSubClient

Um WiFiClient apontado para a 8883 abre um socket TCP e depois trava ou falha, porque o broker espera um handshake TLS, o que muitas vezes aparece como -2 ou -4. Um WiFiClientSecure apontado para a 1883 falha no handshake e retorna -2. O PubSubClient não fala WebSocket de forma alguma, então as portas 8083 e 8084 são para navegadores e ferramentas como as descritas em MQTT sobre WebSocket.

4. Problemas com o Certificado TLS

Com WiFiClientSecure, uma falha na verificação do certificado também é informada como rc=-2. Causas comuns:

  • Nenhum certificado de CA definido. No ESP32, chame setCACert() com a raiz que assinou o certificado do broker. O ConnectMQ usa Let's Encrypt, então a raiz é a ISRG Root X1.
  • Fixar (pinning) um certificado folha ou intermediário que já foi trocado. Os certificados Let's Encrypt têm vida curta; fixe a raiz, não a folha.
  • Hora do sistema errada no ESP8266. O BearSSL verifica as datas de validade, então sincronize o relógio com configTime() antes de conectar.
  • Falta de memória. O handshake TLS precisa de uma boa parte do heap; no ESP8266, um buffer MQTT grande somado ao TLS pode esgotá-lo.

No ESP32, você pode imprimir o erro TLS subjacente após uma tentativa malsucedida:

char err[128];
int code = netClient.lastError(err, sizeof(err));
Serial.printf("TLS error %d: %s\n", code, err);

Para isolar o problema, chame netClient.setInsecure() temporariamente. Se assim conectar, o problema está na configuração do certificado. Nunca publique um firmware com setInsecure().

5. A Rede Bloqueia MQTT de Saída

Redes corporativas, de escolas e algumas redes de convidados bloqueiam as portas de saída 1883 e 8883. Teste o mesmo sketch usando o roteador do celular. Se funcionar ali, peça a liberação da porta ou mova o dispositivo para outro segmento de rede.

6. Tentativas de Conexão Frequentes Demais

Se o broker vê tentativas fracassadas repetidas vindas do seu endereço IP, ele pode recusar conexões temporariamente. O ConnectMQ, por exemplo, bloqueia endereços IP após logins malsucedidos repetidos para proteger os clientes. Um loop de reconexão sem pausa pode transformar uma única senha errada em um bloqueio que depois parece um rc=-2. Sempre espere pelo menos alguns segundos entre as tentativas e aumente o intervalo após várias falhas.

Como Resolver o rc=-4 (Tempo Esgotado)

Aqui o socket foi aberto, mas o CONNACK não chegou dentro do timeout do socket (15 segundos por padrão). Causas típicas:

  • WiFiClient puro em uma porta TLS, como descrito acima.
  • Sinal de Wi-Fi fraco com muita perda de pacotes. Imprima WiFi.RSSI(); qualquer valor por volta de -80 dBm ou mais fraco não é confiável.
  • Código bloqueante. Se a conexão foi estabelecida antes, o -4 também pode aparecer mais tarde, quando loop() não é chamado com frequência suficiente para responder aos pings de keep alive.

Como Resolver o rc=-3 (Conexão Perdida)

A conexão funcionou e depois caiu. Procure por:

  • Client IDs duplicados. Quando um segundo dispositivo se conecta com o mesmo ID, o broker desconecta o primeiro. Duas placas gravadas com o mesmo sketch vão se derrubar alternadamente. Gere os IDs a partir do endereço MAC.
  • Expiração do keep alive. Chamadas longas de delay() ou leituras lentas de sensores deixam mqtt.loop() sem execução.
  • Mensagens grandes ou frequentes demais. Os brokers impõem limites. No servidor MQTT público em broker.connectmq.com, destinado a testes, os clientes estão limitados a 64 KB por mensagem e 10 mensagens por segundo, e ultrapassar os limites pode encerrar a sessão.

Como Resolver os Códigos Positivos (1 a 5)

rc=1: Protocolo Inválido

O PubSubClient envia MQTT 3.1.1 por padrão. Você só verá este código se compilou com MQTT_VERSION definido como 3.1 contra um broker que o rejeita. Remova essa substituição.

rc=2: Client ID Rejeitado

Um client ID vazio é o culpado mais comum. O broker público do ConnectMQ exige um client ID não vazio, mesmo em conexões anônimas. Em um broker privado do ConnectMQ, os client IDs ficam vinculados às credenciais emitidas no portal, então use exatamente o client ID que você recebeu.

rc=3: Servidor Indisponível

O broker está no ar, mas não está aceitando conexões, por exemplo durante uma manutenção ou quando uma cota de conexões foi atingida. Espere e tente de novo. Se o problema persistir no seu próprio broker, verifique se você ultrapassou o limite de conexões do seu plano.

rc=4: Usuário ou Senha Incorretos

Copie as credenciais novamente do portal e fique atento a caracteres invisíveis. Lembre-se de que connect(id, user, pass) recebe o client ID primeiro; inverter a ordem é surpreendentemente comum.

rc=5: Não Autorizado

O broker entendeu as credenciais, mas recusa este cliente, por exemplo porque o usuário e o client ID não pertencem um ao outro. Confira novamente os três valores.

Uma Função de Conexão com Diagnóstico

Coloque isto em qualquer sketch para obter um motivo legível em vez de um simples número:

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;
}

Checklist Rápido de Isolamento

  1. Seu computador consegue alcançar o broker? Execute mosquitto_sub -h broker.connectmq.com -p 1883 -i test-$RANDOM -t "connectmq/demo/check/#" -v. Se falhar, o problema é a sua rede, não a placa.
  2. A placa resolve o nome do host? Use o trecho de DNS acima.
  3. Ela conecta na 1883 com WiFiClient e um client ID anônimo e único? Se sim, o problema está no TLS ou nas credenciais.
  4. Ela conecta na 8883 com setInsecure()? Se sim, corrija o certificado da CA.
  5. Ela conecta com a CA, mas falha com as credenciais? Confira de novo usuário, senha e client ID.

Depois de conectado, o próximo problema que as pessoas encontram é o tamanho das mensagens; veja tamanho do buffer do PubSubClient. Para um passo a passo completo da biblioteca, leia nosso tutorial do PubSubClient para Arduino e, para um projeto completo, veja o guia principal de tutorial IoT com ESP32.

Pare de Caçar Códigos rc com um Broker MQTT Gerenciado

Muitos erros rc=-2 e rc=-4 vêm de brokers auto-hospedados com certificados expirados, portas de firewall fechadas ou serviços que travaram. Um broker MQTT gerenciado como o ConnectMQ elimina essas variáveis: TLS na 8883 com um certificado Let's Encrypt renovado automaticamente, credenciais geradas para você e um cliente MQTT no navegador dentro do portal, para que você confirme que o lado do broker funciona antes de depurar o dispositivo. Crie um broker Serverless gratuito em app.connectmq.com, sem precisar de cartão de crédito.

Perguntas frequentes

O que significa rc=-2 no PubSubClient?

Significa que não foi possível abrir a conexão de rede com o broker. O broker nunca recebeu seu pacote CONNECT, então verifique o Wi-Fi, o DNS, a porta e, no caso de TLS, o certificado da CA.

Por que recebo rc=-2 apenas na porta 8883?

Sua configuração TLS está falhando. Certifique-se de usar WiFiClientSecure, carregar o certificado raiz correto (ISRG Root X1 para brokers com Let's Encrypt) e, no ESP8266, acertar o relógio antes de conectar.

Minha placa conecta e depois mostra rc=-3 a cada poucos segundos. Por quê?

Na maioria das vezes, outro dispositivo ou ferramenta está usando o mesmo client ID, então o broker fica substituindo uma sessão pela outra. Dê a cada dispositivo um ID único, por exemplo baseado no endereço MAC.

O rc=5 é diferente do rc=4?

Sim. O rc=4 significa que o usuário ou a senha estão errados. O rc=5 significa que as credenciais foram entendidas, mas este cliente não tem permissão para conectar, muitas vezes porque o client ID não corresponde às credenciais.

Artigos relacionados

Exemplo de MQTT com ESP-IDF: Monte um Cliente esp-mqtt do Zero

Monte um projeto ESP-IDF a partir de uma pasta vazia com o componente esp-mqtt: configuração do Wi-Fi em modo station, o handler de eventos MQTT, publicação e inscrição, propriedades do MQTT 5 e TLS com o bundle de certificados.

8 min de leitura

Usando os Recursos do MQTT 5 do esp-mqtt no ESP32 com ESP-IDF

Um projeto ESP-IDF prático que ativa o MQTT 5.0 no esp-mqtt e usa user properties, expiração de mensagens, topic aliases, expiração de sessão e response topics com um broker MQTT 5 real.

8 min de leitura

Todos os artigos →

Seu broker MQTT privado está a poucos cliques de distância

Crie uma conta, receba as credenciais do seu broker e conecte seu primeiro dispositivo — sem servidores para instalar, atualizar ou escalar.