Parc reel : 8 US2000C en 2 packs de 4 avec hub, packs d'ages differents, un module en panne et isole (7 actifs), un autre qui faiblit. Consequence : batteryUsableCapacityKwh = 17,5 code en dur dans INPUT_PARSE surestime la reserve reelle de 15 a 20 %. Aucun capteur de capacite ou de sante batterie n'existe cote HA. Energie perdue faute de puits : la premiere estimation (23,9 kWh/jour, 38 %) etait fausse. Le facteur de recalage global de 1,22 est domine par les heures de 8-9 h ou il vaut 4 a 7. Probleme structurel : la censure est correlee au beau temps, donc les donnees manquantes ne le sont pas au hasard et aucun facteur appris sur cet echantillon n'est transportable. Cela invalide le plan initial de l'etape 3. Estimation retenue, borne basse sans recalage, plafonnee par l'enveloppe horaire reellement demontree : 11,8 kWh/jour en moyenne, 23 % de la ressource. On jette donc plus qu'on n'importe (7,83 kWh/jour) : l'energie existe, il manque le reservoir. +8 kWh utiles sont a la fois necessaires et remplissables. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
159 lines
9.5 KiB
Markdown
159 lines
9.5 KiB
Markdown
# Chantier — Bilan énergétique partagé
|
||
|
||
> Journal de bord du chantier ouvert le 24/08/2026. Documentation définitive à
|
||
> écrire à la fin ; ce fichier ne sert qu'à ne rien perdre en route.
|
||
|
||
## Pourquoi ce chantier
|
||
|
||
Constat du propriétaire, 24/08/2026 : « nous avons essayé de résoudre un défaut
|
||
de stratégie par une suite de solutions tactiques ». Trois oscillateurs
|
||
identifiés le même jour (règle de coupure EDF « Fix G », override d'abondance P6
|
||
qui détruisait sa propre condition d'autorisation, inversion des planchers de
|
||
démarrage et de maintien) — tous de la même nature : des seuils empilés par
|
||
couches successives, chacun défendable isolément, dont personne ne vérifiait la
|
||
cohérence d'ensemble. Chaque correctif créait l'oscillateur suivant.
|
||
|
||
**Toute valeur fixe est traitée comme une erreur de conception**, pas comme un
|
||
réglage à affiner.
|
||
|
||
## Décisions actées
|
||
|
||
| Sujet | Décision |
|
||
|---|---|
|
||
| Profil horaire | Recalculé une fois par jour, publié dans des helpers. Pas de recalcul dans la boucle 30 s. |
|
||
| Prudence | Percentile 20, appliqué **une seule fois sur le bilan net** (PV − conso par heure et par jour), jamais séparément sur chaque terme — sinon on cumule deux pessimismes et le déficit passe à 109 % de la batterie, système inutilisable. |
|
||
| SOC | Lissé pour les décisions de pilotage, valeur instantanée conservée pour les planchers de sécurité. |
|
||
| Consommation | Mesurée, jamais supposée. Filtrage contextuel. Mesure non biaisée. |
|
||
| Production PV | **Jamais la mesure brute.** Sans injection, `PV_mesurée = min(ressource, conso + absorption batterie)` : observation censurée dès que la batterie est pleine. Estimateur = prévision, recalée uniquement sur les heures non censurées. |
|
||
| Rétention historique | `recorder.purge_keep_days = 90` (appliqué le 24/08, redémarrage HA fait). Les statistiques long terme étaient déjà sans limite. |
|
||
| Conseiller IA | Les faits restent arithmétiques et déterministes ; l'advisor traite les hypothèses (facteur de confiance sur la prévision, lecture des états et alarmes, explication). Montée en pouvoir en trois paliers, sur un score de prédiction vérifié contre la mesure. |
|
||
|
||
## Sorties attendues du bilan
|
||
|
||
Heure de croisement PV/conso · énergie à couvrir d'ici là · niveau de batterie
|
||
requis (remplace `grid_soc_off` fixe) · marge disponible pour le véhicule ·
|
||
drapeau « production actuellement bridée » · drapeau de santé des mesures.
|
||
|
||
**Objectif ajouté le 24/08 : dimensionner le stockage.** Le propriétaire vise
|
||
l'autonomie et veut savoir combien de batteries ajouter. La ressource gaspillée
|
||
par la censure est précisément l'énergie qu'un stockage supplémentaire
|
||
capterait : le bilan doit donc produire, en plus, une estimation de l'énergie
|
||
perdue par manque de puits et le gain attendu par kWh de batterie ajouté.
|
||
Cela impose une simulation multi-jours sur la ressource *décensurée* — c'est
|
||
l'étape 3 qui la rend possible.
|
||
|
||
### Constat mesuré sur 27 jours (28/07 → 24/08)
|
||
|
||
| Grandeur | Moyenne / jour |
|
||
|---|---|
|
||
| Production PV (censurée, donc minorée) | 38,7 kWh |
|
||
| Consommation totale | 43,1 kWh (dont véhicule 10,0) |
|
||
| Décharge batterie | 11,5 kWh (p90 14,3 · max 16,1 sur 17,5 utiles) |
|
||
| **Import réseau** | **7,83 kWh** — un seul jour sur 27 à zéro |
|
||
|
||
La batterie se vide presque intégralement chaque jour : c'est elle le facteur
|
||
limitant, pas la puissance des onduleurs.
|
||
|
||
### Parc batterie réel (précisé le 24/08)
|
||
|
||
8 Pylontech US2000C **en deux packs de 4 avec un hub**, le premier pack ayant
|
||
deux ans de plus que le second. Un module est en panne et isolé : **le système
|
||
tourne actuellement sur 7**, et un huitième commence à faiblir. Le vieux pack a
|
||
vécu avant la climatisation du garage. Mélanger des packs d'âges différents est
|
||
déconseillé — contrainte de budget, pas choix technique.
|
||
|
||
Conséquence directe sur le code : `batteryUsableCapacityKwh: 17.5` est codé en
|
||
dur dans `INPUT_PARSE.js` et utilisé trois fois dans `WINDOWS_SOURCEV2.js`
|
||
(tampon de prévision, SOC projeté en fin de journée, cible du matin). Avec 7
|
||
modules dont un fatigué, la capacité réelle est plutôt de l'ordre de 14-15 kWh :
|
||
**le contrôleur surestime sa réserve d'environ 15 à 20 %.** Aucun capteur de
|
||
capacité ou de santé batterie n'existe côté HA — à publier depuis le BMS pour
|
||
que cette valeur cesse d'être une constante.
|
||
|
||
### Énergie perdue faute de puits — et pourquoi le recalage de la prévision échoue
|
||
|
||
Première estimation, avec un facteur de recalage global : 23,9 kWh/jour, 38 % de
|
||
la ressource. **Chiffre faux.** Le facteur global valait 1,22 mais il est
|
||
dominé par les heures de 8-9 h, où le recalage ressort à 4 voire 7 : la
|
||
prévision sous-estime massivement la rampe du matin. Or ces heures sont
|
||
sur-représentées parmi les heures exploitables, puisque la batterie y est
|
||
toujours vide.
|
||
|
||
Le problème est structurel : **la censure est corrélée au beau temps.** Les
|
||
heures exploitables de l'après-midi ne le sont que les jours médiocres — d'où
|
||
un recalage qui tombe à 0,24 l'après-midi, avec 1 à 5 échantillons. Les données
|
||
manquantes ne le sont pas au hasard, donc aucun facteur de recalage appris sur
|
||
cet échantillon n'est transportable. Cela invalide le plan initial de l'étape 3.
|
||
|
||
Estimation retenue à la place, **borne basse** : pour chaque heure censurée,
|
||
potentiel = min(prévision brute, enveloppe horaire réellement démontrée). Ne
|
||
suppose aucun recalage et ne dépasse jamais ce que l'installation a déjà produit
|
||
à cette heure-là.
|
||
|
||
| Perte par manque de puits (borne basse) | |
|
||
|---|---|
|
||
| Moyenne | **11,8 kWh/jour** (23 % de la ressource) |
|
||
| Médiane · p80 · max | 10,8 · 19,5 · 25,6 kWh |
|
||
| Jours sans perte | 2 sur 27 |
|
||
|
||
**Le résultat qui tranche la question du dimensionnement : on jette plus (11,8)
|
||
qu'on n'importe (7,83).** L'énergie existe déjà, il manque le réservoir et la
|
||
capacité à l'encaisser. Un ajout d'environ **+8 kWh utiles** est donc à la fois
|
||
nécessaire (côté demande) et remplissable (côté ressource). Réserve : chiffres
|
||
d'août ; l'historique de prévision remonte au 2 mars et permettra de refaire le
|
||
calcul en saison basse.
|
||
|
||
## Avancement
|
||
|
||
- [x] **Étape 1 — détection de la censure** (24/08). `src/energy-balance/` :
|
||
snapshot HA de 26 champs incluant les signaux jamais lus (états MPPT, état
|
||
VE.Bus, alarme de surcharge, ESS BatteryLife, état du bus DC, statut natif de
|
||
la borne, prévision horaire) et nœud `CENSORSHIP.js` qui qualifie chaque
|
||
échantillon. Suite `tests/energy-balance/` : 10 scénarios, dont un snapshot
|
||
réel du 24/08 14:29 correctement classé censuré. Mesure sur l'historique :
|
||
**48 % des heures de jour sont censurées, 77 à 96 % à partir de 13 h.**
|
||
- [x] **Étape 2 — profil de consommation mesuré** (24/08).
|
||
`src/energy-balance/CONSUMPTION_PROFILE.js` : compteurs d'énergie cumulés →
|
||
deltas horaires → distribution par heure de la journée → percentiles.
|
||
Validé sur 28 jours réels (639 heures, aucun compteur remis à zéro) :
|
||
consommation typique 31,9 kWh/jour hors véhicule, 42,8 kWh au p80. Le profil
|
||
tient dans un helper `input_text` (119 caractères sur 255).
|
||
Vérification préalable de la méthode : **seulement 7,8 % des heures de déficit
|
||
sont censurées** — censure et déficit sont physiquement presque exclusifs
|
||
(une heure censurée est une heure où la batterie n'avait plus de place, donc
|
||
une heure de surplus). La grandeur qui pilote la décision EDF est donc
|
||
mesurée sur des données propres.
|
||
- [ ] Étape 3 — estimateur de ressource PV = prévision recalée sur les heures
|
||
exploitables de l'étape 1.
|
||
- [ ] Étape 4 — bilan et ses sorties.
|
||
|
||
## Backlog
|
||
|
||
- [ ] **Doublon `unique_id: victron_vebus_dc_power`** — déclaré deux fois, avec
|
||
deux topics différents : `configuration.yaml:99`
|
||
(`system/0/Dc/Vebus/Power`) et `packages/victron_vebus_mqtt.yaml:63`
|
||
(`vebus/276/Dc/0/Power`). Vérifié le 24/08 : **les deux publient la même
|
||
grandeur** — un système VE.Bus en parallèle n'expose qu'une seule instance
|
||
D-Bus couvrant les deux onduleurs. Ce n'est donc pas un défaut de données,
|
||
seulement une ligne `ERROR` à chaque démarrage et un fichier qui ment sur ce
|
||
qu'il fait. Supprimer les lignes 62-68 du package, garder celle de
|
||
`configuration.yaml` (nom conforme à l'`entity_id` utilisé par `INPUT_PARSE`),
|
||
puis `mqtt.reload` — pas besoin de redémarrer.
|
||
- [ ] **`evcsDedicatedMaxW: 4900`** codé en dur dans `INPUT_PARSE.js`, appliqué
|
||
dès qu'EDF est absent (plafond ~20 A). Encore une valeur au jugé : à
|
||
confronter à la réalité du câblage du circuit dédié avant de la garder ou de
|
||
la remplacer par un helper.
|
||
- [ ] **Alarmes jamais lues** : `sensor.airtria_mpii_v1_overload_alarm`, alarme
|
||
« High charge current » du Battery Monitor (observée active le 24/08),
|
||
`sensor.gx_device_ess_batterylife_state` (peut imposer sa propre limite de
|
||
décharge à l'insu du contrôleur), `sensor.evcs_hq2239dnt7p_status`.
|
||
- [ ] **États MPPT jamais lus** (`sensor.airtria_mppt1_state`,
|
||
`sensor.mppt_450_200_hq2449yr9pt_state`) — indispensables : ils disent si un
|
||
échantillon de production est exploitable ou censuré.
|
||
- [ ] **Contrôle de vraisemblance `PV + VE.Bus = batterie`** — vérifié à 95 W
|
||
près le 24/08 (~9 %). À intégrer comme drapeau de santé permanent : le jour
|
||
où l'identité diverge, un capteur ment.
|
||
- [ ] **États zombies** `stop_source_lost` / `idle_wait_source` — noms
|
||
transitoires peu lisibles dans le journal et le tableau de bord (cf. HANDOFF
|
||
§24, hors périmètre à l'époque).
|