Releases: springfall2008/batpred
Release list
GECloud robustness fix, New inverter config sensor
What's Changed
- feat(output): publish aggregated inverter config as a sensor by @springfall2008 in #4655
- docs: add Hanchu iESS inverter setup by @upton68 in #4620
- GE Cloud: retain the last good reading when leaf values come back null by @springfall2008 in #4657
New Contributors
Full Changelog: v8.51.0...v8.51.1
Octopus, Cloud inverter and misc features/fixes
What's Changed
Octopus fixes
- feat(octopus): configurable minimum-reward threshold for saving-session auto-join by @chalfontchubby in #4595
- fix(octopus): filter saving-session events by target region in Octopus Direct by @chalfontchubby in #4613
- fix(octopus): defer the joined notification to when the join is actually known by @chalfontchubby in #4632
- feat(octopus): flag Octopus rate URLs with no current/future rates by @chalfontchubby in #4629
- fix(ha): treat a null websocket "success" as False, not None by @chalfontchubby in #4628
- fix(octopus): re-wire IOG car slots when the live device set changes by @springfall2008 in #4650
- fix(octopus): split IOG slots at the daily low-rate cap boundary by @chalfontchubby in #4644
Cloud component fixes
- fix(deye,sunsynk): honour read-only in the cloud reconcile loop by @springfall2008 in #4640
- fix(solis): don't enrol an inverter Solis reports as having no battery by @mgazza in #4643
- fix(teslemetry): model Powerwalls as AC coupled, publish site_info for review by @springfall2008 in #4652
- fix(inverter): treat a failing ge_cloud_direct as transient, and name the source by @mgazza in #4642
Features
An entity now tracks external changes and can be seen on the metrics page of the web UI, useful to debug external controls fighting PredBat.
Ability to model freeze charge not totally stopping the battery from discharging.
-
feat(prediction): model residual battery discharge during Freeze Export by @springfall2008 in #4651
-
feat(plan): split the Import p cell when the car's own rate diverges by @chalfontchubby in #4647
Bug fixes
- fix(solcast): stop mislabeling the PV forecast unit-detection log as an error (#2544) by @chalfontchubby in #4634
- gecloud: add --write-register option to test harness by @springfall2008 in #4626
- fix(config): a missing get_arg value is the default, not an error by @mgazza in #4637
- fix(web): stop the dark-mode page flashing white on load/refresh by @chalfontchubby in #4631
- fix(rates): manual API rate overrides no longer mark the whole day by @chalfontchubby in #4627
Full Changelog: v8.50.0...v8.51.0
Octopus saving join service, Bug fixes and minor improvements
What's Changed
Octopus and bottle cap dave fixes
- feat(octopus): Power Up/Power Down migration - join service and entity regex (points 2 & 3 of #4548) by @chalfontchubby in #4601
Small improvements
- fix(config): widen currency-scoped price ranges for non-GBP markets by @chalfontchubby in #4615
- fix(web): serve the Predbat logo locally instead of from GitHub by @chalfontchubby in #4568
Bug fixes
- fix(sunsynk,deye): own the power sign flags instead of inheriting them by @springfall2008 in #4618
- feat(plan): show the actual planned charge/export rate in the hover text by @chalfontchubby in #4608
- Split charge windows at dawn for any combine_charge_slots user, not just low power mode by @springfall2008 in #4604
- fix(ml): resolve NaN training loss on startup and preserve database zero entries by @rholligan in #4597
- fix(output): set device_class on 9 dashboard sensors missing it by @chalfontchubby in #4622
- fix(inverter): discharge_start_service sends the planned rate, not always max by @chalfontchubby in #4621
- fix(octopus): prune Intelligent devices Octopus no longer returns as live by @springfall2008 in #4625
Code cleanup
- refactor(export): name the export_limit freeze/idle sentinels by @chalfontchubby in #4606
New Contributors
- @rholligan made their first contribution in #4597
Full Changelog: v8.49.2...v8.50.0
Sunsynk/Deye Freeze Export fixes
What's Changed
Sunsynk and Deye cloud
Freeze Export was a silent no-op on both Sunsynk and Deye. Predbat signals it by turning the forced-export window off and zeroing the charge rate, but that rate maps to a per-window control that a disabled window never reads — so the inverter was left in ordinary self-use and surplus solar charged the battery instead of being exported. The freeze state meant to catch this was unreachable, and would have written Predbat's internal "99" freeze marker as a battery SoC target, telling the inverter to drive the battery to 99%.
A freeze export now writes Selling First with the per-slot Sell flag on, a zero sell rate and the cap at the reserve — verified against live hardware, including the controlled pair that identifies the slot rate as the sell-rate cap (at full rate the battery drained to the grid at up to 4.7 kW; at zero it held while surplus solar still exported).
- fix(sunsynk): make Freeze Export actually reach the inverter
- fix(deye): apply the same fix to the same registers
- docs(sunsynk,deye): correct what a zero slot rate actually does
- Resolves the Sunsynk
grid_powersign verification — no behaviour change, now pinned to a live sample and a regression test
Both components' freeze charge behaviour is unchanged.
Note for Deye users: the Deye half is applied on register parity with Sunsynk (both clouds drive the same Deye registers) but has not itself been confirmed against live Deye hardware. If your Deye battery exports during a Freeze Export slot, please raise an issue.
Full Changelog: v8.49.1...v8.49.2
Fix Teslemetry forced export never working
What's Changed
Tesla Powerwall fixes
- fix(teslemetry): correct _tesla_dow - Tesla's day-of-week is Monday=0, not Sunday=0 by @springfall2008 in #4611
Full Changelog: v8.49.0...v8.49.1
Split low power charge at dawn, bug fixes
What's Changed
### Features
- fix(plan): split low-power charge windows at dawn, not window end by @chalfontchubby in #4577
Cloud inverter fixes
- fix(sunsynk): make the settings write actually work — group, Sell flag, encodings by @springfall2008 in #4589
- fix(deye): arm the Sell flag, send touDays, stop switching on the generator by @springfall2008 in #4591
- fix(teslemetry): assert optimization_strategy=economics on every tariff push by @springfall2008 in #4603
Docs and cleanup
- docs: add Canadian Solar EP Cube inverter setup by @SkiLtY in #4594
- fix: explain and stop wasting work when predbat.* history isn't recorded (#4583) by @springfall2008 in #4588
Full Changelog: v8.48.8...v8.49.0
Sunsynk/Deye cloud, Octopus and Whatif fixes
What's Changed
- fix(sunsynk): corrections from the first live read-only spike by @springfall2008 in #4578
- fix(deye): correct the TOU slot payload found by the Sunsynk comparison by @springfall2008 in #4586
- fix(whatif) Let a caller supply the storage backend to annual_cli.main() by @mgazza in #4584
- fix(octopus): read saving session available_events from configured entity, not rewritten one by @springfall2008 in #4585
Full Changelog: v8.48.7...v8.48.8
LoadML Memory reduction, Bug fixes, SunSynk cloud (alpha)
What's Changed
Load ML Memory reduction
- perf(load_ml): gather training batches instead of whole epochs by @springfall2008 in #4564
- perf(load_ml): assemble training features from sliding windows by @springfall2008 in #4567
Features
- feat(sunsynk): add Sunsynk Connect cloud inverter integration (untested) by @springfall2008 in #4565
- feat: strengthen Octopus Intelligent earlier-charge skew by @springfall2008 in #4237
- feat(whatif): added consumed battery-cycles by @Easen in #4423
- feat(web): add live apps.yaml download from in-memory settings by @springfall2008 in #4574
Bug fixes
- fix(config): FoxESS support_discharge_freeze should be False, matching FoxCloud by @chalfontchubby in #4538
- fix(web): floor daily_chart=False chart width at 600px, matching daily_chart=True by @chalfontchubby in #4569
- test: add Octopus Intelligent (IOG) dispatch windows to the random benchmark by @springfall2008 in #4566
Full Changelog: v8.48.6...v8.48.7
LoadML memory reduction, Fetch history memory saving, Bug fixes
What's Changed
Memory reduction
- perf(ha): fetch long history windows in chunks to bound peak memory by @springfall2008 in #4558
- perf(load_ml): halve the memory of a training pass by @springfall2008 in #4559
Bug fixes
- fix(execute): stop the status detail repeating the headline state by @springfall2008 in #4556
- fix(inverter): also skip the discharge target write on Hybrid Gen1/Gen2 by @chalfontchubby in #4551
- fix: rate_min_base/rate_max_base computed from raw sparse fetch, not the gap-filled curve by @chalfontchubby in #4553
- fix(inverter): average battery power across each SoC step in find_charge_curve by @springfall2008 in #4552
- fix(inverter): Don't report fatal error for REST failing by @chalfontchubby in #4288
Full Changelog: v8.48.5...v8.48.6
Fix Solis crash that prevented any plan being produced
What's Changed
A single-fix hotfix for Solis users. If you have a Solis inverter, upgrade from v8.48.4 immediately —
on most Solis installs v8.48.4 cannot produce a plan at all.
Bug fixes
The nominal_voltage fix in v8.48.4 (#4502) added a once-per-inverter warning for installs where the
battery capacity has to be estimated from the live measured voltage. The set that tracked which
inverters had already been warned was never initialised on the real component, so the first
publish_entities() run raised:
Error: SolisAPI: 'SolisAPI' object has no attribute 'capacity_voltage_warned'
That aborted the update cycle, so Predbat kept trying to calculate and never produced a plan. The
warning sits on the branch taken whenever solis_nominal_voltage is not set in apps.yaml — which is
every install that has not explicitly configured it, so in practice this hit nearly all Solis users on
v8.48.4.
- fix(solis): initialise capacity_voltage_warned so publish_entities stops crashing by @springfall2008 in #4555
Setting solis_nominal_voltage in apps.yaml also avoids the crash and remains worth doing on its own
merits — it gives an accurate, stable battery capacity instead of one estimated from a voltage that
drifts with charge state.
Testing
The whole Solis test suite passed against a component that could not survive a single real poll, because
MockSolisAPI replaces __init__ wholesale and had stubbed the attribute the production path was
missing. A parity guard now constructs the real component and asserts it sets every attribute the mock
stubs, so this class of mock/real divergence fails in CI rather than on a live inverter.
Full Changelog: v8.48.4...v8.48.5