Commit Graph

139 Commits

Author SHA1 Message Date
Tallagrand Thierry
ed9e72c23b La source exacte l'emporte, et les noms provisoires disparaissent
Un module extrait par --historique-distant porte des horodatages lus
au chronometre ; ses vieux exports texte reposent sur une deduction.
Importer les deux pour le meme module poserait deux series decalees de
plusieurs heures, illisibles. L'importeur ecarte donc le texte des
qu'un releve exact existe pour ce code-barres.

--remplacer efface aussi les lignes rangees sous un nom provisoire du
type pack_ancien:2, sans quoi le module nomme et son fantome
coexisteraient dans les listes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-09-05 16:28:16 +02:00
Tallagrand Thierry
8d076603de Un temoin sain, et l'historique de toute une chaine par un seul branchement
datalist reste local, mais data <adresse> history <n> est adressable
et rend l'enregistrement complet, quinze cellules comprises. Les trois
modules de la chaine ancienne sont donc extraits d'un seul
branchement, tous corriges du meme decalage lu au chronometre : 369
minutes. Les jeux sont enfin comparables entre eux, ce que les
decalages deduits - divergents de deux heures et demie - ne
permettaient pas.

Le module d'adresse 2 donne le temoin qui manquait : meme chaine,
memes courants, memes journees, et ses quinze cellules tiennent dans
onze millivolts d'amplitude les unes des autres, ecart median 6 mV.
Ce qui a tue les autres ne vient donc ni du regime de charge, ni du
pilotage, ni de l'installation.

Sur cette base commune la cellule 14 du module ...0322 passe a 273 mV
et rejoint les atteintes : dix cellules, pas neuf.

L'horloge se propage bien du maitre a sa chaine - j'avais conclu
l'inverse en verifiant une seconde apres l'ecriture, il en faut vingt.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-09-05 16:20:58 +02:00
Tallagrand Thierry
8cf25114f8 Le huitieme code-barres, et une garde sur la carte des adresses
K220803C30160323 complete l'inventaire : les huit modules sont nommes.
La carte adresse -> code-barres ne vaut que pour la chaine du pack
ancien, le pack recent renumerotant lui aussi de 1 a 4 ; l'appliquer
a l'autre chaine attribuerait ses relevés aux mauvais modules.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-09-05 15:29:11 +02:00
Tallagrand Thierry
41b67981da Le decalage d'horloge etait fausse de deux heures par mon propre parseur
Le module ecrit une heure de mur LOCALE. Je l'interpretais comme de
l'UTC, ce qui ajoutait exactement le decalage de Paris a chaque
decalage deduit : d'ou les +7 h 27 et +9 h 59 qui semblaient absurdes
et qui, corriges, tombent sur les valeurs mesurees au chronometre.

La deduction redevient donc fiable, et chaque export voit desormais
son dernier enregistrement atterrir sur l'heure de l'export lui-meme.
Les valeurs mesurees restent en commentaire pour controler la
deduction, pas pour la remplacer.

--remplacer efface les lignes du module avant de reinserer : corriger
un decalage AJOUTAIT sinon une seconde copie decalee, la cle primaire
portant l'instant.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-09-05 15:20:58 +02:00
Tallagrand Thierry
20b21dd46d Un rapport vivant sur l'etat du parc batterie
Genere par script pour que les mesures restent en tete du fichier et
la mise en page en dessous : mettre a jour une valeur, relancer,
republier.

La figure centrale trace l'amplitude balayee par chaque cellule. C'est
la grandeur qui separe une cellule saine d'une cellule morte sans
demonter quoi que ce soit : une cellule ayant perdu sa capacite se
remplit et se vide avant ses voisines, donc elle balaye une plage bien
plus large a courant identique.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-09-05 13:43:55 +02:00
Tallagrand Thierry
8e2b4f3e34 Un tableau Grafana pour les cellules, et le plafond du BMS enfin historise
Le GX n'expose que l'agregat du parc : les quinze tensions d'un module
ne sortent que par la console de son BMS. Le tableau les trace, avec
les paliers d'alarme du materiel lui-meme - 3480, 3520, 3550, 3600 mV
- et met la cellule meneuse en regard du plafond de charge.

Le plafond impose par le BMS, grandeur centrale de tout ce diagnostic,
n'etait pas historise : il l'est desormais, comme l'alarme de tension
de cellule. Ils manquaient tous les deux a la memoire.

Les quatre requetes cellule echouent tant que la table n'existe pas ;
elles passeront apres redemarrage du service et import.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-09-05 13:41:28 +02:00
Tallagrand Thierry
f762616893 Les tensions de cellule entrent dans la base, avec leur decalage d'horloge
Nouvelle table cellule, indexee par CODE-BARRES et non par adresse :
chaque chaine renumerote ses modules a partir de 1, il existe donc
deux « module 1 » dans ce parc.

