# Einen Optimierer schreiben Ein Optimierer ist ein **Server**, der das [Protokoll](protocole.md) spricht: Er antwortet auf den Handshake und dann auf jedes `GetPlan` mit einem Plan aus einem oder mehreren Zeitfenstern oder mit einer Enthaltung. Die Sprache ist frei. Ein minimaler Optimierer passt in rund fünfzig Zeilen Python. Minimale Sitzung, zur Veranschaulichung (die genaue Form steht im [Vertrag](contrat.md)): ```text → {"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":"mein-optimierer","planning":false}} → {"jsonrpc":"2.0","id":2,"method":"GetPlan","params":{ …Kontext… }} ← {"jsonrpc":"2.0","id":2,"result":{"abstain":true,"reason":"premier calcul en cours"}} ``` Drei Punkte, die man nicht übersehen sollte: - **eine Aktion je verfügbarem Verbraucher** im aktuellen Zeitfenster, jede mit ihrem **Grund** als Text (auf Französisch): sonst wird der ganze Plan abgelehnt; - **schnell antworten**: den zuletzt zwischengespeicherten Plan liefern oder sich enthalten, und im Hintergrund rechnen; - **nichts anderswo holen**: Alles, was der Optimierer braucht, Prognosen inbegriffen, steht im Kontext. ## Der Referenz-Optimierer {#reference} Das Engine-Repository enthält einen freien Referenz-Optimierer (GPL-3.0) in Python, nur mit der Standardbibliothek: [`tools/etm-powersync-ref-optimizer/`](https://git.etm-powersync.fr/ETM-Schurig/etm-powersync-energy-plugin-etm/src/branch/main/tools/etm-powersync-ref-optimizer). Er antwortet mit einem Plan aus einem Zeitfenster, der die Kaskade der Engine-Regeln nachbildet, und liest dabei nur den Kontext. Beim Handshake meldet er sich als `powersync-optimizer`. Er ist Ausgangspunkt für einen eigenen Optimierer und Vergleichsmaßstab: Er lauscht standardmäßig am lokalen Socket oder an `tcp://` mit einem gemeinsamen Geheimnis, das aus einer Datei gelesen wird. Er kann auch Fehler einspeisen (Enthaltung, Langsamkeit, ungültiger Plan, andere Hauptversion…), um den Rückfall der Engine zu testen. Anleitung: [seine `README.md`](https://git.etm-powersync.fr/ETM-Schurig/etm-powersync-energy-plugin-etm/src/branch/main/tools/etm-powersync-ref-optimizer/README.md). ## Die Engine an den eigenen Optimierer anbinden {#brancher} Drei JSON-RPC-Methoden der Box (die ersten beiden dem Administrator vorbehalten); ihre genaue Form liefert die Box selbst über `JSONRPC.Introspect`: - `NymeaEnergy.SetOptimizerEndpoint` — wohin verbinden (`unix:///…` oder `tcp://host:port`); - `NymeaEnergy.SetOptimizerToken` — das gemeinsame Geheimnis, dasselbe wie beim Optimierer; - `NymeaEnergy.GetOptimizerStatus` — Zustand der Verbindung: Optimierer lebt, aktive Strategie, gemeldeter Name, letzter Fehlercode. Über `tcp://` ohne Verschlüsselung läuft das Geheimnis im Klartext durch das lokale Netz. ## Die Konformitäts-Testsuite {#conformite} Die Suite `etm-powersync-optimizer-conformance` startet **Ihren** Optimierer und schließt die **echte** Engine daran an, mit simulierten Geräten. Sie prüft, eine Funktion je Punkt: 1. der Handshake wird angenommen; 2. jedes `GetPlan` wird innerhalb der Frist der Engine beantwortet; 3. die gesamte Sitzung, in beide Richtungen, entspricht dem von der Engine mitgebrachten Vertrag, Prüfregeln inbegriffen; 4. jeder Plan wird angewendet: Der Optimierer steuert; 5. die Sicherheitsschleife bleibt obenauf: Ein Sollwert außerhalb der Grenzen wird gekappt, eine Phasenüberlast wird abgeworfen. Die **Qualität** der Pläne bewertet sie nicht. ### Gegen den eigenen Optimierer ausführen Die Engine mit ihren Tests bauen, dann den Befehl angeben, der Ihren Server startet; `{endpoint}` wird darin durch die Adresse ersetzt, an der gelauscht werden soll: ```sh export ETM_POWERSYNC_OPTIMIZER_CMD='exec /pfad/zu/mein-optimierer --listen {endpoint}' export ETM_POWERSYNC_CONFORMANCE_EXPECT=plan # oder abstain ``` Jede Funktion läuft in einem eigenen Prozess. Der vollständige Befehl (Netzisolierung empfohlen), die übrigen Variablen (gemeinsames Geheimnis, Startfrist…) und das Lesen der Fehlschläge stehen in der [`README.md` der Suite](https://git.etm-powersync.fr/ETM-Schurig/etm-powersync-energy-plugin-etm/src/branch/main/tests/auto/conformance/README.md). ### Erwarteter Modus: `plan` oder `abstain` {#mode-attendu} `ETM_POWERSYNC_CONFORMANCE_EXPECT` sagt der Suite, was Ihr Optimierer tut: - **`plan`** (Standard): Er steuert. Jeder Zyklus muss seinen Plan anwenden. - **`abstain`**: Er enthält sich in jedem Zyklus — das ist erlaubt und konform. Die Suite prüft dann, dass die Engine in jedem Zyklus nach ihren Regeln steuert, ohne Fehler zu zählen, und dass die Sicherheit weiter greift; die Prüfung der Kappung entfällt, da es keinen Sollwert zu kappen gibt. Jeder andere Wert lässt die Suite scheitern. **Der Modus wird nicht aus dem Handshake abgeleitet**: `planning` und `capabilities` beschreiben die Form der Pläne, nicht, ob welche erzeugt werden. Der Modus wird angegeben, nicht erraten. ## Auf denselben Eingaben vergleichen {#traces} Die Engine kann auf der Box jeden Zyklus aufzeichnen (standardmäßig aus, `NymeaEnergy.SetOptimizerTrace`). Das Werkzeug `tools/etm-powersync-trace-replay` spielt diese Aufzeichnungen einem Kandidaten-Optimierer vor und fasst die Abweichungen zum aufgezeichneten Plan zusammen. Die Aufzeichnungen bleiben vor Ort.