Live 0.20.0: A (Leftover solar, 60 %) charged to 95 % while B (Cheap hours,
94 %) already covered the expensive hours. dayplan.plan() now takes off the
shortfall what Cheap hours batteries will hold when the hours start (the
ceiling or what their cheap run reaches under the peak aim) and what Solar
first batteries will still hold after the night's use. Home reads a give
block after the planned charge, plan_cover() is the plan's own figure, and
the Why line says other batteries cover.
Co-Authored-By: Claude <noreply@anthropic.com>
With A on Leftover solar and B on Cheap hours (the dynamic scenario, and the
owner's planned setup), the line said "The batteries cannot hold it all. The
grid covers N kWh", while B holds a full charge for the same hours. It now
says "The expensive hours need more than Leftover solar can hold. The rest,
N kWh, comes from another battery or the grid." (NL likewise). DOCS,
DECISIONS and the dayplan/homeview docstrings say the same. Text only.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Bdqr7PiaHcBnzPituu2yTC
OPT-23: a state-only forecast is read from now for every span
(Forecast.between since=), so the plan's per-hour sun adds up to the day's
figure, today and tomorrow. Hourly splits are unchanged. The Forecast tab
reads spans the same way.
OPT-28: a Leftover solar battery buys, from the floor, the sum over the
expensive hours of max(0, house - trust x sun), / EFF. Several Leftover
solar batteries hold it together by capacity, the ceiling passes the rest
on, and what none can hold is said (Plan.uncovered_kwh). Home's grid block,
the Batteries line and the mode help (EN + NL) say the level, what it
covers, and that Leftover solar buys only what the sun will not give.
Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Bdqr7PiaHcBnzPituu2yTC
dayplan._hour_slices() added an hour to the local wall clock and read it
back. Without tzdata (tariff._EUTimezone) 02:00 on the spring change reads
as 00:00 UTC again, so the loop never advanced and the list grew until the
process died. Each step now adds the time left in the local hour to the UTC
instant. Ordinary days give the old slices; the spring day gives 23 slices
and the autumn day 25. No option, no text change.
test_safety123.py: every quarter of 27-29 March and 30 Oct-1 Nov 2027 (and
the US change days) for the slices, dayplan.plan() and
Controller._mode_roles(), each call under a hard time limit.
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Bdqr7PiaHcBnzPituu2yTC
- Cheap hours only fills to the ceiling with or without a forecast, as the
design (section 1) says. Skipping the sun's share cost 0.31 EUR on real
2026 prices (29.72 against P3's 29.41) and saved nothing on the P3 set.
- A forecast reading from before local midnight is stale: until the
integration refreshes, "left today" is still yesterday's 0 and
"tomorrow" is really today.
- Forecast entity ids must be sensor.[a-z0-9_]+ (they go into the
/api/states/<id> path).
- House profile: a stored day that is not a date, or is after today, is
dropped instead of kept forever.
- Text: the forecast line says "for the rest of today"; the learning line
no longer promises "tomorrow" (a plan needs one full day).
- Tests for four surviving review mutants (hour sample floor, the dear run
after the cheap run, share by room, daytime use) and the fixes above.
- Replay tool: `--fc zero` (a forecast of no sun).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A Home Assistant solar forecast (Forecast.Solar, Solcast or Open-Meteo
shapes) and the add-on's own hourly house use decide, before each cheap
run, whether the sun will fill each battery before the expensive hours.
Leftover solar then buys from the grid only the shortfall; Cheap hours only
skips the part the sun covers; Solar first never grid-charges. No, stale or
failed forecast: P3 option A exactly (12 digests pinned from 5a4cdc2).
Replay (16 recorded days, forecast errors from Elia's day-ahead BE solar):
year-earlier prices P4 19.15 vs P2 19.33 / option A 19.44 / old trade 18.14;
real 2026 prices P4 29.19 vs 32.26 / 32.01 / 31.40 EUR net.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>