L'importeur lit les exports d'historique et les CSV de suivi. Deux
pieges corriges en le construisant : le tampon du BMS est circulaire,
donc le plus grand index n'est pas le plus recent - trier par index
donnait un decalage deduit de -865 h ; et les fichiers d'evenements
portent les memes colonnes sans decrire un echantillonnage regulier,
ils sont ecartes.

La deduction du decalage d'horloge reste approximative : sur BAT3 elle
donne huit heures la ou le chronometre en donne six. La console
inscrit desormais le decalage en tete de chaque export, mesure a la
seconde ou il commence ; l'importeur le prefere toujours a sa propre
deduction.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-09-05 13:39:17 +02:00
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
5ed85a5550 Suivi en direct de plusieurs modules d'une chaine pendant l'alarme
--modules 1,2,3 interroge chaque adresse avec soh, qui donne les quinze
tensions et le compteur de sante par cellule. Sans cet argument on ne
lisait que le module portant le cable, alors que l'adressage a distance
permet de couvrir toute la chaine.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-09-05 13:01:51 +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
e4288a221e Le LVHUB ne fait que redemarrer, son journal ne contient rien d'autre
Le cable pose sur le hub revele un LVHUB en SysError 0xe000 : courants
de charge et de decharge autorises a zero, tension de coupure basse a
396,8 V, table des unites remplie de valeurs de remplissage, horloge
jamais sortie de 2000-01-01, et un journal de dix-neuf entrees qui ne
contient que « System is restarting » et « System Reset ».

Le parc, lui, fonctionne : SOC 70 %, charge a 23 A, aucune alarme. Le
GX ne lit donc pas le hub - il lirait zero ampere autorise et rien ne
chargerait.

Gain annexe : sysinfo donne l'echelle d'alarme reelle du materiel,
3480 / 3520 / 3550 / 3600 mV en haut et 3100 / 2900 en bas. Le seuil
de 3550 utilise dans l'analyse etait le bon, mais par chance ; il est
desormais reference.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-09-05 12:18:35 +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
9bd087aa0e Ou vit BatteryView, et pourquoi "help" n'y est pas
La machine Windows 10.10.10.93 porte le cable console et fait tourner
BatteryView. Elle ne repond qu'en SMB : il n'y a rien a interroger a
distance, l'application gardant le port COM pour elle seule.

"help" est une commande de la console serie du BMS, pas une fonction de
BatteryView. Il faut fermer BatteryView pour y acceder, le port etant
exclusif.

Dossier de depot des exports cree, avec la fenetre de capture utile :
a SOC eleve, en pleine charge. En dessous de ~70 % les cellules d'un
LiFePO4 lisent la meme tension et un releve ne peut rien montrer.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-09-05 10:56:52 +02:00
Tallagrand Thierry
27b2004622 L'energie de la session dans le panneau Chargeur VE
Quatrieme valeur : « Session », le compteur de la BORNE, celui qui vaut les
8 kWh de VRM et compte depuis le vrai debut de la charge.

Il vient de PostgreSQL et non d'InfluxDB : `sensor.evcs_hq2239dnt7p_*` n'est
pas dans les globs d'entites envoyees a InfluxDB. Plutot que de redemarrer Home
Assistant pour l'y ajouter — en pleine charge, a 4 h du matin — la valeur est
reprise de la table `session_charge`, ou elle est deja enregistree. Le panneau
passe donc en source « Mixed », chaque requete portant la sienne.

La session n'est affichee que si elle date de moins de deux heures : au-dela,
la case reste vide plutot que d'exhiber le reliquat d'une charge terminee la
veille — meme principe que la fenetre de lecture des autres panneaux.

La premiere rangee passe a sept unites de hauteur et la Batterie a neuf
colonnes : quatre et cinq valeurs cote a cote redevenaient illisibles a cinq
unites, c'est le defaut deja corrige une fois sur ce meme panneau.

54/54 requetes verifiees. Valeur attendue a l'ecran : 8,30 kWh.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-09-05 03:32:46 +02:00
Tallagrand Thierry
9748325356 Le compteur de la borne fait foi, pas mon integration
Le tableau annoncait 750 Wh la ou VRM affichait 8 kWh. Ce n'etait pas une
erreur de mesure mais une erreur de SOURCE : j'integrais la puissance depuis le
moment ou mon detecteur avait commence a fonctionner — 03:16 — pour une session
ouverte a 01:25.

Or la borne tient son propre compteur de session,
`sensor.evcs_hq2239dnt7p_last_session_energy`, qui vaut exactement les 8,0 kWh
de VRM et compte depuis le vrai debut. Nouvelle colonne
`energie_station_kwh` : c'est elle qui alimente desormais les totaux et le
graphique.

Mon integration est conservee en colonne « kWh integres » : l'ecart entre les
deux signale un demarrage ou un redemarrage du service en cours de session, ce
qui est une information en soi. Et elle sert de secours si la borne ne publie
rien.

Cherche au passage, sans succes : VRM affiche « Vehicule : Guest EV » mais
AUCUNE entite ne porte ce champ cote Home Assistant. « Guest EV » signifie
d'ailleurs vehicule NON identifie — Victron ne sait pas non plus qui est
branche.

