Commit Graph

33 Commits

Author SHA1 Message Date
alexei.dolgolyov ecae05d00b feat(metrics): battery + thermal-zone readings with dashboard temp chart
Build Android APK / build-android (push) Failing after 1m40s
Lint & Test / test (push) Successful in 4m18s
Extends MetricsProvider with thermals() returning a ThermalSnapshot
(battery_percent, battery_temp_c, cpu_temp_c — all optional). Each
provider implements it independently:

- AndroidMetricsProvider reads /sys/class/power_supply/battery/{capacity,
  temp} (battery temp is tenths of degC) and walks
  /sys/class/thermal/thermal_zone*, filtering by zone type
  (cpu/soc/tsens/core) so battery and skin sensors don't dominate the
  reading. Rejects nonsense values like INT_MAX from buggy zones.
- PsutilMetricsProvider uses sensors_battery() and
  sensors_temperatures() when present (Linux+laptops); no-ops on
  Windows/macOS where psutil doesn't expose them.
- NullMetricsProvider returns the empty snapshot.

PerformanceResponse gains battery_percent / battery_temp_c / cpu_temp_c.
The metrics-history ring buffer also carries cpu_temp / battery_pct /
battery_temp per sample so the dashboard can graph them over time.

Frontend dashboard (perf-charts.ts) gets a new Temperature chart card,
hidden by default and revealed only after seed/poll confirms the
backend reports cpu_temp_c. Battery temperature shows inline as a
secondary badge. The GPU card now also hides entirely when the backend
reports gpu=null instead of showing an "unavailable" placeholder.
HOST_ONLY_KEYS prevents the System/App/Both toggle from flipping a
non-existent app dataset for temp.

