Close the session when the MQTT client does not take a subscription; name the root topic when the broker refuses one

Two error lines of 8ea7778 did not help the reader act.

"the MQTT client refused to subscribe (N bytes of heap free): no directives until it reconnects": nothing reconnected. The session stayed open without subscriptions and the state SUBSCRIBING for good, because the reconnect only acts on a session that has ended. The free heap was beside the point: AsyncMqttClient 0.9.0 returns 0 from subscribe() only when its session is not open. The bridge now prints "the MQTT client did not take the subscriptions: closing the session, the next one subscribes again" and calls disconnect(), which queues the DISCONNECT packet; the end of the session then starts the reconnect.

"the broker refused the subscription to <topic>": it did not say what to check. The usual cause is a root topic that does not belong to the account, so the line ends with ": check the root topic passed to begin()". The session stays open and the state SUBSCRIBING, since the broker would refuse the same topic again; the comment says so.

Measured with the bridge built for the host against a fake MQTT client (not in the repository): subscribe() returning 0 leads to one disconnect() and, after the session has ended, to one connect() within 7 s and a session that reaches CONNECTED; a SUBACK with 0x80 prints the new line and leaves the session open.

examples/basicLight.cpp for d1_mini, static RAM / flash in bytes: 34,452 / 337,401 -> 34,452 / 337,461, no warnings. 41 host tests pass.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
David 2026-09-28 16:01:25 +00:00
parent c5b4802d65
commit 5b090a43dd
2 changed files with 9 additions and 5 deletions

View file

@ -195,7 +195,10 @@ void Alex2ESP::onMqttConnect(bool sessionPresent)
directiveSubscription = mqttClient.subscribe(directiveFilter.c_str(), 1);
if (discoverSubscription == 0 || directiveSubscription == 0)
{
ALEX2ESP_LOGE("the MQTT client refused to subscribe (%u bytes of heap free): no directives until it reconnects", (unsigned)ESP.getFreeHeap());
// The client takes a subscription whenever its session is open, so this one is not. Without the
// subscriptions the board would stay deaf: the session is closed, and the next one subscribes again.
ALEX2ESP_LOGE("the MQTT client did not take the subscriptions: closing the session, the next one subscribes again");
mqttClient.disconnect();
return;
}
ALEX2ESP_LOGI("connected to %s, subscribing", MQTT_SERVER);
@ -210,7 +213,8 @@ void Alex2ESP::onSubscribe(uint16_t packetId, uint8_t qos)
const String &topic = (packetId == discoverSubscription) ? discoverTopic : directiveFilter;
if (qos == SUBSCRIPTION_REFUSED)
{
ALEX2ESP_LOGE("the broker refused the subscription to %s", topic.c_str());
// The session stays open and the state SUBSCRIBING: the broker would refuse the same topic again
ALEX2ESP_LOGE("the broker refused the subscription to %s: check the root topic passed to begin()", topic.c_str());
return;
}