Add live LED strip preview via WebSocket on target cards
Stream real-time LED colors from running WLED targets to the browser via binary WebSocket (RGB bytes, throttled to ~15 fps). Toggle button on target card opens a compact canvas strip that renders each frame using ImageData. Cached last frame is re-rendered after card reconciliation to prevent flicker during auto-refresh. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -693,6 +693,44 @@ async def target_colors_ws(
|
||||
manager.remove_kc_ws_client(target_id, websocket)
|
||||
|
||||
|
||||
@router.websocket("/api/v1/picture-targets/{target_id}/led-preview/ws")
|
||||
async def led_preview_ws(
|
||||
websocket: WebSocket,
|
||||
target_id: str,
|
||||
token: str = Query(""),
|
||||
):
|
||||
"""WebSocket for real-time LED strip preview. Sends binary RGB frames. Auth via ?token=<api_key>."""
|
||||
authenticated = False
|
||||
cfg = get_config()
|
||||
if token and cfg.auth.api_keys:
|
||||
for _label, api_key in cfg.auth.api_keys.items():
|
||||
if secrets.compare_digest(token, api_key):
|
||||
authenticated = True
|
||||
break
|
||||
|
||||
if not authenticated:
|
||||
await websocket.close(code=4001, reason="Unauthorized")
|
||||
return
|
||||
|
||||
await websocket.accept()
|
||||
|
||||
manager = get_processor_manager()
|
||||
|
||||
try:
|
||||
manager.add_led_preview_client(target_id, websocket)
|
||||
except ValueError:
|
||||
await websocket.close(code=4004, reason="Target not found")
|
||||
return
|
||||
|
||||
try:
|
||||
while True:
|
||||
await websocket.receive_text()
|
||||
except WebSocketDisconnect:
|
||||
pass
|
||||
finally:
|
||||
manager.remove_led_preview_client(target_id, websocket)
|
||||
|
||||
|
||||
# ===== STATE CHANGE EVENT STREAM =====
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user