+etm23 rend à chaque borne détectée une entrée GetLoadConfig, et l'invariant loads[] ⊆ GetLoadConfig est rétabli. Sur .75 : 2 entrées → 4. L'app s'appuyait déjà sur cet invariant pour résoudre libellé, domaine et rang de toute charge publiée. Vérifié sur machine avant d'écrire quoi que ce soit : - l'aller-retour verbatim reste NEUTRE avec les quatre entrées (loadconfig_roundtrip.dart, verdict IDENTIQUE) ; - une entrée evcharger porte id/label/domain/priority/enabled, mode dynamic, et AUCUNE charge utile de mécanisme. Trois défauts que ce contrat révèle côté app : 1. isVariableLoad était défini par défaut (« ni relais ni sg-ready »), donc une borne y tombait. L'écran de mécanisme lui proposait une puissance nominale, des paliers et des temporisations — des réglages qui n'existent pas pour elle et dont l'écriture partirait quand même. Pire, le sélecteur offrait de la basculer en routeur de relais : une bascule que basculerMecanisme() sait construire et qu'aucun écran ne sait défaire. Une borne a maintenant sa section, en lecture seule, qui dit pourquoi il n'y a rien à régler. 2. BorneSection existait pour rattraper des bornes qui n'apparaissaient nulle part. Elles apparaissent maintenant dans leur domaine : la section les afficherait DEUX fois, en affirmant qu'elles n'ont « ni rang ni domaine » et qu'elles ne passent pas par SetLoadConfig. Trois affirmations devenues fausses. Retirée ; son contenu de runtime vit désormais dans l'écran de mécanisme, où il a un sens. 3. Le rang par défaut d'une borne est un ARTEFACT, et l'écran le disait comme un réglage. À la création le plugin donne « le plus petit rang existant moins un, borné à 1 » ; le chauffe-eau occupant déjà le rang 1, l'intention « en tête » dégénère en égalité — trois charges à 1 sur le banc. Le tri reste total (l'id départage), donc l'ordre est reproductible, et c'est précisément ce qui le rend crédible : l'installateur lit un classement plausible et n'y touche pas, validant un ordre que personne n'a posé. Une note le nomme, et disparaît dès le premier vrai réglage. Le glissement, lui, n'a demandé aucun cas particulier — c'était tout l'intérêt d'avoir une seule liste. Vérifié par test, y compris l'inversion borne / charge pilotée. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016vrTVifar2GN5rtUh89Wkq
73 lines
4.0 KiB
Markdown
73 lines
4.0 KiB
Markdown
# Prompt agent plugin — 3g-2 : l'arbitre commande seul
|
|
|
|
> À coller tel quel dans l'agent `powersync-plugin`.
|
|
> Contexte : `.75` en `1.15.2+etm22`, seuil de réserve batterie à 0,4.
|
|
|
|
---
|
|
|
|
**3g-2 — l'arbitre commande seul.**
|
|
|
|
Aujourd'hui `adjustEvChargers()` re-décide après le waterfall : l'arbitre refuse, la ligne
|
|
suivante commande 6 A. La transplantation ne commande donc rien, et si la Terra AC n'avait pas
|
|
été hors ligne, l'ordre serait parti sur du matériel réel.
|
|
|
|
**La règle à établir : une charge, un commandeur.** Pour une borne arbitrée par le waterfall,
|
|
`adjustEvChargers()` ne doit plus émettre d'action de surplus. Ce qui lui reste, et qui doit
|
|
être délimité explicitement : les actions **financées au réseau** — marché de gros, échéance de
|
|
départ — puisque l'échéance est restée au proxy par décision assumée. Le champ `funding` que tu
|
|
viens d'ajouter est le discriminant naturel.
|
|
|
|
**Deux pièges à ne pas laisser ouverts.**
|
|
|
|
Le trou de commande : si le waterfall alloue et que le proxy ne commande plus, vérifie que
|
|
**quelqu'un commande**. Le pire résultat serait une borne qui n'obéit à personne — l'arbitre
|
|
croit avoir servi, rien ne se passe, et le budget est perdu comme dans le cas `evFloorW`.
|
|
|
|
La transition : une borne qui charge sous l'ancien régime au moment du déploiement ne doit pas
|
|
rester bloquée dans un état commandé par un chemin qui n'existe plus. Même précaution qu'à la
|
|
suppression du bloc SG-Ready codé en dur — passer par l'état sûr.
|
|
|
|
**Traite `evFloorW()` dans le même lot.** `acquisitionTolerance` est un seuil de déclenchement,
|
|
pas un plancher : 2 070 W publiés là où 4 140 W sont exigés, donc 2 828 W retirés du budget et
|
|
donnés à personne. Un plancher faux est pire qu'un plancher absent — le waterfall croit avoir
|
|
servi. Et le plancher publié doit correspondre au nombre de phases visé, pas au courant du
|
|
moment.
|
|
|
|
**Et le rang d'une borne doit devenir configurable** — `priority = 100` en dur, `std::sort` non
|
|
stable, donc le test d'inversion est impossible tel quel. Sans lui, LM-1204-b reste hors
|
|
d'atteinte même avec deux bornes en ligne.
|
|
|
|
Vérification : `.75` est à `+etm22`, seuil 0,4, la wallbox simulée répond, la Terra AC est hors
|
|
ligne (`192.168.1.132:502`, `ThingErrorTimeout`) — à regarder avant, c'est le seul obstacle
|
|
matériel restant à LM-1204-b.
|
|
|
|
Ton brief est commité en local dans le dépôt app (`e84f59d`) mais non poussé, faute
|
|
d'identifiants HTTPS. L'agent app pousse en SSH ; signale-le-lui plutôt que de le laisser
|
|
dormir.
|
|
|
|
---
|
|
|
|
## Rappels d'état, au cas où la session redémarre à froid
|
|
|
|
| | |
|
|
|---|---|
|
|
| Banc `.75` | `1.15.2+etm22`, seuil réserve batterie **0,4** (délibéré — 0,9 gèle tout à 50 % de SoC) |
|
|
| Plugin SunSpec | `1.15.2+etm11` — la batterie déclare enfin `energystorage`, signe vérifié dans les 3 états |
|
|
| Banc `.131` | six conteneurs sur la même source, `deploy.sh --check-only` sort 0 |
|
|
| Terra AC | **hors ligne**, `192.168.1.132:502`, `ThingErrorTimeout` — seul obstacle matériel à LM-1204-b |
|
|
| Déploiement | **toujours** `etm-powersync-deploy/deploy.sh`, jamais `dpkg -i` |
|
|
| Accès banc | `ssh etm@192.168.1.75` (ni `root` ni `nymea`) · journal `journalctl -u nymead` |
|
|
|
|
**Non franchi :** LM-1204-b — jamais exercé, c'est le critère qui justifie tout le lot.
|
|
|
|
**Pour l'agent app**, en attente dans `docs/BRIEF_depuis_plugin.md` : `SetChargingInfo`
|
|
substitue silencieusement `targetPercentage = 80` à un champ absent · `loads[].funding`
|
|
(surplus/grid) et l'entrée des bornes dans la télémétrie · `kCodesReserveBatterie` vide alors
|
|
que `BATTERY_RESERVE` publie `socPercent`/`reservePercent`/`withheldW` · et la mise en garde :
|
|
pour une borne, `allocatedW` et son motif sont la décision de l'arbitre, **pas** l'état de la
|
|
borne, tant que 3g-2 n'est pas livré.
|
|
|
|
Côté app, `origin` est en HTTPS sans credential helper — d'où des `origin/…` périmés qui font
|
|
croire à des commits manquants. À basculer en SSH :
|
|
`git remote set-url origin gitea-lan:pakutz79/etm-powersync-app.git`
|