Der nächste Layer ist jetzt als echte gemeinsame Außenkante umgesetzt. Das neue API-Crate in [server.rs](</C:/Users/janni/Documents/RFP/Infinity_Vis _Rust/crates/infinity_host_api/src/server.rs>), [dto.rs](</C:/Users/janni/Documents/RFP/Infinity_Vis _Rust/crates/infinity_host_api/src/dto.rs>) und [main.rs](</C:/Users/janni/Documents/RFP/Infinity_Vis _Rust/crates/infinity_host_api/src/main.rs>) stellt die geforderten versionierten Endpunkte bereit: GET /api/v1/snapshot, GET /api/v1/catalog, GET /api/v1/presets, GET /api/v1/groups, POST /api/v1/command und WS /api/v1/stream. Die API trennt jetzt sauber zwischen Command-, State-, Preview- und Event-Modell, inklusive stabiler Außen-Enums und dokumentierten Fehlerobjekten statt eines unreflektierten 1:1-Core-Leaks.

Darauf sitzt die erste Web-UI V1 direkt gegen diese API in [index.html](</C:/Users/janni/Documents/RFP/Infinity_Vis _Rust/web/v1/index.html>), [app.js](</C:/Users/janni/Documents/RFP/Infinity_Vis _Rust/web/v1/app.js>) und [styles.css](</C:/Users/janni/Documents/RFP/Infinity_Vis _Rust/web/v1/styles.css>). Sie enthält Pattern-/Preset-Auswahl, globale Regler, Gruppenauswahl, Übergänge, Preview, Snapshot-Anzeige und Event-Feed. Die technische Desktop-GUI bleibt bewusst die Engineering-/Diagnoseoberfläche; die kreative Web-UI baut nicht an einer Parallelarchitektur vorbei.

Contract-Tests liegen in [contract.rs](</C:/Users/janni/Documents/RFP/Infinity_Vis _Rust/crates/infinity_host_api/tests/contract.rs>), und die API ist mit Beispiel-Responses in [docs/host_api.md](</C:/Users/janni/Documents/RFP/Infinity_Vis _Rust/docs/host_api.md>) dokumentiert. Zusätzlich habe ich [README.md](</C:/Users/janni/Documents/RFP/Infinity_Vis _Rust/README.md>), [docs/build_and_deploy.md](</C:/Users/janni/Documents/RFP/Infinity_Vis _Rust/docs/build_and_deploy.md>) und [docs/architecture.md](</C:/Users/janni/Documents/RFP/Infinity_Vis _Rust/docs/architecture.md>) auf den neuen Stand gebracht.

Verifiziert habe ich:
- `cargo check -p infinity_host_api`
- `cargo test -p infinity_host_api`
- `cargo test -q`

Nicht verifiziert habe ich eine separate JS-Syntaxprüfung mit `node --check`, weil `node` in dieser Umgebung nicht installiert ist.
This commit is contained in:
2026-04-17 11:58:07 +02:00
parent 9457666fd6
commit a37a3c5cbe
16 changed files with 3166 additions and 55 deletions

View File

@@ -101,7 +101,8 @@ The codebase deliberately blocks activation when these remain unresolved:
## Planned Next Steps
1. Add a network-facing adapter for the shared host API and start the web UI
2. Expand scene authoring and preset editing on top of the existing simulation core
1. Expand creative authoring on top of the now-versioned host API and web UI
2. Keep the engineering GUI focused on mapping, diagnostics, topology, and admin
3. Implement transport adapters without coupling them to any single frontend
4. Keep hardware activation behind explicit later validation gates
4. Add future external show-control bridges such as grandMA on the same API boundary
5. Keep hardware activation behind explicit later validation gates

View File

