Architecture¶
HAEO follows Home Assistant integration patterns with specialized optimization components. This guide focuses on HAEO-specific architecture. For Home Assistant fundamentals, see the Home Assistant developer documentation.
Layered Architecture¶
HAEO separates user configuration from mathematical modeling through two distinct layers:
Device Layer: User-configured elements (Battery, Grid, Solar, Load, Node, Connection) that integrate with Home Assistant sensors and present user-friendly outputs.
Model Layer: Mathematical building blocks that form the linear programming problem.
The Adapter Layer transforms between these layers, enabling composition where a single Device Layer element creates multiple Model Layer elements and devices.
graph LR
subgraph "Device Layer"
Config[User Configuration]
end
subgraph "Adapter Layer"
Adapt[Element Adapters]
end
subgraph "Model Layer"
Model[LP Model]
end
subgraph "Output"
Sensors[HA Sensors]
end
Config --> Adapt
Adapt --> Model
Model -->|optimize| Adapt
Adapt --> Sensors
See Modeling Documentation for detailed layer descriptions.
System Overview¶
graph LR
Sensors[External Sensors] --> IE[Input Entities]
IE --> Coord[Coordinator]
Coord --> Model[Network Model]
Model --> Sensors2[Output Sensors]
The system uses a two-phase platform setup:
- Input phase: HorizonManager created, then Input Platforms (Number, Switch) load and expose configuration data
- Output phase: Coordinator reads from input entities, runs optimization, and Output Platforms (Sensor) display results
Core Components¶
Config Flow (config_flow.py, flows/)¶
User-facing configuration via the Home Assistant UI. The hub flow creates the main entry and exposes additional flows so users can add and manage elements without leaving the standard interface.
See the Home Assistant documentation for the underlying patterns:
HorizonManager (inputs/horizon_manager.py)¶
Manages synchronized forecast time windows for all input entities. Created early in setup before any entity platforms load. Computes period boundaries from tier configuration and notifies subscribers when the horizon advances.
See the Horizon Manager guide for details.
Input Entities (inputs/)¶
Intermediate layer between external sensors and the optimization model. Number and Switch entities load, transform, and expose configuration values with forecast attributes. Operate in two modes: EDITABLE (user-configurable constants) or DRIVEN (values from external sensors).
See the Input Entities guide for details.
Coordinator (coordinator/)¶
Event-driven manager that reads pre-loaded data from input entities, builds the network, runs optimization, and distributes results. Each hub entry creates one coordinator instance.
The coordinator is organized as a module in coordinator/:
coordinator/coordinator.py: Main coordinator class and optimization cyclecoordinator/network.py: Network building functions (create_network(),update_element())
See the DataUpdateCoordinator documentation for the base pattern.
HAEO's coordinator reads from runtime_data.inputs, assembles the optimization network, runs the optimizer in an executor, and pushes the results back to sensor entities.
It triggers optimization on input entity state changes or horizon boundary crossings.
See the Coordinator guide for event-driven update patterns.
Data loaders (data/)¶
Data loaders translate Home Assistant sensor data into time series aligned with the optimization horizon. Input entities call loaders to extract, combine, and fuse forecast data from external sensors. Loaders also validate sensor availability during the config flow. Keep new loaders focused on a single responsibility and reuse the shared parser utilities where possible.
See the Data Loading guide for the extraction pipeline.
Network Builder¶
Creates optimization model from config:
- Instantiates element objects (Battery, Grid, etc.)
- Creates Connection objects
- Builds Network container
- Validates structure
Network Model (model/)¶
LP representation using HiGHS solver:
- Element: Base class with declarative constraint and cost specification
- Network: Container that aggregates element contributions and runs optimization
Model elements are organized in model/elements/ subdirectory.
Elements declare their constraints and costs using decorators, and the network automatically aggregates them.
See Modeling Documentation for mathematical formulations and element types.
Optimization¶
Uses the HiGHS linear programming solver directly via the highspy Python bindings to solve the energy optimization problem.
Minimizes cost while respecting all constraints, returning optimal cost and decision variable values.
Elements use decorators to declare constraints and costs, which the network automatically aggregates. When parameters update (like forecast changes), only affected constraints are rebuilt (warm start optimization).
Sensors (sensors/)¶
Sensor entities expose optimization outputs through standard Home Assistant constructs. Separate modules handle network-level metrics and per-element values, and every sensor carries a forecast attribute so downstream automations can look ahead.
See the Home Assistant documentation:
Model Architecture (model/)¶
Separate subsystem implementing the optimization model:
Design principles:
- Pure Python linear programming using HiGHS via
highspy - Declarative constraint and cost specification using decorators
- Elements declare their requirements; network aggregates automatically
- Parameter updates trigger selective constraint rebuilding (warm start)
- No Home Assistant dependencies in model layer
Key components:
Element: Base class with declarative patternmodel/elements/: Element implementationsmodel/reactive/: Infrastructure for parameter tracking and constraint cachingNetwork: Aggregates element contributions and runs optimization
See Energy Models guide for implementing new elements and Modeling Documentation for mathematical details.
Code Organization¶
The integration lives under custom_components/haeo/ and follows Home Assistant layout conventions.
Rather than documenting every file, focus on how the major areas collaborate:
- Entry points:
__init__.py,config_flow.py, andcoordinator/bootstrap the integration, collect user input, and run optimizations. - Flows (
flows/): Houses hub, element, and options flows; each submodule owns the UI schema for a related group of entries. - Input layer (
inputs/): HorizonManager, Number platform, Switch platform, and InputFieldInfo for intermediate input entities. - Data layer (
data/): Loader modules turn Home Assistant sensors and forecasts into normalized time series. Called by input entities. - Model (
model/): Pure Python optimization layer with declarative constraints and costs.model/elements/: Model element implementations (Battery, Node, Connection types)model/reactive/: Parameter tracking and constraint caching infrastructure
- Metadata (
elements/andschema/): Describe configuration defaults, validation, INPUT_FIELDS registry, and runtime metadata for every element type. - Presentation (
sensors/): Builds sensor platforms that publish optimization results back to Home Assistant. - Translations (
translations/): Provides user-facing strings for config flows and entity names.
Extension Points¶
Adding Element Types¶
-
Create element subfolder in
elements/{element_type}/:__init__.py: Public exportsschema.py: DefineConfigSchemaandConfigDataTypedDictsflow.py: Implement config flow with voluptuous schemasadapter.py: Implementavailable(),load(),create_model_elements(),outputs(), andINPUT_FIELDSregistry
-
Register element type in
elements/__init__.py:- Add
ElementRegistryEntrytoELEMENT_TYPESmapping
- Add
-
Update translations in
translations/en.json:- Add device and selector entries
-
Write tests in
tests/elements/{element_type}/:test_adapter.py: Tests foravailable()andload()functionstest_flow.py: Config flow tests for user and reconfigure steps- Add test data in
tests/flows/test_data/{element_type}.py
-
Document the element:
- User guide in
docs/user-guide/elements/{element_type}.md - Modeling docs in
docs/modeling/device-layer/{element_type}.md
- User guide in
Custom Field Types¶
Extend schema/fields.py:
- Create new Validator subclass with
create_schema()method - Add LoaderMeta subclass if needed for custom loading behavior
- Define field type aliases composing Validator, LoaderMeta, and optional Default
Related Documentation¶
-
Horizon Manager
Synchronized forecast time windows.
-
Input Entities
Intermediate input entity layer.
-
Coordinator Guide
Event-driven update patterns.
-
Energy Models
Network entities and constraints.
-
Testing
Testing patterns and fixtures.