Start the design document with the high-level architecture

DESIGN.md: one process with several threads (D16), three layers (D17),
HA-centric object classes (D18), injected configuration (D19). Design
decisions move from REQUIREMENTS.md to DESIGN.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-05 20:46:23 +02:00
co-authored by Claude Opus 5.5
parent ed8b2237bd
commit f6c5de4fb9
5 changed files with 86 additions and 16 deletions
+63
View File
@@ -0,0 +1,63 @@
# Design
Status: **in progress**, iteration 1, phase 2 (planning and design). High-level architecture
first, then the details for the MVP. Requirements and their decisions (D1–D15):
[REQUIREMENTS.md](REQUIREMENTS.md). Design decisions start at D16.
## Process and threads
- **One process** started by SteamVR does everything: HA connection, sensors, services, all
overlays (D16).
- Several threads inside it for concurrent work. Which work runs in which thread is still open.
## Layers
Three layers; dependencies only go downward (D17).
```
Presentation QML (view and controller)
▼
Business logic entities, services, managers
▼
I/O HA connection (MQTT), SteamVR, system (network, audio)
```
- Qt Quick already enforces separating presentation from logic.
- The overlay platform (`vrdashboard_core`) spans two layers: overlays, rendering and input
are presentation infrastructure; SteamVR access for sensors and actions is I/O.
## Object classes
The app is HA-centric, so its building blocks follow HA's concepts (D18). Objects talk to each
other through Qt signals and slots (Qt's observer pattern). Senders don't know their receivers,
and signals across threads are delivered through the receiver's event loop.
| Class | Role | MVP |
|---|---|---|
| **HA entity** | One HA entity, both directions. Entity → HA: state and JSON attributes. HA → entity: basic commands. Observes value signals of other objects and publishes them; turns MQTT commands into signals other objects act on. Covers sensors, simple actions (`button`), settings (`switch`, `number`), feedback (`event`). | ✓ |
| **HA service** | An action HA calls with parameters: a JSON command on an MQTT command topic (HA side: the standard `mqtt.publish` action). May be more complex than an entity command. Results go back asynchronously, e.g. through an `event` entity. How the user wraps it in HA (scripts, automations, pyscript) is their choice; FrameAssistant only requires stock HA with MQTT (NFR-6). | ✓ (notification) |
| **HA device** | Owns the MQTT connection, discovery and availability, and owns all entity and service objects. One per headset (CON-5). | ✓ |
| **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 (Q2). | ✗ |
| **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. | ✓ |
Notes for later:
- OpenVR delivers all events through one queue; one dispatcher (today `VrRuntime`) hands them
to the wrappers.
- OpenVR is not documented as thread-safe (relevant for the thread decision).
## Open
1. High-level points 3–7 (see [PROGRESS.md](PROGRESS.md), "Next steps").
## Decisions
| # | Date | Decision | Reason |
|---|------|----------|--------|
| D16 | 2026-10-05 | **One process** started by SteamVR does everything; several threads inside it for concurrent work | Meets NFR-2 without extra work, no IPC; the platform already supports several surfaces per process |
| D17 | 2026-10-05 | **Three layers:** presentation (QML), business logic, I/O. The overlay platform spans presentation (overlays, rendering, input) and I/O (SteamVR access) | Simple and enough for the start; Qt Quick already enforces separating presentation from logic |
| D18 | 2026-10-05 | **HA-centric object classes:** HA entity, HA service, HA device, I/O wrappers, overlays, managers, HA web UI, configuration, app; communication through signals and slots | The app is HA-centric; signals/slots decouple objects and work across threads |
| D19 | 2026-10-05 | **Configuration is injected:** the app loads it once as an immutable value and passes each component the part it needs; no singleton | Explicit dependencies, trivial tests with own configs, thread-safe; the app creates all components anyway |