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.
System Overview¶
graph TD
CF[Config Flow] --> CE[Config Entry]
CE --> Coord[Coordinator]
Coord --> Loaders[Data Loaders]
Coord --> Builder[Network Builder]
Builder --> Model[Network Model]
Model --> Solver[LP Solver]
Solver --> Results[Results]
Results --> Sensors[Sensors]
style Coord fill:#FFE4B5
style Solver fill:#90EE90
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 config entry documentation for the underlying Home Assistant patterns.
Coordinator (coordinator.py)¶
Central manager scheduling optimization cycles (default 5 min), loading data, building network, running solver, distributing results. Each hub entry creates one coordinator instance.
See the data update coordinator documentation for the base pattern. HAEO's coordinator gathers sensor values, assembles the optimization network, runs the solver in an executor, and pushes the results back to the entities. It listens for element additions or removals and triggers a refresh whenever the underlying data changes.
Data loaders (data/)¶
Data loaders translate configuration into time series the model can consume. They validate values during the config flow and fetch real sensor data at runtime, including support for common forecast formats. Keep new loaders focused on a single responsibility and reuse the shared parser utilities where possible.
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 PuLP:
- Element: Base class for all model elements with power/energy variables
- Battery: Storage with charge/discharge power, SOC constraints
- Grid: Import/export with optional limits and pricing
- Photovoltaics: Solar generation with optional curtailment
- ConstantLoad, ForecastLoad: Consumption elements
- Node: Virtual balance point enforcing Kirchhoff's law
- Connection: Power flow path with optional min/max limits
- Network: Container with
optimize(),cost(), andconstraints()methods
LP Solver¶
Multiple solvers supported via PuLP:
- HiGHS (default): Fast, open-source, no external dependencies
- CBC, GLPK, COIN-OR, SCIP, CyLP: Alternative solvers
Solves linear programming minimization problem, returns optimal cost and decision variable values.
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. Refer to the sensor entity documentation when adding new measurements.
Model Architecture (model/)¶
Separate subsystem implementing the optimization model:
Design principles: - Pure Python linear programming using PuLP - Elements generate their own variables and constraints - Network assembles elements and runs solver - No Home Assistant dependencies in model layer
Key components:
- Element: Base class with power/energy variable patterns
- Entity classes: Battery, Grid, Photovoltaics, Loads, Node
- Connection: Power flow with limits
- Network: Container with optimize() method
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.pybootstrap the integration, collect user input, and run optimizations on schedule. - Flows (
flows/): Houses hub, element, and options flows; each submodule owns the UI schema for a related group of entries. - Data layer (
data/): Loader modules turn Home Assistant sensors and forecasts into normalized time series for the optimizer. - Model (
model/): Pure Python optimization layer composed of elements, connections, and network orchestration. - Metadata (
elements/andschema/): Describe configuration defaults, validation, and runtime metadata for every element type. - Presentation (
sensors/): Builds coordinator entities and 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 model class in
model/: - Inherit from
Element - Define power/energy variables
-
Implement
cost()andconstraints()methods -
Add element metadata in
elements/: *ConfigSchema: For config flow validation*ConfigData: For runtime with loaded values-
Define field metadata using annotations
-
Register element type in
elements/__init__.py: -
Add to
ELEMENT_TYPESmapping -
Create config flow in
flows/elements/: - Inherit from appropriate base
-
Implement validation and schema generation
-
Update translations in
translations/en.json: -
Add device and selector entries
-
Write tests:
- Model tests in
tests/test_model.py - Config flow tests in
tests/flows/ - Integration tests
Custom Solvers¶
Add solver support in model/network.py:
- Map solver names in
const.py - Add solver validation
- Update
optimize()to handle new solver options
Custom Field Types¶
Extend schema/fields.py:
- Create new
FieldMetasubclass - Define validation schema
- Implement loader logic
- Register with field type system