50/53 : les trois requetes en echec portent sur la nouvelle colonne, que la
migration creera au prochain demarrage du service.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-09-05 03:29:09 +02:00
Tallagrand Thierry
14e04a428a La fenetre de lecture depend du comportement de l'entite au repos
« No data » sur le panneau Chargeur PV a 03:20 : la production avait ete ecrite
pour la derniere fois au coucher du soleil, 370 minutes plus tot, et ma fenetre
etait de 6 h. La valeur zero etait pourtant exacte et connue.

C'est la seconde erreur sur ce meme reglage, en sens inverse de la premiere :
- trop LARGE partout (7 jours), le panneau Reseau affichait un courant vieux de
  quatorze heures, parce que ces capteurs passent en `unavailable` quand AC-IN
  s'ouvre au lieu de tomber a zero ;
- trop ETROITE partout (6 heures), les entites qui publient un vrai zero au
  repos disparaissent de l'ecran alors que leur derniere valeur reste juste.

Il n'y a donc pas de bonne valeur unique. Regle inscrite dans le generateur :
fenetre LARGE (24 h) pour ce qui publie un vrai zero — production PV, borne a
l'arret, trackers ; fenetre COURTE (6 h) pour ce qui disparait, c'est-a-dire
les seules grandeurs du reseau.

Consigne au passage dans le manuel : le proprietaire possede une troisieme
monture, une moto electrique Zero Motorcycles SR/F, a ajouter au selecteur fin
septembre. Avec la remarque qui compte : sa batterie et son chargeur embarque
etant bien plus petits, elle sera peut-etre le premier vehicule du foyer
electriquement distinguable des deux autres.

53/53 requetes verifiees.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-09-05 03:23:07 +02:00
Tallagrand Thierry
0681bf5af4 Lire les journaux avec --since, jamais --tail
Le service ne journalise que lorsqu'il a ecrit quelque chose. `--tail=5`
affiche donc les cinq dernieres lignes quelles qu'elles soient, y compris des
erreurs anterieures au redemarrage : le proprietaire a relance la commande
quatre fois devant un ecran fige montrant des erreurs deja corrigees, alors que
le service tournait normalement.

`--since 2m` borne le temps et non le nombre de lignes. Ajout aussi de la
verification qui ne ment pas, parce qu'elle regarde le resultat et non le
journal : la fraicheur et l'energie accumulee de la derniere session.

Etat verifie a l'instant : derniere mise a jour il y a 19 s, 0,345 kWh
accumules sur la session JEEP en cours, 18 mesures sur les trois dernieres
minutes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-09-05 03:17:43 +02:00
Tallagrand Thierry
22927a2930 Transtypage des parametres : aucun UPDATE de session n'aboutissait
`operator is not unique: unknown * unknown`. node-postgres envoie ses
parametres SANS type ; multiplier deux d'entre eux ne permet pas a PostgreSQL
de choisir un operateur.

Et contrairement a ce que j'ai d'abord annonce, ce n'est pas l'ajout de la part
reseau qui a casse la ligne : les DEUX lignes en souffraient. La premiere
version du detecteur de session n'a jamais reussi un seul UPDATE — la session
enregistree a 02:56 affichait 0,000 kWh avec fin = debut, seul l'INSERT avait
abouti. Verifie en rejouant les trois formes contre la vraie base : l'ancienne
echoue, la nouvelle passe.

Lecon consignee dans le README : l'essai a blanc remplace l'envoi a la base par
un compteur, donc il valide la logique et JAMAIS le SQL. Une erreur de typage y
est invisible par construction. D'ou la regle — tout parametre entrant dans un
calcul porte son ::float8 — et l'obligation de lire le journal du conteneur
apres chaque deploiement du service.

Tableaux : 53/53 depuis que la colonne existe.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-09-05 03:15:15 +02:00
Tallagrand Thierry
c00a2107b3 Tableau « Les vehicules » : ce que chaque voiture encaisse, par periode
Demande du proprietaire : voir ce que la JEEP ou la VW encaisse dans une
session, et evaluer sur une periode (jour, semaine, mois), en assumant
l'imprecision liee a l'impossibilite d'identifier le vehicule au branchement.

Trois panneaux : les totaux par vehicule sur la periode, l'energie par periode
et par vehicule avec le meme pas adaptatif que les autres tableaux (heure /
jour / mois), et la liste des sessions.

L'incertitude est AFFICHEE plutot que masquee :
- un compteur « Etiquette douteuse » — sessions ou le selecteur a change en
  cours de route, ou n'etait pas renseigne ;
- une colonne « Doute » dans le tableau ;
- une serie « Non etiquete » dans le graphique ;
- l'heure de debranchement, qui confirme apres coup puisque les deux vehicules
  partent a des heures differentes.

Le commentaire du generateur consigne pourquoi aucune verification n'est
possible : electriquement les deux voitures sont indiscernables (3 680 contre
3 655 W a consigne identique de 20 A), et horairement la routine s'inverse le
week-end, donc une regle horaire serait fausse un week-end sur deux.

