Commit Graph

121 Commits

Author SHA1 Message Date
e32bfab888 Add LED skip start/end, rename standby_interval to keepalive_interval, remove migrations
LED skip: set first N and last M LEDs to black on a target. Color sources
(static, gradient, effect, color cycle) render across only the active
(non-skipped) LEDs. Processor pads with blacks before sending to device.

Rename standby_interval → keepalive_interval across all Python, API
schemas, and JS. from_dict falls back to old key for existing configs.

Remove legacy migration functions (_migrate_devices_to_targets,
_migrate_targets_to_color_strips) and legacy fields from target model.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 02:15:29 +03:00
9e555cef2e Add composable filter templates, skip keepalive for serial devices
Filter Template meta-filter: reference existing PP templates inside others
for composable, DRY filter chains. Filters are recursively expanded at
pipeline build time with cycle detection. New `select` option type with
dynamic choices populated by the API.

Keepalive optimization: serial devices (Adalight, AmbiLED) don't need
keepalive — they hold last frame indefinitely. Check `standby_required`
capability at processor start, skip keepalive sends for serial targets,
and hide keepalive metrics in the UI. Rename "Standby Interval" to
"Keep Alive Interval" throughout the frontend.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 01:48:23 +03:00
a4083764fb Add 5 procedural LED effects, gradient presets, auto-crop min aspect ratio, static source polling optimization
New features:
- Procedural effect source type with fire, meteor, plasma, noise, and aurora algorithms
  using palette LUT system and 1D value noise generator
- 12 predefined gradient presets (rainbow, sunset, ocean, forest, fire, lava, aurora,
  ice, warm, cool, neon, pastel) selectable from a dropdown in the gradient editor
- Auto-crop filter: min aspect ratio parameter to prevent false-positive cropping
  in dark scenes on ultrawide displays

Optimization:
- Static/gradient sources without animation: stream thread sleeps 0.25s instead of
  frame_time; processor repolls at frame_time instead of 5ms (~40x fewer iterations)
- Inverted isinstance checks in routes to test for PictureColorStripSource only

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 01:03:16 +03:00
9392741f08 Batch API endpoints, reduce frontend polling by ~75%, fix resource leaks
Backend: add batch endpoints for target states, metrics, and device
health to replace O(N) individual API calls per poll cycle.
Frontend: use batch endpoints in dashboard/targets/profiles tabs,
fix Chart.js instance leaks, debounce server event reloads, add
i18n active-tab guards, clean up ResizeObserver on pattern editor
close, cache uptime timer DOM refs, increase KC auto-refresh to 2s.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 18:55:09 +03:00
ee52e2d98f Animation None option, FPS min 1, serial COM lifecycle fixes
- Replace animation Enable checkbox with None option in effect selector;
  show effect description tooltip; disable speed slider when None selected
- Allow target FPS range 1-90 (was 10-90) across UI and backend validation
- Scope serial COM connections to target lifetime (no idle caching);
  use temporary connections for power-off/test mode
- Fix serial black frame on stop: flush after write, delay after task
  cancel to prevent race with in-flight thread pool write

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 04:33:56 +03:00
8a0730d91b Remove idle color feature, simplify power to turn-off only, fix settings serial port bug
- Remove static/idle color from entire stack (storage, API, processing, UI, CSS, locales)
- Simplify device power button to turn-off only (send black frame, no toggle)
- Send black frame on serial port close (AdalightClient.close)
- Fix settings modal serial port dropdown showing WLED devices due to stale deviceType

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 04:04:28 +03:00
1f6c913343 Move FPS from color strip source to target; dynamic capture rate
FPS is a consumption property (how fast to send to a device), not a
production property. Two targets sharing the same source may need
different FPS. This moves the fps field from PictureColorStripSource
to WledPictureTarget across the full stack.

