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
70 lines
4.3 KiB
Markdown
70 lines
4.3 KiB
Markdown
# Phase 5: GameEventValueSource
|
|
|
|
**Status:** ✅ Complete
|
|
**Parent plan:** [PLAN.md](./PLAN.md)
|
|
**Domain:** backend
|
|
|
|
## Objective
|
|
Create a new ValueSource type that exposes game metrics (health, ammo, mana, etc.) as 0.0-1.0 scalar values. These can be bound to any existing effect parameter (brightness, speed, color position) via the BindableFloat/BindableColor system.
|
|
|
|
## Tasks
|
|
|
|
- [x] Task 1: Create `GameEventValueSource` dataclass in `storage/value_source.py`
|
|
- Fields: game_integration_id (str), event_type (str — from standard vocabulary), min_game_value (float, default 0.0), max_game_value (float, default 100.0), smoothing (float, 0.0-1.0, EMA alpha), default_value (float, 0.5), timeout (float, seconds before reverting to default)
|
|
- source_type = "game_event"
|
|
- Implement to_dict/from_dict
|
|
- [x] Task 2: Register "game_event" in `_VALUE_SOURCE_MAP` in value_source.py
|
|
- [x] Task 3: Create `GameEventValueStream` runtime resolver (`core/value_sources/game_event_value_source.py`)
|
|
- Subscribe to EventBus for the configured event_type
|
|
- Normalize incoming value using min/max mapping → 0.0-1.0
|
|
- Apply EMA smoothing if configured
|
|
- Track last_event_time for timeout detection
|
|
- `get_value()` → returns current normalized value (or default if timed out)
|
|
- `get_color()` → returns None (game event value source only provides scalars)
|
|
- Thread-safe (EventBus callback + get_value from render thread)
|
|
- Cleanup: unsubscribe from EventBus on release
|
|
- [x] Task 4: Register in value source manager / factory
|
|
- Add case for "game_event" source_type in the value stream creation logic
|
|
- Inject EventBus reference
|
|
- [x] Task 5: Write tests for GameEventValueSource (serialization, from_dict, defaults)
|
|
- [x] Task 6: Write tests for GameEventValueStream (normalization, smoothing, timeout, thread safety)
|
|
|
|
## Files to Modify/Create
|
|
- `server/src/wled_controller/storage/value_source.py` — add GameEventValueSource + register
|
|
- `server/src/wled_controller/core/value_sources/game_event_value_source.py` — runtime resolver
|
|
- `server/src/wled_controller/core/processing/value_stream.py` — register factory case + event_bus param
|
|
- `server/tests/core/test_game_event_value_source.py` — tests
|
|
|
|
## Acceptance Criteria
|
|
- "game_event" value source type serializes/deserializes correctly
|
|
- Runtime resolver normalizes game values to 0.0-1.0 using min/max
|
|
- EMA smoothing works correctly (smooth transitions, not jumpy)
|
|
- Timeout reverts to default_value when no events received
|
|
- Can be bound to BindableFloat properties on any ColorStripSource
|
|
- All tests pass
|
|
|
|
## Notes
|
|
- EMA formula: `smoothed = alpha * new_value + (1 - alpha) * smoothed` where alpha = 1 - smoothing
|
|
- Timeout uses monotonic clock — compare current time vs last_event_time
|
|
- Best suited for continuous event types (health, mana, ammo) — triggers (kill, death) are less useful here
|
|
- ⚠️ Big Bang: value_source.py is a shared file — coordinate with Phase 4 if running in parallel
|
|
|
|
## Review Checklist
|
|
- [x] All tasks completed
|
|
- [x] Code follows project conventions
|
|
- [x] No unintended side effects
|
|
- [x] Tests pass (24/24)
|
|
|
|
## Handoff to Next Phase
|
|
|
|
### What was implemented
|
|
- **GameEventValueSource** dataclass in `storage/value_source.py` with all required fields (game_integration_id, event_type, min/max mapping, smoothing, default_value, timeout)
|
|
- **GameEventValueStream** in new module `core/value_sources/game_event_value_source.py` — subscribes to GameEventBus, normalizes values, applies EMA smoothing, handles timeout with monotonic clock, thread-safe via threading.Lock
|
|
- **ValueStreamManager** updated with `event_bus` parameter and factory case for `GameEventValueSource` in `core/processing/value_stream.py`
|
|
- **24 tests** covering serialization, normalization (7 cases), smoothing (3 cases), timeout (4 cases), lifecycle (4 cases), thread safety, and hot-update
|
|
|
|
### Integration notes for downstream phases
|
|
- `ValueStreamManager.__init__` now accepts an optional `event_bus: GameEventBus` parameter — Phase 8 (wiring) needs to pass the EventBus instance when constructing ValueStreamManager in `dependencies.py`
|
|
- New module `core/value_sources/` created — contains `__init__.py` and `game_event_value_source.py`
|
|
- No changes to API schemas or routes — Phase 7 (frontend) will need to add "game_event" to the value source editor UI
|