Ajout a la table : `energie_reseau_kwh`, la part venue du reseau, fondee sur le
`source_mode` du controleur — son intention — et non sur la puissance reseau
instantanee, laquelle peut alimenter la maison pendant que le soleil alimente
la voiture.

52/53 requetes verifiees. La seule en echec porte sur cette nouvelle colonne,
que la migration creera au prochain demarrage du service.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-09-05 03:04:06 +02:00
Tallagrand Thierry
e80dbf70fb Table des sessions de charge : etiqueter pendant, pas deviner apres
L'etiquette du vehicule n'existe QUE pendant la session.
`input_select.victron_evcs_vehicle` est un reglage manuel, il change, et rien
ne conservait sa valeur au moment ou la charge avait lieu — une session d'il y
a trois semaines etait anonyme pour toujours, et toute analyse d'usage
impossible.

Nouvelle table `session_charge` : debut, fin, vehicule tel que le selecteur
l'indiquait PENDANT la session, un drapeau disant s'il a change en cours de
route, energie accumulee, puissance et courant maximum, mode source, et
l'heure de debranchement — qui confirme apres coup, les deux vehicules partant
a des heures differentes.

Le service applique lui-meme la migration au demarrage : `schema.sql` n'est
joue qu'a la creation de la base, une table ajoutee plus tard n'y arriverait
jamais. `CREATE TABLE IF NOT EXISTS` rend l'operation rejouable.

On ne DEVINE rien, et le commentaire du schema dit pourquoi :
- electriquement, la VW accepte 3 680 W et la JEEP 3 655 W a consigne
  identique de 20 A — 0,1 A d'ecart, indiscernables ;
- horairement, la routine s'inverse le week-end (la femme du proprietaire
  travaille samedi et dimanche matin), donc « midi = JEEP, nuit = VW » serait
  faux un week-end sur deux.

Essai a blanc : la session en cours serait correctement inscrite (JEEP,
3396 W, Reseau force, profil night_hc).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-09-05 02:54:05 +02:00
Tallagrand Thierry
0cc547e71c Les deux vehicules sont electriquement indiscernables
Recherche d'un signal permettant d'identifier automatiquement le vehicule
branche, a la demande du proprietaire. Resultat NEGATIF, et il merite d'etre
consigne pour qu'on ne le recherche pas deux fois.

Mesure sur deux sessions a consigne identique de 20 A, etiquetees par le
proprietaire : la VW accepte 3 680 W, la JEEP 3 655 W. Vingt-cinq watts
d'ecart, 0,1 A. Les deux embarquent un chargeur de 3,7 kW et saturent au meme
endroit. Ni la puissance de plateau ni le taux d'acceptation de la consigne ne
les separent.

La piste de la latence de demarrage est inexploitable : la table `decision` ne
commence qu'a 01:37 le 04/09, donc l'ordre de demarrage de la session VW de
cette nuit-la n'a pas ete enregistre et les 761 s calcules sont un artefact.

Ce qui EST un signal, et c'est le proprietaire qui l'apporte : la routine du
foyer. La JEEP charge le midi en semaine (sa femme rentre dejeuner), la VW le
soir et la nuit (son fils part a 9 h). Forte presomption, pas certitude — cette
nuit meme, un samedi, c'est la JEEP qui charge.

Consigne dans MANUEL_COMPLET §0, avec le rappel que le selecteur manuel reste
le seul etiquetage fiable et qu'un redemarrage de Home Assistant peut l'annuler.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-09-05 02:46:41 +02:00
Tallagrand Thierry
53d30afcd3 Le panneau BMS affichait sa colonne d'horodatage
Effet de bord du correctif precedent : pour montrer les alarmes, qui sont du
texte, j'avais mis « fields: /.*/ » — ce qui fait aussi remonter la colonne
_time des requetes Flux, affichee en gros au-dessus de chaque valeur.

Un panneau stat n'a besoin d'aucun champ temporel. Les requetes ne renvoient
plus que la valeur. Applique a tous les panneaux stat, pas seulement au BMS :
_time n'y servait a rien et restait un piege latent, invisible tant que le
reglage « champs numeriques seulement » le masquait.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-09-05 02:32:26 +02:00
Tallagrand Thierry
0812431b5b Les flux : format table, pour que le filtre de vue s'applique
Le filtre de vue fonctionne sur le graphique en barres — la capture du
proprietaire montrait bien « Solaire, Voiture » seuls — et echouait sur « Les
flux » avec « Data is missing a time field ». La seule difference entre les
deux etait le format de sortie : `table` d'un cote, `time_series` de l'autre.

Un panneau time series accepte parfaitement une trame de type table des lors
qu'elle porte une colonne temporelle, et le rendu est identique. On aligne donc
« Les flux » sur le format dont on a la PREUVE qu'il se laisse filtrer, plutot
que de continuer a deviner comment `time_series` nomme son champ temporel.

