From 1204676c30657d3763da1d32f14c651c75ef9605 Mon Sep 17 00:00:00 2001 From: "alexei.dolgolyov" Date: Sat, 21 Feb 2026 03:12:45 +0300 Subject: [PATCH] Fix serial send bloat when sharing CSS stream with higher-LED device When two targets share the same color strip source, configure() resizes the stream to the last caller's LED count. If a WLED device (934 LEDs) starts after a serial device (fewer LEDs), the serial target sends the full 934-LED frame over serial, massively inflating send time. Add _fit_to_device() to truncate/tile colors to the target's actual device LED count before sending, so each consumer only transmits what its device needs regardless of the shared stream's current size. Co-Authored-By: Claude Opus 4.6 --- .../core/processing/wled_target_processor.py | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) 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 0a507b0..d6954db 100644 --- a/server/src/wled_controller/core/processing/wled_target_processor.py +++ b/server/src/wled_controller/core/processing/wled_target_processor.py @@ -362,6 +362,22 @@ class WledTargetProcessor(TargetProcessor): return (colors.astype(np.uint16) * device_info.software_brightness >> 8).astype(np.uint8) return colors + @staticmethod + def _fit_to_device(colors: np.ndarray, device_led_count: int) -> np.ndarray: + """Truncate or repeat colors to match the target device LED count. + + Shared streams may be sized to a different consumer's LED count. + This ensures each target only sends what its device actually needs. + """ + n = len(colors) + if n == device_led_count or device_led_count <= 0: + return colors + if n > device_led_count: + return colors[:device_led_count] + # Tile to fill (rare — usually streams are >= device count) + reps = (device_led_count + n - 1) // n + return np.tile(colors, (reps, 1))[:device_led_count] + async def _processing_loop(self) -> None: """Main processing loop — poll ColorStripStream → apply brightness → send.""" stream = self._color_strip_stream @@ -430,7 +446,10 @@ class WledTargetProcessor(TargetProcessor): if prev_colors is not None and (loop_start - last_send_time) >= standby_interval: if not self._is_running or self._led_client is None: break - send_colors = self._apply_brightness(prev_colors, device_info) + kc = prev_colors + if device_info and device_info.led_count > 0: + kc = self._fit_to_device(kc, device_info.led_count) + send_colors = self._apply_brightness(kc, device_info) if self._led_client.supports_fast_send: self._led_client.send_pixels_fast(send_colors) else: @@ -448,6 +467,10 @@ class WledTargetProcessor(TargetProcessor): prev_colors = colors + # Fit to this device's LED count (stream may be shared) + if device_info and device_info.led_count > 0: + colors = self._fit_to_device(colors, device_info.led_count) + # Apply device software brightness send_colors = self._apply_brightness(colors, device_info)