The capture stream now auto-adjusts its rate to max(all connected
target FPS values) via ColorStripStreamManager tracking per-consumer
FPS. UI updates: FPS slider in target editor, FPS badge on target
cards, LED count repositioned in CSS editor, consistent speed icons.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 03:46:08 +03:00
7c0c064453 Fix FPS drops caused by brightness endpoint polling WLED device
The GET /devices/{id}/brightness endpoint was making an HTTP request to
the ESP32 over WiFi on every frontend poll (~3s), causing 150ms async
event loop jitter that froze the LED processing loop. Cache brightness
server-side after first fetch/set, add frontend dedup guard, reduce
get_device_info() frequency, and add processing loop timing diagnostics.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 02:43:03 +03:00
b14da85f3b Fix event loop blocking from perf endpoint and profile detection
- Change /api/v1/system/performance from async def to def so FastAPI
  runs the blocking psutil + NVML GPU queries in a thread pool instead
  of freezing the event loop (polled every 2s by dashboard)
- Batch profile engine's 3 separate run_in_executor detection calls
  into a single _detect_all_sync() call, reducing event loop wake-ups

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 02:06:59 +03:00
c31818a20d Add color_cycle as standalone source type; UI polish
- color_cycle is now a top-level source type (alongside picture/static/gradient)
  with a configurable color list and cycle_speed; defaults to full rainbow spectrum
- ColorCycleColorStripSource + ColorCycleColorStripStream: smooth 30 fps interpolation
  between user-defined colors, one full cycle every 20s at speed=1.0
- Removed color_cycle animation sub-type from StaticColorStripStream
- Color cycle editor: compact horizontal swatch layout, proper module-scope fix
  (colorCycleAdd/Remove now exposed on window, DOM-synced before mutations)
- Animation enabled + Frame interpolation checkboxes use toggle-switch style
- Removed Potential FPS metric from targets and KC targets metric grids

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-20 22:14:42 +03:00
55e25b8860 Frame interpolation, FPS hot-update, timing metrics, KC brightness fixes
- CSS: add frame interpolation option — blends between consecutive captured
  frames on idle ticks so LED output runs at full target FPS even when
  capture rate is lower (e.g. capture 30fps, output 60fps)
- WledTargetProcessor: re-read stream.target_fps each loop tick so FPS
  changes to the CSS source take effect without restarting the target
- WledTargetProcessor: restore per-stage timing metrics on target card by
  pulling extract/map/smooth/total from CSS stream get_last_timing()
- TargetProcessingState schema: add missing timing_extract_ms,
  timing_map_leds_ms, timing_smooth_ms, timing_total_ms fields
- KC targets: add extraction FPS badge to target card props row
- KC targets: fix 500 error when changing brightness — update_fields now
  accepts (and ignores) WLED-specific kwargs
- KC targets: fix partial key_colors_settings update wiping pattern_template_id
  — update route merges only explicitly-set fields using model_dump(exclude_unset=True)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-20 20:29:22 +03:00
7479b1fb8d CSS: add GradientColorStripSource with visual editor
- Backend: GradientColorStripSource storage model, GradientColorStripStream
  with numpy interpolation (bidirectional stops, auto-size from device LED count),
  ColorStop Pydantic schema, API create/update/guard routes
- Frontend: gradient editor modal (canvas preview, draggable markers, stop rows),
  CSS hard-edge card swatch, locale keys (en + ru)
- Fixes: stop row mousedown no longer rebuilds DOM (buttons now clickable),
  position input max-width, bidir/remove button static width

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-20 19:35:41 +03:00
2a8e2daefc CSS: add StaticColorStripSource type with auto-sized LED count
Introduces a new 'static' source type that fills all device LEDs with a
single constant RGB color — no screen capture or processing required.

- StaticColorStripSource storage model (color + led_count=0 auto-size)
- StaticColorStripStream: no background thread, configure() sizes to device
  LED count at processor start; hot-updates preserve runtime size
- ColorStripStreamManager dispatches static sources (no LiveStream needed)
- WledTargetProcessor calls stream.configure(device_led_count) on start
- API schemas/routes: source_type Literal["picture","static"]; color field;
  overlay/calibration-test endpoints return 400 for static
- Frontend: type selector modal, color picker, type-aware card rendering
  (🎨 icon + color swatch), LED count field hidden for static type
