Skip to content

feat(plan): add morning_cover best_soc_max mode - #4514

Draft
jpfelgueiras wants to merge 1 commit into
springfall2008:mainfrom
jpfelgueiras:feature/best-soc-max-morning-cover
Draft

feat(plan): add morning_cover best_soc_max mode#4514
jpfelgueiras wants to merge 1 commit into
springfall2008:mainfrom
jpfelgueiras:feature/best-soc-max-morning-cover

Conversation

@jpfelgueiras

Copy link
Copy Markdown

Summary

Adds a best_soc_max: morning_cover mode that dynamically caps the optimiser's maximum charge target to cover the forecast morning energy gap from the end of the current/next charge window until forecast PV exceeds forecast load.

This avoids needing a fixed best_soc_max value that may be too high on sunny days or too low on cloudy days.

Details

  • Allows best_soc_max: morning_cover to be used as a special mode.
  • Keeps best_soc_max numeric internally so existing optimiser comparisons remain safe.
  • Uses Predbat's existing stepped load and PV forecast arrays.
  • Starts the cover period after the active charge window, or after the next future charge window.
  • Sums forecast load minus forecast PV until PV first exceeds load.
  • Sets best_soc_max to reserve plus the loss-adjusted morning deficit, capped at soc_max.
  • Leaves best_soc_max uncapped if no PV-over-load point is found in the 24h horizon.

Tests

  • python3 -m py_compile apps/predbat/fetch.py apps/predbat/plan.py apps/predbat/tests/test_morning_cover.py apps/predbat/unit_test.py
  • unit_test.py --test morning_cover

@springfall2008

Copy link
Copy Markdown
Owner

Thanks for your contribution.

I don't see why we would want to do this, it seems like a hack to workaround something else, can you share the issue you have with your plan so that it can be looked into?

Thanks

@springfall2008
springfall2008 marked this pull request as draft August 14, 2026 07:13
@jpfelgueiras

Copy link
Copy Markdown
Author

Thanks for taking a look.

The issue I was trying to solve is that a fixed best_soc_max is hard to tune for overnight/cheap-rate charging when the useful target depends heavily on the next morning's forecast PV.

My use case is:

  • Cheap import window ends in the morning.
  • PV usually starts covering house load later in the morning.
  • I want Predbat to charge only enough battery to cover the forecast deficit between the end of the cheap window and the point where forecast PV exceeds forecast load.
  • A static best_soc_max either overcharges on sunny days or undercharges on cloudy days.

So the intended behaviour is not to force a fixed SoC target, but to derive the cap from Predbat's own load/PV forecasts:

reserve + forecast(load - PV) from the end of the charge window until PV first exceeds load.

That said, I understand your concern that this may be too specific or may be working around another planning/tuning issue. If there is an existing Predbat feature or recommended configuration that already expresses "only charge enough to cover the morning gap until solar takes over", I’m happy to use that instead.

The concrete problem I see in the plan is that without a dynamic cap, Predbat can choose to charge more during the cheap window than I need before solar generation starts, because the best cap is not a fixed value across days. I can provide debug output / plan screenshots if that helps identify whether this should be solved differently.
If you want a slightly more concise version:
Thanks for taking a look.

The problem I’m trying to solve is avoiding a fixed best_soc_max for overnight/cheap-rate charging.

The useful cap varies by day: I only want enough battery to cover the forecast house load from the end of the cheap charge window until forecast PV exceeds forecast load. On sunny days that may be a low value; on cloudy days it may be much higher. A static best_soc_max either overcharges or undercharges depending on the forecast.

So the proposed mode derives the cap from Predbat’s own forecast arrays:

reserve + forecast(load - PV) until PV first exceeds load.

I agree it may be too specific, and I’m happy to approach it differently if there is already a better Predbat mechanism for this. The underlying issue is: how should Predbat express “charge only enough overnight to bridge the morning gap until solar takes over” without hardcoding a static kWh cap?

I can share debug/plan output from my setup if that would help.

@springfall2008

Copy link
Copy Markdown
Owner

Hi,

Did you know I just added a pv90 feature which you can enable which should tune the overnight charge much better in these cases?

If you can share you predbat_debug.yaml file I can reproduce a bad plan and see why?

@jpfelgueiras

Copy link
Copy Markdown
Author

Thanks, I had not realised PV90 had landed for this case.

In the meantime I have changed my live setup to use the upstream PV90 feature instead of my local best_soc_max: morning_cover workaround:

best_soc_max: 0.0
calculate_pv90_plan: true
pv_metric90_weight: 0.15
load_scaling90: 0.7

That is clearly the better first thing to test because it is native to Predbat's optimiser and uses the real Solcast PV90 data I have available.

I still think morning_cover is a slightly different approach rather than just an alternative tuning of PV90:

  • PV90 is probabilistic: it changes the optimiser metric by pricing in a sunny / lower-load upside scenario, so unnecessary overnight grid charging becomes less attractive.
  • morning_cover is deterministic: it derives an explicit temporary cap from Predbat's own forecast arrays, covering only the expected deficit from the end of the cheap charge window until forecast PV exceeds forecast load.

The advantage of the morning_cover approach is that it is explainable and bounded: the cap is directly tied to the forecast morning energy gap plus reserve, rather than depending on a scenario weighting. It avoids having to choose a fixed kWh cap that is too high on sunny days and too low on cloudy days.

That said, I agree PV90 is more aligned with Predbat's current architecture, so I will test with PV90 enabled first. If I can still reproduce a bad overnight charge plan, I will capture and share predbat_debug.yaml so you can reproduce it properly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants