Software-only show-control readiness baseline

This commit is contained in:
jan
2026-04-17 21:17:23 +02:00
commit a56cecb23d
51 changed files with 16340 additions and 0 deletions

View File

@@ -0,0 +1,37 @@
# Acceptance Template
Date:
Technician:
Firmware build:
Host build:
## Core Checks
- [ ] System starts from cold boot
- [ ] All 6 nodes discovered
- [ ] All 18 outputs configured
- [ ] All outputs confirm 106 LEDs
- [ ] Global brightness change is visible immediately
- [ ] Blackout works and recovers cleanly
- [ ] Preset recall works under load
- [ ] Node reconnect works during active show
- [ ] 8-hour soak run completed without critical fault
## Mapping Checks
- [ ] Walking pixel test completed on every output
- [ ] Start pixel confirmed for every output
- [ ] Direction confirmed for every output
- [ ] Color order confirmed for every output
- [ ] Top, middle, bottom assignment confirmed on every node
- [ ] No mismatch between configured mapping and observed physical behavior
## Observations
- Notes:
- Exceptions:
- Follow-up actions:

115
docs/architecture.md Normal file
View File

@@ -0,0 +1,115 @@
# Architecture
## Goal
Build a live-capable LED control platform that keeps realtime output deterministic while letting operators change scenes, brightness, tests, and presets without UI jitter leaking into the hot path.
## Current Priority
The current delivery order is intentionally software-first:
1. host-core and shared API
2. scene, preset, group, parameter, transition, and simulation model
3. web UI as the primary creative surface
4. engineering GUI as the technical surface
5. external show-control adapters such as grandMA
6. hardware validation and real node activation later
## Layer Split
1. Control layer
- Shared host API first
- Creative web UI later
- Engineering GUI already implemented in `crates/infinity_host_ui`
- Monitoring, mapping, diagnostics, and admin
- Never the timing master for LED output
2. Realtime engine
- Owns the monotonic clock
- Computes scene state, transitions, and dirty regions
- Produces transport-ready commands or pixel frames
3. Transport and node layer
- Discovery, heartbeat, config sync, sequencing, and recovery
- Control protocol and realtime protocol stay separate
- Latest realtime state wins, stale frames may be dropped
4. ESP32 firmware
- Receives commands
- Maintains local buffers
- Drives three independent outputs per node
- Handles watchdog and reconnect logic locally
## Runtime Model
- Logic tick target: 120 Hz
- Frame synthesis target: 60 Hz
- Network send target: 40-60 Hz, profile dependent
- Preview target: 10-15 Hz
Preview and telemetry are explicitly degradable. Realtime output is not.
## Shared Surface Model
Every surface must talk to the same host API:
- engineering GUI
- future creative web UI
- 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
### Distributed Scene Mode
- Default operating mode
- Host sends scene parameters, time basis, seed, palette, and transitions
- Nodes render locally for low bandwidth and better resilience
### Frame Streaming Mode
- Used for mapping tests, debugging, and effects that cannot run node-local
- Host sends explicit output frames
- Kept logically separate so it does not contaminate the primary scene pipeline
## Mapping Model
The project configuration separates mapping into three layers:
1. Hardware mapping
- Node ID
- Top, middle, bottom output
- Physical output label
- Driver channel reference
- LED count, direction, color order, enable flag
2. Layout mapping
- Optional row and column placement
- Optional preview transforms only
3. Group mapping
- Explicit groups for artistic control and fast operator access
The current example config intentionally keeps layout mapping empty because the old XML is only a spatial reference and the final node-to-room placement must still be confirmed on real hardware.
## Validation Gates
The codebase deliberately blocks activation when these remain unresolved:
- `UART 6`, `UART 5`, `UART 4` still marked as `pending_validation`
- output validation state is not `validated`
- LED count deviates from 106
- node outputs are missing top, middle, or bottom
- driver references are ambiguous or duplicated per node
## Planned Next Steps
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 and generic adapter interface
5. Keep hardware activation behind explicit later validation gates

46
docs/build_and_deploy.md Normal file
View File

