Prose traduite pour Présentation, Protocole, Contrat, Écrire un optimiseur et la page du moteur ; ancres de titres identiques dans les trois langues. Les blocs générés sont identiques d'une langue à l'autre. Les exemples gardent un motif en français, comme l'exige le contrat. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
4.9 KiB
Writing an optimizer
An optimiser is a server that speaks the protocol: it answers the
handshake, then every GetPlan with a plan of one or more slots, or with an abstention.
Any language will do. A minimal optimiser fits in about fifty lines of Python.
Minimal session, for illustration (the exact shape is in the contract):
→ {"jsonrpc":"2.0","id":1,"method":"Handshake","params":{"protocolVersion":"1.1","engine":"etm-powersync-energy-plugin-etm/…"}}
← {"jsonrpc":"2.0","id":1,"result":{"protocolVersion":"1.1","name":"my-optimiser","planning":false}}
→ {"jsonrpc":"2.0","id":2,"method":"GetPlan","params":{ …context… }}
← {"jsonrpc":"2.0","id":2,"result":{"abstain":true,"reason":"premier calcul en cours"}}
Three things not to miss:
- one action per available load in the current slot, each with its reason as text: otherwise the whole plan is rejected (the reason text is in French);
- answer quickly: serve the last cached plan, or abstain, and compute in the background;
- fetch nothing elsewhere: everything the optimiser needs, forecasts included, is in the context.
The reference optimiser
The engine repository contains a free reference optimiser (GPL-3.0), in Python, standard
library only:
tools/etm-powersync-ref-optimizer/.
It answers a one-slot plan that reproduces the cascade of the engine's rules, reading only
the context. At handshake it announces itself as powersync-optimizer.
It is a starting point for writing your own, and a point of comparison: it listens on the
local socket by default, or on tcp:// with a shared secret read from a file. It can also
inject faults (abstention, slowness, invalid plan, different major version…) to test the
engine's fallback. Instructions:
its README.md.
Pointing the engine at your optimiser
Three JSON-RPC methods of the box, reserved to the administrator, described in
INTERFACE.md:
NymeaEnergy.SetOptimizerEndpoint— where to connect (unix:///…ortcp://host:port);NymeaEnergy.SetOptimizerToken— the shared secret, the same as the optimiser's;NymeaEnergy.GetOptimizerStatus— connection status: optimiser alive, active strategy, announced name, last error code.
Over tcp:// without encryption, the secret travels in clear text on the local network.
The conformance suite
The etm-powersync-optimizer-conformance suite starts your optimiser and connects the
real engine to it, on simulated devices. It checks, one function per point:
- the handshake is accepted;
- every
GetPlanis answered within the engine's timeout; - the whole session, both ways, conforms to the contract embedded in the engine, validation rules included;
- every plan is applied: the optimiser is in control;
- the safety loop stays on top: an out-of-bounds setpoint is clamped, a phase overload is shed.
It does not judge the quality of the plans.
Running it against your optimiser
Build the engine with its tests, then give the command that starts your server;
{endpoint} in it is replaced by the address to listen on:
export ETM_POWERSYNC_OPTIMIZER_CMD='exec /path/to/my-optimiser --listen {endpoint}'
export ETM_POWERSYNC_CONFORMANCE_EXPECT=plan # or abstain
Each function runs in its own process. The full command (network isolation recommended),
the other variables (shared secret, start-up delay…) and how to read failures are in the
suite's README.md.
Expected mode: plan or abstain
ETM_POWERSYNC_CONFORMANCE_EXPECT tells the suite what your optimiser does:
plan(default): it is in control. Every cycle must apply its plan.abstain: it abstains on every cycle — that is allowed, and conformant. The suite then checks that the engine drives by its rules on every cycle, without counting a failure, and that safety still holds; the clamping check is skipped, as there is no setpoint to clamp.
Any other value makes the suite fail. The mode is not inferred from the handshake:
planning and capabilities describe the shape of plans, not whether any are produced.
The mode is given, not guessed.
Comparing on the same inputs
The engine can record, on the box, a trace of every cycle (off by default,
NymeaEnergy.SetOptimizerTrace). The tools/etm-powersync-trace-replay tool replays these
traces against a candidate optimiser and summarises the differences from the recorded plan.
Traces stay on site.