diff --git a/server/CLAUDE.md b/server/CLAUDE.md index d115880..67a817b 100644 --- a/server/CLAUDE.md +++ b/server/CLAUDE.md @@ -73,6 +73,10 @@ After restarting the server with new code: 2. **Restart the server** 3. Test with `GET /api/v1/config/displays` +### Modifying server login: +1. Update the logic. +2. **Restart the server** + ### Adding translations: 1. Add keys to `static/locales/en.json` and `static/locales/ru.json` 2. Add `data-i18n` attributes to HTML elements in `static/index.html` diff --git a/server/src/wled_controller/core/wled_client.py b/server/src/wled_controller/core/wled_client.py index 3e2c5e6..0f7ccb0 100644 --- a/server/src/wled_controller/core/wled_client.py +++ b/server/src/wled_controller/core/wled_client.py @@ -234,26 +234,35 @@ class WLEDClient: if not 0 <= brightness <= 255: raise ValueError(f"Brightness must be 0-255, got {brightness}") - # Validate pixel values + # Validate and convert pixel values to Python ints (handles numpy types) + # WLED expects a flat array: [r1, g1, b1, r2, g2, b2, ...] + flat_pixels = [] for i, (r, g, b) in enumerate(pixels): if not (0 <= r <= 255 and 0 <= g <= 255 and 0 <= b <= 255): raise ValueError(f"Invalid RGB values at index {i}: ({r}, {g}, {b})") + # Convert to Python int and flatten to [r, g, b, r, g, b, ...] + flat_pixels.extend([int(r), int(g), int(b)]) - # Build WLED JSON state + # Build WLED JSON state with flat pixel array payload = { "on": True, - "bri": brightness, + "bri": int(brightness), # Ensure brightness is also a Python int "seg": [ { "id": segment_id, - "i": pixels, # Individual LED colors + "i": flat_pixels, # Individual LED colors as flat array } ], } + # Log payload details for debugging + logger.debug(f"Sending {len(pixels)} LEDs ({len(flat_pixels)} values) to WLED") + logger.debug(f"Payload size: ~{len(str(payload))} bytes") + logger.debug(f"First 3 LEDs: {flat_pixels[:9] if len(flat_pixels) >= 9 else flat_pixels}") + try: await self._request("POST", "/json/state", json_data=payload) - logger.debug(f"Sent {len(pixels)} pixel colors to WLED device") + logger.debug(f"Successfully sent pixel colors to WLED device") return True except Exception as e: diff --git a/server/src/wled_controller/static/app.js b/server/src/wled_controller/static/app.js index bacb218..4373a27 100644 --- a/server/src/wled_controller/static/app.js +++ b/server/src/wled_controller/static/app.js @@ -392,6 +392,28 @@ async function loadDevices() { }); const metrics = await metricsResponse.json(); + // Log device info, especially if there are errors + if (metrics.errors_count > 0) { + console.warn(`[Device: ${device.name || device.id}] Has ${metrics.errors_count} error(s)`); + + // Log recent errors from state + if (state.errors && state.errors.length > 0) { + console.error('Recent errors:'); + state.errors.forEach((error, index) => { + console.error(` ${index + 1}. ${error}`); + }); + } + + // Log last error from metrics + if (metrics.last_error) { + console.error('Last error:', metrics.last_error); + } + + // Log full state and metrics for debugging + console.log('Full state:', state); + console.log('Full metrics:', metrics); + } + return { ...device, state, metrics }; } catch (error) { console.error(`Failed to load state for device ${device.id}:`, error); @@ -492,6 +514,7 @@ function attachDeviceListeners(deviceId) { // Device actions async function startProcessing(deviceId) { + console.log(`[Device: ${deviceId}] Starting processing...`); try { const response = await fetch(`${API_BASE}/devices/${deviceId}/start`, { method: 'POST', @@ -504,19 +527,22 @@ async function startProcessing(deviceId) { } if (response.ok) { + console.log(`[Device: ${deviceId}] Processing started successfully`); showToast('Processing started', 'success'); loadDevices(); } else { const error = await response.json(); + console.error(`[Device: ${deviceId}] Failed to start:`, error); showToast(`Failed to start: ${error.detail}`, 'error'); } } catch (error) { - console.error('Failed to start processing:', error); + console.error(`[Device: ${deviceId}] Failed to start processing:`, error); showToast('Failed to start processing', 'error'); } } async function stopProcessing(deviceId) { + console.log(`[Device: ${deviceId}] Stopping processing...`); try { const response = await fetch(`${API_BASE}/devices/${deviceId}/stop`, { method: 'POST', @@ -529,14 +555,16 @@ async function stopProcessing(deviceId) { } if (response.ok) { + console.log(`[Device: ${deviceId}] Processing stopped successfully`); showToast('Processing stopped', 'success'); loadDevices(); } else { const error = await response.json(); + console.error(`[Device: ${deviceId}] Failed to stop:`, error); showToast(`Failed to stop: ${error.detail}`, 'error'); } } catch (error) { - console.error('Failed to stop processing:', error); + console.error(`[Device: ${deviceId}] Failed to stop processing:`, error); showToast('Failed to stop processing', 'error'); } } @@ -697,6 +725,8 @@ async function handleAddDevice(event) { const url = document.getElementById('device-url').value; const led_count = parseInt(document.getElementById('device-led-count').value); + console.log(`Adding device: ${name} (${url}, ${led_count} LEDs)`); + try { const response = await fetch(`${API_BASE}/devices`, { method: 'POST', @@ -710,11 +740,14 @@ async function handleAddDevice(event) { } if (response.ok) { + const result = await response.json(); + console.log('Device added successfully:', result); showToast('Device added successfully', 'success'); event.target.reset(); loadDevices(); } else { const error = await response.json(); + console.error('Failed to add device:', error); showToast(`Failed to add device: ${error.detail}`, 'error'); } } catch (error) { diff --git a/server/src/wled_controller/static/index.html b/server/src/wled_controller/static/index.html index 8d064f6..3f99842 100644 --- a/server/src/wled_controller/static/index.html +++ b/server/src/wled_controller/static/index.html @@ -266,32 +266,34 @@ - @@ -425,7 +427,11 @@ document.body.classList.remove('modal-open'); } - function submitApiKey() { + function submitApiKey(event) { + if (event) { + event.preventDefault(); + } + const input = document.getElementById('api-key-input'); const error = document.getElementById('api-key-error'); const key = input.value.trim(); @@ -454,15 +460,6 @@ startAutoRefresh(); } } - - // Handle Enter key in modal - document.addEventListener('DOMContentLoaded', () => { - document.getElementById('api-key-input').addEventListener('keypress', (e) => { - if (e.key === 'Enter') { - submitApiKey(); - } - }); - });