Add min brightness threshold to LED targets

New per-target property: when effective output brightness
(max pixel value × device/source brightness) falls below
the threshold, LEDs turn off completely. Useful for cutting
dim flicker in audio-reactive and ambient setups.

Threshold slider (0–254) in target editor, badge on card,
hot-swap to running processors, persisted in storage.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-26 15:03:53 +03:00
parent c2deef214e
commit a164abe774
11 changed files with 75 additions and 1 deletions

View File

@@ -317,6 +317,7 @@ class ProcessorManager:
keepalive_interval: float = 1.0,
state_check_interval: int = DEFAULT_STATE_CHECK_INTERVAL,
brightness_value_source_id: str = "",
min_brightness_threshold: int = 0,
):
"""Register a WLED target processor."""
if target_id in self._processors:
@@ -332,6 +333,7 @@ class ProcessorManager:
keepalive_interval=keepalive_interval,
state_check_interval=state_check_interval,
brightness_value_source_id=brightness_value_source_id,
min_brightness_threshold=min_brightness_threshold,
ctx=self._build_context(),
)
self._processors[target_id] = proc

View File

@@ -36,6 +36,7 @@ class WledTargetProcessor(TargetProcessor):
keepalive_interval: float = 1.0,
state_check_interval: int = 30,
brightness_value_source_id: str = "",
min_brightness_threshold: int = 0,
ctx: TargetContext = None,
):
super().__init__(target_id, ctx)
@@ -45,6 +46,7 @@ class WledTargetProcessor(TargetProcessor):
self._state_check_interval = state_check_interval
self._css_id = color_strip_source_id
self._brightness_vs_id = brightness_value_source_id
self._min_brightness_threshold = min_brightness_threshold
# Runtime state (populated on start)
self._led_client: Optional[LEDClient] = None
@@ -210,6 +212,8 @@ class WledTargetProcessor(TargetProcessor):
self._keepalive_interval = settings["keepalive_interval"]
if "state_check_interval" in settings:
self._state_check_interval = settings["state_check_interval"]
if "min_brightness_threshold" in settings:
self._min_brightness_threshold = settings["min_brightness_threshold"]
logger.info(f"Updated settings for target {self._target_id}")
def update_device(self, device_id: str) -> None:
@@ -581,6 +585,15 @@ class WledTargetProcessor(TargetProcessor):
cur_brightness = _effective_brightness(device_info)
# Min brightness threshold: combine brightness source
# with max pixel value to get effective output brightness.
# If below cutoff → snap to 0 (LEDs off).
_thresh = self._min_brightness_threshold
if _thresh > 0 and cur_brightness > 0:
max_pixel = int(np.max(frame))
if max_pixel * cur_brightness // 255 < _thresh:
cur_brightness = 0
# Zero-brightness suppression: if output is black and
# the last sent frame was also black, skip sending.
if cur_brightness <= 1 and _prev_brightness <= 1 and has_any_frame: