New: the AI firewall watches the whole platform and explains each incident in plain words. See how it works

Reply To: ESP32 connects in setup() but client.connected() is false a few seconds later in loop()

Tyler’s right in one line, here’s the longer version. PubSubClient only reads from the socket and sends pings inside client.loop(). Its default keepalive is 15 s. You sleep 30 s, so no ping goes out, the broker drops you for keepalive_timeout, and state -3 is “connection lost”.

Never block in loop(), use a timer instead:

unsigned long last = 0;

void setup() {
  ...
  client.setKeepAlive(60);
  client.setBufferSize(512);
}

void loop() {
  if (!client.connected()) reconnect();   // with a back-off, not a tight loop
  client.loop();                          // every pass
  if (millis() - last >= 30000) {
    last = millis();
    snprintf(buf, sizeof buf, "{"temperature":%.2f}", bme.readTemperature());
    client.publish("v1/telemetry", buf);
  }
}

Keepalive between 30 and 300 s is what the docs recommend. And do what Niall said, the Log tab names the reason for every disconnect.

Accepted solution♥ 1