Files
ledgrab/plans/game-integration/phase-4-css-stream.md
T
alexei.dolgolyov 492bdb95e3 feat: game integration system
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
2026-03-31 13:17:52 +03:00

5.1 KiB

Phase 4: GameEventColorStripStream

Status: Complete Parent plan: 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

  • 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)
  • Task 2: Register "game_event" in _SOURCE_TYPE_MAP in color_strip_source.py
  • 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
  • Task 4: Register in _SIMPLE_STREAM_MAP in color_strip_stream_manager.py
  • 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
  • Task 6: Write tests for GameEventColorStripSource (serialization, factory, update)
  • 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

  • All tasks completed
  • Code follows project conventions
  • No unintended side effects
  • 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