Technical & Architecture Documentation

Under the hood of Orza.

Answers for engineers and battery owners: how Orza reaches a battery it cannot see, the linear programme behind the plan, what Watch mode never touches, and zero-hindsight accounting.

Section 01

The cloud read path

How does Orza reach my battery?

Through the cloud API your manufacturer already runs, authorised by the account you already have. For a Sigenergy system that is the Sigen OpenAPI: you authorise it with your Sigen login, and Orza calls openapi/systems/{systemId}/energyFlow for PV, grid, load and battery power in kW plus battery state of charge. That endpoint is rate-limited to once every five minutes per station, which sets the resolution of everything downstream.

Nothing is installed in your house. No hub, no Raspberry Pi, no always-on computer, no software on your network, no Modbus, no port to open. Your inverter sits behind your router where no server can reach it, and we do not try. The manufacturer's cloud is the only way in, and it is the only way we use.

Why cloud rather than a local connection?

A local link over Modbus is faster and more precise, and we built one; we then decided against ever shipping it. Asking an owner to keep a computer running in order to save money on electricity is a support burden, a security surface and a thing that breaks while you are on holiday. The honest trade is a coarser connection that needs nothing from you, and a product that says plainly which batteries it can and cannot reach.

The cost is real and we would rather state it: five-minute resolution instead of ten seconds, and only the channels the manufacturer chooses to publish.

What can the cloud not tell you?

For Sigenergy: no pack temperature, no state of health, no alarms, and no per-battery-unit breakdown. Those exist in the local Modbus registers and are unreachable without hardware in the house, so as far as this product is concerned they do not exist. adapters/capabilities.py records, per brand, exactly which fields are genuinely reported; the app reads that table and shows a stated reason where a field is missing. It never estimates one and presents it as measured.

What happens when a read fails?

It is recorded as a failure, not as a zero. A half hour with no reading behind it is marked missing, and any day containing one is left out of your savings headline entirely rather than being quietly averaged: a battery pays in one half hour and is repaid in another, so excluding single slots inverts the arithmetic. The gap stays visible in the ledger.

Section 02

The 48-hour optimisation engine

Why solve for 48 hours instead of a rule-based timer?

Simple timers ("charge between 02:00 and 05:00") only look at one night in isolation. They have no idea if tomorrow afternoon will have blazing solar or negative electricity export rates, or if tomorrow night will be 3× more expensive.

Orza treats scheduling as a formal optimisation problem: a linear programme over 96 half-hour intervals, the next two full days, solved all at once rather than slot by slot. Every variable is continuous, so it is a pure LP rather than a mixed-integer one, and it is solved with the open-source CBC solver through PuLP. Solving the whole horizon at once is what avoids the greedy mistake of spending cheap charge tonight that tomorrow evening needed.

What is the solver's objective function?

The solver minimizes total net expenditure over the 48-hour horizon:

Cost = ∑ (Grid Import × Import Price) - ∑ (Grid Export × Export Price) + ∑ Degradation Cost

subject to strict physical constraints: battery energy conservation, maximum inverter charge/discharge kW ratings, round-trip efficiency losses (e.g. 91% for DC-coupled systems), state-of-charge limits (e.g. 10% min reserve, 100% max), and forecasted solar generation.

Does frequent cycling degrade battery cell longevity?

No. We explicitly penalize battery throughput in the solver objective function via a configurable cell degradation cost (typically 1.5p to 3.0p per cycled kWh, based on LFP cycle life warranties). The solver will never cycle your battery to chase fractional-penny margins.

Section 03

The Zero-Hindsight Cost Ledger

What does "Never score with hindsight" mean?

The easy way to produce a big saving is to wait until the day is over, take the solar and load that actually happened, and work out the perfect plan with that knowledge. No plan could have known that in advance, so the number flatters the product.

Orza scores every half hour against the forecast snapshot as it stood when the plan was made. If cloud rolled in unexpectedly, the plan is judged on the forecast it had, not the weather that arrived. Both sides of the comparison, what your system did and what that plan would have done, go through the same costing engine. The saving is the plan measured against what your own system actually did, not against an imaginary battery doing nothing.

How is the baseline calculated?

The baseline represents what your battery would have done under the manufacturer's default self-consumption mode (storing daytime solar, powering nighttime household load until empty, and charging nothing from the grid). We replay both paths through a single authoritative cost function in simulate().

Section 04

Safety, and what we never touch

What happens if Orza goes down?

Your battery carries on. It is your inverter running your manufacturer's own logic, and Orza is not in the power path. There is nothing of ours in your house to crash, and no instruction of ours for your battery to be waiting on. In Watch mode we are a reader: if we stop reading, the ledger shows the gap and your electricity keeps working exactly as it did before you signed up.

Can Orza override hardware safety limits?

It cannot. In Watch mode it sends nothing at all. Even when opt-in control arrives, the only route in is the manufacturer's own API, which accepts a narrow set of documented instructions and applies its own firmware and BMS limits (cell voltage, current, temperature cutoffs) underneath anything we ask for. We cannot reach past that interface, by design, because we have no presence in your house.

Can I override Orza?

In Watch mode there is nothing to override: no instruction is ever sent, so your manufacturer's app remains the only thing telling your battery what to do. When opt-in control arrives, pausing will stop the next instruction rather than racing the last one, and your manufacturer's app and the inverter itself will always outrank us.

Section 05

Tariffs, Half-Hourly Settlement & Forecasts

Which tariffs work best with Orza?

Dynamic and time of use tariffs, import and export. Dynamic tariffs such as Octopus Agile are where the product is worth most, because prices swing from below zero to over 30p/kWh within a day. The engine takes any half hourly price series, so multi-rate tariffs with fixed off-peak windows work the same way.

When are new schedules generated?

Octopus publishes tomorrow's half-hourly Agile prices each afternoon, usually between 16:00 and 16:30. Orza fetches them as soon as they land and re-solves the 48-hour plan; it also re-solves through the day as fresh readings and a fresh solar forecast arrive. In Watch mode the resulting plan is recorded and scored, not sent anywhere.

Section 06

Security, Encryption & Privacy

How is the account I connect stored?

The credential you authorise, your manufacturer account or an API key, is sealed with AES-256-GCM before it is stored, and only the backend holds the key. The browser cannot read or write that table at all, and no credential is ever logged or returned to a page. If the encryption key is missing, the endpoint refuses the request rather than storing anything in plaintext; that is deliberate.

Who owns my telemetry data?

You do. Your historical generation, consumption, and dispatch logs belong to you. We do not monetize, resell, or aggregate your private home usage patterns for advertising.

Ready to see what your battery can do?

Join the free beta. Connect your battery in read-only Watch mode and see what a better plan would have saved on your own house.

Join the free beta