Changement circonscrit a ce seul panneau : les trois autres tableaux utilisent
le meme generateur de requete, n'ont pas de filtre de vue, et restent en
time_series.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-09-05 02:30:19 +02:00
Tallagrand Thierry
c7006a030c Deux defauts introduits avec les vues
1. « Data is missing a time field » sur Les flux. Mon filtre de vue laissait
   passer « time » en minuscules, or la source PostgreSQL nomme le champ
   temporel « Time » avec une majuscule dans le format time_series. Le filtre
   supprimait donc l'axe des temps. Les deux graphies sont desormais acceptees.

2. Les deux alarmes du panneau BMS n'apparaissaient pas. Un panneau stat ne
   reduit que les champs NUMERIQUES par defaut, et « no_alarm » est du texte :
   il faut "/.*/" pour l'afficher. Applique a ce seul panneau — les autres
   n'ont que des nombres et le reglage par defaut y est correct.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-09-05 02:26:39 +02:00
Tallagrand Thierry
2a367d0960 Vues et periodes comme VRM, et un panneau Batterie enfin lisible
Trois demandes du proprietaire apres usage reel.

1. SELECTEUR DE VUE. Variable « vue » en haut du tableau, dans l'esprit de VRM :
   Vue generale / Consommation / Reseau / Batterie / Chargeur VE. La valeur de
   chaque option est directement une alternative d'expression reguliere,
   consommee par la transformation filterFieldsByName des deux graphiques —
   d'ou le separateur « | ». Un seul jeu de requetes, cinq lectures.

2. PAS ADAPTATIF. L'histogramme d'energie suit desormais la periode choisie :
   l'heure jusqu'a 4 jours, le jour jusqu'a 70, le mois au-dela. Sans cela
   « 30 derniers jours » rendait 720 barres illisibles. C'est ce que fait VRM
   en passant de l'heure au jour puis au mois.

3. PANNEAU BATTERIE ILLISIBLE — un defaut que j'avais cree. Cinq valeurs dans
   huit colonnes : Grafana reduisait le texte jusqu'a l'illisible. Porte a dix
   colonnes avec une taille imposee, plutot que de laisser l'ajustement
   automatique decider. Reseau et Charges CA resserres en consequence.

Ajout lie a la panne en cours : panneau « Ce que le BMS impose » — limite de
courant de charge, alarme de tension de cellule, desequilibre, etat de sante.
C'est ce qu'il faudra regarder cet apres-midi.

Sa fenetre de lecture est de 48 h, deliberement differente des 6 h du reste :
un etat d'alarme ne devient jamais indisponible, il se publie, donc sa derniere
valeur EST la valeur courante meme vieille de dix heures. A l'inverse du
courant reseau, dont le capteur disparait et laisse un chiffre qui ment.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-09-05 02:17:21 +02:00
Tallagrand Thierry
38ed843536 Le tableau du systeme : fenetre glissante, et plus de valeur perimee
Trois defauts signales par le proprietaire sur une capture prise a 00:04.

1. FENETRE GLISSANTE. La plage etait « aujourd'hui » : a 00:04 il n'y avait que
   quatre minutes a montrer. Passee a 24 h glissantes. Les etiquettes d'heure
   portent desormais le jour, sans quoi « 22 h » designerait deux heures
   differentes dans la meme fenetre.

2. VALEUR PERIMEE PRESENTEE COMME ACTUELLE — le vrai defaut. Le panneau Reseau
   affichait « Courant 2,2 A » : ecrit QUATORZE HEURES plus tot, du temps ou le
   contacteur etait ferme, alors qu'il est ouvert depuis 10:08. Cause : ma
   fenetre de lecture de 7 jours, posee pour eviter les cases vides.

   Les capteurs du reseau passent en `unavailable` quand AC-IN disparait ; ils
   ne tombent pas a zero. Leur derniere valeur numerique reste donc celle
   d'avant. Fenetre ramenee a 6 h : assez large pour couvrir une nuit sans
   soleil et une borne au repos — dont les zeros sont VRAIS — assez etroite
   pour ecarter une lecture de quatorze heures.

3. Une absence de mesure s'affiche desormais comme un tiret, jamais comme zero.

Verifie apres coup sur les valeurs reelles : Reseau Courant = tiret (la valeur
fausse a disparu), Chargeur PV = 0 W et Chargeur VE = 0 A conserves puisque
justes, Batterie et Charges CA en direct.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-09-05 01:05:22 +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
7c2813a60a Page de decision : dimensionnement du parc batterie
Generateur rejouable (tools/gen-page-batteries.py) plutot qu'un HTML ecrit a la
main : les chiffres viennent des mesures et se recalculent.

Base : 37 nuits completes issues des statistiques long terme de Home Assistant
(fin juillet au 4 septembre, maison seule, voiture deduite) et la courbe
energie/SOC etablie sur 576 paliers.

Le chiffre qui cadre la decision : les 7 modules actifs delivrent 10,7 kWh a la
maison, la nuit mediane en demande 13,2 — la batterie passe la nuit seule
1 fois sur 37. Reparer le module en panne porte cela a 5/37 seulement ; deux
modules de plus le portent a 32/37. Reparer seul ne resout rien.

