diff --git a/server/src/wled_controller/core/processing/processor_manager.py b/server/src/wled_controller/core/processing/processor_manager.py index 793fa7d..0a52119 100644 --- a/server/src/wled_controller/core/processing/processor_manager.py +++ b/server/src/wled_controller/core/processing/processor_manager.py @@ -641,32 +641,15 @@ class ProcessorManager: pixels = [(0, 0, 0)] * ds.led_count await self._send_pixels_to_device(device_id, pixels) - def _is_serial_device(self, device_id: str) -> bool: - """Check if a device uses a serial (COM) connection.""" - ds = self._devices.get(device_id) - return ds is not None and ds.device_type not in ("wled",) - async def _send_pixels_to_device(self, device_id: str, pixels) -> None: - """Send pixels to a device. + """Send pixels to a device via cached idle client. - Serial devices: temporary connection (open, send, close). - WLED devices: cached idle client. + Reuses a cached connection to avoid repeated serial reconnections + (which trigger Arduino bootloader reset on Adalight devices). """ - ds = self._devices[device_id] try: - if self._is_serial_device(device_id): - client = create_led_client( - ds.device_type, ds.device_url, - led_count=ds.led_count, baud_rate=ds.baud_rate, - ) - try: - await client.connect() - await client.send_pixels(pixels) - finally: - await client.close() - else: - client = await self._get_idle_client(device_id) - await client.send_pixels(pixels) + client = await self._get_idle_client(device_id) + await client.send_pixels(pixels) except Exception as e: logger.error(f"Failed to send pixels to {device_id}: {e}") diff --git a/server/src/wled_controller/static/js/app.js b/server/src/wled_controller/static/js/app.js index 23f5b18..6ad2372 100644 --- a/server/src/wled_controller/static/js/app.js +++ b/server/src/wled_controller/static/js/app.js @@ -120,7 +120,7 @@ import { showCalibration, closeCalibrationModal, forceCloseCalibrationModal, saveCalibration, updateOffsetSkipLock, updateCalibrationPreview, setStartPosition, toggleEdgeInputs, toggleDirection, toggleTestEdge, - showCSSCalibration, + showCSSCalibration, toggleCalibrationOverlay, } from './features/calibration.js'; // Layer 6: tabs @@ -345,6 +345,7 @@ Object.assign(window, { toggleDirection, toggleTestEdge, showCSSCalibration, + toggleCalibrationOverlay, // tabs switchTab, diff --git a/server/src/wled_controller/static/js/features/calibration.js b/server/src/wled_controller/static/js/features/calibration.js index de84330..c48ca17 100644 --- a/server/src/wled_controller/static/js/features/calibration.js +++ b/server/src/wled_controller/static/js/features/calibration.js @@ -9,6 +9,7 @@ import { API_BASE, getHeaders, fetchWithAuth } from '../core/api.js'; import { showToast } from '../core/ui.js'; import { Modal } from '../core/modal.js'; import { closeTutorial, startCalibrationTutorial } from './tutorials.js'; +import { startCSSOverlay, stopCSSOverlay } from './color-strips.js'; /* ── CalibrationModal subclass ────────────────────────────────── */ @@ -37,6 +38,11 @@ class CalibrationModal extends Modal { onForceClose() { closeTutorial(); if (_isCSS()) { + const cssId = document.getElementById('calibration-css-id')?.value; + if (_overlayStartedHere && cssId) { + stopCSSOverlay(cssId); + _overlayStartedHere = false; + } _clearCSSTestMode(); document.getElementById('calibration-css-id').value = ''; const testGroup = document.getElementById('calibration-css-test-group'); @@ -55,6 +61,7 @@ const calibModal = new CalibrationModal(); let _dragRaf = null; let _previewRaf = null; +let _overlayStartedHere = false; /* ── Helpers ──────────────────────────────────────────────────── */ @@ -83,6 +90,50 @@ async function _clearCSSTestMode() { } } +function _setOverlayBtnActive(active) { + const btn = document.getElementById('calibration-overlay-btn'); + if (!btn) return; + if (active) { + btn.style.background = 'var(--primary-color)'; + btn.style.color = 'white'; + } else { + btn.style.background = ''; + btn.style.color = ''; + } +} + +async function _checkOverlayStatus(cssId) { + try { + const resp = await fetchWithAuth(`/color-strip-sources/${cssId}/overlay/status`); + if (resp.ok) { + const data = await resp.json(); + _setOverlayBtnActive(data.active); + } + } catch { /* ignore */ } +} + +export async function toggleCalibrationOverlay() { + const cssId = document.getElementById('calibration-css-id')?.value; + if (!cssId) return; + try { + const resp = await fetchWithAuth(`/color-strip-sources/${cssId}/overlay/status`); + if (!resp.ok) return; + const { active } = await resp.json(); + if (active) { + await stopCSSOverlay(cssId); + _setOverlayBtnActive(false); + _overlayStartedHere = false; + } else { + await startCSSOverlay(cssId); + _setOverlayBtnActive(true); + _overlayStartedHere = true; + } + } catch (err) { + if (err.isAuth) return; + console.error('Failed to toggle calibration overlay:', err); + } +} + /* ── Public API (exported names unchanged) ────────────────────── */ export async function showCalibration(deviceId) { @@ -114,6 +165,8 @@ export async function showCalibration(deviceId) { document.getElementById('calibration-device-id').value = device.id; document.getElementById('cal-device-led-count-inline').textContent = device.led_count; document.getElementById('cal-css-led-count-group').style.display = 'none'; + document.getElementById('calibration-overlay-btn').style.display = 'none'; + document.getElementById('calibration-tutorial-btn').style.marginLeft = ''; document.getElementById('cal-start-position').value = calibration.start_position; document.getElementById('cal-layout').value = calibration.layout; @@ -267,6 +320,14 @@ export async function showCSSCalibration(cssId) { calibModal.snapshot(); calibModal.open(); + // Show overlay toggle and check current status + _overlayStartedHere = false; + const overlayBtn = document.getElementById('calibration-overlay-btn'); + overlayBtn.style.display = ''; + document.getElementById('calibration-tutorial-btn').style.marginLeft = '0'; + _setOverlayBtnActive(false); + _checkOverlayStatus(cssId); + initSpanDrag(); requestAnimationFrame(() => renderCalibrationCanvas()); diff --git a/server/src/wled_controller/templates/modals/calibration.html b/server/src/wled_controller/templates/modals/calibration.html index 28ef749..c8932f6 100644 --- a/server/src/wled_controller/templates/modals/calibration.html +++ b/server/src/wled_controller/templates/modals/calibration.html @@ -3,7 +3,8 @@