- Locale keys: color_strip.type, color_strip.static_color (en + ru)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-20 17:49:48 +03:00
018bedf9f6 Overlay: fix 404, crash on repeat, missing edge test colors, device reset on stop
- Target overlay works without active processing: route pre-loads calibration
  and display info from the CSS store, passes to processor as fallback
- Fix server crash on repeated overlay: replace per-window tk.Tk() with single
  persistent hidden root; each overlay is a Toplevel child dispatched via
  root.after() — eliminates Tcl interpreter crashes on Windows
- Fix edge test colors not lighting up: always call set_test_mode regardless
  of processing state (was guarded by 'not proc.is_running'); pass calibration
  so _send_test_pixels knows which LEDs map to which edges
- Fix device reset on overlay stop: keep idle serial client cached after
  clearing test mode; start_processing() already closes it before connecting

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-20 17:16:10 +03:00
a3aeafef13 CSS: add led_count field; calibration dialog improvements; color corrections collapsible section
- Add explicit led_count to PictureColorStripSource (0 = auto from calibration)
- Stream pads with black or truncates to match led_count exactly
- Calibration dialog: show led_count input above visual editor in CSS mode
- Calibration dialog: pre-populate led_count with effective count (cal sum) when stored value is 0
- Calibration dialog: sync preview label live as led_count input changes
- CSS editor: group brightness/saturation/gamma into collapsible "Color Corrections" section

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-20 16:42:32 +03:00
7de3546b14 Introduce ColorStripSource as first-class entity
Extracts color processing and calibration out of WledPictureTarget into a
new PictureColorStripSource entity, enabling multiple LED targets to share
one capture/processing pipeline.

New entities & processing:
- storage/color_strip_source.py: ColorStripSource + PictureColorStripSource models
- storage/color_strip_store.py: JSON-backed CRUD store (prefix css_)
- core/processing/color_strip_stream.py: ColorStripStream ABC + PictureColorStripStream (runs border-extract → map → smooth → brightness/sat/gamma in background thread)
- core/processing/color_strip_stream_manager.py: ref-counted shared stream manager

Modified storage/processing:
- WledPictureTarget simplified to device_id + color_strip_source_id + standby_interval + state_check_interval
- Device model: calibration field removed
- WledTargetProcessor: acquires ColorStripStream from manager instead of running its own pipeline
- ProcessorManager: wires ColorStripStreamManager into TargetContext

API layer:
- New routes: GET/POST/PUT/DELETE /api/v1/color-strip-sources, PUT calibration/test
- Removed calibration endpoints from /devices
- Updated /picture-targets CRUD for new target structure

Frontend:
- New color-strips.js module with CSS editor modal and card rendering
- Calibration modal extended with CSS mode (css-id hidden field + device picker)
- targets.js: Color Strip Sources section added to LED tab; target editor/card updated
- app.js: imports and window globals for CSS + showCSSCalibration
- en.json / ru.json: color_strip.* and targets.section.color_strips keys added

Data migration runs at startup: existing WledPictureTargets are converted to
reference a new PictureColorStripSource created from their old settings.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-20 15:49:47 +03:00
c4e0257389 Polymorphism Phase 2 + remove unused gamma/saturation fields
ProcessorManager: replace all isinstance checks with property-based
dispatch via base TargetProcessor (device_id, led_client,
get_display_index, update_device, update_calibration).

