21 Commits

Author SHA1 Message Date
alexei.dolgolyov 2b5dac2c42 feat(devices): BLE LED controller support (SP110E/Triones/Zengge/Govee)
Build Android APK / build-android (push) Failing after 1m44s
Lint & Test / test (push) Successful in 4m22s
End-to-end BLE streaming: provider + client + per-protocol wire encoders
with whole-strip averaging, desktop (bleak) and Android (Kotlin BleBridge
via Chaquopy) transports, discovery with protocol-family detection that
auto-fills the UI, throttled not-connected warning + 10 s reconnect
cooldown so a dropped link no longer stalls the pipeline at ~30 s/frame,
and an explicit asyncio.wait_for wrapper around bleak connect() since
the WinRT backend doesn't always honor the timeout kwarg.

Also rewrites server/restart.ps1 to be parameterized (-Port / -Module /
-PythonVersion / timeouts / -Quiet), pick the right interpreter via the
py launcher, pre-flight the target module, poll port readiness on both
shutdown and startup, redirect child stdout/stderr so Start-Process
doesn't hang on inherited Git-Bash handles, and return proper exit codes.

Rolls in concurrent work: Android BLE permissions + launcher icons + ru/zh
resources, Chaquopy-safe value_stream psutil fallback, setup-required
modal, asset-store test coverage, and misc system/config touch-ups.
2026-04-21 14:58:35 +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 a0b65e3fcb refactor: move build scripts to build/ directory
Lint & Test / test (push) Successful in 2m21s
Declutters the repo root by consolidating build-common.sh,
build-dist.sh, build-dist-windows.sh, build-dist.ps1, and installer.nsi
into build/. Updates all path references in CI workflows, NSIS installer,
and documentation.
2026-04-12 23:16:40 +03:00
alexei.dolgolyov 02cd9d519c refactor: rename project to LedGrab, split HA integration into separate repo
Lint & Test / test (push) Successful in 1m56s
- Rename Python package: wled_controller -> ledgrab
- Rename env var prefix: WLED_ -> LEDGRAB_ (with auto-migration for old vars)
- Rename localStorage key: wled_api_key -> ledgrab_api_key (with migration)
- Rename HA integration domain: wled_screen_controller -> ledgrab
- Update all imports, build scripts, Docker, installer, config, docs
- Remove HA integration (moved to ledgrab-haos-integration repo)
- Remove hacs.json (belongs in HA repo now)
- Add startup warning for users with old WLED_ env vars
- All tests pass (715/715), ruff clean, tsc clean, frontend builds
2026-04-12 22:45:28 +03:00
alexei.dolgolyov e678e5590a docs: update TODO and frontend context docs
Lint & Test / test (push) Successful in 1m54s
Replace TODO-css-improvements.md with TODO-release.md. Add EntityPalette
and IconSelect patterns for dynamic entity lists to frontend context.
2026-04-12 20:55:58 +03:00
alexei.dolgolyov ace24715c8 feat: add math_wave color strip source type
Lint & Test / test (push) Has been cancelled
Mathematical wave generator that produces per-LED colors from
configurable waveform layers (sine, triangle, sawtooth, square) with
superposition, mapped through a gradient palette. Supports sync clocks,
bindable speed, and up to 8 wave layers.

- Storage model with wave validation and apply_update
- Numpy-vectorized stream with gradient LUT color mapping
- API schemas (create/update/response) and route registration
- Frontend editor with dynamic wave layer rows, gradient picker,
  speed widget, and IconSelect waveform selectors
- i18n in en/ru/zh
2026-04-05 00:41:07 +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 d9cb1eb225 fix: replace emoji characters with SVG icons in buttons and labels
Lint & Test / test (push) Successful in 1m19s
- Endpoint copy buttons: 📋 → ICON_CLONE (3 places)
- Scene preset "used by": 🔗 → ICON_LINK
- Automation webhook condition: 🔗 → ICON_WEB
- Add "No Emoji" rule to contexts/frontend.md
2026-03-25 13:16:46 +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 347b252f06 feat: add auto-name generation to all remaining creation modals
Lint & Test / test (push) Failing after 27s
Audio sources: type + device/parent/channel/band detail
Weather sources: provider + coordinates (updates on geolocation)
Sync clocks: "Sync Clocks · Nx" (updates on speed slider)
Automations: scene name + condition count/logic
Scene presets: "Scenes · N targets" (updates on add/remove)
Pattern templates: "Pattern Templates · N rects" (updates on add/remove)

