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:
@@ -597,18 +597,31 @@ class ProcessorManager:
|
||||
return None
|
||||
|
||||
async def send_static_color(self, device_id: str, color: Tuple[int, int, int]) -> None:
|
||||
"""Send a solid color to a device via the cached idle client."""
|
||||
import numpy as np
|
||||
"""Send a solid color to a device via its provider."""
|
||||
ds = self._devices.get(device_id)
|
||||
if not ds:
|
||||
raise ValueError(f"Device {device_id} not found")
|
||||
try:
|
||||
provider = get_provider(ds.device_type)
|
||||
client = await self._get_idle_client(device_id)
|
||||
frame = np.full((ds.led_count, 3), color, dtype=np.uint8)
|
||||
await client.send_pixels(frame)
|
||||
await provider.set_color(
|
||||
ds.device_url, color,
|
||||
led_count=ds.led_count, baud_rate=ds.baud_rate, client=client,
|
||||
brightness=ds.software_brightness,
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to send static color for {device_id}: {e}")
|
||||
|
||||
async def clear_device(self, device_id: str) -> None:
|
||||
"""Clear LED output on a device (send black / power off)."""
|
||||
ds = self._devices.get(device_id)
|
||||
if not ds:
|
||||
raise ValueError(f"Device {device_id} not found")
|
||||
try:
|
||||
await self._send_clear_pixels(device_id)
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to clear device {device_id}: {e}")
|
||||
|
||||
async def _restore_device_idle_state(self, device_id: str) -> None:
|
||||
"""Restore a device to its idle state when all targets stop.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user