492bdb95e3
Receive real-time events from games (CS2, Dota 2, LoL, etc.) and drive LED effects through the existing color strip and value source pipelines. Core: - GameEventBus (thread-safe pub/sub) with standardized 23-type event vocabulary - GameAdapter ABC + AdapterRegistry + MappingAdapter (YAML-driven) - Built-in adapters: CS2 GSI, Dota 2 GSI, LoL Live Client, Generic Webhook - Community YAML adapters: Minecraft, Valorant, Rocket League - GameEventColorStripStream with 5 effects (flash/pulse/sweep/color_shift/breathing) - GameEventValueSource with EMA smoothing and timeout - 4 built-in effect presets (FPS Combat, MOBA Health, Racing, Generic Alert) - Auto-setup for Valve GSI games (Steam path detection, cfg file writing) - Demo capture engine exposed to non-demo mode Frontend: - Game tab in Streams tree navigation with integration cards - Game integration editor modal with adapter picker, config fields, event mappings - game_event source type in CSS and ValueSource editors - Setup instructions overlay (markdown rendered) - Live event monitor and connection test API: - Full CRUD for game integrations - Event ingestion endpoint (adapter-level auth) - Adapter metadata, presets, auto-setup, status/diagnostics endpoints
79 lines
5.1 KiB
Markdown
79 lines
5.1 KiB
Markdown
# Phase 4: GameEventColorStripStream
|
|
|
|
**Status:** ✅ Complete
|
|
**Parent plan:** [PLAN.md](./PLAN.md)
|
|
**Domain:** backend
|
|
|
|
## Objective
|
|
Create a new ColorStripSource/Stream type that renders LED effects in response to game events. Follows the NotificationColorStripStream pattern — event-driven with a 30 FPS render loop and double-buffered output.
|
|
|
|
## Tasks
|
|
|
|
- [x] Task 1: Create `GameEventColorStripSource` dataclass in `storage/color_strip_source.py`
|
|
- Fields: game_integration_id (str), idle_color (BindableColor), event_mappings (list of EventMapping dicts — override/supplement config-level mappings)
|
|
- source_type = "game_event"
|
|
- Implement to_dict/from_dict/create_from_kwargs/apply_update
|
|
- sharable = False (each target gets its own stream)
|
|
- [x] Task 2: Register "game_event" in `_SOURCE_TYPE_MAP` in color_strip_source.py
|
|
- [x] Task 3: Create `GameEventColorStripStream` (`core/processing/game_event_stream.py`)
|
|
- Constructor: parse event_mappings into lookup dict, subscribe to EventBus
|
|
- `_on_game_event(event)` — callback from EventBus, enqueue effect (thread-safe via deque)
|
|
- Effect types: flash, pulse, sweep, color_shift, breathing
|
|
- Priority-based layering — higher priority effects override lower (same as notification)
|
|
- 30 FPS background render thread with frame_time sleep
|
|
- Double-buffered output under threading.Lock
|
|
- Idle: output idle_color when no active effects
|
|
- `get_latest_colors()` → returns current rendered frame (np.ndarray)
|
|
- `start()` / `stop()` for lifecycle
|
|
- Cleanup: unsubscribe from EventBus on stop
|
|
- [x] Task 4: Register in `_SIMPLE_STREAM_MAP` in `color_strip_stream_manager.py`
|
|
- [x] Task 5: Wire EventBus injection — stream needs access to the singleton EventBus
|
|
- Added `game_event_bus` parameter to ColorStripStreamManager constructor
|
|
- Injection via `set_event_bus()` using same hasattr pattern as asset_store
|
|
- [x] Task 6: Write tests for GameEventColorStripSource (serialization, factory, update)
|
|
- [x] Task 7: Write tests for GameEventColorStripStream (event → effect rendering, priority, idle state, lifecycle)
|
|
|
|
## Files to Modify/Create
|
|
- `server/src/wled_controller/storage/color_strip_source.py` — add GameEventColorStripSource + register
|
|
- `server/src/wled_controller/core/processing/game_event_stream.py` — new stream class
|
|
- `server/src/wled_controller/core/processing/color_strip_stream_manager.py` — register in _SIMPLE_STREAM_MAP, inject EventBus
|
|
- `server/src/wled_controller/core/processing/processor_manager.py` — pass EventBus to stream manager (if needed)
|
|
- `server/tests/core/test_game_event_css.py` — source + stream tests
|
|
|
|
## Acceptance Criteria
|
|
- "game_event" source type serializes/deserializes correctly
|
|
- Stream subscribes to EventBus and renders effects when events arrive
|
|
- Multiple simultaneous effects layer by priority
|
|
- Idle state outputs the configured idle_color
|
|
- Stream cleans up subscriptions on stop
|
|
- All tests pass
|
|
|
|
## Notes
|
|
- Reuse effect rendering logic from NotificationColorStripStream where possible (flash, pulse, sweep are identical)
|
|
- Consider extracting shared effect rendering into a utility if duplication is significant
|
|
- The stream needs the EventBus singleton — simplest injection is via the stream manager's dependencies
|
|
- ⚠️ Big Bang: color_strip_source.py and stream_manager.py are shared files — coordinate with Phase 5 if running in parallel
|
|
|
|
## Review Checklist
|
|
- [x] All tasks completed
|
|
- [x] Code follows project conventions
|
|
- [x] No unintended side effects
|
|
- [x] Tests pass (28/28)
|
|
|
|
## Handoff to Next Phase
|
|
|
|
### What was built
|
|
- `GameEventColorStripSource` dataclass in `storage/color_strip_source.py` with full serialization, factory, and update support
|
|
- `GameEventColorStripStream` in `core/processing/game_event_stream.py` — event-driven stream with 5 effects (flash, pulse, sweep, color_shift, breathing), 30 FPS render loop, double-buffered output, priority-based effect layering
|
|
- EventBus injection via `game_event_bus` parameter on `ColorStripStreamManager` constructor + `set_event_bus()` method on the stream
|
|
|
|
### Integration points for later phases
|
|
- **Phase 7 (frontend)**: The `source_type = "game_event"` needs a UI editor. Fields: `game_integration_id` (EntitySelect), `idle_color` (BindableColor picker), `event_mappings` (list of EventMapping dicts with effect/color/duration/intensity/priority), `led_count`
|
|
- **Phase 8 (wiring)**: `processor_manager.py` needs to pass the `GameEventBus` singleton to `ColorStripStreamManager` via the new `game_event_bus=` constructor parameter. The bus is created in Phase 1's `init_dependencies()`.
|
|
|
|
### Files modified
|
|
- `server/src/wled_controller/storage/color_strip_source.py` — added `GameEventColorStripSource` class + registered in `_SOURCE_TYPE_MAP`
|
|
- `server/src/wled_controller/core/processing/game_event_stream.py` — new file
|
|
- `server/src/wled_controller/core/processing/color_strip_stream_manager.py` — added import, `_SIMPLE_STREAM_MAP` entry, `game_event_bus` constructor param, injection hook
|
|
- `server/tests/core/test_game_event_css.py` — 28 tests covering source serialization, stream lifecycle, rendering, effects, auto-size, and hot-update
|