Understanding Optimization Results¶
This guide explains how to interpret HAEO's optimization results and use them effectively.
Optimization Sensors¶
HAEO creates three main network sensors:
Optimization Cost¶
Entity ID: sensor.{network_name}_optimization_cost
Total cost over the optimization horizon in dollars.
- Lower is better: HAEO minimizes this value
- Includes: Grid import/export costs, configured SOC pricing costs, connection transfer costs
- Unit: $ (or your configured currency)
Lexicographic ordering
When multiple schedules share the same primary cost, HAEO applies a secondary time-preference objective. This ordering favors earlier energy transfers without changing the reported optimization cost.
Optimization Status¶
Entity ID: sensor.{network_name}_optimization_status
Current optimization state:
success: Optimization completed successfullyfailed: Optimization failed (infeasible constraints, solver error, or timeout)pending: Optimization is currently running or has not started yet
When status is failed, check the Home Assistant logs for detailed error messages explaining the cause.
Optimization Duration¶
Entity ID: sensor.{network_name}_optimization_duration
Time taken to solve the optimization in seconds. If this value climbs higher than you expect, adjust the interval tiers or simplify the network. Review the custom tier guidance before changing that value.
Element Sensors¶
Each configured element creates optimization result sensors. The specific sensors depend on the element type—see each element's documentation for complete details on their outputs.
Sensor Structure¶
All HAEO sensors follow a consistent structure:
Current state: The sensor's state shows the optimal value for the current time step.
Forecast attributes: Each sensor includes a forecast attribute containing future timestamped values across your optimization horizon.
Shadow Price Sensors¶
Shadow price sensors publish the marginal value of key constraints over the optimization horizon. They translate physical limits into dollar-per-kilowatt-hour signals that explain the optimizer's dispatch choices.
Available sensors include:
- Nodes:
sensor.{node_name}_power_balancereports the local spot price for energy at each node. - Batteries:
sensor.{battery_name}_power_balance,sensor.{battery_name}_soc_min,sensor.{battery_name}_soc_max,sensor.{battery_name}_energy_in_flow, andsensor.{battery_name}_energy_out_flowquantify the value of stored energy, SOC bounds, and charge/discharge headroom. - Grid:
sensor.{grid_name}_power_max_import_priceandsensor.{grid_name}_power_max_export_priceindicate when import or export limits restrict the optimization. - Inverter:
sensor.{inverter_name}_max_power_dc_to_ac_priceandsensor.{inverter_name}_max_power_ac_to_dc_priceappear when the inverter's per-direction caps are binding. - Load:
sensor.{load_name}_forecast_limit_priceexposes the marginal value of serving this load. - Solar:
sensor.{pv_name}_forecast_limitshows when extra solar output would reduce total cost.
All shadow-price sensors are reported in $/kWh so they sit on the same axis as tariffs and other energy-priced quantities.
Each shadow price sensor mirrors the standard forecast attribute layout so you can inspect future periods in dashboards and automations. Review Shadow Prices for detailed interpretation guidance.
Understanding Forecast Attributes¶
All sensors include forecast attributes with future values:
attributes:
forecast:
'2025-10-11T12:00:00+00:00': 1.23
'2025-10-11T12:05:00+00:00': 1.17
'2025-10-11T12:10:00+00:00': 1.34
# ... more timestamped values
Use these in automations or dashboards to visualize the optimal schedule.
Using Results in Automations¶
Example: Control Battery Based on Optimization¶
automation:
- alias: Follow HAEO Battery Charge Schedule
trigger:
- platform: state
entity_id: sensor.main_battery_power_charge
condition:
- condition: template
value_template: "{{ states('sensor.main_battery_power_charge') | float > 0
}}"
action:
- service: battery.set_charge_power
data:
power: "{{ states('sensor.main_battery_power_charge') | float }}"
- alias: Follow HAEO Battery Discharge Schedule
trigger:
- platform: state
entity_id: sensor.main_battery_power_discharge
condition:
- condition: template
value_template: "{{ states('sensor.main_battery_power_discharge') | float
> 0 }}"
action:
- service: battery.set_discharge_power
data:
power: "{{ states('sensor.main_battery_power_discharge') | float }}"
Note: Battery elements create separate sensors for charging (power_charge) and discharging (power_discharge).
See the battery documentation for complete details.
Performance Considerations¶
Optimization Duration¶
Monitor the optimization duration sensor to keep solve times reasonable (typically under 10 seconds).
If optimization takes too long:
- Adjust interval tiers: Reduce tier 4 count or increase tier durations for faster solving (see custom tier guidance)
- Increase tier durations: Fewer time steps reduce problem size
- Simplify network: Remove unnecessary elements or connections
- Check configuration: Verify all sensors are available and providing valid data
Update Frequency¶
HAEO re-optimizes periodically. Balance:
- More frequent: Better response to changes, higher CPU usage
- Less frequent: Lower CPU usage, may miss price changes
Interpreting Cost¶
The optimization cost represents the total forecasted cost over the full horizon, not just the immediate step. Track changes in this value when you adjust configuration parameters to confirm the optimiser is producing the expected behaviour.
Next steps¶
Explore these guides to act on the optimization outputs.
-
Review a complete example
See how the optimization outputs drive real-world decisions.
-
Build automations from the results
Turn recommended power schedules into actionable automations.
-
Monitor data updates
Understand how new sensor data triggers optimizations.
-
Mathematical Modeling
Understand the optimization formulation.
-
Troubleshooting
Common issues and solutions.