Remove gamma/saturation from ProcessingSettings, ColorCorrection
schema, serialization, and migration — these were never used in the
processing pipeline and are handled by postprocessing template filters.
Delete dead apply_color_correction() function.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 02:34:03 +03:00
99f47fdbf9 Encapsulate target-type dispatch via polymorphism (Phase 1)
Replace isinstance checks with polymorphic methods on PictureTarget
hierarchy: register_with_manager, sync_with_manager, update_fields,
and has_picture_source property.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 02:20:33 +03:00
bef28ece5c 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>
2026-02-19 14:23:47 +03:00
ef925ad0a9 Fix Adalight power toggle using cached idle client and tracked state
Serial devices now route power on/off through the cached idle client
instead of opening a new serial connection (which caused PermissionError).
Adds tracked power_on state to DeviceState since Adalight has no
hardware power query.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 02:26:57 +03:00
46be9922bd Add brightness control to Key Colors targets with HAOS integration
Adds brightness (0.0-1.0) to KeyColorsSettings, applies scaling in the
KC processing pipeline after smoothing, exposes a slider on the WebUI
target card, and creates a HA number entity for KC target brightness.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 02:26:46 +03:00
390f71ebae Cache idle LED clients to avoid repeated Arduino resets
Adalight devices trigger a ~3s bootloader reset on every serial
connection open. Add a persistent idle client cache in ProcessorManager
so calibration test toggles, static color changes, and auto-restore
reuse an existing connection instead of creating a new one each time.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 00:09:55 +03:00
4a1b4f7674 Add real-time system performance charts to dashboard
Backend: GET /api/v1/system/performance endpoint using psutil (CPU/RAM)
and nvidia-ml-py (GPU utilization, memory, temperature) with graceful
fallback. Frontend: Chart.js line charts with rolling 60-sample history
persisted to sessionStorage, flicker-free updates via persistent DOM
and diff-based dynamic section refresh.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 21:02:55 +03:00
29d9b95885 Add profile system for automatic target activation
Profiles monitor running processes and foreground windows to
automatically start/stop targets when conditions are met.
Includes profile engine, platform detector (WMI), REST API,
process browser endpoint, and calibration persistence fix.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 15:12:34 +03:00
d6cf45c873 Add static color for simple devices, change auto-shutdown to auto-restore
- Add `static_color` capability to Adalight provider with `set_color()` method
- Add `static_color` field to Device model, DeviceState, and API schemas
- Add GET/PUT `/devices/{id}/color` API endpoints
- Change auto-shutdown behavior: restore device to idle state instead of
  powering off (WLED uses snapshot/restore, Adalight sends static color
  or black frame)
- Rename `_auto_shutdown_device_if_idle` to `_restore_device_idle_state`
- Add inline color picker on device cards for devices with static_color
- Add auto_shutdown toggle to device settings modal
- Update labels from "Auto Shutdown" to "Auto Restore" (en + ru)
- Remove backward-compat KC aliases from ProcessorManager
- Align card action buttons to bottom with flex column layout

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 13:42:05 +03:00
fc779eef39 Refactor core/ into logical sub-packages and split filter files
Reorganize the flat core/ directory (17 files) into three sub-packages:
- core/devices/ — LED device communication (led_client, wled/adalight clients, providers, DDP)
- core/processing/ — target processing pipeline (processor_manager, target processors, live streams, settings)
- core/capture/ — screen capture & calibration (screen_capture, calibration, pixel_processor, overlay)

Also split the monolithic filters/builtin.py (460 lines, 8 filters) into
individual files: brightness, saturation, gamma, downscaler, pixelate,
auto_crop, flip, color_correction.

Includes the ProcessorManager refactor from target-centric architecture:
ProcessorManager slimmed from ~1600 to ~490 lines with unified
_processors dict replacing duplicate _targets/_kc_targets dicts.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 12:03:29 +03:00
77dd342c4c Add software brightness control for Adalight devices
Emulates hardware brightness by multiplying pixel values before serial
send. Stored per-device and persisted across restarts.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 10:56:19 +03:00
cc91ccd75a Add power toggle button to LED device cards
WLED: native on/off via JSON API. Adalight: sends all-black frame
to blank LEDs (uses existing client if target is running, otherwise
opens temporary serial connection). Toggle button placed next to
delete button in card top-right corner.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 19:18:39 +03:00
3ee17ed083 Optimize KC processing and add reactive HAOS state updates
- Optimize KC frame processing: downsample to 160x90 with cv2.resize
  before rectangle extraction, pre-compute pixel coords, vectorize
  smoothing with numpy arrays
- Add WebSocket event stream for server state changes: processor manager
  fires events on start/stop, new /api/v1/events/ws endpoint streams
  them to connected clients
- Add HAOS EventStreamListener that triggers coordinator refresh on
  state changes for near-instant switch updates
