Skip to content

Smart Optimization

bolagnaise edited this page May 30, 2026 · 36 revisions

Smart Optimization

Warning

The built-in optimizer is actively under development. Expect occasional bugs, unexpected schedules, and behaviour that doesn't match your expectations — especially on less common tariffs, battery configurations, or edge-case scenarios. If the optimizer does something you didn't expect, please report it on Discord or open a GitHub issue with your tariff details and the action plan it generated. Your reports directly improve the algorithm.

Important: Solar forecasting must be configured for accurate scheduling — install a supported Home Assistant forecast integration such as Solcast Solar or Open-Meteo Solar Forecast, or enter your Solcast API key directly in PowerSync's Weather & Solar Forecast settings. PowerSync auto-detects the HA integrations. Without solar forecast data, the optimizer cannot see when solar will be available and will make purely price-based decisions — which can result in unnecessary grid imports even when solar is available.

PowerSync includes a built-in optimizer that calculates the optimal battery charge/discharge schedule based on electricity prices, solar forecasts, and load patterns. No external tools or additional HACS integrations are required.

For Custom / external controller battery systems, Smart Optimization is planner-only. PowerSync reads the Home Assistant entities selected during Battery System setup, generates the same plan and optimizer sensors, and keeps monitoring mode enabled so no battery or inverter commands are sent. Use your existing controller or automations if you want to act on those decisions.

How It Works

