Add static color support, HAOS light entity, and real-time profile updates

- Add static_color capability to WLED and serial providers with native
  set_color() dispatch (WLED uses JSON API, serial uses idle client)
- Encapsulate device-specific logic in providers instead of device_type
  checks in ProcessorManager and API routes
- Add HAOS light entity for devices with brightness_control + static_color
  (Adalight/AmbiLED get light entity, WLED keeps number entity)
- Fix serial device brightness and turn-off: pass software_brightness
  through provider chain, clear device on color=null, re-send static
  color after brightness change
- Add global events WebSocket (events-ws.js) replacing per-tab WS,
  enabling real-time profile state updates on both dashboard and profiles tabs
- Fix profile activation: mark active when all targets already running,
  add asyncio.Lock to prevent concurrent evaluation races, skip process
  enumeration when no profile has conditions, trigger immediate evaluation
  on enable/create/update for instant target startup
- Add reliable server restart script (restart.ps1)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-19 14:23:47 +03:00
parent 6388e0defa
commit bef28ece5c
21 changed files with 410 additions and 78 deletions

View File

@@ -104,6 +104,9 @@ async def create_profile(
target_ids=data.target_ids,
)
if profile.enabled:
await engine.trigger_evaluate()
return _profile_to_response(profile, engine)
@@ -187,6 +190,10 @@ async def update_profile(
except ValueError as e:
raise HTTPException(status_code=404, detail=str(e))
# Re-evaluate immediately if profile is enabled (may have new conditions/targets)
if profile.enabled:
await engine.trigger_evaluate()
return _profile_to_response(profile, engine)
@@ -230,6 +237,9 @@ async def enable_profile(
except ValueError as e:
raise HTTPException(status_code=404, detail=str(e))
# Evaluate immediately so targets start without waiting for the next poll cycle
await engine.trigger_evaluate()
return _profile_to_response(profile, engine)