Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
146 lines
6.6 KiB
JavaScript
146 lines
6.6 KiB
JavaScript
#!/usr/bin/env node
|
||
// Rassemble tout ce qui concerne les BMS Pylontech en une archive lisible par
|
||
// un tiers : un dossier par module, nomme par son code-barres, plus un
|
||
// manifeste trilingue qui dit quel module est quoi et ou regarder en premier.
|
||
//
|
||
// node tools/preparer-archive-pylontech.mjs
|
||
//
|
||
// Le tri se fait sur le CONTENU des fichiers (code-barres lu dedans), jamais
|
||
// sur leur nom : les exports BatteryView et les miens ne se nomment pas pareil.
|
||
|
||
import fs from 'node:fs';
|
||
import path from 'node:path';
|
||
import { execFileSync } from 'node:child_process';
|
||
|
||
const SRC = 'docs/mesures/batteries';
|
||
const OUT = `docs/mesures/archive-pylontech-${new Date().toISOString().slice(0, 10).replace(/-/g, '')}`;
|
||
|
||
// Etat de chaque module, tel qu'etabli le 05/09/2026. Sert au manifeste.
|
||
const MODULES = {
|
||
K220803C30160322: { pack: '2022', adr: 1, cellules: '6, 7, 12, 14', med: 108, ev: 850, etat: 'atteint' },
|
||
K220803C30160323: { pack: '2022', adr: 2, cellules: '—', med: 6, ev: 0, etat: 'temoin' },
|
||
K220803C30160319: { pack: '2022', adr: 3, cellules: '2, 6, 10, 12, 15', med: 45, ev: 688, etat: 'atteint' },
|
||
K220803C30160324: { pack: '2022', adr: 4, cellules: '15', med: 57, ev: 900, etat: 'atteint' },
|
||
Y230202C30371426: { pack: '2023', adr: 1, cellules: '—', med: 2, ev: 19, etat: 'sain' },
|
||
Y230202C30371425: { pack: '2023', adr: 2, cellules: '—', med: 2, ev: 12, etat: 'sain' },
|
||
Y230202C30371431: { pack: '2023', adr: 3, cellules: '—', med: 2, ev: 6, etat: 'sain' },
|
||
Y230202C30371427: { pack: '2023', adr: 4, cellules: '—', med: 2, ev: 1, etat: 'sain' },
|
||
};
|
||
|
||
const lire = (f) => {
|
||
const b = fs.readFileSync(f);
|
||
return b.toString(b[0] === 0xff && b[1] === 0xfe ? 'utf16le' : 'utf8');
|
||
};
|
||
|
||
fs.rmSync(OUT, { recursive: true, force: true });
|
||
fs.mkdirSync(OUT, { recursive: true });
|
||
|
||
const classe = {};
|
||
let communs = 0;
|
||
for (const n of fs.readdirSync(SRC)) {
|
||
const f = path.join(SRC, n);
|
||
if (!fs.statSync(f).isFile()) continue;
|
||
let bc = null;
|
||
for (const code of Object.keys(MODULES)) {
|
||
if (n.includes(code)) { bc = code; break; }
|
||
}
|
||
if (!bc && /\.(txt|csv)$/i.test(n)) {
|
||
const t = lire(f).slice(0, 200000);
|
||
for (const code of Object.keys(MODULES)) if (t.includes(code)) { bc = code; break; }
|
||
}
|
||
const dest = bc ? path.join(OUT, `${MODULES[bc].pack}-${bc}`) : path.join(OUT, 'commun');
|
||
fs.mkdirSync(dest, { recursive: true });
|
||
fs.copyFileSync(f, path.join(dest, n));
|
||
if (bc) (classe[bc] ??= []).push(n); else communs++;
|
||
}
|
||
|
||
const ligne = (bc) => {
|
||
const m = MODULES[bc];
|
||
return `| ${bc} | ${m.pack} | ${m.adr} | ${m.cellules} | ${m.med} mV | ${m.ev} |`;
|
||
};
|
||
const ordre = Object.keys(MODULES);
|
||
const tableau = ordre.map(ligne).join('\n');
|
||
|
||
fs.writeFileSync(path.join(OUT, 'LISEZ-MOI.md'), `# Relevés BMS Pylontech — installation Victron ESS
|
||
*Généré le ${new Date().toLocaleDateString('fr-FR')}*
|
||
|
||
## Français
|
||
|
||
Huit modules US2000C en deux packs de quatre reliés par un LV-HUB. Toutes les
|
||
valeurs ci-dessous sortent des BMS eux-mêmes, lues sur leur console série
|
||
(\`info\`, \`stat\`, \`soh\`, \`data … history\`, \`data … event\`).
|
||
|
||
| Code-barres | Pack | Adr. | Cellules déviantes | Écart médian | Événements |
|
||
|---|---|---:|---|---:|---:|
|
||
${tableau}
|
||
|
||
**Où regarder en premier** : \`2022-K220803C30160324\`, fichier
|
||
\`*-evenements-distant-*.csv\`, ligne du 23/07/2026 17:20 — la cellule 15 est à
|
||
2963 mV **à 84 % de charge** sous 6,5 A, quand ses quatorze voisines sont à
|
||
3291-3303 mV.
|
||
|
||
**Ce qui écarte une cause d'installation** : le module K220803C30160323 partage
|
||
la chaîne, les courants et les journées de deux modules atteints, et n'a
|
||
enregistré **aucun** événement en seize mois.
|
||
|
||
⚠️ **Horodatages** : les horloges internes des BMS avançaient de 6 h 09 à 6 h 13
|
||
au moment des relevés. **Tous les fichiers CSV de ce dossier sont déjà corrigés
|
||
à l'heure réelle (Europe/Paris)**. Les exports BatteryView \`*.txt\`, eux, portent
|
||
l'heure brute du module.
|
||
|
||
## English
|
||
|
||
Eight US2000C modules in two packs of four joined by an LV-HUB. Every value
|
||
below comes from the BMS units themselves, read over their serial console.
|
||
|
||
**Where to look first**: \`2022-K220803C30160324\`, file
|
||
\`*-evenements-distant-*.csv\`, row of 2026-07-23 17:20 — cell 15 sits at
|
||
2963 mV **at 84 % state of charge** under only 6.5 A, while its fourteen
|
||
neighbours are at 3291-3303 mV.
|
||
|
||
**What rules out an installation cause**: module K220803C30160323 shares the
|
||
chain, the currents and the days of two affected modules, and has recorded
|
||
**zero** events in sixteen months.
|
||
|
||
⚠️ **Timestamps**: the BMS internal clocks ran 6 h 09 to 6 h 13 fast. **All CSV
|
||
files here are already corrected to real local time (Europe/Paris).** The
|
||
BatteryView \`*.txt\` exports carry the raw module clock.
|
||
|
||
## 中文
|
||
|
||
八个 US2000C 模块,分为两组,每组四个,通过 LV-HUB 连接。以下所有数值均直接
|
||
读取自各模块 BMS 的串口控制台。
|
||
|
||
**建议优先查看**:\`2022-K220803C30160324\` 目录下的
|
||
\`*-evenements-distant-*.csv\`,2026-07-23 17:20 这一行 —— 在 **84 % 荷电状态**
|
||
下、仅 6.5 A 放电电流时,15 号电芯降至 2963 mV,而其余十四颗仍在
|
||
3291-3303 mV。
|
||
|
||
**可排除安装或使用原因的依据**:模块 K220803C30160323 与两个受损模块位于同一
|
||
通信链,经历相同电流与相同工况,十六个月内**没有任何**事件记录。
|
||
|
||
⚠️ **时间戳**:采集时各 BMS 内部时钟快 6 小时 09 分至 6 小时 13 分。**本目录中
|
||
所有 CSV 文件均已校正为真实当地时间(欧洲/巴黎)**;BatteryView 导出的
|
||
\`*.txt\` 文件仍为模块原始时钟。
|
||
|
||
## Fichiers / Files / 文件
|
||
|
||
- \`*-histo-distant-*.csv\` — historique, un point toutes les 30 min, 15 tensions de cellule
|
||
- \`*-evenements-distant-*.csv\` — journal d'événements, à la seconde, déclenchements uniquement
|
||
- \`*-console.txt\` — sorties \`info\`, \`stat\`, \`soh\`, \`pwr\` verbatim
|
||
- \`*_history_*.txt\`, \`*_event_*.txt\` — exports BatteryView d'origine (UTF-16)
|
||
- \`commun/\` — sessions console couvrant plusieurs modules a la fois, relevés
|
||
simultanés des trois modules du pack 2022, et captures d'écran BatteryView
|
||
`);
|
||
|
||
console.log(`Archive : ${OUT}`);
|
||
for (const bc of ordre) {
|
||
const n = (classe[bc] || []).length;
|
||
console.log(` ${MODULES[bc].pack}-${bc} ${String(n).padStart(2)} fichier(s) ${MODULES[bc].etat}`);
|
||
}
|
||
console.log(` commun ${String(communs).padStart(2)} fichier(s)`);
|
||
|
||
const tgz = `${OUT}.tar.gz`;
|
||
execFileSync('tar', ['czf', tgz, '-C', path.dirname(OUT), path.basename(OUT)]);
|
||
console.log(`\nArchive compressee : ${tgz} (${(fs.statSync(tgz).size / 1048576).toFixed(1)} Mo)`);
|