Connection failed : Attempting MQTT connection...failed, rc=-4

Hello, HIVEMQ SUPPORT FORUM

I’m currently working on a project using an ESP32-Dev-MINI-1 and trying to connect to a HiveMQ Cloud broker, but I’m running into an issue where the MQTT connection keeps timing out.

❖ Problem Summary:

  • The ESP32 fails to establish a connection with the broker.
  • Serial output shows:
    Attempting MQTT connection...failed, rc=-4 try again in 5 seconds

❖ Setup Details:

  • Device: ESP32-MINI-1
  • MQTT Client Library: PubSubClient
  • MQTT Broker: HiveMQ Cloud
  • Broker Address: \broker.hivemq.com
  • Port: 1883
  • WiFi Connection: i-Phone Hotspot

❖ What I’ve Tried:

  • Verified WiFi SSID and password
  • Confirmed DNS resolves broker address
  • Added connection delay after WiFi setup
  • Previously used broker.mqtt-dashboard.com (worked until Jan 2025), but recently tried broker.hivemq.com instead

❖ Observations:

  • client.state() returns -4, which indicates a connection timeout
  • client.state() also returns 5 (MQTT_CONNECTION_LOST) before retrying

❖ Questions:

  1. Could the connection issue be caused by using an iPhone’s personal hotspot?
  2. When I used the hotspot and set broker.hivemq.com as the host with port 1883, everything worked fine until January 2025.
  3. I’ve verified via ping tests that the broker is reachable on port 1883.
  4. Should I consider changing the network environment or switching to a different port (e.g., 8883)?
  5. If there is something I might be missing or doing incorrectly, could you kindly let me know?

------------------------------------------------------------ full code -----------------------------------------------------------------------
#include <WiFi.h>

int cb_state = 0;
int init_state = 1;

const int ledPin = 15;
const int buttonPin = 36;
const int buttonPin2 = 37;
char* value;

/----- Setting AP mode ------/

#include <ESPAsyncWebServer.h>
#include <AsyncTCP.h>

AsyncWebServer server(80);

// Search for parameter in HTTP POST request
const char* PARAM_INPUT_1 = “ssid”;
const char* PARAM_INPUT_2 = “pass”;
const char* PARAM_INPUT_3 = “ip”;
const char* PARAM_INPUT_4 = “gateway”;

// Variables to save values from HTML form
String ssid;
String pass;
String ip;
String gateway;

// File paths to save input values permanently
const char* ssidPath = “/ssid.txt”;
const char* passPath = “/pass.txt”;
const char* ipPath = “/ip.txt”;
const char* gatewayPath = “/gateway.txt”;

/-------------------------/

/----- Initializing SPIFFS ------/

#include “SPIFFS.h”

void initSPIFFS() {
if (!SPIFFS.begin(true))
{
Serial.println(“An error has occurred while mounting SPIFFS”);
}
Serial.println(“SPIFFS mounted successfully”);
}

// Read File from SPIFFS
String readFile(fs::FS &fs, const char * path) {
Serial.printf(“Reading file: %s\r\n”, path);

File file = fs.open(path);
if (!file || file.isDirectory()) {
Serial.println(“- failed to open file for reading”);
return String();
}

String fileContent;
while (file.available()) {
fileContent = file.readStringUntil(‘\n’);
break;
}
return fileContent;
}

// Write file to SPIFFS
void writeFile(fs::FS &fs, const char * path, const char * message) {
Serial.printf(“Writing file: %s\r\n”, path);

File file = fs.open(path, FILE_WRITE);
if (!file) {
Serial.println(“- failed to open file for writing”);
return;
}
if (file.print(message)) {
Serial.println(“- file written”);
} else {
Serial.println(“- frite failed”);
}
}

/--------------------------------/

/* MQTT Initial Configuration */

#include <PubSubClient.h>

#define MSG_BUFFER_SIZE (1024)
char msg[MSG_BUFFER_SIZE];

const char *mqtt_server = “broker.hivemq.com”; // broker.hivemq.com or broker.mqtt-dashboard.com
const int mqtt_port = 1883;

WiFiClient espClient;
PubSubClient client(espClient);

/---------------------/

/----- Register MQTT Callback Function -----/

