Repository navigation
Conversation
… for flexible clearsky overlay
… to match legacy mockup
…o enable historical tracking
|
@rholligan — Claude again, on chalfontchubby's behalf. Thinking on the clipping problem has moved on since we last spoke here, and some of it bears directly on what this PR needs to do. Passing it on rather than letting you find out the hard way. Two things came out of digging into #4865 and a related bug. 1. A lot of "Predbat won't avoid clipping" turns out to be export slots being invisible, not a missing buffer
Battery fills by 11:00, nothing to export into, clips. That's #5221. 2. Once the slots are visible, the existing optimiser already handles itThis is the part most relevant to you. Across every
Every case except the hidden-slot one is already solved by existing logic. Where a prototype slot-admission walk wanted to export, 21/21 and 7/7 of those times were already inside existing candidate windows - it was picking the same slots the optimiser already uses. Worth being straight about what that implies: on this corpus there's no residual for a clipping buffer to fix. Clipping is already costed correctly (clipped PV simply never earns its export revenue), and with slots visible the metric acts on it. 3. But there's a hole neither of us can close from the forecast, and it's yoursEverything above keys off predicted clipping, and a 30-minute-averaged forecast can't represent a 10-minute cloud spike. Same file, same PV data, varying only
A 120x swing on identical data. And the 30 August day it's taken from actually came in 31% under PV50, peaking at 5.48 kW against a 5.5 kW limit - nothing clipped at all. So sizing headroom from the central forecast is a bet, and the parameter it hinges on isn't calibrated against anything I can find. Also worth knowing: Solcast's PV90 for that day peaked at 7.64 kW against a demonstrated clear-sky ceiling of ~9.4 kW - about 18% low. Your choice of What I'd suggestThe strongest remaining case for this PR isn't "the optimiser undervalues clipping" - it doesn't. It's the two things forecast-driven logic can't reach:
That's a narrower feature than "clipping mitigation", but it's a real gap with no other candidate fix, and it's robust precisely because a clear-sky buffer ignores the forecast's fine structure. Practically: this branch is now CONFLICTING against main, and #4871 (the cloud modulation fix) is in - which changes what the model predicts, so any clipping numbers taken before 2 Sep are stale. Happy to run your branch against the same corpus once it's rebased, if that's useful - the harness is just a per-step PV/load walk plus a Analysis by Claude, run and reviewed by chalfontchubby. |
|
@rholligan — Claude on chalfontchubby's behalf, with the review you asked for. Ran the branch locally rather than just reading the diff. Short version: the core design is sound and the clear-sky choice looks better-justified than when you made it. Most of what follows is about separating things that don't need to ship together, because the non-clipping changes in here are what will make this hard to review and risky to merge, not the clipping work itself. The clear-sky approach is right, and for a stronger reason than you hadSizing from clear-sky rather than a forecast percentile is the correct instrument, because it's a physical bound — geometry, not probability. It can't be 31% wrong the way PV50 was on the 30 August day in #4865, and it doesn't depend on Concretely: Solcast's PV90 for that day peaked at 7.64 kW against a demonstrated clear-sky ceiling of ~9.4 kW. Anything sized from PV90 would have undersized the buffer by ~18%. Your One thing that needs fixing: the committed golden baseline doesn't match the branch
The bigger issue: plan changes on a case with the feature switched offThat failing case has The gating on the clipping code itself looks right (
None of these are necessarily wrong. The problem is that they're plan-affecting changes to shared code riding along inside a feature PR that's off by default, which makes it very hard for anyone to tell whether a plan difference is the feature working or a regression. What I'd suggest, and I think it makes this easier not harderSplit into two or three PRs:
That third PR becomes much easier to review and much easier for Trefor to merge, because "flag off means nothing changes" is checkable in one command. Also worth pulling in: #4871 (cloud modulation fix, merged 2 Sep) changes what the model predicts, so any clipping numbers measured before then are stale. And the branch is currently CONFLICTING against main. Where this feature fits now — the scope has narrowed, but it hasn't gone awayWorth knowing what we found while looking at #4865 and #5221, because it changes the argument for this PR rather than weakening it. A lot of "Predbat won't avoid clipping" turns out to be export slots being invisible to the planner — the price threshold that builds
Existing logic already handles these. Clipping is costed correctly today (clipped PV simply never earns its export revenue), so where slots are visible, the metric acts on it. But that leaves exactly the gap this PR fills, and nothing else does:
So the honest framing is that this is a narrower feature than "clipping mitigation" — but it's the only candidate for the part that forecast-driven logic structurally cannot reach. That's a better argument than the one it started with, and it's worth putting in the PR description. Happy to run your branch against the same 12-file corpus once it's rebased and the baseline regenerated — the harness is a per-step PV/load walk plus a Review by Claude, run and reviewed by chalfontchubby. Method: fetched the branch, ran |
|
One follow-up, offered as things to weigh rather than change requests — both might simplify what this PR has to carry. 1. Your auto-tuner and
|
metric_cloud_coverage |
modelled peak | predicted clip |
|---|---|---|
| 0 | 5.51 kW | 0.01 kWh |
| 0.27 | 7.00 kW | 1.57 kWh |
| 0.5 | 8.27 kW | 4.09 kWh |
Same file, same PV data. Since #4871 (merged 2 Sep) that modulation now applies to the PV50/PV90 curves, not just PV10 — so on current main the central forecast already carries intra-slot variance it didn't when you started this work. Two things follow that might be worth testing before finalising the tuner:
- How much of the amplification your tuner learns is now already in the curve? If fix(fetch): make the cloud/load divergence model actually modulate #4871 supplies a chunk of it, the tuner may be double-counting, and
clipping_amplificationmay be doing less work than it was. - Your tuner has better data than the cloud model does. It's measuring real peak-vs-limit per site. If that estimate were fed back as a calibrated cloud factor rather than a clipping-only amplification, it would improve every consumer of the PV curve, not just the buffer. That's a bigger contribution than the buffer itself, and it's mostly code you've already written.
Not saying you should take that on — just that the tuner may be more generally valuable than its current scope, and it's worth knowing before it's finalised as a clipping-private mechanism.
One small note on the implementation while I was reading it: the tuner persists to clipping_auto_tune.json via direct file I/O. CLAUDE.md asks for the Storage component rather than direct file access, so that may get flagged in review.
2. Slot availability may change what the buffer has to do, not just how much
I mentioned #5221 as scope-narrowing, but there's a design angle I didn't draw out.
The two mechanisms answer different halves of the same constraint:
surplus arriving by time T <= export capacity admitted before T + battery headroom
Slot admission raises the first term; your buffer raises the second. Where slots are already visible, the optimiser is currently free to use either — and on the corpus it consistently chose export over headroom, ending at 0.00 clip without reserving anything.
Which raises a question worth answering deliberately: when both are available, which should the plan prefer? Exporting early costs the arbitrage spread if rates rise later; reserving headroom costs the cycling and the risk that the forecast peak doesn't arrive. Those trade off differently per site and per day, and if the buffer applies a cost penalty for insufficient headroom while the optimiser could have solved it more cheaply by exporting, the penalty could push the plan the wrong way.
Might be worth testing the buffer specifically on a case where an export slot would have solved it, to check the two don't fight. If they compose cleanly, that's a good result worth stating; if they don't, better to know before Trefor asks.
Genuinely not trying to expand your scope here — the buffer is still the only candidate for the spiky-cloud gap, and that stands regardless of either point above.
|
Thinking about the auto-tuner point a bit more — there might be a cleaner split available than the one I suggested earlier, if you like the shape of it. Calibration and buffer as separate PRs. The earlier suggestion (standalone fixes / ungated prediction changes / feature) was really about tidiness. This one is along a capability boundary instead, and I think it's a better line:
Why that line might be worth it: The calibration stands alone and helps everyone. A better PV curve improves the planner, clipping prediction, the PV10/PV90 blend — everything downstream. It's useful with the buffer switched off, and to users who'll never turn it on. The dependency only runs one way. The buffer wants good calibration; calibration doesn't need the buffer. So calibration merges first and the buffer builds on it — and if the buffer takes a while in review, the calibration isn't held up behind it. Given what happened to #4036, that seems worth something. They're verifiable by different means. Calibration is a backtest: does the learned amplification predict observed peaks better than the fixed factor? No planning involved. The buffer needs plan-level before/after on clipping days. Different evidence, different questions, neither blocking the other. Two things that cut the other way, so you can weigh them:
So the fuller sequence would be: standalone fixes → ungated Entirely your call — you may well have reasons the tuner needs to stay coupled to the buffer, and "keep it scoped, ship it, generalise later" is a perfectly good answer too. Just wanted to put the option in front of you before the shape is settled. |
|
Thanks for the thorough testing and feedback, @chalfontchubby. Based on your review, I have implemented your core recommendations on branch
Merge StrategyPlease review the recent commits and updates above. Once you and @springfall2008 have had a chance to look over the branch, let's align on the best way to merge - whether to proceed directly with #4086 now that it is conflict-free and passing all checks, or decompose into smaller PRs. |
|
Cheers. I'll read more in a bit, but we will need to get @springfall2008 to look as well. I don't have power to merge. |
…and kernel parity
Introduction:
This PR introduces a native clipping buffer to Predbat. It prevents solar energy loss on high-generation days by creating dynamic headroom in the battery SoC, specifically targeting periods where PV generation is forecast to exceed inverter AC capacity or DNO export limits.
This implementation integrates with the existing cloud model. It extends
SolarAPIto compute and store newpv_clearskyarrays (supporting multiple native upstream sources likeha_solcast_clearsky,solcast_api, andopenmeteo). Clear-sky arrays are used alongside a lightweight auto-tuner to safely estimate peak generation and align it with hardware limits.Resolves issue #1206, supersedes PR #4036.
Key Features:
ha_solcast_clearskyintegration alongside a robustclipping_auto_tunemechanism. This explicitly accounts for those short "break in the clouds" spikes, ensuring the buffer is safely sized even when the standard hourly forecast is smoothed out.solcast.pywith safefloat(val or 0.0)casting to gracefully handle missing HA clear-sky sensor history without crashing.Configuration Parameters:
clipping_buffer_enable: Master toggle for the clipping buffer feature.clipping_clearsky_source: Selection of clear-sky forecast source (recommendsha_solcast_clearsky). This setting is fully exposed in the Home Assistant configuration panel.clipping_use_clearsky_peaks: Toggle to use Clear-Sky generation arrays rather than standard PV forecast arrays to size the buffer.clipping_auto_tune: Automatically learns the scale difference between standard forecasts and hardware limits based on past clipping behavior.clipping_amplification: Manual multiplier for the standard solar forecast (used if Auto-Tune is disabled).clipping_cost_weight: Multiplier to add a harsher financial penalty for clipping, forcing the optimizer to prioritize creating headroom.clipping_limit_override: Manual configuration of the inverter AC ceiling in Watts.clipping_buffer_max_kwh/start_time/end_time: Manual settings to force a fixed static buffer size and time window instead of using the dynamic calculation.Developed with Gemini ✦