@@ -12,12 +12,15 @@ Suggested commands:
```powershell
cargo test
cargo run -p infinity_host -- snapshot --config config/project.example.toml
cargo run -p infinity_host_api -- --config config/project.example.toml --bind 127.0.0.1:9001
cargo run -p infinity_host_ui
cargo run -p infinity_host -- validate --config config/project.example.toml --mode structural
cargo run -p infinity_host -- plan-boot-scene --config config/project.example.toml --preset-id safe_static_blue
```
The native engineering UI and the CLI snapshot currently run against the simulation-backed host API so looks, presets, grouping, and parameter flow can be exercised before transport and firmware integration are complete.
The host API server now exposes the common software-first control boundary over HTTP and WebSocket. The creative web UI is served directly from the same process at `http://127.0.0.1:9001/`.
The native engineering UI and the CLI snapshot continue to run against the same simulation-backed host core so looks, presets, grouping, and parameter flow can be exercised before transport and firmware integration are complete.
Before any live activation, run:

View File

@@ -2,79 +2,341 @@
## Purpose
The host API is the stable boundary that all operator surfaces and later external show-control adapters must use.
The host API is the stable external boundary for:
Current rule:
- the creative web UI
- the existing engineering GUI
- future external show-control adapters such as grandMA
- no UI is allowed to become the realtime clock
- no frontend-specific assumptions are allowed to leak into scene simulation or transport planning
- future grandMA support must land as an adapter on this API, not as a special-case core path
The core rule stays unchanged:
- the API is a control and observation layer
- the realtime engine remains the timing authority
- no surface is allowed to become the LED clock
## Current Implementation
The API lives in:
Runtime pieces:
- `crates/infinity_host/src/control.rs`
- `crates/infinity_host/src/scene.rs`
- `crates/infinity_host/src/simulation.rs`
- `crates/infinity_host_api/src/dto.rs`
- `crates/infinity_host_api/src/server.rs`
The engineering GUI already consumes this API through the `HostApiPort` / `HostUiPort` trait boundary.
The network-facing server is started with:
## Snapshot Model
```powershell
cargo run -p infinity_host_api -- --config config/project.example.toml --bind 127.0.0.1:9001
```
`HostSnapshot` currently exposes:
Creative web UI V1 is served by the same process at:
- system metadata
- global controls
- engine timing and transition state
- catalog of patterns, presets, and groups
- active scene with parameter values
- simulated preview panels
- node and panel status
- recent event log
```text
http://127.0.0.1:9001/
```
This makes it suitable as the shared read model for:
## Versioning
- engineering GUI
- upcoming web UI
- CLI inspection
- later external control bridges
- HTTP and WebSocket routes are versioned under `/api/v1`
- responses include `api_version: "v1"`
- the external DTOs are intentionally not a direct 1:1 dump of internal core structs
## Command Model
## Endpoint Contract
`HostCommand` currently supports:
### GET `/api/v1/snapshot`
Returns the current state and preview in one response.
Example:
```json
{
"api_version": "v1",
"generated_at_millis": 241,
"state": {
"system": {
"project_name": "Infinity Vis",
"schema_version": 1,
"topology_label": "6 nodes / 18 outputs / 106 LEDs"
},
"global": {
"blackout": false,
"master_brightness": 0.2,
"selected_pattern": "solid_color",
"selected_group": null,
"transition_duration_ms": 150
},
"engine": {
"logic_hz": 120,
"frame_hz": 60,
"preview_hz": 15,
"uptime_ms": 241,
"frame_index": 14,
"dropped_frames": 0,
"active_transition": null
},
"active_scene": {
"preset_id": null,
"pattern_id": "solid_color",
"seed": 100,
"palette": [
"#ffffff"
],
"parameters": [],
"target_group": null,
"blackout": false
}
},
"preview": {
"generated_at_millis": 241,
"panels": [
{
"node_id": "node-01",
"panel_position": "top",
"representative_color_hex": "#33CCFF",
"sample_led_hex": [
"#33CCFF",
"#28A3CC",
"#1E7A99"
],
"energy_percent": 28,
"source": "scene"
}
]
}
}
```
### GET `/api/v1/catalog`
Returns the creative catalog:
- patterns
- presets
- groups
### GET `/api/v1/presets`
Returns only preset summaries.
Example:
```json
{
"api_version": "v1",
"presets": [
{
"preset_id": "ocean_gradient",
"pattern_id": "gradient",
"target_group": null,
"transition_duration_ms": 320
}
]
}
```
### GET `/api/v1/groups`
Returns only group summaries.
Example:
```json
{
"api_version": "v1",
"groups": [
{
"group_id": "top_panels",
"member_count": 6,
"tags": [
"row",
"top"
]
}
]
}
```
### POST `/api/v1/command`
Accepts a versioned command envelope.
Example request:
```json
{
"request_id": "web-1713352662000",
"command": {
"type": "set_master_brightness",
"payload": {
"value": 0.42
}
}
}
```
Example response:
```json
{
"api_version": "v1",
"accepted": true,
"request_id": "web-1713352662000",
"generated_at_millis": 522,
"summary": "master brightness set to 42%"
}
```
Errors use a stable error object:
```json
{
"api_version": "v1",
"error": {
"code": "invalid_command",
"message": "command request was rejected: missing field `enabled`"
}
}
```
### WS `/api/v1/stream`
The WebSocket stream emits envelopes with a monotonic sequence and a typed payload.
Stream message types:
- `snapshot`
- `preview`
- `event`
Example snapshot envelope:
```json
{
"api_version": "v1",
"sequence": 17,
"generated_at_millis": 875,
"message": {
"type": "snapshot",
"payload": {
"global": {
"blackout": false,
"master_brightness": 0.35,
"selected_pattern": "gradient",
"selected_group": "top_panels",
"transition_duration_ms": 320
}
}
}
}
```
Example preview envelope:
```json
{
"api_version": "v1",
"sequence": 18,
"generated_at_millis": 875,
"message": {
"type": "preview",
"payload": {
"generated_at_millis": 875,
"panels": [
{
"node_id": "node-01",
"panel_position": "top",
"representative_color_hex": "#FF8A5B",
"sample_led_hex": [
"#FF8A5B",
"#F36E43",
"#D85A2F"
],
"energy_percent": 47,
"source": "transition"
}
]
}
}
}
```
Example event envelope:
```json
{
"api_version": "v1",
"sequence": 19,
"generated_at_millis": 880,
"message": {
"type": "event",
"payload": {
"kind": "info",
"message": "preset recalled: ocean_gradient"
}
}
}
```
## Supported Commands
The current API command set covers:
- `set_blackout`
- `set_master_brightness`
- `select_pattern`
- `recall_preset`
- `select_group`
- `set_scene_parameter`
- `set_transition_duration_ms`
- `trigger_panel_test`
This is intentionally enough for:
- creative look development in the web UI
- engineering test triggers in the native GUI
- future external show-control translation layers
## Web UI V1
The first creative web UI is intentionally limited to:
- blackout
- master brightness
- pattern selection
- preset recall
- group selection
- scene parameter changes
- transition duration changes
- per-panel test triggers
- global brightness
- blackout
- transition duration
- scene parameter controls driven from the API schema
- panel preview
- snapshot display
- event feed
## Simulation Layer
It does not absorb mapping, topology, or hardware-diagnostic workflows. Those stay in the native engineering UI.
The current `SimulationHostService` is not a throwaway mock. It is the software-first runtime for:
## Contract Tests
- look exploration
- preset development
- parameter tuning
- future web UI integration
- API contract testing before hardware activation
The API contract is currently verified in:
It simulates:
- `crates/infinity_host_api/tests/contract.rs`
- active scene state
- pattern rendering previews
- group gating
- transitions
- node connectivity status
- per-panel mapping tests
Covered paths:
## Near-Term Direction
- root web shell
- `GET /api/v1/snapshot`
- `GET /api/v1/catalog`
- `GET /api/v1/presets`
- `GET /api/v1/groups`
- `POST /api/v1/command`
- `WS /api/v1/stream`
1. Keep extending this API instead of adding surface-specific data paths.
2. Add a network-facing adapter for the same API when the web UI starts.
3. Keep engineering GUI focused on topology, mapping, diagnostics, and admin.
4. Add grandMA later as an external show-control adapter against this API.
## Future Direction
Next adapters should be built on this boundary instead of reaching into the host core directly.
That includes:
- a richer web authoring surface
- remote operator clients
- a grandMA bridge that translates external show control into host API commands