diff --git a/goodwe_controller/DOCS.md b/goodwe_controller/DOCS.md index 6523d3f..7c46df8 100644 --- a/goodwe_controller/DOCS.md +++ b/goodwe_controller/DOCS.md @@ -1672,7 +1672,8 @@ balances, so it need not reach `maintenance_soc_target`. The charge counts as done when the battery is within 3 points of the target and has taken no more charge for 60 minutes of charging time, or when the charging time (36 hours) runs out within 3 points of the target. Only the minutes the cheap-hours gate let the -battery charge count. Then the usual hold follows. +battery charge count, and the charge ends after 7 days at the +latest. Then the usual hold follows. **When a cycle fails.** If the battery does not empty in 12 hours, or does not get within 3 points of the target in 36 hours of charging time, the cycle diff --git a/goodwe_controller/test_maint13.py b/goodwe_controller/test_maint13.py index c2bf93b..07881ed 100644 --- a/goodwe_controller/test_maint13.py +++ b/goodwe_controller/test_maint13.py @@ -240,6 +240,10 @@ 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) +_t = t + 2 * timedelta(hours=1) + 2 * MIN +m.tick(_t - 10 * MIN, 70.0) # the clock steps back 10 min +check("...and a step back in time counts nothing (not minus)", + abs(m._trk["open_min"] - before - 7.0) < 1e-9) print("6. restarts and old state files") with tempfile.TemporaryDirectory() as d: @@ -286,6 +290,19 @@ with tempfile.TemporaryDirectory() as d: res, _, out = run(mo, T0 + MIN, 120, 70.0) check("...so it fails when the 36 h are up, as before", out and out[0].failed == "charge") + # A record left by another charge (an add-on rolled back and forward + # again does not clear it) must not be read as this charge's. + stale = {"phase": "charge", + "phase_started": (T0 - timedelta(hours=2)).isoformat(), + "charge_track": {"since": (T0 - timedelta(days=30)).isoformat(), + "open_min": 2000.0, "flat_min": 59.0, + "best": 99.0, "at": None}} + ms = Maintenance(CFG, Mem(stale)) + r = ms.tick(T0, 98.0) + check("a charge record from another charge is ignored: this charge counts " + "its own 2 h and its own best", + r.phase == CHARGE and 119 < ms._trk["open_min"] < 121 + and ms._trk["flat_min"] == 0.0 and ms._trk["best"] == 98.0) mi = Maintenance(CFG, Store(os.path.join(d, "none.json"))) check("no state file: due, no back-off", mi.due(T0) and mi.backoff_until(T0) is None)