93 lines
6.0 KiB
Markdown
93 lines
6.0 KiB
Markdown
# SAFETY-128 - a reading that does not answer the last command is not current
|
|
|
|
**Status: FIXED on release/1.0 (after 0.20.0).** Code: `app/lateness.py`,
|
|
`control.compute(hold=, hold_w=)`, `peakguard.cap_floor()`,
|
|
`Controller._readings_late()`, `Controller.read_inputs()` (feeds the fits).
|
|
Tests: `test_safety128.py` (`tools/safety128_rig.py`, TEST-23's plant).
|
|
|
|
**Cause** (SAFETY-127 report). Home Assistant can deliver readings late but
|
|
still changing. Every gate judges arrival (SAFETY-01) or a value that stops
|
|
changing (SAFETY-18, SAFETY-37), so a late reading passes them all. The loop
|
|
then corrects, each cycle, an error its last command has already fixed: a
|
|
loop with a dead time far longer than its cycle, which swings and grows. The
|
|
peak guard projects the quarter from the same late figures and pushes to the
|
|
inverter limit in its last seconds (OPT-34 rig F-2).
|
|
|
|
**Rule.**
|
|
1. *Find late readings* (`Answer.watch()`, every 2 s, from the 1 s reads).
|
|
- **Batteries** (`Delay`): fit one `d` so that each battery's reading minus
|
|
its own request at `t - d` (averaged over 2 s for the battery's lag and
|
|
the read) is flattest. The house does not move that reading, so a
|
|
repeating load cannot line up with it (review round 1, B1). Needs 5 new
|
|
readings in 60 s and the request and the reading each to move 300 W.
|
|
Late from 9.5 s, after 2 late fits in a row. A late fit must explain 75 %
|
|
and beat every fit up to 6.5 s by 2x; the shortest delay that fits about
|
|
as well (within 2x, or within 2 500 W^2) is taken instead, since a swing's
|
|
period fits again. A slow battery (3-10 s lag) answering at once gives no
|
|
late fit; at a 15-20 s lag some fits read late (see "What it costs").
|
|
No late battery fit counts for 60 s
|
|
after a battery gave nothing under its ask: an emptied battery lined its
|
|
old movement up as 85 s late.
|
|
- **Meter** (`MeterFit`, round 1's fit): `meter(t) + request(t - d)` is the
|
|
house alone at the right `d`. Quick, but confounded by the house. Needs
|
|
16 new values in 60 s, so only a meter of about 3.5 s or faster: at 5 s
|
|
it gave false delays. Late over 8 s. At a slower meter (a 5 s P1) the
|
|
same fit runs over 120 s and calls only a delay over 16 s late, on 2 fits
|
|
in a row, and never ends a verdict (SAFETY-129). Alone it reads 35-90 s on healthy
|
|
runs, a few times in a row; only the slow-start and battery-fit check
|
|
below keeps those from a verdict. 10 s late is not found: it cannot be
|
|
told from a 10 s slow battery, and it does not swing at 5 s.
|
|
- A meter fit says late only with evidence from the batteries' side too:
|
|
a request more than 100 W from the battery reading took 3 s or more to
|
|
move a reading towards it (`SLOW_START_S`; on time they start within
|
|
0-1 s in the recorded house at 1 and 2 s ticks), and no battery fit in
|
|
the last 60 s said on time (under 9.5 s). An ask during which a battery
|
|
gave nothing under its ask is no slow evidence. A repeating load fools
|
|
the meter fit but not these. No meter verdict in the first 150 s.
|
|
- On time again on a battery fit under 6.5 s, or a meter fit within 8 s
|
|
unless a battery fit said late (hysteresis). With no fit for 120 s the
|
|
verdict is dropped.
|
|
2. *Hold.* While late, a request more than 100 W from the battery reading is
|
|
pending until that reading comes within 100 W of it, or half way. Meanwhile
|
|
the loop may not lead the reading by more than 100 W that way, and the peak
|
|
guard's floor is capped at the request that stands. The loop is not held
|
|
while a battery gives nothing under its ask or refuses (SAFETY-52/94).
|
|
3. *Late verdict.* Pending for `LATE_S` (23 s) with no reading moving 100 W
|
|
towards it: control holds, then after `stale_input_s` goes to 0 W
|
|
("readings late"), as for a missing input.
|
|
4. *Seen.* While late an amber row says "Home Assistant readings show requests
|
|
about N seconds late, so control holds the batteries." (NL too). N is the
|
|
batteries' fitted delay: Home Assistant's lag plus the battery's own
|
|
answer. While only the meter has shown it the row gives no figure. One
|
|
WARNING (`READINGS_LATE`) per episode and one line when it ends.
|
|
|
|
**With readings on time** no verdict was reached in any reviewer scenario
|
|
(owner-shaped house, ovens 20/40 to 60/60 s, clouds, a 300 W/s battery, 6-8 s
|
|
dead times, HA jitter 0-4 s, an EV following the meter, capped batteries, HA
|
|
restarts, meter pauses; 1, 2 and 5 s meters) nor in 2 days of the recorded
|
|
house at 1, 2 and 5 s ticks, so the commands are the same as without the gate.
|
|
The fits run all the time; the pull request has the counts.
|
|
|
|
**What it costs.**
|
|
- Found 36-68 s after a lag starts at 1-2 s meters; at a 5 s meter 30 s late
|
|
is found within 100 s after it starts (88 s measured) (the loop first moves 100 W after 60 s,
|
|
SAFETY-129) with the export above -200 W, and 10 s late is not found. Until
|
|
then control is as before. In a quiet house the "readings late" row stays
|
|
about 2 minutes longer after the lag ends (126 s against 32 s on base); no
|
|
harm measured, and it clears as early as on base when the load changes.
|
|
- A battery that answers slowly is read as late readings and held: a dead
|
|
time of 10 s or more (8 s reads 7-8; 10 s reads 10 at 1-2 s meters, 9 at
|
|
5 s), or a 15-20 s lag (review round 2). The GoodWe measured settles in 6 s
|
|
(`freshness.PLANT_SETTLE_S`); the row then blames Home Assistant wrongly.
|
|
- The row can stay up to 180 s after the readings are on time on a steady
|
|
site. While only the meter has shown the delay it gives no figure.
|
|
- A battery that cannot follow while the readings are late (at a limit, not
|
|
reading 0 W) is held, then set to 0 W after 38 s.
|
|
- The fits cost a few ms every 2 s (x86, measured after 3 idle days); the
|
|
history they read is bounded (60 s of readings, 150 s of requests).
|
|
|
|
**Left out.** The setpoint -> Home Assistant round trip: the fitted delay gives
|
|
the figure from readings the add-on already has. The hold's step-and-pull-back
|
|
at extreme lag and the arbitrage charge's sizing on late readings
|
|
(`charge_room_w()`) are follow-up cards.
|