All follow the same pattern: name auto-generates on create, stops
when user manually edits the name field.
2026-03-24 21:44:28 +03:00
alexei.dolgolyov fc62d5d3b1 chore: sync CI/CD with upstream guide and update context docs
Lint & Test / test (push) Failing after 30s
release.yml: add fallback for existing releases on tag re-push.
installer.nsi: add .onInit file lock check, use LaunchApp function
instead of RUN_PARAMETERS to fix NSIS quoting bug.
build-dist.ps1: copy start-hidden.vbs to dist scripts/.
start-hidden.vbs: embedded Python fallback for installed/dev envs.

Update ci-cd.md with version detection, NSIS best practices, local
build testing, Gitea vs GitHub differences, troubleshooting.
Update frontend.md with full entity type checklist and common pitfalls.
2026-03-24 13:59:27 +03:00
alexei.dolgolyov 0716d602e2 docs: add CI/CD context file and pre-commit lint rule
Lint & Test / test (push) Failing after 13s
Create contexts/ci-cd.md documenting release pipeline, build scripts,
CI runners, and versioning. Reference it from CLAUDE.md context table.
Add mandatory pre-commit lint check rule to CLAUDE.md.
2026-03-22 13:52:47 +03:00
alexei.dolgolyov f2871319cb refactor: comprehensive code quality, security, and release readiness improvements
Lint & Test / test (push) Failing after 48s
Security: tighten CORS defaults, add webhook rate limiting, fix XSS in
automations, guard WebSocket JSON.parse, validate ADB address input,
seal debug exception leak, URL-encode WS tokens, CSS.escape in selectors.

Code quality: add Pydantic models for brightness/power endpoints, fix
thread safety and name uniqueness in DeviceStore, immutable update
pattern, split 6 oversized files into 16 focused modules, enable
TypeScript strictNullChecks (741→102 errors), type state variables,
add dom-utils helper, migrate 3 modules from inline onclick to event
delegation, ProcessorDependencies dataclass.

Performance: async store saves, health endpoint log level, command
palette debounce, optimized entity-events comparison, fix service
worker precache list.

Testing: expand from 45 to 293 passing tests — add store tests (141),
route tests (25), core logic tests (42), E2E flow tests (33), organize
into tests/api/, tests/storage/, tests/core/, tests/e2e/.

DevOps: CI test pipeline, pre-commit config, Dockerfile multi-stage
build with non-root user and health check, docker-compose improvements,
version bump to 0.2.0.

Docs: rewrite CLAUDE.md (202→56 lines), server/CLAUDE.md (212→76),
create contexts/server-operations.md, fix .js→.ts references, fix env
var prefix in README, rewrite INSTALLATION.md, add CONTRIBUTING.md and
.env.example.
2026-03-22 00:38:28 +03:00
alexei.dolgolyov 122e95545c Card bulk operations, remove expand/collapse, graph color picker fix
- Bulk selection mode: Ctrl+Click or toggle button to enter, Escape to exit
- Shift+Click for range select, bottom toolbar with SVG icon action buttons
- All CardSections wired with bulk actions: Delete everywhere,
  Start/Stop for targets, Enable/Disable for automations
- Remove expand/collapse all buttons (no collapsible sections remain)
- Fix graph node color picker overlay persisting after outside click
- Add Icons section to frontend.md conventions
- Add trash2, listChecks, circleOff icons to icon system
- Backend: processing loop performance improvements (monotonic timestamps,
  deque-based FPS tracking)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 01:21:27 +03:00
alexei.dolgolyov 191c988cf9 Graph node FPS hover tooltip, full names, no native SVG tooltips
Graph editor:
- Floating FPS tooltip on hover over running output_target nodes (300ms delay)
- Shows errors, uptime, and FPS sparkline seeded from server metrics history
- Tooltip positioned below node with fade-in/out animation
- Uses pointerover/pointerout with relatedTarget check to prevent flicker
- Fixed-width tooltip (200px) with monospace values to prevent layout shift
- Node titles show full names (removed truncate), no native SVG <title> tooltips

