MAINT-11: start or stop the maintenance cycle per battery
maint_start and maint_abort take an optional unit. With two or more batteries each Batteries card has Start cycle and Stop cycle buttons. One slot per site stays: a start while a battery cycles is refused and names it (no queue). A battery that is switched off, an unknown unit, and a stop on a battery that is not cycling are refused with a plain message. A request with no unit is the old call. The scheduler and the phase machine are unchanged. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Bdqr7PiaHcBnzPituu2yTC
This commit is contained in:
co-authored by
Claude
parent
79dd0770f9
commit
21d8a944bc
@@ -2777,6 +2777,43 @@ class Controller:
|
||||
out["sell"] = pm.sell
|
||||
return out
|
||||
|
||||
async def _maint_unit_action(self, what, unit, now) -> dict:
|
||||
"""MAINT-11: start or abort the maintenance cycle of ONE named battery.
|
||||
|
||||
Returns `{"error", "code", "unit"}` for a refusal and changes nothing.
|
||||
The site keeps its one maintenance slot: a start while any battery
|
||||
holds it is refused (no queue), see DECISIONS/MAINT-11. The phase
|
||||
machine is not touched beyond `force_start()` and `abort()`, the same
|
||||
two calls the bare button makes.
|
||||
"""
|
||||
inv = next((i for i in self.inverters if i.name == unit), None)
|
||||
if inv is None:
|
||||
return self._maint_refusal("unit")
|
||||
machine = self.maints[self.inverters.index(inv)]
|
||||
if what == "maint_start":
|
||||
holder = next((i for i, m in zip(self.inverters, self.maints)
|
||||
if m.phase in POWER_MOVING), None)
|
||||
if holder is not None:
|
||||
return self._maint_refusal("busy", holder.name)
|
||||
if self.modes_on and not self.pack_mode(inv).use:
|
||||
return self._maint_refusal("off", inv.name)
|
||||
for msg in machine.force_start(now):
|
||||
self.log_event(msg, hint=messages.hint(
|
||||
"maintenance", phase=machine.phase))
|
||||
return {"unit": inv.name, "phase": machine.phase}
|
||||
if machine.phase not in POWER_MOVING:
|
||||
return self._maint_refusal("idle", inv.name)
|
||||
for msg in machine.abort(now, "operator"):
|
||||
self.log_event(msg, hint=messages.hint("maintenance",
|
||||
phase=machine.phase))
|
||||
await self.command_site_zero()
|
||||
return {"unit": inv.name, "phase": machine.phase}
|
||||
|
||||
@staticmethod
|
||||
def _maint_refusal(code, unit="") -> dict:
|
||||
return {"error": messages.maint_refused(code, unit), "code": code,
|
||||
"unit": unit}
|
||||
|
||||
def mode_values(self) -> dict:
|
||||
"""OPT-11 P2: each battery's mode and switch, for their HA state
|
||||
topics. Read from the store, so they are right after a restart. Empty
|
||||
@@ -7513,6 +7550,10 @@ class Controller:
|
||||
# would read as the stop button not working.
|
||||
await self.command_site_zero()
|
||||
return {"auto": self.auto}
|
||||
if what in ("maint_start", "maint_abort") and unit is not None:
|
||||
# MAINT-11: the operator named the battery. A request with no unit
|
||||
# falls through to the branches below, unchanged.
|
||||
return await self._maint_unit_action(what, unit, now)
|
||||
if what == "maint_start":
|
||||
# ⚠️ WHICH PACK, BECAUSE THERE ARE NOW SEVERAL AND THE BUTTON HAS
|
||||
# ONE LABEL. `_maint_button()` answers it: the pack that holds the
|
||||
|
||||
Reference in New Issue
Block a user