Releases: hass-energy/haeo
v0.4.0rc5
HAEO v0.4.0rc5
Pre-release aligned with main after merging the version bump PR.
Includes manifest/pyproject/uv.lock version 0.4.0rc5.
v0.4.0rc4
What's Changed
- Make policy pricing reactively update without rebuilding network by @TrentHouliston in #408
- Deep copy subentry data and add noqa reasons by @TrentHouliston in #410
- Improve forecast card responsive layout and controls by @TrentHouliston in #411
- Show forecast card paired power limits by @TrentHouliston in #412
- Update release version command by @TrentHouliston in #413
Full Changelog: v0.4.0rc3...v0.4.0rc4
v0.4.0rc3
What's Changed
- Add HAEO forecast card with modular JSX rendering by @TrentHouliston in #352
- Fix policy and element value updates not applying by @TrentHouliston in #406
- Bump version to 0.4.0rc3 by @TrentHouliston in #407
Full Changelog: v0.4.0rc2...v0.4.0rc3
v0.4.0rc2
What's Changed
- Publish versioned documentation site by @TrentHouliston in #390
- Fix policy pricing placement via sink-side minimum s-t cut by @TrentHouliston in #393
- Document min-cut pricing placement and VLAN-to-all-sinks reachability by @TrentHouliston in #394
- Fix diagnostic serialization by @BrendanAnnable in #396
- Update diagnostic schema and add version by @BrendanAnnable in #397
- Migrate legacy early-charge-incentive default through to a real policy by @TrentHouliston in #399
- Absorb VLAN tags at sinks and exclude edges into a VLAN's own source by @TrentHouliston in #401
- Add snapshot dev tool by @BrendanAnnable in #403
- Fix migration duplicate elements by @BrendanAnnable in #404
- Update version to v0.4.0rc2 by @BrendanAnnable in #405
Full Changelog: v0.4.0rc1...v0.4.0rc2
v0.4.0rc1
HAEO v0.4.0rc1
Pre-release — this is a beta for testing before the stable v0.4.0 release.
Caution
Back up your Home Assistant configuration before upgrading. This release includes a one-way schema migration (v1.3) that restructures your element configuration data. Once migrated, you cannot downgrade back to v0.3.x without restoring a backup.
What could go wrong:
- Battery discharge wear costs and charge incentives are moved into a new Policies element. If the migration misinterprets a pricing value (particularly entity-based charge incentives), the optimizer may treat an incentive as a cost or vice versa.
- Connections are restructured from bidirectional to unidirectional. If a bidirectional connection had asymmetric settings, the split may not perfectly preserve both directions.
- All config values change storage format (raw values → typed objects). External tools or automations that read HAEO config entry data directly will break.
- Entity unique IDs are stabilized during migration. Duplicate entities with old section-prefixed IDs are cleaned up automatically, but any external references to old entity IDs may need updating.
Recommended steps: Take a full Home Assistant backup, upgrade, then check Settings → Devices & Services → HAEO to verify your elements and the new Policies subentry look correct. Check the Home Assistant log for any migration warnings.
Highlights
- ⚡ Power policies — define per-source pricing rules so the optimizer knows that solar exports earn feed-in tariffs while battery exports incur wear costs
- 🎯 Deterministic optimization — new calibrated multiobjective solver eliminates random tie-breaking, giving consistent dispatch schedules every run
- 🔋 Sheddable loads & battery salvage value — loads can now be curtailed when economically justified, and batteries value their remaining stored energy at the horizon end
- 🌍 Automatic currency detection — HAEO reads your price sensor units and displays the correct currency symbol without configuration
⚠️ Breaking Changes
Pricing moves to power policies
Battery discharge wear costs, charge incentives, and solar production costs have moved from individual element configuration into the new Power Policy element. Existing configurations are migrated automatically (v1.3 migration), but you should verify your policies after upgrading:
- Open HAEO settings → you should see a new "Policies" subentry
- Confirm the migrated rules match your previous pricing
- Battery charge incentive prices are negated during migration (positive stored value → negative policy price) to preserve the original incentive semantics
If you had entity-based (non-constant) charge incentive prices, check the Home Assistant log for a migration warning — you may need to create a negating template sensor.
Entity unique IDs stabilized
Entity unique IDs have been normalized to remove section prefixes introduced in earlier versions. Duplicates are cleaned up automatically during migration. If you reference HAEO entity IDs in automations or dashboards, check that they still resolve after upgrading.
User-Facing Changes
New Features
- Power policy element — define directional pricing rules with source/target matching and wildcard support (#369)
- Sheddable loads — mark loads as curtailable so the optimizer can shed them when cost-effective (#303)
- Battery salvage value — assign a terminal value ($/kWh) to stored energy, discouraging unnecessary end-of-horizon discharge (#302)
- Nordpool integration — automatic extraction of energy pricing from Nordpool
raw_today/raw_tomorrowsensor attributes (#367) - Deterministic optimization — three solver modes (lexicographic, blended, calibrated) for consistent dispatch schedules every run (#301)
- Last run timestamp — optimization status sensor now includes a
last_runattribute showing when the optimizer last completed (#381)
Configuration Improvements
- Grouped UI sections — config flows now organize fields into collapsible sections for easier navigation (#266)
- Automatic currency symbol detection — reads currency from your price sensor units; falls back to HA config currency (#368)
- Policy source/target filtering — policy config flow only shows elements that can actually source or sink power (e.g., solar appears as source only, load as target only) (#380)
- Policy rule context in sensors — policy price input numbers now expose sibling fields (source, target, rule name) in state attributes (#377)
Bug Fixes
- Fix optimizer crash when optional efficiency field is unset or cleared (#360)
- Fix battery power limits and efficiency segment ordering (#297)
- Fix network period tracking across optimization runs (#295)
- Fix recorder forecast filtering dropping valid entries (#310)
- Fix participant name resolution after Home Assistant restart — deserialized strings are now converted to ElementType (#373)
- Fix optimizer re-run race condition when updating subentry values concurrently (#375)
- Fix battery charge incentive price sign in migration (#376)
- Fix policy compilation blocking unpolicied flows — changed from default-deny to default-allow so flows without explicit policies pass freely (#379)
- Fix policy endpoint restore values rendering as
[object Object]in the UI (#383, #384) - Fix policy edit flow not preserving existing source/target when fields are omitted (#382)
- Require explicit
enabledandpriceon policy rules; backfill missing fields during migration (#385) - Fix policy performance: directed reachability graph and objective-level calibration eliminate 10-12x slowdown when policies are enabled (#387)
- Stabilize entity unique IDs across config migrations; remove duplicate section-prefixed entities (#388)
- Remove null values from horizon sensor attributes (#348)
Advanced User Changes
Connection model is now unidirectional
Connections are now explicitly directional (source → target). Bidirectional connections use two separate connection entries. Existing bidirectional connections are migrated automatically, but verify that import/export paths are configured correctly after upgrading.
Configuration data format change
Element configuration now stores values as typed objects ({"type": "entity", "value": [...]} / {"type": "constant", "value": 0.5}) instead of raw values. This is migrated automatically — no action required — but any external tools reading config entry data directly will need updating.
Bug Fixes
- Fix connection segment ordering for directional flows (#299)
Developer-Facing Changes
Developer Highlights
The entire optimization engine has been extracted into a standalone core/ package with zero Home Assistant dependencies. This is the largest architectural change since HAEO's initial release — 20+ PRs restructured the codebase into clean layers that can be tested, debugged, and eventually distributed independently of Home Assistant.
Architecture
- Core package extraction — model, schema, adapters, and data loading moved to
custom_components/haeo/core/with enforced import boundaries (#312–#340) - Three-layer architecture — device layer (elements/) → adapter layer (core/adapters/) → model layer (core/model/) with clear data flow
- Import linter — enforces that
core/has no Home Assistant imports (#320) - Unidirectional connections with functional segment composition — segments compose as expression chains rather than using auxiliary linking variables (#364)
- Tag infrastructure — power flow tagging system enables per-source tracking through the network graph (#370)
- Policy compilation pipeline — 8-step compilation from policy rules to tagged connection costs: flow enumeration → signature computation → VLAN assignment → directed reachability analysis → connection tagging → source tags → access lists → pricing injection; default-allow model for unpolicied flows (#369, #379, #387)
- Element capability metadata —
can_source/can_sinkon element adapters for filtering policy participants (#380) - Calibration by objective — multiobjective calibration now compares primary objective cost instead of per-variable values, avoiding false mismatches from degenerate tag-split variables (#387)
- Consolidated migration — all migration work collapsed into a single v1.3 step with stable entity unique ID normalization and duplicate cleanup (#388)
- OptimizationContext — immutable frozen dataclass capturing all optimization inputs for reproducible diagnostics (#291, #305)
- StateMachine protocol — minimal interface isolating model from Home Assistant state access (#314)
- ElementType enum — single StrEnum for all element types replacing string literals (#319)
Schema/API Changes
- Object-based config storage — values stored as discriminated TypedDicts (
EntityValue,ConstantValue,NoneValue) with type predicates (#296) - ListFieldHints — generic infrastructure for declaring input fields within list-typed config fields (#371)
- Config loader — centralized resolution of entity/constant/none values from config data (#338, #339, #342)
- Enriched schemas — schemas now carry enough metadata to eliminate adapter
inputs()methods (#322) - Schema migrations formalized — structured step pipeline with v0.3.3 fixture regression tests (#359)
- Scalar input support — data loader handles non-forecast numeric inputs for fields like salvage value (#302)
Testing & Documentation
v0.3.3
v0.3.3 Release Notes
This is a hotfix release fixing the "Record forecast data" hub setting. Previously forecast data was still be recorded (ignoring the setting), causing the recorder database to grow quickly in size (often by multiple GBs).
HA will naturally purge these entries from the database over time (10 days is the default retention time), although you can force it using the recorder.purge_entites service action if required.
Contributors
Full Changelog
- Fix recorder forecast filtering by @BrendanAnnable in #310
Full Changelog: v0.3.2...v0.3.3
v0.3.2
v0.3.2 Release Notes
Highlights
- 🔋 Fixed battery power limits — Efficiency losses are now correctly applied after power limits, fixing battery power limits
- 🕐 Fixed period duration updates — Optimization periods now correctly update when tier boundaries change
Contributors
Full Changelog
- Fix battery power limits and efficiency ordering by @BrendanAnnable in #297
- Fix network period tracking by @BrendanAnnable in #295
Full Changelog: v0.3.1...v0.3.2
v0.3.1
🧹 Device removal now correctly detects stale devices
What's Changed
- Fix stale device cleanup by @TrentHouliston in #286
Full Changelog: v0.3.0...v0.3.1
v0.3.0
v0.3.0 Release Notes
Highlights
- ⚡ Control when optimization runs — New auto-optimize switch lets you pause automatic optimization and trigger it manually via the
haeo.optimizeservice - 🎨 Beautiful new entity selector — Configurable entities now use a sleek choose selector for a much cleaner configuration experience
- 🔋 Simplified battery modeling — Battery partitions replaced with streamlined SOC-based pricing for cleaner entity structure
- 🕐 Better forecast alignment — Optimization tiers now align with clock boundaries (e.g. every 5, 30, 60 minutes) for more intuitive scheduling
- 🔧 Enhanced debugging tools — New diagnostics service with time-travel capability for troubleshooting optimization behavior
- 💾 Smaller database footprint — Forecast history is no longer recorded by default, significantly reducing recorder database size
- 🔄 Fixed price interpolation — New interpolation mode option stops prices from being incorrectly interpolated from Amber Express
- 🐛 Fixed occasional infeasibility — Deferred network updates eliminate a race condition that could cause optimization to fail
⚠️ Breaking Changes
Battery Entity Structure Changed (#265)
Battery "balance" section devices have been removed. If you have automations or dashboards referencing battery balance partition entities, you'll need to update them.
Migration: Remove any references to battery balance partition entities. The battery now uses a single, simplified entity structure with SOC-based pricing.
Update Interval Configuration Removed (#252)
The update interval configuration option has been removed as it was no longer used. HAEO now uses event-driven optimization triggered by input changes.
Migration: No action required — this setting was not functional in recent versions.
Optimization Tiers Now Align with Clock Boundaries (#236)
Optimization tiers now align with clock boundaries (e.g. 5-minute marks) rather than using fixed-size intervals from an arbitrary start time. This provides more intuitive scheduling but changes when tier boundaries occur.
Migration: No action required for most users. If you had automations that relied on exact tier timing, they may need adjustment.
User-Facing Changes
New Features
- Auto-optimize switch (#254) — Toggle automatic optimization on/off from the UI. When disabled, use the new
haeo.optimizeservice to trigger optimization manually or via automations - Diagnostics service (#247) — New service for debugging optimization behavior with detailed diagnostic output
- Time-travel diagnostics (#250) — Run diagnostics at a specific point in time to debug historical optimization decisions
- Record forecast option (#274) — Configure whether to record forecast data to the recorder database
- Interpolation mode (#275) — New interpolation mode option for the HAEO extractor for compatiblity with Amber Express
Improvements
- Clock-aligned timesteps (#236) — Optimization periods now align with clock boundaries for more predictable scheduling
- More impatient setup (#276) — Reduced setup timeout from 30s to 5s for quicker startup
Developer-Facing Changes
Developer Highlights
- Composable connection architecture (#227) — Connections are now built from composable components (efficiency, pricing, power limits), enabling flexible combinations without exponential complexity
- Declarative input entities (#239) — Input entities are now defined by configuration, making the system more maintainable and extensible
Architecture
- Deferred network updates (#277) — Element updates are now batched and applied at optimization time rather than immediately, reducing unnecessary processing
- Simplified data pipeline (#240, #242) — Removed legacy
loadfunction andbuild_config_datapipeline - NumPy array storage (#243) — Element config series now stored as numpy arrays for better performance
- Improved type safety (#230) — Model layer calls are now fully typed
Testing & Documentation
- Timezone-aware scenarios (#251) — Scenario tests now run in specified timezone for consistent results
- Updated battery documentation — Docs updated to reflect new SOC-based pricing model
Contributors
Full Changelog
- Type the calls to the model layer to improve type safety by @TrentHouliston in #230
- Add buy me a coffee links by @TrentHouliston in #232
- Replace configurable entity with choose selector by @BrendanAnnable in #226
- Make the input entities be defined by configuration by @TrentHouliston in #239
- Remove the load function by @TrentHouliston in #240
- Remove build_config_data pipeline by @TrentHouliston in #242
- Store element config series as numpy arrays by @TrentHouliston in #243
- Align timesteps with clock boundaries by @BrendanAnnable in #236
- Fix amber prices in dev by @BrendanAnnable in #246
- Add diagnostics service by @BrendanAnnable in #247
- Run scenarios in given timezone by @BrendanAnnable in #251
- Add time travelling to diagnostics service by @BrendanAnnable in #250
- Remove update interval configuration by @BrendanAnnable in #252
- Change connections to be made of composable components by @TrentHouliston in #227
- Add auto optimize switch by @BrendanAnnable in #254
- Replace battery partitions with SOC pricing by @TrentHouliston in #265
- Bump the github-actions group across 1 directory with 3 updates by @dependabot[bot] in #263
- Add record forecast config option by @BrendanAnnable in #274
- Add interpolation mode by @BrendanAnnable in #275
- Update setup timeout to 5 by @BrendanAnnable in #276
- Defer network updates until optimization time by @BrendanAnnable in #277
Full Changelog: v0.2.1...v0.3.0rc1
v0.3.0rc1
v0.3.0rc1 Release Notes
Highlights
- ⚡ Control when optimization runs — New auto-optimize switch lets you pause automatic optimization and trigger it manually via the
haeo.optimizeservice - 🎨 Beautiful new entity selector — Configurable entities now use a sleek choose selector for a much cleaner configuration experience
- 🔋 Simplified battery modeling — Battery partitions replaced with streamlined SOC-based pricing for cleaner entity structure
- 🕐 Better forecast alignment — Optimization tiers now align with clock boundaries (e.g. every 5 minutes) for more intuitive scheduling
- 🔧 Enhanced debugging tools — New diagnostics service with time-travel capability for troubleshooting optimization behavior
- 💾 Smaller database footprint — Forecast history is no longer recorded by default, significantly reducing recorder database size
⚠️ Breaking Changes
Battery Entity Structure Changed (#265)
Battery "balance" section devices have been removed. If you have automations or dashboards referencing battery balance partition entities, you'll need to update them.
Migration: Remove any references to battery balance partition entities. The battery now uses a single, simplified entity structure with SOC-based pricing.
Update Interval Configuration Removed (#252)
The update interval configuration option has been removed as it was no longer used. HAEO now uses event-driven optimization triggered by input changes.
Migration: No action required — this setting was not functional in recent versions.
Optimization Tiers Now Align with Clock Boundaries (#236)
Optimization tiers now align with clock boundaries (e.g. 5-minute marks) rather than using fixed-size intervals from an arbitrary start time. This provides more intuitive scheduling but changes when tier boundaries occur.
Migration: No action required for most users. If you had automations that relied on exact tier timing, they may need adjustment.
User-Facing Changes
New Features
- Auto-optimize switch (#254) — Toggle automatic optimization on/off from the UI. When disabled, use the new
haeo.optimizeservice to trigger optimization manually or via automations - Diagnostics service (#247) — New service for debugging optimization behavior with detailed diagnostic output
- Time-travel diagnostics (#250) — Run diagnostics at a specific point in time to debug historical optimization decisions
- Record forecast option (#274) — Configure whether to record forecast data to the recorder database
- Interpolation mode (#275) — New interpolation mode option for the HAEO extractor for compatiblity with Amber Express
Improvements
- Clock-aligned timesteps (#236) — Optimization periods now align with clock boundaries for more predictable scheduling
- More impatient setup (#276) — Reduced setup timeout from 30s to 5s for quicker startup
Developer-Facing Changes
Developer Highlights
- Composable connection architecture (#227) — Connections are now built from composable components (efficiency, pricing, power limits), enabling flexible combinations without exponential complexity
- Declarative input entities (#239) — Input entities are now defined by configuration, making the system more maintainable and extensible
Architecture
- Deferred network updates (#277) — Element updates are now batched and applied at optimization time rather than immediately, reducing unnecessary processing
- Simplified data pipeline (#240, #242) — Removed legacy
loadfunction andbuild_config_datapipeline - NumPy array storage (#243) — Element config series now stored as numpy arrays for better performance
- Improved type safety (#230) — Model layer calls are now fully typed
Testing & Documentation
- Timezone-aware scenarios (#251) — Scenario tests now run in specified timezone for consistent results
- Updated battery documentation — Docs updated to reflect new SOC-based pricing model
Contributors
Full Changelog
- Type the calls to the model layer to improve type safety by @TrentHouliston in #230
- Add buy me a coffee links by @TrentHouliston in #232
- Replace configurable entity with choose selector by @BrendanAnnable in #226
- Make the input entities be defined by configuration by @TrentHouliston in #239
- Remove the load function by @TrentHouliston in #240
- Remove build_config_data pipeline by @TrentHouliston in #242
- Store element config series as numpy arrays by @TrentHouliston in #243
- Align timesteps with clock boundaries by @BrendanAnnable in #236
- Fix amber prices in dev by @BrendanAnnable in #246
- Add diagnostics service by @BrendanAnnable in #247
- Run scenarios in given timezone by @BrendanAnnable in #251
- Add time travelling to diagnostics service by @BrendanAnnable in #250
- Remove update interval configuration by @BrendanAnnable in #252
- Change connections to be made of composable components by @TrentHouliston in #227
- Add auto optimize switch by @BrendanAnnable in #254
- Replace battery partitions with SOC pricing by @TrentHouliston in #265
- Bump the github-actions group across 1 directory with 3 updates by @dependabot[bot] in #263
- Add record forecast config option by @BrendanAnnable in #274
- Add interpolation mode by @BrendanAnnable in #275
- Update setup timeout to 5 by @BrendanAnnable in #276
- Defer network updates until optimization time by @BrendanAnnable in #277
Full Changelog: v0.2.1...v0.3.0rc1