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
4.3 KiB
4.3 KiB
Phase 5: GameEventValueSource
Status: ✅ Complete Parent plan: 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
- Task 1: Create
GameEventValueSourcedataclass instorage/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
- Task 2: Register "game_event" in
_VALUE_SOURCE_MAPin value_source.py - Task 3: Create
GameEventValueStreamruntime 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
- Task 4: Register in value source manager / factory
- Add case for "game_event" source_type in the value stream creation logic
- Inject EventBus reference
- Task 5: Write tests for GameEventValueSource (serialization, from_dict, defaults)
- 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 + registerserver/src/wled_controller/core/value_sources/game_event_value_source.py— runtime resolverserver/src/wled_controller/core/processing/value_stream.py— register factory case + event_bus paramserver/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) * smoothedwhere 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
- All tasks completed
- Code follows project conventions
- No unintended side effects
- Tests pass (24/24)
Handoff to Next Phase
What was implemented
- GameEventValueSource dataclass in
storage/value_source.pywith 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_busparameter and factory case forGameEventValueSourceincore/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 optionalevent_bus: GameEventBusparameter — Phase 8 (wiring) needs to pass the EventBus instance when constructing ValueStreamManager independencies.py- New module
core/value_sources/created — contains__init__.pyandgame_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