MAINT-13 round 2: gate open when nothing holds the charge back; safety93 scenario restored
- gate_open is true with no price gate set up, in a cheap window, or while the pack is taking charge; the stall rule and timeout now work on a no-tariff site. - reset the save timer on a phase change; exact 5 min gap-cap test. - test_safety93: original timeout scenario kept (B finished) plus a case where a due B takes the slot after A's failure. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Bdqr7PiaHcBnzPituu2yTC
This commit is contained in:
co-authored by
Claude Sonnet 5.5
parent
28eff568b5
commit
6f05b2e4be
@@ -231,10 +231,12 @@ check("...or in a complete charge when the pack is near full",
|
||||
out and out[0].phase == HOLD)
|
||||
m = in_charge()
|
||||
res, t, out = run(m, T0, 10, 70.0)
|
||||
before = m._trk["open_min"]
|
||||
res = m.tick(t + 2 * timedelta(hours=1), 70.0)
|
||||
trk = m._trk
|
||||
check("a gap in the ticks (add-on down) counts for at most 5 minutes",
|
||||
trk["open_min"] < 20, )
|
||||
check("a gap in the ticks (add-on down) counts for exactly 5 minutes (the cap)",
|
||||
abs(m._trk["open_min"] - before - 5.0) < 1e-9)
|
||||
m.tick(t + 2 * timedelta(hours=1) + 2 * MIN, 70.0)
|
||||
check("...and a 2 minute step counts 2", abs(m._trk["open_min"] - before - 7.0) < 1e-9)
|
||||
|
||||
print("6. restarts and old state files")
|
||||
with tempfile.TemporaryDirectory() as d:
|
||||
@@ -437,6 +439,45 @@ check("...and its failure is on B's keys",
|
||||
c.maints[1].store.get_time("last_failed") is not None
|
||||
and c.maints[0].store.get_time("last_failed") is None)
|
||||
|
||||
# a site with no price entities and no fixed tariff: nothing holds the charge back
|
||||
NOTARIFF = {k: v for k, v in OPTS1.items()
|
||||
if k not in ("price_now_entity", "price_avg_entity")}
|
||||
c, h = controller(NOTARIFF, False)
|
||||
m = put_in_charge(c, 0, 5, 100.0)
|
||||
one_cycle(c)
|
||||
got = m._trk["open_min"] - 100.0
|
||||
check("N=1, no tariff and no price entities: the gate counts as open, so the "
|
||||
f"3 minutes count (+{got:.1f}) although `cheap` is false",
|
||||
not c.cheap and 2.5 < got < 3.5)
|
||||
c, h = controller(NOTARIFF, False)
|
||||
m = put_in_charge(c, 0, 40, CHARGE_TIMEOUT_MIN + 1)
|
||||
one_cycle(c)
|
||||
check("...and a pack past its charging time there fails at once (not 7 days)",
|
||||
m.phase == IDLE and len(notes(h)) == 1)
|
||||
c, h = controller(OPTS1, False)
|
||||
c.inverters[0].batt = -800.0
|
||||
check("price gate closed but the pack is taking 800 W (sun): gate open",
|
||||
c._charge_gate_open(c.inverters[0]) is True)
|
||||
c.inverters[0].batt = -10.0
|
||||
check("...closed and about idle: gate closed",
|
||||
c._charge_gate_open(c.inverters[0]) is False)
|
||||
c.inverters[0].batt = None
|
||||
check("...no battery reading: gate closed", c._charge_gate_open(c.inverters[0]) is False)
|
||||
c, h = controller(OPTS1, True)
|
||||
c.cheap = True
|
||||
check("price gate open: gate open", c._charge_gate_open(c.inverters[0]) is True)
|
||||
c, h = controller(dict(NOTARIFF, static_profile="x"), False)
|
||||
check("a fixed tariff set up counts as a gate (closed outside its cheap hours)",
|
||||
c._charge_gate_open(c.inverters[0]) is False)
|
||||
|
||||
# the save timer is reset on a phase change
|
||||
mm = in_charge()
|
||||
mm.tick(T0 + MIN, 70.0)
|
||||
saved_before = mm._trk_saved
|
||||
mm.abort(T0 + 2 * MIN, "operator")
|
||||
check("leaving CHARGE resets the save timer along with the record",
|
||||
saved_before is not None and mm._trk is None and mm._trk_saved is None)
|
||||
|
||||
print("9. the words")
|
||||
en, nl = messages.maint_failed("charge", 7), messages.maint_failed("drain", 7)
|
||||
for n_ in (en, nl):
|
||||
|
||||
Reference in New Issue
Block a user