Document iteration 1: settings file, HA Dashboard tab, new hooks
README: settings file, --config, the new tab. ARCHITECTURE.md and CLAUDE.md: prepare() hook, app command-line options, app code layout, WebEngine notes, the moc raw-string pitfall. THIRD_PARTY_NOTICES: Qt WebEngine. Ship config.example.json; the package README explains the set-up. PROGRESS.md and DESIGN.md: phase 3 results and deviations. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+23
-10
@@ -37,13 +37,19 @@ the order in which all of that is created and destroyed.
|
||||
|
||||
Your app derives from it:
|
||||
- **Constructor:** configuration (`addSurface()`, optionally `setAppKey()`,
|
||||
`setDisplayName()`, `setQuickStyle()`, `setQmlModule()`).
|
||||
`setDisplayName()`, `setQuickStyle()`, `setQmlModule()`). The app's own command-line
|
||||
options go to the base constructor as a list of `QCommandLineOption`s; they are parsed and
|
||||
listed in `--help` with the built-in ones, and read with `isOptionSet()`/`optionValue()`.
|
||||
- **Hooks:**
|
||||
- `prepare(QString* error)`: first, once mode and app key are known, before the QML
|
||||
engine, the surfaces and SteamVR exist (not for manifest commands). Returning `false`
|
||||
ends `exec()` with the error and exit code 1, e.g. for invalid settings.
|
||||
- `loading()`: the shared QML engine, the surfaces and their render backends exist; QML
|
||||
isn't loaded yet. Set up what the QML needs here.
|
||||
- `started()`: everything runs. Connect to surfaces and input here.
|
||||
- **Accessors:** `mode()`, `appKey()`, `appName()`, `engine()`, `surfaces()`, `surface()`
|
||||
(the first), `surface(id)`, `vrRuntime()`, `navigation()`.
|
||||
- **Accessors:** `mode()`, `appKey()`, `appName()`, `isOptionSet()`, `optionValue()`,
|
||||
`engine()`, `surfaces()`, `surface()` (the first), `surface(id)`, `vrRuntime()`,
|
||||
`navigation()`.
|
||||
- **Lifetime:** the base constructor creates the `QGuiApplication`, so your members can be
|
||||
QObjects with timers. All QML and surfaces are torn down at the end of `exec()`, while your
|
||||
object and its members still exist.
|
||||
@@ -121,15 +127,16 @@ sequenceDiagram
|
||||
## Start and shutdown (overlay mode)
|
||||
|
||||
1. **Start:**
|
||||
1. Connect to SteamVR (`VR_Init`).
|
||||
2. Create one render backend per surface. The first surface decides the API, including a
|
||||
1. Call `prepare()`; stop with exit code 1 if it fails.
|
||||
2. Connect to SteamVR (`VR_Init`).
|
||||
3. Create one render backend per surface. The first surface decides the API, including a
|
||||
fallback to OpenGL; the others use the same API, because Qt's graphics API is
|
||||
process-wide.
|
||||
3. Call `loading()`.
|
||||
4. Load each surface's QML.
|
||||
5. Create the overlays.
|
||||
6. Set up controller navigation.
|
||||
7. Call `started()`, then run the event loop.
|
||||
4. Call `loading()`.
|
||||
5. Load each surface's QML.
|
||||
6. Create the overlays.
|
||||
7. Set up controller navigation.
|
||||
8. Call `started()`, then run the event loop.
|
||||
2. **Shutdown runs in reverse**, with one rule found on the Frame: **overlays first, then
|
||||
SteamVR, then the graphics devices.** OpenVR requires shutting down before the devices it
|
||||
got textures from are destroyed. Otherwise its client library frees objects on a dead
|
||||
@@ -160,3 +167,9 @@ For e.g. a notification app: a `WorldOverlay` (another `Overlay` subclass, creat
|
||||
(`VROverlayFlags_MakeOverlaysInteractiveIfVisible`).
|
||||
|
||||
The surface structure is ready for it: `SurfaceConfig` would gain a kind and a placement.
|
||||
|
||||
## FrameAssistant on top
|
||||
|
||||
The app itself (`src/Dashboard.*`, `src/config/`, `src/ha/`, `src/qml/`) builds on this
|
||||
platform; its design (Home Assistant connection, entities, overlays, threads) is in
|
||||
[DESIGN.md](DESIGN.md).
|
||||
|
||||
+6
-4
@@ -150,7 +150,7 @@ and signals across threads are delivered through the receiver's event loop.
|
||||
| **I/O wrappers** | Data sources and actuators; know nothing about HA. One wrapper object per OpenVR interface used (e.g. `IVRSystem`, `IVRApplications`, `IVRChaperone`, `IVRSettings`). System wrappers (network, audio) later. | OpenVR ✓, system ✗ |
|
||||
| **Overlays** | View and controller of MVC (QML), as dashboard tabs or world overlays. Get their data (the model) from other objects. | ✓ |
|
||||
| **Managers** | One object per stateful feature that manages and coordinates it, using entities, services and overlays. Notification manager (MVP); status card manager (SRV-6/7) later. | notifications ✓ |
|
||||
| **HA web UI** | Encapsulates Qt WebEngine for the dashboard tab (DSH-1; Q2 for DSH-2). | ✓ (DSH-1) |
|
||||
| **HA web UI** | Encapsulates Qt WebEngine for the dashboard tab (DSH-1; Q2 for DSH-2). `src/ha/HaWebUi`, a QML singleton in the app itself (not `frameassistant_lib`: QML types must be part of the QML module). | ✓ (DSH-1) |
|
||||
| **Configuration** | Settings from the JSON file, loaded once by the app as an immutable value. Each component gets the part it needs through its constructor (D19). | ✓ |
|
||||
| **App** | The managing object: owns all of the above as components and wires them together. | ✓ |
|
||||
|
||||
@@ -314,10 +314,12 @@ Layout follows common practice (e.g. Zigbee2MQTT's `…/<device>/set`); one topi
|
||||
code ≠ 0 (CFG-2, via the start-up hook D21).
|
||||
- Unknown keys: a warning in the log, no abort (catches typos without breaking across
|
||||
versions).
|
||||
- Password in plain text: warn if the file is readable by others; otherwise file permissions
|
||||
(`chmod 600`).
|
||||
- Password in plain text: warn if the file holds a password and is readable by others;
|
||||
otherwise file permissions (`chmod 600`). (Implemented this way: a readable file without a
|
||||
password is harmless.)
|
||||
- Throttle intervals (SEN-14) are fixed per entity in the code for the MVP.
|
||||
- A `config.example.json` ships in the package.
|
||||
- A `config.example.json` ships in the package (`share/frameassistant/`); the package's
|
||||
README.txt explains how to set it up.
|
||||
- To check on the Frame when TLS is implemented: where the system certificates are
|
||||
(`/etc/ssl/certs`?), for the `ca_file` default.
|
||||
|
||||
|
||||
+23
-3
@@ -5,9 +5,12 @@ CLAUDE.md ("Working rules").
|
||||
|
||||
## Current state
|
||||
|
||||
- **Implementation iteration 1 (DSH-1 and configuration), phase 3 (implementation).**
|
||||
Requirements (D13) and design ([DESIGN.md](DESIGN.md)) are approved; the plan below was
|
||||
approved on 2026-10-05.
|
||||
- **Implementation iteration 1 (DSH-1 and configuration), phase 3 (implementation) done,
|
||||
waiting for the user's approval.** All plan steps are implemented and committed; next is
|
||||
phase 4, testing on the Frame (plan item 10).
|
||||
- **Open point found:** started by SteamVR, the app writes no log file (the manifest passes no
|
||||
`--log-file`, stderr goes to SteamVR). CFG-2 wants the settings error "in the log file and
|
||||
on stderr". To be decided.
|
||||
|
||||
## Next steps
|
||||
|
||||
@@ -77,6 +80,23 @@ Known limitation: the bundled-Qt package does not support WebEngine in this iter
|
||||
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.
|
||||
- Phase 3 of implementation iteration 1:
|
||||
- Platform: `prepare()` hook and app-specific command-line options, tested in
|
||||
`tst_surfaces` (incl. `surfaces_prepare_fail`).
|
||||
- Settings file (`src/config/`, new library `frameassistant_lib`), `--config`; `tst_config`
|
||||
(37 cases). `config.example.json` in the package; README.txt explains the set-up.
|
||||
- "HA Dashboard" tab: `WebEngineView`, `HaWebUi` with a persistent profile, WebEngine
|
||||
initialisation in `main()`. Host: desktop mode loads a local test page, profile data
|
||||
lands in `~/.local/share/frameassistant/webengine`; snapshot renders both tabs.
|
||||
- Build containers with Qt WebEngine. Cross build: the aarch64 binary needs no private Qt
|
||||
symbols, at most `Qt_6.8` and `GLIBC_2.34`. Container tests 8/8 (incl. Vulkan with
|
||||
validation layers, no messages).
|
||||
- Snags: moc misses classes in files with raw strings containing `//` (CLAUDE.md);
|
||||
generated QML type registration includes headers by file name; Qt ≥ 6.9 hints at
|
||||
`WebEngineProfilePrototype` (not in the Frame's 6.8). Deviations: `HaWebUi` lives in the
|
||||
app, not the library; the password warning needs a password in the file.
|
||||
- Not verified yet: WebEngine with a URL in the off-screen pipeline (Frame, phase 4); the
|
||||
bundled package (not supported for WebEngine in this iteration).
|
||||
- Plan for implementation iteration 1 approved; phase 3 started.
|
||||
- Plan for implementation iteration 1 written; new tab "HA Dashboard" (D38, D39).
|
||||
- MVP implemented in four iterations; DSH-1 first, at the user's wish (D37).
|
||||
|
||||
Reference in New Issue
Block a user