Second point, moins attendu : au-dela de la consommation nocturne le stockage
ne cycle plus. Le surplus de milieu de journee est un probleme de preneur, pas
de stockage — la voiture absorbe deja 9,8 kWh/jour en mediane.

Reserve inscrite en clair : toutes les mesures sont d'ete, les compteurs
exploitables ne remontant qu'a fin juillet.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-09-04 20:15:44 +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
f6f235b0f4 InfluxDB : la connexion quitte le YAML, Home Assistant l'a deja importee
Home Assistant 2026.8 avertit que la configuration YAML de la CONNEXION
InfluxDB est depreciee et cessera de fonctionner en 2026.9.0. Il a deja importe
l'existant dans une entree d'integration (source: import, titre
"evcs (http://10.10.10.22:8086)") : l'historisation continue de fonctionner,
seule la duplication reste a retirer.

Le fichier de reference du depot ne porte donc plus api_version, ssl, host,
port, token, organization ni bucket. include / exclude / tags restent en YAML :
c'est le perimetre des entites historisees, non concerne par la depreciation.

Le jeton vit desormais dans l'entree d'integration ; influxdb_token reste dans
secrets.yaml comme copie de reference et ne doit pas etre supprime.

Rien n'est modifie sur l'installation : le retrait des sept lignes de
configuration.yaml demande un redemarrage de Home Assistant, a faire hors des
fenetres qui comptent.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-09-04 19:39:54 +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
ea9248e949 Un quatrieme tableau, pour le telephone
L'application Grafana de l'App Store ne parle qu'a Grafana Cloud ; une instance
auto-hebergee se consulte au navigateur, epingle sur l'ecran d'accueil. Reste
que les trois tableaux existants sont dessines pour un ecran large.

Contrainte de conception, verifiee et notee dans le README : sous ~770 px,
Grafana passe CHAQUE panneau en pleine largeur et les empile. Le nombre de
panneaux devient le nombre d'ecrans a faire defiler. D'ou six panneaux
seulement, et les chiffres regroupes dans deux panneaux "stat" — plusieurs
valeurs dans un meme panneau restent cote a cote, la ou six panneaux separes
auraient fait six ecrans.

La reponse d'abord : batterie, marge (ce qu'elle a moins ce qu'il lui faut),
excedent. Puis l'energie a couvrir et l'heure du relais solaire. Puis les deux
courbes qui expliquent ces chiffres, la frise du reseau, et les huit derniers
evenements.

26/26 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:02:28 +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
d001cbbf2a Faire taire deux erreurs de demarrage Grafana qui n'en sont pas
Grafana journalise au niveau ERREUR l'absence des dossiers de provisionnement
`plugins/` et `alerting/`, que ce deploiement n'utilise pas. Le service
demarre et fonctionne parfaitement, mais un journal qui crie au loup apprend a
etre ignore — et celui-la sera lu pour comprendre un incident.

Deux dossiers vides, avec un .gitkeep qui explique pourquoi ils existent
(git ne versionne pas les dossiers vides). Effet au prochain demarrage du
conteneur, rien d'urgent.

Deploiement verifie en reel : Grafana repond 200 sur http://10.10.10.22:3001,
database ok, provisionnement des tableaux termine sans erreur.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-09-04 08:25:40 +02:00
Tallagrand Thierry
d41b0a0eb0 Grafana ne doit pas etre otage de la sante de PostgreSQL
`condition: service_healthy` rendait le demarrage de Grafana dependant du
healthcheck de PostgreSQL (intervalle 1 min). Grafana n'a pourtant besoin
d'aucune base pour demarrer, seulement pour repondre a une requete : la
condition ajoutait un mode de panne sans contrepartie, et un outil de
diagnostic doit surtout etre disponible quand quelque chose va mal.
Ramene a un simple ordre de demarrage.

Procedure corrigee sur deux points constates au deploiement reel :
- `sudo` est obligatoire sur DSM (socket Docker inaccessible autrement) ;
- le `git pull` que j'avais indique n'a aucun sens : /volume2/projects cote
  Syno et /mnt/projects cote poste sont le meme dossier (export NFS depuis
  10.10.10.22), il n'existe qu'une seule copie du depot.

Configuration verifiee en la rejouant dans un conteneur local, volume nomme
compris : deux sources de donnees, trois tableaux dans le dossier EVCS,
database ok, aucune erreur de provisionnement.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-09-04 08:20:40 +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
931e07eca9 Le service d historisation consigne lui-meme les evenements qu il constate
Une courbe sans ses evenements ne s interprete pas. Le service voit passer les
etats toutes les minutes : autant qu il en tire les conclusions plutot que d
attendre que quelqu un y pense.

Douze etats DISCRETS suivis — contacteur EDF, session reseau de nuit, verrou
hysteresis, vehicule branche, strategie, vehicule selectionne, etat BatteryLife,
mode de l Auto Charge Manager, reseau necessaire, vigilance orage, production
bridee. Les grandeurs continues restent dans mesure et les decisions dans
decision : un evenement qui double une autre table est du bruit. Une lecture
unavailable n est pas une transition mais une absence de lecture, elle n est pas
consignee.

