Commit Graph

113 Commits

Author SHA1 Message Date
Tallagrand Thierry
1132d3147f Le declenchement saisi en direct : 3550 mV, cinq secondes, et le plafond reste
Suivi console des trois modules pendant que l'alarme montait. A
13:04:48 les cellules meneuses sont a 3526 et 3541 mV, a 13:05:08 a
3555 et 3575, et a 13:05:13 le courant de charge autorise tombe de 50
a 30 A. Le seuil lu dans sysinfo est bien celui qui commande.

Ensuite les cellules se detendent et l'alarme repasse au vert, mais le
plafond reste : c'est pour cela que le bridage dure des heures quand
l'alarme ne dure que des minutes.

Le module sain de la meme chaine montre 13 mV au meme instant. Le
bridage est produit par deux modules et subi par les sept.

Les dates des codes-barres sont des dates de fabrication : le pack
sain a sejourne en stock, ce qui reconcilie les six mois d'ecart avec
les deux ans de service. Et comme il a encaisse 345 cycles sans une
seule cellule marquee, les degats de l'autre pack ne viennent pas de
l'usure mais de deux cellules descendues sous trois volts.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-09-05 13:08:31 +02:00
Tallagrand Thierry
9b8e25bafe L'horloge de BAT3 est a l'heure, et l'annee se donne sur deux chiffres
Elle avancait de 6 h 09 min 12 s, mesure directement en comparant son
RTC a l'horloge du poste - ce qui tranche definitivement contre
l'estimation de huit heures obtenue le matin par correlation.

Le message d'usage annonce time [year] [month] [day] [hour] [minute]
[second] sans preciser que l'annee tient sur deux chiffres : la forme
a quatre chiffres est refusee.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-09-05 12:48:38 +02:00
Tallagrand Thierry
342791ef32 BAT3 n'a qu'une cellule atteinte, moins que deux modules restes en service
Au repos, quatorze de ses cellules tiennent dans quatre millivolts et
la quinzieme est cinquante-cinq millivolts plus bas. Sur son
historique elle oscille sur 683 mV quand ses voisines font 150 -
signature presque identique a la cellule 12 du module 1.

Le module retire du parc a donc moins de cellules malades que deux de
ceux qui y sont restes. Neuf cellules sur les cent cinq du parc, sur
trois modules ; tout le reste est intact.

Le LVHUB n'a rien : les diodes sont vertes et la mesure du courant
prouvait deja qu'il agrege les sept modules. Son journal de
redemarrages, ce sont nos propres branchements de console.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-09-05 12:43:10 +02:00
Tallagrand Thierry
d59bf59070 Cinq modules sur sept sont sains, et le hub n'y est pour rien
Lecture simultanee : les quatre modules du pack 2 totalisent 50,65 A
quand le GX en rapporte 90,60. La difference, 39,95 A, ce sont les
trois modules du pack 1. Le GX agrege donc bien les sept, et les deux
packs se partagent le courant a cinq pour cent pres.

Ma conclusion de §50 - la moitie du parc invisible - etait donc
fausse. Le hub possede un mode console dans lequel le brancher le fait
probablement entrer, ce qui explique les valeurs aberrantes lues.

Le pack 2 affiche soixante cellules a zero apres 340 cycles. La
reparation porte donc sur huit cellules reparties sur deux modules du
pack 1, et rien d'autre.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-09-05 12:27:56 +02:00
Tallagrand Thierry
55f981a730 Deux modules atteints sur trois, et la jauge suit la cellule la plus faible
La console repond depuis Linux. L'adressage a distance fonctionne : un
branchement par pack suffit, et `soh <adresse>` donne le compteur de
sante par cellule en une seconde.

Le module 3 designe exactement les cinq cellules deduites ce matin de
son historique. Le module 1, sain en juillet, est passe de 7 a 498
evenements de surtension en six semaines ; sa cellule 12 oscille sur
691 mV quand ses douze cellules saines font 178 mV.

Ses pires ecarts sont en bas, pas en haut : 317 mV a un pretendu
2 % de charge alors que le parc etait a 3,236 V par cellule. Le BMS
croit la batterie vide parce qu'une cellule l'est. C'est tres
probablement le genou a 33 % mesure dans la courbe energie/SOC.

Correction : le champ SOH de stat n'est pas une note sur 100, le
module irreprochable affiche 0 comme le module abime.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-09-05 12:05:39 +02:00
Tallagrand Thierry
021aa9f127 Le bridage a un coupable : cinq cellules du module d'adresse 3
Les exports BatteryView contiennent la sortie brute de la console du
BMS : 1798 enregistrements sur 37 jours, avec les 15 tensions de
cellule a chaque fois. La preuve etait deja ecrite, il n'y avait rien
a attendre de l'apres-midi.

Les cellules 2, 6, 10, 12 et 15 montent a 3554-3649 mV quand les dix
autres plafonnent a 3440, et descendent a 3128-3236 quand les autres
s'arretent a 3252. Monter plus haut ET descendre plus bas est la
signature d'une capacite moindre. Le BMS leur attribue d'ailleurs un
pourcentage de charge distinct dans chaque enregistrement, et note le
module 0 sur 100 contre 100 pour un module sain du meme parc.

L'ecart est de 12 mV a 60 % de charge et de 168 mV a 85 % : c'est
pourquoi un releve du matin ne peut rien montrer.

Deux outils rejouables : la console serie sans dependance, dont le
lecteur de table a ete eprouve sur la sortie reelle avant tout
branchement, et l'analyse d'historique.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-09-05 11:22:44 +02:00
Tallagrand Thierry
0adf86fe1e Le bridage de charge est une cellule, et il commence a 75 %
L'episode du 04/09 apres-midi etait deja enregistre dans InfluxDB, sans qu'aucun
cable serie ait ete branche : l'alarme "tension de cellule elevee" passe a
warning a 16:36:04, la limite de courant imposee par le BMS tombe de 150 a 20 A
en trois minutes, et le parc n'est alors qu'a 50,76 V pour une CVL autorisee de
53,2 V — il restait 2,4 V de marge.

Ce n'est donc pas la tension du parc qui limite mais UNE cellule. A 50,76 V sur
15 cellules, la moyenne est de 3,384 V : la cellule fautive est ~200 mV
au-dessus des quatorze autres.

Deux corrections a ce que nous croyions : le bridage commence vers 75 % de SOC
et non 94 % (le 94 % est seulement ou le parc finit par arriver a 20 A), et
`cell_imbalance` reste no_alarm tout du long — seule la protection de surtension
se declenche.

Et l'explication de "je ne vois rien dans les logs" : le desequilibre est
invisible sous ~70 % de SOC, la courbe LiFePO4 y etant plate. Une capture faite
le matin batterie a 45 % ne peut rien montrer.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-09-05 00:07:54 +02:00
Tallagrand Thierry
ba99c506d7 Connexion InfluxDB retiree du YAML, et un effet de bord a connaitre
configuration.yaml : sept cles de connexion retirees (api_version, ssl, host,
port, token, organization, bucket), include/exclude/tags conserves. Home
Assistant avait deja importe la connexion dans une entree d'integration, donc
l'historisation n'a jamais ete menacee. Sauvegarde
SAVE_CONFIG/configuration.yaml.bak.20260904-194304, diff verifie.

Redemarrage en 30 s. Apres : InfluxDB recoit 1065 points en 90 s, aucune erreur
au journal, PostgreSQL inchange.

⚠️ Effet de bord releve par le detecteur d'evenements, sans le chercher : le
reglage manuel du selecteur de vehicule fait a 19:36 (VW -> JEEP) a ete ANNULE
par la restauration d'etat du redemarrage (JEEP -> VW a 19:44:12). Ce
selecteur determine l'heure de depart retenue, donc toute la mecanique de nuit.
Regle inscrite : apres un redemarrage, relire les helpers regles a la main dans
l'heure precedente.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-09-04 19:46:13 +02:00
Tallagrand Thierry
5fa4edf293 Le systeme : replique locale de la vue generale VRM
La console VRM est hebergee dans le cloud Victron et disparait quand une
coupure d'orage emporte Internet. Meme vision, lue sur le reseau local :
reseau, charges, batterie, borne, production, detail par tracker, les flux
dans le temps et l'energie heure par heure.

