MQTT client on libmosquitto with its own thread (iteration 2, step 2)

MqttClient is the interface the HA layer will use; MosquittoClient
implements it with one std::thread for DNS, connect, network loop and
reconnect with backoff (D45, amends D42: mosquitto_loop_start() blocks
the caller on DNS and stops silently on TLS/protocol errors).
tst_mqtt tests it against a local mosquitto: messages, retained
messages, first connect and reconnect, last will, login.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-06 16:09:53 +02:00
co-authored by Claude Opus 5.5
parent e0229d6647
commit 96df60e6bd
8 changed files with 805 additions and 29 deletions
+14 -3
View File
@@ -22,9 +22,9 @@ CLAUDE.md ("Working rules").
The error itself is covered off the device by `tst_config`. Checks 3 and 4 run in the next
session on the Frame (iteration 2 testing needs it too).
- **Implementation** follows the order in DESIGN.md (steps 1–7). Step 1 (libmosquitto in
CMake and the containers) done; next: step 2 (`MqttClient`, `MosquittoClient`,
integration test).
- **Implementation** follows the order in DESIGN.md (steps 1–7). Steps 1 (libmosquitto in
CMake and the containers) and 2 (`MqttClient`, `MosquittoClient`, `tst_mqtt`) done; next:
step 3 (`HaEntity`, `HaSensor`, `HaDevice`, unit tests).
## Next steps
@@ -133,6 +133,17 @@ Known limitation: the bundled-Qt package does not support WebEngine in this iter
2.0.21 (aarch64) and the copyright file. The binary doesn't need the library yet (nothing
calls it; `--as-needed`), which changes in step 2. On the host, the GUI tests can't run in
this session (no display).
- User: no need to ask for permission to continue between the steps of this phase.
- Step 2: `MqttClient` interface, `MosquittoClient`, `tst_mqtt` (12 cases against a local
mosquitto). Reading libmosquitto 2.0.21's source showed that `mosquitto_loop_start()`
doesn't fit (blocking DNS in the caller, silent thread end on TLS/protocol errors); the
user chose an own `std::thread` (D45, amends D42). Findings: a failed first connect is
retried; libmosquitto loses the DNS error code; `strerror()` is localised (German on the
dev host), so errors use `strerrordesc_np()`. Test pitfall: `QTRY_*` evaluates its
expression once more at the end, so it must not consume data (`readAll…()`). Checked:
host 3 × 12/12; `container-test.sh` 9/9 (Debian's libmosquitto 2.0.21), no Vulkan
validation messages; cross build: private Qt symbols only `QVulkan*`, at most
`GLIBC_2.34`; the app binary links libmosquitto only from step 4 on (first use).
### 2026-10-05: requirements approved