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.
343 lines
6.2 KiB
Markdown
343 lines
6.2 KiB
Markdown
# Host API
|
|
|
|
## Purpose
|
|
|
|
The host API is the stable external boundary for:
|
|
|
|
- the creative web UI
|
|
- the existing engineering GUI
|
|
- future external show-control adapters such as grandMA
|
|
|
|
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
|
|
|
|
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 network-facing server is started with:
|
|
|
|
```powershell
|
|
cargo run -p infinity_host_api -- --config config/project.example.toml --bind 127.0.0.1:9001
|
|
```
|
|
|
|
Creative web UI V1 is served by the same process at:
|
|
|
|
```text
|
|
http://127.0.0.1:9001/
|
|
```
|
|
|
|
## Versioning
|
|
|
|
- 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
|
|
|
|
## Endpoint Contract
|
|
|
|
### 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:
|
|
|
|
- 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
|
|
|
|
It does not absorb mapping, topology, or hardware-diagnostic workflows. Those stay in the native engineering UI.
|
|
|
|
## Contract Tests
|
|
|
|
The API contract is currently verified in:
|
|
|
|
- `crates/infinity_host_api/tests/contract.rs`
|
|
|
|
Covered paths:
|
|
|
|
- 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`
|
|
|
|
## 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
|