Files
led-controller/src/util/brightness_combine.py
2026-05-10 16:55:07 +12:00

87 lines
2.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
Combine global, group, device (and optional zone) brightness into one 0255 wire value.
Formula: ``(f1/255) * (f2/255) * ... * (fn/255) * 255`` with integer rounding — one ``b`` sent to the driver.
"""
from __future__ import annotations
from models.device import normalize_mac
def clamp255(value) -> int:
try:
v = int(value)
except (TypeError, ValueError):
return 255
return max(0, min(255, v))
def multiply_brightness_factors(factors: list) -> int:
"""Product ``(f1/255)*(f2/255)*...*255``; each factor clamped to 0..255."""
if not factors:
return 255
fs = [clamp255(f) for f in factors]
if len(fs) == 1:
return fs[0]
num = 1
for f in fs:
num *= f
den = 255 ** (len(fs) - 1)
return max(0, min(255, (num + den // 2) // den))
def _mac_in_device_list(raw_list, target_mac: str) -> bool:
tm = normalize_mac(target_mac)
if not tm:
return False
if not isinstance(raw_list, list):
return False
for raw in raw_list:
if normalize_mac(str(raw)) == tm:
return True
return False
def effective_brightness_for_mac(
settings_obj,
groups_model,
devices_model,
mac: str,
*,
zone_brightness=None,
) -> int:
"""
Factors (each 0..255): Pi **global_brightness**, each group's **output_brightness**
(neutral 255 if the device is in no group), device **output_brightness** (default 255),
optional **zone_brightness** from the zone slider when applying live.
"""
m = normalize_mac(mac)
if not m:
return 255
g_global = clamp255(settings_obj.get("global_brightness", 255))
dev_doc = devices_model.read(m)
if dev_doc is not None and dev_doc.get("output_brightness") is not None:
d_b = clamp255(dev_doc.get("output_brightness"))
else:
d_b = 255
group_factors = []
for _gid, gdoc in groups_model.items():
if not isinstance(gdoc, dict):
continue
if not _mac_in_device_list(gdoc.get("devices"), m):
continue
group_factors.append(clamp255(gdoc.get("output_brightness", 255)))
if not group_factors:
group_factors = [255]
factors = [g_global, *group_factors, d_b]
if zone_brightness is not None:
factors.append(clamp255(zone_brightness))
return multiply_brightness_factors(factors)