##
Latest Updates (v3.15.106–v3.16.0)
### Solar Forecast Pipeline Simplified — Removed Stale Correction Layers (v3.16.0)
* **Solar (PV) forecast accuracy improved by removing several correction layers that had drifted out of sync with the underlying yield-learning** — Three changes: (1) the daily PV bias factor (a correction learned from past forecast-vs-actual ratios) no longer applies once the per-slot solar yield factors have converged (≥10 learned slots) — previously it kept multiplying an already-corrected forecast by up to 1.54×, double-counting the correction (`learning-engine.js`, `getDailyPvBiasFactor`); (2) the “clear-sky ceiling” — a separate hard radiation-based cap on the PV forecast — has been removed entirely; the forecast is now radiation × learned yield factor, capped only by the panel’s rated capacity; (3) an abandoned experimental “Cabauw decorrelation” scaffold (unused nowcast correction, never enabled) has been stripped from `weather-forecaster.js` and `learning-engine.js`. Together these collapse a stack of stacking correction layers into a single traceable pipeline (radiation → yield-learning → daily-bias gate → DP forecast), with the *same* forecast feeding the DP optimizer, the planning chart, and the explainability text — verified by code-trace, no separate snapshots.
* **Overnight battery reserve now also reacts to forecast model disagreement, not just historical accuracy** — The refill-reserve floor (which holds back charge overnight when next-day PV is uncertain) previously based its confidence only on past forecast accuracy and bias-corrected delivery ratio. It now also folds in the *forward* spread between weather-model ensembles (MF/GFS/ICON/KNMI) for the upcoming day — wide model disagreement raises the reserve floor even when historical accuracy looks fine, since past accuracy can’t see that tomorrow’s forecast is unusually uncertain. `optimization-engine.js`, `refillConfidenceFromForecast`.
* New economic-dominance regression test: lifting the PV forecast for any slot can never *decrease* the optimizer’s projected profit under net-metering (more free PV input is always neutral-or-better). `test/optimizer-properties.test.js`
### Planning Chart No Longer Projects a Grid Charge the Runtime Won’t Make (v3.15.97)
* **The planning table no longer shows `to_full` (grid charge) on a low-SoC slot when the PV forecast is strong** — On a cheap, low-SoC slot where the forecast PV roughly cancels forecast consumption (net surplus ≈ 0), the planning mapper’s low-SoC grid top-up fired and projected `to_full`, while the live runtime peak-shaved from PV and never pulled from the grid. The chart over-promised a grid charge that reality skips. The planning top-up is now suppressed whenever PV is strong (≥ 400 W), mirroring the runtime — which suppresses top-up via its real `estimatedNetPvSurplusW` signal whenever PV is producing. Strong PV now projects PV-only charging (`pv_trickle` / `zero_charge_only`); the top-up still fires when PV is genuinely weak or absent and no peak-shave is possible. Economically sound too: when PV refills the battery for free, a grid top-up is pure cycle-cost loss. Regression tests in `test/policy-planning.test.js`
### SoC-Drift False Positive on Planned Charge from Empty (v3.15.97)
* **A planned `to_full` charge from an empty battery is no longer flagged as a BMS-calibration drift** — When the battery legitimately starts the day at 0% (drained overnight by the planned evening discharge) and the plan commands a normal `to_full` grid charge, the SoC-drift detector fired a false `
SoC drift detected` the instant charging began. Cause: the drift timer was anchored to when SoC *last changed*, which for an empty+idle battery was hours earlier overnight — so the “20 minutes stuck while charging” threshold was already satisfied before a single minute of real charging had elapsed. The detector now anchors to when *charging-while-stuck began* (new `computeChargeStuckAnchor` helper, reset whenever the battery is idle or SoC leaves 0%), so the delta measures sustained charging duration. A fresh `to_full` stays silent; a battery that genuinely won’t take charge for 20+ min still fires correctly, and the real BMS-calibration two-phase signature (75 W → 800 W) is unchanged. Regression tests in `test/battery-soc-drift.test.js`
### Overnight Reserve Now Reacts to PV-Forecast Bias (v3.15.97)
* **The battery holds an overnight reserve when the PV forecast has been over-optimistic, not just when it is volatile** — The refill-reserve floor (which keeps the battery from draining to empty before an uncertain next-day PV refill) was driven only by forecast *volatility* (CV). A *consistently* over-optimistic forecast — low CV but PV delivering only ~half of what was predicted — produced full confidence and no reserve, so the battery drained to 0% overnight and was forced into a thin-margin morning grid top-up. The reserve confidence now also folds in the bias-corrected delivery ratio (`refillConfidenceFromForecast` in `optimization-engine.js`): when PV under-delivers versus the forecast the DP actually uses, confidence drops proportionally and the floor engages. Over-delivery is upside and is ignored. Scales by SoC-span fraction, so 1–4 battery setups behave consistently. Unit tests in `test/refill-confidence.test.js`
### Explainability Tells You Why the Battery Holds Reserve (v3.15.97)
* **The decision reason now explains an overnight reserve hold** — When the refill-reserve floor holds charge back on a slot where the price would normally allow discharging, the explainability panel previously showed only the generic “DP gepland: bewaren”. It now shows a dedicated reason (“
Reserve aangehouden voor morgenochtend — PV-voorspelling onzeker …”) whenever the reserve is the reason discharge is withheld. New branch in `explainability-engine.js`, tests in `test/explainability-refill-reserve.test.js`
### Planning Chart Battery Power No Longer Shows Impossible Values (v3.15.97)
* **The planning table’s `Batt(W)` column is clamped to the hardware charge/discharge limit** — On the leading partial-hour row the per-slot SoC is stepwise (held per DP slot, then jumps), so dividing a full-slot SoC delta by a shorter collapsed group implied a charge power above the physical maximum (e.g. 1602 W on an 800 W unit). The optimizer itself always respects `maxChargePowerW`; this is a display-only clamp so the diagnostic never shows a physically impossible power
### Weak-PV Surplus No Longer Exported Before a Reachable Peak (v3.15.97)
* **A cloudy-afternoon slot with a small PV surplus now charges the battery instead of dumping it to the grid** — Observed live (2026-06-01 14:00): a strong ~2 kW PV surplus was exported (−1.7 kWh to grid) while the battery sat at 57% with room to spare and an evening price peak of €0.52 ahead. Cause: the PV-uncertainty/cloud haircut (`pvCloudFactor ≈ 0.60`) pushed the slot’s `pvCoverage` just under the `pvStrongCoverage` threshold (0.5), blocking the `pvStoreWins` path; simultaneously the next hour was a strong-PV slot, which resets `trickleSuffixMaxPrice` to 0 (the cap assumes that refill saturates the battery, making a later peak unreachable), blocking the `pvTrickle` path. With both blocked the slot fell through to `pvExportWins` and the surplus was exported — even though the uncapped store value (€0.374) beat the price (€0.25) and the battery never saturated (the plan peaked at 85%). `optimization-engine.js` now stores a weak-slot surplus when the battery still has room and the uncapped store value beats the price, treating the later peak as reachable. The trickle cap is unchanged for strong-PV slots, so genuine export-wins cases (a peak that PV truly refills) still export. Regression test `test/dp-pvstrong-cap-export.test.js`
### Planning Chart PV-Charge SoC Projection No Longer Loses Efficiency Twice (v3.15.97)
* **The planning chart projected PV charging too low** — The chart’s SoC projection multiplied the PV-charge step by the round-trip efficiency (`rte ≈ 0.74`), so 1.6 kWh of PV into a 5.376 kWh battery drew as +22% instead of +30% of state-of-charge. Round-trip efficiency belongs in the *value* math (`storeValue = price × rte`), not in the SoC *state*: the battery physically gains the charged kWh. Every other projection path already tracked raw kWh — the grid-charge branch in the same function and the optimizer forward-sim in `optimization-engine.js` — so only the PV-charge branch was inconsistent. Removed the stray `* rte` in `buildPlanningSchedule` (`policy-engine.js`); display-only, no runtime decision effect
### Planning Chart Matches Real Export Decisions (v3.15.97)
* **The planning chart no longer projects the battery filling on slots the optimizer actually exports** — On variable/cloudy days the chart could show the battery charging up to full from PV while the live policy was exporting that surplus to the grid (plan ≠ reality). Cause: the chart’s SoC projection valued storing PV with the *uncapped* maximum future price, while the runtime mapper uses the *trickle-capped* store value — a far evening peak that tomorrow’s PV will refill anyway should not make storing today worthwhile. When a future peak sits beyond a strong-PV refill, the uncapped value over-stated storing and the chart drew a fill that never happened. Both projections (the optimizer forward-sim in `optimization-engine.js` and the re-mapper `_mapActionToHwModeForPlanning` in `policy-engine.js`, which drives the drawn SoC line) now gate PV charging on the same capped *store-beats-export* test the runtime uses: when exporting wins, the slot is shown as `standby` with a flat SoC. Verified live — `export more profitable → standby, no override`, `drift 0.0pp`
### PV Forecast Cap at Inverter Peak (v3.15.97)
* **PV forecast can no longer exceed the system’s physical peak** — On clear days where actual PV ran well above the morning model, the intraday correction ratio (e.g. ×2) multiplied the forecast above `pv_capacity_w`, producing impossible values (e.g. 5.8 kW on a 3.57 kWp system) on the “Batterij Vandaag” and “PV Opwek” charts — and, worse, made the DP over-estimate PV recharge (risking premature discharge stop). The blended/bias/intraday-corrected forecast is now capped at the inverter peak as the final step before the optimizer, the chart forecast line, and the stored hourly forecast consume it. Solcast values are additionally clamped at the source (`solcast-provider.js`), since a misconfigured Solcast resource capacity can report above the physical system limit
### EV Charging Gate (v3.15.94)
* **New flow action `Set EV charging state` (v3.15.94)** — Tell the policy engine when an electric vehicle starts or stops charging. While EV charging is active the battery is forced to `zero_charge_only` (`standby` when SoC ≥ max): the EV draws from grid and PV instead of cycling the home battery, but PV surplus may still top up the battery. The flag auto-clears after 8 hours as a safety net in case the “stop” trigger is missed, and is persisted to settings so it survives app restarts. Implemented as an early-return gate in `_mapPolicyToHwMode` so it overrides discharge for any policy mode (`balanced`, `eco`, `aggressive`, `balanced-dynamic`). Logged as `[MAPPING][EV]` for diagnostics
### Internationalisation (v3.15.94)
* **7 new languages added** — Driver compose, capabilities, flow cards, and locale strings now include German (de), Danish (da), French (fr), Swedish (sv), Norwegian (no), Finnish (fi), and Hungarian (hu)
### UI Text Fix (v3.15.94)
* **“Standby” spelling normalized** — `Stand-by` (with hyphen, including non-breaking hyphen variant) replaced by `Standby` in `driver.settings.compose.json` and `explainability-engine.js`
Connectivity, Memory & Provider Reliability (v3.15.93)
-
TCP ping socket-destroy on error path (v3.15.93) —
tcpPingin bothincludes/legacy/homewizard.jsanddrivers/energy_socket/device.jspreviously closed the socket only onconnectandtimeoutevents, not onerror. While Node usually auto-closes sockets on error, edge cases (e.g. EHOSTUNREACH with retained native references) could accumulate file descriptors over days. Error handler now callssocket.destroy()explicitly -
SHARED_SOCKET_AGENT.maxSockets scales with device count (v3.15.93) — The shared HTTP agent for
energy_socketdevices was hard-capped atmaxSockets: 4. With 15+ devices the agent became a bottleneck: failing devices held slots up to ~17s on the timeout/retry path, starving healthy devices.maxSocketsis now set tomax(4, ceil(deviceCount / 3))on each device init (idempotent — last writer wins). A user with 19 energy sockets now gets 7 slots instead of 4 -
Recovery poller jitter (v3.15.93) — When multiple energy_socket devices go offline simultaneously (e.g. WiFi access-point hiccup), all their 10-second TCP-ping recovery pollers would fire in lockstep, producing a thundering herd on the AP during recovery. Each recovery poller now starts after a random 0-10s delay before its
setIntervalbegins, spreading the load -
EHOSTUNREACH / ENETUNREACH backoff (v3.15.93) — On hard network errors (host unreachable / route down), the device now skips polling for 60 seconds instead of retrying every 10s. The backoff is reset on successful poll or any discovery callback (available, address-changed, last-seen). Saves CPU and log noise when a device is genuinely offline
-
Open-Meteo retry on transient failures (v3.15.93) —
weather-forecaster.jsnow usesfetchWithRetryfor the three Open-Meteo endpoints (ensemble radiation, standard hourly, tilted irradiance). On TIMEOUT or 5xx response the request is retried once after 3s. Open-Meteo overloads at peak times occasionally caused stale weather cache for up to an hour; the retry catches most transient failures -
Xadi price endpoints fetched in parallel (v3.15.93) — The Xadi provider previously fetched
/today,/next24h, and/day/tomorrowsequentially (each with a 10s timeout, worst case ~30s). Now all three are fetched in parallel viaPromise.allSettled, reducing worst case to ~10s. Deduplication viaseenTimestampsSet is preserved -
kWhPrice page-structure-change detection (v3.15.93) — When the kwhprice.eu HTML scraper returned 0 slots, the provider silently returned an empty array — even if the HTML was large (indicating the page loaded but the CSS selector no longer matched). The provider now throws an explicit “page structure may have changed” error when
html.length > 2000and 0 slots are parsed, engaging the stale-cache fallback and surfacing the issue in the logs -
Drop [MEM][socket] init log spam (v3.15.93) — Each
energy_socketdevice wrote two[MEM][socket]heap-stats log lines on init. With 19 devices that’s 38 noise lines per app restart with no operational value. Removed
PV Forecast, Optimizer & Battery Policy Fixes (v3.15.83–v3.15.87)
-
Per-model GTI via solar transposition + KNMI kt bias classification (v3.15.83) — PV forecast accuracy per Open-Meteo model now uses Global Tilted Irradiance (GTI) computed via the Perez transposition model rather than GHI. This ensures the per-model radiation error is evaluated on the same tilted plane as the actual panel yield. Simultaneously, the daily radiation bias factor is now selected based on the KNMI clearness index (kt) rather than Open-Meteo cloud cover fraction — OM systematically over-estimates cloud cover (42% vs 15% measured), causing the wrong bias tier to be selected on partially-cloudy days
-
PV chart data key separated + kt-based bias apply + memory reduction (v3.15.84) — The PV chart now uses a dedicated data key independent of the forecast pipeline, preventing stale forecast values from persisting across recomputes. kt-based bias is applied earlier in the forecast chain so downstream models see the corrected irradiance. Internal forecast buffers reduced to lower heap usage during ensemble fetches
-
Chart midnight rollover fix + ensemble fetch timeout 10→15s (v3.15.85) — The planning chart camera image swapped tomorrow’s chart for today’s after midnight due to a day-boundary comparison error; fixed. The Open-Meteo ensemble fetch timeout was extended from 10s to 15s to reduce spurious timeout failures on slow upstream responses. Battery policy capabilities now expose projected profit, PV forecast, bias factor, and current DP plan summary as Homey capability values
-
Policy: fix policy_enabled permanently stuck after predictive interaction with restart (v3.15.87) — Two related bugs that left
policy_enabled = falseafter HW Slim laden (predictive) ended: (1) Restart DURING predictive:_policyEnabledBeforePredictivewas in-memory only and lost on restart; the restore guard (!== null) skipped the restore, blocking all policy runs until the next restart. Fixed: persist the value to settings at predictive-start; fall back to persisted value (thentrue) when restoring. (2) Restart AFTER predictive ended before restore ran:_isPredictiveModewasfalseon init, so neither the restore branch nor the P1 poll path fired; policy stayed disabled. Fixed: at startup, ifpolicy_enabled_before_predictiveis present in settings and the hardware is no longer in predictive mode, restorepolicy_enabledimmediately. Both paths now trigger an immediate policy check on predictive end instead of waiting up to 15 minutes for the next slot boundary -
Policy: min-price discharge override for DP preserve at night (v3.15.87) — The DP optimizer could choose
preserveat night to protect opportunity value for next-day PV recharge, even when the current price exceeded the user’s configured minimum discharge price. This occurred when the SoC was near the PV absorption cliff: one discharge step would drop SoC below the refillable threshold, so the DP correctly valued the future state but violated the user’s price floor intent. Added a policy-layer override that forcesdischargewhen DP says preserve, price ≥ configured minimum, SoC > min_soc, and no PV is active. Observed: 3-hour discharge gap at SoC 32%, price €0.268–0.281, minimum €0.180 -
Optimizer: smooth isolated preserve islands in discharge sequences (v3.15.86) — A single
preserveslot flanked bydischargeon both sides with a price delta below 1 ct is a DP numerical edge case (floating-point score tie at a local price minimum). Such slots are now overridden todischargein a post-DP smoothing pass; projected SoC is propagated forward accordingly. Observed impact: one 15-min standby at €0.273 between €0.281 and €0.274 discharge slots
PV Forecast — KNMI Ground-Truth & Fixes (v3.15.81–v3.15.82)
-
KNMI station ground-truth for model accuracy (v3.15.81) — PV forecast accuracy tracking now uses independent in-situ radiation measurements from the nearest KNMI automatic weather station (e.g. Cabauw) as the daily actual, instead of Open-Meteo’s own historical data. Open-Meteo used its own archived data as the “actual” reference, creating circular validation that could not detect systematic model bias. KNMI station data is fetched hourly via the EDR API and accumulated into a daily average used as ground-truth in the nightly learning step. Falls back to Open-Meteo if fewer than 4 daylight readings were collected or if no API key is configured. Requires a KNMI EDR API key configured in device settings (register at dataplatform.knmi.nl)
-
NOCT temperature derating for fallback PV forecast (v3.15.81) — The pre-learning fallback PV forecast (used before sufficient yield data has accumulated) now applies a thermal derating factor for high ambient temperatures. Silicon PV panels lose approximately 0.4%/°C above 25°C cell temperature; on hot summer days the flat-PR fallback overpredicted by up to 10%. The correction uses ambient temperature from the Open-Meteo forecast and the standard NOCT model. Panels with a learned yield factor already embed temperature effects empirically — correction applies only to the fallback path
-
P1 meter identify accepts empty response body (v3.15.82) — The P1 meter returns an empty HTTP body on
/api/system/identify; the strict JSON object-type check caused a false “Invalid response format” error. HTTP status code alone is now used to detect failure
PV Forecast — Cloud Uncertainty, Solcast p10 & Per-Model Accuracy (v3.15.80)
-
Solcast p10 cloud-aware selection (v3.15.80) — When Solcast’s
pv_estimate(p50) exceeds the Open-Meteo NWP forecast by ≥10% for a given slot, the optimizer switches topv_estimate10(pessimistic 10th-percentile) for that slot. On clear days both models agree and p50 is used; on overcast days where Solcast’s satellite/ML lags a weather front, OM sees the cloud cover first and the p10 switch prevents over-reliance on PV that won’t arrive. Logged asp10=Xslotsper day in[PV blend] -
Cloud uncertainty discount in DP (v3.15.80) — When cloud cover exceeds 70%,
pvCoveragein the DP forward and backward passes is discounted by up to 40% (factor 0.6–1.0). Prevents the optimizer from discharging at break-even prices early in the day by relying on uncertain PV recharge that may not materialise on overcast days. Shown in the PV bias line as×0.87 (pv-onzekerheid)and logged as[PV cloud uncertainty] -
Per-model OM radiation curves in PV accuracy chart (v3.15.80) — The PV forecast accuracy section now shows a second chart with individual Open-Meteo model curves (Météo-France ARPEGE, GFS, ICON, KNMI) alongside actual measured production. Per-model Watt estimates are recorded per 15-min accuracy sample and stored in
pv_predictions. Per-model EMA accuracy scores are shown as pills once a full day of data has accumulated -
Météo-France ARPEGE Europe replaces ECMWF IFS04 in ensemble blend (v3.15.80) — ECMWF IFS04 returned null
shortwave_radiationfor all hourly slots via the Open-Meteo ensemble endpoint and contributed nothing to the blend or accuracy tracking. Replaced with Météo-France ARPEGE Europe (10 km, West-European coverage), which provides full hourly radiation data. Accuracy prior set to 0.82
Battery Policy — Grid Top-Up Timing (v3.15.79)
- Low-SoC top-up deferred to cheapest upcoming slot (v3.15.79) —
lowSocGridTopUpnow only fires when the current price is the minimum price in the next 8 hours. Previously, the top-up could trigger at any price belowdynamicMaxChargePrice, causing premature grid charging when a cheaper DP-planned slot existed shortly ahead. With two batteries (1600 W charge rate), charging at a sub-optimal price erases the efficiency margin entirely
Diagnostics & PV Accuracy (v3.15.78)
-
Policy run debug: dynamicMaxChargePrice + lowSocGridTopUp (v3.15.78) — The
policy_last_run_debugsnapshot now storesdynamicMaxChargePrice(the effective charge price ceiling at the time of the run) andlowSocGridTopUp(whether the low-SoC grid top-up path was triggered). Both are shown in the diagnostic output. Previously, post-hoc diagnosis of unexpectedto_fulldecisions was impossible because only the current dynamic max was available, not the value from the actual run -
PV net surplus accuracy tracking (v3.15.78) — Learning engine now tracks predicted vs actual net PV surplus (PV minus consumption during solar hours). An EMA correction factor
pv_net_surplus_factor[0.4–1.1] adjusts the terminal value calculation in the DP optimizer so next-day battery dispatch is planned on realistic rather than idealised surplus -
Optimizer terminal value uses adjusted PV tomorrow (v3.15.78) —
terminalPvKwhTomorrowpasses the surplus-accuracy-corrected PV estimate to the DP forward pass, preventing the optimizer from over-discharging today when tomorrow’s PV was historically over-predicted
Battery Policy — Night Behaviour Fixes (v3.15.77)
-
Sunset guard broken after midnight weather refresh (v3.15.77) — After midnight, a weather cache refresh set
todaySunsetto the current day’s future sunset timestamp. Because the current time (e.g. 00:48 UTC) was before that sunset (19:30 UTC),_afterSunsetevaluated tofalse, letting stale PV estimates (EMA still decaying) pass the guard and mappreservetozero_charge_onlyinstead ofstandby. Fix:_afterSunsetis now alsotruewhen the current time is beforetodaySunrise, covering the entire pre-dawn window regardless of which day’s sunset is cached -
SoC staleness at policy run (v3.15.77) —
battery_group_average_socis updated by a 60-second interval; when the policy engine ran between updates it used a stale SoC, causing the DP to plan from the wrong starting point. Fix:_updateBatteryGroup()is now called immediately before_getBatteryState()on every policy run, refreshing the capability from live WS data -
Event history battery power from WS (v3.15.77) —
battWin event history entries now reads_lastPowerdirectly from the plugin_battery WebSocket (seconds-fresh) instead of the 30s-stalebattery_group_power_wcapability. Falls back to the capability when no plugin_battery device is found -
BMS calibration detection (v3.15.77) — Battery management systems occasionally run a calibration cycle: battery charges at full power but reports SoC=0% and power=0W. This caused event history entries to look like unexplained grid spikes. Policy engine now detects this signature (
soc=0%,battW≈0,gridW>700W, nighttime, no charge/discharge mode commanded) and marks the entryexception: bms_calibration
Battery Policy — PV Forecast Accuracy (v3.15.69–v3.15.76)
-
Multi-source rain correction + ensemble averaging (v3.15.74) — Buienradar now samples 5 geographic points (center + N/S/E/W at ±0.05°) for more representative local precipitation. PV forecast now averages 4 Open-Meteo radiation models (ECMWF, GFS, ICON, KNMI Harmonie), with spread-adjusted weighting to reduce outlier influence
-
3-class daily PV bias stratification by cloud cover (v3.15.73) — Daily PV bias factor is now derived from three cloud-cover classes (clear/partial/overcast) rather than a single global correction, improving accuracy for mixed-sky days
-
Intraday PV scaling with winsorised ratios + CV dampening (v3.15.72) — Intraday reoptimisation scales the PV forecast to match morning actuals. Ratio samples are now winsorised (outlier-clipped) and dampened by their coefficient of variation, preventing a single cloudy-then-clear hour from over-correcting the full-day forecast
-
Clear-sky forecast floor (v3.15.63) — Intraday reopt now enforces a clear-sky model as a ceiling on per-slot PV corrections; slots cannot be scaled above theoretical maximum irradiance
Earlier Updates (v3.13–v3.15.58)
-
v3.15.40 — Negative price charging (
to_fullwhen price < 0);preserve→standbybij negatieve prijzen; slot0RemainingFrac fix; P1 firmware batteryPower=0 correctie -
v3.15.37 — Yield-factor normalisation; Solcast moved to
_updateWeather; cycle recorded on discharge→charge transition; predictive modes in camera -
v3.15.35–36 — Startup crash fix (serialised settings write queue); SDM polling spread; memory log per device type
-
v3.15.10+ — DP-primary refactor (sole decision-maker); PV accuracy fix; intraday PV scaling; explainability DP-reasons; PV chart fix; weather attenuation; DP terminal value; per-slot confidence margin; profit tracking; SoC forward simulation
-
v3.15.10 — pvCoverage net surplus; pvKwhTomorrow net-absorbable; dp.fill guard non-PV only; three-tier discharge floor; linear PV interpolation; Solcast integration; self-sufficiency tracking; consumption margin; PV camera image
-
v3.14.24–3.14.29 — Discharge SoC projection consumption-aware; discharge floor consistent DP/display; opportunistic discharge; pre-peak urgent charging; lat/lon weather; forecast blending; PV score rebalanced
-
v3.14.19 — Solar yield learning; weekend/weekday consumption patterns; battery cycle cost; pure DP kernel
-
v3.14.0 — 15-min price granularity; optimizer on 96 slots; explainability color coding
-
v3.13.68 — OptimizationEngine (DP scheduler); WebSocket throttle configurable
-
v3.13.58 — Baseload battery correction; RTE learning fixes; WebSocket performance; tiered updates
-
v3.13.49 — Active mode capability; dynamic pricing v2; WebSocket stability; CPU/performance overhaul
-
v3.13.37 — PV detection sticky state; grid charging during PV fix
-
v3.13.28 — Manual IP override; battery-aware baseload; weather-aware discharge; dynamic sunrise/sunset
-
v3.13.14 — Battery Policy driver; ML learning engine; cloud P1/water meter support; trigger cards