393 files

This commit is contained in:
Home Assistant Version Control
2026-09-27 17:16:54 +00:00
parent b05b7a897e
commit 39d97ac2db
404 changed files with 54006 additions and 11034 deletions
@@ -441,3 +441,37 @@ def resample_adaptive(
return segments, target_dt
def quiet_run_before(
points: list[tuple[float, float]], last_active: float, stop_threshold_w: float
) -> float:
"""Length of the sub-threshold run immediately preceding ``last_active``.
Recognises a terminal pump-out from the trace alone: if the final
above-threshold sample is preceded by a long quiet stretch, that sample is
the event the drying led up to, not the last moment of washing. Returns 0.0
when the sample before it is still active.
Shared on purpose. The banked-tail repair and ``CycleDetector._keep_tail_cap``
have to answer this question the same way, or a cycle gets one allowance live
and a different one when the repair re-judges it (register item 347).
"""
# The terminal event is a RUN of above-threshold samples, not one sample, so
# walk back to where that run starts before measuring the quiet in front of
# it. Measuring from `last_active` itself finds only the run's own width.
idx = [i for i, (o, _p) in enumerate(points) if o <= last_active]
if not idx:
return 0.0
i = idx[-1]
while i > 0 and points[i - 1][1] > stop_threshold_w:
i -= 1
run_start = points[i][0]
# Now the last above-threshold sample before that run, if any.
prev_active: float | None = None
for offset, power in points:
if offset >= run_start:
break
if power > stop_threshold_w:
prev_active = offset
if prev_active is None:
return 0.0
return max(0.0, run_start - prev_active)