Vue d'ensemble : entrées, protection contre la surcharge, cycle de répartition en six étapes, optimiseur en option, adaptateurs, charges. Rangs et domaines : une seule liste pour le moteur ; les domaines ne servent qu'à l'affichage de l'app, un chauffe-eau peut être servi en dernier. Encadré : une borne détectée arrive en fin de liste. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ry3vBrJT1tHdxAaXdCWi6L
8.9 KiB
How the engine decides
COMMUNITY
The box's energy engine drives your loads on its own: EV chargers, water heater, SG-Ready heat pump, relays. It is free software (GPL-3.0) and it is the one that decides in the Community edition. This page describes its logic for installers and integrators; the following pages detail each feature.
Overview
flowchart TB
CPT["Grid meter<br/>current per phase, export, import"]
BAT["Battery<br/>state of charge"]
APP["App<br/>one-off requests"]
CFG["Installer settings<br/>ranks, bounds, obligations"]
subgraph M["Energy engine, on the box"]
PROT["Overload protection<br/>on every measurement, overrides"]
subgraph C["Allocation cycle, every minute"]
C1["1. Measurement and draw margin"] --> C2["2. Charging deadlines"]
C2 --> C3["3. Battery reserve"]
C3 --> C4["4. Eco pass<br/>one-off requests, obligations"]
C4 --> C5["5. Comfort pass<br/>surplus in cascade, by rank"]
C5 --> C6["6. One command per load"]
end
AD["Adapters<br/>bounds and locks of each load"]
end
OPT["Optimizer, optional<br/>proposes the allocation"]
VE["EV chargers"]
ECS["Water heaters<br/>relay or adjustable"]
PAC["SG-Ready heat pump"]
REL["Relays"]
CPT --> PROT
CPT --> C1
BAT --> C3
APP --> C4
CFG --> C
OPT -. "plan" .-> C6
C6 --> AD
PROT --> AD
AD --> VE & ECS & PAC & REL
Overload protection and the adapters always stay with the engine: an optimizer, if connected, only proposes the allocation.
Two loops, two priorities
The engine keeps safety apart from allocation. They are two separate loops, running at different rates and with different priorities.
- Overload protection, on every measurement. As soon as the measured balance changes, the engine reads the current of each phase at the grid meter. If a phase exceeds the configured limit, it immediately lowers the current of the EV chargers, then releases it when the margin returns. The other loads (water heater, heat pump, relays) are shed at the start of the next cycle (load management). This protection overrides any allocation decision.
- The allocation cycle, every minute. It shares the available power between the loads, on the one-minute measurement of the electrical balance, and runs again right away when you change a setting. It is the only place where a strategy comes in: the built-in rules, or an optimizer if one is connected.
If the grid meter goes silent (more than 90 s without a reading), the engine suspends allocation and puts the loads in a safe position: adjustable loads at 0 W, relays open, heat pump in normal operation, chargers already charging brought down to minimum current, no new load started. Overload protection stays active. Allocation resumes on the cycle after the meter comes back.
The rules, in order
On every cycle, the engine applies the same steps, in the same order.
- Measure. The starting point is what the grid meter measures (export and import). The engine also derives the draw margin from it: what the installation can still take from the grid without exceeding the phase limit. No grid purchase, whatever its reason, goes beyond it.
- Serve charging deadlines. A vehicle that must be charged by a given time is served from the grid, outside the surplus sharing.
- Protect the battery. If a home battery is below its reserve threshold, the surplus goes to it first: the controlled loads get none of it. Above the threshold, what it absorbs counts as available surplus. Its discharge is never counted as surplus.
- Guaranteed needs ("eco" pass). First the one-off requests made from the app ("heat now"): the load gets its full power, whatever its rank. Then the daily obligations, for example a minimum amount of energy for the water heater before a given time: the engine buys the missing energy from the grid, spread evenly until the deadline, and switches to full power when only the time strictly needed is left. These purchases stay within the draw margin.
- Share the surplus in cascade ("comfort" pass). Loads are served in the
priority order you set (1 = served first). Each receives what is left of the
budget, within its bounds, and the budget is decreased accordingly. There is one
budget: without it, three managers would each see "2 kW of surplus" and draw 6. In
turn, for each load:
- what it already consumes is given back to it: a running load is not counted against itself;
- below its minimum power, it stays off rather than running at half power, and the budget moves on to the next one. An EV charger may still start with a small top-up from the grid, within the configured tolerance;
- a load under lock (minimum on or off time, delay between two changes) keeps its current power;
- an unavailable load keeps its current power, with no new setpoint; what it consumes is still counted.
- One command per load. The guaranteed need and the surplus share of the same load are merged: each load receives a single setpoint, with its reason.
Ranks and domains
The engine knows only one list: each load has a rank, across all categories, and the cascade follows that rank. A load's domain (electric vehicle, domestic hot water, air conditioning, heating, battery) is a label chosen by the installer: the engine does not read it to decide.
The app uses it to present the service order by domain: you set the order of the domains, then the order of the loads within each domain. At commissioning it proposes: electric vehicle, domestic hot water, air conditioning, heating. Since everything rests on the single list, nothing forces the loads of a domain to follow each other: a backup water heater can be served last of all, after the heating, and one charger can come before the water heater while another comes after.
flowchart LR
subgraph AV["Proposed order"]
direction TB
a1["1 · EV garage"] --> a2["2 · EV visitor"] --> a3["3 · Main water heater"] --> a4["4 · Backup water heater"] --> a5["5 · Heat pump"]
end
subgraph AP["After adjustment"]
direction TB
b1["1 · EV garage"] --> b2["2 · Main water heater"] --> b3["3 · EV visitor"] --> b4["4 · Heat pump"] --> b5["5 · Backup water heater"]
end
AV ==>|"only ranks change"| AP
classDef ev stroke:#3b82f6,stroke-width:3px
classDef ecs stroke:#ef4444,stroke-width:3px
classDef chauf stroke:#f59e0b,stroke-width:3px
class a1,a2,b1,b3 ev
class a3,a4,b2,b5 ecs
class a5,b4 chauf
Blue border: electric vehicle · red: domestic hot water · orange: heating.
!!! tip "Set the ranks at commissioning" A detected charger is added automatically at the end of the list, whatever its domain. Two loads with the same rank are separated by their identifier, which nobody chose. Set the order in the app at commissioning.
The bounds of each load
Each load carries bounds entered by the installer, which every decision respects, whatever the strategy:
- a power floor and ceiling. For an EV charger they are in current (times the number of phases), and the ceiling is further capped by the phase limit;
- anti-flapping locks: minimum on and off time, delay between two changes. An EV charger has its own (delay between on and off, delay between two current changes);
- for an SG-Ready heat pump: the state chosen from the estimated power of each state, with hysteresis and a minimum hold time. The blocking state is never commanded by the surplus.
The reason for every decision
The engine makes no decision without stating why. Every decision carries a non-empty
reason (decisionReason): a stable code and its parameters, which the app displays
in your language — "insufficient surplus", "below minimum power", "charging deadline"…
The list of codes is published with the
optimizer protocol.
The measurement, never the result of control
The surplus is computed on the raw measurement of the grid meter, as measured. Never on a balance recomputed after control: the engine would be reading itself and would oscillate.
Without internet
Everything above runs on the box. Without internet, the engine controls, applies safety and answers the app on your local network. Only the PV forecast stops. In the Community edition, neither the forecast nor the entered tariff enters the decisions of the rules: both are displayed and recorded, never used to decide.
And an optimizer?
An optimizer can propose a plan over several hours, based on forecasts. It replaces the allocation step, never the overload protection or the bounds. See the Optimizer section.