Reconnect with back-off on every disconnect reason and log it

The session is opened again whatever AsyncMqttClient gives as the reason, after 1 s doubling
to 60 s (AlexaReconnectBackoff, reset when a session opens), and only while Wi-Fi is up.
1.1.0 retried a lost TCP connection every 5 s and nothing else, silently: a refused password
or a broker that was restarting left the board offline until a reset.
Every disconnect prints its reason in words and the wait before the next attempt. The first
connect waits for Wi-Fi; a connect without an answer after 30 s counts as failed, because the
MQTT client reports nothing when no TCP connection was made. Keep-alive 30 s.
basicLight: RAM 34,452 -> 34,476 B, flash 337,461 -> 338,281 B; host tests 41 -> 45.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
David 2026-09-28 18:43:00 +00:00
parent cb5c9876fe
commit 2ed52c8721
6 changed files with 194 additions and 23 deletions

View file

@ -45,7 +45,9 @@ public:
// Begin function for initialization: MQTT username, MQTT password, root topic (the same order as alex2node).
// The username and the password are not copied: they have to stay valid for as long as the client is used.
// Starts SNTP; loop() opens the MQTT session once the clock is set, or after 5 s without an answer.
// Starts SNTP; loop() opens the MQTT session once Wi-Fi is up and the clock is set, or after 5 s of Wi-Fi
// without an answer. A session that ends or is refused is opened again after 1 s, then 2 s, 4 s ... up to once
// a minute, while Wi-Fi is up; the reason is printed and returned by getDisconnectReason().
void begin(const char *username, const char *password, const char *rootTopic);
Alex2ESPState getState() const;
@ -74,7 +76,7 @@ public:
private:
static const unsigned long CLOCK_WAIT_MS = 5000; // How long the first connect waits for SNTP
static const unsigned long CLOCK_WARNING_MS = 60000; // How often an unset clock is reported while it is used
static const unsigned long RECONNECT_INTERVAL_MS = 5000;
static const unsigned long CONNECT_TIMEOUT_MS = 30000; // How long a connect may stay without an answer
static const unsigned long DISCOVERY_WINDOW_MS = 5000; // How long the backend keeps collecting a discovery answer
static const unsigned long DISCOVERY_RETRY_MS = 20; // Pause before a refused discovery publish is tried again
@ -89,10 +91,12 @@ private:
Alex2ESPState state;
AsyncMqttClientDisconnectReason disconnectReason;
bool useSntp;
unsigned long beginTime; // millis() when begin() ran
unsigned long clockWaitStarted; // millis() when begin() ran, or when Wi-Fi was last seen down before the first connect
bool linkWaitLogged; // The wait for Wi-Fi before the first connect has been reported
bool clockWarned; // The unset clock has been reported
unsigned long lastClockWarning; // millis() of that report
unsigned long lastReconnectTime;
unsigned long waitingSince; // millis() of the connect while CONNECTING, of the disconnect while DISCONNECTED
AlexaReconnectBackoff backoff; // The wait before the next connect
uint16_t discoverSubscription; // Packet ids of the two SUBSCRIBEs, to match their acknowledgements
uint16_t directiveSubscription;
uint8_t subscriptionsPending;
@ -116,6 +120,7 @@ private:
//loop processing function
void connectWhenClockIsSet();
void connect();
void warnAboutClock();
void handleMqttReconnection();
void continueDiscovery();