void callback(char *topic, byte *payload, unsigned int length)
{
Serial.print(“Message arrived [”);
Serial.print(topic);
Serial.print("] ");

char c;
for (int i = 0; i < length; i++)
{
Serial.print((char)payload[i]);
Serial.println(payload[i]);
c = (char)payload[0];
}

if (c == ‘3’) {
value = “OFF”;
snprintf(msg, MSG_BUFFER_SIZE, “2 LED %s”, value);
client.publish(“USG/esp32/30”, msg);
digitalWrite(ledPin, HIGH);
cb_state = 0;
}
else if (c == ‘1’) {
digitalWrite(ledPin, LOW);
client.publish(“CB Control”, “CB off”);
Serial.println(“Message published [CB off]”);
value = “ON”;
snprintf(msg, MSG_BUFFER_SIZE, “1 LED %s”, value);
client.publish(“USG/esp32/30”, msg);
cb_state = 0;
}
else if (c == ‘2’)
{
if (ledPin == 0)
{
snprintf(msg, MSG_BUFFER_SIZE, “1”);
client.publish(“USG/esp32/30”, msg);
}
else
{
snprintf(msg, MSG_BUFFER_SIZE, “0”);
client.publish(“USG/esp32/30”, msg);
}
}
else if (c == ‘4’)
{
init_state = 0;
}
}

/-------------------------/

/----- Connecting to MQTT Broker -----/

void setup_MQTT() {
while (!client.connected()) {
Serial.print(“Attempting MQTT connection…”);

String clientId = "ESP32Client-";
clientId += String(random(0xffff), HEX);

if (client.connect(clientId.c_str())) {
  Serial.println("connected");
  client.subscribe("USG/esp32/state/30");
} else {
  Serial.print("failed, rc=");
  Serial.print(client.state());
  Serial.println(" try again in 5 seconds");
  delay(5000);
}

}
}
/-----------------------------------/

/------ Connecting to WiFi ------/

void setup_WiFi()
{
if (ssid == “” || ip == “”) {
Serial.println(“Undefined SSID or IP address.”);
return;
}

WiFi.mode(WIFI_STA);
WiFi.begin(ssid.c_str(), pass.c_str());

Serial.print(“Connecting to WiFi”);

unsigned long startAttemptTime = millis();
const unsigned long timeout = 10000; // wait up to 10 seconds

while (WiFi.status() != WL_CONNECTED && millis() - startAttemptTime < timeout)
{
Serial.print(“.”);
delay(500);
}

if (WiFi.status() == WL_CONNECTED)
{
Serial.println(“\nWiFi connected”);
Serial.print(“IP address: “);
Serial.println(WiFi.localIP());
}
else
{
Serial.println(”\nWiFi connection failed. Starting AP Mode.”);
APserver_Load(); // Enter AP mode if WiFi fails
}

}

/---------------------------/

/---- Launching AP server to update WiFi information ----/

void APserver_Load()
{
Serial.println(“Setting AP(Access Point)”);
// Use ESP32 as hotspot softAP(“SSID”, password)
WiFi.softAP(“CB_Monitoring System”, NULL);

IPAddress IP = WiFi.softAPIP();
Serial.print("AP IP address: ");
Serial.println(IP);

// Web Server Root URL
server.on(“/”, HTTP_GET, (AsyncWebServerRequest * request) {
request->send(SPIFFS, “/wifimanager.html”, “text/html”);
});

server.serveStatic(“/”, SPIFFS, “/”);

server.on(“/”, HTTP_POST, (AsyncWebServerRequest * request) {
int params = request->params();
for (int i = 0; i < params; i++) {
const AsyncWebParameter* p = request->getParam(i);
if (p->isPost()) {
if (p->name() == PARAM_INPUT_1) {
ssid = p->value().c_str();
Serial.print("SSID set to: ");
Serial.println(ssid);
writeFile(SPIFFS, ssidPath, ssid.c_str());
}
if (p->name() == PARAM_INPUT_2) {
pass = p->value().c_str();
Serial.print("Password set to: ");
Serial.println(pass);
writeFile(SPIFFS, passPath, pass.c_str());
}
if (p->name() == PARAM_INPUT_3) {
ip = p->value().c_str();
Serial.print("IP Address set to: ");
Serial.println(ip);
writeFile(SPIFFS, ipPath, ip.c_str());
}
if (p->name() == PARAM_INPUT_4) {
gateway = p->value().c_str();
Serial.print("Gateway set to: ");
Serial.println(gateway);
writeFile(SPIFFS, gatewayPath, gateway.c_str());
}
}
}
request->send(200, “text/plain”, "Done. ESP will restart, connect to your router and go to IP address: " + ip);
delay(3000);
ESP.restart();
});
server.begin();
}

/--------------------------------------------/

void setup()
{
Serial.begin(115200);
pinMode(ledPin, OUTPUT);
pinMode(buttonPin, INPUT_PULLUP);
pinMode(buttonPin2, INPUT_PULLUP);
initSPIFFS();

// Load values saved in SPIFFS
ssid = readFile(SPIFFS, ssidPath);
pass = readFile(SPIFFS, passPath);
ip = readFile(SPIFFS, ipPath);
gateway = readFile (SPIFFS, gatewayPath);
Serial.println(ssid);
Serial.println(pass);
Serial.println(ip);
Serial.println(gateway);

setup_WiFi();

if (WiFi.status() != WL_CONNECTED)
{
APserver_Load();
}

IPAddress brokerIP;
if (WiFi.hostByName(mqtt_server, brokerIP)) {
Serial.print("Broker IP resolved: ");
Serial.println(brokerIP);
} else {
Serial.println(“Failed to resolve broker hostname”);
}

client.setServer(mqtt_server, mqtt_port);
client.setCallback(callback);
Serial.println(“MQTT server and callback function registered”);
}

/------------------------ Define button push function ---------------------------/

// Debounce time (millisecond)
#define DEBOUNCE_TIME 50
// Previous stable state
int lastStableState = LOW;
// Previous unstable state
int lastUnstableState = LOW;
// Current state
int currentState;
// Time when the pin was last toggled
unsigned long lastChangeTime = 0;

unsigned long previousMillis = 0;
const long interval = 3000; // Interval for function execution (3 seconds)

void buttonPushed()
{
cb_state = 1;
client.publish(“LED Control”, “LED on”);
Serial.println(“Message published [LED Control] LED on”);
value = “ON”;
snprintf(msg, MSG_BUFFER_SIZE, “0 LED %s”, value);
client.publish(“USG/esp32/30”, msg);
}

bool isFirstRun = true;

void buttonReleased()
{
if (isFirstRun) {
isFirstRun = false;
return;
}

cb_state = 0;
digitalWrite(ledPin, HIGH);

client.publish(“LED Control”, “LED on”);
Serial.println(“Message published [LED Control] LED on”);
value = “ON”;
snprintf(msg, MSG_BUFFER_SIZE, “2 LED %s”, value);
client.publish(“USG/esp32/30”, msg);
}

/----------------------------------------------------------------------/

void yourFunction()
{
int A = digitalRead(ledPin);
Serial.println(A);
if (cb_state == 0 )
{
if (A == 0)
{
snprintf(msg, MSG_BUFFER_SIZE, “1 LED”);
client.publish(“USG/esp32/30”, msg);
Serial.println(“CB ON”);
}
else
{
snprintf(msg, MSG_BUFFER_SIZE, “2 LED”);
client.publish(“USG/esp32/30”, msg);
Serial.println(“CB off”);
}
}
}

void loop()
{
// Check WiFi and try to connect to MQTT
if (WiFi.status() == WL_CONNECTED) {

if (!client.connected()) {
  setup_MQTT();  // Try MQTT only after WiFi is connected
}

client.loop();

}

else {
setup_WiFi(); // Reconnect WiFi if disconnected
}

unsigned long currentMillis = millis();

// Execute at defined interval
if (currentMillis - previousMillis >= interval && init_state == 1)
{
previousMillis = currentMillis;
yourFunction();
}

if (init_state == 0)
{
currentState = digitalRead(buttonPin);
if (currentState != lastUnstableState)
{
lastChangeTime = millis();
lastUnstableState = currentState;
}
if ((millis() - lastChangeTime) > DEBOUNCE_TIME)
{
if (lastStableState == HIGH && currentState == LOW)
{
Serial.println(“Short-circuit detected”);
buttonPushed();
}
if (lastStableState == LOW && currentState == HIGH) {
Serial.println(“Recovered”);
buttonReleased();
}
lastStableState = currentState;
}
}

delay(20);
}


I apologize for posting such a long piece of code — I understand it may be inconvenient to read. However, I truly hope this issue can be resolved, which is why I included everything in detail. I know there may be many parts I couldn’t figure out due to my lack of experience or knowledge. I would be sincerely grateful for any help or guidance you can provide.

Thanks in advance!

Best regards,
[Changdae]

The short answer might be that the public broker (broker.hivemq.com) was actually overloaded during your testing. That has happened with some frequency - especially in the past month, which results in the server refusing new connections and closing existing ones. In other words, timeouts and other errors. You will probably encounter a similar error when trying to connect to the broker using the hivemq websocket test webpage..

On the upside, it provides an opportunity to test your code’s failover techniques, but it can be very frustrating. The recommended solution in other threads is to move to a dedicated (not public) hivemq instance which can still be free, but has additional requirements (like implementing TLS) that can be daunting to someone learning about MQTT or running with low bandwidth.

To see if that resolves your issue without implementing TLS complexities, you could change your code to connect to other vendor public test brokers that also support unencrypted connections..

hth