Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011uJ47NxgfpGnuuMr3f2n7Z
660 lines
41 KiB
Markdown
660 lines
41 KiB
Markdown
# HANDOFF.md — EVCS / Grid Hysteresis — État au 09/07/2026
|
||
|
||
> ⚠️ Les sessions **§1 à §72** (09/07 → 17/09/2026) sont ARCHIVÉES SANS PERTE
|
||
> dans `HANDOFF_ARCHIVE_2026.md` (fichier NON chargé automatiquement —
|
||
> `grep`/lecture à la demande). Ce fichier ne garde vivantes que les sessions
|
||
> récentes (**§73→**). Split lossless vérifié par md5 le 24/09/2026.
|
||
|
||
## Index des sessions archivées (§1→§72 — détail dans HANDOFF_ARCHIVE_2026.md)
|
||
|
||
- 1. Contexte Projet
|
||
- 2. Architecture Data-Flow
|
||
- 3. Patchs déployés le 09/07/2026 (session opencode)
|
||
- 4. Root Cause de l'incident « EDF ON à 48 % sans charge Jeep » (nuit 08→09/07)
|
||
- 5. Sémantique utile (pour ne pas re-chercher)
|
||
- 6. Méthode de travail validée (à réutiliser)
|
||
- 7. Backlog / Point du 10/07 au réveil
|
||
- 8. Historique des sessions
|
||
- ⚙️ CONFIG LOCALE — Qwen3.6-35B sur DGX Spark (≠ gros modèle cloud)
|
||
- 🧩 SKILLS n8n — validées le 16/07/2026 (Qwen3.6 local, PAS gros modèle)
|
||
- 9. Session du 18/07/2026 (matin)
|
||
- 10. Session du 04/08/2026 (matin) — Fix grid HC 1h30 + libération takeover
|
||
- 11. Session du 07/08/2026 — P7 : Charge HC nuit automatique (VW hybride) + outillage push
|
||
- 12. Session du 07/08/2026 (soir) — R1 : Déduplication du moteur nuit
|
||
- 13. Session du 07/08/2026 (soir) — R3 : Suite de tests golden
|
||
- 14. Session du 07/08/2026 (soir) — P8 : Libération EDF quand le véhicule est plein
|
||
- 15. Session du 07/08/2026 (soir) — R2 : Git = source de vérité du code des nodes
|
||
- 16. Session du 07/08/2026 (nuit) — Agent IA planificateur en MODE OMBRE
|
||
- 17. Session du 08/08/2026 — Incident rebond EDF nuit 07-08/08 : fixes A/B/C/D
|
||
- 18. Session du 09/08/2026 — Incident nuit 08-09/08 : le rebond est revenu par un AUTRE chemin (Fix E)
|
||
- 19. Session du 09/08/2026 (suite) — Fix F : la mémoire "charge terminée" est prioritaire sur les gardes
|
||
- 20. Session du 09/08/2026 — PREMIER CÂBLAGE RÉEL de l'advisor : cible SOC matin
|
||
- 21. Session du 09/08/2026 — P9 : charge réseau avant départ + sélecteur véhicule VW/JEEP
|
||
- 22. Session du 09/08/2026 — P10 : mémoire "véhicule plein" en journée
|
||
- 23. Session du 12/08/2026 — P11 : reset du collant au changement de véhicule
|
||
- 26. Session du 27/08/2026 — L'oscillateur du takeover nuit, et deux acteurs non lus
|
||
- Diagnostic en attente de vérification (Qwen, 22/08)
|
||
- 24. Session du 22/08/2026 — Fix G : coupure EDF quand l'override EVCS disparaît mi-session (hystérésis)
|
||
- 25. Session du 24/08/2026 — Fix G retiré + diagnostic des deux oscillateurs
|
||
- 27. Session du 30/08/2026 — Deux propriétaires GX de la décision réseau, jamais lus
|
||
- 28. Session du 31/08/2026 — La substitution ne se reproduit plus (batterie preneuse). Cas « batterie pleine » encore ouvert
|
||
- 29. Session du 31/08/2026 (suite) — Fenêtre d'établissement du réseau
|
||
- 30. Session du 31/08/2026 (suite) — Séquence d'ouverture du contacteur
|
||
- 31. Session du 01/09/2026 (nuit) — La consigne réseau appartient désormais au contrôleur
|
||
- 32. Session du 01/09/2026 (nuit) — État réel de la résilience, faits vérifiés
|
||
- 33. Session du 01/09/2026 (nuit) — Chien de garde EVCS sur le second Synology
|
||
- 34. Session du 01/09/2026 (nuit) — Sauvegarde Home Assistant : elle n'existait pas, elle existe
|
||
- 35. Session du 01/09/2026 — La table des bandes SOC déclarait un temps que personne ne lisait
|
||
- 36. Session du 03/09/2026 — Un demarrage se decide sur l'excedent, pas sur la production
|
||
- 37. Session du 03/09/2026 (suite) — La provocation solaire demandee aux chargeurs eux-memes
|
||
- 38. Session du 03/09/2026 (suite) — Le plancher du soir cesse d'etre un niveau fixe
|
||
- 39. Session du 03/09/2026 (suite) — La cible du matin devient une energie
|
||
- 40. Session du 03/09/2026 (suite) — Session reseau UNIQUE de la nuit
|
||
- 41. Session du 03/09/2026 (suite) — La conversion energie ↔ SOC devient une courbe mesuree
|
||
- 42. Session du 04/09/2026 — Pourquoi la memoire s'arretait a la semaine
|
||
- 43. Nuit du 03-04/09 — La session unique tenait le contacteur, pas l'energie
|
||
- 44. Mise en service d'InfluxDB (04/09/2026 07:28) — la memoire est complete
|
||
- 45. Session du 04/09/2026 — Grafana : les deux bases se consultent
|
||
- 46. Session du 04/09/2026 — « Le systeme » : replique locale de la vue VRM
|
||
- 47. Session du 04/09/2026 (soir) — Connexion InfluxDB retiree du YAML, et un effet de bord du redemarrage
|
||
- 48. Session du 05/09/2026 — Le bridage de charge est une CELLULE, et il commence a 75 %
|
||
- 49. Session du 05/09/2026 — Le bridage a un coupable nomme : le module d'adresse 3
|
||
- 50. Session du 05/09/2026 (midi) — Lecture en direct de la chaine BMS depuis Linux
|
||
- 51. Session du 05/09/2026 (12h30) — Le parc est sain a cinq modules sur sept, et le hub n'est pas coupable
|
||
- 52. Session du 05/09/2026 (12h45) — BAT3 lue isolee : UNE cellule, et elle est en meilleur etat que deux modules restes en service
|
||
- 53. Session du 05/09/2026 (13h05) — Le declenchement saisi en direct, et l'origine des degats
|
||
- 54. Session du 05/09/2026 (18h30) — Le tampon d'evenements : la cellule 12 est detruite en ce moment, toutes les nuits
|
||
- 55. Session du 05/09/2026 (19h15) — La cellule 15 de BAT3 ne peut plus debiter, meme pleine
|
||
- 56. Session du 05/09/2026 (soir) — Dates d'achat, et ce qu'elles eliminent
|
||
- 57. Session du 06/09/2026 — Le relachement du contacteur se mesurait sur un instant
|
||
- 58. Session du 07/09/2026 — La borne annonce « charge terminee » apres 0,10 kWh
|
||
- 59. Session du 07/09/2026 — Fix H : un statut « charged » doit etre credible
|
||
- 60. Session du 07/09/2026 — Tableau « La journee », et un report de valeur qui fabriquait de l'energie
|
||
- 61. Session du 08/09/2026 — La prevision se juge sur la date qu'elle decrit
|
||
- 62. Session du 11/09/2026 — Le credit solaire sur la consigne reseau, valide en reel
|
||
- 63. Session du 13/09/2026 — Le conseiller ne lisait pas mal : on lui parlait mal
|
||
- 64. Session du 13/09/2026 — Le parc butait sur NOTRE plafond, pas sur le sien
|
||
- 65. Session du 13/09/2026 (soir) — Six sessions sur douze etaient mal etiquetees
|
||
- 66. Session du 13/09/2026 (soir) — Contrat d'etiquetage du concierge, arrete des deux cotes
|
||
- 67. Session du 14/09/2026 — L'auteur des transitions etait lisible depuis le debut
|
||
- 68. Nuit du 14 au 15/09/2026 — P12 : la voiture se charge sur le solaire d'hier
|
||
- 69. Session du 16/09/2026 — Premiere nuit P12, battement de coeur, guichet d'ordres, et la telemetrie BMS qui ment
|
||
- 70. Nuit du 16 au 17/09/2026 — Le chien de garde arretait la charge qu'il devait proteger
|
||
- 71. Session du 17/09/2026 — La prevision entre dans les tableaux Grafana
|
||
- 72. Session du 17/09/2026 (apres-midi) — Le reseau force a une echeance, et la surconsigne n'etait pas le defaut qu'on croyait
|
||
|
||
---
|
||
|
||
## 73. Nuit du 17 au 18/09/2026 — Dissocier la recharge batterie de la fonction EVCS
|
||
|
||
### Ce qui a declenche le chantier, et une correction de sens
|
||
Deux sessions ont passe l'apres-midi a signaler au proprietaire qu'un changement
|
||
de la consigne reseau reduisait la recharge de la batterie sous
|
||
`force_grid_now`. Sa reponse ferme la question : **« force_grid_now pour moi
|
||
c'est pour recharger la voiture, ça me va comme cela »**. Nous raisonnions tous
|
||
les deux comme si cette strategie etait une commande de recharge batterie —
|
||
parce que l'episode du 17/09 en avait eu l'effet. C'etait un effet de bord, pas
|
||
l'intention.
|
||
|
||
⚠️ A retenir : `force_grid_now` = « charge la voiture sur le reseau
|
||
maintenant ». Toute consequence sur la batterie solaire est incidente et ne doit
|
||
pas servir d'argument pour ou contre une evolution de cette strategie.
|
||
|
||
Et c'est lui qui en tire le chantier : **la recharge de la batterie solaire doit
|
||
devenir une fonction propre**, avec son tableau de bord et sa commande — un
|
||
bouton de charge manuelle en heures creuses pour les cas ou le bilan ne
|
||
l'autorise pas alors que la meteo ou la brievete du jour d'hiver la justifient.
|
||
|
||
### FAIT — le detail par cellule pendant la charge (Grafana)
|
||
Le detail cellule par cellule existait deja. Ce qui manquait etait le « pendant
|
||
la charge » : rien ne disait QUAND le module chargeait, et **un ecart entre
|
||
cellules ne veut rien dire hors de son courant** — le 05/09, meme module et meme
|
||
tension de parc, la cellule meneuse etait a 3555 mV sous 50 A et a 3496 mV sous
|
||
30 A.
|
||
|
||
Le releve console porte le courant depuis le 17/09 mais l'ingestion ecrivait
|
||
`null`. Elle lit desormais la colonne `courant_mA`, **reperee par son NOM** : les
|
||
US5000 et les US2000C n'emettent pas les memes colonnes, et une position ferait
|
||
lire la mauvaise grandeur des qu'on deplace le cable d'un pack a l'autre.
|
||
|
||
Deux panneaux : « Sante des modules — tous, d'un coup d'oeil » (le resume qu'on
|
||
lit en premier, la ou les autres panneaux demandent de choisir un module
|
||
d'avance) et « Le module chargeait-il ? ». Releve au deploiement, cinq modules
|
||
vivants, ecarts de **1 a 3 mV** — le parc restant est sain.
|
||
|
||
### CONCEPTION ARRETEE, NON ECRITE — la charge HC manuelle
|
||
Trois pistes, mesurees sur banc golden par la session voisine.
|
||
|
||
**Piste 2 — un chemin separe qui ne toucherait que la consigne et le contacteur :
|
||
MORTE.** Le controleur reecrit la consigne de repos a chaque cycle des que
|
||
`gridSessionActive` est faux : sonde a 5000 W poses de l'exterieur, ramenes a
|
||
700 W en trente secondes. Elle ne se fait pas ecraser par accident, elle
|
||
**s'auto-detruit** : pour qu'elle tienne il faudrait que le controleur la
|
||
connaisse, donc qu'elle ne soit plus separee.
|
||
|
||
**Piste 3 — forcer la cible du bilan : RETENUE, mais l'ENDROIT du forcage decide
|
||
de tout.**
|
||
|
||
| forcage | takeover | consigne | resultat |
|
||
|---|---|---:|---|
|
||
| **en aval** (un bouton ecrit `balance_required_soc`) | engage | **700 W** | batterie a ~100 W |
|
||
| **en amont** (dans `BALANCE.js`) | engage | **2333 W** | le manque reel finance |
|
||
|
||
⚠️ **Le cas en aval est le pire des trois parce qu'il A L'AIR DE MARCHER** :
|
||
contacteur ferme, session engagee, et une consigne qui ne finance rien. C'est le
|
||
defaut du 01/09 et du 04/09 a l'identique, et le seul des trois resultats
|
||
indiagnosticable depuis le tableau de bord. `required_soc` ENGAGE la session,
|
||
`grid_energy_needed_kwh` la FINANCE : les desolidariser donne une session muette.
|
||
|
||
**Point d'insertion, une ligne.** `BALANCE.js`, fonction `coverage()`, ligne 226 :
|
||
|
||
const requiredSocRawPct = socForEnergy(energyToCoverKwh, socFloorPct);
|
||
|
||
`requiredSocPct`, `socMarginPct`, `gridNeeded` et `gridEnergyNeededKwh` en
|
||
derivent tous dans les huit lignes suivantes. Un `Math.max(..., plancherManuel)`
|
||
a cet endroit fait donc bouger la cible ET le manque **ensemble par
|
||
construction** : le couplage implicite qui fait la fragilite de la piste 3
|
||
devient une consequence de la forme du code, et non une discipline a tenir.
|
||
|
||
### Trois effets a connaitre avant d'ecrire
|
||
1. **Les deux profils montent ensemble.** `coverage()` est appelee pour p50 ET
|
||
p80, donc le plancher monte aussi `required_soc_prudent`, qui est le plancher
|
||
de P12. Pendant une charge manuelle, la voiture cesserait donc de descendre
|
||
la batterie. Coherent — on ne remplit pas au reseau pendant que la voiture
|
||
vide — mais **une nuit ou il veut les deux, il n'aura que l'un**. C'est
|
||
structurel, aucune echeance n'y change rien.
|
||
2. ⚠️ **Le bilan ne connait pas les heures creuses.** `grep` sur les douze
|
||
fichiers de `src/energy-balance/` : zero occurrence de `hc_night` /
|
||
`hc_midday`. Sans garde de temps, une cible manuelle a 85 % fuit dans la
|
||
journee et mord sur `BATTERY_CLOUD_LOCKS.js:451`,
|
||
`eveningSocStartFloorPct = max(eveningSocStartMin, balanceRequiredSocPct)` —
|
||
la voiture ne demarrerait plus le soir. Ce n'est pas theorique, c'est une
|
||
ligne qui s'applique tous les soirs.
|
||
**Solution retenue : l'echeance, pas les bornes.** Meme mecanique que
|
||
l'expiration de `force_grid_now` (§72), deja eprouvee en production. Et
|
||
l'argument architectural : le bilan repond a « de combien la batterie a-t-elle
|
||
besoin », pas a « quand est-ce bon marche » ; lui apprendre les fenetres
|
||
tarifaires couplerait deux preoccupations aujourd'hui propres, et ajouterait
|
||
un endroit de plus a penser le jour ou une borne bouge.
|
||
3. **Rien d'autre n'est touche.** Le bloc « prochaine fenetre de deficit »
|
||
n'appelle pas `coverage()` (il utilise `socForEnergy` directement, l.287), et
|
||
un plancher a 85 reste loin sous l'ecretage a 100, donc aucune interaction
|
||
avec le signal de sous-dimensionnement de §26.
|
||
|
||
### La decision qui reste au proprietaire
|
||
Contraindre le bilan (piste 3) ou l'ignorer (piste 1, un `sourceMode` de plus
|
||
dans le controleur). **Ce n'est pas un choix de technique mais de sens** :
|
||
contraindre garde un seul arbitre, ignorer en cree un second — et ce projet a
|
||
deja paye cher les automates concurrents (charges programmees de l'ESS §26,
|
||
consigne a 4200 W §27, plancher SOC de l'ESS §27).
|
||
|
||
Reste aussi a construire, apres sa reconfiguration du LVHUB : le resume de
|
||
l'etat des cellules cote Home Assistant, et le bouton lui-meme.
|
||
|
||
---
|
||
*Document mis a jour le : 18/09/2026 (~03:15) — releve par cellule avec le courant, conception de la charge HC manuelle arretee et non ecrite*
|
||
|
||
## 74. Session du 20/09/2026 — Nuit LVHUB, correctifs swap rapide, et re-mesure du parc assaini
|
||
|
||
### La nuit LVHUB (18-19/09) : le detail batterie est mort depuis le 15/09, pas a cause des packs
|
||
Detail complet dans `docs/PROTOCOLE_LVHUB_CERBO.md`. En resume : le proprietaire
|
||
a voulu passer le pack US2000C en maitre a la place du pack US5000. **Six
|
||
leviers essayes, aucun ne ramene les trames etendues** du Cerbo (nombre de
|
||
modules, capacite, tensions de cellule, firmware) : rescan, redemarrage Cerbo,
|
||
MAJ firmware Cerbo, inversion du maitre, reset hub, sequence complete rejouee.
|
||
Les trames de BASE passent (SOC, limites 250/250 A, alarmes → le BMS protege) ;
|
||
seules les ETENDUES sont `null`, et ce **depuis le redemarrage HA du 15/09
|
||
05:09** (§69), donc AVANT toute manip de packs. Cause = la couche logicielle
|
||
Venus `can-bus-bms v0.71`, pas le materiel ni l'ordre des packs. **Ne plus
|
||
toucher au materiel batterie pour ce symptome — demontre inutile.** A instruire
|
||
a froid : firmware du LV-Hub, ou effet de la MAJ Venus, sur doc constructeur.
|
||
Config a garder : US5000 maitre → cable bleu → hub → Cerbo, cable gris entre
|
||
packs (seule combinaison qui donne les 3 bips). Le chainage inter-groupes ne
|
||
marche que dans le sens US5000-tete.
|
||
|
||
### Incident du swap rapide (19/09) et les correctifs — P11-bis, bouton reset, alerte
|
||
VW debranchee ~14:50, JEEP branchee, mais le swap n'a dure que **14 s** → la
|
||
borne a GELE son etat (charging_time reste a 1h25, jamais reinitialise). P11
|
||
(base uniquement sur charging_time ≤ 90s) restait aveugle → le collant
|
||
"vehicule plein" de la VW a bloque la JEEP, qui n'a pas charge de l'apres-midi.
|
||
Un debranchement FRANC de 30s a tout debloque.
|
||
|
||
Correctifs deployes (golden 113 → 116) :
|
||
- **P11-bis** : `sessionFresh` gagne un SECOND signal, l'age du dernier
|
||
(re)branchement (`as_timestamp` du last_changed de vehicle_connected),
|
||
independant du charging_time de la borne. Le swap de 14s avait bien fait
|
||
bouger ce last_changed. Meme fenetre 90s. Gabarit + INPUT_PARSE
|
||
(`evcsVehicleConnectedAgeSec`) + WINDOWS.
|
||
- **Bouton reset borne** (`input_boolean.evcs_reset_borne`, carte EVCS Master) :
|
||
echappatoire manuelle, force une session fraiche un cycle, momentane (le
|
||
controleur le rebascule off).
|
||
- **Detection anomalie "branchee mais ne charge pas"** (historiseur) : helper
|
||
`input_text.evcs_alerte_charge` (SPARK/OpenClaw envoie le WhatsApp), toggle
|
||
maitre `input_boolean.evcs_alerte_charge_enabled` (OFF, opt-in, seuils
|
||
500W/10min A CALIBRER). Critere robuste par la censure sans injection.
|
||
- Cote OpenClaw (SPARK) : le concierge ecrit desormais AUSSI le selecteur
|
||
`input_select.victron_evcs_vehicle` sur confirmation WhatsApp (plus besoin de
|
||
le regler a la main), + message spontane utilisable (une reponse VW/JEEP sans
|
||
question posee est appliquee) + menage gateway (la saturation qui avalait les
|
||
messages).
|
||
|
||
### ⚠️ RE-MESURE DE LA COURBE BATTERIE SUR LE PARC ASSAINI (le point majeur)
|
||
Le parc compte maintenant **13 equivalents US2000 sains** : 4 US5000 (pack 1,
|
||
neufs 03/2026) + 5 US2000C (pack 2, dont l'ancien module sain `…0323`). Les
|
||
modules abimes (cellules 12 et 15 mortes) sont sortis. Cellules du pack 2
|
||
mesurees a **3-6 mV d'ecart** (contre 168 mV sur l'ancien parc), SOH 99.
|
||
|
||
`node tools/mesure-courbe-batterie.mjs 8` sur ce parc donne une courbe
|
||
**PLATE a 0,30 kWh/point de 25 a 97 %, PLUS DE GENOU**. Le genou a 33 % (§41)
|
||
etait la signature de la cellule 12 morte : il a disparu avec elle. La reserve
|
||
utile a quasiment **double : 12,4 → ~23 kWh** (100 → 22 %).
|
||
|
||
Recalage deploye (rec 1) :
|
||
- `src/energy-balance/BALANCE.js` : `kneePct` 33 → 0, pentes 0,169/0,097 →
|
||
**0,1615 plat** (× echelleParc 13/7 = 0,30 au parc actuel).
|
||
- `src/nodes/INPUT_PARSE.js` : `batteryUsableCapacityKwh` 2,414 → **2,308
|
||
kWh/module** (0,30/13 × 100).
|
||
- helper `evcs_balance_usable_capacity_kwh` 15 → 23 (inerte mais coherent).
|
||
- Tests bilan 50/50 (10 attendus re-figes, verifies a la main), golden 116/116,
|
||
golden-acm 20/20. Mutation deux sens sur la courbe.
|
||
|
||
⚠️ **La courbe est un RESULTAT DE MESURE, a remesurer apres toute evolution du
|
||
parc.** Les constantes 0,1615 et 2,308 valent pour 13 modules ; le scaling
|
||
`modules/7` (helper `evcs_balance_modules_en_service` = 13) adapte au nombre.
|
||
|
||
### Rec 2 : top-off ACM 52,4 → 52,8 V
|
||
Le 52,4 V avait ete pose le 06/09 pour menager la cellule 12 faible du pack
|
||
ancien. Ce pack est sorti ; on releve le top-off pour atteindre une charge plus
|
||
pleine et **recalibrer la jauge SOC Pylontech** (qui derive tant qu'on n'atteint
|
||
jamais 100 %). 52,8 V = 3,52 V/cellule, sous les 53,2 V autorises par le BMS, et
|
||
la cellule haute du pack 2 est a 3356 mV. patch rejouable
|
||
`tools/patch-20260920-topoff-52v8.mjs`.
|
||
|
||
### ⚠️ ANGLE MORT A LEVER : cellules du pack 1 (US5000) hors surveillance
|
||
Le releve serie continu est sur le pack 2 (US2000C) ; les trames etendues du
|
||
Cerbo sont mortes (voir ci-dessus). Les cellules du **pack 1 (US5000) ne sont
|
||
donc PAS surveillees en continu**. Lues saines le 19/09 (`pwr` : Vlow 3330 /
|
||
Vhigh 3331, ~1-2 mV), et les US5000 sont neufs. Le proprietaire a commande un
|
||
**2e cable console** pour surveiller les deux packs. La re-mesure de courbe et
|
||
la capacite, elles, couvrent BIEN le parc entier (agregat SOC/puissance du
|
||
Cerbo). Seule la sante CELLULE du pack 1 manque — d'ou la prudence sur le
|
||
top-off, applique sur autorisation explicite du proprietaire.
|
||
|
||
### Production vs consommation (7 jours, 13-19/09)
|
||
Maison a ~40 kWh/jour, conso qui DEPASSE souvent la production (15/09 : 29 vs
|
||
39 ; 17/09 : 27 vs 42). Deja tendu en septembre ; l'hiver sera nettement
|
||
deficitaire. (PV mesuree = censuree sans injection, ressource reelle plus haute
|
||
les jours ou la batterie s'est remplie tot.)
|
||
|
||
---
|
||
*Document mis a jour le : 20/09/2026 — nuit LVHUB (trames etendues mortes cote Venus), P11-bis + bouton reset + alerte, courbe batterie remesuree (plate 0,30, ~23 kWh utiles), top-off 52,8 V*
|
||
|
||
## 75. Session du 24/09/2026 — Le releve des cellules migre du portable vers le Synology .17
|
||
|
||
### Le declencheur
|
||
Le releve serie des cellules Pylontech tournait sur le PC PORTABLE (boucle
|
||
`deploy/releve-cellules/lancer.sh`, @reboot crontab). Il est mort le **20/09 a
|
||
17:29** : le portable a redemarre a 18:13, son garde anti-doublon a vu un
|
||
`pgrep` transitoire et a refuse de relancer -> **4 jours de trou** dans la table
|
||
`cellule`, Grafana « No data » (§74 finissait juste avant ce constat). Le
|
||
portable n'a pas vocation a rester allume ; le proprietaire a propose d'utiliser
|
||
le **.17** (ARCHIVE3, DS920+), toujours allume, avec le cable FTDI sur un port
|
||
USB du NAS.
|
||
|
||
### Ce qui a rendu la migration possible (verifie, pas suppose)
|
||
- DSM embarque les pilotes `usbserial.ko` + `ftdi_sio.ko` (presents dans
|
||
`/lib/modules/`), simplement pas charges d'office. **Verrou decisif leve.**
|
||
- Le .17 monte deja le depot en NFS : `10.10.10.22:/volume2/projects` ->
|
||
`/volume1/homes/TMZF5455/projects`. Le conteneur ecrit donc les CSV dans le
|
||
meme `docs/mesures/batteries/` que lit le service d'historisation du **.22**.
|
||
**Un seul maillon bouge : le lecteur serie.** Toute la chaine aval est
|
||
inchangee.
|
||
- ⚠️ Le montage NFS est **`noexec`** : node LIT le .mjs (OK), mais un script ne
|
||
peut pas etre EXECUTE directement depuis ce montage.
|
||
|
||
### Ce qui a ete construit (`deploy/releve-cellules/`)
|
||
- **`compose.yaml`** : conteneur `node:20-bookworm-slim`, `restart:
|
||
unless-stopped`, device `/dev/ttyUSB0` mappe, depot monte en `/depot`. Tourne
|
||
en **`user: 1026:100`** (PAS root : le NFS peut ecraser root via root_squash ;
|
||
le dossier CSV est g+w pour `users`). TMZF5455 est dans le groupe `docker` ->
|
||
compose sans sudo. Remplace la boucle `lancer.sh`.
|
||
- **`charger-pilotes.sh`** : charge les modules (verifie via `lsmod`, ne fait PAS
|
||
confiance au code retour de `modprobe`) et `chmod 666 /dev/ttyUSB0` (le
|
||
conteneur n'est pas root). A lancer au boot en **root**.
|
||
- **`README.md`** : deploiement, bascule depuis le portable, verification.
|
||
|
||
### Garde anti-blocage ajoute a `pylontech-console.mjs` (--suivi)
|
||
Cause racine de la panne du 20/09 identifiee : **`lireJusqua` resout au timeout
|
||
au lieu de rejeter**, donc un port fige renvoie du vide en boucle sans jamais
|
||
crasher — `restart: unless-stopped` ne l'aurait pas rattrape. Un controle du
|
||
`mtime` du CSV force `process.exit(1)` apres 3x le pas sans ecriture, pour que
|
||
le superviseur (conteneur ou lancer.sh) rouvre le port. Protege les deux hotes.
|
||
|
||
### L'EPREUVE DU FEU : reboot + saut majeur DSM 7.3.2 -> 7.4.1 le meme coup
|
||
Le proprietaire a tout tente d'un coup. **Le premier boot a echoue**, revelant
|
||
deux pieges que l'update majeur cree — desormais corriges et **documentes dans
|
||
le README** :
|
||
|
||
1. **`noexec`** : la tache DSM appelait le CHEMIN NU du script -> « Permission
|
||
denied ». Corrige : commande **`sh <chemin>`** (lit au lieu d'executer).
|
||
2. **L'update majeur EFFACE le sudo passwordless** : DSM 7.4.1 a supprime le
|
||
NOPASSWD de TMZF5455, donc l'auto-elevation `sudo -n` du script est morte.
|
||
Parade durable : la **tache de boot tourne en root** (aucun sudo requis). Un
|
||
update majeur peut aussi DESACTIVER les taches declenchees — a reverifier.
|
||
|
||
Autres faits etablis : le noyau est **inchange** (4.4.302+ en 7.4.1, donc pas de
|
||
souci de vermagic) ; les `.ko` existent toujours ; le cable FTDI est bien
|
||
enumere (`0403:6001 FT232R USB UART`). `insmod` en root fonctionne sans erreur.
|
||
|
||
### Preuve du dernier maillon (reboot propre, ZERO intervention)
|
||
Second reboot, sans rien charger a la main :
|
||
```
|
||
uptime 14 min · /dev/ttyUSB0 cree a 14:14:11 en crw-rw-rw- (666)
|
||
conteneur Up · base .22 ingere les 5 modules (dernier point 14:24)
|
||
```
|
||
Le **666** est la preuve decisive : seul `charger-pilotes.sh` fait ce chmod, et
|
||
il n'a pas ete lance a la main -> la tache de boot (root, `sh`) s'est executee
|
||
seule. Chaine complete automatique validee.
|
||
|
||
### Config finale de la tache DSM (a ne pas casser)
|
||
Planificateur de taches DSM, tache declenchee **« Au demarrage »**,
|
||
**utilisateur = root**, commande :
|
||
```
|
||
sh /volume1/homes/TMZF5455/projects/EVCS/EVCS/deploy/releve-cellules/charger-pilotes.sh
|
||
```
|
||
Le `@reboot lancer.sh` du portable est **retire** de son crontab (remplace par
|
||
une note) : ne jamais le reactiver, il ferait un second lecteur sur la meme
|
||
chaine (relevés faux, silencieux).
|
||
|
||
### Limite inchangee
|
||
Le cable est sur le **pack 2** (5x US2000C) ; le **pack 1** (US5000) reste hors
|
||
surveillance cellule jusqu'au 2e cable en commande. La courbe de capacite et le
|
||
SOC couvrent tout le parc (agregat Cerbo).
|
||
|
||
---
|
||
*Document mis a jour le : 24/09/2026 — releve migre sur le Synology .17 (conteneur + tache boot root/sh), survie prouvee sur reboot + update DSM 7.4.1*
|
||
|
||
## 76. Session du 24/09/2026 — Le rapport de nuit extrapolait l'import sur les heures futures
|
||
|
||
### Le bug (signale par la session SPARK via les compteurs d'energie)
|
||
Rapport du 24/09 : « Au total 4,2 kilowattheures importes » pour la nuit, contre
|
||
**~1,6 kWh** vus par deux compteurs d'ENERGIE independants (le compteur EDF de
|
||
facturation `edf_general_ok_energie_totale` : 1,53 ; les compteurs AC-in Victron
|
||
`airtria_mpii_v1_energy_from_ac_in_1_to_*` : 1,60). Deux compteurs concordent :
|
||
c'est le 4,2 qui est faux.
|
||
|
||
### La cause — et ce n'etait PAS celle proposee d'abord
|
||
SPARK diagnostiquait une surestimation par la cadence d'echantillonnage
|
||
(`sum/60000` supposant 1 point/min alors qu'il y en aurait 2,7). **Faux, et
|
||
verifie en base** : le SQL ne sommait pas les points bruts, il construisait une
|
||
grille `generate_series` a la minute + derniere valeur connue, donc 1 point/min
|
||
par construction. Donnees d'ailleurs eparses : **130 points sur 961 minutes**.
|
||
Le 2,7 (= 4,2/1,53) etait une coincidence numerique, pas un mecanisme.
|
||
|
||
La vraie cause : **le rapport tourne a 06:47 mais sa fenetre va jusqu'a 10:00**.
|
||
Le `generate_series` remplit les ~3 h futures, et la derniere puissance connue
|
||
(le reseau qui importait encore a 06:47) est reportee sur 193 minutes fantomes.
|
||
Preuve : rejeu de l'ancienne methode tronquee a 06:47 -> **3,79 kWh**, cohcerent
|
||
avec le 4,2 ; la meme methode sur la fenetre COMPLETE (donnees presentes cet
|
||
apres-midi) redonne **1,60**. Elle n'etait donc fausse QUE parce qu'elle tournait
|
||
avant la cloture de sa propre fenetre.
|
||
|
||
⚠️ Lecon de methode : cette cause ne se trouve qu'en REJOUANT la requete sur les
|
||
donnees, pas en raisonnant sur un ratio. J'ai rejoue plutot que de croire le
|
||
diagnostic du ratio sur parole — c'est ce qui a evite de « corriger » la mauvaise
|
||
chose.
|
||
|
||
### Le correctif (deploye 24/09, `ec5f43e`)
|
||
`tools/rapport-nuit.mjs` : integration **ponderee par l'intervalle reel** entre
|
||
points (`lead(ts)`, cap 300 s pour qu'un trou n'extrapole rien ; aucun point
|
||
apres le dernier echantillon donc aucune extrapolation) **et fenetre plafonnee a
|
||
`now()`**. Applique aux QUATRE grandeurs integrees (importe, injecte, voiture,
|
||
batterie_chargee) qui partageaient la formule. Verifie : **1,60 kWh** sur fenetre
|
||
complete (= les compteurs), **1,19** en simulation 06:47 (import reel jusque-la).
|
||
|
||
⚠️ **Option ecartee** : lire le delta d'un compteur d'ENERGIE cumule (le plus
|
||
robuste en principe) est **inapplicable ici** — ces compteurs
|
||
(`edf_general_ok_energie_totale`, AC-in Victron) ne sont PAS dans la table
|
||
PostgreSQL `mesure` (seul `sensor.victron_grid_power_l1` y est) ; SPARK les lisait
|
||
direct sur HA (recorder SQLite). Si un jour on veut la methode compteur, il faut
|
||
d'abord ajouter ces entites a l'historisation.
|
||
|
||
⚠️ **Portee** : tous les rapports depuis le 08/09 surestimaient ces kWh (ils
|
||
tournent toujours avant 10 h). Le RESTE du rapport (SOC, heures de fermeture,
|
||
vehicule, injection) etait juste — ces faits ne sont pas integres.
|
||
|
||
### Decalage de l'heure d'envoi 06:47 -> 07:30 (proposition du proprietaire)
|
||
Le fix stoppe la SURestimation, mais a 06:47 le rapport reste INCOMPLET : il rate
|
||
l'import 06:47->07:24. Raisonnement du proprietaire : la fenetre HC ferme a 07:24,
|
||
et si l'ajustement de la cible du matin fait son travail il n'y a **pas** d'autre
|
||
fermeture EDF ensuite — donc un rapport apres 07:24 capture l'import COMPLET de la
|
||
nuit. `RAPPORT_HEURE/MINUTE` passe a **07:30** (`historise-evcs.mjs`).
|
||
|
||
Reserve consignee : les jours ou la cible du matin est trop basse, l'hysteresis
|
||
peut refermer EDF apres 07:24 (cas plein tarif §39) et un rapport a 07:30 le
|
||
raterait. C'est l'exception ; 07:30 est strictement meilleur que 06:47 (toujours
|
||
incomplet). La fenetre de calcul restant plafonnee a `now()`, l'heure d'envoi peut
|
||
etre avancee/reculee sans risque de fantome.
|
||
|
||
---
|
||
*Document mis a jour le : 24/09/2026 — rapport de nuit : integration ponderee + fenetre plafonnee (fin de l'extrapolation), envoi decale a 07:30 pour un total complet*
|
||
|
||
## 77. Session du 24/09/2026 — Banc de test PV pour l'agent vocal OpenClaw
|
||
|
||
### Contexte
|
||
Le proprietaire pilote OpenClaw en vocal depuis son iPhone et veut le faire
|
||
travailler la gestion PV. Coordination avec la session SPARK (qui tient
|
||
OpenClaw) : moi la source de verite et les attendus (j'ai PostgreSQL/InfluxDB et
|
||
l'historique HA), SPARK le harnais et la fiche de l'agent. Deux etages, comme
|
||
pour le concierge (§65/§66) : je ne touche pas a OpenClaw, SPARK ne fabrique pas
|
||
d'attendu.
|
||
|
||
### La source de verite d'abord (consignee MANUEL §0)
|
||
Production PV reelle du jour = SOMME des trois `*_yield_today` par chargeur
|
||
(airtria_mppt1 + mppt_450_200_hq2449yr9pt + v1), remis a zero chaque nuit. Verifie
|
||
le 24/09 (45,1 kWh) et recoupe par l'integrale de `victron_pv_power_system`
|
||
(44,0). Trois pieges ecartes : `energy_production_today` = PREVISION (Forecast.
|
||
Solar), `gx_device_pv_energy` = compteur PARTIEL et gelable, `*_d_hier` = la
|
||
veille.
|
||
|
||
### Le banc — 9 gammes, snapshots reels figes + attendus
|
||
Modele : `campagne-conseiller.mjs` (§63). Chaque gamme = fiche de l'agent +
|
||
snapshot capteurs fige + question, note sur >=3 passages. Snapshots batis sur
|
||
mes chiffres reels (jamais inventes), tires de la table `mesure` (puissances,
|
||
SOC, courant, import) et de l'historique HA (`yield_today`, modes MPPT,
|
||
prevision). Les 4 competences :
|
||
- **Lire la bonne source** : G1 production du jour (45,1 = somme yields, pas la
|
||
prevision) · G2 reste a produire (26,8 = `energy_production_today_remaining`,
|
||
le SEUL cas ou la prevision est juste).
|
||
- **Discriminer** : G3 bridage batterie pleine (SOC 97, +1 A, 7 MPPT
|
||
`voltage_current_limited`, import nul -> ecretage normal) · G4 vraie baisse
|
||
(PV quasi identique a G3 mais SOC 69, +25 A, 7 MPPT `mppt_active` -> ressource
|
||
limitee, rien de gache) · G5 substitution anormale (MPPT bridés MAIS import ~
|
||
conso -> le reseau remplace le solaire, SIGNALER).
|
||
- **Decider** : G6 charge voiture refusee sur excedent negatif (-1854 W,
|
||
batterie en decharge) · G7 reste-t-il du solaire a capter (un MPPT limited ->
|
||
oui, ressource refusee dispo).
|
||
- **Hygiene donnees** : G8 compteur GX gele (last_changed vieux -> ne pas citer)
|
||
· G9 `yield_today` unavailable (production partielle, ne pas sommer un trou).
|
||
|
||
### Ce que le banc a TROUVE (sa raison d'etre)
|
||
**G5 a echoue 0/3 au premier tour.** La regle de substitution etait pourtant
|
||
dans la fiche, mais l'agent concluait « bridage normal » sur batterie pleine +
|
||
MPPT bridés SANS verifier l'import reseau. SPARK a reordonne la fiche pour forcer
|
||
l'import en controle nº1 (« jamais conclure bridage sans avoir verifie que
|
||
l'import ~ 0 ») -> G5 = 3/3, G3/G4 sans regression. C'est le cas qui verrouille
|
||
la distinction bridage/substitution — celle qui a coute des mois d'observation
|
||
au proprietaire (§26-§31). Banc complet : **9/9 sur 3 passages**.
|
||
|
||
### Statut des snapshots (pour un futur re-figeage)
|
||
Reels a figer : G1, G2, G3, G4, G6, G7 (dates/valeurs dans les messages a SPARK
|
||
du 24/09). G5 = valeurs reelles du 27/08 (hors table `mesure`, anterieures au
|
||
04/09) mais comportement CORRIGE depuis le 31/08 -> cas d'apprentissage, ne se
|
||
reproduit plus. G8/G9 = synthetiques d'hygiene. Le banc extrait la fiche live
|
||
d'AGENTS.md d'OpenClaw a chaque run : toute evolution de la fiche est re-testee.
|
||
|
||
### Capteurs de discrimination (rappel, tous lus par l'agent)
|
||
Les 7 `*_operation_mode` (v1, airtria_mppt1, mppt_450_200 device + 4 trackers),
|
||
`victron_battery_soc`, `victron_battery_current` (signe = sens),
|
||
`victron_consumption_power_l1`, `victron_grid_power_l1`, `victron_pv_power_system`.
|
||
Regle-cle : bridage NORMAL ⇒ import nul ; substitution ANORMALE ⇒ import ~ conso.
|
||
|
||
---
|
||
*Document mis a jour le : 24/09/2026 — banc PV 9/9 pour OpenClaw (source de verite + discrimination bridage/vraie baisse/substitution), la source vit dans MANUEL §0*
|
||
|
||
## 78. Session du 24-25/09/2026 — Détail cellule exposé en helpers HA pour l'agent vocal
|
||
|
||
Les trames BMS cellule de HA sont mortes depuis le 15/09 (§69) ; le relevé série
|
||
(table `cellule`, sur le NAS depuis §75) est la seule source vivante. Pour que
|
||
l'agent vocal OpenClaw lise le détail cellule en direct sans taper PostgreSQL, le
|
||
service d'historisation publie désormais trois helpers HA à chaque cycle, depuis
|
||
le dernier relevé série :
|
||
- `input_number.evcs_cell_spread_max_mv` — écart max du pack (mV)
|
||
- `input_text.evcs_cell_weakest_module` — code-barres du module le plus sensible
|
||
- `input_number.evcs_cell_releve_age_min` — âge du dernier relevé (min)
|
||
|
||
L'âge permet à l'agent la même discipline que pour le gel GX : frais → il donne
|
||
la valeur, vieux → il dit « muet ». `publierCellulesHelpers()` dans
|
||
`tools/historise-evcs.mjs` (SQL sur les modules du dernier lot, à ±5 min du
|
||
max(ts)), appelée après l'ingestion. Package `evcs_cellules.yaml` (sans
|
||
`initial:` — réécrits chaque cycle), rechargé sans redémarrage. Vérifié en réel
|
||
le 25/09 : écart 21 mV, âge 1 min, module K220803C30160323 (le plus ancien du
|
||
pack 2). SPARK bascule l'agent dessus (fiche + gamme G13 live).
|
||
|
||
---
|
||
*Document mis a jour le : 25/09/2026 — détail cellule publié en helpers HA (source série vivante), agent vocal câblé*
|
||
|
||
## 79. Session du 25/09/2026 — Les jugements sortent de la fiche de l'agent vocal
|
||
|
||
SPARK a restructure l'AGENTS.md d'OpenClaw (28 247 / 30 000 car, plafond par
|
||
fichier du gateway) : permutation pure des sections, l'energie en tete (dans les
|
||
45 % gardes mot pour mot si le fichier tronque), md5 des 10 sections identiques.
|
||
Le code du gateway ne charge que AGENTS.md et USER.md : pas de split possible.
|
||
|
||
⚠️ Decouverte : la fiche est sur le fil du rasoir. 96 car ajoutes dans le bloc
|
||
CELLULE (pour G13b) ont fait tomber G5 (substitution) de 7/7 a 1/7, sans lien
|
||
semantique. Plutot que de rediger mieux, les deux jugements sont sortis du
|
||
modele et calcules par le service d'historisation (`tools/diagnostics-agent.mjs`,
|
||
fonctions pures, `node tests/diagnostics-agent/run.mjs` 15/15, deux mutations
|
||
qui mordent) :
|
||
- `sensor.evcs_pv_diagnostic` : `bridage_normal` / `substitution_edf` /
|
||
`ressource_limitee` / `reseau_en_appoint` / `pas_de_production` /
|
||
`indetermine`, avec explication et grandeurs en attributs. L'import est teste
|
||
AVANT de conclure au bridage, par l'ordre du code (regle du 31/08). Bruit
|
||
compteur 100 W.
|
||
- `sensor.evcs_cellules` : ecart max (mV) si releve frais ; `perime` au-dela de
|
||
30 min (3 pas de 10 min, comme la garde anti-blocage §75) SANS ecart ni module
|
||
en attribut ; `muet` si base injoignable ou cycle en echec. L'agent ne peut
|
||
plus citer une valeur perimee : il ne la voit pas.
|
||
Les deux sont republies meme quand le cycle echoue. Les anciens helpers
|
||
`evcs_cell_*` (§78) sont RETIRES le 25/09 apres bascule de la fiche par SPARK
|
||
(package `evcs_cellules.yaml` supprime, sauvegarde `.bak-20260925` a cote).
|
||
Banc SPARK apres migration : 13/13, G5 7/7, G13b 7/7 ; fiche 28 247 -> 27 129 car.
|
||
|
||
Suite du meme jour, deux capteurs de plus (tests 26/26, mutations qui mordent) :
|
||
- `sensor.evcs_production_jour_kwh` (G1/G9) : somme des trois `yield_today`
|
||
device, statut complet/partiel/indisponible, chargeurs muets nommes. ⚠️ Les
|
||
trois chargeurs se remettent a zero a des heures DIFFERENTES (00:37, 00:41,
|
||
00:45 le 25/09) : un rendement non nul modifie avant minuit compte pour 0.
|
||
- `sensor.evcs_charge_solaire` (G6/G7) : RELAIS de la decision du controleur
|
||
(`non_branchee` / `en_attente` / `en_charge_solaire` / `en_charge_reseau` /
|
||
`indetermine`), raison du controleur et excedent en attributs. Delibrement PAS
|
||
un second arbitre : l'agent explique, il ne decide pas.
|
||
Defaut corrige dans la fiche par SPARK : « off » ne prouve pas une ressource
|
||
refusee (la nuit les 7 sont off) — seul `limited` compte.
|
||
Multi-agents (code du gateway lu par SPARK) : possible, routage par point
|
||
d'entree (binding canal/compte/fil), outils et memoire isoles par agent ; UN seul
|
||
point d'entree vocal => le vocal reste a l'agent par defaut (maison). Serveur
|
||
Spark `max-batch-size 1` : requetes serialisees, aucun gain de debit. Retenu :
|
||
pas d'agent d'accueil (double la latence, aiguillage faillible), un fil par agent.
|
||
|
||
### Bilan final de la migration (25/09, ~02:00)
|
||
La partie energie de la fiche OpenClaw ne CALCULE plus rien : elle relaie des
|
||
etats et des explications. Fiche 28 247 -> **27 006 car** (marge ~3 000 sous le
|
||
plafond de 30 000), backup conserve cote SPARK. **Banc complet 15/15**, et
|
||
7 passages sur chaque cas migre : G5, G6, G7, G7b, G7c, G9, G13b = 7/7.
|
||
|
||
| question de l'agent | il lit | avant |
|
||
|---|---|---|
|
||
| bridage ou substitution ? (G3-G5) | `sensor.evcs_pv_diagnostic` (etat) | jugeait l'import et les modes |
|
||
| reste-t-il du solaire a capter ? (G7) | `sensor.evcs_pv_diagnostic` (etat) | comptait limited/off (faux la nuit) |
|
||
| production du jour (G1/G9) | `sensor.evcs_production_jour_kwh` | sommait trois capteurs |
|
||
| la voiture peut-elle charger ? (G6) | `sensor.evcs_charge_solaire` | calculait PV − conso |
|
||
| reste a produire (G2) | `sensor.energy_production_today_remaining` | soustrayait prevision − realise |
|
||
| detail cellule (G13) | `sensor.evcs_cellules` | lisait des helpers qui gardaient la valeur perimee |
|
||
|
||
Correspondance « reste a capter », a ne pas remplacer par l'attribut brut
|
||
`mppt_bridés` (qui vaut 0 quand les modes sont illisibles et ferait dire « non »
|
||
avec assurance) : `bridage_normal` -> oui · `substitution_edf` -> oui + anomalie
|
||
a signaler · `ressource_limitee` / `reseau_en_appoint` / `pas_de_production` ->
|
||
non · `indetermine` -> « je ne peux pas le dire ». Verrouille par G7c.
|
||
|
||
Reste dans la fiche, volontairement : G8 (ne jamais lire un compteur GX comme un
|
||
delta) — une interdiction, pas un jugement ; P1 et P3 retirent a l'agent toute
|
||
raison de lire ces compteurs.
|
||
|
||
⚠️ **Doctrine a garder pour toute evolution de l'agent** : quand une reponse
|
||
depend d'un raisonnement sur des mesures, le calcul va dans
|
||
`tools/diagnostics-agent.mjs` (fonction pure + test + mutation) et l'agent
|
||
relaie l'etat. Une regle en prose est fragile : un ajout sans rapport ailleurs
|
||
dans la fiche l'a fait basculer (G5, 7/7 -> 1/7). Et quand une decision existe
|
||
deja ailleurs (controleur EVCS), l'agent la RELAIE, il ne la recalcule jamais.
|
||
Limite connue : si le service d'historisation meurt, les quatre capteurs se
|
||
figent ; l'agent verifie `sensor.evcs_historisation_heartbeat`.
|
||
|
||
### Incident du matin 25/09 — le capteur de charge disait « solaire » la nuit
|
||
Le proprio : « l'agent a delire ce matin sur la charge voiture ». Cause = MON
|
||
capteur, pas l'agent. `chargeSolaire` classait toute source qui ne commence pas
|
||
par « Reseau » comme solaire : de **01:25 a 06:00**, `sensor.evcs_charge_solaire`
|
||
a publie `en_charge_solaire` alors que la JEEP chargeait sur la BATTERIE
|
||
(« Assistance batterie nuit », puis reseau force de 06:02 a 06:42 ; session
|
||
7,9 kWh dont 2,2 reseau). L'agent a relaye fidelement une fausse verite.
|
||
Correctif : correspondance EXPLICITE libelle par libelle de `sourceModeLabel`
|
||
(HA_SERVICE_CALLS_OUTPUT.js), nouveaux etats `en_charge_batterie`,
|
||
`en_charge_sonde`, et `en_charge` sans origine pour un libelle inconnu. Test
|
||
garde-fou qui lit la table DANS le code du controleur : un libelle ajoute la-bas
|
||
fait tomber les tests (mutation verifiee). Tests 32/32.
|
||
⚠️ Lecon : un capteur-verdict deplace la fragilite de la fiche vers le code ; le
|
||
code doit donc etre teste sur TOUT le domaine d'entree (ici les sept libelles),
|
||
pas seulement sur les cas du banc.
|
||
|
||
⚠️ **Correction du diagnostic ci-dessus** : ce defaut etait reel, mais ce n'est
|
||
PAS lui qui a produit la reponse du matin. Transcript recupere par SPARK (vocal,
|
||
~11:49, « bilan energetique de la nuit ») : « la JEEP a pris 0,56 kWh (100 %
|
||
batterie, zero reseau), elle est arrivee a la cible de 35 % et s'est arretee vers
|
||
4 h ». FABRICATION : l'outil de l'agent ne lit que la session EN COURS (aucune a
|
||
11:49), et la voiture n'a pas de SOC — les « 35 % » sont la cible de la batterie
|
||
maison. J'avais conclu « l'agent a relaye fidelement » sans avoir vu sa reponse.
|
||
Correctif : `sensor.evcs_bilan_nuit` (etat `complet` / `en_cours`), calcule par
|
||
`donneesNuit()` de `tools/rapport-nuit.mjs` — le MEME code que le courriel de
|
||
07:30, extrait sans changer le texte (identique caractere pour caractere sur
|
||
cinq nuits : 25, 24, 20, 10 et 06/09). Attributs : vehicules (kWh, dont reseau,
|
||
debut, fin), fermetures reseau et import, SOC batterie maison, `soc_voiture` =
|
||
« aucun capteur », et `texte_rapport` (le rapport lisible a voix haute). Publie
|
||
au premier cycle puis toutes les 5 min. Tests 37/37.
|
||
SPARK active aussi la journalisation des entrees/sorties d'outils (retention
|
||
courte, jetons masques) : ce matin on n'a pas pu voir ce que l'agent avait lu.
|
||
|
||
Journaux OpenClaw (decision du proprio) : transcripts avec entrees/sorties
|
||
d'outils dans `/volume1/docker/openclaw-data/agents/<agent>/sessions/` (ARCHIVE3,
|
||
vu d'ici `/mnt/ARCH3/docker/openclaw-data/...`) — la source pour tout incident
|
||
de l'agent. Retention **30 jours** sur les `*.zst` archives (jamais les `*.jsonl`
|
||
actifs), tous agents : timer systemd `openclaw-session-rotate.timer` (quotidien
|
||
00:00, Persistent) -> `/usr/local/bin/openclaw-session-rotate.sh`. Skill
|
||
`session-logs` OFF (l'agent ne lit pas ses journaux). Jeton HA absent des
|
||
archives (0/89 au 25/09). ⚠️ Une mise a jour majeure de DSM a deja efface une
|
||
config systeme (sudo NOPASSWD, §75) : reverifier le timer apres chaque MAJ DSM.
|
||
|
||
Grafana « Le solaire » : panneau **Production du jour par chargeur** (yield_today
|
||
des trois chargeurs + Total, trace seulement si les trois publient). Le suiveur
|
||
V1 manquait a InfluxDB : `sensor.v1_*` absent de `influxdb.include` de HA —
|
||
ajoute le 25/09 (sauvegarde `configuration.yaml.bak-20260925-v1`, check_config
|
||
valide), **effectif au prochain redemarrage de HA, que le proprio fait lui-meme**
|
||
(apres : verifier le selecteur vehicule, §47). Le suiveur est aussi ajoute aux
|
||
panneaux des modes (etiquette « Suiveur », sinon il tombait dans « Ensemble ») et
|
||
du detail par tracker, dont la description attribuait a tort son absence a un
|
||
defaut de publication.
|
||
|
||
---
|
||
*Document mis a jour le : 25/09/2026 — bilan de nuit pour l'agent, retention des journaux, production par chargeur dans Grafana*
|