Die gemeinsame Plattform ist jetzt softwareseitig deutlich vollständiger. Der Host-Core hat mit [show_store.rs](</C:/Users/janni/Documents/RFP/Infinity_Vis _Rust/crates/infinity_host/src/show_store.rs>) eine echte Runtime-Bibliothek und Persistenz für aktive Szene, Runtime-Presets, Runtime-Gruppen und kreative Varianten bekommen; die Simulation in [simulation.rs](</C:/Users/janni/Documents/RFP/Infinity_Vis _Rust/crates/infinity_host/src/simulation.rs>) liefert jetzt typisierte Command-Ergebnisse, saubere Fehlercodes und persistiert nach data/runtime_state.json. Dazu kommt das generische External-Show-Control-Interface in [external_control.rs](</C:/Users/janni/Documents/RFP/Infinity_Vis _Rust/crates/infinity_host/src/external_control.rs>), damit spätere Adapter nur auf definierte Commands und Snapshot-/Preset-/Parameter-Flächen zugreifen.

Die API v1 ist als Produktgrenze geschärft in [dto.rs](</C:/Users/janni/Documents/RFP/Infinity_Vis _Rust/crates/infinity_host_api/src/dto.rs>) und [server.rs](</C:/Users/janni/Documents/RFP/Infinity_Vis _Rust/crates/infinity_host_api/src/server.rs>): getrennte Modelle für `state`, `preview`, `snapshot`, `command response`, `event stream` und stabile Fehlerobjekte mit echten Codes statt generischem Fallback. Dazu kamen `GET /api/v1/state` und `GET /api/v1/preview`, neue persistenzbezogene Commands wie `save_preset`, `save_creative_snapshot`, `recall_creative_snapshot`, `set_transition_style` und `upsert_group`, plus serverseitige Durchreichung der echten Fehlercodes. Die kreative Web-UI 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>) nutzt jetzt genau diese API für Preset-Speichern/Überschreiben, Varianten, Transition-Style, filterbaren Eventfeed und klarere Preview-Darstellung, ohne Parallelarchitektur.

Die Doku ist auf den neuen Stand gezogen in [docs/host_api.md](</C:/Users/janni/Documents/RFP/Infinity_Vis _Rust/docs/host_api.md>), [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>). Verifiziert habe ich `cargo check -q` und `cargo test -q`; dabei laufen die erweiterten Contract- und Persistenztests in [contract.rs](</C:/Users/janni/Documents/RFP/Infinity_Vis _Rust/crates/infinity_host_api/tests/contract.rs>) sowie neue Core-Tests in [show_store.rs](</C:/Users/janni/Documents/RFP/Infinity_Vis _Rust/crates/infinity_host/src/show_store.rs>) und [simulation.rs](</C:/Users/janni/Documents/RFP/Infinity_Vis _Rust/crates/infinity_host/src/simulation.rs>). Nicht separat verifiziert habe ich einen echten Browserlauf der Web-UI; die JS-Datei wurde hier nicht mit `node` geprüft, weil `node` in dieser Umgebung nicht installiert ist.
This commit is contained in:
2026-04-17 12:34:03 +02:00
parent a37a3c5cbe
commit 8e19f535ae
20 changed files with 2399 additions and 459 deletions

View File

@@ -55,6 +55,13 @@ Every surface must talk to the same host API:
- CLI inspection
- future grandMA adapter
The host core now also carries a runtime show store and persistence layer for:
- saved presets
- runtime user groups
- active scene state
- creative snapshots and variants
The current software-first implementation uses a simulation-backed host API so looks, presets, parameters, and grouping can be developed before real node activation.
## Modes
@@ -104,5 +111,5 @@ The codebase deliberately blocks activation when these remain unresolved:
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. Add future external show-control bridges such as grandMA on the same API boundary
4. Add future external show-control bridges such as grandMA on the same API boundary and generic adapter interface
5. Keep hardware activation behind explicit later validation gates

View File