Tout dans Grafana, rien dans Home Assistant — et pour une raison trouvee en
verifiant si son tableau Energie pouvait servir : gx_device_pv_energy et les
compteurs d'energie batterie du GX se remettent a zero sans le signaler.
state_class total sans last_reset, donc HA n'auto-detecte pas la remise a zero
et a enregistre -373,35 kWh sur l'heure de 07:00. Les energies sont donc
obtenues en INTEGRANT LA PUISSANCE, methode qui ignore le probleme.

Trois versions du calcul avant la bonne : somme ponderee (laissait des trous,
une grandeur stable n'etant jamais reecrite), moyenne des minutes presentes
(sur-comptait : 5,13 kWh a 01 h pour 22 minutes observees), puis axe des
minutes complet + report + avg x count/60 = energie reellement accumulee,
correcte y compris pour l'heure en cours.

Recoupement avec la capture VRM du proprietaire : 8,07 kWh de reseau contre
"Depuis reseau 9,0 kWh", l'ecart valant exactement les treize minutes entre
l'ouverture des heures creuses et le demarrage du service d'historisation.

45/45 requetes verifiees contre les bases reelles.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-09-04 09:44:29 +02:00
Tallagrand Thierry
64aee4bfcc Les requetes s'executaient, les grandeurs etaient fausses
Trois defauts trouves en LISANT les tableaux, qu'aucune des 19 requetes ne
signalait puisqu'elles s'executaient toutes sans erreur.

1. `historise-evcs.mjs` horodate chaque mesure avec son propre last_updated —
   le vrai instant de la mesure, et c'est le bon choix. Mais deux grandeurs ne
   partagent alors presque jamais le meme ts : 2656 lignes pour 2656 instants
   distincts. Mes GROUP BY ts rendaient une ligne par grandeur avec une seule
   colonne remplie, donc la courbe "Excedent" — la grandeur meme du §36 —
   etait VIDE sur les 2650 lignes.

2. Le service n'ecrit que les changements, donc un regroupement a la minute
   laisse des trous : la difference n'existait que 73 minutes sur 434. Report
   de la derniere valeur connue, ce que fait aussi le controleur en temps
   reel. 430/435 apres.

3. L'energie horaire par sum(valeur)/60 suppose 60 echantillons par heure ; il
   y en a eu 26 a 47. Integration ponderee par la duree, plafonnee a 300 s
   pour qu'un arret du service n'extrapole pas une valeur perimee. ~9 %
   d'ecart. Le "25 a 58 %" que j'avais d'abord annonce etait faux : il
   comparait la somme a la moyenne, qui ignore la duree.

Plus deux corrections d'affichage : la colonne `jour` s'affichait
"2026-09-04 02:00:00" (date nue rendue comme instant UTC), et le decompte des
chargeurs MPPT est de six entites publiees, pas sept.

Lecon : verifier-dashboards.mjs prouve qu'une requete s'EXECUTE, pas qu'elle
rend la grandeur voulue — une colonne integralement nulle passe sans un mot.
Ce sont les courbes regardees a l'ecran qui ont attrape les trois.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-09-04 08:48:42 +02:00
Tallagrand Thierry
fe029cfdff Grafana : les deux bases se consultent, et les requetes sont verifiees
Trois tableaux de bord provisionnes depuis git, sur le modele de la regle R2
(le depot est la source de verite, l'interface ne peut pas les ecraser) :

  La nuit      SOC reel contre SOC exige par le bilan, et la marge entre les
               deux. C'est la question qui avait demande une nuit d'archeologie
               le 03/09.
  Le solaire   l'excedent (§36), la censure, et le mode declare par chacun des
               sept chargeurs (§37) — le signal le plus direct dont on dispose.
  Prevision    l'ecart heure par heure, avec la bande de censure dessous : une
               production sous la prevision peut vouloir dire mauvaise
               prevision OU absence de preneur.

Les evenements de la table `evenement` deviennent des marqueurs verticaux sur
tous les graphiques — une courbe sans ses evenements ne s'interprete pas.

tools/verifier-dashboards.mjs rejoue CHAQUE requete pour de vrai (SQL contre
PostgreSQL, Flux contre InfluxDB, macros Grafana substituees), annotations
comprises puisqu'elles s'executent sur tous les panneaux. Sans lui une requete
cassee ne se voit qu'a l'ecran, panneau par panneau. 19/19 au deploiement.

Port 3001 et non 3000 : sonde avant d'ecrire la ligne, quelque chose ecoute
deja sur 3000 — la lecon du 5432 deja pris par le PostgreSQL de DSM.

Connexion PostgreSQL par le role evcs_lecture : un tableau de bord ne doit pas
pouvoir ecrire dans la memoire. Aucun secret duplique, aucun secret commite :
le provisionnement les reference par $VARIABLE depuis les deux .env.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-09-04 08:06:25 +02:00
Tallagrand Thierry
2846192e96 InfluxDB en service : la memoire de mesures est complete
Redemarrage de Home Assistant a 07:28, apres la fermeture de la fenetre HC,
aucune charge en cours et PV nul. API de retour en 22 s, capteurs revenus en 31
apres le keepalive Venus, un seul cycle du controleur manque. Aucun trou dans
l historisation PostgreSQL : l ecart maximal entre deux mesures de SOC sur les
40 minutes encadrant le redemarrage est de 80 s et se situe avant, ce qui est la
cadence normale du service.

249 entites distinctes ecrivent dans InfluxDB dans les dix minutes qui suivent,
a la resolution native — jusqu a 84 points en 10 min pour la puissance AC-out.
C est ce que PostgreSQL ne peut pas faire et ce pour quoi la proposition B
existait.

Premiere interrogation reelle de la memoire avec le role de lecture seule : onze
points sous la ligne du bilan ce matin, lisibles en une requete.

Faille de conception reperee et consignee : la table evenement a ete creee pour
consigner deploiements et incidents, mais le role d analyse est en lecture seule
donc je ne peux pas y ecrire. Ce redemarrage aurait du y figurer. A trancher
entre une commande d ecriture dans le service d historisation ou un INSERT
restreint a cette seule table.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-09-04 07:30:38 +02:00
Tallagrand Thierry
cf6e9afe31 La session unique tenait le contacteur, pas l energie
La veille de nuit a rendu son verdict : UNE seule bascule sur 69 releves entre
01:26 et 07:07. La session reseau unique fait ce pour quoi elle a ete concue,
EDF ferme d un bout a l autre de la fenetre sans creneau ni oscillation.

Mais a 02:50, la voiture finie, le sourceMode est passe a bloque et la consigne
reseau est retombee de 5078 a 50 W. Contacteur ferme, reseau disponible, heures
creuses, et l ESS ne demandait que 50 W pendant que la maison tirait 770 W sur
la batterie. Trois heures et demie, SOC 44 vers 17 pour cent, 2,60 kWh pris a la
batterie quand le reseau etait la et bon marche. L Auto Charge Manager est reste
pret a recharger avec DVCC a 30 A, mais la consigne ne demandait jamais l
energie. C est le defaut du 01/09 revenu ailleurs : j avais etabli que fermer le
contacteur ne suffit pas, puis cree la veille une nouvelle raison de le garder
ferme sans la brancher sur la consigne.

gridSessionActive inclut desormais l engagement de session. Regle : tant que le
contacteur est ferme a notre demande, la consigne couvre la maison, peu importe
laquelle des deux raisons le tient.

Consigne de repos portee de 50 a 200 W a la demande du proprietaire, avec une
justification mesuree : sur 12 074 echantillons du point de raccordement, 17 %
sont negatifs, mediane -18 W. Ce n est pas de l injection — la batterie
debitait 744 W au meme moment et les 22,7 Wh cumules representent 0,9 % de ce
qu elle perdait — c est le regulateur qui chasse autour d une cible trop proche
de zero. A 200 W le point de fonctionnement reste positif sur l essentiel des
excursions, sans supprimer les pointes les plus fortes.

Consigne aussi que le 20 % n est pas le notre mais le plancher de l ESS, qui a
fini par faire de lui-meme a 06:20 ce que la session aurait du faire depuis
02:50, apres avoir vide la batterie de 27 points.

Golden 78 -> 80, deux mutations ciblees. Piege rencontre et documente : la
premiere redaction du contrefactuel portait deux fois la clef balance_status, et
en JavaScript la derniere gagne — il testait donc l inverse de son libelle. Un
contrefactuel doit reposer sur une difference physique, pas sur la surcharge d
une clef deja presente.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-09-04 07:21:08 +02:00
Tallagrand Thierry
b27c91a3f6 La memoire s arretait a la semaine faute d un attribut, pas de place disque
Trois corrections a ce que j affirmais. L historique brut ne s arrete pas a
7 jours : il remonte au 14/08, soit 20,8 jours, et s allonge vers les 90
configures — mon chiffre datait du 27/08. La base n est pas corrompue : le
"malformed" venait de ma lecture avec immutable=1, qui ignore le journal WAL. Et
le volume de 10.10.10.17 n est pas de 133 Go mais de 7,0 To dont 5,0 libres :
j avais interroge df sur le dossier parent du point de montage, donc sur la
racine de mon propre poste. Le proprietaire l a releve, capture a l appui.

Cause reelle du manque de memoire : sur 288 entites ayant des statistiques long
terme, les quatre series dont le bilan depend n y etaient pas — consommation,
PV, reseau, courant batterie. Home Assistant ne construit ces statistiques que
pour les capteurs declarant state_class, et neuf capteurs sur vingt a unite
numerique le declaraient. Le SoC le declarait, d ou ses six mois d historique.

Correctif : dix lignes state_class: measurement dans configuration.yaml, rien
d autre, diff verifie, sauvegarde prealable. Exclu volontairement la puissance
nominale des onduleurs, constante a 9000 W. Procedure check_config, mqtt.reload
puis keepalive Venus pour forcer la republication — aucun trou, les series sont
revenues numeriques dans la seconde. 288 entites en statistiques deviennent 299.

Fait a 00:57, vingt-sept minutes avant l ouverture de la fenetre HC, premiere
nuit du test de la session reseau unique : un rechargement MQTT aveugle le
controleur le temps de la republication et ne doit jamais avoir lieu juste avant
01:24.

Consigne aussi la verification de la prevision solaire — le total est bon a 89
et 110 % pres, mais la forme est systematiquement decalee, production plus tot
que prevu et apres-midi sur-promis d un facteur 2 a 3 apres 16 h, ce qui
sous-estime l energie a couvrir — et le constat sur le conseiller en mode ombre,
d accord 92,5 % du temps avec les regles et qui argumente desormais pour le
palier qu on vient de remplacer.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-09-04 00:59:17 +02:00
Tallagrand Thierry
6603c5dfd2 La conversion energie/SOC devient une courbe mesuree, pas une constante
576 paliers de SOC mesures sur 8 jours (tools/mesure-courbe-batterie.mjs,
ajoute) : pour chaque palier ou le SOC reste a une valeur puis descend d un
point, on integre la puissance batterie, en ecartant les paliers ou la batterie
a charge et ceux ou le reseau a apporte quoi que ce soit.

Resultat : plate a 0,169 kWh/point de 33 a 93 — six tranches independantes entre
0,163 et 0,171 — genou net a 32-33, puis 0,097 en dessous. Sous le genou un
point de SOC vaut 57 % de ce qu il vaut au-dessus, ce qui est coherent avec le
parc reel (un module en panne sur huit, un autre qui faiblit).

Energie utile totale de 100 a 22 % : 12,39 kWh mesures, contre 11,70 vus par le
bilan (15 kWh a plat) et 13,65 par INPUT_PARSE (17,5). Les deux constantes
etaient fausses, dans des sens opposes.

Comme 15 kWh se situe ENTRE les deux pentes, l erreur changeait de signe : SOC
requis trop bas de 3 a 4 points pour un petit deficit, trop haut de 4 a 6 pour
un gros. Cela corrige au passage une affirmation inexacte de la section 40, ou
j avais ecrit que required_soc etait systematiquement trop bas d un facteur
1,75 : ce facteur comparait la vitesse de descente du SOC a celle de la ligne,
deux grandeurs differentes, et l ecart venait surtout de la sous-estimation de
la consommation par le profil p50. La correction est posee en tete de la
section 40.

Trois fonctions remplacent les cinq conversions lineaires de BALANCE.js ;
requiredSocAtStartPct reste non ecrete au-dela de 100, l extrapolation utilisant
la pente haute. INPUT_PARSE passe de 17,5 a 16,9 avec la consigne explicite
qu un calcul traversant le genou doit lire la courbe et non cette constante.

Tests du bilan 42/42 apres mise a jour deliberee de six attendus, chacun verifie
a la main contre la courbe. Un libelle corrige : le seuil fixe de 30 % tombait
juste ce matin-la par coincidence, pas par construction. Deux mutations — pente
basse ramenee a la pente haute, puis genou ramene au plancher — font tomber les
six memes scenarios. Golden 78, hysteresis 7 et advisor inchanges.

Les trois nombres sont des resultats de mesure, pas des reglages, et vivent dans
le code avec l outil qui les produit ; a rejouer apres l extension du parc.

Principale erreur restante du bilan, desormais devant la conversion : le profil
de consommation p50 sous-estimait de 33 % les heures 03-06 de la nuit du
02-03/09. A instruire separement.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-09-03 23:28:57 +02:00
Tallagrand Thierry
914ef021b2 Session reseau unique de la nuit : engagement sur le bilan, sortie sur la fenetre
§26 avait pose l objectif et designe le critere. Avant d ecrire quoi que ce
soit, j ai mesure les kWh reellement sortis de la batterie par point de SOC sur
cinq fenetres et trois nuits : 0,164 a 0,171 kWh/point au-dessus de 42 %, soit
environ 17 kWh, mais 0,121 entre 45 et 22 % et 0,082 entre 33 et 20 %. En bas
d echelle un point de SOC vaut moitie moins, alors que BALANCE.js convertit avec
une constante unique de 15 kWh. required_soc y est donc systematiquement trop
bas — c est le facteur 1,75 mesure la nuit du 02-03/09, ou le SOC descendait
bien plus vite que la ligne.

Cette mesure a dicte la conception : le relachement de la session ne peut pas
etre un seuil de SOC, puisqu il porterait sur une grandeur fausse et que tout
seuil que le SOC repasse ensuite rouvre l oscillateur du 27/08. Les deux
variantes evidentes — relacher sur required_soc, ou sur required_soc_prudent
avec la bande p50/p80 — ont ete ecartees pour cette raison.

Retenu : engagement sur le bilan (batterie sous la cible), relachement a la fin
de la fenetre. L oscillation devient structurellement impossible, la condition
de sortie etant monotone : une fenetre ne se ferme qu une fois. Un nouveau
helper input_boolean.victron_evcs_night_grid_session_committed porte
l engagement, cree par input_boolean.reload sans redemarrage HA et ecrit
seulement sur changement reel ; sans cette persistance la garde redeviendrait
une bande, donc un oscillateur.

Effet : l ACM recharge jusqu a la cible puis tient la batterie a 2 A, la maison
finit la nuit sur le reseau en heures creuses au lieu de vider la reserve, et la
batterie arrive a l aube pres de sa cible avec de la place pour le solaire. La
coupure immediate E2 de l hysteresis exige l absence d override et le helper
takeover reste ON : aucune modification du workflow d hysteresis.

Golden 75 -> 78. Le scenario epingle quelques heures plus tot comme limite
connue devient celui du correctif, attendu mis a jour dans le meme commit.
Quatre mutations ; la plus parlante retire la garde bilan et fait tomber les
trois scenarios anti-oscillateur du 27/08 — les tests de l ancien correctif
protegent le nouveau code.

Prerequis identifie et non traite : la conversion kWh vers points de SOC est une
constante la ou la realite est une courbe. Consequence, un sous-declenchement
possible en bas d echelle, jamais une oscillation. Prochain chantier du bilan.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-09-03 23:14:49 +02:00
Tallagrand Thierry
05bdf019c2 La cible du matin devient une energie a couvrir, plus un palier
La regle classait le lendemain en trois paliers a partir de son TOTAL (>= 18 kWh
-> 35 %, >= 10 -> 55 %, sinon 85 %) et ignorait donc l heure d arrivee de
l energie. Le 03/09 demain annoncait 33,9 kWh — donc "fort", donc 35 % — avec un
matin creux (0,03 kWh a 7 h, 0,77 a 8 h) et un croisement a 9 h. Meme defaut que
le plancher du soir, a l autre bout de la nuit.

Releve de la nuit 02-03/09, requis contre reel : 00:30 62,4 / 53 ; 03:00
50,4 / 45 ; 04:30 41,7 / 37 ; 06:00 37,1 / 22 — cible fixe a 35 tout du long.
Le required_soc decroit proprement avec la nuit qui se consomme (6,1 -> 0 kWh a
couvrir), la batterie est restee sous la ligne toute la nuit, et le bilan le
savait des 00:30. A 03:00 EDF a ete relache cinq points sous la ligne ; le
reseau est revenu de 07:24 a 10:33 au plein tarif, 1,49 kWh.

La cible vaut desormais min(90, max(palier ou advisor, required_soc)). Sens
unique delibere : la direction corrigee est celle de l echec observe, et le
principe unificateur des deux cablages est que le bilan ne pousse jamais dans le
sens "couvre moins bien la nuit". Plafond 90 parce qu au-dela la batterie cesse
d etre un puits et evince la production du matin, et parce que le bilan publie
sans ecretage des valeurs superieures a 100 — sans ce plafond la cible serait
inatteignable et EDF resterait allume toute la nuit. C est deja la borne du
chemin advisor, aucune constante nouvelle.

Pas d oscillateur : required_soc decroit de facon monotone pendant la nuit et la
passe unique de recovery reste en place. Gardes et repli identiques au plancher
du soir, kill-switch existant.

Golden 70 -> 75. Quatre mutations font tomber chacune exactement un scenario
different. Un cinquieme scenario fige une LIMITE CONNUE, mesuree par sonde : la
passe unique de recovery latche le relachement pour toute la session, donc la
cible dynamique n ameliore que la premiere passe. §26 avait deja designe le bon
critere de re-engagement — un budget d energie restant a couvrir, qui appartient
au bilan ; la suite touche la machine a etats de la nuit et fera l objet d un
chantier propre.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-09-03 22:51:09 +02:00
Tallagrand Thierry
6f3f98e8b6 Le plancher du soir vient de l energie a couvrir, plus d un niveau fixe
grep evcs_balance sur les deux workflows de decision renvoyait 0 depuis la mise
en service du bilan le 26/08 : il calculait l heure de croisement, l energie a
couvrir et le SOC requis, et personne ne l ecoutait. Le 03/09 a 19:44 les deux
nombres coexistaient dans le meme systeme — evening_soc_start_min a 85 %, un
niveau qui ne sait rien de la nuit, contre evcs_balance_required_soc a 99,7 %,
l energie a couvrir jusqu au croisement de 9 h. A SOC 94 le premier autorisait
la charge, le second disait que la batterie ne passerait pas la nuit seule.

Le plancher de demarrage du soir vaut desormais max(regle, bilan). Sens unique
delibere : le bilan peut durcir, jamais relacher. L assouplir — il dira souvent
moins de 85 % par forte prevision d ete — autoriserait des charges qui n ont pas
lieu aujourd hui, decision distincte a valider pour elle-meme. Le max rend au
passage la garde robuste sans borne ni ecretage : une valeur nulle, negative ou
aberrante ne peut pas relacher le plancher.

Portee demarrage : le plancher de maintien reste min(...), donc a 80 %, et
aucune charge en cours n est coupee. L abondance P6 continue de primer, etant
une preuve mesuree que la ressource depasse ce que le systeme absorbe.

Gardes : fraicheur inferieure a 30 min (six cycles du bilan), horodatage futur
rejete, statut ok, valeur finie. Sinon regle historique. Aucun nouveau toggle :
evcs_balance_enabled a OFF arrete les ecritures du bilan, balance_last_run se
fige, la fraicheur expire et le plancher retombe seul sur 85 % en une
demi-heure — un helper de plus aurait fait doublon.

Gabarit complet re-rendu contre HA : 195 champs, JSON valide, aucun null.
parseAdvisorRunToMs reutilise, l advisor et le bilan publiant le meme format.

Golden 66 -> 70. Quatre mutations — bilan ignore, Math.max remplace par une
affectation directe, garde de fraicheur supprimee, garde de statut supprimee —
font tomber chacune exactement un scenario, et un different a chaque fois.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-09-03 22:19:33 +02:00
Tallagrand Thierry
7a26078e73 La provocation solaire se demande aux chargeurs, pas au SOC
Le correctif precedent bloque l incident de 19:44, mais un excedent proche de
zero est ambigu : c est la signature de la censure ET celle de l equilibre de
fin de journee. Le releve du 03/09 contient les deux avec le meme excedent —
18:50 : +14 W, ressource refusee ; 19:41 : +1 W, plus rien a donner. Rejeu du
19:41 : batteryAssistSolarStartOk etait encore vrai. Trois minutes avant
l incident, le systeme aurait commis la meme faute.

Le plan annoncait de lire evcs_balance_pv_censored. Lecture de CENSORSHIP.js :
ce drapeau est un OU de motifs dont l un est exactement le proxy qu on voulait
remplacer (socPct >= 90 et batterie sans puits). Et il est reste ON jusqu au
calcul de 19:50, soit cinq minutes APRES le demarrage de la charge — ce qui l a
fait basculer n est pas la censure mais sun_elevation passant sous 10 degres.
Il n aurait pas bloque l incident.

Le signal juste, ce sont les chargeurs eux-memes : sept entites
sensor.*_mppt_operation_mode, jamais lues par aucun workflow. mppt_active = je
suis a mon point de puissance maximale, je donne tout ; voltage_current_limited
ou off = je me retiens faute de preneur. Le 03/09 elles ont bascule a 19:20,
soit 24 minutes avant pv_censored, sans aucun proxy et a la cadence de la
boucle. Contre-verification le 01/09 a 14:22 : les trackers restaient limites
PENDANT une charge de 3,4 kW sous 6,9 kW de PV, donc le signal ne s auto-annule
pas a midi.

Collecte sans aucun entity_id code en dur (selectattr sur mppt et
operation_mode), expression testee sur /api/template puis gabarit complet
re-rendu : 191 champs, JSON valide, aucun null. Lectures inexploitables
ecartees, et repli sur le comportement anterieur quand il n en reste aucune.

Garde de DEMARRAGE uniquement, structurellement : la lier au sourceMode ou au
maintien ferait que la charge, en donnant un preneur au MPPT, detruirait sa
propre condition d autorisation — le bistable de l abondance P6 corrige le
24/08.

Golden 64 -> 66. Mutation dans trois directions : garde neutralisee -> 1 echec
cible, provocation toujours refusee -> 3 echecs, lecture illisible traitee
comme "a fond" -> 1 echec sur le scenario de repli.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-09-03 21:41:31 +02:00
Tallagrand Thierry
ef3d7ed7b2 Un demarrage se decide sur l excedent, pas sur la production
Le 03/09 a 19:44, voiture branchee : PV 758 W, maison 1202 W, batterie deja
a -12 A, nuit qui tombe. Le controleur a lance 1,6 kW de charge parce que
pv_start_min_w (700 W) est une puissance PV absolue : "758 >= 700, donc il y
a du soleil". L excedent valait -444 W. En 33 minutes la voiture a pris
0,897 kWh et la batterie en a rendu 1,479 kWh (SOC 94 -> 85), la veille d une
nuit que le bilan energetique annoncait deja deficitaire.

Rejeu du releve dans la vraie chaine : rawSolarStartOk ET
batteryAssistSolarStartOk etaient tous deux vrais. Corriger le seul seuil PV
n aurait donc rien change ; les deux chemins sont traites ensemble.

La grandeur juste est ce qui reste une fois la maison servie. Sans injection
et reseau absent, PV - maison(hors EVCS) vaut la puissance batterie au signe
pres, et separe les deux situations que la mesure PV seule confond : sous
censure la production se cale sur la maison, l excedent vaut ~0 et il y a de
la ressource refusee ; en deficit reel l excedent est negatif et la batterie
porte deja la maison. Zero est la frontiere physique entre les deux, verifiee
sur le releve du 03/09 (excedent positif sur toute la plage ou pv_censored
etait ON, negatif ensuite).

Aucune constante nouvelle, aucun champ de snapshot, aucun helper :
derived.houseNonEvcsW existait deja. Le chemin "soleil reel" reutilise
pv_start_min_w tel quel, applique a la bonne grandeur ; le chemin
"provocation" exige seulement excedent >= 0. Demarrage uniquement : les
conditions de maintien gardent leur plancher et leur tolerance temporelle.

Golden 61 -> 64, autour d une paire de releves reels pris a 54 minutes d ecart
dont les lectures PV ne different que de 11 W (769 puis 758) : le premier
demarre, le second non. apresmidi-provocation-p3 est corrige : il portait
PV 300 W, maison 600 W, batterie +2 A reseau ouvert, un trou de 300 W que rien
n alimente, et passait quand meme parce que le demarrage ne regardait jamais
le bilan. Mutation dans les deux sens : 2 echecs cibles a chaque fois,
excedent-censure-demarre restant vert (il tient par le chemin assistance).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-09-03 20:53:50 +02:00
Tallagrand Thierry
10987a04d8 Un depassement souple de la batterie doit durer pour compter
La table des bandes SOC declarait depuis toujours un courant souple tolere
pendant des minutes et un courant dur tolere quelques secondes. Les deux
tolerances etaient calculees, exportees dans le debug, et lues par aucune
decision : le controleur comparait un echantillon instantane a un plancher,
toutes les 30 s.

A SOC 94 la batterie est en float et son courant oscille entre +1,8 et -2,6 A
d'un echantillon a l'autre. Le test devenait un tirage a pile ou face et la
charge du vehicule s'arretait sur du bruit : deux fois le 01/09, quatre a six
fois par jour la semaine precedente. Chaque arret coutait environ 0,45 kWh,
la batterie etant pleine et le vehicule le seul preneur.

Le correctif est purement temporel : aucun seuil n'est deplace, aucune
constante ajoutee. La tolerance de la bande est branchee sur les trois
conditions de MAINTIEN, via un helper de persistance qui porte le debut du
depassement en cours. Le plancher de demarrage et le garde dur restent
instantanes : la tolerance est du confort, jamais du risque.

Golden 56 -> 61. Preuve par mutation dans les deux sens : tolerance supprimee
-> 2 echecs cibles, tolerance infinie -> 3 echecs cibles, l'arret dur restant
vert dans les deux cas.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-09-01 20:10:28 +02:00
Tallagrand Thierry
a7ebaabb8b Chemin d ecriture du chien de garde demontre, pas seulement simule
Sonde de 777 W reellement publiee sur le topic de consigne du GX,
relue, puis valeur d origine remise par le script. Le dry-run supprimait
exactement ce maillon.

Et la fin de session s est deroulee dans le bon ordre sans coordination :
consigne retombee a 50 W a 03:31:30 avec l etat de fin de charge, puis
contacteur ouvert 34 s plus tard. La demande baisse avant que le reseau
parte.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-09-01 03:36:09 +02:00
Tallagrand Thierry
57c696928d Sauvegarde Home Assistant : configuree, poussee sur deux autres machines, verifiee
Aucune sauvegarde HA n avait jamais ete faite, et git ne la couvrait pas
-- un seul fichier HA y etait versionne. HA declarait pourtant trois
destinations Synology, dont 10.10.10.22 et une troisieme machine en
10.10.10.50 absente de toute la documentation du projet.

Quotidienne 04:45, sept copies, base d historique exclue (20 Mo au lieu
de 4,4 Go), poussee sur les trois machines. La configuration passe par
le websocket car l API REST ne l expose pas.

Verifiee archive en main : .storage, packages, dashboards, secrets et
custom_components presents, base d historique absente comme voulu.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-09-01 03:13:55 +02:00
Tallagrand Thierry
ccd764beb9 Chien de garde EVCS : remise en etat sur quand le controleur se tait
Le controleur pilote depuis cette nuit la consigne de puissance reseau.
S il meurt en pleine session, elle reste haute et le reseau reprend la
place du solaire toute la journee. Ce chien de garde repare ce risque.

Signal de vie : l API d executions n8n, pas un helper HA. Verifie que HA
ne rafraichit pas l horodatage d un input_text reecrit a l identique --
surplus_state paraissait fige depuis 40 min alors que tout tournait.

Il agit en MQTT direct sur le GX Venus, troisieme machine independante
des deux NAS, jamais via HA ni via le cloud Tuya. Il ne decide rien : il
remet la consigne au repos, arrete la borne, et se tait. Une seule
action par panne, verrou jusqu au retour du controleur.

Tests : controleur vivant, panne simulee, et verrou sur 5 cycles.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-09-01 02:59:56 +02:00
Tallagrand Thierry
807ae45b7f Etat reel de la resilience : trois SPOF nommes, dont un cloud
Le depot git est deja sur le second Synology. Aucune sauvegarde HA
n existe. La cle de chiffrement n8n tient dans 56 octets sans copie.
Et le contacteur EDF est un Tuya CLOUD : couper le reseau depend
d internet, sur un site ou l orage emporte la connexion.

Le GX Venus (10.10.10.9) est en revanche une troisieme machine avec son
propre broker MQTT : consigne reseau, DVCC et arret de borne y sont
atteignables sans HA ni cloud. C est le socle d un chien de garde.

Meteo-France est installee : la reserve d orage tourne deja.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-09-01 02:48:20 +02:00
Tallagrand Thierry
a57ff19ead La consigne de puissance reseau appartient au controleur
Fermer le contacteur ne suffit pas : au-dessus du SOC minimal, l ESS en
autoconsommation ne preleve que sa consigne et laisse la batterie porter
maison et voiture. Nuit du 01/09 : charge HC demarree a 01:25, arretee a
01:26 par le garde batterie, contacteur ferme et inerte jusqu a 02:00.

La consigne a 4200 W du proprietaire n etait pas decorative : c est elle
qui faisait fonctionner la prise de relais nocturne depuis le 07/08. La
retirer le 31/08 a supprime la substitution de journee et casse la nuit.

Le controleur ecrit desormais la consigne lui-meme, a partir du besoin
mesure, seulement pendant une session reseau deliberee, avec une bande
asymetrique : trop basse se corrige tout de suite, trop haute ne coute
rien. Deux ecritures en 25 minutes au lieu d une toutes les 30 s.

Golden 51 -> 56. Verifie en reel : batterie a 0 A, voiture a 3500 W.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-09-01 02:14:57 +02:00
Tallagrand Thierry
fc49e6c31a Sequence d ouverture : baisser le courant avant que le reseau parte
Le plafond majore (28 A en BOOST) n est legitime que tant que le reseau alimente
AC-IN : sinon les deux MultiPlus portent seuls la voiture plus la maison, le
mecanisme du W-105. Personne ne baissait avant l ouverture -- c est l hysteresis
qui ouvre, l EVCS l apprenait apres coup -- et quand il l apprenait, la reduction
attendait le cooldown de courant et descendait d un pas a la fois.

Correctif sans poignee de main ni helper nouveau : le plafond majore exige que
l EVCS DEMANDE lui-meme le reseau. Sa demande tombe au cycle ou la fenetre se
ferme (30 s), l hysteresis ne peut ouvrir qu ensuite (override disparu PUIS
min_on, cycle 1 min) : l EVCS baisse toujours avant, mecaniquement.

Second volet : un plafond n est pas une cible qu on approche. Reduction
immediate et directe au plafond, sans cooldown.

Le calcul du plafond a ete deplace apres sourceMode dans WINDOWS_SOURCEV2 ; rien
entre les deux ne le lisait, verifie avant de bouger.

Helper a 20 A par defaut : comportement inchange. Le correctif ne mord que sur
le BOOST 28 A, le cas dangereux.

Golden 48 -> 51, chaque cas apparie a son contrefactuel. Mutations des deux
volets separement : 1 puis 2 echecs cibles, restauration 51/51.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-08-31 20:03:23 +02:00
Tallagrand Thierry
f0479945c4 Fenetre d etablissement : ne plus decider sur les mesures du transitoire
A la fermeture du contacteur, PV, import et courant batterie ne decrivent aucun
regime permanent pendant ~150 s (mesure du 31/08). La boucle de 30 s y prenait
cinq decisions, et la moyenne PV 10 min en gardait la trace dix minutes de plus
-- le systeme lisait "plus de soleil", en concluait qu il avait besoin du
reseau, et confirmait sa propre premisse.

Aucun seuil nouveau : le systeme publiait deja l horodatage de la transition et
personne ne le lisait. Pendant la fenetre, on ne demarre pas et on ne laisse pas
une charge s arreter sur ces mesures ; les step-down restent libres.

Deux asymetries voulues : la fenetre ne s ouvre qu a l ARRIVEE du reseau (a sa
disparition les onduleurs reprennent tout, les gardes doivent agir plus vite),
et elle suspend le confort, jamais le risque.

Golden 42 -> 48, chaque cas apparie a son contrefactuel hors fenetre. Mutation :
gridSettling force a false -> 2 echecs cibles, restauration -> 48/48.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-08-31 18:18:03 +02:00
Tallagrand Thierry
f07d4cb0f1 Batterie pleine : l effondrement existe, mais il dure 2 min 30
Campagne decisive a SOC 90-92 %, batterie n absorbant plus que 22 A. La
fermeture du contacteur fait bien chuter la production de 79 % en un pas de
mesure (2663 -> 559 W), simultanement a l apparition de l import -- l
observation du proprietaire est exacte. Mais la recuperation est totale en
~2 min 30 : import 112 W et production 3158 W, au-dessus du niveau d avant.

Etat etabli hors transitoire : -7,0 % et +2,0 % contre les phases ouvertes
voisines. Aucune substitution permanente.

Meme mecanisme qu a batterie preneuse ; sans tampon, la seule variable d
ajustement est le bridage des MPPT, d ou l effet spectaculaire. Avec l ancienne
consigne a 4200 W le transitoire ne pouvait pas se terminer. Cout par
fermeture : ~150 Wh batterie pleine, ~50 Wh sinon.

Ni VEConfigure ni firmware justifies par ces mesures.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-08-31 13:20:30 +02:00
Tallagrand Thierry
40f34418d6 Le reseau ne prend plus la place du solaire, batterie preneuse
Nuit complete + deux campagnes alternees apres la correction de la consigne
reseau (4200 -> 50 W) : l'import colle a la consommation, la production monte
librement contacteur ferme, et les transitions locales donnent +0,5 % et
+13,1 % la ou le 27/08 mesurait -73 %.

Le transitoire de fermeture est caracterise : le reseau reprend toute la maison
et le solaire bascule vers la batterie, puis l'import retombe a la consigne en
~2 min 15 (25 W, 52 W). Cout ~50-60 Wh par fermeture.

Outillage : tools/test-edf-alterne.mjs (protocole alterne, restauration
garantie) et tools/analyse-test-alterne.mjs. Deux pieges d'instrumentation
corriges -- garde meteo quand les phases ouvertes divergent entre elles, et
biais du parseur qui laissait tomber les lignes ou le premier tracker etait
bride.

Reste ouvert : le cas batterie pleine, celui que le proprietaire designe comme
decisif, ou le solaire n'a plus de destination quand le reseau reprend la maison.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-08-31 11:23:35 +02:00
Tallagrand Thierry
457f4c8727 Consigne reseau a 4200 W : le proprietaire non lu de la substitution EDF
Le symptome prouve le 27/08 (73 % de la production solaire remplacee par du
reseau des que le contacteur se ferme) trouve une explication complete cote
GX, sans toucher aux onduleurs.

number.gx_device_ac_power_setpoint vaut 4200 W la ou le defaut Victron est
50 W. C'est le Grid setpoint de l'ESS : la puissance que le systeme s'efforce
en permanence de prelever sur le reseau. L'ESS regulant la puissance au point
de raccordement, son seul levier pour faire place a cet import quand la maison
et la batterie sont deja servies est de brider les MPPT via DVCC.

Les deux campagnes du 27/08 se reconcilient arithmetiquement : a 10:47 l'import
monte a 4113 W, soit la consigne ; a 11:38 la batterie en absorption n'accepte
que ~1070 W et conso 2258 + batterie 1070 - PV 1043 = 2285 W contre 2287
mesures. Le residu constant de ~1040 W etait la signature d'un plancher, pas
d'une reduction proportionnelle.

Seconde trouvaille : le SOC minimal de l'ESS est a 40 %, au-dessus de la cible
de 35 % du controleur. Le GX recharge donc sur le reseau de sa propre
initiative des que le controleur relache — etat `recharge` observe les 29 et
30/08. Troisieme automate contradictoire sur la meme batterie apres les charges
programmees. Arbitrage laisse au proprietaire.

L'assistant ESS tourne et aucune alarme VE.Bus n'est levee : l'hypothese d'un
assistant perdu au passage en parallele est affaiblie, pas eliminee. La partie
VEConfigure reste donc en seconde intention dans la procedure, avec sauvegarde
obligatoire et interdiction de relancer le System Configurator.

Aucun reglage n'est modifie ici : ce commit ne contient que le diagnostic et la
procedure.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-08-30 21:41:46 +02:00
Tallagrand Thierry
cf7eb47356 Bilan : reserve d orage, en mode ombre
Une coupure reseau n arrete pas l installation : le solaire et la batterie
continuent, seul le filet de secours disparait. La reserve a tenir est donc la
couverture prudente p80 que le bilan calcule deja — aucune constante nouvelle.
En deficit c est la fenetre traversee, en surplus la prochaine, car a 15 h la
reponse « rien a couvrir » est exacte et inutile.

Le seuil d activation est la vigilance orange, echelle officielle de
Meteo-France et non un nombre choisi ici. Le snapshot lit l alerte sans
connaitre la commune, donc le code marche des l installation de l integration
et publie « indisponible » en attendant.

Tests 38 -> 42. Le fixture du test de perimetre ombre ne contenait pas storm :
les nouvelles ecritures n etaient pas couvertes. Corrige, assertion explicite,
preuve par mutation.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-08-27 12:05:15 +02:00
Tallagrand Thierry
99aba9da0d Preuve : la presence d EDF substitue le reseau au solaire (-73 %)
Protocole alterne OFF/ON/OFF/ON, 15 s d echantillon, avec la tension batterie
et l etat des chargeurs MPPT — des capteurs qu aucun workflow ne lisait.

PV 3858 W hors reseau, 1112 W reseau present, 4025 W hors reseau, 1043 W
reseau present, 4358 W a la fin. Consommation inchangee, DVCC constant,
batterie loin de la saturation. Bascule en 75-90 s, retour en 32 s, quatre
fois. La production moyenne est plus haute a la fin qu au debut : l hypothese
nuages du test precedent est morte.

Ce n est pas la censure normale par manque de preneur : le solaire alimentait
integralement les memes charges 90 s plus tot. Anomalie apparue depuis le
passage des deux MultiPlus II en maitre/esclave. Piste configuration ESS en
parallele avant tout firmware.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-08-27 11:52:33 +02:00
Tallagrand Thierry
76e8695364 Mesure : test controle EDF vs MPPT, et un import reseau non demande
Le test infirme deux hypotheses et en decouvre une troisieme. La limite DVCC
reste a 130 A pendant toute la fenetre : l Auto Charge Manager n est pas en
cause. Aucun bridage du MPPT visible, mais la batterie avait 25 points de
marge — la condition du proprietaire (batterie pleine) n est pas reproduite,
donc son observation n est pas contredite, seulement pas testee.

En revanche, fermer EDF fait importer du reseau en rampe jusqu a 4113 W pour
charger la batterie, conso maison a 880 W. A la coupure le courant batterie
tombe de 104,6 a 25,7 A en 15 s. Les programmations ESS etaient deja
desactivees : le proprietaire de cet ordre reste a identifier.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-08-27 10:58:00 +02:00
Tallagrand Thierry
13e35cdbba ESS : desactivation des charges reseau programmees du GX
Trois fenetres actives tous les jours (01:35 et 07:30 vers 45 %, 12:24 vers
55 %) chargeaient la batterie sur le reseau des qu EDF etait present, en
concurrence avec la cible du matin de l EVCS. C etait un contournement manuel
du proprietaire, utile l hiver, inutile l ete. Les cinq sont desactivees : le
controleur EVCS est seul proprietaire de la decision reseau.

Consigne le besoin hivernal correspondant : en heure solaire l hiver ajoute
~2 h de nuit a couvrir, donc la cible du matin doit monter vers 80 % et se
deduire du croisement production/consommation, pas d un palier fixe.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-08-27 10:47:55 +02:00
Tallagrand Thierry
f18c6e07f6 Nuit : la recovery batterie est une passe unique, pas un oscillateur
La bande de 2 points du Fix A engageait le takeover a SOC 33 et le relachait
a 35 : 0,34 kWh, soit une demi-heure de conso nocturne plate. Trois cycles EDF
la nuit du 26-27/08, six la nuit du 20-21/08, 2,5 kWh importes pour rien.

Une seule passe de recovery par session de nuit. Le plancher dur reste un
terme independant, l hysteresis garde sa bande 20/30, et le vrai critere de
re-engagement (un budget d energie) appartient au bilan, pas a une constante
de plus ici.

Golden 40 -> 42, preuve par mutation. Documente aussi deux acteurs non lus :
les charges programmees de l ESS (45 % la nuit, contre notre cible 35 %) et
le regime majoritairement hors reseau.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-08-27 10:33:21 +02:00
Tallagrand Thierry
057e0f7d8f Corrige l'inversion plancher de demarrage / plancher de maintien (EVCS)
Incident du 24/08 12:24-12:28 : bascule de profil vers midday_hc_or_solar
avec SOC 58 %. Plancher de demarrage = min(midday_soc_min 75, abondance P6
40) = 40 ; plancher de maintien = max(soc_stop_min 29, 75-15) = 60. Le
systeme avait donc le droit de DEMARRER ce qu'il n'avait pas le droit de
MAINTENIR : cycle limite a la periode de min_run (3 min) sur toute la bande
[40 %, 60 %], et ~2,6 kW de PV ecretes a chaque creux (PV 10,24 kW -> 7,64 kW
quand la borne s'arrete, ESS sans injection).

Deux volets indissociables dans BATTERY_CLOUD_LOCKS.js :
- effectiveSocHoldFloor = min(regle du profil, plancher de demarrage
  effectif). Sans abondance, comportement inchange.
- l'abondance P6 se prouve au demarrage (batterie >= +20 A) mais se maintient
  en charge (batterie >= 0) : sinon la charge du vehicule, qui detourne
  precisement le surplus, detruit sa propre condition d'autorisation.

Golden 39 -> 40. Preuve par mutation sur midday-inversion-start-hold : code
d'avant -> stop / "Conditions de maintien perdues", apres -> step_up 19 A.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-08-24 12:46:18 +02:00
Tallagrand Thierry
522f47e821 Retrait de Fix G + garde-fous anti-yoyo + diagnostic des deux oscillateurs
Fix G provoquait un yoyo EDF de 2-4 min (coupure a SOC 21 en bypass min_on
contre rallumage a SOC 20 en bypass cooldown) : son garde `soc > gridSocOn`
ne protegeait que l'instant de l'engagement sur SOC bas, pas la phase de
remontee 20 -> 30. jsCode restaure byte-identique a la version pre-Fix-G.

Le fixture de test portait les fallbacks du code (22/35) au lieu des valeurs
de production lues via MCP (20/30), et le scenario de non-regression testait
SOC 18 %, le seul point que Fix G epargnait. Suite reecrite avec les
garde-fous manquants h-recovery-band-no-cut-21/-25. Mutation : Fix G
reapplique -> 4/7 echecs, retire -> 7/7.

Documentation du diagnostic des deux oscillateurs (yoyo EDF et oscillation
de la charge EVCS en plein soleil) dans MANUEL_COMPLET 11.8 et HANDOFF 25.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-08-24 12:20:12 +02:00
Tallagrand Thierry
e68fa160b6 Fix G: coupure EDF générique quand l'override EVCS disparaît mi-session
Incident nuit 21-22/08 : la fenêtre HC nuit se ferme pendant que le véhicule
est encore en session active (pas encore flag "charge terminée"). L'EVCS
relâche correctement son override, mais émet un état transitoire générique
(stop_source_lost/idle_wait_source) qu'aucune règle de coupure immédiate du
workflow Grid Hysteresis (Fix C/E2) ne reconnaît. EDF restait alors maintenu
des heures par la boucle générique jusqu'au seuil statique gridSocOff,
plafonnant le MPPT Victron à ~100W et privant la maison de solaire.

Nouvelle règle générique (Compute Grid Hysteresis) basée sur evcsGridOverride
plutôt que sur une liste blanche de noms de surplus_state — couvre donc aussi
tout futur état non énuméré. Garde anti-glitch sur lecture HA invalide.
Nouvelle suite tests/golden-hysteresis/ (7 scénarios, première pour ce
workflow), câblée bloquante dans tools/n8n-push.mjs. Déployé et validé
(golden-hysteresis 7/7, golden EVCS 39/39 inchangé).

Écarte le diagnostic incomplet laissé par un autre agent dans HANDOFF.md
(edf_general_ok_off côté EVCS aurait créé un deuxième écrivain non coordonné
sur le même switch).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-22 19:56:06 +02:00
Tallagrand Thierry
5bc9784583 P11: reset du collant 'plein' au changement de véhicule (charging_time)
- incident 12/08: JEEP chargée -> débranchée -> VW branchée bloquée par le
  collant night_recovery_done_idle de la JEEP
- snapshot +evcs_charging_time, INPUT_PARSE parseChargingTimeToSec
- WINDOWS: sessionFresh (<=90s) neutralise vehicleChargeCompleted/
  dayVehicleFullIdle/departureChargeDone/evcsStatusCharged
- golden 36->39, validé live 05:00:30 (VW débloquée: recovery_done -> wait_grid_takeover)
- HANDOFF §23 + MANUEL reset collant
2026-08-12 05:01:26 +02:00
Tallagrand Thierry
819eafd4d4 P10: mémoire 'véhicule plein' en journée (collant jusqu'au débranchement)
- WINDOWS: dayVehicleFullIdle (statut 3 ou VDF, héritages jour<->nuit),
  sourceMode blocked même face au solaire
- DECISION: branche collante day_vehicle_full_idle au-dessus des gardes
- échappatoires force_charge_now/force_grid_now (golden)
- golden 33->36, validé live 10:04:30 (latch en 16 s sur la VW pleine)
- HANDOFF §22 + MANUEL états collants
2026-08-09 10:06:25 +02:00
Tallagrand Thierry
0419c741de P9: charge réseau avant départ (hors HC) + sélecteur véhicule VW/JEEP
- helpers: input_select.victron_evcs_vehicle, departure_time_jeep (06:30),
  toggle allow_grid_departure_urgent (OFF) — package victron_evcs_vehicles.yaml
- INPUT_PARSE: departureTimeMin par véhicule sélectionné
- WINDOWS: fenêtre départ ≤120min hors HC → grid_hc_allowed (solar_only prioritaire),
  état collant departure_done_idle à la fin de charge
- BCL: gridAllowedBySoc += departureUrgentActive
- DECISION: branche collante departure_done_idle au-dessus des gardes
- HA_SERVICE_CALLS: takeover helper tenu pendant P9 (ACM + hystérésis)
- hystérésis: cut immédiat étendu à departure_done_idle (patch rejouable)
- golden 29→33, HANDOFF §21
2026-08-09 08:27:24 +02:00
Tallagrand Thierry
98c9202bad Advisor: premier câblage réel — cible SOC matin (toggle, bornes, fraîcheur 120min)
- nouveau toggle input_boolean.evcs_advisor_apply_night_target (package + carte, OFF par défaut)
- snapshot/INPUT_PARSE: advisor_apply/target/status/last_run (+parseAdvisorRunToMs DD/MM HH:mm)
- WINDOWS: batteryMorningTargetPct = advisor si ON+ok+frais, clamp [max(22,hardFloor),90],
  sinon règles forecast; traçabilité '(ADVISOR)' dans la reason DECISION
- golden 26→29 (appliqué / stale / toggle off)
- HANDOFF §20 (surveillance + rollback 3 niveaux)
2026-08-09 07:32:46 +02:00
Tallagrand Thierry
6ca6ea99de Fix F: mémoire 'charge terminée' prioritaire sur les gardes (rebond rebranchement 09/08)
- DECISION: branche done/recovery_done remontée dans la cascade principale
  (avant mustStopHard) → le collant se réécrit chaque cycle, survit aux
  micro-charges de la VW et aux hard stops batterie
- branche Fix E interne supprimée (remplacée par la branche haute)
- golden 25→26 (night-hard-stop-necrase-pas-done)
- HANDOFF §19
2026-08-09 07:03:19 +02:00
Tallagrand Thierry
b287e5ba73 Fix E: latch 'charge terminée' en session active + coupure recovery_done (incident rebond 08-09/08)
- DECISION: branche completed prioritaire dans la session active (avant VDF/source-lost)
  → état collant écrit au 1er cycle status=3, relais encore fermé
- WINDOWS: garde puissance <=300W sur Fix D (anti-glitch)
- Hystérésis: turn_off_recovery_done (bypass min_on, dry-run 5 cas)
- golden 23→25 (session armée status 3, flap statut post-latch)
- HANDOFF §18
2026-08-09 06:31:33 +02:00
Tallagrand Thierry
9bc4af0ea1 Fixes A/B/C/D incident rebond EDF nuit 07-08/08 + GRAFCET doc
- A: état collant night_recovery_done_idle + bande cible−2 (anti-rebond takeover)
- B: snapshot relit night_session_start_soc/at (fin des réécritures 30s)
- C: hystérésis grid — turn_off_vehicle_unplugged (coupure immédiate, bypass min_on)
- D: evcs_status_raw==3 (charged) = fin de charge immédiate
- golden 19→23 scénarios (2 attendus mis à jour, 4 nouveaux)
- MANUEL_COMPLET §11.6 GRAFCET cycle nuit, HANDOFF §17, vision-notes incident
2026-08-08 14:20:21 +02:00
Tallagrand Thierry
b20b3b19fc HANDOFF: analyse LLM advisor (qwen3-vl sous-optimal, option routage intelligent prête, statu quo surveillé) 2026-08-08 00:56:15 +02:00
Tallagrand Thierry
63d56bf284 Agent IA planificateur EVCS en MODE OMBRE (Advisor Shadow V1)
- Workflow n8n tdfInZns7cqo8fU2 actif (15 min): snapshot HA compact -> prompt FR
  -> LLM local Spark (modèle dynamique via /v1/models) avec fallback OpenRouter
  claude-haiku-4.5 (credential chiffré, clé hors git) -> validation stricte
  (enums, bornes, rejet total si invalide) -> helpers advisor_* + divergence
  + compteurs accord/divergence + logbook.
- GARANTIE OMBRE structurelle: écritures limitées à advisor_*/logbook,
  vérifiée par tests/advisor/run.mjs (16 tests, bloquants au push).
- Kill-switch input_boolean.evcs_advisor_enabled.
- Extension R2 multi-workflows (lib-node-map WORKFLOWS[], build/extract/push
  par fichier, n8n-create.mjs, gen-advisor-workflow.mjs).
- Helpers HA via package NFS + carte dashboard EVCS Master (backup fait).
- 1re reco réelle: auto_solar_plus, cible 35%, accord avec le réel.
- Fix sécurité n8n-push: plus de fallback d'id implicite vers le workflow EVCS.
2026-08-07 22:42:06 +02:00
Tallagrand Thierry
1ae8129658 R2: git = source de vérité — src/nodes/ + build/extract intégrés au push
- src/nodes/*.js (6 nodes + template snapshot) = source de vérité unique.
- n8n-push.mjs reconstruit le JSON depuis src/ avant syntaxe+golden+PUT
  (src gagne toujours; n8n-extract.mjs pour resynchroniser si édition UI).
- n8n-build.mjs --check pour vérifier la synchro.
- Copies historiques déplacées dans archive/ (mortes, dérivées de la prod).
- .gitignore: backups locaux de rollback.
- AGENTS.md: règle R2 pour toutes les futures sessions (dont Qwen local).
- Validé: idempotence, mutation/restauration, pipeline push complet en réel.
2026-08-07 21:03:52 +02:00
Tallagrand Thierry
b10c90c74f P8: libération EDF quand véhicule plein (nuit HC) + fix latch inversé du 04/08
- vehicleChargeCompleted COLLANT via prev_surplus_state (nouveau champ snapshot):
  vehicle_full_or_paused -> night_session_done_idle auto-entretenu jusqu'au
  débranchement ou fin de fenêtre.
- Fix inversion 04/08: le latch takeover se libère à la fin de charge
  (était: || vehicleChargeCompleted qui le GARDAIT).
- P7 relâché quand charge finie; sourceMode nuit -> blocked (zéro retry).
- SOC > cible: takeover OFF -> hystérésis coupe EDF. SOC <= cible: takeover ON
  -> EDF maintenu + ACM recharge batterie (spec 'sauf si sous seuil').
- night_session_done_idle ne matche aucun pattern no-demand de l'hystérésis
  (condition de fonctionnement de l'override batterie basse).
- Golden: 19/19 (3 nouveaux scénarios P8, 16 existants inchangés).
2026-08-07 19:40:30 +02:00