From bbb21021668f20badcb7016b35e201746b139510 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=27=C3=A9lectron=20rare?= <108685187+electron-rare@users.noreply.github.com> Date: Sat, 4 Jul 2026 12:58:53 +0200 Subject: [PATCH] docs: add French translation of README MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Context: the project README is written in English while the client (KompleX KapharnaüM) and field technicians are French-speaking. Approach: full translation of README.md into README.fr.md, keeping tables, badges, code blocks and anchors identical. Changes: - Add README.fr.md (complete French translation) - Cross-link to the English version at the top of the file Impact: French-speaking users get first-class documentation without diverging from the English source of truth. --- README.fr.md | 381 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 381 insertions(+) create mode 100644 README.fr.md diff --git a/README.fr.md b/README.fr.md new file mode 100644 index 0000000..4301c1c --- /dev/null +++ b/README.fr.md @@ -0,0 +1,381 @@ +

+ PCB BMU +

+ +

KXKM Batterie Parallelator

+ +

+ Battery Management Unit pour packs 24-30V en parallèle
+ Jusqu'à 32 batteries · ESP32-S3 · BLE + MQTT + InfluxDB · App iOS compagnon +

+ +

+ + CI + + + QA + + ESP-IDF + Licence + Tests +

+ +> 🇬🇧 English version: [README.md](README.md) + +--- + +## Vue d'ensemble + +Le **KXKM Batterie Parallelator** est une Battery Management Unit (BMU) embarquée qui met en parallèle, en toute sécurité, plusieurs packs de batteries (24-30V) pour des installations scéniques hors réseau. Chaque batterie est surveillée individuellement (tension, courant, température) et peut être déconnectée en quelques microsecondes via des interrupteurs MOSFET. + +Conçu par [L'Electron Rare](https://lelectronrare.fr) pour [KompleX KapharnaüM](https://komplex-kapharnaum.net) (Villeurbanne, France) — une compagnie d'arts vivants qui déploie de la scénographie numérique dans l'espace public, sans alimentation secteur. + +### Fonctionnalités clés + +| Fonctionnalité | Description | +|----------------|-------------| +| Protection par batterie | Détection sous/sur-tension, surintensité, déséquilibre | +| Reconnexion automatique | Backoff exponentiel avec verrouillage permanent après 5 défauts | +| Équilibrage doux (soft-balancing) | Duty-cycling avec mesure opportuniste de R_int | +| Intégration Victron | Instant Readout BLE + émulation GATT SmartShunt + scanner de périphériques | +| Interface tactile | Écran LVGL 320x240 avec grille batteries, SOH, graphiques | +| App iOS compagnon | Supervision temps réel en BLE, cache hors-ligne, accès par rôles | +| Télémétrie cloud | MQTT + InfluxDB + Grafana avec persistance hors-ligne | +| Mises à jour OTA | Double partition avec rollback automatique | + +--- + +## Démarrage rapide + +```bash +# Firmware ESP-IDF (production) +cd firmware-idf +source ~/esp/esp-idf/export.sh +idf.py build +idf.py -p /dev/cu.usbmodem* flash monitor + +# PlatformIO (Arduino legacy) +pio run -e kxkm-s3-16MB --target upload + +# Lancer tous les tests (aucun matériel requis) +pio test -e sim-host # 13 tests PlatformIO +cd firmware-idf && idf.py build # 13 tests host ESP-IDF + +# Stack cloud (serveur kxkm-ai) +cd kxkm-api && cp .env.example .env && docker compose up -d +``` + +--- + +## Architecture + +``` + ┌──────────────────────────┐ + │ ESP32-S3-BOX-3 │ + │ Écran LVGL 320x240 │ + │ NimBLE + WiFi │ + └─────────┬────────────────┘ + │ I2C 50kHz + ┌───────────────┼───────────────┐ + │ │ │ + ┌─────▼─────┐ ┌─────▼─────┐ ┌─────▼─────┐ + │ TCA9535 │ │ TCA9535 │ │ ...×8 │ + │ 4× MOSFET │ │ 4× LED │ │ │ + └─────┬─────┘ └───────────┘ └───────────┘ + │ + ┌─────▼─────┐ + │ INA237 ×4 │ ← par TCA (tension + courant) + └───────────┘ + + ┌──────────────────────────────────────────────────────┐ + │ Stack Cloud │ + │ BMU ──MQTT──► Mosquitto ──► Telegraf ──► InfluxDB │ + │ │ │ + │ iPhone ◄──BLE──► BMU Grafana ◄───────────┘ │ + │ iPhone ◄──REST──► FastAPI ◄─────────────────┘ │ + └──────────────────────────────────────────────────────┘ +``` + +### Composants firmware (ESP-IDF, 25 modules) + +| Composant | Rôle | +|-----------|------| +| `bmu_protection` | Machine à états : 5 états, 5 critères, verrouillage permanent | +| `bmu_balancer` | Soft-balancing par duty-cycling + mesure R_int | +| `bmu_ina237` | 16× moniteurs de puissance INA237 (shunt 2mΩ) | +| `bmu_tca9535` | 8× expanders GPIO (interrupteurs + LEDs) | +| `bmu_ble` | NimBLE 4 services GATT + Victron SmartShunt | +| `bmu_ble_victron` | Victron Instant Readout (advertising chiffré AES-CTR) | +| `bmu_ble_victron_scan` | Scanner BLE central pour périphériques Victron | +| `bmu_display` | LVGL : grille batteries, infos pack, SOH, graphiques, swipe | +| `bmu_influx` + `_store` | Client InfluxDB + persistance hors-ligne FAT/SD | +| `bmu_mqtt` | ESP-MQTT avec identifiants d'authentification | +| `bmu_vedirect` | Parseur UART Victron VE.Direct (chargeur solaire) | +| `bmu_rint` | Mesure de résistance interne par impulsion | +| `bmu_web` | HTTP + WebSocket avec auth par token + rate limiting | +| `bmu_config` | Config runtime NVS + clés périphériques Victron | +| `bmu_storage` | NVS, FAT, SPIFFS, carte SD, USB MSC | +| `bmu_ota` | Mise à jour firmware OTA avec rollback | + +### Logique de protection + +``` +Nb_switch < 5 → Reconnexion immédiate dès que la condition disparaît +Nb_switch == 5 → Délai de 10 secondes avant reconnexion +Nb_switch > 5 → Verrouillage permanent (LED rouge clignotante) jusqu'au redémarrage +``` + +| Seuil | Défaut | Configurable | +|-------|--------|:------------:| +| Tension min | 24 000 mV | via Kconfig + NVS | +| Tension max | 30 000 mV | via Kconfig + NVS | +| Courant max | 10 000 mA | via Kconfig + NVS | +| Déséquilibre | 1 000 mV | via Kconfig + NVS | +| Délai de reconnexion | 10 000 ms | via Kconfig | +| Limite de commutations | 5 | via Kconfig | + +### Comportement des LEDs + +| État | LED | +|------|-----| +| Connectée | Vert fixe | +| Déconnectée | Rouge fixe | +| Erreur | **Rouge clignotant** (~1 Hz) | +| Verrouillée | Rouge fixe | + +--- + +## App iOS compagnon + +