@@ -12,13 +12,13 @@ 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_api -- --config config/project.example.toml --bind 127.0.0.1:9001 --runtime-state data/runtime_state.json
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 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 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/`. Runtime creative data such as saved presets, groups, active scene state, and creative snapshots are persisted to `data/runtime_state.json` by default.
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.

View File

@@ -2,58 +2,107 @@
## Purpose
The host API is the stable external boundary for:
The host API is the stable external product boundary for:
- the creative web UI
- the existing engineering GUI
- future external show-control adapters such as grandMA
- the native engineering GUI
- future remote operator clients
- later external show-control adapters such as a grandMA bridge
The core rule stays unchanged:
The realtime rule remains strict:
- the API is a control and observation layer
- the realtime engine remains the timing authority
- no surface is allowed to become the LED clock
- the host core remains the timing authority
- no frontend or external adapter is allowed to become the LED clock
## Current Implementation
## Runtime Components
Runtime pieces:
Core and API implementation:
- `crates/infinity_host/src/control.rs`
- `crates/infinity_host/src/scene.rs`
- `crates/infinity_host/src/show_store.rs`
- `crates/infinity_host/src/simulation.rs`
- `crates/infinity_host/src/external_control.rs`
- `crates/infinity_host_api/src/dto.rs`
- `crates/infinity_host_api/src/server.rs`
The network-facing server is started with:
Server startup:
```powershell
cargo run -p infinity_host_api -- --config config/project.example.toml --bind 127.0.0.1:9001
cargo run -p infinity_host_api -- --config config/project.example.toml --bind 127.0.0.1:9001 --runtime-state data/runtime_state.json
```
Creative web UI V1 is served by the same process at:
Creative web UI V1 is served by the same process:
```text
http://127.0.0.1:9001/
```
## Versioning
## Versioning Policy
- 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
The current public contract is `v1`.
## Endpoint Contract
Rules:
### GET `/api/v1/snapshot`
- all public HTTP and WebSocket routes are namespaced under `/api/v1`
- every response body carries `api_version: "v1"`
- additive fields are allowed inside `v1`
- semantic breaking changes require a new version namespace
- external consumers must treat undocumented internal-only fields as unstable and ignore them
Returns the current state and preview in one response.
## Stable External Models
Stable external response families:
- command response
- state snapshot
- preview snapshot
- combined snapshot
- catalog
- event stream
- typed error object
Stable external command families:
- global control
- pattern and preset selection
- group targeting
- scene parameter updates
- transition configuration
- preset persistence
- creative snapshot persistence and recall
- panel test trigger
## Internal Versus External Fields
External and stable in `v1`:
- every field defined in `crates/infinity_host_api/src/dto.rs`
- route names and payload shapes documented below
- error object shape `{ api_version, error: { code, message } }`
- event stream envelope shape `{ api_version, sequence, generated_at_millis, message }`
Internal and not part of the API contract:
- the exact shape of `HostSnapshot` in `crates/infinity_host/src/control.rs`
- simulation-only storage layout in `data/runtime_state.json`
- internal event history buffering size
- internal scene library structures in `show_store.rs`
- engineering-GUI-specific rendering or polling behavior
## HTTP Endpoints
### GET `/api/v1/state`
Returns only the stable state snapshot.
Example:
```json
{
"api_version": "v1",
"generated_at_millis": 241,
"generated_at_millis": 512,
"state": {
"system": {
"project_name": "Infinity Vis",
@@ -63,104 +112,113 @@ Example:
"global": {
"blackout": false,
"master_brightness": 0.2,
"selected_pattern": "solid_color",
"selected_group": null,
"transition_duration_ms": 150
"selected_pattern": "gradient",
"selected_group": "top_panels",
"transition_duration_ms": 320,
"transition_style": "chase"
},
"engine": {
"logic_hz": 120,
"frame_hz": 60,
"preview_hz": 15,
"uptime_ms": 241,
"frame_index": 14,
"uptime_ms": 512,
"frame_index": 30,
"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
"active_transition": {
"style": "chase",
"from_pattern_id": "solid_color",
"to_pattern_id": "gradient",
"duration_ms": 320,
"progress": 0.28
}
}
},
}
}
```
### GET `/api/v1/preview`
Returns only the stable preview snapshot.
Example:
```json
{
"api_version": "v1",
"generated_at_millis": 512,
"preview": {
"generated_at_millis": 241,
"generated_at_millis": 512,
"panels": [
{
"node_id": "node-01",
"panel_position": "top",
"representative_color_hex": "#33CCFF",
"representative_color_hex": "#FF8A5B",
"sample_led_hex": [
"#33CCFF",
"#28A3CC",
"#1E7A99"
"#FF8A5B",
"#F36E43",
"#D85A2F"
],
"energy_percent": 28,
"source": "scene"
"energy_percent": 47,
"source": "transition"
}
]
}
}
```
### GET `/api/v1/snapshot`
Returns the convenience composition of `state` plus `preview`.
This route exists for lightweight clients and debugging. Consumers that want strict separation should prefer `GET /api/v1/state` and `GET /api/v1/preview`.
### GET `/api/v1/catalog`
Returns the creative catalog:
Returns the stable creative library:
- patterns
- presets
- groups
- creative snapshots
Example preset summary:
```json
{
"preset_id": "ocean_gradient",
"pattern_id": "gradient",
"target_group": null,
"transition_duration_ms": 320,
"transition_style": "crossfade",
"source": "built_in"
}
```
Example creative snapshot summary:
```json
{
"snapshot_id": "variant_floor",
"label": "Variant Floor",
"pattern_id": "noise",
"target_group": "bottom_panels",
"transition_duration_ms": 220,
"transition_style": "chase",
"saved_at_unix_ms": 1760000000000
}
```
### 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.
Accepts one versioned command envelope.
Example request:
@@ -168,9 +226,11 @@ Example request:
{
"request_id": "web-1713352662000",
"command": {
"type": "set_master_brightness",
"type": "save_creative_snapshot",
"payload": {
"value": 0.42
"snapshot_id": "variant_floor",
"label": "Variant Floor",
"overwrite": false
}
}
}
@@ -184,85 +244,44 @@ Example response:
"accepted": true,
"request_id": "web-1713352662000",
"generated_at_millis": 522,
"summary": "master brightness set to 42%"
"command_type": "save_creative_snapshot",
"summary": "creative snapshot saved: variant_floor"
}
```
Errors use a stable error object:
## Stable Error Object
All API failures return:
```json
{
"api_version": "v1",
"error": {
"code": "invalid_command",
"message": "command request was rejected: missing field `enabled`"
"code": "unknown_creative_snapshot",
"message": "creative snapshot 'does_not_exist' does not exist"
}
}
```
Stable `v1` error families currently include:
- `invalid_request_json`
- `invalid_command`
- `unknown_group`
- `unknown_preset`
- `unknown_creative_snapshot`
- `preset_exists`
- `snapshot_exists`
- `group_exists`
- `persist_failed`
- `missing_websocket_key`
- `not_found`
## WebSocket Event Stream
### 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:
The stream emits a typed envelope with a monotonic sequence counter:
```json
{
@@ -272,16 +291,29 @@ Example event envelope:
"message": {
"type": "event",
"payload": {
"kind": "info",
"message": "preset recalled: ocean_gradient"
"kind": "warning",
"code": "unknown_creative_snapshot",
"message": "creative snapshot 'does_not_exist' does not exist"
}
}
}
```
## Supported Commands
Stable message types:
The current API command set covers:
- `snapshot`
- `preview`
- `event`
Stable event kinds:
- `info`
- `warning`
- `error`
## Guaranteed Commands In `v1`
Guaranteed control commands:
- `set_blackout`
- `set_master_brightness`
@@ -290,53 +322,76 @@ The current API command set covers:
- `select_group`
- `set_scene_parameter`
- `set_transition_duration_ms`
- `set_transition_style`
- `trigger_panel_test`
This is intentionally enough for:
Guaranteed persistence and creative-library commands:
- creative look development in the web UI
- engineering test triggers in the native GUI
- future external show-control translation layers
- `save_preset`
- `save_creative_snapshot`
- `recall_creative_snapshot`
- `upsert_group`
## Web UI V1
## Persistence Behavior
The first creative web UI is intentionally limited to:
The simulation-backed host service now persists runtime-facing creative data to `data/runtime_state.json` by default.
- pattern selection
- preset recall
- group selection
- global brightness
- blackout
- transition duration
- scene parameter controls driven from the API schema
- panel preview
- snapshot display
- event feed
Persisted data includes:
It does not absorb mapping, topology, or hardware-diagnostic workflows. Those stay in the native engineering UI.
- active scene
- global blackout and brightness state
- transition duration and style
- runtime user presets
- runtime user groups
- creative snapshots and variants
## Contract Tests
This persistence file is an internal runtime artifact, not the public API contract.
The API contract is currently verified in:
## External Show Control Adapter Boundary
The generic internal adapter surface lives in:
- `crates/infinity_host/src/external_control.rs`
Key rule:
- future adapters may only translate external intent into the defined host command surface
- they must not reach into simulation internals, UI state, or hardware driver details directly
## Contract And Integration Coverage
Current software-side hardening lives in:
- `crates/infinity_host_api/tests/contract.rs`
- `crates/infinity_host/src/show_store.rs` tests
- `crates/infinity_host/src/simulation.rs` tests
Covered paths:
Covered flows include:
- 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`
- state, preview, snapshot, catalog, presets, and groups endpoints
- command success and typed command failure
- WebSocket snapshot, preview, and event messages
- group targeting
- parameter updates
- transition configuration
- blackout
- preset save
- creative snapshot save and recall
- persistence across restart
- a longer ignored load-oriented sequence for platform hardening
## Future Direction
## Web UI Scope
Next adapters should be built on this boundary instead of reaching into the host core directly.
The current web UI intentionally focuses on creative use:
That includes:
- pattern and preset selection
- group targeting
- transition configuration
- scene parameters
- preset save and overwrite
- creative snapshot save and recall
- preview
- raw snapshot display
- filterable event feed
- a richer web authoring surface
- remote operator clients
- a grandMA bridge that translates external show control into host API commands
Mapping, topology diagnostics, panel-test administration, and low-level node status remain primarily in the native engineering GUI.