Strategies
Strategies are the gateway's autonomous control modes. Each strategy is responsible for computing a battery setpoint on every control cycle and dispatching a SetBatterySetpointCommand. The active strategy is selected by the platform and stored in the gateway's desired state; the gateway applies it on a recurring tick.
Available Strategies
| Strategy | Description |
|---|---|
| Net Zero | Minimises grid import/export using a PID feedback loop |
| Discharge | Discharges the battery at maximum power until MinStateOfCharge is reached |
| Charge | Charges the battery at maximum power until MaxStateOfCharge is reached |
| Peak Shaving | Reduces peak grid demand by capping import above a target threshold |
| Manual | Suppresses automatic strategy execution; only explicit commands are accepted |
Common Behaviour
All strategies share these mechanisms regardless of their specific logic.
Mode Gate
Before any strategy runs, ApplyStrategyCommandHandler checks the current GatewayMode. If the gateway is in Manual mode, the strategy is skipped entirely and the command returns without calling IStrategy.ApplyStrategy. This gate applies to every strategy - individual strategy code never needs to check the mode.
The gateway can be switched between modes via the platform API. See Gateway Service for details.
AbstractStrategy Base Class
All concrete strategies extend AbstractStrategy, which provides two helpers used at the start of every control cycle:
GetBatteryConfiguration()- loads the currentBatteryConfiguration(SoC limits, power limits, PID tuning, control parameters) for the single battery asset.GetBatteryName()- resolves the asset name used in subsequent commands and queries.
Both helpers throw InvalidOperationException if no battery asset is configured, which surfaces as a strategy failure log and does not crash the gateway process.
SoC Guard
Every strategy checks the battery SoC against MinStateOfCharge and/or MaxStateOfCharge before dispatching a setpoint. The exact guard and fallback behaviour differs per strategy - see each strategy's page for specifics.
Terminal Action
Every strategy cycle ends with SetBatterySetpointCommand(batteryName, setpointWatts, mode), where mode is one of Charging, Discharging, or Idle. The setpoint and mode are the only two things a strategy produces.
Registration
Strategies are registered as keyed singletons in StrategyRegistration.AddStrategies(), keyed by their Strategy enum value. StrategyFactory resolves the correct instance at runtime via [FromKeyedServices].
Because strategies are singletons they must be thread-safe. Stateful strategies (e.g. Net Zero, which holds a PidController) must manage their internal state carefully.
Behaviour Tests
Gateway-level mode-gating behaviour is covered by GatewayModeBehaviorTests (LightBDD, Voltimax.Edge.Gateway.BehaviorTests):
- Manual mode suppresses strategy execution -
ApplyStrategyCommandis dispatched butIStrategy.ApplyStrategyis never called. - Auto mode allows strategy execution - the resolved strategy runs normally.