- Reduce HAOS polling interval from 10s to 3s for fresher FPS metrics
- Fix overlay button tooltips: flatten nested JSON keys in locale files
  to match flat dot-notation lookup used by t() function

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 14:21:47 +03:00
67da014684 Rewrite HAOS integration: target-centric architecture with KC color sensors
- Rewrite integration to target-centric model: each picture target becomes
  a HA device under a server hub with switch, FPS, and status sensors
- Replace KC light entities with color sensors (hex state + RGB attributes)
  for better automation support via WebSocket real-time updates
- Add WebSocket manager for Key Colors color streaming
- Add KC per-stage timing metrics (calc_colors, broadcast) with rolling avg
- Fix KC timing fields missing from API by adding them to Pydantic schema
- Make start/stop processing idempotent to prevent intermittent 404 errors
- Add HAOS localization support (en, ru) using translation_key system
- Rename integration from "WLED Screen Controller" to "LED Screen Controller"
- Remove obsolete select.py (display select) and README.md

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 13:01:40 +03:00
4f4d17c44d Add screen overlay visualization for LED target testing
Implements transparent on-screen overlay that displays LED calibration data
directly on the target display for easier setup and debugging. Overlay shows
border zones, LED position axes with tick labels, and calibration details.

Features:
- Tkinter-based transparent overlay window with click-through support
- Border zones highlighting pixel sampling areas (colored rectangles)
- LED position axes with numbered tick marks at regular intervals
- Calibration info box showing target name, LED counts, and configuration
- Toggle button (eye icon) in target cards for show/hide
- Localized UI strings (English and Russian)

Implementation:
- New screen_overlay.py module with OverlayWindow and OverlayManager classes
- Overlay runs in background thread with proper asyncio integration
- API endpoints for start/stop/status overlay control
- overlay_active state tracking in processor manager

Known limitation: tkinter threading cleanup causes server restart when overlay
is closed, but functionality works correctly while overlay is active.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-16 22:33:16 +03:00
ac5c1d0c82 Optimize numpy pipeline, add per-stage timing, and auto-sync LED count
- Eliminate 5 numpy↔tuple conversions per frame in processing hot path:
  map_border_to_leds returns ndarray, inline numpy smoothing with integer
  math, send_pixels_fast accepts ndarray directly
- Fix numpy boolean bug in keepalive check (use `is not None`)
- Add per-stage pipeline timing (extract/map/smooth/send) to metrics API
  and UI with color-coded breakdown bar
- Expose device_fps from WLED health check in API schemas
- Auto-sync LED count from WLED device: health check detects changes and
  updates storage, calibration, and active targets automatically
- Use integer math for brightness scaling (uint16 * brightness >> 8)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 17:43:16 +03:00
afb20f2dac Add configurable baud rate for Adalight with dynamic FPS hint
Baud rate is now a first-class device field, passed through the full
stack: Device model → API schemas → routes → ProcessorManager →
AdalightClient. The frontend shows a baud rate dropdown (115200–2M)
for Adalight devices in both Add Device and Settings modals, with a
live "Max FPS ≈ N" hint computed from LED count and baud rate.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 16:35:41 +03:00
1612c04c90 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>
2026-02-16 15:55:42 +03:00
242718a9a9 Add LEDDeviceProvider abstraction and standby capability flag
Consolidate all device-type-specific logic into LEDDeviceProvider ABC
with provider registry. WLEDDeviceProvider handles client creation,
health checks, validation, mDNS discovery, and brightness control.
Routes now delegate to providers instead of using if/else type checks.

Add standby_required capability and expose device capabilities in API.
Target editor conditionally shows standby interval based on selected
device's capabilities.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 13:39:27 +03:00
638dc526f9 Add WLED auto-discovery via mDNS with zeroconf
Scan the local network for WLED devices advertising _wled._tcp.local.
and present them in the Add Device modal for one-click selection.

- New discovery.py: async mDNS browse + parallel /json/info enrichment
- GET /api/v1/devices/discover endpoint with already_added dedup
- Header scan button (magnifying glass icon) in add-device modal
- Discovered devices show name, IP, LED count, version; click to fill form
- en/ru locale strings for discovery UI

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 13:06:29 +03:00
b5a6885126 Add LED device abstraction layer for multi-controller support
Introduce abstract LEDClient base class with factory pattern so new
LED controller types can plug in alongside WLED. ProcessorManager is
now fully type-agnostic — all device-specific logic (health checks,
state snapshot/restore, fast send) lives behind the LEDClient interface.