@@ -0,0 +1,46 @@
# Build and Deploy
## Host Side
Required tools:
- Rust stable toolchain
- `cargo`
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 --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/`. 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.
Before any live activation, run:
```powershell
cargo run -p infinity_host -- validate --config config/project.example.toml --mode activation
```
Activation mode is expected to fail until the hardware mapping has been confirmed and the config is updated from `pending_validation` to concrete driver references.
## Firmware Side
Required tools:
- ESP-IDF
- Xtensa or RISC-V toolchain matching the actual ESP32 variant
Suggested layout:
- `firmware/esp32_node/`
- build with `idf.py build`
- flash with `idf.py -p <serial-port> flash monitor`
The firmware skeleton is intentionally conservative. It will not silently select a backend for `UART 6`, `UART 5`, or `UART 4`.

87
docs/config_schema.md Normal file
View File

@@ -0,0 +1,87 @@
# Config Schema
## Primary File
The example project file is [config/project.example.toml](../config/project.example.toml).
## Root Objects
- `metadata`
- `topology`
- `transport_profiles`
- `safety_profiles`
- `presets`
## `metadata`
- `project_name`
- `schema_version`
- `default_transport_profile`
- `default_safety_profile`
## `topology`
- `expected_node_count`
- `outputs_per_node`
- `leds_per_output`
- `nodes`
- `layout_panels`
- `groups`
## `topology.nodes[]`
- `node_id`
- `display_name`
- `network.reserved_ip`
- `network.telemetry_label`
- `outputs`
## `topology.nodes[].outputs[]`
Required:
- `panel_position`
- `physical_output_name`
- `driver_channel.kind`
- `driver_channel.reference`
- `led_count`
- `direction`
- `color_order`
- `enabled`
- `validation_state`
Optional:
- `logical_panel_name`
## Activation Rules
Structural validation accepts `pending_validation` so the system can model unresolved wiring.
Activation validation rejects any output that is still:
- `driver_channel.kind = "pending_validation"`
- `validation_state != "validated"`
This is intentional and prevents accidental deployment against guessed hardware assumptions.
## Groups
`topology.groups[]` keeps grouping explicit and simple:
- `group_id`
- `tags`
- `members[] = { node_id, panel_position }`
## Layout
`topology.layout_panels[]` is optional and only needed for preview or spatial effects:
- `node_id`
- `panel_position`
- `row`
- `column`
- `rotation_degrees`
- `mirror_x`
- `mirror_y`

397
docs/host_api.md Normal file
View File

@@ -0,0 +1,397 @@
# Host API
## Purpose
The host API is the stable external product boundary for:
- the creative web UI
- the native engineering GUI
- future remote operator clients
- later external show-control adapters such as a grandMA bridge
The realtime rule remains strict:
- the API is a control and observation layer
- the host core remains the timing authority
- no frontend or external adapter is allowed to become the LED clock
## Runtime Components
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`
Server startup:
```powershell
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:
```text
http://127.0.0.1:9001/
```
## Versioning Policy
The current public contract is `v1`.
Rules:
- 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
## 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": 512,
"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": "gradient",
"selected_group": "top_panels",
"transition_duration_ms": 320,
"transition_style": "chase"
},
"engine": {
"logic_hz": 120,
"frame_hz": 60,
"preview_hz": 15,
"uptime_ms": 512,
"frame_index": 30,
"dropped_frames": 0,
"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": 512,
"panels": [
{
"node_id": "node-01",
"panel_position": "top",
"representative_color_hex": "#FF8A5B",
"sample_led_hex": [
"#FF8A5B",
"#F36E43",
"#D85A2F"
],
"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 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.
### GET `/api/v1/groups`
Returns only group summaries.
### POST `/api/v1/command`
Accepts one versioned command envelope.
Example request:
```json
{
"request_id": "web-1713352662000",
"command": {
"type": "save_creative_snapshot",
"payload": {
"snapshot_id": "variant_floor",
"label": "Variant Floor",
"overwrite": false
}
}
}
```
Example response:
```json
{
"api_version": "v1",
"accepted": true,
"request_id": "web-1713352662000",
"generated_at_millis": 522,
"command_type": "save_creative_snapshot",
"summary": "creative snapshot saved: variant_floor"
}
```
## Stable Error Object
All API failures return:
```json
{
"api_version": "v1",
"error": {
"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 stream emits a typed envelope with a monotonic sequence counter:
```json
{
"api_version": "v1",
"sequence": 19,
"generated_at_millis": 880,
"message": {
"type": "event",
"payload": {
"kind": "warning",
"code": "unknown_creative_snapshot",
"message": "creative snapshot 'does_not_exist' does not exist"
}
}
}
```
Stable message types:
- `snapshot`
- `preview`
- `event`
Stable event kinds:
- `info`
- `warning`
- `error`
## Guaranteed Commands In `v1`
Guaranteed control commands:
- `set_blackout`
- `set_master_brightness`
- `select_pattern`
- `recall_preset`
- `select_group`
- `set_scene_parameter`
- `set_transition_duration_ms`
- `set_transition_style`
- `trigger_panel_test`
Guaranteed persistence and creative-library commands:
- `save_preset`
- `save_creative_snapshot`
- `recall_creative_snapshot`
- `upsert_group`
## Persistence Behavior
The simulation-backed host service now persists runtime-facing creative data to `data/runtime_state.json` by default.
Persisted data includes:
- active scene
- global blackout and brightness state
- transition duration and style
- runtime user presets
- runtime user groups
- creative snapshots and variants
This persistence file is an internal runtime artifact, not the public API contract.
## 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 flows include:
- 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
## Web UI Scope
The current web UI intentionally focuses on creative use:
- 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
Mapping, topology diagnostics, panel-test administration, and low-level node status remain primarily in the native engineering GUI.

View File

@@ -0,0 +1,26 @@
# Legacy XML Reference
Source reviewed:
- `c:\Users\janni\Nextcloud\Documents\Infinity Vis\sample_data\infinity_mirror_mapping_clean.xml`
Useful facts extracted from the legacy file:
- 3 rows by 6 columns logical preview layout
- 18 total tiles
- 106 LEDs per tile
- legacy transport metadata mentions WLED, Art-Net, and per-tile IP addresses
- each tile is described as four perimeter segments summing to 106 LEDs
What this file is **not** used for:
- it is not the new hardware-mapping schema
- it is not proof of the final ESP32 node-to-panel assignment
- it does not validate `UART 6`, `UART 5`, or `UART 4`
- it should not be imported as a generic slice engine
Recommended use:
- use it as a preview and spatial-reference aid only
- manually transfer final room layout after the new hardware mapping is physically validated

View File

@@ -0,0 +1,50 @@
# Local Software-Only Runbook
## Voraussetzungen
- Rust `stable` Toolchain mit `cargo`, `rustc`, `rustfmt` und `clippy`
- dieses Repo ist lokal aktuell **kein echter Git-Clone**, sondern nur ein Arbeitsbaum ohne `.git`
- keine Hardware ist fuer den software-only Betrieb noetig
Beispiel fuer eine user-lokale Rust-Installation:
```bash
curl -sSf https://sh.rustup.rs -o /tmp/rustup-init.sh
sh /tmp/rustup-init.sh -y --profile minimal --default-toolchain stable
. "$HOME/.cargo/env"
rustup component add rustfmt clippy
```
## Start
```bash
. "$HOME/.cargo/env"
cargo run -p infinity_host_api -- --config config/project.example.toml --bind 127.0.0.1:9001 --runtime-state data/runtime_state.json
```
## Lokale URLs
- Creative Web-UI: `http://127.0.0.1:9001/`
- State API: `http://127.0.0.1:9001/api/v1/state`
- Preview API: `http://127.0.0.1:9001/api/v1/preview`
- Snapshot API: `http://127.0.0.1:9001/api/v1/snapshot`
- WebSocket-Stream: `ws://127.0.0.1:9001/api/v1/stream`
## Minimale Smoke-Checks
1. Web-UI laedt unter `http://127.0.0.1:9001/`.
2. `GET /api/v1/state` antwortet mit `api_version: "v1"`.
3. `ws://127.0.0.1:9001/api/v1/stream` verbindet und liefert zuerst `snapshot`, dann `preview`.
4. In der Web-UI oder ueber `POST /api/v1/command` funktionieren diese Basisfluesse:
- preset recall
- preset save / overwrite
- creative snapshot save / recall
- blackout
## Runtime-State und Recovery
- Runtime-Persistenz liegt standardmaessig unter `data/runtime_state.json`.
- Beim Schreiben werden aktiver Scene-State, Runtime-Presets, Runtime-Gruppen, Creative Snapshots und globale Steuerwerte persistiert.
- Fehlende Dateien sind okay.
- Leere, defekte oder schema-inkompatible Persistenzdateien blockieren den Serverstart nicht mehr.
- In diesen Recovery-Faellen startet der Host mit Default-State und erzeugt Warning-/Info-Events im Eventfeed statt abzubrechen.

67
docs/protocol.md Normal file
View File

@@ -0,0 +1,67 @@
# Protocol
## Design Rules
- Separate control traffic from realtime traffic
- Version every envelope
- Keep realtime messages disposable
- Prefer idempotent control commands
- Let nodes recover independently after packet loss or reconnect
## Control Protocol
Purpose:
- Discovery
- Heartbeat
- Config sync
- Preset recall
- Panic and blackout
- Telemetry
Current envelope model:
- `protocol_version`
- `sequence`
- `sent_at_millis`
- `message`
Current control messages:
- `discovery_hello`
- `discovery_ack`
- `config_sync`
- `heartbeat_request`
- `heartbeat`
- `preset_recall`
- `blackout`
`config_sync` carries the authoritative per-node hardware assignment so the node can reject invalid activation before the first frame.
## Realtime Protocol
Purpose:
- Scene parameters for distributed rendering
- Explicit pixel frames for frame streaming mode
- Resync requests
Current realtime messages:
- `scene_parameters`
- `pixel_frame`
- `resync_request`
## Delivery Semantics
- Control messages must be small and replay-safe where possible
- Realtime messages use latest-state-wins semantics
- Nodes may drop stale realtime frames rather than replay them
- A reconnecting node must request or receive a clean config sync before resuming output
## DDP Compatibility
DDP is treated as an optional compatibility shell for frame streaming mode only.
The internal model is intentionally broader than DDP because the preferred operating path is distributed scene mode with time-based parameters and node-local rendering.

View File

@@ -0,0 +1,113 @@
# Show-Control Primitives
## Ziel
Diese Primitive-Menge ist die kleine, dauerhafte interne Steuersemantik fuer software-only Show-Control. Sie bleibt bewusst generisch:
- keine UI-spezifischen Sonderfaelle
- keine grandMA-spezifische Kopplung
- keine zweite Architektur neben Host-Core und API
Der Implementierungspfad liegt in `crates/infinity_host/src/external_control.rs`.
## Primitive
### `blackout`
- Typ: direkt, mutierend
- Semantik: setzt globalen Blackout an oder aus
- Idempotenz: ja, bezogen auf den Zielzustand
- Fehlercodes: unterliegende Host-Fehler nur bei Persistenzproblemen, typischerweise `persist_failed`
- Event-Auswirkung: Info-Event auf Erfolg
### `recall_preset`
- Typ: direkt, mutierend
- Semantik: recalled ein Preset inklusive seiner Zielgruppe und Transition-Metadaten
- Idempotenz: praktisch ja, wenn dasselbe Preset erneut recalled wird
- Fehlercodes: `unknown_preset`, `persist_failed`
- Event-Auswirkung: Info-Event auf Erfolg, Warning-Event bei unbekanntem Preset
### `recall_creative_snapshot`
- Typ: direkt, mutierend
- Semantik: recalled einen gespeicherten Creative Snapshot inklusive Scene- und Transition-State
- Idempotenz: praktisch ja, wenn derselbe Snapshot erneut recalled wird
- Fehlercodes: `unknown_creative_snapshot`, `persist_failed`
- Event-Auswirkung: Info-Event auf Erfolg, Warning-Event bei unbekanntem Snapshot
### `set_master_brightness`
- Typ: direkt, mutierend
- Semantik: setzt globale Helligkeit, intern auf `0.0..1.0` geklemmt
- Idempotenz: ja, bezogen auf den geklemmten Zielwert
- Fehlercodes: typischerweise nur `persist_failed`
- Event-Auswirkung: Info-Event auf Erfolg
### `set_pattern`
- Typ: staged
- Semantik: staged das Pattern fuer die naechste explizite Transition
- Idempotenz: ja, letzter Wert gewinnt
- Fehlercodes: `invalid_pattern_id`
- Event-Auswirkung: kein Host-Event bis `trigger_transition`
### `set_group_parameter`
- Typ: staged
- Semantik: staged einen Scene-Parameter fuer die naechste Transition und kann optional gleichzeitig die Zielgruppe fuer diese Transition setzen
- Idempotenz: ja, letzter Wert pro Parameter-Key gewinnt
- Fehlercodes: `invalid_group_parameter_key`
- Event-Auswirkung: kein Host-Event bis `trigger_transition`
### `upsert_group`
- Typ: direkt, mutierend
- Semantik: legt eine Runtime-Gruppe an oder ueberschreibt sie bewusst mit `overwrite: true`
- Idempotenz: ja mit `overwrite: true`, nein mit `overwrite: false`
- Fehlercodes: `invalid_group_id`, `invalid_group_members`, `group_exists`, `persist_failed`
- Event-Auswirkung: Info-Event auf Erfolg
### `set_transition_style`
- Typ: staged
- Semantik: staged Transition-Style und optional Duration fuer die naechste explizite Transition
- Idempotenz: ja, letzter Wert gewinnt
- Fehlercodes: keine zusaetzlichen Primitive-Fehler
- Event-Auswirkung: kein Host-Event bis `trigger_transition`
### `trigger_transition`
- Typ: ausfuehrend, mutierend
- Semantik: materialisiert den aktuell gestagten Transition-Intent in den Host
- Ausfuehrungsreihenfolge:
1. `select_group` nur wenn ueber staged Parameter ein Gruppenkontext gesetzt wurde
2. `set_transition_duration_ms` nur wenn staged
3. `set_transition_style` nur wenn staged
4. `select_pattern`
5. `set_scene_parameter` fuer alle staged Parameter
- Idempotenz: nein, erfolgreicher Trigger konsumiert den gestagten Intent
- Fehlercodes: `transition_pattern_required` plus unterliegende Host-Fehler wie `unknown_group` oder `persist_failed`
- Event-Auswirkung: die unterliegenden Host-Kommandos erzeugen die sichtbaren Info-/Warning-Events
### `request_snapshot`
- Typ: read-only
- Semantik: liefert den aktuellen Host-Snapshot ohne Host-Mutation
- Idempotenz: ja
- Fehlercodes: keine Primitive-eigenen
- Event-Auswirkung: keine
## Hinweis zur Adapter-Nutzung
Die staged Primitive sind fuer externe Show-Control-Adapter gedacht, die absichtlich mehrere kleine Eingaben sammeln und erst mit `trigger_transition` in einen Host-seitigen Uebergang umsetzen. Direkte UI- oder API-Kommandos koennen weiterhin eager bleiben; die stabile interne Adapter-Semantik wird davon nicht aufgeblasen.
Ein stateless Port darf staged Primitive nicht stillschweigend akzeptieren. Wenn `set_pattern`, `set_group_parameter`, `set_transition_style` oder `trigger_transition` ohne Session-/Adapter-Kontext direkt an einem Port landen, ist der erwartete Fehlercode `show_control_session_required`.
## Referenz-Client
Der sehr duenne generische Referenzpfad liegt in `crates/infinity_host/src/external_control.rs`:
- `ReferenceShowControlClient::stateful(...)` fuer direkte plus staged Flows
- `ReferenceShowControlClient::stateless(...)` zum bewussten Nachweis, dass staged Primitive am nackten Port mit `show_control_session_required` abgewiesen werden
- `BufferedShowControlAdapter` und `ShowControlSession` als kleine Buffer-/Commit-Implementierung ohne neue Grundarchitektur

37
docs/testing.md Normal file
View File

@@ -0,0 +1,37 @@
# Testing
## Unit Tests
Host-side unit tests currently cover:
- fixed LED count validation
- duplicate driver reference rejection
- activation guard against unresolved hardware mapping
- protocol envelope version stamping
## Planned Integration Tests
1. Host to node config sync
2. Host to node preset recall during load
3. Reconnect and resync after heartbeat timeout
4. Frame streaming fallback without scene-mode support
## Soak Tests
Target procedure:
1. Run a continuous scene loop for 8 hours
2. Rotate presets on a schedule
3. Simulate packet loss and node reconnects
4. Log dropped frames, reconnect count, and jitter
## Hardware Validation Tests
Required before live deployment:
1. Walking pixel test across all 106 LEDs on each of the 18 outputs
2. Start pixel verification per output
3. Direction verification per output
4. Color order verification per output
5. Final confirmation of which physical channel maps to top, middle, and bottom on every node

View File

@@ -0,0 +1,14 @@
# Validation Open Points
These items must be resolved before the system can move from structural validation to activation validation:
1. Confirm the real meaning of `UART 6`, `UART 5`, and `UART 4`.
2. Confirm the exact LED chipset and required output timing backend.
3. Confirm whether every output truly has exactly 106 active LEDs, with no dummy or reserve pixels.
4. Confirm color order for each output.
5. Confirm direction and start pixel for each output.
6. Confirm which physical node controls which installed top, middle, and bottom panel.
7. Confirm whether transport runs over dedicated Wi-Fi or wired Ethernet.
8. Confirm whether DDP compatibility is optional or mandatory in the first deployment.
9. Confirm whether the first production UI is Tauri, egui, or another adapter on top of the host core.