Le redemarrage de Home Assistant est detecte sans capteur d uptime, qui n existe
pas ici : au redemarrage HA restaure ses helpers et leur pose un last_changed
neuf. Le 04/09 a 07:28:49, 352 entites partageaient la seconde du redemarrage
dont 183 input_number. Le service prend donc le mode des last_changed des
input_number — aucune entite codee en dur, et l estimation se corrige d
elle-meme puisque entre deux redemarrages seuls les helpers reellement ecrits s
ecartent du mode. Sous dix helpers d accord, la signature est jugee trop faible
et rien n est affirme.

Un episode d indisponibilite de Home Assistant est journalise AU RETOUR avec sa
duree : au moment de la panne, la base n est peut-etre pas joignable non plus.

Au premier cycle l etat est enregistre SANS rien journaliser, sinon chaque
redemarrage du service produirait douze fausses transitions ; seul le demarrage
du service est consigne.

Verifie de bout en bout en conditions reelles et non seulement a blanc : essai a
blanc avec cycle court, bascule reelle du selecteur de vehicule puis
restauration. Amorcage sans fausse transition, cycle sans changement a zero
evenement, les deux bascules relevees, etat restaure.

Documente aussi le GRANT INSERT sur la seule table evenement pour le role d
analyse — insert seulement, ni update ni delete : on ajoute une annotation,
jamais on ne reecrit ni n efface les precedentes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-09-04 07:43:49 +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
a189ad958c Pont pour le jeton InfluxDB, et sudo dans la commande de controle
La commande de controle affichee par creer-role-lecture.sh manquait sudo :
elle echouait sur la socket Docker au lieu de tester le role, donc elle ne
controlait rien.

exporter-jeton-influx.sh recopie le jeton d ecriture InfluxDB du .env local
(droits 600, lisible du seul compte DSM) vers le .env a la racine du depot,
lisible depuis le poste de travail. Sans ce pont il faudrait afficher le jeton
pour le recopier a la main dans le secrets.yaml de Home Assistant, qui vit sur
une autre machine — exactement ce qu on cherche a ne plus faire. Rien n est
affiche.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-09-04 01:58:42 +02:00
Tallagrand Thierry
2e27e4dfdb Un role de lecture seule dont le mot de passe se genere et ne s affiche pas
Le proprietaire releve, a juste titre, que ma commande precedente lui demandait
de CHOISIR un mot de passe — trois messages apres lui avoir explique qu un
secret se genere et ne se choisit pas. Contradiction corrigee par un script.

creer-role-lecture.sh cree le role evcs_lecture en lecture seule, tire son mot
de passe avec openssl et le depose directement dans le .env a la racine du
depot, sans jamais l afficher : rien a recopier entre deux endroits, donc rien
a exposer dans une capture. Il est rejouable — si le role existe et que son mot
de passe est deja dans le fichier, il ne fait rien.

Deux raisons de ne pas analyser avec le compte evcs : une memoire dont tout
l interet est de ne pas etre reecrite ne se consulte pas avec un compte qui peut
ecrire, et un mot de passe range dans un fichier lisible par un autre compte ne
doit pas etre celui qui gouverne la base. Les privileges par defaut couvrent les
tables futures, et un REVOKE explicite ferme l ecriture par ceinture.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-09-04 01:54:39 +02:00
Tallagrand Thierry
ab66a9ed54 PostgreSQL sur 5433 : DSM occupe deja le port standard
Le demarrage a echoue sur "listen tcp4 0.0.0.0:5432: bind: address already in
use". Synology fait tourner son propre PostgreSQL sur le port standard pour ses
services internes ; on ne le deloge pas, on se met a cote. Notre base est donc
publiee sur 5433, et ce port ne sert qu a l analyse depuis un poste de travail.

Corrige au passage une erreur de conception que ce plantage a revelee : j avais
repris network_mode bridge du chien de garde, ou il se justifiait parce qu il
n a qu un conteneur et doit joindre le GX. Ici il prive les trois services du
reseau interne de compose, donc de la resolution par nom — ce qui m avait
conduit a coder l adresse 10.10.10.22 en dur dans le service d historisation
pour qu il rejoigne une base situee dans le meme compose. Supprime : les
conteneurs se parlent desormais par nom de service, sans dependre du port
publie ni d une IP.

InfluxDB a demarre du premier coup, 8086 etant libre.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-09-04 01:35:52 +02:00
Tallagrand Thierry
7e2ed6d076 Generer les secrets de la memoire plutot que les inventer
Question du proprietaire : HA_TOKEN il l a, mais les mots de passe PostgreSQL
et InfluxDB, il les invente ? Non — ils se generent. Les deux bases n existent
pas encore, c est ce fichier qui decide de leurs identifiants, et personne ne
les tape jamais : les conteneurs les lisent dans .env et Home Assistant lit le
jeton dans son propre secrets.yaml.