Documentation:
- Added duration/numeric formatting conventions to contexts/frontend.md
- Added node hover tooltip docs to contexts/graph-editor.md

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 15:45:59 +03:00
alexei.dolgolyov 00c9ad3a86 Live KC test WS, sync clock fix, device card perf, camera icons, tab indicator
Key Colors test:
- New WS endpoint for live KC target test streaming (replaces REST polling)
- Auto-connect on lightbox open, auto-disconnect on close
- Uses same FPS/preview_width as CSS source test (no separate controls)
- Removed FPS selector, start/stop toggle, and updateAutoRefreshButton

Device cards:
- Fix full re-render on every poll caused by relative "Last seen" time in HTML
- Last seen label now patched in-place via data attribute (like FPS metrics)
- Remove overlay visualization button from LED target cards

Sync clocks:
- Fix card not updating start/stop icon: invalidate cache before reload

Other:
- Tab indicator respects bg-anim toggle (hidden when dynamic background off)
- Camera backend icon grid uses SVG icons instead of emoji
- Frontend context rule: no emoji in IconSelect items

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 02:03:07 +03:00
alexei.dolgolyov a4a0e39b9b Replace bare — and generic None in selectors with descriptive None (reason) labels
All optional entity selectors now use the format "None (description)" with
i18n keys instead of hardcoded "—" or bare "None". Added common.none_no_cspt,
common.none_no_input, common.none_own_speed keys to all 3 locales. Updated
frontend context with the convention.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 17:46:37 +03:00
alexei.dolgolyov 49c2a63d68 Bundle frontend with esbuild, serve fonts offline, fix dashboard
- Add esbuild bundling: JS (IIFE, minified, sourcemapped) and CSS into
  single dist/ files, replacing 15+ individual CSS links and CDN scripts
- Bundle Chart.js and ELK.js from npm instead of CDN (fully offline)
- Serve DM Sans and Orbitron fonts locally from static/fonts/
- Fix dashboard automation card stretching full width (max-width: 500px)
- Fix time_of_day condition not localized in automation cards
- Add Chrome browser tools context file for MCP testing workflow
- Update frontend context with bundling docs and Chrome tools reference

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-14 22:20:20 +03:00
alexei.dolgolyov 39981fbc45 Add graph editor filter, anchor-based positioning, and context docs
- Add name/kind/subtype filter bar with keyboard shortcut (F key)
- Filtered-out nodes get dimmed styling, nearly invisible on minimap
- Add anchor-based positioning for minimap and toolbar (remembers
  which corner element is closest to, maintains offset on resize)
- Fix minimap not movable after reload (_applyMinimapAnchor undefined)
- Fix ResizeObserver to use anchor system for both minimap and toolbar
- Add graph-editor.md context file and update frontend.md with graph sync notes
- Add filter i18n keys for en/ru/zh locales

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 18:39:14 +03:00
alexei.dolgolyov bd7a315c2c Add visual graph editor for entity interconnections
SVG-based node graph with ELK.js autolayout showing all 13 entity types
and their relationships. Features include:

- Pan/zoom canvas with bounds clamping and dead-zone click detection
- Interactive minimap with viewport rectangle, click-to-pan, drag-to-move,
  and dual resize handles (bottom-left/bottom-right)
- Movable toolbar with drag handle and inline zoom percentage indicator
- Entity-type SVG icons from Lucide icon set with subtype-specific overrides
- Command palette search (/) with keyboard navigation and fly-to
- Node selection with upstream/downstream chain highlighting
- Double-click to zoom-to-card, edit/delete overlay on hover
- Legend panel, orphan node detection, running state indicators
- Full i18n support with languageChanged re-render
- Catmull-Rom-to-cubic bezier edge routing for smooth curves

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 15:01:47 +03:00
alexei.dolgolyov e912019873 Improve CSS test preview: HD resolution, screen-only border, and refactor frontend docs
- Bump capture preview resolution from 480×360 to 960×540 (HD)
- Increase preview FPS from 2 to ~12 FPS (AUX_INTERVAL 0.5→0.08)
- Add accent-color border on screen rect only (not LED edges) via ::after
- Use dynamic aspect-ratio from decoded JPEG frames instead of fixed height
- Widen modal to 900px for picture sources
- Move frontend conventions from CLAUDE.md to contexts/frontend.md

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