Fix autorestore logic and protocol badge per device type
Autorestore fixes: - Snapshot WLED state before connect() mutates it (lor, AudioReactive) - Gate restore on auto_shutdown setting (was unconditional) - Remove misleading auto_restore capability from serial provider - Default auto_shutdown to false for all new devices Protocol badge fixes: - Show correct protocol per device type (OpenRGB SDK, MQTT, WebSocket) - Was showing "Serial" for all non-WLED devices Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -29,8 +29,7 @@ class SerialDeviceProvider(LEDDeviceProvider):
|
||||
# power_control: can blank LEDs by sending all-black pixels
|
||||
# brightness_control: software brightness (multiplies pixel values before sending)
|
||||
# health_check: serial port availability probe
|
||||
# auto_restore: blank LEDs when targets stop
|
||||
return {"manual_led_count", "power_control", "brightness_control", "health_check", "auto_restore"}
|
||||
return {"manual_led_count", "power_control", "brightness_control", "health_check"}
|
||||
|
||||
async def check_health(self, url: str, http_client, prev_health=None) -> DeviceHealth:
|
||||
# Generic serial port health check — enumerate COM ports
|
||||
|
||||
@@ -82,6 +82,7 @@ class WLEDClient(LEDClient):
|
||||
self._client: Optional[httpx.AsyncClient] = None
|
||||
self._ddp_client: Optional[DDPClient] = None
|
||||
self._connected = False
|
||||
self._pre_connect_state: Optional[dict] = None
|
||||
|
||||
async def connect(self) -> bool:
|
||||
"""Establish connection to WLED device.
|
||||
@@ -107,6 +108,9 @@ class WLEDClient(LEDClient):
|
||||
)
|
||||
self.use_ddp = True
|
||||
|
||||
# Snapshot device state BEFORE any mutations (for auto-restore)
|
||||
self._pre_connect_state = await self.snapshot_device_state()
|
||||
|
||||
# Create DDP client if needed
|
||||
if self.use_ddp:
|
||||
self._ddp_client = DDPClient(self.host, rgbw=False)
|
||||
@@ -465,7 +469,14 @@ class WLEDClient(LEDClient):
|
||||
# ===== LEDClient abstraction methods =====
|
||||
|
||||
async def snapshot_device_state(self) -> Optional[dict]:
|
||||
"""Snapshot WLED state before streaming (on, lor, AudioReactive)."""
|
||||
"""Snapshot WLED state (on, lor, AudioReactive).
|
||||
|
||||
If connect() already captured a pre-mutation snapshot, returns that
|
||||
instead of the current (potentially already-modified) state.
|
||||
"""
|
||||
# Return pre-connect snapshot if available (captured before DDP setup)
|
||||
if hasattr(self, '_pre_connect_state') and self._pre_connect_state is not None:
|
||||
return self._pre_connect_state
|
||||
if not self._client:
|
||||
return None
|
||||
try:
|
||||
|
||||
@@ -165,6 +165,7 @@ class ProcessorManager:
|
||||
send_latency_ms=send_latency_ms,
|
||||
rgbw=rgbw,
|
||||
zone_mode=ds.zone_mode,
|
||||
auto_shutdown=ds.auto_shutdown,
|
||||
)
|
||||
|
||||
# ===== EVENT SYSTEM (state change notifications) =====
|
||||
|
||||
@@ -75,6 +75,7 @@ class DeviceInfo:
|
||||
send_latency_ms: int = 0
|
||||
rgbw: bool = False
|
||||
zone_mode: str = "combined"
|
||||
auto_shutdown: bool = False
|
||||
|
||||
|
||||
@dataclass
|
||||
|
||||
@@ -197,9 +197,11 @@ class WledTargetProcessor(TargetProcessor):
|
||||
self._task = None
|
||||
await asyncio.sleep(0.05)
|
||||
|
||||
# Restore device state
|
||||
# Restore device state (only if auto_shutdown is enabled)
|
||||
if self._led_client and self._device_state_before:
|
||||
await self._led_client.restore_device_state(self._device_state_before)
|
||||
device_info = self._ctx.get_device_info(self._device_id)
|
||||
if device_info and device_info.auto_shutdown:
|
||||
await self._led_client.restore_device_state(self._device_state_before)
|
||||
self._device_state_before = None
|
||||
|
||||
# Close LED connection
|
||||
|
||||
Reference in New Issue
Block a user