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.