-
-
Notifications
You must be signed in to change notification settings - Fork 16
Smart Optimization
Important: Solar forecasting must be configured for accurate scheduling — either install the Solcast Solar HA integration (recommended, PowerSync auto-detects it) or enter your Solcast API key directly in PowerSync's Weather & Solar Forecast settings. Without solar forecast data, the optimizer has no visibility on solar production and will make purely price-based decisions — which can result in unnecessary grid imports even when solar is available.
PowerSync includes a built-in linear programming (LP) optimizer that calculates the optimal battery charge/discharge schedule based on electricity prices, solar forecasts, and load patterns. No external dependencies required.
Acknowledgement: The optimization approach was inspired by HAEO (Home Assistant Energy Optimizer).
The optimizer uses scipy's HiGHS LP solver to solve a cost minimization problem over a 48-hour horizon:
Minimize: Sum (import_price[t] * grid_import[t] - export_price[t] * grid_export[t]) * dt
Subject to:
- Power balance: solar[t] + grid_import[t] + battery_discharge[t]
= load[t] + grid_export[t] + battery_charge[t]
- SOC dynamics: soc[t] = soc_0 + Sum(charge*eff - discharge/eff) * dt / capacity
- SOC limits: backup_reserve <= soc[t] <= 1.0
- Rate limits: charge <= max_charge_kw, discharge <= max_discharge_kw
The optimizer runs directly inside PowerSync:
- Collects price, solar, and load forecasts from configured providers
- Overlays EV charging plans into the load forecast (if EV integration is enabled)
- Solves the LP problem in a background thread (typically < 1 second)
- Maps the solution to battery actions (charge, discharge, idle, self-consumption)
- Executes battery commands via the appropriate control method
If scipy is unavailable, a greedy fallback optimizer runs instead.
| Action | What It Does | When It's Used |
|---|---|---|
| CHARGE | Force charge battery from grid | Cheap import periods (overnight off-peak) |
| EXPORT | Force discharge battery to grid | Expensive export periods (evening peak) |
| IDLE | Hold battery at current SOC (sets backup reserve) | Grid is cheaper than battery round-trip |
| SELF_CONSUMPTION | Battery operates naturally | Solar hours, moderate prices |
| Feature | Description |
|---|---|
| 48-Hour Optimization | Plans battery actions for the next 48 hours |
| 5-Minute Resolution | 576 optimization intervals for fine-grained control |
| Solar Integration | Uses Solcast forecast data for solar predictions |
| Price Integration | Works with Amber, Localvolts, Octopus, Flow Power, AEMO, and TOU tariffs |
| EV Load Awareness | Incorporates planned EV charging into the load forecast |
| Daily Cost Tracking | Actual cost (midnight to now) + predicted cost (now to midnight) |
| Zero Setup | Built-in — no external integrations or HACS repos needed |
When using dynamic pricing providers (Amber, AEMO, Octopus Agile/Flux, Flow Power), the optimizer receives price forecasts up to 48 hours ahead. Near-term prices are accurate but far-future forecasts are speculative — a predicted 40c/kWh spike at 2am tomorrow might settle at 22c.
Without adjustment, the LP would take those speculative prices at face value. It might charge overnight at 20c for a "spike" 18 hours away that never materializes, when cheaper midday solar charging is available in between.
Confidence decay addresses this by pulling above-median prices toward the median as they get further from now:
decayed_price = median + (raw_price - median) × e^(-rate × excess_hours)
| Parameter | Value | Description |
|---|---|---|
| Horizon | 4 hours | Prices within 4h are trusted completely (no decay) |
| Decay rate | 0.15 | Exponential decay coefficient beyond the horizon |
With a median of 21c/kWh and a raw forecast price of 30c/kWh:
| Hours ahead | Excess | Decay factor | Decayed price |
|---|---|---|---|
| 5h | 0h | 1.00 | 30.0c (within horizon) |
| 8h | 2h | 0.74 | 27.7c |
| 12h | 6h | 0.41 | 24.7c |
| 24h | 18h | 0.07 | 21.6c (nearly median) |
The decay is asymmetric — only above-median prices are decayed. Below-median (cheap) prices are preserved because cheap periods are structurally reliable: midday solar dumps and off-peak overnight rates are predictable, not speculative.
This ensures the LP can see that midday at 15c is genuinely cheaper than overnight at 18c, and won't pre-charge overnight for a dubious far-future spike when cheaper daytime charging is available.
Note: Confidence decay is not applied to static TOU providers (GloBird, custom tariffs) where prices are known and fixed.
The hardware backup reserve is a floor that the battery hardware enforces independently of the optimizer. This is useful as a safety net — even if the optimizer schedules a full discharge, the hardware won't go below this level.
- Set via the mobile app: Settings > Optimization > Reserve Levels > Hardware Backup Reserve
- This value is written directly to the battery hardware (e.g. Tesla backup_reserve, FoxESS min_soc)
- The LP optimizer's backup reserve is a separate, software-level floor used during schedule planning
- Typically set the hardware reserve a few percent below the optimizer reserve as a safety margin
Solcast Solar forecast is required. Without it, the optimizer cannot see when solar will be available and will make decisions based only on electricity prices — leading to unnecessary grid imports even when the sun is shining and your battery is full.
Configure one of:
- Solcast Solar HA integration (recommended) — install via HACS, PowerSync auto-detects it. No API key needed in PowerSync.
- Solcast API key in PowerSync — enter directly in the Weather & Solar Forecast settings (in HA config flow or mobile app). Requires a free account at toolkit.solcast.com.au.
- Install Solcast Solar (see prerequisites above)
- Go to Settings > Devices & Services > PowerSync > Configure
- Select Smart Optimization (Built-in LP) as your optimization provider
- Set your backup reserve percentage
- In the mobile app: Controls > toggle Enable on the Smart Optimization card
- View the schedule by tapping View Full Schedule
Use the power_sync.enable_optimizer and power_sync.disable_optimizer services in HA automations. For example, disable the optimizer during a manual force charge window and re-enable afterwards:
automation:
- alias: "Disable optimizer for manual charge"
trigger:
- platform: state
entity_id: input_boolean.manual_charge
to: "on"
action:
- service: power_sync.disable_optimizer
- service: power_sync.force_charge
data:
duration_minutes: 60
- alias: "Re-enable optimizer after manual charge"
trigger:
- platform: state
entity_id: input_boolean.manual_charge
to: "off"
action:
- service: power_sync.enable_optimizer+-----------------------------------------------------------+
| Data Sources |
| - Amber/Localvolts/Octopus/Flow Power/AEMO prices |
| - Solcast solar forecasts |
| - Historical load estimation |
| - EV charging plan overlay |
+-----------------------------------------------------------+
|
v
+-----------------------------------------------------------+
| Built-in LP Optimizer (scipy linprog / HiGHS) |
| Collects forecasts -> LP solve -> Optimal schedule |
| Fallback: Greedy algorithm if scipy unavailable |
+-----------------------------------------------------------+
|
v
+-----------------------------------------------------------+
| Execution Layer |
| Schedule -> Battery commands |
| - Tesla: TOU tariff trick |
| - FoxESS: Remote control registers (46001-46004) |
| - Sigenergy: Remote EMS mode control |
| - Sungrow: Modbus force mode commands |
| - GoodWe: ECO Charge/Discharge modes |
+-----------------------------------------------------------+
PowerSync creates forecast sensors for dashboard visibility:
| Sensor | Description | Unit |
|---|---|---|
sensor.powersync_price_import_forecast |
Grid import price forecast | $/kWh |
sensor.powersync_price_export_forecast |
Feed-in/export price forecast | $/kWh |
sensor.powersync_solar_forecast |
Solar PV generation forecast | W |
sensor.powersync_load_forecast |
Home consumption forecast | W |
Each sensor includes a forecast attribute with up to 576 data points (48 hours at 5-minute intervals).
The optimization screen in the mobile app shows:
| Section | Description |
|---|---|
| Status | Whether optimization is active and the current mode |
| Current/Next Action | What the battery is doing now and what's coming next |
| Predicted Cost | Estimated electricity cost for the day |
| Savings | How much you're saving vs no optimization |
| 48-Hour Chart | Visual timeline of SOC and power |
| Upcoming Actions | List of scheduled charge/discharge periods |