The configuration sync of the Home Assistant adapter skipped every value that is false in
Python, so an entity state of 0 or off never reached the configuration. It also set any
path it was given: the documented example devices/batteries/0/capacity_wh named a device
"0" that does not exist, so EOS silently added a new battery with a random device id.
Apply every value except an unavailable or unknown entity, and only update settings that
exist; report other paths as an error. The example now addresses the battery by its
device_id.
Signed-off-by: SchaafAlexander <86607129+SchaafAlexander@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The automatic field migration recursed into every dict and addressed each
leaf by a "/"-joined path. Keys that themselves contain "/" - e.g. the config
paths used as keys of adapter.homeassistant.config_entity_ids - were split
into path elements. set_nested_value() then created a "devices" entry with
an empty string default and failed further down, so every version migration
replaced the mapping by {"devices": ""}.
Migrate a dict whose keys contain "/" as one value instead of per key.
Signed-off-by: SchaafAlexander <86607129+SchaafAlexander@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
No PV forecast modelled snow lying on the modules, so after a snowfall the
optimizer planned with PV that never came. The local Open-Meteo/pvlib
backend can now reduce the forecast by the snow coverage (opt-in via
pvforecast.akkudoktor.snow_enabled):
- Request hourly snowfall and snow depth with the weather and run the NREL
snow coverage model (pvlib.snow) per plane.
- Correct the coverage with measured PV production: production above the
model clears it at once; low production raises it only while snow is
plausible, so curtailment and inverter outages are not learned as snow.
Persisting snow damps the slide rate, fading with
snow_feedback_memory_hours.
- Rebuild the coverage from snow_lookback_days on every update instead of
storing state.
- Exclude intervals with possible snow from the calibration fit.
- Warn when PV meter readings are missing or stale; ignore impossible meter
jumps.
_plane_power keeps its two-value signature (used by the adaptive provider in
#1422); the irradiance comes from the new _plane_power_and_poa.
Tests replay real February 2026 data from one plant (snow on 02-19/20).
Signed-off-by: SchaafAlexander <86607129+SchaafAlexander@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
LFP batteries can only recalibrate their state of charge close to full
charge, so many systems expect a full charge every few weeks and some
start one on their own at an arbitrary, possibly expensive time. EOS can
now plan it instead (GENETIC only, off by default).
New battery settings: full_charge_interval_days (unset = off),
full_charge_soc_percentage, full_charge_detect_percentage,
full_charge_allow_grid and the informational cell_chemistry. The last
full charge is read from the measured SoC history; nothing is stored.
When the next one is due within the horizon (or overdue), the maximum
SoC is raised to the target. With full_charge_allow_grid the optimizer
must reach the target once before the deadline, which is at least 24 h
away (penalty battery_full_charge_miss on the best SoC reached), so it
picks the cheapest time itself. Without it, PV surplus may fill the
battery but the target is not enforced.
Signed-off-by: SchaafAlexander <86607129+SchaafAlexander@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* feat(eosdash): plan page with EMS plan timeline and persisted settings
Fixes:
- SolutionCard no longer appends to the module-level solution_excludes
list on every render (the list grew without limit).
- All EOSdash pages: keep the scroll position after htmx actions instead
of jumping to the bottom; Bokeh() reserves the plot height.
- Default visible PV column pvforecast_power_w -> pvforecast_ac_energy_wh
(the old column no longer exists).
- All EOSdash pages: remove w-screen from components.Page (horizontal
scrollbar).
- Solution chart: energy is the main axis; the always empty power axis is
only shown with power columns. Typo "Electricty" fixed.
Features:
- EMS plan timeline per device, plan table as collapsible section.
- Solution chart rework: KPI row, legend, totals view, value axes for the
displayed columns only, units menu, currency from the timezone, aligned
time axes with the timeline, themed tooltips, system font.
- Per-column and per-command settings: visibility, alias, color, style;
device aliases.
- New config section eosdash.plan (server/dash/dashsettings.py) stores the
plan page settings in the EOS configuration; docs regenerated.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: SchaafAlexander <86607129+SchaafAlexander@users.noreply.github.com>