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:
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
|
||||
358
docs/host_api.md
358
docs/host_api.md
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user