SAFETY-118: a missing peak forecast reading keeps the unit-fault state
A missing reading (unavailable, unknown, failed read, non-numeric) no longer clears the fault: no false 'used again' INFO, no repeated WARNING, the status row stays. Adds pv.has_reading(). DECISIONS wording fixed; tests added. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude
parent
f0b4e68e49
commit
7d52dc1c0f
@@ -178,15 +178,22 @@ check("no unit is a different cause and warns", len(warns()) == 3
|
||||
and "has no unit" in warns()[2])
|
||||
reads(c)
|
||||
check("...and only once", len(warns()) == 3)
|
||||
USED = (logging.INFO, "The 15-minute demand forecast is used again.")
|
||||
|
||||
|
||||
def used():
|
||||
return [r for r in rec.rows if r == USED]
|
||||
|
||||
|
||||
h.fc = st("unavailable")
|
||||
reads(c)
|
||||
check("unavailable is no unit fault and adds no warning", len(warns()) == 3)
|
||||
check("unavailable adds no warning and no 'used again'",
|
||||
len(warns()) == 3 and not used())
|
||||
h.fc = st(820, "W")
|
||||
reads(c)
|
||||
check("a good unit is read again and logs INFO, not a warning",
|
||||
c.peak_fc == 820.0 and len(warns()) == 3
|
||||
and rec.rows[-1] == (logging.INFO,
|
||||
"The 15-minute demand forecast is used again."))
|
||||
check("a good unit is read again: one INFO, no new warning",
|
||||
c.peak_fc == 820.0 and len(warns()) == 3 and len(used()) == 1
|
||||
and rec.rows[-1] == USED)
|
||||
n = len(warns())
|
||||
for s in (st(820, "W"), st(0.8, "kW")):
|
||||
h.fc = s
|
||||
@@ -291,7 +298,72 @@ print(" NL bad unit:", messages.peak_forecast_unit("kWh", "nl"))
|
||||
check("the strings differ by cause and by language",
|
||||
len({messages.peak_forecast_unit(u, l) for u in ("", "kWh")
|
||||
for l in ("en", "nl")}) == 4)
|
||||
check("pv.unit_fault: None for a good unit and for a missing reading",
|
||||
print("6. a missing reading leaves the unit fault as it was (F1)")
|
||||
|
||||
|
||||
lg.addHandler(rec)
|
||||
|
||||
|
||||
def prow(c):
|
||||
return [r for r in c.checks() if r.get("id") == "peak_forecast"]
|
||||
|
||||
|
||||
def flap(first, gap, last):
|
||||
"""first, gap, first again (or last): the log rows and the status row
|
||||
after each cycle."""
|
||||
rec.rows.clear()
|
||||
c, h = make(first)
|
||||
out = []
|
||||
for s in (first, gap, last):
|
||||
h.fc = s
|
||||
reads(c)
|
||||
out.append((len(warns()), len(used()), len(prow(c)), c.peak_fc))
|
||||
return out
|
||||
|
||||
|
||||
for label, first, gap in [
|
||||
("kWh -> unavailable -> kWh", st(820, "kWh"), st("unavailable", "kWh")),
|
||||
("kWh -> unknown -> kWh", st(820, "kWh"), st("unknown", "kWh")),
|
||||
("kWh -> failed read -> kWh", st(820, "kWh"), None),
|
||||
("kWh -> non-numeric -> kWh", st(820, "kWh"), st("sunny", "kWh")),
|
||||
("no unit -> failed read -> no unit", st(820), None),
|
||||
("no unit -> unavailable -> no unit", st(820), st("unavailable"))]:
|
||||
r = flap(first, gap, first)
|
||||
check(f"{label}: one WARNING, no 'used again', row on all 3 ({r})",
|
||||
[x[0] for x in r] == [1, 1, 1] and [x[1] for x in r] == [0, 0, 0]
|
||||
and [x[2] for x in r] == [1, 1, 1]
|
||||
and [x[3] for x in r] == [None, None, None])
|
||||
r = flap(st(820, "kWh"), st("unavailable", "kWh"), st(820, "W"))
|
||||
check(f"kWh -> unavailable -> W: the fault clears only on the W reading ({r})",
|
||||
[x[1] for x in r] == [0, 0, 1] and [x[2] for x in r] == [1, 1, 0]
|
||||
and [x[0] for x in r] == [1, 1, 1] and r[2][3] == 820.0)
|
||||
rec.rows.clear()
|
||||
c, h = make(st(820, "W"))
|
||||
for s in (st(820, "W"), st("unavailable", "W"), None, st("sunny", "W")):
|
||||
h.fc = s
|
||||
reads(c)
|
||||
check(f"good unit, reading {s and s['state']!r}: no row, no log",
|
||||
not prow(c) and not warns() and not used())
|
||||
rec.rows.clear()
|
||||
c, h = make(st(820, "kWh"))
|
||||
reads(c)
|
||||
for s in (st("unavailable", "kWh"), None):
|
||||
h.fc = s
|
||||
reads(c)
|
||||
check("fault row stays while the reading is missing",
|
||||
len(prow(c)) == 1 and prow(c)[0]["text"]
|
||||
== messages.row_peak_forecast_unit("kWh"))
|
||||
c, h = make(st(820, "W"))
|
||||
h.fc = st("unavailable", "W")
|
||||
reads(c)
|
||||
check("good-unit sensor only unavailable: the fault row stays away",
|
||||
not prow(c))
|
||||
lg.removeHandler(rec)
|
||||
check("has_reading: numbers only",
|
||||
pv.has_reading(st(0, "kWh")) and pv.has_reading(st("1.5"))
|
||||
and not pv.has_reading(None) and not pv.has_reading(st("unavailable"))
|
||||
and not pv.has_reading(st("unknown")) and not pv.has_reading(st("x")))
|
||||
check("pv.unit_fault: None for a good unit and for a missing reading (has_reading tells them apart)",
|
||||
pv.unit_fault(st(1, "kW")) is None and pv.unit_fault(None) is None
|
||||
and pv.unit_fault(st("unavailable")) is None
|
||||
and pv.unit_fault(st(1)) == "" and pv.unit_fault(st(1, "kWh")) == "kWh")
|
||||
|
||||
Reference in New Issue
Block a user