Files
Infinity_Vis_Rust/docs/host_api.md
JFly02 a37a3c5cbe 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.
2026-04-17 11:58:07 +02:00

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