Repository navigation
Local Energy Manager
The Energy Manager Standalone is an automated battery-control engine that runs a 15-second decision loop inside Home Assistant. It reads your P1 smart meter, solar production, battery SOC, and (optionally) a solar forecast, and automatically manages your inverter's operating mode β charge, discharge, self-consume, or idle.
This is the Standalone engine: it decides locally from real-time sensor data and rules you configure. A future Day Ahead engine (optimising against dynamic energy prices) is planned as a separate release.
It builds on top of Battery Protection, not instead of it. The SOC minimum/maximum limits are read from the existing protection number entities and are always respected.
Runs on a Local Modbus RS485 entry. The engine drives the battery through the same Idle/Charge/Discharge/Self-Consume surface as the mode buttons, so it needs a connection that can send battery commands: a Hybrid inverter or a HALO (HYX-MS3000AC) over local Modbus. HYXI's cloud doesn't forward battery commands sent with owners' API keys, so a cloud entry doesn't offer the Energy Manager (see Device Control). On a HALO, two things differ: it reports no battery capacity, so tick Override Battery Capacity and set the value (see Battery capacity); and it has no PV input, so the solar-driven priorities (Solar Optimization, and the forecast-based night preservation) stay idle β the engine still does emergency-SOC, night self-consume, and high-load assist. Export Limiting is single-phase-inverter only and never appears for a HALO.
- A Local Modbus RS485 entry for the inverter.
- Enable Device Control & Protection turned on first (integration Configure menu β see Device Control).
- A P1 smart meter entity (a grid power sensor) already set up in Home Assistant.
- Settings β Devices & Services β HYXI β Configure.
- Enable Device Control & Protection and save.
- Re-open Configure β Enable Energy Manager Standalone (Beta) is now visible. Enable it and set:
-
P1 Smart Meter β your grid power sensor (required, e.g.
sensor.p1_meter_power). - Solar Forecast Remaining Today β remaining solar energy for today in kWh (optional, see below).
- Solar Forecast Current Power β current predicted solar power in W (optional).
- Inverter to Control β which inverter the engine manages.
- Override Battery Capacity / Battery Capacity (Wh) β manual capacity, only used when the override box is ticked (see below).
-
P1 Smart Meter β your grid power sensor (required, e.g.
- Save.
The engine is still off at this point. You must also turn on the Energy Manager switch entity. Night Mode, High Load Assist, and Export Limiting are each separate switches, off by default, enabled individually.
The engine can use forecast data for smarter battery-preservation and charge-timing decisions. Two optional entities:
-
Solar Forecast Remaining Today (kWh) β used for night-preservation: the engine checks whether the remaining solar can recharge the battery to the night target before sunset. Works with:
-
Forecast.Solar β the
energy_production_today_remainingsensor -
Solcast β the
forecast_remaining_todaysensor - any sensor giving remaining solar energy for today in kWh
-
Forecast.Solar β the
-
Solar Forecast Current Power (W) β reserved for future use. Forecast.Solar
power_production_now, or Solcastforecast_this_hour.
With no forecast entities configured, the engine estimates solar availability from current production and time to sunset.
The engine needs your battery's total capacity (Wh) for SOC calculations, night-reserve estimation, and high-load cost analysis. Determined in priority order:
- Manual override β if Override Battery Capacity is ticked and a value is set, that value is always used.
-
API auto-detection β the
batCapmetric from your inverter (reported in kWh, converted to Wh). Most hybrid inverters report this automatically. - Fallback β 2000 Wh if neither is available.
If your inverter reports
batCapcorrectly (visible as the "Battery Capacity" sensor on the inverter device), you don't need to configure anything. The override is for when the API value is missing, wrong, or you've modified your battery.A HALO over local Modbus reports no capacity at all, so without the override the engine falls straight through to the 2000 Wh fallback β which is almost certainly too small and will make its SOC and night-reserve maths wrong. Set the override.
Every 15 seconds the engine evaluates these in order β the first match wins:
| # | Condition | Action |
|---|---|---|
| 1. Emergency Low SOC | SOC < SOC Minimum | Charge from solar; from grid at β€ 2000 W if solar is absent and Grid Charge Allowed is on; otherwise idle to stop further drain |
| 2. Over-Max SOC | SOC > SOC Maximum | Forced discharge β at the higher of current grid import or 1000 W, capped at max discharge power |
| 2b. Export Limiting | Grid export > Max Grid Export | Single-phase only, switch must be on β charge to absorb, or curtail PV. Details |
| 3. High Load Assist | Home load > High Load Threshold | Switch must be on β battery assist if affordable, else idle. Details |
| 4. Night Mode | Nighttime (sun below horizon) | Switch must be on β self-consume, or idle at the SOC minimum. Details |
| 5. Solar Optimization | Solar producing + SOC < max | Smart-charge from solar, tuned to keep grid import/export near zero. Details |
| Default | none of the above | Self-consume (safe fallback) |
Requires: Night Mode switch β ON (default OFF).
Manages battery use overnight and preserves charge for overnight consumption:
-
At night (sun below horizon, no solar):
- SOC above SOC Minimum β self-consume (battery powers the house)
- SOC at or below SOC Minimum β idle (stop discharging, protect the reserve)
-
During daytime β night preservation:
- If SOC has dropped to or below the calculated night SOC target, the house is importing, and the solar forecast can't cover the gap β idle (preserve battery for tonight)
The night SOC target is calculated from:
-
Average Night Consumption(W) β configurable; also auto-updated hourly from real P1 data between 21:00β06:00 -
Night Buffer %β extra safety margin (default 5 %) - Battery capacity (options or API)
- Hours until sunrise
night_target = soc_min + ((avg_consumption Γ hours_remaining Γ (1 + buffer%)) / capacity) Γ 100
Example: 400 W average consumption, 14.8 kWh battery, 5 % buffer, 20 % SOC minimum, 12 hours to sunrise β night target β 20 % + 34 % = 54 %. The engine preserves battery above 54 % during the day if it calculates solar won't recharge it before sunset.
Requires: High Load Battery Assist switch β ON (default OFF).
Detects when home consumption exceeds a configurable threshold and decides whether the battery should help:
-
Home load > High Load Threshold, assist enabled:
- Calculates the SOC cost of 30 minutes of assist at 50 % of max discharge power
- Affordable (SOC after assist still above the night target) β self-consume (battery helps)
- Not affordable (would drain below night target) β idle (let the grid handle it)
- Home load below threshold β no action, falls through to the next priority.
Use case: oven, EV charger, heat pump β stop the battery draining itself to cover a temporary spike and leaving too little reserve for the night.
Requires: Export Limiting switch β ON (default OFF). Single-phase devices only β it uses peak-shaving control (controlId 1021), which three-phase inverters don't have.
Caps how much power is fed back to the grid:
-
Export > Max Grid Export, battery has room (SOC < Max):
- Charges to absorb the excess (min 300 W, capped at max charge power); continuously re-tunes as export fluctuates
-
Export > Max Grid Export, battery full:
- Peak-shaving
stopto curtail PV entirely; 30-second cooldown between stop/hold toggles prevents oscillation
- Peak-shaving
-
Export drops below the limit:
- Peak-shaving
holdto resume PV; back to self-consume
- Peak-shaving
Use case: feed-in tariff caps, grid-connection limits, or maximising self-consumption.
When solar is producing and the battery isn't full:
-
Entry gate β solar must exceed
Min Solar for Charge(default 1000 W). -
Export confirmation β grid export must exceed
Charge Entry Threshold(default 500 W) for several consecutive readings before entering charge mode (prevents charge/discharge oscillation on cloudy days). - Power tuning β once charging, the engine continuously adjusts charge power to keep P1 near zero.
- Bottom-out exit β if charge power sits at minimum (100 W) for 3 consecutive ticks, exit to self-consume.
- Sunset urgency β within 4 hours of sunset, if SOC is below the night target and the forecast won't cover it, entry thresholds relax to capture the remaining solar.
The Grid Charge Allowed switch (on the inverter device, not the Energy Manager device) controls whether the engine may charge from the grid during emergencies β used only when SOC is below minimum with no solar available. Default OFF.
All Energy Manager entities live on a virtual Energy Manager device linked to your inverter.
| Entity | Purpose |
|---|---|
| Energy Manager | Master on/off for the decision loop |
| Night Mode | Night self-consume + battery preservation |
| High Load Battery Assist | Battery assist during high home loads |
| Export Limiting | Cap grid export by charging the battery (single-phase only) |
| Grid Charge Allowed | Allow grid charging in low-SOC emergencies (lives on the inverter device) |
| Entity | Unit | Default | Range | Purpose |
|---|---|---|---|---|
| High Load Threshold | W | 6500 | 1000β20000 | Home load above this triggers high-load logic |
| Max Charge Power | W | 5000 | 500β15000 | Maximum charge power sent to the inverter |
| Max Discharge Power | W | 5000 | 500β15000 | Maximum discharge power |
| Min Solar for Charge | W | 1000 | 200β3000 | Solar must exceed this to consider charging |
| Mode Switch Cooldown | s | 60 | 10β300 | Minimum seconds between mode changes |
| Power Change Threshold | W | 100 | 10β500 | Minimum power change before resending a command |
| Power Adjust Cooldown | s | 30 | 5β120 | Minimum seconds between power adjustments |
| Night Buffer | % | 5 | 0β20 | Extra safety margin for the night SOC calculation |
| Avg Night Consumption | W | 400 | 100β2000 | Baseline night power draw (auto-updates hourly) |
| Charge Margin | W | 150 | 0β500 | Buffer between solar charge and the grid balance point |
| Charge Entry Threshold | W | 500 | 100β2000 | Grid export required before entering charge mode |
| Charge Re-entry Delay | s | 300 | 30β600 | Cooldown before re-entering charge after an exit |
| Bottomout Cooldown | s | 300 | 60β900 | Extended cooldown after a charge bottom-out exit |
| P1 Smoothing Period | s | 60 | 1β300 | Rolling-average window for P1 meter readings |
| Max Grid Export | W | 0 | 0β10000 | Max allowed grid export before charging kicks in (single-phase only) |
Set once in Configure, not entities:
| Setting | Default | Purpose |
|---|---|---|
| Override Battery Capacity | OFF | Enable the manual battery-capacity override |
| Battery Capacity (Wh) | 2000 | Manual capacity value (only used when the override is ticked) |
| Dry-Run Mode | OFF | Engine logs decisions and fires HA events but skips all API calls |
| Entity | Purpose |
|---|---|
| EM Decision | Active decision label, e.g. solar_charge, night_self_consume
|
| EM Last Action | Last mode command sent, e.g. charge @ 2500W (or [dry-run] charge @ 2500W) |
| EM Status |
running, stopped, disabled, stale, cooldown, dry_run, or error
|
| Battery Energy Available | Usable energy above the SOC minimum (Wh) |
| Hours Until Sunrise / Sunset | Calculated from sun.sun
|
| P1 Average Power | Rolling average of P1 meter readings (W) |
| Entity | Purpose |
|---|---|
| Night Mode Active | Currently nighttime (sun below horizon, no solar) |
| High Load Detected | Home load exceeds the high-load threshold |
The engine fires hyxi_em_mode_changed on every mode change β usable in automations:
| Field | Description |
|---|---|
sn |
Inverter serial number |
mode |
New mode β charge, discharge, self_consume, idle
|
power |
Target power in watts (null for idle/self-consume) |
previous_mode |
Mode before the change |
decision |
Decision label that triggered the change |
dry_run |
true if in dry-run mode (field absent otherwise) |
While the engine is running it owns its inverter β the hyxi_cloud.set_battery_mode action refuses to send a mode to it unless you pass force: true, because the next decision tick would just undo an un-forced command anyway. To hand control back to your own automation, turn the Energy Manager switch off (or pass force: true for a one-off nudge and accept that the engine will override it shortly).
Check the EM Status sensor first β it tells you why nothing's happening before you dig further. If the inverter's data is older than four poll intervals (at least two minutes), the engine pauses with status stale and a repair issue explains why; both clear themselves once fresh data arrives. The status table is in Troubleshooting β Energy Manager.