diff --git a/server/src/wled_controller/core/processing/wled_target_processor.py b/server/src/wled_controller/core/processing/wled_target_processor.py index 5c733e3..70d3db8 100644 --- a/server/src/wled_controller/core/processing/wled_target_processor.py +++ b/server/src/wled_controller/core/processing/wled_target_processor.py @@ -433,12 +433,16 @@ class WledTargetProcessor(TargetProcessor): if ws in self._preview_clients: self._preview_clients.remove(ws) - async def _broadcast_led_preview(self, colors: np.ndarray) -> None: - """Broadcast LED colors as binary RGB bytes to preview WebSocket clients.""" + async def _broadcast_led_preview(self, colors: np.ndarray, brightness: int = 255) -> None: + """Broadcast LED colors as binary RGB bytes to preview WebSocket clients. + + Wire format: [brightness_byte] [R G B R G B ...] + First byte is the effective brightness (0-255), rest is RGB pixel data. + """ if not self._preview_clients: return - data = colors.astype(np.uint8).tobytes() + data = bytes([brightness]) + colors.astype(np.uint8).tobytes() async def _send_safe(ws): try: @@ -605,7 +609,7 @@ class WledTargetProcessor(TargetProcessor): send_timestamps.append(now) self._metrics.frames_keepalive += 1 if self._preview_clients and (now - _last_preview_broadcast) >= 0.066: - await self._broadcast_led_preview(send_colors) + await self._broadcast_led_preview(send_colors, cur_brightness) _last_preview_broadcast = now self._metrics.frames_skipped += 1 while send_timestamps and send_timestamps[0] < now - 1.0: @@ -640,7 +644,7 @@ class WledTargetProcessor(TargetProcessor): # Broadcast to LED preview WebSocket clients (throttled to ~15 fps) if self._preview_clients and (now - _last_preview_broadcast) >= 0.066: - await self._broadcast_led_preview(send_colors) + await self._broadcast_led_preview(send_colors, cur_brightness) _last_preview_broadcast = now self._metrics.timing_send_ms = send_ms diff --git a/server/src/wled_controller/static/css/cards.css b/server/src/wled_controller/static/css/cards.css index f2d06b1..9822cd0 100644 --- a/server/src/wled_controller/static/css/cards.css +++ b/server/src/wled_controller/static/css/cards.css @@ -631,13 +631,27 @@ ul.section-tip li { .led-preview-panel { padding: 4px 0 0; + position: relative; } .led-preview-canvas { display: block; width: 100%; - height: 16px; + height: 32px; border-radius: 3px; image-rendering: pixelated; background: #111; } + +.led-preview-brightness { + position: absolute; + right: 4px; + top: 50%; + transform: translateY(-50%); + font-size: 0.8rem; + font-family: var(--font-mono, monospace); + color: #fff; + text-shadow: 0 0 3px rgba(0,0,0,0.8); + pointer-events: none; + opacity: 0.8; +} diff --git a/server/src/wled_controller/static/js/features/targets.js b/server/src/wled_controller/static/js/features/targets.js index 3c809e1..b0085f4 100644 --- a/server/src/wled_controller/static/js/features/targets.js +++ b/server/src/wled_controller/static/js/features/targets.js @@ -846,6 +846,7 @@ export function createTargetCard(target, deviceMap, colorStripSourceMap, valueSo