- New led_client.py: LEDClient ABC, DeviceHealth, factory functions
- WLEDClient inherits LEDClient, encapsulates WLED health checks and state management
- device_type field on Device storage model (defaults to "wled")
- Rename target_type "wled" → "led" with backward-compat migration
- Frontend: "WLED" tab → "LED", device type badge, type selector in
  add-device modal, device type shown in target device dropdown
- All wled_* API fields renamed to device_* for generic naming

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 12:41:02 +03:00
afce183f79 Add skip LEDs feature with physical resampling and per-edge tick labels
Skip LEDs at the start/end of the strip are blacked out while the full
screen perimeter is resampled onto the remaining active LEDs using linear
interpolation. Calibration canvas tick labels show per-edge display
ranges clipped to the active LED range. Moved LED offset control from
inline overlay to a dedicated form row alongside the new skip inputs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 10:55:21 +03:00
398f090eca Port WLED optimizations to KC loop: fix FPS metrics, add keepalive and auto-refresh test
- Fix KC fps_actual to use frame-to-frame timestamps (was inflated by measuring before sleep)
- Add fps_potential, fps_current, frames_skipped, frames_keepalive metrics to KC loop
- Add keepalive broadcast for static frames so WS clients stay in sync
- Expose all KC metrics in get_kc_target_state() and update UI card to show 7 metrics
- Add auto-refresh play/pause button to KC test lightbox (polls every ~1s)
- Fix WebSocket color swatches computing hex from r,g,b when hex field is absent
- Fix WebSocket auth crash by using get_config() instead of module-level config variable
- Fix lightbox closing when clicking auto-refresh button (event bubbling)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 15:57:07 +03:00
9383fb9a53 Apply postprocessing filters in KC test endpoint
The KC test was showing the raw captured image instead of the processed
one. Now resolves the filter chain from postprocessing templates and
applies them before color extraction, matching live KC processing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 15:38:32 +03:00
3100b0d979 Add frame-change detection, keepalive, current FPS, and compact metrics UI
Skip redundant processing/DDP sends when screen is static using object
identity comparison. Add configurable standby interval to periodically
resend last frame keeping WLED in live mode. Track frames skipped,
keepalive count, and current FPS (rolling 1-second send count). Always
use DDP regardless of LED count. Compact metrics grid with label-value
rows and remove Skipped from UI display.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 15:17:14 +03:00
8d5ebc92ee Optimize WLED processing pipeline and add FPS metrics
- Add numpy-based DDP pixel packing (send_pixels_numpy) and fast send
  path (send_pixels_fast) eliminating per-pixel Python loops
- Move ProcessedLiveStream filter processing to background thread so
  get_latest_frame() returns pre-computed cached result instantly
- Vectorize map_border_to_leds for average interpolation using cumulative
  sums instead of 934 individual np.mean calls (~16ms -> <1ms)
- Batch all CPU work into single asyncio.to_thread call per frame
- Fix FPS calculation to measure frame-to-frame interval (was measuring
  processing time only, reporting inflated values)
- Add Potential FPS metric showing theoretical max without throttling
- Add FPS label to WLED target card properties
- Add fps_potential field to TargetProcessingState API schema

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 14:43:19 +03:00
0da1243fb0 Add KC target test button, API docs header link, and UI polish
- Add POST /api/v1/picture-targets/{target_id}/test endpoint for single-frame
  color extraction preview on Key Colors targets
- Add test button on KC target cards that opens lightbox with spinner,
  displays captured frame with rectangle overlays and color swatches
- Add API docs link in WebUI header
- Swap confirm dialog button colors (No=red, Yes=neutral)
- Remove type badges from WLED and KC target cards

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 22:10:01 +03:00
87e7eee743 Add Pattern Templates for Key Colors targets with visual canvas editor
Introduce Pattern Template entity as a reusable rectangle layout that
Key Colors targets reference via pattern_template_id. This replaces
inline rectangle storage with a shared template system.