+ KXKM BMU — SwiftUI + CoreBluetooth +

+ +| Fonctionnalité | Transport | +|----------------|-----------| +| Tableau de bord batteries temps réel | BLE (poll 2s) | +| Détail batterie + graphique de tension | BLE | +| Interrupteur ON/OFF + reset | BLE (selon rôle) | +| Config protection (pas de 0,025 V/A) | BLE | +| Config WiFi de la BMU | BLE | +| Journal d'audit + filtrage | SQLDelight local | +| Mode hors-ligne avec indicateur de cache | Bascule automatique | +| Tableau de bord SOH + R_int | BLE + REST | +| Scan des périphériques Victron | BLE passif | + +**3 rôles** : Admin (complet), Technicien (contrôle), Observateur (lecture seule) — PIN + Face ID. + +**Code** : `iosApp/` (Xcode, CoreBluetooth) + `kxkm-bmu-app/` (module Kotlin partagé KMP) + +--- + +## Intégration BLE Victron + +La BMU interagit avec l'écosystème Victron via trois mécanismes : + +| Mécanisme | Direction | Protocole | +|-----------|-----------|-----------| +| Instant Readout | BMU → VictronConnect | Advertising chiffré AES-CTR (PID 0xA389) | +| GATT SmartShunt | BMU → tout client BLE | 9 caractéristiques en lecture seule (V, I, SOC, Ah, TTG, T, alarme) | +| Scanner de périphériques | Périphériques Victron → BMU | Scan BLE passif, déchiffrement AES, cache 8 périphériques | + +Types d'enregistrements Victron supportés : Solar (0x01), Battery (0x02), Inverter (0x03), DC-DC (0x04). + +--- + +## Infrastructure cloud + +Stack Docker sur le serveur `kxkm-ai` : + +| Service | Port | Rôle | +|---------|------|------| +| Mosquitto | 1883, 9001 | Broker MQTT (authentifié) | +| InfluxDB 2.7 | 8086 | Stockage séries temporelles (org=kxkm, bucket=bmu) | +| Telegraf | - | Passerelle MQTT → InfluxDB | +| FastAPI | 8400 | API REST (sync, historique, audit) | +| Grafana 11 | 3001 | 3 tableaux de bord (live, flotte, solaire) | + +**Installation** : `cp .env.example .env` — renseigner tous les secrets (clé API, token InfluxDB, identifiants MQTT, mot de passe Grafana, origines CORS). Tous les secrets passent par des variables d'environnement `${...}`, `chmod 600 .env`. + +**Résilience hors-ligne** : quand le WiFi/InfluxDB est injoignable, la télémétrie est persistée en flash FAT interne (`/fatfs/influx/`) avec rotation sur 2 fichiers (512 Ko chacun). Rejeu automatique à la reconnexion. + +--- + +## Tests + +**26 tests au total** — aucun matériel requis. + +### PlatformIO sim-host (13 tests) + +```bash +pio test -e sim-host +``` + +| Suite | Tests | Couvre | +|-------|:-----:|--------| +| `test_protection` | 10 | Machine à états V/I/déséquilibre/verrouillage | +| `test_battery_route_validation` | - | Bornes d'index + vérifications d'état | +| `test_influx_buffer_codec` | - | Encodage line-protocol InfluxDB | +| `test_web_mutation_rate_limit` | 3 | Fenêtre glissante + multi-IP | +| `test_web_route_security` | 9 | Token en temps constant + Bearer | +| `test_ws_auth_flow` | 7 | Auth combinée + rate limit | +| `test_mqtt_influx_codec` | 3 | JSON MQTT + parsing des topics | +| `test_emulation_bench` | - | Benchmark d'émulation | + +### Tests host ESP-IDF (13 tests) + +```bash +cd firmware-idf && idf.py build +``` + +| Suite | Tests | Couvre | +|-------|:-----:|--------| +| `test_protection` | 13 | Machine à états complète (ESP-IDF) | +| `test_victron_gatt` | 8 | Encodage GATT (V, SOC, alarme, TTG, T) | +| `test_victron_scan` | 5 | Parsing des trames, expiration, MAC, CID | +| `test_ble_victron` | - | Encodage des trames batterie/solaire | +| `test_vedirect_parser` | - | Parsing des trames VE.Direct | +| `test_rint` | - | Calcul de R_int | +| `test_config_labels` | - | Gestion des étiquettes batterie | +| `test_vrm_topics` | - | Génération des topics VRM | + +### Pipelines CI/CD + +| Pipeline | Déclencheur | Gate | +|----------|-------------|------| +| `ci.yml` | push/PR | 13 tests sim-host au vert | +| `sim-host-tests.yml` | push/PR | + build S3 + RAM ≤75% + Flash ≤85% | +| `esp-idf-ci.yml` | push/PR | + tests host ESP-IDF + flash ≤85% des 2 Mo OTA | + +**Occupation flash actuelle** : 81 % (1,69 Mo / 2 Mo de partition OTA) — 19 % de marge. + +--- + +## Audit de sécurité + +**Tous les constats résolus** au 2026-04-07. + +
+Phase 1 — Migration (mars 2026) : 7/7 résolus + +| ID | Constat | Statut | +|----|---------|--------| +| CRIT-001 | Appels de fonctions obsolètes | ✅ | +| CRIT-002 | Variable globale Nb_INA non fiable | ✅ | +| CRIT-003 | Accès I2C sans mutex | ✅ | +| CRIT-004 | Initialisation de mutex manquante | ✅ | +| HIGH-005 | Race condition WebSocket V/I | ✅ | +| HIGH-006 | Race condition reconnect_time | ✅ | +| HIGH-007 | Globales non initialisées | ✅ | + +
+ +
+Phase 2 — Audit approfondi (mars-avril 2026) : 13/13 résolus + +| ID | Sévérité | Constat | Correctif | +|----|----------|---------|-----------| +| CRIT-A | Critique | Incohérence d'unités mV/V | ESP-IDF : mV partout | +| CRIT-B | Critique | Déséquilibre comparé à la config au lieu du max de flotte | bmu_protection | +| CRIT-C | Critique | Deadlock dans le switch web | bmu_web | +| CRIT-D | Critique | Routes non authentifiées | bmu_web_security | +| HIGH-1 | Haute | Surintensité négative ignorée | Facteur bidirectionnel | +| HIGH-2 | Haute | WebSocket non authentifié | Token sur la première trame | +| HIGH-3 | Haute | XSS dans /log | Vérification null cJSON | +| HIGH-4 | Haute | MQTT en clair | Auth Mosquitto + .env | +| HIGH-5 | Haute | Changement de vitesse I2C non protégé | I2CLockGuard | +| HIGH-7 | Haute | battery_voltages[] public | state_mutex | +| HIGH-8 | Haute | Crash de la tâche Influx si la SD échoue | Repli influx_store | +| MED-1 | Moyenne | Pas de verrouillage permanent (F08) | BMU_STATE_LOCKED | +| MED-010 | Moyenne | Harmonisation mV/V | mV partout | + +
+ +
+Audit infrastructure (avril 2026) : 5/5 résolus + +| Constat | Correctif | +|---------|-----------| +| Accès anonyme Mosquitto | Auth + fichier de mots de passe | +| Secrets en dur dans docker-compose | Tout via .env (chmod 600) | +| Token InfluxDB par défaut | Régénéré (44 caractères aléatoires) | +| CORS allow_origins=["*"] | Restreint via variable d'environnement | +| Perte de données hors-ligne | Persistance FAT/SD + rejeu | + +
+ +--- + +## Matériel + +### Révisions du PCB + +| Version | Statut | Fichiers | +|---------|--------|----------| +| BMU v1 | Fabriquée | `hardware/PCB/` | +| BMU v2 | Prête pour production (ERC 0, BOM 107) | `hardware/pcb-bmu-v2/` | + +### Circuits intégrés clés + +| CI | Boîtier | Rôle | Adresse I2C | +|----|---------|------|-------------| +| INA237 | VSSOP-10 | Moniteur de puissance (V/I/P) | 0x40-0x4F (16 max) | +| TCA9535 | TSSOP-24 | Expander GPIO (interrupteurs + LEDs) | 0x20-0x27 (8 max) | +| ISO1540 | SOIC-8 | Isolateur I2C galvanique | - | +| IRF4905 | D2PAK | MOSFET canal P (55V, 74A) | - | + +### Cartographie I2C + +``` +TCA_0 (0x20) → INA 0x40-0x43 → Batteries 1-4 +TCA_1 (0x21) → INA 0x44-0x47 → Batteries 5-8 +TCA_2 (0x22) → INA 0x48-0x4B → Batteries 9-12 +TCA_3 (0x23) → INA 0x4C-0x4F → Batteries 13-16 +``` + +Contrainte topologique : `Nb_TCA × 4 == Nb_INA` — toute incohérence déclenche le fail-safe (tout OFF). + +--- + +## Structure du projet + +``` +KXKM_Batterie_Parallelator/ +├── firmware-idf/ # Firmware ESP-IDF 5.4 (25 composants) +│ ├── components/ # Composants ESP-IDF modulaires +│ ├── main/ # Point d'entrée app_main +│ └── test/ # Tests host Unity (13 suites) +├── firmware/ # Firmware PlatformIO/Arduino legacy +│ ├── src/ # Modules source +│ ├── test/ # Tests sim-host (8 suites, 13 tests) +│ └── lib/INA237/ # Fork local du driver INA237 +├── iosApp/ # App iOS SwiftUI (CoreBluetooth) +├── kxkm-bmu-app/ # Module Kotlin partagé KMP +│ └── shared/ # Logique métier multiplateforme +├── kxkm-api/ # Stack Docker (Mosquitto, InfluxDB, FastAPI, Grafana) +├── hardware/ # Schémas KiCad + Gerbers (v1 + v2) +├── specs/ # Gates Kill_LIFE (S0-S3) +├── docs/ # Specs, plans, gouvernance, recherche +├── grafana/dashboards/ # 3 dashboards Grafana JSON +└── scripts/ # CI, QA, pipeline ML +``` + +--- + +## À propos de KompleX KapharnaüM + +[KompleX KapharnaüM](https://komplex-kapharnaum.net) est une compagnie d'arts vivants basée à Villeurbanne (Lyon, France), active depuis plus de 20 ans dans les arts de rue, le spectacle vivant et la création numérique. La compagnie développe sa propre plateforme matérielle embarquée (K32, à base d'ESP32) et maintient des outils open source sur [GitHub](https://github.com/KomplexKapharnaum). + +--- + +## Licence + +[GNU General Public License v3.0](LICENSE) + +--- + +

+ Construit avec ESP-IDF, LVGL, NimBLE, SwiftUI, FastAPI, InfluxDB et Grafana.
+ Développé par L'Electron Rare pour KompleX KapharnaüM +