preparer-env.sh les tire avec openssl rand, reprend HA_TOKEN du .env a la
racine plutot que d en creer un nouveau, pose les droits a 600, et affiche la
ligne a recopier dans secrets.yaml. Il refuse d ecraser un .env existant :
regenerer les mots de passe d une base deja creee la rendrait inaccessible.

Corrige au passage un piege laisse dans l exemple : POSTGRES_PASSWORD et
PGPASSWORD etaient deux variables a tenir egales a la main. Le fichier s appelle
desormais .env, donc compose l utilise aussi pour la substitution, et le service
d historisation reprend le mot de passe par substitution. Un seul secret
PostgreSQL desormais.

Generateur essaye dans un bac a sable : fichier conforme, refus de regeneration
verifie. Fichiers d echange des editeurs ajoutes au gitignore.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-09-04 01:29:12 +02:00
Tallagrand Thierry
230039d2a2 Memoire de mesures : PostgreSQL et InfluxDB sur le second Synology
Le proprietaire a tranche : on met les deux en service et on decidera a l usage
s il faut garder les deux. Elles ne repondent pas a la meme question.

PostgreSQL garde ce que n8n CALCULE — sorties du bilan, decisions du
controleur, prevision telle qu elle a ete publiee — parce que ce ne sont pas des
capteurs, donc qu aucune statistique Home Assistant ne les retient, et parce que
ce sont des vecteurs, du texte et des jointures. Cinq tables, une vue de confort
qui repond a la question restee sans reponse le 03/09 : ce que le bilan exigeait
contre le SOC reellement atteint, heure par heure.

InfluxDB garde ce que Home Assistant OBSERVE, a la resolution native et sur tout
le perimetre energie, y compris les entites auxquelles personne n a encore
pense. C est exactement ce qui a manque le 03/09, quand les modes des chargeurs
MPPT se sont reveles etre le bon signal alors que personne ne les enregistrait.

Les deux sur 10.10.10.22 : cette machine ne porte qu un service, quand
10.10.10.17 en porte quatre. Le volume n est pas l argument, les deux Synology
ont des teraoctets libres.

L alimentation de PostgreSQL ne passe volontairement PAS par n8n. Tout ce que
n8n calcule, il le publie deja dans des helpers Home Assistant : les lire donne
la meme information sans toucher aux trois workflows de production stabilises
hier soir ni creer d identifiant dans n8n. L horodatage retenu est celui de Home
Assistant et non celui du sondage, si bien qu une valeur inchangee porte la meme
clef primaire et n est pas reecrite : on enregistre quand la grandeur bouge, pas
quand on regarde.

Essai a blanc verifie sur l installation reelle : 15 mesures, 1 ligne de bilan,
1 decision, 2 previsions, avec les bonnes dates. Le mode blanc comptait d abord
les lignes ecrites, donc zero par construction — corrige pour compter ce qu il
ecrirait, sans quoi il ne verifiait rien.

Le branchement de Home Assistant sur InfluxDB demande un redemarrage et n est
donc PAS applique : le fichier de configuration est pret, a poser en milieu de
matinee, jamais entre 01:24 et 07:24.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-09-04 01:11:09 +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
e6e5c6f7b4 Consigner la maison : repas, strategie hivernale, blocage de charge a 94 %
Informations donnees par le proprietaire, a ne pas lui faire repeter.

La consommation est pilotee par les repas et non par une courbe lisse : quatre
personnes, bouilloire a 05:45, grille-pain a 08:00, cuisson du soir dont
l heure varie entre 20 h et 23 h selon les jours, et des repas differents d un
jour a l autre. Un profil horaire moyen ne represente donc rien, et moyenner
deux jours dont le pic est a 20 h et a 23 h produit un profil que ni l un ni
l autre ne ressemble. C est la cause la plus probable de la sous-estimation du
profil p50 mesuree la nuit du 02-03/09. Le proprietaire souligne aussi qu une
decharge courte mais forte n a pas le meme effet sur le stockage et l autonomie
qu une decharge lente de meme energie, et que ce n est pas lineaire — la courbe
energie/SOC du 03/09 ne dit rien du rendement sous fort courant.

Strategie hivernale : deux charges reseau par jour, batterie a 85 % en heures
creuses de nuit pour faire la jonction avec le PV du matin, puis une recharge de
midi pour tenir jusqu a la fenetre suivante. C est un contournement manuel de la
meme famille que les charges programmees ESS et la consigne a 4200 W ; le besoin
reste entier et ne doit pas etre retire avant que le bilan sache le produire
seul. Le cablage du 03/09 ne couvre que la session de nuit.

Un pack bloque la charge a 94 %, ce qui explique que la courbe mesuree s arrete
a 93. En rebranchant le pack isole, le blocage pourrait descendre a 85 %, valeur
possiblement fausse et donc a mesurer. Si le blocage reel est a 85, le plafond
de 90 % de la cible du matin devient inatteignable.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-09-04 00:14:57 +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