fix: clamp() collapsed to minimum when min_brightness > max_brightness (#1507)

* fix: clamp() collapsed to minimum when min_brightness > max_brightness

A user can intentionally set min_brightness > max_brightness (or the
equivalent for color temperature) for an inverted timescale -- e.g. a
porch light that should be brighter at night than during the day.
clamp()'s max(minimum, min(value, maximum)) assumed minimum <= maximum;
when inverted, min(value, maximum) is always <= maximum < minimum, so
max(minimum, ...) always returns minimum. linear and tanh brightness
modes -- both of which end in a clamp(brightness, min_brightness,
max_brightness) call -- got stuck returning one fixed value regardless
of the time of day.

Fixes #1421

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* test: accept current Home Assistant brightness validation errors

Keep asserting the maximum brightness limit without depending on the validation library's dictionary-path wording.

---------

Co-authored-by: Oscar Pacheco <proscar@MacBook-Pro-de-Oscar.local>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Bas Nijholt <bas@nijho.lt>
Co-authored-by: Bas Nijholt <basnijholt@gmail.com>
This commit is contained in:
proscar87 2026-09-06 01:10:21 -06:00 • committed by GitHub
commit 67d4a2f657
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 101 additions and 3 deletions

View file

@ -528,5 +528,13 @@ def lerp(x: float, x1: float, x2: float, y1: float, y2: float) -> float:
def clamp(value: float, minimum: float, maximum: float) -> float:
"""Clamp value between minimum and maximum."""
return max(minimum, min(value, maximum))
"""Clamp value between minimum and maximum.
`minimum` is not assumed to be <= `maximum`: a user may intentionally
configure `min_brightness > max_brightness` (or the equivalent for color
temperature) for an inverted timescale (#1421). Sort the bounds first so
that case clamps against the real lower/upper bound instead of
collapsing to `minimum` for every input.
"""
low, high = (minimum, maximum) if minimum <= maximum else (maximum, minimum)
return max(low, min(value, high))