From 7942577967cd0145f04f423d58935c2e903be5c6 Mon Sep 17 00:00:00 2001 From: Tallagrand Thierry Date: Sat, 26 Sep 2026 00:57:42 +0200 Subject: [PATCH] Pack 1 (US5000) sous surveillance cellule : repli bat, essais code-barres, boot tolerant Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_011uJ47NxgfpGnuuMr3f2n7Z --- HANDOFF.md | 17 +++++++++- .../pack1/releve-pack1.service | 9 +++-- docs/MANUEL_COMPLET.md | 18 +++++++--- tools/pylontech-console.mjs | 34 +++++++++++++++---- 4 files changed, 64 insertions(+), 14 deletions(-) diff --git a/HANDOFF.md b/HANDOFF.md index 20cafc6..c5c9ffe 100644 --- a/HANDOFF.md +++ b/HANDOFF.md @@ -664,5 +664,20 @@ Le rebranchement du cable FTDI a revele deux defauts, corriges par une garde (ttyUSB0 -> ttyUSB1). Nom stable `/dev/pylontech-pack2` par numero de serie du cable, conteneur recree si le port change. Verifie : 5 modules relus a 16:53. +### 26/09 (nuit) — le pack 1 est enfin sous surveillance cellule +Nouveau poste **`yd-5CG6110DG0`** (HP EliteBook 840 G3, 10.10.10.61, IP reservee +DHCP, Ubuntu 26.04, BIOS mis a jour N75 01.61 -> 01.62 « Critical »), dedie au +cable Prolific du pack 1. Service `releve-pack1` (deploy/releve-cellules/pack1/), +lien udev `/dev/pylontech-pack1` par numero de serie, depot en NFS, rabat et +veille neutralises. Trois defauts trouves en le mettant en service : +- **course au boot** : reseau declare pret avant de l'etre, montage NFS rate, + service jamais relance (Restart= ne couvre pas un echec de dependance) -> + plus de RequiresMountsFor, verification en ExecStartPre ; +- **US5000 sans `soh`** (« Unknown command ») -> repli sur `bat ` ; +- **code-barres parfois non lu au demarrage** -> trois essais par adresse. +`pylontech-console.mjs --suffixe pack1` separe les CSV des deux lecteurs ; +`evcs_cellules` regarde 15 min (deux lecteurs non synchronises) et publie +`modules_lus`. Verifie : **9 modules en base, ecart max 2 mV**. + --- -*Document mis a jour le : 25/09/2026 — agent vocal, Grafana par chargeur, garde du releve cellules* +*Document mis a jour le : 26/09/2026 — pack 1 sous surveillance cellule (poste yd-5CG6110DG0)* diff --git a/deploy/releve-cellules/pack1/releve-pack1.service b/deploy/releve-cellules/pack1/releve-pack1.service index d169d77..7b0f01a 100644 --- a/deploy/releve-cellules/pack1/releve-pack1.service +++ b/deploy/releve-cellules/pack1/releve-pack1.service @@ -9,11 +9,16 @@ Description=Releve des cellules Pylontech du pack 1 (US5000) Wants=network-online.target After=network-online.target remote-fs.target -# Le lecteur lit son code et ecrit ses CSV dans le depot, monte en NFS. -RequiresMountsFor=/mnt/projects/EVCS/EVCS +# PAS de RequiresMountsFor= : au boot du 26/09, NetworkManager a declare le +# reseau pret 0,8 s avant qu'il le soit vraiment, le montage NFS a echoue +# (« Network is unreachable ») et le service, dependance en echec, n'a JAMAIS +# ete relance — Restart= ne couvre pas un echec de dependance. On verifie donc +# le depot dans ExecStartPre (l'acces declenche l'automontage) : un echec y est +# un echec du service, que Restart=always rattrape toutes les 30 s. [Service] User=tmzf5455 +ExecStartPre=/usr/bin/test -r /mnt/projects/EVCS/EVCS/tools/pylontech-console.mjs WorkingDirectory=/mnt/projects/EVCS/EVCS # /dev/pylontech-pack1 : lien stable pose par 90-pylontech.rules d'apres le # NUMERO DE SERIE du cable, jamais d'apres l'ordre d'enumeration. diff --git a/docs/MANUEL_COMPLET.md b/docs/MANUEL_COMPLET.md index a7fa484..cab26cd 100644 --- a/docs/MANUEL_COMPLET.md +++ b/docs/MANUEL_COMPLET.md @@ -121,10 +121,20 @@ par un LV-Hub.** il a disparu avec elles. Cellules du pack 2 mesurées à **3-6 mV d'écart**, SOH 99, limites BMS 250 A -charge / 250 A décharge, 53,2 V. ⚠️ Les cellules du **pack 1 (US5000) ne sont -pas sous surveillance continue** : le relevé série est sur le pack 2 et les -trames étendues du Cerbo sont mortes depuis le 15/09 (HANDOFF §69/§74). 2e câble -console en commande. +charge / 250 A décharge, 53,2 V. **Depuis le 26/09/2026, les deux packs sont sous +surveillance cellule continue** (les trames étendues du Cerbo restent mortes +depuis le 15/09, HANDOFF §69/§74) : +- **pack 2** (5 × US2000C) : câble FTDI sur le Synology .17, conteneur + `evcs-releve-cellules` (`deploy/releve-cellules/`) ; +- **pack 1** (4 × US5000) : câble à puce Prolific PL2303, **sans pilote sur + DSM**, lu par le portable **`yd-5CG6110DG0`** (10.10.10.61, EliteBook 840 G3), + service `releve-pack1` (`deploy/releve-cellules/pack1/`). Écart mesuré au + démarrage : 1 à 2 mV. Le firmware US5000 (B69.26) ne connaît pas `soh` : le + lecteur lit alors `bat `. Leur horloge interne a ~6 h d'avance (sans effet : + le relevé horodate avec l'heure de la machine). +`sensor.evcs_cellules` attribut `modules_lus` : **9 attendus** ; moins = un +lecteur muet. Un câble FTDI de remplacement pour le pack 1 est commandé (il +permettrait de tout lire depuis le Synology). **Capacité RE-MESURÉE le 20/09** (`tools/mesure-courbe-batterie.mjs`, HANDOFF §74) : courbe **plate à 0,30 kWh/point, sans genou**, réserve utile **~23 kWh** diff --git a/tools/pylontech-console.mjs b/tools/pylontech-console.mjs index 371f113..70654fd 100644 --- a/tools/pylontech-console.mjs +++ b/tools/pylontech-console.mjs @@ -397,8 +397,14 @@ async function main() { // exactement le piege ouvert quand le cable a change de pack le 05/09. const codes = new Map(); for (const ad of adresses) { - const info = await commande(l, `info ${ad}`, 8000); - const bc = (info.match(/Barcode\s*:\s*(\S+)/) || [])[1]; + // Trois essais par adresse (26/09) : sur les US5000, `info 4` est revenu + // une fois sans code-barres au demarrage — ligne pas encore videe. Un seul + // rate ne doit pas faire perdre un cycle entier au service. + let bc = null; + for (let essai = 0; essai < 3 && !bc; essai++) { + const info = await commande(l, `info ${ad}`, 8000); + bc = (info.match(/Barcode\s*:\s*(\S+)/) || [])[1] || null; + } if (!bc) { console.log(`Code-barres illisible pour l'adresse ${ad} : on n'enregistre pas a l'aveugle.`); console.log('Relancer la commande — la ligne aura eu le temps de se vider.'); @@ -411,6 +417,7 @@ async function main() { console.log('L\'heure enregistree est l\'heure REELLE de cette machine, pas celle du module'); console.log('(l\'horloge interne du module derive de plusieurs heures).'); console.log('Ctrl-C pour arreter.\n'); + let sansSoh = false; // passe a vrai si le firmware ignore `soh` (US5000) // Garde anti-blocage : si la ligne serie se fige (adaptateur qui ne repond // plus, module eteint), les lectures reviennent VIDES sans jamais lever // d'erreur (lireJusqua resout au timeout au lieu de rejeter), et le CSV @@ -436,12 +443,25 @@ async function main() { try { puis = courantsParModule(await commande(l, 'pwr', 10000)); } catch { /* on garde les tensions */ } for (const ad of adresses) { - const t = await commande(l, `soh ${ad}`, 10000); - // `soh` : " " const c = []; - for (const ligne of t.split('\n')) { - const m = ligne.trim().match(/^(\d{1,2})\s+(\d{4})\s+(\d+)\s+(\w+)/); - if (m) c.push({ n: +m[1] + 1, mV: +m[2] }); + if (!sansSoh) { + const t = await commande(l, `soh ${ad}`, 10000); + // `soh` : " " + for (const ligne of t.split('\n')) { + const m = ligne.trim().match(/^(\d{1,2})\s+(\d{4})\s+(\d+)\s+(\w+)/); + if (m) c.push({ n: +m[1] + 1, mV: +m[2] }); + } + // ⚠️ Le firmware des US5000 (B69.26, 26/09/2026) repond « Unknown + // command 'soh' ». On bascule alors sur `bat`, pour toute la session. + if (/Unknown command/i.test(t)) sansSoh = true; + } + if (sansSoh) { + // `bat` : " ..." (une ligne par cellule) + const t = await commande(l, `bat ${ad}`, 10000); + for (const ligne of t.split('\n')) { + const m = ligne.trim().match(/^(\d{1,2})\s+(\d{4})\s+(-?\d+)\s+(-?\d+)\s+([A-Za-z]+)/); + if (m) c.push({ n: +m[1] + 1, mV: +m[2] }); + } } if (c.length < 10) { console.log(`${horodate()} module ${ad} : illisible`); continue; } const v = c.map((x) => x.mV);