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 @@
+
+
+
+
+KXKM Batterie Parallelator
+
+
+ Battery Management Unit pour packs 24-30V en parallèle
+ Jusqu'à 32 batteries · ESP32-S3 · BLE + MQTT + InfluxDB · App iOS compagnon
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+> 🇬🇧 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
+