La borne annonce "charge" apres deux minutes, on ne la croit plus

Le 07/09 a 14:28:18 la borne a declare le statut 3 apres 2 min 42 s de charge
et 0,10 kWh livre. Le controleur l'a cru, a latche day_vehicle_full_idle, et la
JEEP est restee immobile deux heures en plein soleil alors qu'elle pouvait
charger : elle a repris a 16:30 et tenu.

La premiere idee etait de distinguer une vraie fin de charge d'une interruption
par la forme de la coupure. La mesure a la seconde l'a tuee : les deux courbes
sont superposables (VW 06/09, vraie fin : 1534 -> 550 -> 82 -> 11 -> 0 W ;
JEEP 07/09, faux positif : 1626 -> 741 -> 100 -> 13 -> 0 W). Aucun signal
electrique instantane ne separe les deux cas.

Seule la duree de session les distingue, et le systeme porte deja la grandeur
qui dit ce qu'est une charge etablie : min_run_minutes, 29 min en production.
Trois formes de "charged", une seule est refusee :

  energie de session nulle       -> vehicule plein a l'arrivee, on latche (P10)
  energie > 0, session < min_run -> charge INTERROMPUE, on ne latche pas
  energie > 0, session >= min_run -> charge menee a terme, on latche

Aucune constante nouvelle. Pas d'oscillateur : une session interrompue
redemarre a energie nulle, donc un second "charged" immediat retombe dans le
premier cas et latche.

Confirmation independante le meme jour : Uconnect a envoye a 14:29 un courriel
"RECHARGE ELECTRIQUE INTERROMPUE" invitant a controler la borne et le
connecteur. Le vehicule qualifie donc l'evenement d'interruption. Le releve de
la boite montre que c'est chronique depuis au moins decembre 2025 (12
interruptions et 6 echecs entre le 31/12 et le 08/03) : nos automates n'ont pas
cree le defaut, ils en ont augmente le cout.

Golden 80 -> 84, dont le releve reel et ses deux contrefactuels (duree et
energie). Trois mutations tombent chacune sur un jeu different ; celle qui rend
le cas "energie nulle" non credible fait echouer trois scenarios existants
(P10, Fix D, Fix E).

Corrige au passage le HANDOFF du 06/09 : last_session_energy ne decrit pas la
derniere session terminee, il suit la session en cours (verifie dans InfluxDB).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GwpFpy2aQ2rJok6tNQSbVj
This commit is contained in:
Tallagrand Thierry
2026-09-07 17:19:33 +02:00
parent 3fe84e09d4
commit 1c1b22311a
6 changed files with 639 additions and 20 deletions

View File

