SAFETY-87: peak guard uses every battery that can still give
At N>=2 a battery at or under its own peak reserve is held: it gives nothing for the peak (weight 0 while the site gives) and the guard's need is placed on the live, non-refusing batteries above theirs. The guard is floor-limited, and alarms, only when those cannot hold the limit at full power for ALARM_HOLD_S. The peak alarms no longer read "Not ready" or hold the Home page at 0 W, because control keeps running. N=1 is byte-identical. DECISIONS/SAFETY-87-guard-uses-able-batteries.md. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019DBUfvndgHwaV339Fvd2gr
This commit is contained in:
@@ -923,24 +923,25 @@ def state_of(c, level, shadow):
|
||||
|
||||
|
||||
def build(c, *, level: str, checks: list, now: datetime | None = None,
|
||||
lang: str = "en") -> dict:
|
||||
lang: str = "en", held: bool | None = None) -> dict:
|
||||
"""The structured half of `/status`, in `lang` (UX-13 P5). Pure reads of
|
||||
the controller."""
|
||||
_LANG[0] = uitext.lang_of(lang)
|
||||
try:
|
||||
return _build(c, level=level, checks=checks, now=now)
|
||||
return _build(c, level=level, checks=checks, now=now, held=held)
|
||||
finally:
|
||||
_LANG[0] = "en"
|
||||
|
||||
|
||||
def _build(c, *, level, checks, now):
|
||||
def _build(c, *, level, checks, now, held=None):
|
||||
now = now or datetime.now(timezone.utc)
|
||||
shadow = bool(c.shadow)
|
||||
kind = state_of(c, level, shadow)
|
||||
# A red banner means every inverter is at 0 W (the status cascade), so
|
||||
# nothing is planned until it clears. Shadow mode still plans: it is
|
||||
# what the add-on would do.
|
||||
held = level == "bad" and not shadow
|
||||
# what the add-on would do. `held` False: an alarm while control runs
|
||||
# (SAFETY-87, the peak alarms).
|
||||
held = level == "bad" and not shadow and held is not False
|
||||
running = (bool(c.auto) or shadow) and not held
|
||||
settled = all(at_zero(inv) for inv in c.inverters)
|
||||
ctl = next((r for r in checks if r.get("id") == "controller"), None)
|
||||
|
||||
Reference in New Issue
Block a user