After a fresh today reading in the night (02:00 on the rig) went stale (05:00), Hold.stand_in(as_today=True) served the 17:05 "tomorrow" figure again until 06:00: the plan went back to 95 %, the latch took it, and Leftover solar charged back up. read_sum() now skips that stand-in once every today sensor has given a fresh reading for the day (Hold.replaced()); the stale newer reading follows the OPT-27 rules. Co-Authored-By: Claude <noreply@anthropic.com>
4.6 KiB
OPT-34 - the night charge keeps its level when the kept forecast ends
Status: done on release/1.0, not released. Tests: test_opt34.py.
The defect (OPT-27 rig test, F-1). The kept evening figure ended at midnight + 3 h. With the sensors silent from 17:05 the Leftover solar battery's level went with it in the middle of the charge: A ended at 49.8 % against 79.9 % with a fresh figure. Whether Forecast.Solar refreshes after midnight on a live site is not known, so the add-on does not depend on it.
The rule.
- A charge under way keeps its level (
Controller._latch_charge()). While there is a forecast (fresh or kept), each battery that charges from the grid in the cheap run takes its planned level into a latch (store keynight_charge_latch). With no forecast,plan_targets()gives the latched level, and the wide no-forecast gap does not refuse the next slice of the run (weather_held(), as TARIFF-24 does for the run under way). While a forecast is there the latch follows the plan, up or down as a fresh figure moves it. It lasts through every cheap run on and one price slot after the last, and it ends at once when its end time passes, whatever the run state (it is also ignored at a restart if it has ended). A battery that is switched off or changed to another mode leaves it. Night bound (manager's call, 2026-10-31): a run carries the latch on only if it starts by the bell start (06:00 local) after the latch began; that run finishes, plus one slot. Chosen over a fixed 12 h because the night tariff (22:00-07:00) needs the 06:00-07:00 slice and 12 h from a late start would reach into the day. With dynamic prices a chain of cheap slots cannot carry a night's level into the next day. - The evening's tomorrow figure is today's until the bell starts, 06:00 local
(
BELL_FROM_H,solarfc._bell_start()), not until midnight + 3 h. Nothing has been produced yet, so it is still the whole day. - Up to 15 h old for that case only (
KEPT_MORNING_MAX_AGE_S): a 17:05 reading is 12 h 55 min old at 06:00. It must have been at most 12 h old at midnight, so a 09:05 reading, unusable since 21:05, does not come back for five minutes after midnight. Same-day figures and the daytime rule keep 12 h and 3 h. - A fresh figure replaces the kept one at once, as before.
Rig F-1 fix: once every today sensor has given a fresh reading after
midnight, the evening figure is no stand-in for that day any more
(
Hold.replaced()). When that reading goes stale (3 h), it is kept or not as any today reading (OPT-27), so it is "no forecast" at night and the latch keeps the level it set; the older 17:05 figure never comes back. Rig: A stopped at 69.5 % after a brighter 02:00 figure, then charged back to 94.4 % from 05:15 when the 17:05 figure returned. Test:test_opt34.pyF-1.
Step 1 alone is enough for the owner's shape, steps 2-3 are still needed. With the window put back to midnight + 3 h the owner's night still ends as a fresh figure ends it (A 86.9 %, B 95.0 %), because the charge had started at 22:00. But a charge that has not started by 03:00 (the price dips at 04:00, or the headroom is taken) has no level to latch: A ends at 38 % against 78 %. The plan, the screens and a restart also need the figure itself.
Screens. "Solar forecast read {at}, kept for tonight." is still true until
06:00 and unchanged. After the figure ends, with a charge still going on: "No
solar forecast now. The charge under way goes on to its planned level." /
"Nu geen zonneprognose. De lopende lading gaat door tot het geplande niveau."
(home_words.solar.latched, only while a cheap run is on and a latched battery is below its level).
Not used. A figure over 15 h old; a morning figure at night (12 h); a figure for another day; a bad value or unit; and no latch for a charge that has not started, for a battery that is not charging, or after the cheap runs have ended (plus one slot).
Not changed. Charge sizing, the peak guard, Cheap hours, modes off, arbitrage. A fresh figure that LOWERS the level during a charge still lowers it, as before.
Mutants (all red in test_opt34.py): no latch; window back to midnight + 3 h;
15 h without a limit; no "usable at midnight" rule; the latch without the narrow
gap, without its save, or not kept through the next run; the window 6 h after
midnight instead of 06:00 local (DST); 15 h cut to 12 h; the new screen line off or shown without a cheap run; no expiry check; no pruning of a changed mode; no night bound; a left-the-plan battery keeping its level; no replaced() check (F-1); replaced() with one of several today sensors (any, not all).