Backend:
- New PatternTemplate data model, store (JSON persistence), CRUD API
- KC targets now reference pattern_template_id instead of inline rectangles
- ProcessorManager resolves pattern template at KC processing start
- Picture source test endpoint supports capture_duration=0 for single frame
- Delete protection: 409 when template is referenced by a KC target

Frontend:
- Pattern Templates section in Key Colors sub-tab with card UI
- Visual canvas editor with drag-to-move, 8-point resize handles
- Background capture from any picture source for visual alignment
- Precise coordinate list synced bidirectionally with canvas
- Resizable editor container, viewport-constrained modal
- KC target editor uses pattern template dropdown instead of inline rects
- Localization (en/ru) for all new UI elements

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 18:07:40 +03:00
5f9bc9a37e Add Key Colors target type for extracting colors from screen regions
Introduce a new "key_colors" target type alongside WLED targets, enabling
real-time color extraction from configurable screen rectangles with
average/median/dominant modes, temporal smoothing, and WebSocket streaming.

- Split WledPictureTarget into its own module, add KeyColorsPictureTarget
- Add KC target lifecycle to ProcessorManager (register, start/stop, processing loop)
- Extend API routes and schemas for KC targets (CRUD, settings, state, metrics, colors)
- Add WebSocket endpoint for real-time color updates with auth
- Add KC sub-tab in Targets UI with editor modal and live color swatches
- Add EN and RU translations for all key colors strings

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 16:43:09 +03:00
55814a3c30 Introduce Picture Targets to separate processing from devices
Add PictureTarget entity that bridges PictureSource to output device,
separating processing settings from device connection/calibration state.
This enables future target types (Art-Net, E1.31) and cleanly decouples
"what to stream" from "where to stream."

- Add PictureTarget/WledPictureTarget dataclasses and storage
- Split ProcessorManager into DeviceState (health) + TargetState (processing)
- Add /api/v1/picture-targets endpoints (CRUD, start/stop, settings, metrics)
- Simplify device API (remove processing/settings/metrics endpoints)
- Auto-migrate existing device settings to picture targets on first startup
- Add Targets tab to WebUI with target cards and editor modal
- Add en/ru locale keys for targets UI

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 15:27:41 +03:00
c3828e10fa Refactor capture engine architecture, rename PictureStream to PictureSource, and split API modules
- Separate CaptureEngine into stateless factory + stateful CaptureStream session
- Add LiveStream/LiveStreamManager for shared capture with reference counting
- Rename PictureStream to PictureSource across storage, API, and UI
- Remove legacy migration logic and unused compatibility code
- Split monolithic routes.py (1935 lines) into 5 focused route modules
- Split schemas.py (480 lines) into 7 schema modules with re-exports
- Extract dependency injection into dedicated dependencies.py

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 14:27:00 +03:00
472acd700a Add full-image lightbox and restore WLED state on stop
- Add GET /picture-streams/full-image endpoint to serve full-res images
- Click static image preview thumbnail to open full-res lightbox
- Snapshot WLED state (on/off, lor, AudioReactive) before streaming
- Restore saved WLED state when streaming stops

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 03:06:59 +03:00
66eecdb3c9 Fix settings persistence, streaming stability, and UI polish
- Fix device settings partial update using model_fields_set for true merge
- Add missing interpolation_mode and smoothing to all API responses
- Fix send_pixels race condition when wled_client is None during stop
- Allow LED segments to exceed edge pixel count (float stepping)
- Fix modal scroll lock using position:fixed to prevent layout shift
- Show loading state for brightness slider until real value is fetched
- Remove stream description from stream selector dialog

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 02:59:34 +03:00
aa02a5f372 Add WLED brightness control, auto-name dialogs, and UI fixes
- Brightness slider now reads/writes actual WLED device brightness via
  new GET/PUT /devices/{id}/brightness endpoints (0-255 range)
- Cache last-known brightness to prevent slider jumping on card refresh
- Auto-generate names for stream, engine template, and PP template dialogs
- Fix sub-tabs not re-rendering on language change
- Add capture template icon (camera) to stream card pills
- Fix last calibration tutorial popup position

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 02:20:35 +03:00