The optimizer finds the cheapest way to run your home over the next 48 hours. It works out:

  • When to charge the battery (cheapest grid periods, or from solar)
  • When to discharge or export (highest price periods)
  • When to leave the battery alone (when it's not worth the round-trip losses)

It runs every 5 minutes, updating the plan as prices and solar forecasts change.

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 level Grid is cheaper than the battery round-trip
SELF_CONSUMPTION Battery operates naturally Solar hours, moderate prices
OFF_GRID Physically disconnect from grid (Tesla only) Negative export prices — avoids paying to export

Features

Feature Description
48-Hour Planning Plans battery actions for the next 48 hours
5-Minute Resolution Fine-grained control throughout the day
Solar Integration Uses Solcast or Open-Meteo forecast data for solar predictions
Load Forecasting Learns household load from Home Assistant recorder history
Price Integration Works with Amber, Localvolts, Octopus, Flow Power, EPEX, AEMO, NZ TOU, and custom 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 needed beyond a supported solar forecast source
Off-Grid Curtailment Automatically islands the Powerwall during negative export prices (opt-in, Tesla only)

Optimization Settings

These settings are available during setup and later under Settings > Devices & Services > PowerSync > Configure > Optimization.

Setting What It Controls
Optimization mode Selects Smart Optimization or the battery's native/default behavior
Enable Smart Optimization Turns the LP optimizer on or off without deleting saved optimizer settings
Monitoring mode Blocks battery and inverter write commands while prices, sensors, forecasts, and plans keep updating
Minimum discharge level Software reserve used by the LP and execution guard
Hardware backup reserve Physical reserve written to supported batteries as a safety floor
Battery capacity / maximum charge / maximum discharge Model values used by the optimizer and manual force controls
Allow grid charging When off, Smart Optimization can still use solar surplus but will not import grid energy just to charge the battery
Spread export across window Smooths planned battery export across each eligible export window
Spread import across window Smooths planned grid charging across same-price import windows
Profit Max target time / SOC Defines when and how full the battery should be before known high-value export windows

Monitoring mode is a control boundary, not a data boundary. It is useful for observing plans or debugging setup because PowerSync still refreshes tariffs and sensors, but it suppresses battery and inverter writes.

Custom / external controller systems always use this boundary. The selected telemetry entities still feed optimizer state, daily cost tracking, solar/load planning, and forecast sensors, but PowerSync never attempts hardware dispatch for that battery system.

Off-Grid Curtailment in the Optimizer (v2.12.0+)

When enabled in Battery Setup > Local Control, the optimizer can physically disconnect the Powerwall from the grid during low-value export periods. This is a stronger curtailment method — the grid connection physically opens, guaranteeing zero export.

The optimizer identifies eligible periods where export value is below 1 c/kWh and projected SOC is near full, then groups them into runs of at least 15 minutes to avoid rapid reconnection cycling. A reconnect window is automatically inserted before any upcoming charge period.

Requirements:

  • Tesla Powerwall with completed gateway pairing
  • Off-grid curtailment enabled in Battery Setup > Local Control
  • Optimizer enabled

Safety gates:

  • SOC floor (default 40%) — won't go off-grid below this battery level
  • Near-full battery gate — optimizer overlay only schedules off-grid curtailment when projected SOC is at least 98%
  • Daily duration cap (default 6 hours)

When the optimizer is enabled, the independent curtailment loop is bypassed to prevent conflicts. If the optimizer is disabled, the independent curtailment loop still works.

Solar continues producing while off-grid — it charges the battery and powers the home. The battery is the sole backup when solar is insufficient, which is why the SOC floor is important.


Confidence Decay (Dynamic Pricing Only)

When using dynamic pricing (Amber, Localvolts, AEMO, Octopus Agile/Flux, Flow Power, EPEX), 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 optimizer might charge overnight at 20c for a "spike" 18 hours away that never materialises, when cheaper midday solar charging is available in between.

Confidence decay pulls far-future above-average prices toward the average as they get further from now:

Parameter Value Description
Horizon 6 hours Prices within 6h are trusted completely (no decay)
Decay rate 0.15 How quickly speculative prices are discounted beyond the horizon

Example

With an average of 21c/kWh and a raw forecast price of 30c/kWh:

Hours ahead Decayed price
7h (just outside horizon) 28.8c
10h 25.9c
14h 23.7c
24h 21.6c (nearly at average)

Asymmetric Decay

The decay is asymmetric — only above-average prices are decayed. Below-average (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 optimizer 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.

Load Forecasting

Smart Optimization needs an estimate of future home load so it can decide whether stored battery energy is more valuable for household self-consumption or for export.

PowerSync uses load sources in this order:

  1. Home Assistant recorder history — PowerSync builds its own load forecast from the configured or auto-detected home-load sensor.
  2. Simple fallback profile — if no usable history exists, PowerSync falls back to a basic residential load curve based on the current load.

The local history model uses the last 30 days of Home Assistant recorder data. It groups usage by local weekday, hour, and half-hour bucket, so Monday 7:30pm is compared mainly with previous Monday 7:30pm periods rather than with unrelated times of day.

To avoid overreacting to one unusual night, PowerSync applies several protections:

  • Recent samples are weighted more heavily, with a 14-day half-life.
  • Extreme high or low samples are clipped from buckets when enough history exists.
  • Exact weekday/time buckets need at least two samples before they are trusted by themselves.
  • A single exact sample is blended with similar weekday/weekend history rather than copied directly.
  • If a bucket is missing, PowerSync falls back to same day type, then any day at the same time, then the overall robust average.
  • A small smoothing pass removes sharp slot-to-slot jumps after the forecast is built.

If a Home Assistant weather entity is configured, PowerSync can also adjust load forecasts for temperature-sensitive usage such as air conditioning or heating. The temperature adjustment uses the same filtered history window as the load model.

Planned EV charging is added on top of the household load forecast before the LP solve, so the battery optimizer can plan around vehicle charging instead of competing with it.

Away Mode

Away Mode protects the load forecast from holiday or low-occupancy periods. Without it, an extended trip can fill the recorder history with very low consumption, causing the optimizer to underestimate normal evening and overnight load when you return.

Away Mode solves this in two stages:

Stage 1 — Enable before you leave While the switch is on, PowerSync records the departure time. As the house sits empty, recent low-load history can still bias the optimizer toward exports rather than reserving battery for non-existent home load.

Stage 2 — Disable when you get home Turning the switch off records your return time and starts a 7-day recovery status. The load forecaster excludes the away period from its 30-day history window, then uses the most recent normal data around it. As real post-return usage accumulates, it naturally replaces older pre-trip data. The visible recovery status ends after 7 days, while the away interval remains excluded from history until it ages out of the 30-day lookback.

If you accidentally toggle the switch on and off within an hour, it is treated as a no-op and no recovery window starts.

How to Use

switch.power_sync_away_mode

It appears under your PowerSync device in Settings → Devices & Services → PowerSync → Configuration.

  1. Before leaving: turn the switch ON
  2. When you get home: turn the switch OFF — recovery starts automatically
  3. After ~7 days: the recovery status clears; the switch can be left off

Recovery Status

While recovering, sensor.power_sync_load_forecast_today_remaining exposes these attributes:

Attribute Description
away_in_recovery true during the 7-day recovery window
away_recovery_remaining_hours Hours until the window closes automatically
away_enabled_at ISO timestamp of departure
away_disabled_at ISO timestamp of return

Note: Away mode affects the load forecast only. Solar forecasting uses weather/irradiance data and is unaffected.


Profit Maximisation Mode (v2.12.158+)

By default, the LP optimizer is conservative with stored battery energy. It still exports when the tariff makes export worthwhile, but it also values the battery charge left at the end of the planning horizon. That end-of-horizon value is the optimizer's "insurance" against bad solar forecasts, higher-than-expected overnight prices, or home load arriving after the visible export window.

Profit Maximisation Mode tells the LP to value near-term export revenue more than that future recharge insurance.

Profit Max Off vs On

Behaviour Profit Max OFF Profit Max ON
Main goal Lowest bill with more SOC protection after the forecast horizon Maximise high-value export opportunities, accepting more recharge risk
End-of-horizon battery value Full terminal SOC weight (1.0) Reduced terminal SOC weight (0.3)
What that means Stored energy is treated as valuable, so the LP is reluctant to drain the battery unless the export margin is clearly worth it Stored energy is treated as easier to replace, so the LP is more willing to discharge into strong export windows
Dynamic price confidence Above-average prices beyond 6 hours are discounted toward the average Above-average prices are trusted for 12 hours before decay starts
Flow Power Happy Hour Happy Hour export prices are still shown and used, but the LP does not add a special "be full before Happy Hour" target Adds a pre-window SOC target so the battery aims to be full before the next Happy Hour export window
GloBird ZEROHERO Works from the tariff's export-price schedule; low-value positive export rates can still invite small exports More willing to spend battery energy in any positive export period, so set non-Super-Export periods to 0c if they should not trigger battery export
Grid charging before exports Charges only when the normal LP economics choose it More likely to charge ahead of a known export window if grid charging is allowed
Risk profile Lower risk of finishing the day too empty Higher risk of later grid import if solar underperforms or the next cheap charge period is missed

What Changes Internally

When the switch is off, PowerSync uses a terminal SOC weight of 1.0. The LP compares export revenue against the estimated replacement cost of stored energy, including round-trip efficiency losses. This makes the schedule more likely to hold charge for the evening, overnight load, or the next day.

When the switch is on, PowerSync lowers that terminal SOC weight to 0.3. The battery's future replacement value still exists, but it has much less influence. This makes exports more attractive and makes it easier for the LP to spend stored energy during high export periods.

For dynamic providers other than Flow Power, Profit Max also extends the confidence horizon from 6 hours to 12 hours. That means a high export price later today is discounted less aggressively, so the LP is more likely to plan around it instead of assuming it may disappear.

Flow Power is handled differently because Happy Hour is contractual rather than speculative. PowerSync does not apply confidence decay to Flow Power's fixed export window. With Profit Max on, Flow Power sites with a Happy Hour export rate get an additional pre-window SOC target: the LP tries to reach 100% before the next 17:30-19:30 Happy Hour window, with a 15-minute safety buffer. Happy Hour is 45c/kWh in NSW, QLD, and SA, 35c/kWh in VIC, and not available in TAS.

The pre-window SOC target is configurable. In Settings > Devices & Services > PowerSync > Configure > Optimization, set Profit Max full by time as an HH:MM local time. The default is 17:15, which targets full SOC 15 minutes before a 17:30 export window. This setting is also exposed through the optimization settings API used by the mobile app.

The target SOC is also configurable. The default is 100%, but sites with smaller batteries, uncertain solar, or a later overnight import risk can set a lower target so Profit Max aims for a partial fill before the export window instead of always targeting full.

GloBird ZEROHERO is not hard-coded like Flow Power. PowerSync follows the tariff schedule it reads from Tesla or the custom tariff configured in PowerSync. For ZEROHERO, set the Super Export window, commonly 6pm-9pm, to the boosted export value from the user's plan, and set export rates outside that window to 0c if those low feed-in periods should not trigger battery export. Profit Max can then help prioritise the special export window, but it will not understand the daily kWh cap by itself.

What Does Not Change

Profit Max does not remove the optimizer backup reserve or the hardware backup reserve. Those floors still apply.

Profit Max does not allow battery export into negative or zero-value export slots. Solar surplus can still export normally, but intentional battery-to-grid export is only allowed where PowerSync has an allowed export slot, such as a positive sell price, Flow Power Happy Hour, Export Boost, or a joined Octopus Saving Session.

Profit Max does not override demand charge protection, grid charging disabled settings, inverter limits, SOC limits, or force-mode/manual actions.

When to Use It

Turn Profit Max on when you have a strong, predictable export window and you want the battery to prioritise that revenue. Good fits include Flow Power Happy Hour, GloBird ZEROHERO/Super Export when the tariff export rates are shaped correctly, and dynamic tariffs where export spikes are large and reasonably reliable.

Leave Profit Max off when you want a more conservative schedule, when solar forecasts are uncertain, when overnight recharge prices are volatile, when your battery capacity is small relative to evening load, or when you mainly care about avoiding imports rather than maximising export revenue.

Example: Flow Power Happy Hour

With Profit Max off, the LP may decide that keeping SOC for later self-consumption is more valuable than fully emptying into Happy Hour, especially if the next cheap charge period is not obvious inside the horizon.

With Profit Max on, PowerSync treats Happy Hour as the target. If grid charging is allowed, the LP tries to fill the battery before the 17:30 start, blocks charging during the Happy Hour window itself, and is more willing to export stored energy during the high-rate period.

If your export window starts at a different time, update Profit Max full by time to the local time you want the battery to be full. For example, a 18:00 export window usually pairs with a target around 17:45.

Example: GloBird ZEROHERO

For GloBird ZEROHERO, the key setup is the export tariff shape. Use the user's own fact sheet, but a common current setup is:

Period Import price Export price for LP
Free charge window, e.g. 11:00-14:00 0c/kWh if applicable 0c/kWh
Super Export / ZEROHERO, e.g. 18:00-21:00 Actual import rate Boosted total export value, commonly 15c/kWh
All other periods Actual import rate 0c/kWh unless intentionally exporting for the ordinary FiT

With that shape, the LP sees only the Super Export window as valuable battery-export time. Profit Max then lowers the future-SOC penalty, making the battery more willing to export during that window. If the user leaves the ordinary low FiT as a positive export price outside the window, PowerSync may export outside ZEROHERO because the LP sees those slots as valid export opportunities.

switch.power_sync_profit_max_mode

It appears under your PowerSync device in Settings → Devices & Services → PowerSync → Configuration.

Note: Profit Max only helps static TOU plans when the tariff schedule exposes a meaningful export window. For GloBird ZEROHERO, that means positive export in the Super Export window and 0c export outside it. A flat positive FiT across the day gives the LP permission to export across the day.


Spread Export Across Window

Spread Export Across Window is an optional Smart Optimization switch for supported batteries. When it is off, the optimizer keeps the existing behaviour: if the LP decides to export stored battery energy, PowerSync commands the export action at the configured maximum discharge/export power.

When the switch is on, PowerSync keeps the LP's total planned battery-export energy for each eligible export window, but spreads that energy evenly across the whole allowed window. For example, if the LP planned 5 kWh of battery export inside a 2-hour export window, PowerSync converts that window to a flat target of about 2.5 kW instead of exporting at maximum power for a shorter period.

This is useful when you want a smoother export profile across a known window such as Flow Power Happy Hour, GloBird ZEROHERO/Super Export, Export Boost, or another positive export-price period.

Behaviour

  • Default is off.
  • Available in both normal Smart Optimization and Profit Max mode.
  • Does not create extra export beyond the LP result; it only redistributes the planned export energy.
  • Still respects the optimizer backup reserve, hardware reserve, demand-window protection, export permissions, negative/zero export blocking, off-grid overlays, calibration guards, and manual force-mode ownership.
  • The target is clamped to the configured maximum discharge/export power.

Supported Batteries

The switch is shown only for batteries where PowerSync can send a target discharge/export power:

  • GoodWe
  • Sigenergy
  • Sungrow
  • FoxESS
  • AlphaESS
  • Solax
  • SAJ H2/HS2
  • Fronius Reserva
  • Neovolt / Bytewatt

Tesla and ESY Sunhome keep the existing max-rate export behaviour. Tesla export control is tariff/mode driven rather than a reliable target-watt dispatch path, and ESY Sunhome is mode-only.

How to Enable

For existing installations, go to Settings > Devices & Services > PowerSync > Configure > Optimization and enable Spread export across window.

PowerSync also creates a Home Assistant config switch on supported batteries:

switch.power_sync_optimization_spread_export

It appears under your PowerSync device in Settings -> Devices & Services -> PowerSync -> Configuration.


Spread Import Across Window

Spread Import Across Window is an optional Smart Optimization switch for supported batteries. When it is off, the optimizer keeps the existing behaviour: planned grid charging uses the configured maximum charge power where the LP asks for charge.

When the switch is on, PowerSync keeps the LP's total planned grid-charge energy for each same-price import window, but spreads that energy evenly across the whole window. For example, if the LP planned 4 kWh of grid charging inside a 2-hour off-peak period, PowerSync converts that window to a smoother target around 2 kW instead of charging at maximum power for a shorter burst.

This is useful for free or flat off-peak import windows where you want the battery to fill steadily rather than sprint at the start of the window.

Behaviour

  • Default is off.
  • It only redistributes charge energy already planned by the LP.
  • It does not spread through blocked slots, export/discharge slots, or different-price periods.
  • It still respects grid-charge disabled settings, optimizer reserve, hardware reserve, battery capacity, maximum charge power, demand-charge protection, and manual force-mode ownership.
  • Free import slots can still be treated aggressively by the optimizer; Spread Import smooths the resulting planned energy where the battery supports target charge power.

Supported Batteries

The switch is shown only for batteries where PowerSync can send a target charge power:

  • GoodWe
  • Sigenergy
  • Sungrow
  • FoxESS
  • AlphaESS
  • Solax
  • Fronius Reserva
  • Neovolt / Bytewatt
  • SolarEdge

Tesla, ESY Sunhome, and SAJ H2/HS2 do not use this spread-import path. Tesla control is tariff/mode driven, ESY Sunhome is mode-only, and SAJ H2/HS2 uses percentage-based passive controls that are not used for this smoother charge path.

How to Enable

For existing installations, go to Settings > Devices & Services > PowerSync > Configure > Optimization and enable Spread import across window.

PowerSync also creates a Home Assistant config switch on supported batteries:

switch.power_sync_optimization_spread_import

Hardware Backup Reserve (v2.5.0+)

The hardware backup reserve is a floor that supported battery hardware enforces independently of the optimizer. This is useful as a safety net — even if the optimizer schedules a full discharge, the hardware should not go below this level.

  • Set via the mobile app: Settings > Optimization > Reserve Levels > Hardware Backup Reserve
  • This value is written through power_sync.set_backup_reserve using the percent field
  • The 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
  • ESY Sunhome and SAJ H2/HS2 do not expose backup reserve writes, so this hardware floor is not available on those systems
  • Fronius Reserva exposes this when the upstream Fronius Modbus integration provides the Reserva minimum SOC entity
  • Neovolt / Bytewatt exposes this when the upstream Neovolt integration provides the default discharging cutoff SOC entity
  • SolarEdge exposes this when the upstream SolarEdge storage-control entity set includes a writable backup reserve or minimum SOC number

Enable/Disable Optimizer

Prerequisites

Solar forecast data 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.

Configure one of:

  • Solcast Solar HA integration — install via HACS, PowerSync auto-detects it. No API key needed in PowerSync.
  • Open-Meteo Solar Forecast HA integration — install via HACS, configure your PV array geometry, and leave its API key blank unless you have your own Open-Meteo endpoint/key. PowerSync auto-detects its forecast sensors and combines multiple configured arrays.
  • Solcast API key in PowerSync — enter directly in the Weather & Solar Forecast settings. Requires a free account at toolkit.solcast.com.au.

Manual

  1. Configure a supported solar forecast source (see prerequisites above)
  2. During initial PowerSync setup, choose your electricity provider and battery system first
  3. On the Optimization Provider step, select Smart Optimization (Built-in LP)
  4. Set battery capacity, maximum charge/discharge power, the optimizer backup reserve, hardware backup reserve, grid-charge allowance, and any optional optimizer switches such as Spread export across window, Spread import across window, and Profit Max target settings
  5. Complete the battery connection step for your battery system
  6. In the mobile app: Controls > toggle Enable on the Smart Optimization card
  7. View the schedule by tapping View Full Schedule

For existing installations, go to Settings > Devices & Services > PowerSync > Configure > Optimization.

Via PowerSync Automations

Use the mobile app's Automations screen to add Enable Optimizer and Disable Optimizer actions. These are PowerSync automation actions, not Home Assistant Developer Tools services. For Home Assistant YAML automations, call power_sync.force_charge, power_sync.force_discharge, or power_sync.restore_normal as needed, and use the PowerSync app control to change the optimizer state.

Forecast Sensors

PowerSync creates forecast sensors for dashboard visibility:

Sensor Description Unit / Attributes
sensor.power_sync_lp_import_price_forecast Average grid import price over the optimizer horizon $/kWh; attributes include min_price, max_price, price_values
sensor.power_sync_lp_export_price_forecast Average export/feed-in value over the optimizer horizon $/kWh; attributes include min_price, max_price, price_values
sensor.power_sync_lp_solar_forecast Total forecast solar energy over the optimizer horizon kWh; attributes include peak_kw, forecast_values_kw
sensor.power_sync_lp_load_forecast Total forecast home load over the optimizer horizon kWh; attributes include peak_kw, forecast_values_kw
sensor.power_sync_load_forecast_today_remaining Remaining load forecast for today kWh; includes Away Mode recovery attributes when active
sensor.power_sync_load_forecast_tomorrow Tomorrow's load forecast kWh

Forecast arrays can contain 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 battery level and power
Upcoming Actions List of scheduled charge/discharge periods

Smart Optimization summary — current & next action 24-hour action plan TOU schedule and 48-period price forecast


Technical Optimizer Details

This section describes how the Smart Optimizer works internally. It is intended for users who want to understand why the LP chose a particular action, why it may hold charge instead of exporting, or why the battery returned to self-consumption at the optimizer reserve.

Solve Cycle

PowerSync's optimizer is a rolling linear program. Each solve builds a fresh forecast from the current Home Assistant state, calculates a 48-hour schedule at 5-minute resolution, stores the schedule for the dashboard and mobile app, then immediately executes the current slot.

The optimizer normally re-runs on aligned 5-minute wall-clock boundaries. It can also be triggered by fresh price data or coordinator refreshes. A lock prevents overlapping solves, so if multiple triggers arrive at the same boundary only one LP run is allowed to proceed.

The schedule is not a static upload to the battery. PowerSync keeps recalculating, then applies the current action through the active battery controller. This lets the plan react to updated prices, updated solar forecasts, changed SOC, EV charging plans, manual force modes, curtailment state, and Home Assistant restarts.

Inputs

Each solve uses these main inputs:

Input How It Is Used
Import prices Cost of drawing from the grid for each 5-minute slot
Export prices Value, or cost, of exporting to the grid for each slot
Solar forecast Expected PV generation in kW from Solcast or Open-Meteo Solar Forecast
Load forecast Expected home load in kW, learned from Home Assistant recorder history
Current SOC Starting battery state of charge
Battery capacity Converts charge/discharge power into SOC movement
Maximum charge/discharge power Caps the LP's battery power decisions
Optimizer backup reserve Software SOC floor used by the LP and execution guard
Hardware backup reserve Optional physical reserve written to supported batteries as a safety net
Grid-charge setting Controls whether grid import may charge the battery
Export permission slots Controls where intentional battery-to-grid export is allowed
EV plan Adds planned EV charging to the load forecast so the battery and EV do not fight each other
Demand charge state Adds import penalties and can override actions during demand windows

Load forecasting uses a 30-day recorder-history model grouped by local weekday and time bucket. Recorder samples are recency-weighted, outlier-clipped, and blended with same weekday/weekend history when an exact bucket is sparse. Away Mode excludes the away interval from that history window so holiday usage does not become the normal baseline.

Solar forecasting uses Solcast or Open-Meteo Solar Forecast where available. If no supported solar forecast source is configured, stale, or unavailable, the optimizer has little or no visibility of future solar and the schedule becomes mostly price-driven.

Price Processing

The prices shown in the app are the display prices. The LP may use adjusted prices internally so it can model tariff features and operational protections:

  • Dynamic provider forecasts are converted to 5-minute import/export arrays.
  • Static TOU tariffs are expanded into 5-minute forecast slots.
  • Flow Power Happy Hour is applied as a fixed export window where configured.
  • Export Boost, Octopus Saving Sessions, Chip Mode, and demand-charge penalties are overlaid before the LP solve.
  • For dynamic tariffs, confidence decay pulls far-future above-median prices toward the median. Cheap prices are preserved because cheap periods are usually structural, while distant spikes are less certain.
  • Flow Power is not confidence-decayed because Happy Hour is contractual rather than speculative.

This means the chart can show the raw tariff while the LP uses a more conservative or feature-aware price signal.

LP Formulation

When SciPy is available, PowerSync calls scipy.optimize.linprog using four variables for every time step:

Variable Meaning
grid_import[t] Grid power imported in kW
grid_export[t] Grid power exported in kW
battery_charge[t] Battery charging power in kW
battery_discharge[t] Battery discharging power in kW

The objective is cost minimisation:

minimise sum(import_price[t] * grid_import[t] - export_price[t] * grid_export[t]) * interval_hours

PowerSync then adds a few practical terms:

  • A terminal SOC value so the LP does not treat the final slot as a reason to empty the battery for free.
  • A free-electricity charge bonus so 0c import windows are used decisively.
  • Small tie-breaker values so equal-price periods form stable contiguous blocks instead of scattered one-slot actions.
  • A Profit Max terminal weight reduction when Profit Max is enabled, making future stored energy less valuable relative to near-term export revenue.

Economic Model

The LP does not simply compare the buy price and sell price directly. It models battery energy losses and the cost or opportunity cost of replacing stored energy later.

PowerSync uses a default battery efficiency of 92% in the optimizer model:

stored_energy = charge_energy * 0.92
battery_energy_used = delivered_energy / 0.92

For a grid-charge-then-discharge cycle, the effective AC-to-AC efficiency is approximately:

0.92 * 0.92 = 0.846

That means a buy/sell or buy/consume decision needs roughly an 18% higher future value before round-trip losses are covered:

future value >= buy price / (0.92 * 0.92)

Examples:

Buy price Approximate break-even future value
10c/kWh 11.8c/kWh
20c/kWh 23.6c/kWh
30c/kWh 35.4c/kWh

PowerSync does not currently add an explicit battery degradation or cycle-wear cost, such as 2c/kWh cycled. The optimizer accounts for energy losses, reserve constraints, inverter power limits, export permission windows, and stored-energy acquisition cost, but it does not currently price long-term battery wear as a separate cost.

For self-consumption, stored energy is valuable when it avoids a future import price high enough to justify the efficiency loss. For export, the optimizer checks whether the export value is worthwhile compared with import price and stored-energy acquisition cost. This helps avoid exporting energy below the best known cost of replacing it.

Constraints

The LP is bounded by physical and user-configured constraints:

  • Power balance must hold for every slot: solar, grid import, and battery discharge must cover load, grid export, and battery charge.
  • SOC must remain between the optimizer backup reserve and 100%.
  • Battery charge and discharge power cannot exceed the configured limits.
  • If grid charging is disabled, battery charging is limited to solar surplus.
  • When intentional battery export is not allowed, grid export is capped to solar surplus only.
  • Battery discharge is limited to home self-consumption unless the slot is explicitly allowed for battery-to-grid export.
  • Export must be backed by solar surplus or battery discharge; the LP cannot invent grid-import-to-export arbitrage.
  • Same-slot charge/discharge loops are blocked.
  • Charge can be blocked inside export-only windows so the battery charges before the window rather than during it.
  • Profit Max can add a pre-window SOC floor so the battery targets full SOC before a known high-value export period.

If the current SOC is already below the optimizer reserve, the normal LP would be infeasible. PowerSync temporarily uses the current SOC as the effective reserve for that solve. That lets the LP plan recovery without allowing the battery to discharge any further. If the LP is still infeasible, PowerSync relaxes the reserve as a fallback; if SciPy is unavailable or the solve fails, it falls back to a greedy scheduler.

Export Permissions

Battery-to-grid export is not allowed everywhere. PowerSync builds a per-slot export mask from:

  • Positive export-price opportunities.
  • Flow Power Happy Hour when Profit Max is enabled.
  • Export Boost windows.
  • Joined saving-session windows.

Solar surplus can still export when battery export is not allowed. The restriction is specifically about spending stored battery energy for grid export.

The LP also checks acquisition cost. If stored energy was likely bought from the grid and the export price is below that acquisition cost, discharge is restricted to home self-consumption rather than battery-to-grid export.

If Spread Export Across Window is enabled on a target-power-capable battery, PowerSync post-processes the LP schedule after these export permissions are applied. For each contiguous allowed export window, it sums the battery-export energy the LP already planned, then spreads that Wh value evenly across the full window as flat export actions. This happens independently of Profit Max; Profit Max only changes how willing the LP is to plan export and which Flow Power pre-window targets apply.

Action Mapping

The LP solves power flows, not Home Assistant service calls. After solving, PowerSync maps the flow result to user-visible actions:

Action Technical Meaning
charge Grid import is greater than home load and battery charge power is above the action threshold. Free import slots are forced to max charge.
export Battery discharge and grid export are both above the action threshold.
idle The LP wants to hold useful SOC for a future opportunity while the home draws from grid.
self_consumption Natural battery operation: solar charging, battery serving home load, or no forced action needed.
off_grid A Tesla-only post-LP curtailment overlay physically disconnects the site from grid during eligible low-value export periods.

The action threshold is 100 W, which avoids rapid action changes from tiny solver values.

idle is deliberately different from self_consumption. In idle, PowerSync is trying to hold SOC for later, so it may use a hold mode or a temporary reserve change. In self_consumption, the battery should behave naturally and serve the house, subject to the hardware reserve.

Execution Layer

After a solve, PowerSync immediately executes the current slot. The polling loop then keeps re-solving and reapplying actions on 5-minute boundaries.

Execution is battery-system specific:

  • charge calls the controller's force-charge path for the current action window.
  • export calls the force-discharge path. By default, PowerSync requests the configured maximum discharge power because many inverters use that value as an export limit. When Spread Export Across Window is enabled on a supported target-power battery, PowerSync uses the post-processed action power instead.
  • idle uses the safest available hold mechanism for the battery system. This can be a native hold/backup mode, a temporary backup reserve change, or self-consumption mode when no stronger hold is available.
  • self_consumption calls the battery's self-consumption or restore-normal path and avoids unnecessary repeat API calls when the hardware is already in the right mode.
  • off_grid delegates to the Tesla local curtailment fallback, which enforces pairing, SOC, duration, and reconnection checks.

When leaving idle, PowerSync restores the pre-idle reserve or work mode before applying the new action. This prevents a temporary hold value from becoming the user's permanent hardware reserve.

Optimizer Reserve vs Hardware Reserve

The optimizer backup reserve is a software floor. It means the LP must not plan forced discharge/export below that SOC, and the executor must stop forced/max discharge once the battery reaches the floor.

At or below the optimizer reserve, PowerSync should return the battery/inverter to self_consumption, not keep it in an optimizer discharge/export mode and wait for hardware to stop it. This contract applies across supported battery systems.

The hardware backup reserve is separate. Where supported, it is a physical or manufacturer-enforced floor. It is best treated as a lower safety net, usually a few percent below the optimizer reserve. The optimizer reserve controls scheduling intent; the hardware reserve is a last line of defence.

Runtime Safeguards

Before executing the LP action, PowerSync applies runtime guards:

  • Blocks forced export/discharge when current SOC is at or below the optimizer reserve.
  • Overrides export to self-consumption when the current export price is below 1c/kWh.
  • Skips force charge/export during suspected battery calibration.
  • Overrides idle to self-consumption during demand-charge windows so the battery helps reduce grid import.
  • Blocks export near demand windows when preserving battery is more valuable.
  • Reconnects from off-grid before any action that needs the grid.
  • Retries pending reserve restoration after IDLE until it succeeds.
  • Cancels optimizer-created force modes if the new LP plan changes direction.

Manual force modes are tracked separately from optimizer-created force modes so a user command is not accidentally treated as an LP decision.

Why the Schedule May Look Conservative

The LP is not only chasing the highest price in the visible chart. It also accounts for:

  • Round-trip efficiency losses.
  • The cost or opportunity cost of replacing stored energy later.
  • The optimizer backup reserve.
  • Whether battery export is allowed in that slot.
  • Whether solar is forecast to refill the battery.
  • Whether the export price is real, boosted, contractual, or speculative.
  • Upcoming EV charging and home load.
  • Demand-charge protection and other overlays.
  • Battery-specific execution limits.

For example, the optimizer may hold SOC during a moderate-price period if a stronger export window is forecast later, or it may avoid export if the sell price does not beat the value of using that energy for home load after efficiency losses. Profit Max reduces that future-SOC penalty, so it is more willing to spend stored energy in high-value export windows, but it still respects reserves, export permissions, and hardware limits.

Clone this wiki locally