Python 3, bibliothèque standard seule, GPL-3.0. Socket unix par défaut (unix:///run/powersync/optimizer.sock, 0660), tcp:// accepté. Handshake (majeure, capacités, token lu dans un fichier et relu à chaque handshake, -32001 puis fermeture s'il diffère), GetPlan, abstention, plusieurs clients à la fois (un fil par connexion, plan fonction pure de la requête). Plan à un créneau qui reproduit la passe confort du waterfall rule-based depuis le seul contexte GetPlan : tri (rang, id), surplus net signé, recrédit, réserve de stockage, plancher, plafond, verrous, mapping SG-Ready avec hystérésis. Codes du catalogue émissible seulement, clés documentées seulement (--list-codes, confronté au moteur par le test). Modes d'injection : normal, abstain, slow, invalid, expired, wrong-major, drop, unknown-load, forbidden-kind, missing-load, echo-token, protocol-1.0, deviate ; --mode-file pour changer de mode sans reconnexion. README. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
68 lines
3.5 KiB
Markdown
68 lines
3.5 KiB
Markdown
# `etm-powersync-ref-optimizer` — optimiseur de référence
|
|
|
|
Python 3, bibliothèque standard seule, GPL-3.0 comme le dépôt. Protocole : `docs/OPTIMIZER_PROTOCOL.md`
|
|
1.1 (annexe E). Il répond un plan à **un créneau** qui reproduit le waterfall du rule-based (passe
|
|
confort : même ordre, même budget, mêmes écrêtages) en ne lisant **que** le contexte `GetPlan` — aucun
|
|
accès réseau sortant, aucun fichier hors le token. Usages : test de bout en bout du moteur, point de
|
|
comparaison d'un banc, exemple pour qui écrit son propre optimiseur.
|
|
|
|
Ce qu'il ne reproduit pas (le contexte 1.1 ne le porte pas) : passe éco, dérogations, plafond de
|
|
soutirage, paliers d'un `relay-router` (il envoie une consigne continue que le routeur arrondit),
|
|
refus de commande, proxy VE. L'en-tête du script le détaille.
|
|
|
|
## Lancer
|
|
|
|
```sh
|
|
# socket local (défaut : unix:///run/powersync/optimizer.sock, mode 0660)
|
|
./tools/etm-powersync-ref-optimizer/etm-powersync-ref-optimizer
|
|
|
|
# sur le LAN, avec un token (lu dans un FICHIER, jamais en argument)
|
|
./tools/etm-powersync-ref-optimizer/etm-powersync-ref-optimizer --listen tcp://0.0.0.0:7600 \
|
|
--token-file /etc/powersync/optimizer.token
|
|
```
|
|
|
|
Il écrit `ÉCOUTE <endpoint>` sur la sortie standard quand il écoute (le port réel de `tcp://…:0`),
|
|
et son journal sur la sortie d'erreur. Plusieurs clients à la fois (un fil par connexion, aucun état
|
|
partagé) : le moteur et un rejeu peuvent lui parler ensemble. SIGTERM l'arrête proprement.
|
|
|
|
## Pointer le moteur dessus
|
|
|
|
```sh
|
|
# méthodes NymeaEnergy (permission Admin) — INTERFACE.md, « Optimiseur »
|
|
NymeaEnergy.SetOptimizerEndpoint {"endpoint": "unix:///run/powersync/optimizer.sock"}
|
|
NymeaEnergy.SetOptimizerToken {"token": "<le même secret que dans --token-file>"} # clé seule
|
|
NymeaEnergy.GetOptimizerStatus # optimizerAlive, activeStrategy, name, lastErrorCode…
|
|
```
|
|
|
|
Sur `tcp://` sans TLS, le token circule en clair sur le LAN (protocole §3).
|
|
|
|
## Traces, puis rejeu
|
|
|
|
```sh
|
|
NymeaEnergy.SetOptimizerTrace {"enabled": true} # défaut : désactivé
|
|
NymeaEnergy.GetOptimizerTrace # → directory
|
|
# une ligne par cycle : <directory>/etm-powersync-optimizer-trace-AAAA-MM-JJ.ndjson
|
|
|
|
# rejouer une journée sur un optimiseur (celui-ci, ou un candidat)
|
|
./tools/etm-powersync-trace-replay <directory>/etm-powersync-optimizer-trace-2026-10-17.ndjson \
|
|
--endpoint unix:///run/powersync/optimizer.sock --fail-on-divergence
|
|
```
|
|
|
|
Le rejeu compare, cycle par cycle, les actions du créneau courant au plan enregistré (`tools/README.md`).
|
|
|
|
## Modes d'injection de défauts (`--mode`, tests)
|
|
|
|
`normal` · `abstain` · `slow` (répond après `--slow-s`, défaut 12 s, au-delà des 10 s du moteur) ·
|
|
`invalid` (`slots` n'est pas une liste) · `expired` (`validUntil` passé) · `wrong-major` (handshake
|
|
2.0) · `drop` (ferme la connexion à chaque `GetPlan`) · `unknown-load` · `forbidden-kind` (kind
|
|
`constraint`) · `missing-load` (une charge disponible absente du créneau courant) · `echo-token`
|
|
(recopie le token dans `reason` et `planId`) · `protocol-1.0` (optimiseur 1.0 : sans champs 1.1) ·
|
|
`deviate` (cascade en ordre inverse : doit diverger).
|
|
|
|
`--mode-file FICHIER` : le mode est relu dans ce fichier à chaque message — un test change de mode
|
|
sans reconnexion. `--list-codes` : le catalogue des codes émissibles qu'il embarque (le test
|
|
d'intégration le confronte au moteur).
|
|
|
|
Tests : `tests/auto/refoptimizer` (suite `etm-powersync-refoptimizer`, moteur réel + ce script en
|
|
sous-processus).
|