Add Adalight serial LED device support with per-type discovery and capability-based UI
Implements the second device provider (Adalight) for Arduino-based serial LED controllers, validating the LEDDeviceProvider abstraction. Adds serial port auto-discovery, per-type discovery caching with lazy-load, capability-driven UI (brightness control, manual LED count, standby), and serial port combobox in both Add Device and General Settings modals. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -83,7 +83,12 @@ async def create_device(
|
||||
|
||||
try:
|
||||
result = await provider.validate_device(device_url)
|
||||
led_count = result["led_count"]
|
||||
led_count = result.get("led_count") or device_data.led_count
|
||||
if not led_count or led_count < 1:
|
||||
raise HTTPException(
|
||||
status_code=422,
|
||||
detail="LED count is required for this device type.",
|
||||
)
|
||||
except httpx.ConnectError:
|
||||
raise HTTPException(
|
||||
status_code=422,
|
||||
@@ -146,18 +151,28 @@ async def discover_devices(
|
||||
_auth: AuthRequired,
|
||||
store: DeviceStore = Depends(get_device_store),
|
||||
timeout: float = 3.0,
|
||||
device_type: str | None = None,
|
||||
):
|
||||
"""Scan the local network for LED devices via all registered providers."""
|
||||
"""Scan for LED devices. Optionally filter by device_type (e.g. wled, adalight)."""
|
||||
import asyncio
|
||||
import time
|
||||
|
||||
start = time.time()
|
||||
capped_timeout = min(timeout, 10.0)
|
||||
# Discover from all providers in parallel
|
||||
providers = get_all_providers()
|
||||
discover_tasks = [p.discover(timeout=capped_timeout) for p in providers.values()]
|
||||
all_results = await asyncio.gather(*discover_tasks)
|
||||
discovered = [d for batch in all_results for d in batch]
|
||||
|
||||
if device_type:
|
||||
# Discover from a single provider
|
||||
try:
|
||||
provider = get_provider(device_type)
|
||||
except ValueError:
|
||||
raise HTTPException(status_code=400, detail=f"Unknown device type: {device_type}")
|
||||
discovered = await provider.discover(timeout=capped_timeout)
|
||||
else:
|
||||
# Discover from all providers in parallel
|
||||
providers = get_all_providers()
|
||||
discover_tasks = [p.discover(timeout=capped_timeout) for p in providers.values()]
|
||||
all_results = await asyncio.gather(*discover_tasks)
|
||||
discovered = [d for batch in all_results for d in batch]
|
||||
elapsed_ms = (time.time() - start) * 1000
|
||||
|
||||
existing_urls = {d.url.rstrip("/").lower() for d in store.get_all_devices()}
|
||||
@@ -213,6 +228,7 @@ async def update_device(
|
||||
name=update_data.name,
|
||||
url=update_data.url,
|
||||
enabled=update_data.enabled,
|
||||
led_count=update_data.led_count,
|
||||
)
|
||||
|
||||
# Sync connection info in processor manager
|
||||
@@ -220,7 +236,7 @@ async def update_device(
|
||||
manager.update_device_info(
|
||||
device_id,
|
||||
device_url=update_data.url,
|
||||
led_count=None,
|
||||
led_count=update_data.led_count,
|
||||
)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
Reference in New Issue
Block a user