Automated energy management for a Qcells/SolaX X3 Hybrid inverter using EMHASS (Energy Management for Home Assistant) and Home Assistant automations.
This repository contains Home Assistant configurations, sensors, MPC (Model Predictive Control) payload templates, and battery management automations that optimize solar usage with price forecasts via EMHASS.
This project integrates:
- EMHASS for energy optimization with a 15-minute MPC horizon
- Solax Power Hybrid Inverter (X3-Hybrid) controlled via the Home Assistant
solaxintegration - Home Assistant Automations to execute remote control modes based on MPC forecasts
- Dynamic scheduling of battery charge/discharge based on price, PV forecast, and load
The goal is to maximize self-consumption, minimize grid cost, and keep the battery within safe state-of-charge (SOC) bounds.
This setup assumes:
- Home Assistant (Container or OS)
- EMHASS installed and reachable via REST API
- Solax Power integration for the inverter & battery (Modbus or built-in API)
- Qcells/SolaX inverter with firmware that supports Mode 8 remote control
- Forecast sources such as Solcast and/or price feeds
sensors.yaml: Template sensors for forecasts and MPC inputsrest_commands.yml: REST definitions for EMHASS API calls*.ymlautomations: MPC control & battery automations
- 15-minute MPC horizon using EMHASS
- Cost-optimized scheduling based on:
- PV forecast
- Load forecast
- Day-ahead electricity prices
- Battery SOC constraints
- Automatic REST-based triggering from Home Assistant
The MPC controller uses:
- PV forecast (e.g., Solcast)
- Load forecast (ML-predict sensor)
- Price forecast (EPEX/Nord Pool)
- Battery SOC (Solax Modbus sensor)
- Cost minimization objective (
costfun = cost)
The payload sensor builds the EMHASS API call and sends it every 15 minutes.
All forecast and MPC output sensors are stored in dictionary (dict) format instead of flat time-series sensors.
This design choice significantly simplifies:
- Start-time alignment
- Time-index calculations
- MPC horizon handling
- Synchronization between PV, load, grid and battery forecasts
Each dict entry contains explicit timestamps, allowing robust time arithmetic without relying on implicit sensor update intervals.
- Minute-based closed-loop execution
- Follows MPC scheduled battery power (
p_batt_forecast) - Supports:
- Grid charging
- PV charging
- No-discharge periods
- Normal operation fallback
- Additional SOC safety stop outside EMHASS
This automation reads:
sensor.p_batt_forecastsensor.soc_batt_forecastfrom dayahead- PV & load sensors
📌 Battery Safety We enforce SOC bounds both in EMHASS config and within automations. For example, a safety stop is triggered when SOC < 22%. In Version v1.1.0 the min SOC is set to 20%, in addition a recovery loop is implemented to recharge battery back to 25% to keep the loop alive.
For visualization, an ApexCharts card shows:
- Price forecast
- PV forecast
- Load forecast
- Grid & battery power forecasts
Below is an example configuration snippet:
📈 ApexCharts – MPC Forecast Visualization
type: custom:apexcharts-card
experimental:
color_threshold: true
graph_span: 6h
span:
start: minute
now:
show: true
label: now
color: red
yaxis:
- id: first
decimals: 2
apex_config:
forceNiceScale: true
- id: second
opposite: true
min: -4000
max: 8000
decimals: 0
apex_config:
forceNiceScale: true
header:
show: true
title: Energy flow
show_states: true
colorize_states: true
series:
- entity: sensor.epex_spot_data_total_price_3
yaxis_id: first
curve: stepline
float_precision: 2
show:
in_header: after_now
stroke_width: 1
name: price kWh
data_generator: |
return entity.attributes.data.map((entry) => {
return [new Date(entry.start_time), entry.price_per_kwh];
});
- entity: sensor.p_pv_forecast
yaxis_id: second
curve: stepline
show:
in_header: before_now
stroke_width: 1
name: PV Forecast
color: rgb(255,215,0)
data_generator: |
return entity.attributes.forecasts.map((entry) => {
return [new Date(entry.date), entry.p_pv_forecast];
});
- entity: sensor.p_load_forecast
yaxis_id: second
curve: stepline
show:
in_header: before_now
stroke_width: 1
name: Load Forecast
color: rgb(255,0,0)
data_generator: |
return entity.attributes.forecasts.map((entry) => {
return [new Date(entry.date), entry.p_load_forecast];
});
- entity: sensor.p_grid_forecast
yaxis_id: second
curve: stepline
opacity: 0.1
color: rgb(0,255,255)
type: area
show:
in_header: before_now
stroke_width: 1
name: Grid Forecast
data_generator: |
return entity.attributes.forecasts.map((entry) => {
return [new Date(entry.date), entry.p_grid_forecast];
});
- entity: sensor.p_batt_forecast
yaxis_id: second
curve: stepline
opacity: 0.1
color: green
type: area
show:
in_header: before_now
stroke_width: 1
name: Batt Forecast
data_generator: |
return entity.attributes.battery_scheduled_power.map((entry) => {
return [new Date(entry.date), entry.p_batt_forecast];
});
...
You can add additional panels for day-ahead MPC outputs and SOC forecast.
🐞 Known Issues & Notes
The Home Assistant EMHASS Add-on installation is not fully compatible with the file path structure used in the EMHASS standalone setup.
Several paths (e.g. for forecast CSV files) differ from the upstream documentation and cannot be used reliably inside the add-on environment.
To avoid filesystem path issues, this project:
- Executes EMHASS
predictvia REST - Publishes the load forecast as a Home Assistant sensor
- Converts the forecast into dictionary format
- Feeds the resulting dict sensor back into subsequent MPC and battery control logic
This approach:
- Avoids direct file access inside the EMHASS container
- Keeps all data exchange within Home Assistant
- Improves robustness and portability across installations
While this deviates from the standalone EMHASS workflow, it has proven to be reliable in long-term operation with the Home Assistant add-on.
🛠 Usage Enable EMHASS server and configure Home Assistant to publish data Schedule dayahead optimization at ~05:30 Run regular MPC optimizations every 15 minutes Battery automation runs every minute to follow the MPC plan
📬 Contributions If you have improvements, examples, or fixes, feel free to submit a Pull Request.
This project relies on the excellent Home Assistant SolaX Modbus integration:
👉 https://github.com/wills106/homeassistant-solax-modbus
It provides detailed inverter and battery metrics and allows reliable remote control of operating modes required for MPC-based optimization.
📜 License
This project is released under the MIT License.