Tests: 6 new for thermals (battery tenths-of-degC parsing, CPU zone
filtering, fallback when sensors absent, INT_MAX rejection); 18 metrics
tests total; full suite 733 passing.
2026-04-14 13:48:01 +03:00
alexei.dolgolyov 546b24d015 refactor(metrics): MetricsProvider abstraction with Android /proc backend
Build Android APK / build-android (push) Failing after 1m39s
Lint & Test / test (push) Successful in 4m20s
Moves direct psutil.* calls behind a MetricsProvider Protocol so the
codebase no longer needs ad-hoc `if psutil is not None` guards at every
call site. Each provider lives in its own module under
utils/metrics/: PsutilMetricsProvider for desktop, NullMetricsProvider
as a zeroed fallback, AndroidMetricsProvider that reads /proc/stat,
/proc/meminfo, /proc/self/stat, and /proc/self/status directly (psutil
isn't available under Chaquopy). The Android provider tracks the
previous CPU sample so cpu_percent() returns delta-based percentages
matching psutil's interval=None semantics, and degrades to zeros when
any /proc file is unreadable instead of crashing the dashboard.

Factory get_metrics_provider() in utils/metrics/__init__.py picks
Android > psutil > Null. api/routes/system.py and
core/processing/metrics_history.py now go through the factory; psutil
import is confined to one place. 12 new unit tests cover paren-in-comm
parsing of /proc/self/stat, delta CPU%, missing-file resilience, and
factory selection order. Full suite: 727 passing.
2026-04-14 13:34:32 +03:00
alexei.dolgolyov 488df98996 fix(frontend): add autocomplete attrs to credential inputs
Build Android APK / build-android (push) Failing after 1m40s
Lint & Test / test (push) Successful in 3m35s
Silences browser accessibility warnings on the HA token, MQTT username,
and MQTT password fields. Uses new-password for the secret inputs to
discourage Chrome's site-password autofill from leaking into broker /
HA-token configuration.
2026-04-14 12:50:50 +03:00
alexei.dolgolyov 151cea3ecb ci: Android multi-ABI APK pipeline + pydantic-core wheel rebuild
Build Android APK / build-android (push) Failing after 2m31s
Lint & Test / test (push) Successful in 6m15s
Adds .gitea/workflows/build-android.yml — Linux runner installs JDK 17,
Python 3.11, Android SDK/NDK, symlinks server/src/ledgrab into the
Chaquopy python source dir, and runs assembleDebug on master pushes /
assembleRelease on v* tags. APK is uploaded as an artifact and attached
to the Gitea release on tag push. Conditional signing config in
build.gradle.kts reads keystore from env vars (CI secrets) and falls
back to debug signing locally. Gradle wrapper (gradlew/gradlew.bat/
gradle-wrapper.jar) committed so CI can drive the build.

Rebuilds pydantic-core wheels for arm64-v8a and x86_64 — both were
missing libpython3.11.so in NEEDED, which would have crashed at import
on real devices. build-pydantic-core.sh rewritten as a multi-ABI builder:
selects targets via args, sets RUSTFLAGS=-C link-arg=-Wl,--no-as-needed
-C link-arg=-lpython3.11 to force the symbol-resolution dependency,
uses the per-ABI sysconfigdata + libpython staged in
android/.build-cache/, prefers `py -3.11` on Windows (Git Bash's
python3.11 is an MSStore stub), uses the .cmd clang wrapper on Windows
(fixes os error 193), and verifies NEEDED via llvm-readelf after each
build. abiFilters restored to the full triple in build.gradle.kts;
multi-ABI debug APK builds cleanly (~99 MB).
2026-04-14 12:36:13 +03:00
alexei.dolgolyov 8574424fb7 feat: Android TV app embedding Python server via Chaquopy
Lint & Test / test (push) Successful in 2m10s
Adds a native Android TV application that runs the full LedGrab Python
server in-process via Chaquopy. Captures the TV box screen using the
MediaProjection API and exposes the existing web UI on the device's
local network — users configure via phone/tablet browser.

Android (new /android/ module):
- Kotlin shell: MainActivity, CaptureService (foreground service),
  ScreenCapture (MediaProjection + ImageReader), PythonBridge (Chaquopy).
- Polished Leanback-themed UI with QR code for easy web UI access.
- AGP 8.9 + Chaquopy 17 + Gradle 8.11 (avoids the AGP 8.7 thread-lock bug).
- Pre-built pydantic-core wheels for arm64-v8a, x86_64, x86 cross-compiled
  with maturin + Android NDK, linked against Chaquopy's libpython3.11.so.

Python server platform guards:
- New utils/platform.py with is_android()/is_windows()/is_linux() helpers.
- Guard every top-level import of desktop-only packages (mss, psutil,
  sounddevice, pyserial, PyAudioWPatch, etc.) with try/except ImportError.
- Android-incompatible calls gated with None-checks so the server runs on
  reduced capabilities on Android (no CPU/RAM metrics, no mss displays).
- utils/image_codec.py gains a Pillow fallback for resize + JPEG encode
  when cv2 is unavailable; all internal cv2.resize callers migrated.
- New android_entry.py start_server/stop_server invoked from Kotlin.
- get_displays API falls back to best available engine when mss fails.

New capture engines:
- MediaProjectionEngine: receives RGBA frames pushed from Kotlin through
  a thread-safe queue; caches last frame for static-screen previews.
- ScrcpyClientEngine: optional H.264 streaming via scrcpy-client library
  (priority 10, overrides the ADB-screencap engine when installed).

Frontend:
- Tab loaders previously required an apiKey; now correctly treat
  "auth disabled" as authenticated (Android has no auth by default).
- Re-trigger the active tab's loader after loadServerInfo resolves
  authRequired, since initTabs runs earlier.
- Add i18n keys for the demo / mediaprojection / scrcpy_client engines.

Docs:
- TODO.md: follow-ups for multi-ABI wheel rebuilds, CI pipeline, USB
  serial LED controllers, root-only capture, perf metrics abstraction.
- CLAUDE.md: Android dependency sync policy (pip --exclude doesn't exist).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 03:11:43 +03:00
alexei.dolgolyov cc9900d801 feat: support nesting for composite color strip sources
Lint & Test / test (push) Successful in 2m17s
Allow composite sources to reference other composite/mapped sources as
layers. Adds cycle detection (via transitive dependency graph walk),
depth limiting (MAX_COMPOSITE_DEPTH=4), and a runtime safety net in the
stream manager. Frontend layer dropdown now shows all source types
except the source being edited.

17 new tests covering cycles, depth limits, and valid nesting — all
715 tests passing.
2026-04-12 20:41:15 +03:00
alexei.dolgolyov 4940007e54 feat: add Group device type for combining multiple devices
Lint & Test / test (push) Successful in 2m19s
Introduces a new "group" device type that aggregates multiple physical
(or nested group) devices into one virtual device. Supports two modes:
- Sequence: LEDs concatenated end-to-end (led_count = sum of children)
- Independent: full pixel array resampled to each child independently

Includes cycle detection (DFS) to prevent circular group references,
delete protection for devices referenced by groups, recursive LED count
resolution for nested groups, and reorder controls (move up/down) for
child devices in the UI.

Backend: Device model, API schemas, GroupLEDClient, GroupDeviceProvider,
route validation, processing pipeline integration.
Frontend: type picker, child device picker with reorder, mode selector,
i18n (en/ru/zh), layers icon, CSS for group child rows.
Tests: 20 unit tests for cycle detection, LED count resolution, and
GroupLEDClient (sequence slicing, independent resampling, cleanup).
2026-04-11 02:26:56 +03:00
alexei.dolgolyov 492bdb95e3 feat: game integration system
Receive real-time events from games (CS2, Dota 2, LoL, etc.) and drive
LED effects through the existing color strip and value source pipelines.

Core:
- GameEventBus (thread-safe pub/sub) with standardized 23-type event vocabulary
- GameAdapter ABC + AdapterRegistry + MappingAdapter (YAML-driven)
- Built-in adapters: CS2 GSI, Dota 2 GSI, LoL Live Client, Generic Webhook
- Community YAML adapters: Minecraft, Valorant, Rocket League
- GameEventColorStripStream with 5 effects (flash/pulse/sweep/color_shift/breathing)
- GameEventValueSource with EMA smoothing and timeout
- 4 built-in effect presets (FPS Combat, MOBA Health, Racing, Generic Alert)
- Auto-setup for Valve GSI games (Steam path detection, cfg file writing)
- Demo capture engine exposed to non-demo mode

Frontend:
- Game tab in Streams tree navigation with integration cards
- Game integration editor modal with adapter picker, config fields, event mappings
- game_event source type in CSS and ValueSource editors
- Setup instructions overlay (markdown rendered)
- Live event monitor and connection test

API:
- Full CRUD for game integrations
- Event ingestion endpoint (adapter-level auth)
- Adapter metadata, presets, auto-setup, status/diagnostics endpoints
2026-03-31 13:17:52 +03:00
alexei.dolgolyov 384362ccf1 feat: new value source types (HA entity, gradient map, strip extract) + UI fixes
Lint & Test / test (push) Successful in 1m27s
New value source types:
- ha_entity: reads numeric values from HA entity state/attribute, normalizes
  via min/max range, applies EMA smoothing. EntitySelect for HA connection
  and entity selection with live entity list fetching.
- gradient_map: maps a float value source (0-1) through a gradient entity.
  EntitySelect for both input source and gradient with inline previews.
- css_extract: extracts single color by averaging LED range from a color
  strip source. EntitySelect for source selection.

Value source type picker:
- Filter tabs (All / Numeric / Color) above the icon grid
- showTypePicker extended with filterTabs + onFilterChange support

Palette selectors converted to EntitySelect:
- Effect palette, gradient preset, and audio palette selectors now use
  command-palette style EntitySelect with gradient strip previews

Tab indicator fixes:
- Icon now updates on tab switch (was passing no args to updateTabIndicator)
- Visible with any background effect active, not just Noise Field
- Noise Field is the default background effect for new users

Dashboard section collapse fix:
- Split header into clickable toggle (chevron+label) and non-clickable
  actions area — buttons no longer trigger collapse/expand

Discriminated union fix (422 errors):
- source_type/target_type now always included in update payloads for:
  CSS editor, LED target, HA light target, simple calibration,
  advanced calibration
2026-03-29 20:38:22 +03:00
alexei.dolgolyov 8a17bb5caa feat: BindableFloat — universal value source binding for all scalar properties
Lint & Test / test (push) Successful in 1m20s
Introduce BindableFloat abstraction that allows any numeric property to be
either a static value or dynamically driven by a ValueSource. Backward-compatible
serialization: plain float when unbound, {value, source_id} dict when bound.

Backend:
- storage/bindable.py — BindableFloat dataclass + bfloat() helper
- 25+ scalar properties converted across all entity types
- Runtime VS acquisition in ColorStripStreamManager for CSS bindings
- All stream hot loops use self.resolve() for live values
- KeyColorsColorStripStream now inherits ColorStripStream

Frontend:
- BindableScalarWidget (slider + VS picker toggle) for all editors
- TypeScript BindableFloat type + helpers
- Graph editor edges for all bindable properties
- Audio source channel IconSelect grid

Fixes: daylight longitude, candlelight wind_strength/candle_type from_dict
2026-03-29 00:33:24 +03:00
alexei.dolgolyov e2e1107df7 feat: asset-based image/video sources, notification sounds, UI improvements
Lint & Test / test (push) Has been cancelled
- Replace URL-based image_source/url fields with image_asset_id/video_asset_id
  on StaticImagePictureSource and VideoCaptureSource (clean break, no migration)
- Resolve asset IDs to file paths at runtime via AssetStore.get_file_path()
- Add EntitySelect asset pickers for image/video in stream editor modal
- Add notification sound configuration (global sound + per-app overrides)
- Unify per-app color and sound overrides into single "Per-App Overrides" section
- Persist notification history between server restarts
- Add asset management system (upload, edit, delete, soft-delete)
- Replace emoji buttons with SVG icons throughout UI
- Various backend improvements: SQLite stores, auth, backup, MQTT, webhooks
2026-03-26 20:40:25 +03:00
alexei.dolgolyov 7939322a7f feat: reduce build size — replace Pillow with cv2, refactor build scripts
Build Release / create-release (push) Successful in 1s
Build Release / build-docker (push) Successful in 42s
Lint & Test / test (push) Successful in 2m50s
Build Release / build-windows (push) Successful in 3m27s
Build Release / build-linux (push) Successful in 1m59s
- Create utils/image_codec.py with cv2-based image helpers
- Replace PIL usage across all routes, filters, and engines with cv2
- Move Pillow from core deps to [tray] optional in pyproject.toml
- Extract shared build logic into build-common.sh (detect_version, cleanup, etc.)
- Strip unused NumPy/PIL/zeroconf/debug files in build scripts
2026-03-25 14:18:16 +03:00
alexei.dolgolyov 382a42755d feat: add auto-update system with release checking, notification UI, and install-type-aware apply
- Abstract ReleaseProvider interface (Gitea impl, swappable for GitHub/GitLab)
- Background UpdateService with periodic checks, debounce, dismissed version persistence
- Install type detection (installer/portable/docker/dev) with platform-aware asset matching
- Download with progress events, silent NSIS reinstall, portable ZIP/tarball swap scripts
- Version badge pulse animation, dismissible banner with icon buttons, Settings > Updates tab
- Single source of truth: pyproject.toml version via importlib.metadata, CI stamps tag with sed
- API: GET/POST status, check, dismiss, apply, GET/PUT settings
- i18n: en, ru, zh (27+ keys each)
2026-03-25 13:16:18 +03:00
alexei.dolgolyov 9dfd2365f4 feat: migrate storage from JSON files to SQLite
Lint & Test / test (push) Failing after 28s
Replace 22 individual JSON store files with a single SQLite database
(data/ledgrab.db). All entity stores now use BaseSqliteStore backed by
SQLite with WAL mode, write-through caching, and thread-safe access.

- Add Database class with SQLite backup/restore API
- Add BaseSqliteStore as drop-in replacement for BaseJsonStore
- Convert all 16 entity stores to SQLite
- Move global settings (MQTT, external URL, auto-backup) to SQLite
  settings table
- Replace JSON backup/restore with SQLite snapshot backups (.db files)
- Remove partial export/import feature (backend + frontend)
- Update demo seed to write directly to SQLite
- Add "Backup Now" button to settings UI
- Remove StorageConfig file path fields (single database_file remains)
2026-03-25 00:03:19 +03:00
alexei.dolgolyov ef33935188 feat: add weather source entity and weather-reactive CSS source type
Lint & Test / test (push) Failing after 34s
New standalone WeatherSource entity with pluggable provider architecture
(Open-Meteo v1, free, no API key). Full CRUD, test endpoint, browser
geolocation, IconSelect provider picker, CardSection with test/clone/edit.

WeatherColorStripStream maps WMO weather codes to ambient color palettes
with temperature hue shifting and thunderstorm flash effects. Ref-counted
WeatherManager polls API and caches data per source.

CSS editor integration: weather type with EntitySelect source picker,
speed and temperature influence sliders. Backup/restore support.

i18n for en/ru/zh.
2026-03-24 18:52:46 +03:00
alexei.dolgolyov 2240471b67 Add demo mode: virtual hardware sandbox for testing without real devices
Demo mode provides a complete sandbox environment with:
- Virtual capture engine (radial rainbow test pattern on 3 displays)
- Virtual audio engine (synthetic music-like audio on 2 devices)
- Virtual LED device provider (strip/60, matrix/256, ring/24 LEDs)
- Isolated data directory (data/demo/) with auto-seeded sample entities
- Dedicated config (config/demo_config.yaml) with pre-configured API key
- Frontend indicator (DEMO badge + dismissible banner)
- Engine filtering (only demo engines visible in demo mode)
- Separate entry point: python -m wled_controller.demo (port 8081)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 16:17:14 +03:00
alexei.dolgolyov 304fa24389 Comprehensive WebUI review: 41 UX/feature/CSS improvements
Safety & Correctness:
- Add confirmation dialogs to Stop All, turnOffDevice
- i18n confirm dialog (title, yes, no buttons)
- Fix duplicate tutorial-overlay ID
- Define missing CSS variables (--radius, --text-primary, --hover-bg, --input-bg)
- Fix toast z-index conflict with confirm dialog (2500 → 3000)

UX Consistency:
- Add backdrop-close to test modals
- Add device clone feature (only entity without it)
- Add sync clocks to command palette
- Replace 20+ hardcoded accent colors with CSS vars/color-mix()
- Remove dead .badge duplicate from components.css
- Make calibration elements keyboard-accessible (div → button)
- Add aria-labels to color picker swatches
- Fix pattern canvas mobile horizontal scroll
- Fix graph editor mobile bottom clipping

Polish:
- Add empty-state messages to all CardSection instances
- Convert 21 px font-sizes to rem
- Add scroll-behavior: smooth with reduced-motion override
- Add @media print styles
- Add :focus-visible to 4 missing interactive elements
- Fix settings modal close label (Cancel → Close)
- Fix api-key submit button i18n

New Features:
- Command palette actions: start/stop targets, activate scenes, enable/disable
- Bulk start/stop API endpoints (POST /output-targets/bulk/start|stop)
- OS notification history viewer modal
- Scene "used by" automation reference count on cards
- Clock elapsed time display on Streams tab cards
- Device "last seen" relative timestamp on cards
- Audio device refresh button in edit modal
- Composite layer drag-to-reorder
- MQTT settings panel (broker config with JSON persistence)
- WebSocket log viewer with level filtering and ring buffer
- Runtime log-level adjustment (GET/PUT endpoints + settings UI)
- Animated value source waveform canvas preview
- Gradient custom preset save/delete (localStorage)
- API key read-only display in settings
- Backup metadata (file size, auto/manual badges)
- Server restart button with confirm + overlay
- Partial config export/import per entity type
- Progressive disclosure in target editor (Advanced section)

CSS Architecture:
- Define radius scale tokens (--radius-sm/md/lg/pill)
- Scope .cs-filter selectors to remove 7 !important overrides
- Consolidate duplicate toggle switch (filter-list → settings-toggle)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 18:46:38 +03:00
alexei.dolgolyov 294d704eb0 Add CSPT entity, processed CSS source type, reverse filter, and UI improvements
- Add Color Strip Processing Template (CSPT) entity: reusable filter chains
  for 1D LED strip postprocessing (backend, storage, API, frontend CRUD)
- Add "processed" color strip source type that wraps another CSS source and
  applies a CSPT filter chain (dataclass, stream, schema, modal, cards)
- Add Reverse filter for strip LED order reversal
- Add CSPT and processed CSS nodes/edges to visual graph editor
- Add CSPT test preview WS endpoint with input source selection
- Add device settings CSPT template selector (add + edit modals with hints)
- Use icon grids for palette quantization preset selector in filter lists
- Use EntitySelect for template references and test modal source selectors
- Fix filters.css_filter_template.desc missing localization
- Fix icon grid cell height inequality (grid-auto-rows: 1fr)
- Rename "Processed" subtab to "Processing Templates"
- Localize all new strings (en/ru/zh)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 02:16:59 +03:00
alexei.dolgolyov f6f428515a Update TODO.md and add task tracking rule to CLAUDE.md
Remove completed/deferred items from TODO.md and add instruction
to use TODO.md as the primary task tracker instead of TodoWrite.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 17:40:16 +03:00
alexei.dolgolyov 304c4703b9 Add manual backup trigger endpoint
POST /api/v1/system/auto-backup/trigger creates a backup on demand
and returns the created file info (filename, size, timestamp).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 14:27:44 +03:00
alexei.dolgolyov b0a769b781 Move tags input under name field in all entity editor modals
Remove the separate tags form-group (label, hint toggle, hint text)
from all 14 editor modals and place the tags container directly
below the name input for a cleaner, more compact layout.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 12:15:46 +03:00
alexei.dolgolyov ee40d99067 Add Daylight Cycle value source type
New value source that outputs brightness (0-1) based on the daylight
color LUT, computing BT.601 luminance from the simulated sky color.
Supports real-time wall-clock mode or configurable simulation speed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 11:27:36 +03:00
alexei.dolgolyov 1ce25caa35 Clean up TODO.md: remove completed items, add new P1 tasks
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 11:07:44 +03:00
alexei.dolgolyov 954e37c2ca Add auto-restart for crashed processing loops, remove sync clock badge
- Auto-restart: ProcessorManager detects fatal task crashes via done
  callback and restarts with exponential backoff (2s-30s, max 5 attempts
  in 5 min window). Manual stop disables auto-restart. Restart state
  exposed in target state API and via WebSocket events.
- Remove "Running"/"Paused" badge label from sync clock dashboard cards
  (pause/play button already conveys state).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 01:53:04 +03:00
alexei.dolgolyov 30fa107ef7 Add tags to all entity types with chip-based input and autocomplete
- Add `tags: List[str]` field to all 13 entity types (devices, output targets,
  CSS sources, picture sources, audio sources, value sources, sync clocks,
  automations, scene presets, capture/audio/PP/pattern templates)
- Update all stores, schemas, and route handlers for tag CRUD
- Add GET /api/v1/tags endpoint aggregating unique tags across all stores
- Create TagInput component with chip display, autocomplete dropdown,
  keyboard navigation, and API-backed suggestions
- Display tag chips on all entity cards (searchable via existing text filter)
- Add tag input to all 14 editor modals with dirty check support
- Add CSS styles and i18n keys (en/ru/zh) for tag UI
- Also includes code review fixes: thread safety, perf, store dedup

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 22:20:19 +03:00
alexei.dolgolyov 353a1c2d85 Rename picture-targets to output-targets across entire codebase
Rename all Python modules, classes, API endpoints, config keys, frontend
fetch URLs, and Home Assistant integration URLs from picture-targets to
output-targets. Store loads both new and legacy JSON keys for backward
compatibility with existing data files.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 10:55:36 +03:00
alexei.dolgolyov 8061c26bef 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>
2026-03-09 10:04:40 +03:00
alexei.dolgolyov 80b48e3618 Add clone support for scene presets and update TODO
- Add clone_preset() to ScenePresetStore with deep copy of target snapshots
- Add POST /scene-presets/{id}/clone API endpoint
- Add clone button to scene preset cards in Automations tab
- Add i18n keys for clone feedback in all 3 locales
- Add TODO items for dashboard stats collapse and protocol badge review

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 20:17:09 +03:00
alexei.dolgolyov 9ee6dcf94a Add PWA support and mobile responsive layout
- PWA manifest, service worker (stale-while-revalidate for static assets,
  network-only for API), and app icons for installability
- Root-scoped /manifest.json and /sw.js routes in FastAPI
- New mobile.css with responsive breakpoints at 768/600/400px:
  fixed bottom tab bar on phones, single-column cards, full-screen modals,
  compact header toolbar, touch-friendly targets
- Fix modal-content-wide min-width overflow on small screens
- Update README with Camera, OpenRGB, and PWA features

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 13:20:21 +03:00
alexei.dolgolyov 8fe9c6489b Add camera/webcam capture engine with engine-aware display picker
- New CameraEngine using OpenCV VideoCapture for webcam capture
- HAS_OWN_DISPLAYS class attribute on CaptureEngine base to distinguish
  engines with their own device lists from desktop monitor engines
- Display picker renders device list for cameras/scrcpy, spatial layout
  for desktop monitors
- Engine-aware display label formatting (camera name vs monitor index)
- Stream modal properly loads engine-specific displays on template change,
  edit, and clone
- Camera backend config rendered as dropdown (auto/dshow/msmf/v4l2)
- Remove offline label from device cards (healthcheck indicator suffices)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 12:46:28 +03:00
alexei.dolgolyov b9ec509f56 Add OpenRGB device support for PC peripheral ambient lighting
New device type enabling control of keyboards, mice, RAM, GPU, and fans
via the OpenRGB SDK server (TCP port 6742). Includes auto-discovery,
health monitoring, state snapshot/restore, and fast synchronous pixel
send with brightness scaling. Also updates TODO.md with complexity notes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 11:30:02 +03:00
alexei.dolgolyov bf2fd5ca69 Add noise gate, palette quantization filters and drag-and-drop filter ordering
- Add noise gate filter: suppresses per-pixel color flicker below threshold
  using stateful frame comparison with pre-allocated int16 buffers
- Add palette quantization filter: maps pixels to nearest color in preset
  or custom hex palette, using chunked processing for memory efficiency
- Add "string" option type to filter schema system (base, API, frontend)
- Replace up/down buttons with pointer-event drag-and-drop in PP template
  filter list, with clone/placeholder feedback and modal auto-scroll
- Add frame_interpolation locale keys (was missing from all 3 locales)
- Update TODO.md: mark completed processing pipeline items

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 10:58:02 +03:00
alexei.dolgolyov 62b3d44e63 Add stop-all buttons to target sections, perf chart color reset, and TODO
- Add stop-all buttons to LED targets and KC targets section headers
  (visible only when targets are running, uses headerExtra on CardSection)
- Add reset ability to performance chart color pickers (removes custom
  color from localStorage and reverts to default)
- Remove CODEBASE_REVIEW.md
- Add prioritized TODO.md with P1/P2/P3 feature roadmap

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 01:46:58 +03:00