Skip to content

Smart Optimization

bolagnaise edited this page Apr 5, 2026 · 36 revisions

Smart Optimization

Important: The optimizer requires Solcast Solar to be installed and configured for accurate scheduling. 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. See Enable Smart Optimization below.

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).

How It Works

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:

  1. Collects price, solar, and load forecasts from configured providers
  2. Overlays EV charging plans into the load forecast (if EV integration is enabled)
  3. Solves the LP problem in a background thread (typically < 1 second)
  4. Maps the solution to battery actions (charge, discharge, idle, self-consumption)
  5. Executes battery commands via the appropriate control method

If scipy is unavailable, a greedy fallback optimizer runs instead.

Action Model

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

Features

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

Confidence Decay (Dynamic Pricing Only)

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

Example

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)

Asymmetric Decay

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.

Hardware Backup Reserve (v2.5.0+)

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

Enable/Disable Optimizer

Prerequisites

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.

Install one of:

  • Solcast Solar integration (recommended) — PowerSync auto-detects it, no API key needed in PowerSync
  • Solcast API key — enter directly in PowerSync's Weather & Solar Forecast settings (requires free account at toolkit.solcast.com.au)

Manual

  1. Install Solcast Solar (see prerequisites above)
  2. Go to Settings > Devices & Services > PowerSync > Configure
  3. Select Smart Optimization (Built-in LP) as your optimization provider
  4. Set your backup reserve percentage
  5. In the mobile app: Controls > toggle Enable on the Smart Optimization card
  6. View the schedule by tapping View Full Schedule

Via Automation (v2.5.0+)

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

Architecture

+-----------------------------------------------------------+
|  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                      |
+-----------------------------------------------------------+

Forecast Sensors

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).

Understanding the Schedule

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

Optimization Status 24-Hour Schedule Action Plan

Clone this wiki locally