Architecture¶
HAFO follows a simple, focused architecture designed for extensibility.
Overview¶
flowchart TD
subgraph HA[Home Assistant]
CF[Config Flow] --> FC[Forecaster Coordinator]
FC --> FS[Forecast Sensor]
FC --> RS[Recorder Statistics]
end
Components¶
Config Flow (config_flow.py)¶
Handles the UI configuration for creating forecast helpers. Uses Home Assistant's helper pattern for entity creation.
Forecasters (forecasters/)¶
Each forecaster is a coordinator - they extend DataUpdateCoordinator directly.
This design allows each forecaster to determine its own update interval based on its data source characteristics.
The coordinator module (coordinator.py) provides a factory function create_forecaster() that instantiates the appropriate forecaster type based on configuration.
Currently implemented:
- HistoricalShiftForecaster: Extends
DataUpdateCoordinator, shifts history forward by N days, updates hourly
Sensor (sensor.py)¶
Exposes the forecast data to Home Assistant. Provides the forecast as both state (current value) and attributes (full series).
Data Flow¶
- Configuration: User creates a forecast helper via the config flow
- Initialization: The appropriate forecaster coordinator is created via
create_forecaster() - Fetching: Forecaster fetches statistics from the recorder on its update interval
- Transformation: Historical data is shifted forward to project into the future
- Exposure: Sensor exposes the forecast data
Note: Forecast cycling (repeating patterns to fill longer horizons) is not done by HAFO. Consumers of the forecast (like HAEO) are responsible for cycling data to meet their specific horizon requirements.
Adding New Forecasters¶
To add a new forecasting algorithm:
- Create a new module in
forecasters/ - Extend
DataUpdateCoordinatorand implement_async_update_data() - Define an appropriate
UPDATE_INTERVALfor the data source - Register it in
FORECASTER_TYPESincoordinator.py - Add the option to the config flow dropdown
- Add documentation
Extension Points¶
- New Forecasters: Add coordinator classes in
forecasters/and register inFORECASTER_TYPES - New Sensors: Add sensor types in
sensor.py - Data Sources: Each forecaster can fetch from different sources (recorder, APIs, etc.)