@@ -4627,13 +4627,20 @@ de dix minutes) :
| 06 01:25-02:44 | 4,24 kWh | 4,200 | 1 % |
| 06 13:32-13:42 | 0,34 kWh | 4,200 | **1135 %** |
⚠️ **La semantique de `last_session_energy` n'etait pas etablie** — le capteur
n'etait pas historise, donc aucune serie ne permettait de trancher entre
« derniere session terminee » et « session en cours avec reinitialisation
tardive ». Deux indices concordants recueillis apres coup : au moment de la
reparation il lisait 0,3 kWh et `..._last_session_time` 11 min, soit exactement
la session de midi. Il decrit donc la derniere session TERMINEE, et le lire
PENDANT une session donne la precedente.
⚠️ **CORRECTION du 07/09/2026 — la semantique affirmee ici etait FAUSSE.**
J'avais conclu que le capteur decrit la « derniere session TERMINEE » et que le
lire pendant une session donne la precedente. La serie InfluxDB, disponible
depuis le 06/09, montre l'inverse sans ambiguite : **il suit la session EN
COURS**, au pas de 0,1 kWh —
`0 (14:25:12) -> 0,1 (14:27:52)`, remise a zero a `16:28:31`, puis
`0,1 -> 0,2 -> 0,3 ... -> 1,1` pendant la charge. `_last_session_time` fait de
meme en minutes. Le nom du capteur est trompeur.
Le correctif applique le 06/09 (compteur cumulatif `total_energy`) reste le bon
choix, et le `GREATEST` reste bien le coupable du double comptage : la remise a
zero est simplement TARDIVE en debut de session, si bien que le premier
echantillon porte encore le total de la session precedente et que l'operateur
monotone le verrouille. C'est le mecanisme qui etait mal decrit, pas la
conclusion pratique.
Correctif (`tools/historise-evcs.mjs`) :
1. **Le compteur CUMULATIF de la borne** (`..._total_energy`, ~3 780 kWh)
@@ -4969,16 +4976,250 @@ ARCHIVE_1_VIDEO.hbk` et **reussit** : l'hote de destination va bien, c'est le
dossier qui a disparu.
Anciennete : dix notifications d'echec retrouvees, **zero reussite**, la plus
ancienne du **06/06/2026**. Les photos 2008-2015 de ARCHIVE (10.10.10.50) n'ont
donc aucune sauvegarde depuis au moins trois mois, et l'alerte quotidienne
partait dans une boite a 17 600 messages non lus.
ancienne du **06/06/2026**. ⚠️ Chiffre corrige apres lecture du journal
Hyper Backup (voir plus bas) : la derniere sauvegarde reussie date du
**24/08/2025**, soit **plus d'un an**, et non trois mois — les courriels
conserves ne remontaient simplement pas plus loin. L'alerte quotidienne partait
dans une boite a 17 600 messages non lus.
⚠️ Non corrige : 10.10.10.50 n'accepte pas ma cle SSH, et recreer un partage
puis reconfigurer Hyper Backup est une decision qui appartient au proprietaire.
Deux voies : recreer un dossier partage `ARCHIVEFAMILLE` sur 10.10.10.22, ou
repointer la tache vers un partage existant (`NetBackup` est le nom
conventionnel). Dans les deux cas il faudra une sauvegarde COMPLETE au premier
passage, le `.hbk` n'existant pas.
⚠️ **Acces SSH a 10.10.10.50 (ARCHIVE), etat au 06/09/2026.** Le compte est
**`thierry`** (donne par le proprietaire, et confirme par l'entree
`synology_dsm` de Home Assistant : hote 10.10.10.50, port DSM **5002**,
utilisateur `thierry` — les deux autres NAS utilisent `TMZF5455`). Le port SSH
22 repond, mais l'authentification par cle est refusee (`Permission denied
(publickey,password)`) pour tous les comptes essayes, alors que le
proprietaire dit avoir ajoute la cle. Causes DSM habituelles, dans l'ordre de
probabilite : le repertoire personnel est en 0777 (DSM le cree ainsi) et
`StrictModes` de sshd le refuse ; le compte n'appartient pas au groupe
**administrators**, seul autorise a ouvrir une session SSH sur DSM ; le service
**Repertoire personnel** (User Home) est desactive donc `~` n'existe pas.
Verification et reparation, a lancer par le proprietaire depuis son terminal :
```
ssh thierry@10.10.10.50 'mkdir -p ~/.ssh; \
echo "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHWfzf2109Rsv9jt2P592NgcK+7qR5teFULPgQNleoHj tmzf5455@yd-5CD8345759" >> ~/.ssh/authorized_keys; \
chmod 700 ~/.ssh; chmod 600 ~/.ssh/authorized_keys; chmod 755 "$HOME"; \
id; ls -ld "$HOME" ~/.ssh ~/.ssh/authorized_keys'
```
Le `chmod 755` sur le repertoire personnel est le point le plus souvent oublie :
sans lui sshd ignore silencieusement le fichier de cles, ce qui explique
exactement le symptome « j'ai ajoute la cle et ca ne marche pas ».
### La tache « Synology NAS 1 », lue dans sa configuration (06/09/2026)
Acces SSH a 10.10.10.50 obtenu (voir ci-dessus), `/usr/syno/etc/synobackup.conf`
lu directement. Les trois taches de ce NAS :
| tache | source (sur .50) | destination (sur .22) | depot | etat |
|---|---|---|---|---|
| WEB petit sino vers gros | `/web` | partage `web` | `ARCHIVE_2.hbk` | depot fige au **25/12/2019** |
| **Synology NAS 1** | **`/photo`, 399 Go** | partage **`ARCHIVEFAMILLE`** | `ARCHIVE_1_PHOTOS_2008_2015.hbk` | **echoue depuis ≥ 06/06/2026** |
| Synology NAS 2 | `/video` | partage `video` | `ARCHIVE_1_VIDEO.hbk` | reussit, depot du jour |
Details de la tache en echec : creee le **26/08/2018**, compte `TMZF5455`,
port **6281**, `trans_type=image_remote`, rotation activee, chiffrement
desactive.
**Le partage `ARCHIVEFAMILLE` n'existe pas sur 10.10.10.22** — verifie a la
racine des deux volumes. Et **aucun depot de photos n'existe nulle part** sur
ce NAS : `find /volume* -name "*.hbk"` ne rend que les trois depots ci-dessus,
dont aucun n'est celui des photos. La duree d'execution nulle relevee dans le
courriel d'echec s'explique entierement : Hyper Backup ne trouve pas le partage
de destination et s'arrete avant d'ouvrir le depot.
**Correction retenue : recreer un dossier partage nomme exactement
`ARCHIVEFAMILLE` sur 10.10.10.22, sur `/volume2`.** La tache existante repart
alors sans etre touchee — c'est la voie la moins invasive, DSM 7 ne permettant
pas de changer la destination d'une tache Hyper Backup existante (il faudrait
la recreer, et perdre son historique de versions).
Place : `/volume2` a **9,8 To libres** sur 11, `/volume1` seulement 850 Go sur
1,8 To. Les 399 Go du premier passage tiennent dans les deux, mais `/volume2`
laisse de la marge pour la rotation des versions.
⚠️ Le premier passage sera une sauvegarde **COMPLETE** de 399 Go, le depot
n'existant plus. Prevoir plusieurs heures.
### CORRECTION — recreer le partage etait necessaire, PAS suffisant
`sudo` libre obtenu sur 10.10.10.50 (procedure ci-dessous), donc
`/var/log/synolog/synobackup.log` enfin lisible. Il corrige deux choses que
j'avais affirmees.
**1. L'echec ne date pas de trois mois mais de PLUS D'UN AN.** Les courriels
d'alerte ne remontaient qu'a juin 2026 ; le journal, lui, donne :
| date | evenement |
|---|---|
| **24/08/2025 03:06** | **derniere sauvegarde REUSSIE** — 112 818 fichiers |
| 06/09/2025 | premier echec, « The network connection is closed. » |
| 01/03/2026 | dernier echec de ce type |
| **07/03/2026** | l'erreur change : « The backup destination does not exist. [Path: ARCHIVEFAMILLE] » |
**109 echecs enregistres.** L'enchainement se lit tout seul : la connexion a
casse d'abord (septembre 2025), et le partage `ARCHIVEFAMILLE` a ete supprime
plus tard, vers debut mars 2026 — ce qui repond a la question ouverte du
paragraphe suivant.
**2. Recreer le partage ne suffit pas a faire repartir la tache.** Apres
creation du partage, l'erreur a bien change — preuve que la destination est
desormais jointe et authentifiee :
```
16:15:52 Failed to start backup task. (The destination file does not exist.)
[Path: /volume2/ARCHIVEFAMILLE/ARCHIVE_1_PHOTOS_2008_2015.hbk/Config/version_info.db not exist]
```
Une tache Hyper Backup existante **exige de retrouver son depot** et refuse de
le recreer : elle cherche `<depot>.hbk/Config/version_info.db`. Le depot ayant
disparu avec le partage, la tache est **irrecuperable en l'etat**. Mon
affirmation « la tache existante repart telle quelle » etait fausse.
**Marche a suivre reelle** : creer une NOUVELLE tache dans Hyper Backup sur
10.10.10.50 — Sauvegarde de donnees → serveur Synology distant → `10.10.10.22`,
compte `TMZF5455`, partage `ARCHIVEFAMILLE`, depot
`ARCHIVE_1_PHOTOS_2008_2015`, source = dossier partage `photo` (399 Go) — puis
supprimer l'ancienne tache « Synology NAS 1 ». La creation d'une tache Hyper
Backup n'a pas d'equivalent en ligne de commande : elle se fait dans DSM.
L'historique de versions est perdu de toute facon, le depot n'existant plus.
⚠️ **Piege a retenir** : `synobackup --backup <id> --type image` rend
**code 0 et une sortie vide meme quand il echoue**, en root comme en simple
utilisateur. Le seul retour exploitable est
`/var/log/synolog/synobackup.log`.
### Seconde tache cassee, decouverte au passage : « WEB petit sino vers gros »
Elle echoue **tous les jours a 03:00**, avec « The network connection is
closed. » — et `enable_notify=true`, donc elle alerte elle aussi. Configuration :
source `/web` du .50, destination `10.10.10.22` partage `web`, depot
`ARCHIVE_2.hbk`, **port 873** (rsync en clair) la ou les deux autres taches
utilisent 6281.
Ce n'est PAS un probleme de port : depuis le .50, **873 et 6281 repondent tous
les deux**, et sur le .22 `netstat` montre `rsync` en ecoute sur 873 et
`img_backupd` sur 6281. Le depot `/volume1/web/ARCHIVE_2.hbk` est fige au
**25/12/2019**. Cause a instruire separement (authentification rsync, ou depot
inutilisable).
### RESOLU le 06/09/2026 a 22:53 — nouvelle tache, sauvegarde en cours
Journal Hyper Backup du .50 :
```
18:54:20 thierry: Backup task [Synology NAS 1] was removed.
20:59:51 thierry: Backup task [WEB petit sino vers gros] was removed.
22:53:04 thierry: Setting of backup task [Synology NAS 1 ARCHIVE FAMILLE] was created
to backup to [TMZF5455@10.10.10.22::ARCHIVEFAMILLE/ARCHIVE_1_PHOTOS_2008_2015.hbk]
22:53:32 SYSTEM: [Synology NAS 1 ARCHIVE FAMILLE] Backup task started.
```
Verifie cote destination : le depot
`/volume2/ARCHIVEFAMILLE/ARCHIVE_1_PHOTOS_2008_2015.hbk` existe, appartient a
`TMZF5455`, et **grossit** (395 Mo puis 604 Mo a une minute d'intervalle).
Aucune erreur depuis le demarrage. La seconde tache cassee
(« WEB petit sino vers gros ») a ete supprimee plutot que reparee — decision du
proprietaire ; le depot `/volume1/web/ARCHIVE_2.hbk` de 2019 reste sur le .22
et peut etre efface si `/web` n'a plus de valeur.
Ne restent donc que deux taches sur le .50 : `task_3` (« Synology NAS 2 »,
`/video` → partage `video`) et `task_4` (la nouvelle).
⚠️ **La nouvelle tache sauvegarde `["/photo","/video"]`**, alors que l'ancienne
ne prenait que `/photo`. `/video` est deja sauvegarde par « Synology NAS 2 »
dans un depot de **455 Go** sur `/volume1/video` du .22. Le premier passage
copiera donc ~399 Go de photos **plus ~455 Go de videos en double**, soit
~854 Go. L'espace ne manque pas (9,8 To libres sur `/volume2`) mais c'est
plusieurs heures et un demi-tera pour rien si l'inclusion de `/video` etait une
case cochee par erreur. A trancher par le proprietaire — se corrige dans les
parametres de la tache.
### Partage recree le 06/09/2026 a 16:14
`/volume2/ARCHIVEFAMILLE` existe. Verifie, cote destination :
- chemin et type conformes (`synoshare --get`) ;
- ACL **identique a celle du partage `video` dont la tache reussit** :
`group:administrators:allow:rwxpdDaARWc--` — et le compte de la tache,
`TMZF5455`, est administrateur. Les droits ne bloqueront pas ;
- port **6281 joignable depuis 10.10.10.50** (teste) ;
- 9,8 To libres sur `/volume2`.
⚠️ **Le lancement en ligne de commande ne fonctionne PAS depuis mon acces.**
`/usr/syno/bin/synobackup --backup 2 --type image` rend **code 0 et une sortie
vide, sans rien demarrer** : aucun processus, `--is-backup-restore-running`
repond « pas en cours », et le depot n'apparait pas cote destination. La
commande exige root et echoue silencieusement — piege a connaitre, le code de
retour ne signale rien.
⚠️ **`sudo` demande un mot de passe sur 10.10.10.50**, contrairement a
10.10.10.22 ou il est libre. Consequence : ni le lancement de la tache ni la
lecture de `/var/log/synolog/` et `/var/log/messages` ne me sont accessibles
sur ce NAS.
Lancement a faire par le proprietaire : **Hyper Backup → tache « Synology
NAS 1 » → Sauvegarder maintenant**, qui donne en prime la progression des
399 Go.
### Pourquoi `sudo` est libre sur 10.10.10.22 et pas sur 10.10.10.50
Les deux NAS ne tournent pas la meme version : **10.10.10.22 est en DSM 7.3.2**,
**10.10.10.50 en DSM 6.2.4** (fin de support Synology). Sur le .22,
`/etc/sudoers` porte en ligne 11 `%administrators ALL=NOPASSWD: ALL`, ce que
DSM 6 ne pose pas.
⚠️ **`visudo` n'existe nulle part sur 10.10.10.50** (verifie par `find`), alors
que `sudo` lui-meme est en 1.9.5p2. Il n'y a donc **aucune validation
syntaxique possible avant d'appliquer**, et une erreur dans `sudoers` verrouille
`sudo` entierement. Garder une session root ouverte pendant la manipulation
n'est pas une precaution de style, c'est le seul filet.
Procedure (a lancer par le proprietaire, DSM 6.2.4) :
```
# terminal 1 — NE PAS FERMER avant la validation
ssh thierry@10.10.10.50
sudo -i # mot de passe DSM
cp -a /etc/sudoers /etc/sudoers.bak.$(date +%Y%m%d-%H%M%S)
grep -c '^#includedir /etc/sudoers.d' /etc/sudoers
```
Si la reponse est `1` (repertoire inclus, a preferer : le fichier survit aux
mises a jour DSM) :
```
echo 'thierry ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/thierry-nopasswd
chown root:root /etc/sudoers.d/thierry-nopasswd
chmod 0440 /etc/sudoers.d/thierry-nopasswd
```
Si la reponse est `0` :
```
echo 'thierry ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers
```
Validation depuis un **second** terminal, la session root toujours ouverte :
```
ssh thierry@10.10.10.50 'sudo -n id' # doit rendre uid=0(root)
```
En cas d'erreur de syntaxe, revenir au terminal 1 (toujours root) :
`rm -f /etc/sudoers.d/thierry-nopasswd` et/ou restaurer la sauvegarde
`/etc/sudoers.bak.*`.
Portee retenue : la regle ne vise que `thierry`, pas tout le groupe
`administrators` — plus etroit que ce qui est en place sur le .22. Contrepartie
assumee, identique a celle deja acceptee sur le .22 : toute cle SSH installee
pour ce compte devient root sans obstacle.
⚠️ Question ouverte : pourquoi ce partage a disparu de 10.10.10.22. Il existait
forcement en 2018 puisque la tache a tourne. A rapprocher d'une eventuelle
reorganisation des volumes — `/volume2/video_1/ARCHIVE_1_VIDEO.hbk` (fige au
05/03/2026) est un depot double de celui de `/volume1/video`, ce qui ressemble
a une migration de volume laissee en plan.
### Les annotations Grafana etaient devenues illisibles
Sept jours d'historique produisaient une foret de pointilles orange masquant les
@@ -5028,3 +5269,213 @@ tous a sa charge. Sur un parc de quatre modules (7,1 kWh utiles de 100 a 22 %),
---
*Document mis a jour le : 06/09/2026 (~13:10) — relachement du contacteur sur une duree gagee sur le bilan, golden-hysteresis 20/20, deploye*
## 58. Session du 07/09/2026 — La borne annonce « charge terminee » apres 0,10 kWh
### Symptome
JEEP branchee a 14:26, immobile jusqu'a 16:29 en plein soleil. Le controleur
affichait `day_vehicle_full_idle` (P10, « vehicule plein en journee »), source
`Bloque`.
### Ce que la borne a reellement declare
`sensor.evcs_hq2239dnt7p_status`, entree dans l'historisation InfluxDB la veille
— c'est ce capteur qui tranche, et il n'etait pas lisible avant le 06/09 :
```
14:25:12 waiting_for_start
14:25:32 start_charging
14:25:36 charging -> 1239 puis 1577 W, 6 -> 8 A
14:28:18 charged <-- apres 2 min 42 s et 0,10 kWh
14:28:30 waiting_for_start
(deux heures d'immobilite : l'etat collant tient, comme concu)
16:29:02 disconnected <-- cable branche, liaison perdue
16:29:06 waiting_for_start
16:29:31 start_charging
16:29:35 charged <-- QUATRE SECONDES apres le demarrage
16:29:55 disconnected
16:29:59 waiting_for_start
16:30:03 start_charging
16:30:07 charging -> tient, 1947 W a 10 A, en montee
```
**Le controleur n'a rien bloque : il a cru la borne.** Fix D (§17) et P10 (§22)
traitent `status == charged` + puissance nulle comme une fin de charge, et
latchent un etat collant jusqu'au debranchement. C'est exactement ce qui a ete
demande. Le signal d'entree, lui, etait faux.
Un `charged` quatre secondes apres `start_charging` ne peut pas etre vrai. Et
les deux `disconnected` cable branche designent une rupture du signal pilote —
**piste materielle a instruire en premier** : connecteur cote vehicule et cote
borne, verrouillage de la prise, cable. Aucune alarme n'est publiee par la
borne, aucune alarme VE.Bus active.
### Ce qui a leve le collant : PAS le selecteur de vehicule
Le proprietaire a change `input_select.victron_evcs_vehicle` de VW a JEEP a
16:28:32, et la charge est repartie 90 s plus tard. **Coincidence, pas cause** :
`dayVehicleFullIdle` exige `parsed.evcsVehicleConnected`, et c'est le
`disconnected` de 16:29:02 qui a fait tomber cette condition. Le rythme des
transitions qui suivent (4 s, 20 s) exclut une manipulation humaine.
⚠️ Ne pas en conclure que corriger le selecteur debloque une charge.
### Comparaison avec la veille (VW, 06/09) — le phenomene n'est pas tout neuf
La VW a subi deux interruptions (`waiting_for_start` a 15:20:35 et 15:52:35)
mais elle est repartie **seule en une trentaine de secondes** a chaque fois, et
a livre 4,30 kWh ; son `charged` de 16:06:42 est arrive apres 1 h 32 de charge,
donc legitime. Les interruptions existaient donc deja ; ce qui est nouveau
aujourd'hui, c'est le `charged` premature qui verrouille le systeme derriere.
### Defaut de conception a corriger (PROPOSE, non deploye)
Le controleur traite identiquement trois situations que l'energie de session
separe sans ambiguite :
| situation | energie livree | duree | verdict |
|---|---:|---:|---|
| vehicule plein rebranche | 0 kWh | — | `charged` legitime, collant justifie |
| **interruption anormale** | **0,10 kWh** | **2-4 min** | **doit etre reessaye** |
| vraie fin de charge | 4,30 kWh | 1 h 32 | `charged` legitime |
La distinction ne demande aucune constante inventee : la borne publie
`sensor.evcs_hq2239dnt7p_last_session_energy` et `_last_session_time`, toutes
deux historisees depuis le 06/09. Un `charged` qui suit une charge REELLE mais
dont la session n'a livre qu'une energie derisoire n'est pas une fin de charge,
c'est une interruption — et le collant ne doit pas se poser.
⚠️ Le cas « 0 kWh livre » doit rester collant : c'est le cas P10 d'origine
(VW pleine rebranchee, 09/08).
### Cout de l'episode
Deux heures d'immobilite (14:28 → 16:29) un jour a 2,5 kW de production
disponible et batterie a 96-97 %, donc sur de la ressource qui etait de toute
facon refusee. Le cout n'est pas en energie achetee mais en energie solaire
non captee par le vehicule.
---
*Document mis a jour le : 07/09/2026 — `charged` premature de la borne, piste materielle a instruire, correctif controleur propose*
## 59. Session du 07/09/2026 — Fix H : un statut « charged » doit etre credible
### La mesure qui a decide de la conception
Premiere idee : distinguer une vraie fin de charge d'une interruption par la
FORME de la coupure — une batterie qui se remplit decroit, une interruption
coupe net. **Mesure a la seconde des deux cas, elle est morte sur place :**
| | T-4 s | T-3 s | T-2 s | T-1 s | T |
|---|---:|---:|---:|---:|---:|
| VW 06/09 16:06:42, **vraie fin** (4,30 kWh, 1 h 32) | 1534 W | 550 | 82 | 11 | 0 |
| JEEP 07/09 14:28:18, **faux positif** (0,10 kWh, 2 min 42 s) | 1626 W | 741 | 100 | 13 | 0 |
Les deux courbes sont superposables. **Aucun signal electrique instantane ne
separe les deux cas** — ni la puissance, ni sa pente. Ne pas reessayer cette
piste.
Ce qui les separe est la DUREE de la session. Et le systeme porte deja la
grandeur qui dit ce qu'est une charge etablie : **`min_run_minutes`, qui vaut
29 minutes en production** (le `3` qu'on lit dans `INPUT_PARSE.js` n'est que le
repli du code — meme piege qu'au 24/08 avec les seuils 22/35 de l'hysteresis).
### Le correctif
Dans `WINDOWS_SOURCEV2.js`, `evcsStatusCharged` gagne une condition de
credibilite. Trois formes de « charged », dont une seule est refusee :
| energie livree par la session | duree | verdict |
|---|---|---|
| **nulle** | — | vehicule plein a l'arrivee → collant (cas P10 d'origine) |
| > 0 et session **< `min_run_minutes`** | courte | **charge INTERROMPUE → on ne latche pas** |
| > 0 et session **>= `min_run_minutes`** | longue | charge menee a terme → collant |
Aucune constante nouvelle : `min_run_minutes` existe, et l'energie de session
est publiee par la borne.
**Pas d'oscillateur** : une session interrompue redemarre a energie nulle, donc
un second « charged » immediat retombe dans le premier cas et latche. La
convergence est garantie en une tentative supplementaire.
### Chaine technique
- `HA_SNAPSHOT_TEMPLATE` : `+evcs_session_energy_kwh` ←
`sensor.evcs_hq2239dnt7p_last_session_energy` (gabarit re-rendu contre HA :
**198 champs, JSON valide, aucun null**) ;
- `INPUT_PARSE` : `parsed.evcsSessionEnergyKwh` ;
- `WINDOWS_SOURCEV2` : `chargedSessionEnergyKwh`, `chargedSessionEstablished`,
`chargedCredible`, tous trois exportes pour la tracabilite.
**Repli** : capteur absent → energie 0 → credible → comportement d'avant. C'est
pourquoi les 80 scenarios existants sont inchanges (leur fixture ne porte pas
le champ).
### Golden 80 → 84
`charged-interrompu-ne-latche-pas` (le releve du 07/09 : 2 min 42 s, 0,10 kWh →
la charge CONTINUE a 7 A au lieu de se bloquer) · `charged-session-etablie-latche`
(contrefactuel de duree : 1 h 32, 4,30 kWh → collant) ·
`charged-energie-nulle-latche` (contrefactuel d'energie : 0 kWh → collant, cas
P10 preserve) · `night-charged-interrompu-ne-latche-pas` (la meme garde en
fenetre HC : la charge reseau continue).
Preuve par mutation, trois directions, **chacune tombant sur un jeu different** :
garde retiree → les 2 scenarios « interrompu » ; cas energie nulle rendu non
credible → 4 scenarios dont **3 EXISTANTS** (`day-vw-pleine-statut3`,
`night-vw-statut-charged`, `night-charged-en-session-active`) ; duree ignoree →
le scenario « session etablie ». Restauration → 84/84.
### Confirmation independante par le constructeur (Gmail, 07/09)
Le vehicule dispose de sa propre telematique (Uconnect) qui envoie un courriel
depuis `uconnectservices@jeep.com`. Le 07/09 a **14:29**, soit **une minute
apres** le `charged` de la borne de 14:28:18 :
> « RECHARGE ELECTRIQUE INTERROMPUE — Nous avons detecte que la recharge de
> votre Jeep a ete **interrompue**. Nous vous invitons a controler votre borne
> et le connecteur de recharge, et a reessayer. »
**Le vehicule qualifie l'evenement d'INTERRUPTION, pas de fin de charge.** Fix H
traite donc le bon probleme, et la piste materielle est celle que le
constructeur designe lui-meme (« votre borne et le connecteur »).
⚠️ **Jeep distingue QUATRE evenements la ou la borne n'a qu'un statut** :
« RECHARGE ELECTRIQUE COMMENCEE » · « VOUS VOILA CHARGE A BLOC » (fin normale) ·
« RECHARGE ELECTRIQUE INTERROMPUE » · « RECHARGE INFRUCTUEUSE » (echec au
demarrage). C'est exactement l'information qui manque au controleur.
### Le defaut est CHRONIQUE, et anterieur a tout notre outillage
Releve dans la boite de reception, decembre 2025 → mars 2026 : au moins
**12 « interrompue »** (31/12, 04/01 ×2, 05/01, 14/01, 17/01, 23/01, 29/01,
15/02, 20/02, 08/03 ×2) et **6 « infructueuse »** (17/01, 23/01, 27/01, 28/01,
23/02, 08/03). Deux journees typiques :
| 08/03/2026 | 23/01/2026 |
|---|---|
| 08:24 infructueuse | 12:53 commencee |
| 11:44 commencee | 13:15 infructueuse |
| **11:59 interrompue (15 min)** | 14:01 commencee |
| 15:12 commencee | **15:34 interrompue** |
| 17:11 interrompue | |
Ce n'est donc pas une consequence de nos correctifs ni de la borne en
firmware 2.08 : le vehicule signale des interruptions depuis au moins neuf
mois. Ce que nos automates ont change, c'est le COUT d'une interruption (deux
heures de blocage au lieu d'une reprise).
⚠️ **Aucun courriel Jeep entre le 18/03/2026 et le 07/09/2026** dans l'index de
recherche, alors que l'index couvre bien les jours recents (le rapport de nuit
de 06:47 y figure). Trois lectures possibles, non tranchees : notifications
Uconnect desactivees puis reactivees, JEEP non chargee a la maison sur cette
periode, ou trou d'indexation. A verifier avec le proprietaire.
### Piste : faire du courriel Jeep un signal du systeme (PROPOSE)
Ces courriels arrivent ~1 minute apres l'evenement et portent la qualification
que la borne ne sait pas donner. Chaine possible : filtre Gmail → transfert vers
un webhook n8n → `input_text.victron_evcs_jeep_last_event` → lu par
`WINDOWS_SOURCEV2` (« interrompue » ⇒ ne jamais latcher le collant).
⚠️ **Signal d'appoint, jamais de securite** : latence de deux cycles, dependance
a Internet (or les coupures d'orage sont frequentes ici) et a un service cloud
tiers. Fix H doit rester la garde principale, qui elle est locale.
### Ce que le correctif ne traite PAS
La cause premiere reste materielle et n'est pas instruite : deux
`disconnected` cable branche le 07/09 a 16:29:02 et 16:29:55, et un « charged »
quatre secondes apres `start_charging`. Fix H **borne le cout** d'un signal
faux ; il ne repare pas le signal. Connecteur, verrouillage et cable restent a
inspecter.
---
*Document mis a jour le : 07/09/2026 — Fix H prepare (golden 84/84, gabarit valide contre HA), en attente de validation avant PUT*

View File

@@ -38,6 +38,7 @@
"evcs_current_a": states("sensor.victron_evcs_current"),
"evcs_ac_power_w": states("sensor.victron_evcs_ac_power"),
"evcs_charging_time": states("sensor.victron_evcs_charging_time"),
"evcs_session_energy_kwh": states("sensor.evcs_hq2239dnt7p_last_session_energy"),
"evcs_charging_switch": states("switch.victron_evcs_charging"),
"evcs_auto_start_switch": states("switch.victron_evcs_auto_start"),

View File

@@ -328,6 +328,11 @@ const parsed = {
evcsAcPowerW: Math.max(0, num(input.evcs_ac_power_w, 0)),
evcsChargingTimeSec: parseChargingTimeToSec(input.evcs_charging_time),
// Energie deja livree par la session EN COURS (kWh). Le capteur de la borne
// s'appelle "last_session_energy" mais il suit la session courante et repart
// de zero a chaque nouvelle connexion (verifie le 07/09/2026 : 0 -> 0,1 -> 0,2
// ... pendant la charge). Sert a juger la credibilite d'un statut "charged".
evcsSessionEnergyKwh: Math.max(0, num(input.evcs_session_energy_kwh, 0)),
evcsChargingSwitchOn: low(input.evcs_charging_switch || 'off') === 'on',
evcsAutoStartSwitchOn: low(input.evcs_auto_start_switch || 'off') === 'on',

View File

@@ -430,10 +430,36 @@ const sessionFresh =
// collant écrit par DECISION pendant la session (voir Fix E DECISION).
// P11 : sur une session neuve, on ignore aussi un éventuel statut 3 résiduel
// (le temps que la borne renégocie avec le nouveau véhicule).
// Fix H (07/09/2026) : un statut "charged" n'est pas cru sur parole.
// La borne l'a annonce le 07/09 a 14:28:18 apres 2 min 42 s de charge et
// 0,10 kWh livre, ce qui a latche `day_vehicle_full_idle` pour deux heures
// alors que le vehicule pouvait charger (il a repris a 16:30 et tenu).
//
// Aucun signal ELECTRIQUE instantane ne separe une vraie fin de charge d'une
// interruption : mesure a la seconde des deux coupures, elles sont
// superposables (VW 06/09, vraie fin : 1534 -> 550 -> 82 -> 11 -> 0 W ;
// JEEP 07/09, faux positif : 1626 -> 741 -> 100 -> 13 -> 0 W). Seule la
// DUREE de la session les distingue, et le systeme porte deja la grandeur qui
// dit ce qu'est une charge etablie : min_run_minutes (29 min en production).
//
// Deux formes de "charged" sont credibles, et une seule ne l'est pas :
// energie de session nulle -> le vehicule etait plein en arrivant (P10)
// session >= min_run_minutes -> charge menee a son terme
// entre les deux -> charge INTERROMPUE : on ne latche pas
// Convergence : une session interrompue redemarre a energie nulle, donc un
// second "charged" immediat retombe dans le premier cas et latche.
const chargedSessionEnergyKwh = Math.max(0, parsed.evcsSessionEnergyKwh || 0);
const chargedSessionEstablished =
Number.isFinite(parsed.evcsChargingTimeSec) &&
parsed.evcsChargingTimeSec >= params.minRunMinutes * 60;
const chargedCredible =
chargedSessionEnergyKwh <= 0 || chargedSessionEstablished;
const evcsStatusCharged =
!sessionFresh &&
Number.parseFloat(parsed.evcsStatusRaw) === 3 &&
Math.max(0, parsed.evcsAcPowerW || 0) <= 300;
Math.max(0, parsed.evcsAcPowerW || 0) <= 300 &&
chargedCredible;
const vehicleChargeCompleted =
nightSessionActive &&
@@ -1043,6 +1069,9 @@ return [{
// P11
sessionFresh,
chargedSessionEnergyKwh,
chargedSessionEstablished,
chargedCredible,
}
}
}];

View File

@@ -317,6 +317,139 @@ export const scenarios = [
// Incident 09/08 09:49 : VW pleine, le surplus solaire retentait une charge
// toutes les ~15 min (statut "Charged", 0 W) → usure relais. Désormais
// collant jusqu'au débranchement, avec héritage des états done de la nuit.
// ===== Fix H (07/09/2026) : credibilite du statut "charged" =====
// Releve reel : la borne a annonce "charged" a 14:28:18 apres 2 min 42 s de
// charge et 0,10 kWh livre, ce qui a bloque le vehicule deux heures. Les deux
// coupures (vraie fin de charge et interruption) sont ELECTRIQUEMENT
// identiques, mesurees a la seconde : seule la duree de session les separe.
{
id: 'charged-interrompu-ne-latche-pas',
label: 'Statut 3 apres 2 min 42 s et 0,10 kWh livre (releve 07/09) -> interruption, PAS de collant',
time: AFTERNOON,
overrides: {
evcs_vehicle_connected: 'on', evcs_device_connected: 'on',
soc_percent: '96', pv_power_w: '2600', pv_power_10m_avg_w: '2500',
pv_trend_w: '0', battery_current_a: '2',
house_ac_power_w: '2100', vebus_ac_out_l1_power_w: '2100',
evcs_charging_switch: 'on',
charge_permission_now: 'on',
control_latch: 'on',
evcs_current_a: '0',
evcs_ac_power_w: '0',
evcs_status_raw: '3',
evcs_charging_time: '2m 42s',
evcs_session_energy_kwh: '0.1',
prev_surplus_state: 'charging_hold',
},
expect: {
profile: 'outside_window',
sourceMode: 'solar_only',
state: 'charging_step_up_battery',
decision: 'step_up',
desiredCharging: true,
currentA: 7,
takeoverNeeded: false,
edfOnAction: false,
takeoverHelperService: 'turn_off',
},
},
{
id: 'charged-session-etablie-latche',
label: 'CONTREFACTUEL : meme statut 3 apres 1 h 32 et 4,30 kWh (releve VW 06/09) -> vraie fin, collant',
time: AFTERNOON,
overrides: {
evcs_vehicle_connected: 'on', evcs_device_connected: 'on',
soc_percent: '96', pv_power_w: '2600', pv_power_10m_avg_w: '2500',
pv_trend_w: '0', battery_current_a: '2',
house_ac_power_w: '2100', vebus_ac_out_l1_power_w: '2100',
evcs_charging_switch: 'on',
charge_permission_now: 'on',
control_latch: 'on',
evcs_current_a: '0',
evcs_ac_power_w: '0',
evcs_status_raw: '3',
evcs_charging_time: '1h 32m 0s',
evcs_session_energy_kwh: '4.3',
prev_surplus_state: 'charging_hold',
},
expect: {
profile: 'outside_window',
sourceMode: 'blocked',
state: 'day_vehicle_full_idle',
decision: 'stop_vehicle_full_or_paused',
desiredCharging: false,
currentA: 6,
takeoverNeeded: false,
edfOnAction: false,
takeoverHelperService: 'turn_off',
},
},
{
id: 'charged-energie-nulle-latche',
label: 'CONTREFACTUEL : statut 3 avec ZERO kWh livre (vehicule plein a l arrivee, cas P10) -> collant',
time: AFTERNOON,
overrides: {
evcs_vehicle_connected: 'on', evcs_device_connected: 'on',
soc_percent: '96', pv_power_w: '2600', pv_power_10m_avg_w: '2500',
pv_trend_w: '0', battery_current_a: '2',
house_ac_power_w: '2100', vebus_ac_out_l1_power_w: '2100',
evcs_charging_switch: 'on',
charge_permission_now: 'on',
control_latch: 'on',
evcs_current_a: '0',
evcs_ac_power_w: '0',
evcs_status_raw: '3',
evcs_charging_time: '3m 20s',
evcs_session_energy_kwh: '0',
prev_surplus_state: 'charging_hold',
},
expect: {
profile: 'outside_window',
sourceMode: 'blocked',
state: 'day_vehicle_full_idle',
decision: 'stop_vehicle_full_or_paused',
desiredCharging: false,
currentA: 6,
takeoverNeeded: false,
edfOnAction: false,
takeoverHelperService: 'turn_off',
},
},
{
id: 'night-charged-interrompu-ne-latche-pas',
label: 'Nuit HC : statut 3 apres 3 min et 0,10 kWh -> interruption, la charge HC continue',
time: NIGHT,
overrides: {
evcs_vehicle_connected: 'on', evcs_device_connected: 'on',
night_session_active: 'on',
allow_grid_hc_night: 'on',
soc_percent: '55', pv_power_w: '0', pv_power_10m_avg_w: '0',
pv_trend_w: '0', battery_current_a: '0',
house_ac_power_w: '800', vebus_ac_out_l1_power_w: '800',
evcs_charging_switch: 'on',
charge_permission_now: 'on',
control_latch: 'on',
grid_switch: 'on',
acin1_available: '1',
evcs_current_a: '0',
evcs_ac_power_w: '0',
evcs_status_raw: '3',
evcs_charging_time: '3m 0s',
evcs_session_energy_kwh: '0.1',
prev_surplus_state: 'charging_step_up_grid_hc',
},
expect: {
profile: 'night_hc',
sourceMode: 'grid_hc_allowed',
state: 'night_wait_grid_takeover_runtime',
decision: 'hold',
desiredCharging: false,
currentA: 6,
takeoverNeeded: true,
edfOnAction: true,
takeoverHelperService: 'turn_on',
},
},
{
id: 'day-vw-pleine-statut3',
label: 'Matin PV fort, session armée 0 W, statut 3 → day_vehicle_full_idle collant (stop propre, plus de solaire)',

File diff suppressed because one or more lines are too long