Choose libmosquitto and an own HA discovery layer

D14: libmosquitto from Debian, shipped in the package (Qt MQTT needs the
exact Qt version; nothing on the Frame). D15: own device-based discovery
layer on Qt's JSON classes. Document the libraries per requirement and
what the Frame provides (Qt modules, OpenSSL 3.2.1, glibc 2.39).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-05 19:50:39 +02:00
co-authored by Claude Opus 5.5
parent ba6302a4c0
commit ed8b2237bd
3 changed files with 110 additions and 4 deletions
+14 -2
View File
@@ -13,8 +13,8 @@ CLAUDE.md ("Working rules").
Phase 2 for the MVP scope (D8: MQTT connection + discovery + availability, the MVP sensors, a
basic notification). Design topics, proposed order:
1. Q4: MQTT client library (licence, availability on SteamOS, TLS/login, Qt event-loop
integration, deployment).
1. ~~Q4: MQTT client library~~: done, libmosquitto (D14). Remaining for the design: Qt
event-loop integration, shipping the library in the package (build + `install.sh`).
2. Component structure: configuration, MQTT/discovery layer, sensor sources, notification
service; how they fit into `Dashboard` (the app class).
3. HA entity model: topics, discovery payloads, availability, device grouping (CON-2/3/5,
@@ -31,6 +31,18 @@ whether they constrain the MVP architecture.
### 2026-10-05: requirements approved
- User approved REQUIREMENTS.md including the priorities (D13). Phase 2 started.
- Q4 decided: libmosquitto, shipped in the package (D14). Qt MQTT ruled out: private Qt API
requires the exact Qt version. Checked on the Frame: no MQTT library installed; libssl/
libcrypto 3 and libcjson 1 present.
- HA discovery: own small layer on QJson, device-based discovery (D15); hacpp and the
embedded libraries rejected.
- Checked on the Frame which Qt modules, plugins and audio/network tools exist; library list
per requirement in REQUIREMENTS.md Appendix C. Notable: Qt WebEngine and Qt WebSockets are
present (relevant for Q2/Q3).
- libmosquitto ABI check: Debian's 2.0.21 needs at most `OPENSSL_3.0.0`/`GLIBC_2.34`; the
Frame has OpenSSL 3.2.1 and glibc 2.39. No libcjson dependency. D14 holds.
- Stay with the Debian build container: an Arch container wouldn't match SteamOS's own package
versions (private repos, rolling Arch) and has no arm64 multiarch for cross builds.
### 2026-10-04/05: project set-up and requirements
+74 -2
View File
@@ -126,9 +126,9 @@ FrameAssistant.
| # | Question | Status |
|---|----------|--------|
| Q1 | Several notifications at once: stack, queue, replace by tag? | open, design exploration |
| Q2 | Dashboard: HA's own web UI vs. native VR UI? | open, design exploration |
| Q2 | Dashboard: HA's own web UI vs. native VR UI? | open, design exploration (Qt WebEngine exists on the Frame, Appendix C) |
| Q3 | Dashboard data: HA WebSocket API (token) in addition to MQTT, or MQTT only? | open, design |
| Q4 | Which MQTT client library? Licence, availability on SteamOS, TLS/login support. | open, design |
| Q4 | Which MQTT client library? Licence, availability on SteamOS, TLS/login support. | answered: libmosquitto, shipped in the package (D14, Appendix B) |
| Q5 | Status card: own tab or part of the main tab? | answered: own tab, on demand (D9) |
| Q6 | MVP sensor list? | answered (MVP column) |
| Q7 | Minimum supported HA version? | answered: current release, no legacy features (D10) |
@@ -152,6 +152,8 @@ FrameAssistant.
| D11 | 2026-10-05 | Fixed sensor set; unsupported or missing values are "unavailable" | Same entities on every device, predictable in HA |
| D12 | 2026-10-05 | Notification confirmations are reported to HA as events, if easy | Cheap to add, useful for automations |
| D13 | 2026-10-05 | Requirements approved as drafted, priorities included (MVP = Must, other wanted features = Should, SRV-7 and NOT-10 = Could) | End of phase 1 |
| D14 | 2026-10-05 | MQTT client: **libmosquitto** from Debian's package in the build container, shipped in the release package like `libopenvr_api.so` | Not on the Frame; Qt MQTT would need the exact Qt version (Appendix B) |
| D15 | 2026-10-05 | HA MQTT discovery: **own small layer on Qt's JSON classes**, using device-based discovery (one `<prefix>/device/<id>/config` topic with all entities under `cmps`) | No suitable library (Appendix B); HA recommends device-based discovery for multi-entity devices (NFR-7) |
## Appendix A: data sources
@@ -202,3 +204,73 @@ screenshot (`RequestScreenshot`), launch apps (`IVRApplications`), notifications
- **VR session duration** (time since put on): break reminders, statistics.
- **Mic in use**: user is talking (voice chat), so don't play announcements.
- **Streaming from a PC** vs. standalone (Steam Link), if detectable.
## Appendix B: MQTT client library (Q4)
Evaluated 2026-10-05 for D14.
| | libmosquitto (C) | Qt MQTT | Eclipse Paho C/C++ |
|---|---|---|---|
| Licence | EPL-2.0 / EDL-1.0 | GPL-3 or commercial (no LGPL) | EPL-2.0 / EDL-1.0 |
| On the Frame (SteamOS, checked) | no | no | no |
| Arch repos / Debian | `mosquitto` / `libmosquitto-dev` | `qt6-mqtt` / Qt add-on | AUR only / `libpaho-mqtt-dev` |
| Login, TLS | yes (OpenSSL) | yes (QSslSocket) | yes |
- **Qt MQTT is ruled out**, not because of its licence (the user accepts GPL-3), but because it
uses Qt's private API: `QMqttClientPrivate` derives from `QObjectPrivate`. QtCore then requires
the *exact* Qt version (`checkForIncompatibleLibraryVersion()` in `qobject_p.h` calls
`qFatal("Cannot mix incompatible Qt library …")`). A Qt MQTT built against Debian's Qt 6.8.2
aborts on the Frame's Qt 6.8.0 and would break with every SteamOS Qt update. It would only
work with Qt bundled (about 46 MB instead of about 3 MB).
- **libmosquitto** does not depend on Qt. Debian trixie's `libmosquitto1` 2.0.21 (arm64)
needs only `libssl.so.3`, `libcrypto.so.3` and `libc.so.6`, with symbol versions up to
`OPENSSL_3.0.0` and `GLIBC_2.34`. The Frame has OpenSSL 3.2.1 and glibc 2.39 (checked
2026-10-05), so it fits. Licence per Debian: EPL-2.0 or EDL-1.0 (`uthash.h`: BSD-1-Clause);
the licence text must ship with the package.
- Paho: no advantage over libmosquitto; uses its own threads.
- Integration into the Qt event loop (`QSocketNotifier` on `mosquitto_socket()`) is part of the
design.
### HA discovery libraries (D15)
No library fits; discovery itself is just JSON on a config topic.
- [hacpp](https://github.com/pblxptr/hacpp) (C++, Linux): rejected. Early stage ("everything
can be changed soon"); only binary sensor, sensor, button, cover; buffers messages on
reconnect (contradicts CON-4); own MQTT client (async_mqtt) on Boost.Asio ≥ 1.90 (not on the
Frame), Conan 2, GCC 14+; its own event loop next to Qt's; TLS/login undocumented.
- [HAMqttDevice](https://github.com/plapointe6/HAMqttDevice),
[KLib-HomeAssistantMqtt](https://github.com/KazaLab/KLib-HomeAssistantMqtt),
[hamqtt](https://registry.platformio.org/libraries/dalib666/hamqtt): Arduino/embedded payload
generators with per-component topics.
- homie-cpp: implements the Homie convention, not HA discovery.
## Appendix C: libraries per requirement
Checked on the Frame 2026-10-05 (SteamOS, system Qt 6.8.0). Rule: **a Qt add-on module must
come from the Frame's system Qt.** Shipping one fails like Qt MQTT (Appendix B): Qt's modules
use Qt's private API, which requires the exact Qt version.
| Need | Requirements | Candidate | On the Frame | New dependency |
|---|---|---|---|---|
| JSON | CFG-1, CON-2 | `QJsonDocument` (QtCore) | ✓ | no |
| HA discovery | CON-2/3/5, SEN-15 | own layer (D15) | — | no |
| MQTT | CON-1 | libmosquitto (D14) | ✗, shipped; its deps `libssl.so.3`, `libcrypto.so.3` ✓ (Appendix B) | yes |
| IP address | SEN-12 | `QNetworkInterface` (QtNetwork) | ✓ | no |
| SSID, signal | SEN-12 | NetworkManager via QtDBus | ✓ `libQt6DBus`, `nmcli` | no |
| Volume, mute, output | SEN-13, SRV-3 | PipeWire via libpulse, or `wpctl`/`pactl` | ✓ `libpulse.so.0`, `libpipewire-0.3.so.0`, `wpctl`, `pactl` | to decide in design |
| Sounds, audio from URL | NOT-4, SRV-8 | Qt Multimedia + QtNetwork | ✓ `libQt6Multimedia`, FFmpeg plugin | no |
| HTTPS (downloads, WebSocket) | SRV-8, Q3 | Qt TLS plugin | ✓ `libqopensslbackend.so` | no |
| Translations | NFR-4 | `QTranslator`, `lupdate`/`lrelease` | ✓ (build-time tools) | no |
| Dashboard, HA web UI | DSH-1, Q2 | Qt WebEngine (Quick) | ✓ `libQt6WebEngineCore`, `libQt6WebEngineQuick`, `libQt6WebView` | no; works with our off-screen renderer and Vulkan? Needs a spike |
| Dashboard, native UI | DSH-1, Q2/Q3 | HA WebSocket API via Qt WebSockets | ✓ `libQt6WebSockets` | no |
| Haptics, fade, apps | SRV-1/2 | OpenVR | ✓ | no |
| Tests | NFR-8 | QtTest | ✓ (host only) | no |
Also present and possibly useful later: `libQt6TextToSpeech`, Qt's `networkinformation` plugin.
Open points:
- The Debian build container needs the matching `-dev` packages (amd64 and arm64) for every
module used. Not checked yet.
- WebEngine and Multimedia come with SteamOS's desktop (KDE) packages; a SteamOS update could
remove them.
+22
View File
@@ -62,6 +62,28 @@ Without the deploy script: copy the `.tar.gz`, unpack it on the Frame, run `./in
| Process names are cut to 15 characters | Scripts find running instances by command line, not by name |
| Floated/pinned dashboard tabs stay visible and operable in games | Rendering follows the overlay's visibility, not the dashboard's |
## Libraries on the Frame
Checked 2026-10-05; details per requirement in [REQUIREMENTS.md](REQUIREMENTS.md), Appendix C.
- **System Qt 6.8.0** under `/usr/lib` includes, besides the base modules: DBus, Network,
Multimedia (FFmpeg plugin), WebSockets, WebEngine (Core, Quick), WebView, TextToSpeech,
Positioning, Sensors, Svg, VirtualKeyboard. TLS plugins: `libqopensslbackend.so`,
`libqcertonlybackend.so`.
- It apparently comes with the KDE Plasma desktop mode (plugins for plasma, kwin, discover).
**SteamVR does not use Qt 6:** nothing under `/opt/steamvr` links or ships `libQt6*`. So the
system Qt is not a SteamVR dependency, which is one more reason to keep the bundled-Qt
fallback.
- **Qt add-on modules must come from the system Qt.** Shipping one fails: they use Qt's private
API, and QtCore aborts on any version mismatch ("Cannot mix incompatible Qt library").
- **Not present:** any MQTT library (no `libmosquitto`, no Qt MQTT). FrameAssistant ships
libmosquitto.
- **Present:** OpenSSL 3.2.1 (`libssl.so.3`, `libcrypto.so.3`), glibc 2.39, `libcjson.so.1`
(1.7.17), `libpulse.so.0`, `libpipewire-0.3.so.0`, and the tools `wpctl`, `pactl`, `nmcli`.
- **Libraries we ship must not need newer symbol versions** than the Frame has (e.g.
`OPENSSL_3.x`, `GLIBC_2.x`): check with `readelf -V`. Debian's libmosquitto needs at most
`OPENSSL_3.0.0` and `GLIBC_2.34`.
## Notes
- **The Frame's package repositories** in `/etc/pacman.conf` are private (URLs marked