MAINT-14: accurate no-level wording per phase; name the limit that ended the charge
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
f39e52efd3
commit
ef35f4b925
@@ -60,7 +60,8 @@ allows discharge.
|
|||||||
|
|
||||||
- **HOLD with no SoC** still holds 0 W and, as before, does not end while the
|
- **HOLD with no SoC** still holds 0 W and, as before, does not end while the
|
||||||
reading is missing: its time check sits behind the same early return. A HOLD
|
reading is missing: its time check sits behind the same early return. A HOLD
|
||||||
needs no level to end, so this is a candidate follow-up, not part of this fix.
|
needs no level to end, so this is a candidate follow-up, not part of this fix. It is card MAINT-15. The "no battery level" line in
|
||||||
|
HOLD says only that the hold waits for the level.
|
||||||
- It does not tell the operator why the reading is missing (sensor, register,
|
- It does not tell the operator why the reading is missing (sensor, register,
|
||||||
link). It does not reuse the stale-input gate; it is the cycle's own rule.
|
link). It does not reuse the stale-input gate; it is the cycle's own rule.
|
||||||
- The charge itself is still driven by the control loop, which has its own
|
- The charge itself is still driven by the control loop, which has its own
|
||||||
|
|||||||
@@ -563,8 +563,11 @@ class Maintenance:
|
|||||||
if (not self._nosoc_said and (now - self._nosoc_since).total_seconds()
|
if (not self._nosoc_said and (now - self._nosoc_since).total_seconds()
|
||||||
>= NOSOC_NOTE_MIN * 60):
|
>= NOSOC_NOTE_MIN * 60):
|
||||||
self._nosoc_said = True
|
self._nosoc_said = True
|
||||||
|
tail = ("The hold waits for the level to come back."
|
||||||
|
if phase == HOLD else
|
||||||
|
f"The time limit of the {phase} still applies.")
|
||||||
msg = (f"maintenance: no battery level for {NOSOC_NOTE_MIN} min. "
|
msg = (f"maintenance: no battery level for {NOSOC_NOTE_MIN} min. "
|
||||||
f"The time limit of the {phase} still applies.")
|
f"{tail}")
|
||||||
_LOG.warning("%s", msg)
|
_LOG.warning("%s", msg)
|
||||||
events.append(msg)
|
events.append(msg)
|
||||||
if phase == HOLD:
|
if phase == HOLD:
|
||||||
@@ -587,9 +590,12 @@ class Maintenance:
|
|||||||
f"charge counts as done -> holding "
|
f"charge counts as done -> holding "
|
||||||
f"{self.cfg.hold_min} min to balance")
|
f"{self.cfg.hold_min} min to balance")
|
||||||
return MaintResult(HOLD, True, 0.0, False, events)
|
return MaintResult(HOLD, True, 0.0, False, events)
|
||||||
|
if elapsed > CHARGE_WALL_TIMEOUT_MIN:
|
||||||
|
lim = f"the {CHARGE_WALL_TIMEOUT_MIN // 1440}-day limit"
|
||||||
|
else:
|
||||||
|
lim = f"{trk['open_min'] / 60:.0f} h of charging time"
|
||||||
return self._fail(now, "charge",
|
return self._fail(now, "charge",
|
||||||
f"charge stuck, battery level unknown, after "
|
f"charge stuck, battery level unknown, after {lim}")
|
||||||
f"{trk['open_min'] / 60:.0f} h of charging time")
|
|
||||||
return MaintResult(CHARGE, False, None, True, events)
|
return MaintResult(CHARGE, False, None, True, events)
|
||||||
|
|
||||||
def abort(self, now: datetime, why: str) -> list:
|
def abort(self, now: datetime, why: str) -> list:
|
||||||
|
|||||||
@@ -240,6 +240,29 @@ m = in_charge()
|
|||||||
res, _, out, ev = run(m, T0, 5, None)
|
res, _, out, ev = run(m, T0, 5, None)
|
||||||
check("a 5 min gap says nothing", ev == [])
|
check("a 5 min gap says nothing", ev == [])
|
||||||
|
|
||||||
|
print("5b. the words per phase")
|
||||||
|
m = in_charge()
|
||||||
|
m.tick(T0 + MIN, 100.0)
|
||||||
|
_, _, _, ev = run(m, T0 + 2 * MIN, 30, None)
|
||||||
|
note = [e for e in ev if "no battery level for" in e]
|
||||||
|
check("HOLD: the line exists and claims no time limit",
|
||||||
|
len(note) == 1 and "time limit" not in note[0] and "waits" in note[0])
|
||||||
|
m = in_charge()
|
||||||
|
_, _, _, ev = run(m, T0, 30, None)
|
||||||
|
check("charge keeps its wording", any("time limit of the charge" in e for e in ev))
|
||||||
|
m = in_charge()
|
||||||
|
run(m, T0, 10, 70.0)
|
||||||
|
_, _, out, ev = run(m, T0 + 10 * MIN, CHARGE_WALL_TIMEOUT_MIN + 30, None,
|
||||||
|
gate=False, step=5)
|
||||||
|
fail = [e for e in ev if "ABORT" in e]
|
||||||
|
check("7-day backstop: the reason names the 7-day limit, not '0 h'",
|
||||||
|
len(fail) == 1 and "7-day limit" in fail[0] and "0 h" not in fail[0])
|
||||||
|
m = in_charge()
|
||||||
|
_, _, out, ev = run(m, T0, CHARGE_TIMEOUT_MIN + 10, None)
|
||||||
|
fail = [e for e in ev if "ABORT" in e]
|
||||||
|
check("charge-time limit: the reason gives the hours of charging time",
|
||||||
|
len(fail) == 1 and "36 h of charging time" in fail[0])
|
||||||
|
|
||||||
print("6. restart while the SoC is missing")
|
print("6. restart while the SoC is missing")
|
||||||
with tempfile.TemporaryDirectory() as d:
|
with tempfile.TemporaryDirectory() as d:
|
||||||
path = os.path.join(d, "state.json")
|
path = os.path.join(d, "state.json")
|
||||||
|
|||||||
Reference in New Issue
Block a user