Releases: Bascht74/ha-pv-optimizer
Releases · Bascht74/ha-pv-optimizer
Release list
V6.15.1
Fixed
- The top-balancing start message no longer claims to calibrate anything. It still announced an
internal state of charge set to 100 %, a step that went out with the shadow BMS, so the line
reported an action the blueprint has not taken since and contradicted the charge level it
printed in the same breath. - Every message that prints the state of charge now says which one it is. Where a shadow BMS is
assigned, the blueprint plans on its reading while the inverter shows its own, so a bare
percentage left the reader to guess which of the two scales a number belonged to. Those messages
now name the shadow BMS and give the inverter's value beside it, and stay as they were where no
shadow BMS is assigned.
V6.15.0
Added
- Hot water can be made from a sunny day, not only from a feed-in peak. The boost used to start
only once the grid export passed its threshold — surplus the battery was already refusing — so
on an ordinary autumn day nothing released it and the heat pump took the tank from the battery
in the evening or before sunrise. A second gate now reads the day's forecast: if one charge's
worth of energy can be taken out of the remaining surplus and the escalation still does not
trigger, the energy is there even when none of it is reaching the grid. The moment has to carry
the draw as well, so the gate also asks that sun minus house consumption exceeds the power the
charging plan wants — read before the battery takes its share, because a charging battery holds
the grid export at zero — and that enough surplus hours are left for the boost's run time and
its charging lead. It carries a tank-temperature limit of its own, because curtailed energy at
the feed-in gate is free while forecast surplus is not; whichever of the two limits is the
tighter one governs. It stands down during the morning blockade, whose own charging start is
figured with a buffer that knows nothing of a hot-water draw, and while the battery does not
hold a charge plus the general buffer above its discharge floor, so a cloud gap is carried by
the battery rather than by the grid. The new field "Strom je Warmwasser-Ladung (kWh)" carries
the amount and is the switch: left at 0, the blueprint behaves as before and no configured
instance changes.
Changed
- The hot-water boost no longer tops up an almost full tank. Its hysteresis is the distance below
the boost target at which a boost may begin, and the default moves to a wider gap. Every charge
costs the same pipe and start-up heat whatever its size, so a short top-up returns far less per
kilowatt-hour than a full one, and a narrow gap lets a run of sunny days produce one small charge
a day. Only the default and the help text change; an instance that sets the field keeps its value.
V6.14.0
Changed
- The mandatory startup-phase timer is no longer named after the heat pump. Whatever starts it,
peak shaving leaves the charge current alone while it runs, and that holds with or without the
heat-pump boost configured, so the timer is the way to keep the battery out of the way of any
large appliance. Field label and help text say that now; the field itself is unchanged, so no
instance needs reassigning. - One battery pack is mandatory, every further one is optional. The three BMS 2 fields (cell
voltage and both cell temperatures) are no longer demanded by the startup check, so a
single-pack site can leave them empty the way the BMS 3 fields already could. With them
empty the blueprint computes with one pack throughout: capacity, temperature limit and
cell balancing all read pack 1 alone. The worked example behind the charge rates now says
which number is the pack count, which only read as obvious while two packs were assumed. - The help text of the state-of-charge field read as if the shadow-BMS field below it had to be
filled in too. Both descriptions now say plainly that the second sensor is optional: left empty,
the inverter's own reading alone drives the whole cascade, and only a filled-in shadow field
brings both values into the conversion of the discharge-floor registers.
Removed
- The escalation ceiling on the state of charge is gone as an input. No branch ever read the
field, while the escalation itself stops at a fixed 97 % that sits in its own entry condition —
so the field could only ever have lowered a ceiling that already held, and it never did. The
fixed limit stays; what goes is the field that made it look adjustable per site. An instance
that still assigns the key is unaffected, the blueprint simply ignores it, and from this release
the configuration block of the diagnostic recording carries one key fewer than older lines.
Fixed
- The helper template no longer gives the half-hourly meters a cycle of their own. The blueprint
zeroes them every thirty minutes anyway, and a daily cycle put the meter's own reset on the
same second as the run that reads the last slot before midnight, which the run loses because
it queues behind the five-minute run. That slot then learned a zero and the running mean
pulled it down further every night. A site that already copied the template has to drop the
cycle:line from each half-hourly meter it actually runs — house consumption, each wallbox,
the backup circuit; the counters evaluated per period keep theirs. Re-importing the blueprint
does not touch its package. - The helper template no longer pins the charge mode to
normalat startup. The mode is
memory, not decoration: the morning blockade holds through the end of its window only by
recognising itself, and the top-up branch leaves case B alone for the same reason. With
initial:set, Home Assistant skips restoring the value, so every restart quietly dropped
that memory. Without it a freshly created helper still starts on the first option. Here too a
site that already copied the template has to delete theinitial:line itself. - The helper template gives every timer
restore: true. Without it a timer that was running when
Home Assistant restarts comes back idle, and the branch it guards then reads a state that no
longer exists: the cell-balancing cooldown, the peak-shaving hold, the startup phase and the
boost runtime each end silently mid-run. A site that already copied the template has to add the
four lines itself. - The help text of the startup-phase timer and of its duration field said the battery drops to
0 A while the timer runs. It does not: that branch holds the charge current at the value it
last had and leaves lowering to the branches that own it, which the branch comment has said
all along. The same wrong picture had been carried from one wording to the next. - The logbook line for an interrupted peak-shaving hold named the heat pump as the reason. The
condition it reports only tests that the startup-phase timer runs, and anything may have
started it, so the line now names the timer instead of guessing the appliance. - A pack is now assigned as a whole or not at all: as soon as one of a pack's three sensors is
set, the startup check demands the other two and names the missing one. A half-assigned pack
used to compute silently wrong numbers — a missing highest cell temperature was read as 99 °C
and throttled the charge current to zero, a missing lowest one left the pack out of the
capacity, and a missing cell voltage left it unwatched during cell balancing. - The lowest cell temperature of pack 1 is a mandatory field now. Left empty, no pack counted
as reachable and the whole system ran on the emergency charge current for good, reporting
the BMS as offline — a state that is indistinguishable from a real outage in the logbook,
while the cause was an unassigned field the startup check could have named. - The second-opinion request to the optimizer now describes the battery the inverter actually
enforces. Its minimum state of charge is the ToU register in force instead of the general
minimum, so the schedules it returns can be compared with the blueprint's own plan; a request
built on a floor the inverter does not release yields schedules that could never have been
run. The floor is capped at the current state of charge, because a floor above the starting
point leaves no feasible schedule at all. Charge and discharge efficiency now come from the
same constants the blueprint's own planning uses, so both sides of the comparison assume the
same battery. Diagnosis only; no register is written on that run. In the recording,s_min_pct
of the request now reports the floor that was actually sent instead of the general minimum, so
those lines cannot be compared across this release. - The run that learns the consumption profiles now converts the discharge floor into the same
scale as the rest of the blueprint. It keeps its own copies of the hold detection because the
variable chain does not run there, and those copies compared the raw register against a minimum
that is meant in the second BMS's scale. Where the two scales differ, a floor one step above the
minimum counted as "not holding", so the night side of the loss accounting stayed silently at
zero, and the cap on the accumulated night import came out short by the offset. Without a second
sensor the offset is zero and nothing changes. The slot line of the recording now carries the
offset itself, and its floor and held-back energy are in the same scale as the run line, where
they previously were not despite the same names.
V6.13.0
Added
- An optional second state-of-charge sensor. Where a more accurate BMS measures the same
battery, the whole cascade now computes in its scale, and the difference to the inverter's
own reading is applied at the register boundary only: added when the discharge floor is
written, subtracted when it is read back. The inverter enforces its ToU registers against
its own BMS, so a floor derived from the accurate reading was enforced at the wrong state
of charge. Without the sensor the difference is zero and nothing changes. - A logbook message when the second reading is unusable and control falls back to the
inverter's own value. Nothing about the behaviour shows that fallback, and a reading taken
as zero would pull the floor to the bottom.
Changed
- The state-of-charge field is now explicitly the value the inverter itself sees; the more
accurate sensor belongs in the new field. Instances that followed the earlier hint and put
a shadow sensor in the old field have to swap the two before the new one takes effect. - The inverter's shutdown state of charge is converted into the control scale before the
backup reserve builds on it, because that reserve is what holds in an outage. - Without discharge planning the ToU minimum is written converted as well, so the configured
percentage means the same state of charge everywhere it is used. - The balancing voltage stays as an input, now only as the threshold at which the measured pack
voltage counts as full while every BMS is offline — the fallback that starts a balancing run
when no cell voltages are readable. It is named and described for that role; value and effect
are unchanged.
Removed
- The blueprint no longer writes any voltage to the inverter. Raising the float voltage for a
cell-balancing run, setting it back when the cooldown timer expires and the midnight check that
caught a voltage left raised by a lost timer are gone, together with the two float-voltage
inputs and the timer triggers that existed only to drive them. Writing a setpoint the charger
already manages means owning its failure modes for no gain: cell balancing works through the
throttled charge current alone.
V6.12.3
Fixed
- The mandatory-helpers section still offered the shadow BMS helpers as fields that may stay
empty, and a comment on the fallback for a total BMS outage still explained itself through the
shadow BMS. Both were written in the release that removed it, and they name something the
blueprint no longer has.
V6.12.2
Fixed
- Two field texts still described the charge counter as part of the shadow BMS, alongside a
discharge counter the blueprint no longer has. The counter is the probe that tells the blueprint
whether the inverter connection is alive: when it reports unavailable the run is stopped instead
of steering on substitute values. The section text even offered it as a field that may stay
empty, which would have dropped half of that probe without a word. - The installation step still told the reader to delete the optional package blocks. They ship
commented out, so there is nothing to delete, and cutting in that region is how a whole
utility_meter group was once lost along with the house meter next to it.
V6.12.1
Fixed
- The second opinion recorded a night low for the evcc optimizer that was not one. Its horizon
ends after 24 hours, and beyond it there is nothing left to gain, so the solver parks the
battery at 100 % for the rest of the plan and covers the house from the grid on paper. Whenever
the detected night fell into that stretch, the recorded low described the edge of the horizon
rather than a decision, and read as if the optimizer wanted a far higher floor than it does. The
low is now reported only when the plan actually discharges over the night;nacht_abfallgives
the drop it found, so a missing value says why.
V6.12.0
Removed
- The shadow BMS leaves the blueprint. Deriving a state of charge from the energy counters is a
battery concern, not a charge-control one: the blueprint never owned the formula, it only wrote
the tare helpers the external sensor read back. It now consumes a state of charge like any other
measurement and no longer cares where it comes from. Gone with it are the inputs for the shadow
BMS sensor and both tare helpers, the discharge counter that had no other use, the trigger and
branch for recalibrating while the battery leaves 100 %, and the tare anchoring in the
cell-balancing branch. The charge counter stays: it is also the probe that tells the blueprint
the inverter connection is alive. - The helper package no longer ships the two tare helpers; they belong to the shadow BMS.
Added
- The five mandatory input sections now name the fields inside them that may stay empty, and the
function that is lost with each. A section marked mandatory otherwise suggests every field in it
has to be assigned, while several of them only gate an optional feature. - Tests for the priority cascade: one scenario per branch, stating which branch wins and what it
writes to the inverter, plus the couplings in which a change to one branch can quietly disable
another. A coverage test reads the branch aliases out of the blueprint and compares them with the
ones the scenarios reach, so a new branch turns it red until a scenario covers it.
V6.11.0
Added
- A logbook entry for the case in which surplus is actually lost: the inverter curtails once the
feed-in passes the peak-shaving threshold and it can no longer route the current into the
battery. That is the counter-condition to the peak-shaving branch, which does not start on a
full battery, so until now the one situation that costs yield was the only one not reported.
The debounced export trigger reports it once per crossing, the half-hour run keeps a lasting
curtailment visible.
Changed
- The charge-current simulation halves the search interval instead of stepping through it in
1 A increments. The simulated capacity is monotonic in the current, so bisection returns the
same value in a fixed number of rounds. The stepping scan ran up to the configured maximum
whenever the demand could not be covered in the window at all, which is the most common case
and the one where the result is only a fallback. - The optional parts of the helper package ship commented out instead of asking to delete them.
Home Assistant validates each group as a whole, so one forgotten placeholder in the wallbox or
backup-circuit blocks dropped the mandatory half-hourly house meter with it, and the error then
pointed at an unassigned field rather than at its cause. - Traces are kept for 800 runs instead of 400, so a diagnosis still finds the day before last.
- The diagnostic recording is set up outside the web root. Everything under
/config/wwwis
served at/localwithout any authentication, and the recording describes the site in detail.
The setup releases one directory throughallowlist_external_dirsand names Samba, the file
editor or scp as the way to fetch the file. - The weather recording keys each source by its integration instead of its entity id. Entity names
carry the site location on some integrations, and only the source matters for comparing forecast
error; one entity per integration keeps the mapping unambiguous. Without a registry entry the
position in the selection is used, never the entity id. - The note appended to the peak-shaving message when no morning blockade ran is marked as
informative instead of a misjudgement of the forecast. Shaving a peak is what the branch is for,
and it costs nothing while the battery still takes charge; the new curtailment entry reports the
case that does.
Removed
- The calendar guard that suppressed the morning blockade from November to February, together
with the snow detection that hung off it. The detection could never fire, because its own
condition required one of those months while the blockade excluded them in the same chain.
What the guard was for is answered more precisely elsewhere: the blockade only starts when the
forecast expects an export peak worth shaving, and the reality check pulls the available
surplus down to what the panels actually produce, so covered panels keep it from starting.
Fixed
- Two field descriptions offered a shadow BMS as supplied although the package states it is not
included, and the description of the battery power sensor did not name the sign convention the
export and discharge detection depend on. - The blueprint description named the state before the discharge planning existed. It now says
what the automation does today, which is the first text Home Assistant shows in the list. - The description of the first time-of-use field promised a nightly recharge from the grid. That
behaviour went away when the discharge planning took over the registers. The field now states
what it does and names the inverter operation mode the value needs to take effect. - Three comments claimed a 30 s debounce for the two export triggers where the code has two
minutes for both. The reason for the equal debounce is now written once, at the trigger it
belongs to, instead of being restated in contradictory form at three places. - The optimizer request in the package waited up to two minutes. The run sits in the same queue
as monitoring and peak shaving, so a hanging optimizer delayed control; it now gives up after
twenty seconds, which is ample for a local service and diagnosis only anyway.
V6.9.0
Added
- Optional inputs for the backup circuit: a half-hourly energy meter of the load on the
inverter's UPS output and a helper in which the blueprint learns its 48-slot profile
(watt-hours per half hour). Both are recorded per half hour; nothing is controlled yet.
The profile is the basis for a backup reserve in a later version.
Changed
- The discharge floor is planned per half hour over a rolling 72-hour window instead of per
calendar day. The forecast trust applies by lead time (under 24 hours in full, then the two
configured factors) to each slot's surplus, deficits count in full, and the running sum is
clamped at zero: deficits before a sunny stretch are carried by the floor itself and do not
reduce the refill. Nothing switches at midnight or at sunrise any more; the two trust
inputs now read "24 to 48 hours" and "48 to 72 hours ahead". - The refill is measured up to the largest intermediate maximum, so the target is reached
at the end of the best sun day rather than at midnight after the evening consumption. - Tomorrow, day 3 and day 4 use their own Solcast half-hour arrays when the sensors carry
detailedForecast; otherwise the day total is spread in today's shape. Days are matched by
the date of their array, so a late sensor roll-over at midnight no longer shifts the horizon. - The recording carries the half-hour arrays of the three following days (state, P10 and
start only) and the first counted slot of the plan. - README names the inverter setting "Battery Operation Mode: Voltage" as a reason for a
floor that is not honoured: in that mode the SOC fields of the time-of-use programs are
ignored.