docs: §10 déployé sur .75, et le design de la commande perdue
Déploiement vérifié SUR MACHINE et non déduit du script : version relue, nymead actif, arbitre initialisé, et les quatre motifs du §10 présents dans le binaire posé. Piège de vérification noté au passage : authorisedW, perPhaseBound et binding sont des QStringLiteral, donc stockés en UTF-16 et invisibles à `strings` par défaut. Un premier relevé les donnait absents — j'ai failli les rapporter manquants. `strings -el` les trouve. Vérifier une chaîne dans un binaire demande de savoir comment elle y est encodée. Et le design du premier constat de l'app, ouvert plutôt qu'attaqué au code. Trois choses qu'il établit, toutes mesurées : Le titre est trop étroit. « Réappliquer la commande de l'arbitre » ne décrit pas le cas : en mode manuel l'arbitre NE COMMANDE PAS. Ce qui s'est passé est qu'une écriture du proxy a échoué pendant l'indisponibilité, que personne ne l'a rejouée, et que l'organe est resté sur une consigne dont plus aucun commandeur ne se réclame. La pièce qui manque est là où le constat porte : l'EvAdapter ne garde PAS sa dernière consigne, là où les adaptateurs en watts la gardent. Ils en ont besoin pour l'écrêtage de verrou ; la borne était pilotée par le proxy, qui n'a jamais eu à se relire. Le vrai coût n'est pas l'affichage. draw.committedW à 0 pendant que 4,4 kW sont tirés veut dire que le budget de surplus est calculé sans ces watts : le moteur alloue de l'énergie qui n'existe pas. Le délestage, lui, protège — il agit sur la marge MESURÉE, qui les inclut. C'est le budget qui ment. Quatre décisions posées, dont la principale : signaler toujours, réappliquer jamais telle quelle. Rejouer une consigne vieille de plusieurs minutes, c'est décider avec des données mortes — ce que le mode dégradé L2 refuse déjà de faire. Ce qui manque n'est pas le rejeu, c'est que l'écart soit DIT tant qu'il dure, et il dure indéfiniment quand personne ne reprend la main. Ordre de travail : mémoire de la commande, puis écart publié sans décider dessus, puis comptabilité corrigée, et la reprise en main EN DERNIER — c'est la seule étape qui commande du matériel, et on saura alors combien de fois le cas se produit vraiment. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015F7G5VeaPVSMeVNjiGj36p
This commit is contained in:
parent
24d8f55997
commit
4d73ff2482
@ -1,5 +1,12 @@
|
||||
powersync-energy-plugin-nymea (1.15.2+etm43) trixie; urgency=medium
|
||||
|
||||
* DÉPLOYÉ SUR .75 le 2026-09-01, version relue sur la box et `nymead` actif. Les quatre motifs
|
||||
du §10 sont présents dans le binaire posé — vérifié sur machine, pas déduit du script.
|
||||
* Piège de vérification, noté : `authorisedW`, `perPhaseBound` et `binding` sont des
|
||||
QStringLiteral, donc stockés en UTF-16 et INVISIBLES à `strings` par défaut. Un premier
|
||||
relevé les donnait absents. `strings -el` les trouve. Vérifier une chaîne dans un binaire
|
||||
demande de savoir comment elle y est encodée.
|
||||
|
||||
* ECO_FLOOR_MISSED — le motif a désormais son ÉMETTEUR, et c'est pourquoi il est créé
|
||||
maintenant. Ce matin il n'en avait pas : le créer aurait posé un invariant sur un code que
|
||||
rien ne produit, un test toujours vert. La bascule de période (LM-1013-c) l'a fait naître —
|
||||
|
||||
107
docs/DESIGN_COMMANDE_PERDUE.md
Normal file
107
docs/DESIGN_COMMANDE_PERDUE.md
Normal file
@ -0,0 +1,107 @@
|
||||
# DESIGN — la commande perdue, et l'écart que personne ne mesure
|
||||
|
||||
*(Ouvert le 2026-09-01, sur le premier constat de `RELEVE_APP_20260831.md`. Le design avant le
|
||||
code, comme pour le délestage et le §10.)*
|
||||
|
||||
## 1. Le fait, tel qu'il a été mesuré
|
||||
|
||||
Coupure Modbus. La box journalise `Restoring manual values of false 6 A` trois secondes après.
|
||||
La borne, elle, reste à `power: true`, **7 A** — la consigne que l'arbitre lui avait donnée au
|
||||
cycle d'avant. Le lien revient : **rien ne réapplique**. En mode manuel personne ne commande,
|
||||
donc l'écart est **permanent**.
|
||||
|
||||
**4,4 kW réellement tirés, `draw.committedW` à 0, un budget de surplus de 2 349 W qui ignore ces
|
||||
watts.**
|
||||
|
||||
## 2. Ce que le fait dit vraiment — et il est plus large que son titre
|
||||
|
||||
« Réappliquer la commande de l'arbitre » ne décrit pas le cas : **en mode manuel, l'arbitre ne
|
||||
commande pas**. Ce qui s'est passé est autre chose, et c'est pire :
|
||||
|
||||
1. Le proxy amont a voulu restaurer des valeurs manuelles (`false 6 A`) ;
|
||||
2. l'écriture a échoué pendant l'indisponibilité ;
|
||||
3. **personne ne l'a rejouée** ;
|
||||
4. l'organe est resté sur une consigne **dont plus aucun commandeur ne se réclame** — ni
|
||||
l'arbitre, qui ne commande plus, ni le mode manuel, dont la consigne n'a pas atterri.
|
||||
|
||||
> **La troisième forme de la même famille.** Après la télémétrie qui ne distinguait pas une
|
||||
> issue de son contraire (`ECS-111`) et la valeur de retour qui faisait passer un refus pour un
|
||||
> succès (`ECS-415`), voici **l'exécution** : une écriture perdue, un état sain en apparence,
|
||||
> `available` à vrai, et personne pour savoir que la commande n'a jamais atterri.
|
||||
|
||||
## 3. Ce que le moteur a déjà — et ce qui manque
|
||||
|
||||
| Pièce | État |
|
||||
|---|---|
|
||||
| Dernière consigne écrite, charges en watts | **existe** — `m_currentSetpointW`, `m_currentStage` |
|
||||
| Dernière consigne écrite, **bornes VE** | **MANQUE** — `EvAdapter` ne garde que `m_lastActionAt` |
|
||||
| Ce que l'organe FAIT | **existe** — `EvCharger::maxChargingCurrent()`, états du Thing |
|
||||
| Ce que l'organe MESURE, et ce que ça vaut | **existe** — `deviceMeasurement()`, `measurement.source` (`LM-1105`/`LM-1106`) |
|
||||
| Détection de la FIN d'une indisponibilité | **MANQUE** — le seul chemin est `clearFault()`, actionné par l'opérateur |
|
||||
| Comparaison commandé / constaté | **MANQUE** — nulle part |
|
||||
|
||||
**Le constat porte sur les bornes, et c'est précisément là que la mémoire de la commande manque.**
|
||||
Ce n'est pas un hasard : les adaptateurs de charges en watts gardent leur consigne parce qu'ils
|
||||
en ont besoin pour l'écrêtage de verrou ; la borne, elle, était pilotée par le proxy amont, qui
|
||||
n'a jamais eu à se relire.
|
||||
|
||||
## 4. LES DÉCISIONS
|
||||
|
||||
**4.1 — Réappliquer, ou signaler ?**
|
||||
Réappliquer automatiquement une consigne vieille de plusieurs minutes est un geste **dangereux** :
|
||||
le monde a changé pendant l'indisponibilité — le surplus, l'heure, l'échéance. Rejouer une
|
||||
décision périmée, c'est décider avec des données mortes, exactement ce que le mode dégradé L2
|
||||
refuse de faire.
|
||||
|
||||
**Recommandation : SIGNALER toujours, RÉAPPLIQUER jamais telle quelle.** Au retour de
|
||||
disponibilité, le cycle normal reprend la main et décide sur des données fraîches — c'est déjà
|
||||
le bon comportement. Ce qui manque n'est pas le rejeu, c'est que **l'écart soit dit tant qu'il
|
||||
dure**. Et il dure indéfiniment quand personne ne reprend la main, ce qui est le cas du relevé.
|
||||
|
||||
**4.2 — Que publie-t-on, et sous quelle forme ?**
|
||||
Un écart n'a de sens que rapporté à ce qu'on sait de l'organe. Proposition : un objet `command`
|
||||
au niveau de la charge, publié **seulement quand la comparaison est possible** —
|
||||
|
||||
```jsonc
|
||||
"command": { "expectedW": 1380, "observedW": 4400, "divergent": true, "since": "…" }
|
||||
```
|
||||
|
||||
**`measurement.source` conditionne ce que vaut cette comparaison**, et doit donc la gouverner :
|
||||
contre `none`, il n'y a rien à comparer et l'objet est **absent** — pas `divergent: false`, qui
|
||||
affirmerait la concordance qu'on ne peut pas constater. Même règle que partout ailleurs ici.
|
||||
|
||||
**4.3 — Et la COMPTABILITÉ, qui est le vrai coût.**
|
||||
`draw.committedW` à 0 pendant que 4,4 kW sont tirés n'est pas un défaut d'affichage : le budget
|
||||
de surplus est calculé sans ces watts, donc **le moteur alloue de l'énergie qui n'existe pas**.
|
||||
Une charge que l'arbitre ne commande plus mais qui consomme est de la **consommation fixe**, au
|
||||
même titre que la base de la maison — c'est exactement le raisonnement d'`ECS-410` pour une
|
||||
charge gelée, appliqué à une cause nouvelle.
|
||||
|
||||
**Recommandation : la retrancher du budget, sans l'allouer.** Elle n'est pas servie, elle est
|
||||
subie. La compter comme allouée serait prétendre l'avoir décidée.
|
||||
|
||||
> **Sur 18 kVA c'est invisible ; sur 6 kVA c'est le disjoncteur.** Et le délestage ne rattrape
|
||||
> pas ce cas : il agit sur la marge MESURÉE, qui inclut bien ces 4,4 kW — donc il protège. Ce
|
||||
> qui reste faux est le **budget**, qui promet un surplus déjà consommé.
|
||||
|
||||
**4.4 — Faut-il un état « commande en vol perdue » distinct d'un défaut ?**
|
||||
`ECS-410`/`ECS-414` couvrent l'écriture qui échoue trois fois → défaut. Ici l'écriture a échoué
|
||||
**pendant une indisponibilité**, et la charge est ensuite redevenue disponible : le défaut se
|
||||
lève, la divergence reste. À trancher : est-ce un `faultCode` de plus, ou un état orthogonal ?
|
||||
|
||||
## 5. ORDRE DE TRAVAIL — deux étapes à comportement constant d'abord
|
||||
|
||||
**Étape 1 — la MÉMOIRE de la commande, sans rien en faire.** `EvAdapter` retient sa dernière
|
||||
consigne appliquée, comme les autres adaptateurs le font déjà. Publication seule, comportement
|
||||
constant. Sans cette pièce, aucune des suivantes n'est calculable.
|
||||
|
||||
**Étape 2 — l'ÉCART publié, sans décider dessus.** L'objet `command`, gouverné par
|
||||
`measurement.source`. C'est la moitié qui rend le défaut **visible**, et elle ne change aucune
|
||||
décision — même stratégie qu'à l'étape C du §10, où publier le régime a précédé de décider avec.
|
||||
|
||||
**Étape 3 — la COMPTABILITÉ corrigée.** La conso subie sort du budget. C'est ici que le
|
||||
comportement change, et c'est la seule étape qui le fasse.
|
||||
|
||||
**Étape 4 — la reprise en main**, si elle est jugée nécessaire après avoir vu les traces des
|
||||
étapes 2 et 3. **Délibérément en dernier** : c'est la seule qui commande du matériel, et on
|
||||
saura alors combien de fois le cas se produit réellement.
|
||||
Loading…
x
Reference in New Issue
Block a user