Le reseau ne prend plus la place du solaire, batterie preneuse

Nuit complete + deux campagnes alternees apres la correction de la consigne
reseau (4200 -> 50 W) : l'import colle a la consommation, la production monte
librement contacteur ferme, et les transitions locales donnent +0,5 % et
+13,1 % la ou le 27/08 mesurait -73 %.

Le transitoire de fermeture est caracterise : le reseau reprend toute la maison
et le solaire bascule vers la batterie, puis l'import retombe a la consigne en
~2 min 15 (25 W, 52 W). Cout ~50-60 Wh par fermeture.

Outillage : tools/test-edf-alterne.mjs (protocole alterne, restauration
garantie) et tools/analyse-test-alterne.mjs. Deux pieges d'instrumentation
corriges -- garde meteo quand les phases ouvertes divergent entre elles, et
biais du parseur qui laissait tomber les lignes ou le premier tracker etait
bride.

Reste ouvert : le cas batterie pleine, celui que le proprietaire designe comme
decisif, ou le solaire n'a plus de destination quand le reseau reprend la maison.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
This commit is contained in:
Tallagrand Thierry
2026-08-31 11:23:35 +02:00
parent aa83b5c3d9
commit 40f34418d6
5 changed files with 570 additions and 0 deletions

View File

@@ -1670,3 +1670,133 @@ mêler au diagnostic.
--- ---
*Document mis à jour le : 30/08/2026 — consigne réseau 4200 W et SOC minimal ESS 40 % identifiés comme propriétaires non lus de la décision réseau ; procédure d'intervention rédigée* *Document mis à jour le : 30/08/2026 — consigne réseau 4200 W et SOC minimal ESS 40 % identifiés comme propriétaires non lus de la décision réseau ; procédure d'intervention rédigée*
## 28. Session du 31/08/2026 — La substitution ne se reproduit plus (batterie preneuse). Cas « batterie pleine » encore ouvert
Première vérification de la correction de la consigne réseau (4200 → 50 W,
§27), sur une nuit complète puis deux campagnes alternées.
### La nuit 30-31/08 : l'import colle à la consommation
Une seule session réseau, `switch.edf_general_ok_switch` ON à **05:04:10**
(hystérésis, SOC 21 ≤ seuil 20) et OFF à **10:08:04** (SOC 30 ≥ seuil OFF).
Aucun rebond, aucun créneau.
| heure | import réseau | conso maison | courant batterie |
|---|---:|---:|---:|
| 05:15 | 780 W | 732 W | 0 A |
| 06:30 | 507 W | 477 W | −1 A |
| 07:45 | 781 W | 751 W | +4 A |
À comparer au test du 27/08 10:47 où, pour 877 W de consommation, l'import
montait en rampe jusqu'à **4113 W** pour gaver la batterie. Le comportement a
disparu. Détail de la fermeture : de 05:04 à 05:13 l'import est resté à
**24-56 W** (la consigne) pendant que la batterie continuait de servir la maison
à −15 A ; à 05:14, SOC atteignant le plancher ESS de 20 %, l'ESS a basculé —
import = charge maison, batterie à 0 A, SOC plat à 20 % jusqu'à 08:00. Manuel.
### Le matin : réseau présent, production libre
De 08:40 à la coupure de 10:08, contacteur toujours fermé :
| heure | PV | import | conso | I batterie |
|---|---:|---:|---:|---:|
| 08:45 | 1 303 W | **18 W** | 1 109 W | +2 A |
| 09:25 | 3 425 W | **39 W** | 805 W | +50 A |
| 10:05 | **5 244 W** | **47 W** | 952 W | +83 A |
`sensor.mppt_450_200_hq2449yr9pt_mppt_operation_mode` est resté `mppt_active`
sur toute la fenêtre : le chargeur déclare lui-même chercher son point de
puissance maximale pendant que le réseau est présent.
### Campagnes alternées (`tools/test-edf-alterne.mjs`)
Journaux : `docs/mesures/20260831-1043-test-edf-alterne.log` (phases 180 s) et
`20260831-1101-test-edf-alterne.log` (phases 240 s).
Transitions exploitables, chaque phase fermée contre ses voisines ouvertes :
| phase | PV fermée | PV voisines ouvertes | écart | trackers bridés |
|---|---:|---:|---:|---:|
| 10:47 ON_1 | 7 168 W | 7 131 W | **+0,5 %** | 2,7/7 (DVCC, I=124 A) |
| 11:13 ON_2 | 7 920 W (max 8 759) | 7 002 W | **+13,1 %** | 4,5/7 (DVCC, I=125 A) |
Le 27/08, la même manœuvre faisait tomber la PV de 3 885 à 1 045 W en 90 s avec
six trackers sur sept en `voltage_current_limited`. **La substitution ne se
reproduit plus à batterie preneuse.** Le bridage résiduel observé est le bridage
NORMAL : il apparaît quand le courant batterie approche la limite DVCC (125 sur
130 A) et il s'accompagne d'un import réseau nul — critère de discrimination
utilisable : bridage normal ⇒ import nul ; bridage anormal ⇒ l'import remplace
la production.
### Mécanisme identifié : un transitoire de reprise, qui retombe à la consigne
À chaque fermeture du contacteur, le réseau reprend d'un coup **toute** la charge
de la maison et la totalité du solaire bascule vers la batterie. Bilan vérifié au
watt près (10:48:15 : PV 7222 + grid 2120 − conso 2249 = 7093 W contre 7107 W de
charge batterie mesurée). Puis l'import **décroît jusqu'à la consigne** :
| campagne | import à la fermeture | après ~2 min 15 |
|---|---:|---:|
| 11:05 ON_1 | 1 985 W | **25 W**, stable |
| 11:13 ON_2 | 2 600 W | **52 W** puis −41 W |
Coût ≈ 50-60 Wh par fermeture. Avec l'ancienne consigne à 4200 W, cette reprise
n'avait aucune raison de redescendre : elle se stabilisait sur « le réseau
alimente tout, on bride le solaire pour faire de la place ». C'est
vraisemblablement le même mécanisme, dont la correction de consigne a rétabli
l'extinction. Corollaire : chaque fermeture coûte, ce qui plaide pour une
session réseau unique et dimensionnée plutôt que des créneaux répétés.
Note : aucun transitoire à la fermeture de 05:04 (PV nulle) — il n'y a rien à
rediriger quand il n'y a pas de solaire.
### CE QUI N'EST TOUJOURS PAS TESTÉ — batterie pleine (à faire)
Tout ce qui précède s'est mesuré à SOC 40-54 %, batterie absorbant 60 à 125 A.
Le propriétaire maintient, sur plusieurs mois d'observation, que le cas décisif
est **batterie pleine** : plus de tampon, donc le solaire qui alimentait la
maison n'a plus de destination quand le réseau la reprend. Discrimination
attendue, contacteur fermé, maison ~2 kW, SOC ≥ 90 % :
| observation | conclusion |
|---|---|
| PV ≈ conso (~2 kW), import ≈ 50 W | corrigé — écrêtage normal, le solaire sert la maison |
| PV ≈ 0-1 kW, import ≈ conso | non corrigé — éviction ; VEConfigure (§27, `docs/PROCEDURE_ESS_PARALLELE.md` étape 1) |
Le 27/08 à 11:38, SOC 86-88 %, batterie n'acceptant plus que ~1 kW, on avait
PV 1043 W pour une maison à 2258 W et un import de 2287 W : le solaire SOUS la
consommation et le réseau AU-DESSUS. C'est le point le plus proche du cas
décisif dont on dispose, et il est du mauvais côté. Trois minutes de protocole
alterné à SOC ≥ 90 suffiront à trancher.
### Outillage ajouté
- `tools/test-edf-alterne.mjs` — protocole alterné OFF/ON/OFF/ON/OFF, phases et
pas d'échantillonnage paramétrables. Mesure PV, tension et courant batterie,
conso, import, SOC, limite DVCC, présence physique AC-IN et le mode des 7
chargeurs solaires. **Désactive l'hystérésis pendant le test et restaure tout
à la fin, sur Ctrl-C et sur erreur.** Journal horodaté dans `docs/mesures/`.
- `tools/analyse-test-alterne.mjs` — résumé par phase et verdict.
Deux pièges d'instrumentation corrigés en cours de route, à ne pas réintroduire :
1. **Garde météo.** Les phases OUVERTES voient toutes la même ressource : si
elles divergent entre elles (33 % et 42 % sur les deux campagnes du 31/08),
la moyenne ON contre OFF est ininterprétable. L'outil refuse désormais de
conclure dans ce cas et compare chaque phase fermée à ses voisines
immédiates. C'est ce piège qui avait pollué le premier test du 27/08.
Contrôle interne utile : si la PV chute AVANT l'apparition de l'import, ce
sont des nuages (cas de la phase ON_2 du 31/08 10:53, chute 6995 → 3607 W
avec l'import encore à zéro).
2. **Biais du parseur.** La lecture des modes MPPT était ancrée sur `MPPT `, ce
qui faisait tomber en silence toute ligne dont le PREMIER tracker était bridé
— précisément les échantillons à mesurer — et biaisait le résultat vers
« aucun bridage ». Le bloc de modes est le dernier champ : l'ancrer sur
`edf on|off`, jamais sur le mot `MPPT`.
### Signal indépendant : la jauge de SOC s'effondre en bas d'échelle
Entre 04:00 et 04:20, le SOC est passé de **30 à 22 %** alors que la batterie ne
débitait que ~11 A (≈ 550 W), tension stable à 49 V. Huit points sur un parc de
~15 kWh représentent 1,2 kWh, soit plus de deux heures à ce débit — pas vingt
minutes. La jauge ne mesure plus, elle réestime. Comportement classique d'un
parc vieillissant près du genou de décharge, cohérent avec le module en panne
connu (7 modules actifs sur 8, cf. MANUEL §0).
Conséquence : tous les seuils des deux workflows (20, 30, 22, 35) sont exprimés
dans une grandeur non linéaire en bas d'échelle. À verser au chantier du bilan
énergétique ; ne pas « corriger » par un seuil de plus.
---
*Document mis à jour le : 31/08/2026 (~11:30) — substitution non reproduite à batterie preneuse (nuit + 2 campagnes alternées) ; transitoire de fermeture caractérisé et retombant à la consigne ; cas batterie pleine à tester*

View File

@@ -0,0 +1,72 @@
TEST ALTERNE EDF <-> MPPT — 31/08/2026 10:43:54
phases 180s, echantillon 15s, sequence OFF_1 / ON_1 / OFF_2 / ON_2 / FIN_OFF
etat initial : edf off | latch off | hysteresis on
consigne reseau 50 W | SOC min ESS 20 % | limite active 20.0 %
MPPT ordre: mppt1 rs_1 rs_2 rs_3 rs_4 rs_g v1 (MPPT=cherche le max, lim_=se retient)
10:43:56 | OFF_1 | PV 7353 | U 50.13 | I 97.3 | conso 2270 | grid 0 | SOC 39 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
10:44:11 | OFF_1 | PV 6985 | U 50.15 | I 95.8 | conso 2258 | grid 0 | SOC 40 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
10:44:26 | OFF_1 | PV 6710 | U 50.16 | I 91.3 | conso 2276 | grid 0 | SOC 40 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
10:44:41 | OFF_1 | PV 6216 | U 50.12 | I 75.5 | conso 2309 | grid 0 | SOC 40 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
10:44:56 | OFF_1 | PV 6749 | U 50.10 | I 70.7 | conso 2246 | grid 0 | SOC 40 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
10:45:11 | OFF_1 | PV 6683 | U 50.17 | I 91.3 | conso 2263 | grid 0 | SOC 40 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
10:45:26 | OFF_1 | PV 5462 | U 50.10 | I 67.8 | conso 2252 | grid 0 | SOC 40 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
10:45:42 | OFF_1 | PV 5423 | U 50.08 | I 64.4 | conso 2270 | grid 0 | SOC 40 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
10:45:57 | OFF_1 | PV 6697 | U 50.10 | I 74.8 | conso 2268 | grid 0 | SOC 40 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
10:46:12 | OFF_1 | PV 6911 | U 50.12 | I 78.3 | conso 2264 | grid 0 | SOC 40 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
10:46:27 | OFF_1 | PV 7168 | U 50.18 | I 97.2 | conso 2246 | grid 0 | SOC 40 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
10:46:42 | OFF_1 | PV 7498 | U 50.19 | I 96.0 | conso 2272 | grid 0 | SOC 40 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
>>> EDF ON
10:47:00 | ON_1 | PV 7278 | U 50.21 | I 98.9 | conso 2252 | grid 0 | SOC 41 | DVCC 130A/51.5V | acin 1 | edf on | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
10:47:15 | ON_1 | PV 7169 | U 50.23 | I 99.0 | conso 2244 | grid 0 | SOC 41 | DVCC 130A/51.5V | acin 1 | edf on | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
10:47:30 | ON_1 | PV 7447 | U 50.22 | I 95.3 | conso 2286 | grid 0 | SOC 41 | DVCC 130A/51.5V | acin 1 | edf on | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
10:47:45 | ON_1 | PV 7327 | U 50.22 | I 94.5 | conso 2300 | grid 0 | SOC 41 | DVCC 130A/51.5V | acin 1 | edf on | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
10:48:00 | ON_1 | PV 7221 | U 50.22 | I 95.4 | conso 2252 | grid 0 | SOC 41 | DVCC 130A/51.5V | acin 1 | edf on | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
10:48:15 | ON_1 | PV 7222 | U 50.37 | I 141.1 | conso 2249 | grid 2120 | SOC 41 | DVCC 130A/51.5V | acin 1 | edf on | volt volt volt volt MPPT volt volt
10:48:30 | ON_1 | PV 6884 | U 50.36 | I 129.1 | conso 2245 | grid 1914 | SOC 41 | DVCC 130A/51.5V | acin 1 | edf on | volt volt volt volt MPPT volt volt
10:48:45 | ON_1 | PV 7087 | U 50.37 | I 126.8 | conso 2252 | grid 1727 | SOC 41 | DVCC 130A/51.5V | acin 1 | edf on | volt MPPT MPPT MPPT MPPT volt volt
10:49:00 | ON_1 | PV 7331 | U 50.37 | I 126.0 | conso 2309 | grid 1556 | SOC 42 | DVCC 130A/51.5V | acin 1 | edf on | volt volt volt volt MPPT volt volt
10:49:15 | ON_1 | PV 7458 | U 50.37 | I 124.4 | conso 2228 | grid 1248 | SOC 42 | DVCC 130A/51.5V | acin 1 | edf on | volt MPPT MPPT MPPT MPPT MPPT MPPT
10:49:30 | ON_1 | PV 7520 | U 50.37 | I 122.8 | conso 2293 | grid 1117 | SOC 42 | DVCC 130A/51.5V | acin 1 | edf on | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
10:49:45 | ON_1 | PV 6730 | U 50.35 | I 115.5 | conso 2271 | grid 886 | SOC 42 | DVCC 130A/51.5V | acin 1 | edf on | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
>>> EDF OFF
10:50:04 | OFF_2 | PV 7329 | U 50.32 | I 108.6 | conso 2254 | grid 0 | SOC 42 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
10:50:19 | OFF_2 | PV 6540 | U 50.28 | I 99.0 | conso 2397 | grid 0 | SOC 42 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
10:50:34 | OFF_2 | PV 7382 | U 50.25 | I 93.0 | conso 2338 | grid 0 | SOC 42 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
10:50:49 | OFF_2 | PV 7356 | U 50.28 | I 99.0 | conso 2240 | grid 0 | SOC 42 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
10:51:04 | OFF_2 | PV 7639 | U 50.28 | I 99.8 | conso 2243 | grid 0 | SOC 42 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
10:51:19 | OFF_2 | PV 7381 | U 50.28 | I 101.0 | conso 2240 | grid 0 | SOC 43 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
10:51:34 | OFF_2 | PV 7508 | U 50.27 | I 98.2 | conso 2257 | grid 0 | SOC 43 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
10:51:49 | OFF_2 | PV 7700 | U 50.27 | I 100.2 | conso 2331 | grid 0 | SOC 43 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
10:52:04 | OFF_2 | PV 7879 | U 50.28 | I 101.6 | conso 2305 | grid 0 | SOC 43 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
10:52:19 | OFF_2 | PV 7570 | U 50.29 | I 103.3 | conso 2328 | grid 0 | SOC 43 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
10:52:34 | OFF_2 | PV 7853 | U 50.29 | I 103.3 | conso 2311 | grid 0 | SOC 43 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
10:52:49 | OFF_2 | PV 7899 | U 50.30 | I 106.8 | conso 2309 | grid 0 | SOC 43 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
>>> EDF ON
10:53:07 | ON_2 | PV 6995 | U 50.30 | I 103.0 | conso 2329 | grid 0 | SOC 43 | DVCC 130A/51.5V | acin 1 | edf on | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
10:53:22 | ON_2 | PV 5384 | U 50.22 | I 80.6 | conso 2822 | grid 0 | SOC 43 | DVCC 130A/51.5V | acin 1 | edf on | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
10:53:37 | ON_2 | PV 4032 | U 50.01 | I 23.6 | conso 2793 | grid 0 | SOC 44 | DVCC 130A/51.5V | acin 1 | edf on | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
10:53:52 | ON_2 | PV 3607 | U 49.91 | I 6.9 | conso 2825 | grid 0 | SOC 44 | DVCC 130A/51.5V | acin 1 | edf on | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
10:54:07 | ON_2 | PV 3686 | U 49.87 | I 11.4 | conso 2804 | grid 0 | SOC 44 | DVCC 130A/51.5V | acin 1 | edf on | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
10:54:22 | ON_2 | PV 3707 | U 50.03 | I 70.3 | conso 2874 | grid 2717 | SOC 44 | DVCC 130A/51.5V | acin 1 | edf on | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
10:54:37 | ON_2 | PV 3794 | U 50.06 | I 63.8 | conso 2926 | grid 2598 | SOC 44 | DVCC 130A/51.5V | acin 1 | edf on | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
10:54:52 | ON_2 | PV 3037 | U 50.05 | I 57.4 | conso 2719 | grid 2221 | SOC 44 | DVCC 130A/51.5V | acin 1 | edf on | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
10:55:07 | ON_2 | PV 2968 | U 50.01 | I 43.8 | conso 2731 | grid 1956 | SOC 44 | DVCC 130A/51.5V | acin 1 | edf on | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
10:55:22 | ON_2 | PV 3078 | U 49.98 | I 39.8 | conso 2739 | grid 1760 | SOC 44 | DVCC 130A/51.5V | acin 1 | edf on | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
10:55:37 | ON_2 | PV 3603 | U 49.98 | I 43.8 | conso 2767 | grid 1555 | SOC 44 | DVCC 130A/51.5V | acin 1 | edf on | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
10:55:52 | ON_2 | PV 4702 | U 50.00 | I 50.1 | conso 2741 | grid 1343 | SOC 44 | DVCC 130A/51.5V | acin 1 | edf on | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
>>> EDF OFF
10:56:11 | FIN_OFF| PV 4788 | U 50.07 | I 65.7 | conso 2664 | grid 0 | SOC 44 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
10:56:26 | FIN_OFF| PV 5765 | U 50.02 | I 51.7 | conso 2682 | grid 0 | SOC 44 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
10:56:41 | FIN_OFF| PV 5249 | U 50.00 | I 44.5 | conso 2634 | grid 0 | SOC 44 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
10:56:56 | FIN_OFF| PV 4821 | U 49.96 | I 36.0 | conso 2664 | grid 0 | SOC 44 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
10:57:11 | FIN_OFF| PV 6658 | U 49.98 | I 45.1 | conso 2642 | grid 0 | SOC 44 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
10:57:26 | FIN_OFF| PV 7882 | U 50.15 | I 93.1 | conso 2644 | grid 0 | SOC 44 | DVCC 130A/51.5V | acin 0 | edf off | volt MPPT MPPT MPPT MPPT MPPT MPPT
10:57:41 | FIN_OFF| PV 5740 | U 50.26 | I 114.8 | conso 2360 | grid 0 | SOC 44 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
10:57:56 | FIN_OFF| PV 5774 | U 50.12 | I 61.2 | conso 2327 | grid 0 | SOC 45 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
10:58:11 | FIN_OFF| PV 4755 | U 50.10 | I 61.2 | conso 2336 | grid 0 | SOC 45 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
10:58:26 | FIN_OFF| PV 4824 | U 50.04 | I 48.1 | conso 2350 | grid 0 | SOC 45 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
10:58:41 | FIN_OFF| PV 5987 | U 50.05 | I 55.6 | conso 2345 | grid 0 | SOC 45 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
10:58:56 | FIN_OFF| PV 6074 | U 50.09 | I 67.5 | conso 2381 | grid 0 | SOC 45 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
>>> RESTAURATION (fin de campagne)
>>> etat restaure : edf off | latch off | hysteresis on

View File

@@ -0,0 +1,92 @@
TEST ALTERNE EDF <-> MPPT — 31/08/2026 11:01:00
phases 240s, echantillon 15s, sequence OFF_1 / ON_1 / OFF_2 / ON_2 / FIN_OFF
etat initial : edf off | latch off | hysteresis on
consigne reseau 50 W | SOC min ESS 20 % | limite active 20.0 %
MPPT ordre: mppt1 rs_1 rs_2 rs_3 rs_4 rs_g v1 (MPPT=cherche le max, lim_=se retient)
11:01:02 | OFF_1 | PV 5200 | U 50.09 | I 48.2 | conso 2275 | grid 0 | SOC 46 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
11:01:17 | OFF_1 | PV 6109 | U 50.11 | I 60.3 | conso 2279 | grid 0 | SOC 46 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
11:01:32 | OFF_1 | PV 5632 | U 50.19 | I 84.3 | conso 1983 | grid 0 | SOC 46 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
11:01:47 | OFF_1 | PV 8639 | U 50.35 | I 131.3 | conso 2108 | grid 0 | SOC 46 | DVCC 130A/51.5V | acin 0 | edf off | volt volt volt volt MPPT volt volt
11:02:02 | OFF_1 | PV 8510 | U 50.38 | I 126.4 | conso 2372 | grid 0 | SOC 46 | DVCC 130A/51.5V | acin 0 | edf off | volt MPPT MPPT MPPT MPPT MPPT MPPT
11:02:18 | OFF_1 | PV 8540 | U 50.33 | I 100.9 | conso 2452 | grid 0 | SOC 46 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
11:02:33 | OFF_1 | PV 7535 | U 50.30 | I 89.8 | conso 2424 | grid 0 | SOC 47 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
11:02:48 | OFF_1 | PV 6464 | U 50.30 | I 97.3 | conso 2393 | grid 0 | SOC 47 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
11:03:03 | OFF_1 | PV 7018 | U 50.22 | I 74.3 | conso 2400 | grid 0 | SOC 47 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
11:03:18 | OFF_1 | PV 7233 | U 50.28 | I 93.0 | conso 2381 | grid 0 | SOC 47 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
11:03:33 | OFF_1 | PV 8269 | U 50.32 | I 104.7 | conso 2405 | grid 0 | SOC 47 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
11:03:48 | OFF_1 | PV 6161 | U 50.29 | I 84.4 | conso 2395 | grid 0 | SOC 47 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
11:04:03 | OFF_1 | PV 5965 | U 50.20 | I 58.6 | conso 2404 | grid 0 | SOC 47 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
11:04:18 | OFF_1 | PV 6338 | U 50.22 | I 77.2 | conso 2397 | grid 0 | SOC 47 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
11:04:33 | OFF_1 | PV 6878 | U 50.22 | I 75.6 | conso 2409 | grid 0 | SOC 47 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
11:04:48 | OFF_1 | PV 6276 | U 50.20 | I 66.7 | conso 2394 | grid 0 | SOC 48 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
>>> EDF ON
11:05:06 | ON_1 | PV 5262 | U 50.16 | I 61.4 | conso 2452 | grid 0 | SOC 48 | DVCC 130A/51.5V | acin 1 | edf on | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
11:05:21 | ON_1 | PV 5674 | U 50.13 | I 57.5 | conso 2458 | grid 0 | SOC 48 | DVCC 130A/51.5V | acin 1 | edf on | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
11:05:36 | ON_1 | PV 5740 | U 50.10 | I 54.3 | conso 2410 | grid 0 | SOC 48 | DVCC 130A/51.5V | acin 1 | edf on | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
11:05:51 | ON_1 | PV 6539 | U 50.18 | I 78.4 | conso 2083 | grid 0 | SOC 48 | DVCC 130A/51.5V | acin 1 | edf on | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
11:06:06 | ON_1 | PV 7018 | U 50.23 | I 80.1 | conso 2107 | grid 0 | SOC 48 | DVCC 130A/51.5V | acin 1 | edf on | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
11:06:21 | ON_1 | PV 5203 | U 50.35 | I 114.4 | conso 2113 | grid 1985 | SOC 48 | DVCC 130A/51.5V | acin 1 | edf on | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
11:06:36 | ON_1 | PV 5126 | U 50.31 | I 93.4 | conso 2107 | grid 1811 | SOC 48 | DVCC 130A/51.5V | acin 1 | edf on | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
11:06:52 | ON_1 | PV 4853 | U 50.29 | I 90.0 | conso 2131 | grid 1603 | SOC 48 | DVCC 130A/51.5V | acin 1 | edf on | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
11:07:07 | ON_1 | PV 4935 | U 50.26 | I 78.6 | conso 2184 | grid 1418 | SOC 48 | DVCC 130A/51.5V | acin 1 | edf on | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
11:07:22 | ON_1 | PV 5147 | U 50.23 | I 74.6 | conso 2140 | grid 1135 | SOC 48 | DVCC 130A/51.5V | acin 1 | edf on | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
11:07:37 | ON_1 | PV 5535 | U 50.26 | I 84.6 | conso 2120 | grid 939 | SOC 48 | DVCC 130A/51.5V | acin 1 | edf on | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
11:07:52 | ON_1 | PV 4455 | U 50.21 | I 62.1 | conso 2079 | grid 659 | SOC 48 | DVCC 130A/51.5V | acin 1 | edf on | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
11:08:07 | ON_1 | PV 4105 | U 50.14 | I 50.5 | conso 2086 | grid 445 | SOC 49 | DVCC 130A/51.5V | acin 1 | edf on | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
11:08:22 | ON_1 | PV 4116 | U 50.08 | I 42.0 | conso 2160 | grid 307 | SOC 49 | DVCC 130A/51.5V | acin 1 | edf on | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
11:08:37 | ON_1 | PV 5153 | U 50.09 | I 50.3 | conso 2070 | grid 25 | SOC 49 | DVCC 130A/51.5V | acin 1 | edf on | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
11:08:52 | ON_1 | PV 4488 | U 50.09 | I 48.3 | conso 2067 | grid 25 | SOC 49 | DVCC 130A/51.5V | acin 1 | edf on | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
>>> EDF OFF
11:09:10 | OFF_2 | PV 4483 | U 50.06 | I 38.3 | conso 2314 | grid 0 | SOC 49 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
11:09:25 | OFF_2 | PV 4953 | U 50.05 | I 41.6 | conso 2305 | grid 0 | SOC 49 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
11:09:40 | OFF_2 | PV 6915 | U 50.10 | I 58.7 | conso 2304 | grid 0 | SOC 49 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
11:09:55 | OFF_2 | PV 6850 | U 50.19 | I 76.7 | conso 2310 | grid 0 | SOC 49 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
11:10:10 | OFF_2 | PV 6174 | U 50.22 | I 76.9 | conso 2309 | grid 0 | SOC 49 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
11:10:25 | OFF_2 | PV 5937 | U 50.16 | I 59.6 | conso 2374 | grid 0 | SOC 49 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
11:10:40 | OFF_2 | PV 6519 | U 50.17 | I 64.4 | conso 2319 | grid 0 | SOC 49 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
11:10:55 | OFF_2 | PV 5987 | U 50.22 | I 74.4 | conso 2340 | grid 0 | SOC 49 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
11:11:10 | OFF_2 | PV 4922 | U 50.15 | I 51.5 | conso 2381 | grid 0 | SOC 49 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
11:11:25 | OFF_2 | PV 5392 | U 50.10 | I 43.9 | conso 2361 | grid 0 | SOC 49 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
11:11:40 | OFF_2 | PV 5504 | U 50.16 | I 62.3 | conso 2347 | grid 0 | SOC 49 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
11:11:55 | OFF_2 | PV 6235 | U 50.17 | I 67.1 | conso 2324 | grid 0 | SOC 49 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
11:12:11 | OFF_2 | PV 7208 | U 50.26 | I 84.7 | conso 2330 | grid 0 | SOC 49 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
11:12:26 | OFF_2 | PV 5227 | U 50.24 | I 69.9 | conso 2350 | grid 0 | SOC 50 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
11:12:41 | OFF_2 | PV 4526 | U 50.14 | I 44.0 | conso 2371 | grid 0 | SOC 50 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
11:12:56 | OFF_2 | PV 3986 | U 50.11 | I 40.1 | conso 4229 | grid 0 | SOC 50 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
>>> EDF ON
11:13:14 | ON_2 | PV 4963 | U 50.05 | I 38.8 | conso 2398 | grid 0 | SOC 50 | DVCC 130A/51.5V | acin 1 | edf on | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
11:13:29 | ON_2 | PV 5666 | U 50.07 | I 41.0 | conso 2369 | grid 0 | SOC 50 | DVCC 130A/51.5V | acin 1 | edf on | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
11:13:44 | ON_2 | PV 5415 | U 50.14 | I 59.1 | conso 2374 | grid 0 | SOC 50 | DVCC 130A/51.5V | acin 1 | edf on | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
11:13:59 | ON_2 | PV 6240 | U 50.14 | I 62.6 | conso 2380 | grid 0 | SOC 50 | DVCC 130A/51.5V | acin 1 | edf on | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
11:14:14 | ON_2 | PV 7346 | U 50.24 | I 87.1 | conso 2635 | grid 0 | SOC 50 | DVCC 130A/51.5V | acin 1 | edf on | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
11:14:29 | ON_2 | PV 7398 | U 50.47 | I 142.9 | conso 2730 | grid 2600 | SOC 50 | DVCC 130A/51.5V | acin 1 | edf on | volt volt volt volt MPPT volt volt
11:14:44 | ON_2 | PV 6944 | U 50.48 | I 129.5 | conso 2495 | grid 2190 | SOC 50 | DVCC 130A/51.5V | acin 1 | edf on | volt MPPT MPPT MPPT MPPT MPPT volt
11:14:59 | ON_2 | PV 7122 | U 50.50 | I 127.0 | conso 2498 | grid 1949 | SOC 51 | DVCC 130A/51.5V | acin 1 | edf on | volt volt volt volt MPPT volt volt
11:15:14 | ON_2 | PV 7312 | U 50.52 | I 126.2 | conso 2540 | grid 1806 | SOC 51 | DVCC 130A/51.5V | acin 1 | edf on | volt volt volt volt MPPT volt volt
11:15:29 | ON_2 | PV 7540 | U 50.53 | I 126.8 | conso 2482 | grid 1536 | SOC 51 | DVCC 130A/51.5V | acin 1 | edf on | volt volt volt volt MPPT volt volt
11:15:44 | ON_2 | PV 7966 | U 50.54 | I 123.9 | conso 2515 | grid 1237 | SOC 51 | DVCC 130A/51.5V | acin 1 | edf on | volt volt volt volt MPPT volt volt
11:15:59 | ON_2 | PV 8017 | U 50.54 | I 121.3 | conso 2503 | grid 1094 | SOC 51 | DVCC 130A/51.5V | acin 1 | edf on | volt volt volt volt MPPT volt MPPT
11:16:14 | ON_2 | PV 8456 | U 50.56 | I 123.5 | conso 2499 | grid 828 | SOC 51 | DVCC 130A/51.5V | acin 1 | edf on | volt volt volt volt MPPT volt volt
11:16:29 | ON_2 | PV 8592 | U 50.57 | I 125.9 | conso 2116 | grid 277 | SOC 52 | DVCC 130A/51.5V | acin 1 | edf on | volt volt volt volt MPPT volt volt
11:16:44 | ON_2 | PV 8488 | U 50.59 | I 126.8 | conso 2089 | grid 52 | SOC 52 | DVCC 130A/51.5V | acin 1 | edf on | volt MPPT MPPT MPPT MPPT MPPT MPPT
11:16:59 | ON_2 | PV 8759 | U 50.57 | I 121.0 | conso 2092 | grid -41 | SOC 52 | DVCC 130A/51.5V | acin 1 | edf on | volt MPPT MPPT MPPT MPPT MPPT MPPT
>>> EDF OFF
11:17:17 | FIN_OFF| PV 8921 | U 50.58 | I 127.5 | conso 2058 | grid 0 | SOC 52 | DVCC 130A/51.5V | acin 0 | edf off | volt volt volt volt MPPT volt volt
11:17:32 | FIN_OFF| PV 8483 | U 50.58 | I 126.6 | conso 2054 | grid 0 | SOC 52 | DVCC 130A/51.5V | acin 0 | edf off | volt MPPT MPPT MPPT MPPT MPPT MPPT
11:17:47 | FIN_OFF| PV 8296 | U 50.57 | I 121.9 | conso 2024 | grid 0 | SOC 52 | DVCC 130A/51.5V | acin 0 | edf off | volt MPPT MPPT MPPT MPPT MPPT MPPT
11:18:02 | FIN_OFF| PV 7904 | U 50.57 | I 122.9 | conso 2024 | grid 0 | SOC 53 | DVCC 130A/51.5V | acin 0 | edf off | volt MPPT MPPT MPPT MPPT MPPT MPPT
11:18:17 | FIN_OFF| PV 8785 | U 50.59 | I 128.9 | conso 2025 | grid 0 | SOC 53 | DVCC 130A/51.5V | acin 0 | edf off | volt volt volt volt MPPT volt volt
11:18:32 | FIN_OFF| PV 8128 | U 50.60 | I 125.2 | conso 2028 | grid 0 | SOC 53 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
11:18:48 | FIN_OFF| PV 8287 | U 50.61 | I 127.3 | conso 2018 | grid 0 | SOC 53 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
11:19:03 | FIN_OFF| PV 6198 | U 50.50 | I 90.7 | conso 2021 | grid 0 | SOC 53 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
11:19:18 | FIN_OFF| PV 8660 | U 50.47 | I 89.1 | conso 2012 | grid 0 | SOC 53 | DVCC 130A/51.5V | acin 0 | edf off | volt volt volt volt MPPT volt MPPT
11:19:33 | FIN_OFF| PV 8310 | U 50.58 | I 120.2 | conso 2019 | grid 0 | SOC 54 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
11:19:48 | FIN_OFF| PV 8015 | U 50.59 | I 118.9 | conso 2317 | grid 0 | SOC 54 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT MPPT MPPT MPPT MPPT
11:20:03 | FIN_OFF| PV 8740 | U 50.55 | I 111.1 | conso 2364 | grid 0 | SOC 54 | DVCC 130A/51.5V | acin 0 | edf off | MPPT MPPT MPPT volt volt volt MPPT
11:20:18 | FIN_OFF| PV 9047 | U 50.61 | I 121.6 | conso 2392 | grid 0 | SOC 54 | DVCC 130A/51.5V | acin 0 | edf off | volt MPPT MPPT MPPT MPPT MPPT MPPT
11:20:33 | FIN_OFF| PV 9009 | U 50.64 | I 124.3 | conso 2343 | grid 0 | SOC 54 | DVCC 130A/51.5V | acin 0 | edf off | volt MPPT MPPT MPPT MPPT MPPT MPPT
11:20:48 | FIN_OFF| PV 9155 | U 50.64 | I 122.4 | conso 2459 | grid 0 | SOC 54 | DVCC 130A/51.5V | acin 0 | edf off | volt MPPT MPPT MPPT MPPT MPPT volt
11:21:03 | FIN_OFF| PV 9115 | U 50.66 | I 127.1 | conso 2343 | grid 0 | SOC 54 | DVCC 130A/51.5V | acin 0 | edf off | MPPT volt volt volt MPPT volt volt
>>> RESTAURATION (fin de campagne)
>>> etat restaure : edf off | latch off | hysteresis on

View File

@@ -0,0 +1,119 @@
#!/usr/bin/env node
// Resume par phase d'un journal produit par tools/test-edf-alterne.mjs.
// Usage: node tools/analyse-test-alterne.mjs docs/mesures/<fichier>.log [secondesIgnorees]
//
// Les N premieres secondes de chaque phase sont ignorees par defaut (90 s) :
// la bascule du contacteur met ~30 a 90 s a s'etablir, et inclure le transitoire
// ecraserait l'ecart qu'on cherche a mesurer.
import fs from 'node:fs';
const file = process.argv[2];
const SKIP = Number(process.argv[3] ?? 90);
const lines = fs.readFileSync(file, 'utf8').split('\n');
const rows = [];
for (const l of lines) {
const m = l.match(
// Le bloc des modes MPPT est le DERNIER champ : on l'ancre sur "edf on|off",
// jamais sur le mot MPPT. Ancrer sur "MPPT " faisait tomber en silence toute
// ligne dont le PREMIER tracker etait bride -- c'est-a-dire precisement les
// echantillons a mesurer -- et biaisait le resultat vers "aucun bridage".
/^(\d{2}:\d{2}:\d{2}) \| (\w+)\s*\| PV\s+(-?\d+) \| U\s+([\d.]+) \| I\s+(-?[\d.]+) \| conso\s+(-?\d+) \| grid\s+(-?\d+) \| SOC\s+(\d+).*\| edf (?:on|off) \| (.*)$/
);
if (!m) continue;
const [, t, phase, pv, u, i, conso, grid, soc, modes] = m;
rows.push({
t, phase,
pv: +pv, u: +u, i: +i, conso: +conso, grid: +grid, soc: +soc,
lim: modes.trim().split(/\s+/).filter((m) => m !== 'MPPT').length,
sec: (+t.slice(0, 2)) * 3600 + (+t.slice(3, 5)) * 60 + (+t.slice(6, 8)),
});
}
const order = [];
const byPhase = new Map();
for (const r of rows) {
if (!byPhase.has(r.phase)) { byPhase.set(r.phase, []); order.push(r.phase); }
byPhase.get(r.phase).push(r);
}
const avg = (a, k) => (a.length ? a.reduce((s, x) => s + x[k], 0) / a.length : NaN);
const n = (x, d = 0) => (Number.isFinite(x) ? x.toFixed(d) : '—');
console.log(`Journal : ${file} (${rows.length} echantillons, ${SKIP}s de transitoire ignorees par phase)\n`);
console.log('phase n | PV moy | PV max | conso | grid | I bat | SOC | trackers brides');
console.log('---------------------------------------------------------------------------------');
const summary = [];
for (const p of order) {
const all = byPhase.get(p);
const t0 = all[0].sec;
const a = all.filter((r) => r.sec - t0 >= SKIP);
const use = a.length ? a : all;
const s = {
phase: p, n: use.length,
pv: avg(use, 'pv'), pvmax: Math.max(...use.map((r) => r.pv)),
conso: avg(use, 'conso'), grid: avg(use, 'grid'), i: avg(use, 'i'),
soc: avg(use, 'soc'), lim: avg(use, 'lim'),
};
summary.push(s);
console.log(
`${p.padEnd(8)}${String(s.n).padStart(3)} |${n(s.pv).padStart(9)} |${n(s.pvmax).padStart(8)} |` +
`${n(s.conso).padStart(8)} |${n(s.grid).padStart(7)} |${n(s.i, 1).padStart(7)} |${n(s.soc, 1).padStart(5)} |` +
`${n(s.lim, 1).padStart(9)} / 7`
);
}
const off = summary.filter((s) => !s.phase.startsWith('ON'));
const on = summary.filter((s) => s.phase.startsWith('ON'));
// --- garde meteo -------------------------------------------------------------
// Les phases OUVERTES sont toutes censees voir la meme ressource solaire. Si
// elles ne s'accordent pas entre elles, c'est le ciel qui a change pendant la
// campagne : la moyenne ON contre moyenne OFF devient ininterpretable, et il ne
// faut surtout pas la presenter comme un resultat (piege rencontre le 27/08 au
// premier test, et de nouveau le 31/08).
const pvOffs = off.map((s) => s.pv);
const spread = Math.max(...pvOffs) - Math.min(...pvOffs);
const spreadPct = (spread / (pvOffs.reduce((a, b) => a + b, 0) / pvOffs.length)) * 100;
console.log('\n--- STABILITE DE LA RESSOURCE ---');
console.log(`PV moyenne des phases OUVERTES : ${off.map((s) => `${s.phase} ${n(s.pv)} W`).join(' | ')}`);
console.log(`Ecart entre phases ouvertes : ${n(spread)} W (${n(spreadPct, 1)} % de la moyenne)`);
const meteoStable = spreadPct < 15;
console.log(meteoStable
? '=> ressource stable : la comparaison globale ON/OFF est exploitable.'
: '=> RESSOURCE INSTABLE (nuages) : la comparaison globale ON/OFF n est PAS exploitable.\n Se fier uniquement aux transitions ci-dessous, phase par phase.');
// --- comparaison locale : chaque ON contre ses voisines OFF -------------------
console.log('\n--- TRANSITIONS (chaque phase fermee contre ses voisines ouvertes) ---');
for (const s of on) {
const idx = order.indexOf(s.phase);
const voisins = summary.filter((x) => Math.abs(order.indexOf(x.phase) - idx) === 1 && !x.phase.startsWith('ON'));
if (!voisins.length) continue;
const ref = voisins.reduce((a, x) => a + x.pv, 0) / voisins.length;
const d = s.pv - ref;
const pct = (d / ref) * 100;
console.log(
`${s.phase} : PV ${n(s.pv)} W contre ${n(ref)} W chez ${voisins.map((v) => v.phase).join('+')}` +
` => ${d >= 0 ? '+' : ''}${n(d)} W (${pct >= 0 ? '+' : ''}${n(pct, 1)} %)` +
` | import ${n(s.grid)} W | trackers brides ${n(s.lim, 1)}/7`
);
}
console.log('\n--- VERDICT ---');
if (!meteoStable) {
console.log('Campagne partiellement inexploitable (ressource instable).');
console.log('Verifier a la main, sur le journal brut, si la chute de PV precede ou suit');
console.log('l apparition de l import reseau : si elle la PRECEDE, ce sont des nuages.');
} else {
const pvOff = pvOffs.reduce((a, b) => a + b, 0) / pvOffs.length;
const pvOn = on.reduce((a, s) => a + s.pv, 0) / on.length;
const gOn = on.reduce((a, s) => a + s.grid, 0) / on.length;
const pct = ((pvOn - pvOff) / pvOff) * 100;
console.log(`PV ouverte ${n(pvOff)} W | PV fermee ${n(pvOn)} W | ecart ${pct >= 0 ? '+' : ''}${n(pct, 1)} %`);
console.log(Math.abs(pct) < 10
? '=> PAS DE SUBSTITUTION : la production ne depend pas de la presence du reseau.'
: '=> SUBSTITUTION : la production chute quand le reseau est la.');
console.log(`Import moyen en phase fermee : ${n(gOn)} W (consigne ESS ~50 W attendue si le solaire couvre tout).`);
}

157
tools/test-edf-alterne.mjs Normal file
View File

@@ -0,0 +1,157 @@
#!/usr/bin/env node
// Campagne de test EDF <-> MPPT, protocole ALTERNE.
//
// Usage: node tools/test-edf-alterne.mjs [phaseSec] [sampleSec]
// node tools/test-edf-alterne.mjs 180 15 (defaut)
//
// Protocole : OFF / ON / OFF / ON / OFF, phases de duree egale, echantillon
// regulier. L'alternance est ce qui rend la mesure interpretable : une derive
// meteo monotone ne peut pas produire un signal qui suit le contacteur quatre
// fois de suite.
//
// Ce que le script mesure a chaque echantillon : PV totale, tension et courant
// batterie, consommation maison, import reseau, SOC, limite DVCC, presence
// physique AC-IN, et le mode de fonctionnement des 7 chargeurs solaires
// (mppt_active = cherche son point de puissance maximale ; sinon il se retient).
//
// SECURITE : l'hysteresis reseau est desactivee pendant le test puis restauree,
// ainsi que le latch et l'etat du contacteur. La restauration est faite aussi
// sur Ctrl-C et sur erreur.
import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
const HA = process.env.HA_URL || 'http://10.10.10.17:8123';
function loadToken() {
if (process.env.HA_TOKEN) return process.env.HA_TOKEN;
const m = fs.readFileSync(path.join(ROOT, '.env'), 'utf8').match(/^\s*HA_TOKEN\s*=\s*(.+?)\s*$/m);
if (!m) { console.error('HA_TOKEN absent de .env'); process.exit(1); }
return m[1].replace(/^["']|["']$/g, '');
}
const TOKEN = loadToken();
const H = { Authorization: `Bearer ${TOKEN}`, 'Content-Type': 'application/json' };
const get = async (id) => {
const r = await fetch(`${HA}/api/states/${id}`, { headers: H });
if (!r.ok) return null;
return (await r.json()).state;
};
const call = async (svc, data) => {
const [d, s] = svc.split('.');
const r = await fetch(`${HA}/api/services/${d}/${s}`, { method: 'POST', headers: H, body: JSON.stringify(data) });
if (!r.ok) throw new Error(`${svc} -> HTTP ${r.status} ${await r.text()}`);
};
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
// --- entites -----------------------------------------------------------------
const MPPT = [
['mppt1', 'sensor.airtria_mppt1_mppt_operation_mode'],
['rs_1', 'sensor.mppt_450_200_hq2449yr9pt_pv_tracker_solar_1_operation_mode'],
['rs_2', 'sensor.mppt_450_200_hq2449yr9pt_pv_tracker_solar_2_operation_mode'],
['rs_3', 'sensor.mppt_450_200_hq2449yr9pt_pv_tracker_solar_3_operation_mode'],
['rs_4', 'sensor.mppt_450_200_hq2449yr9pt_pv_tracker_solar_4_operation_mode'],
['rs_g', 'sensor.mppt_450_200_hq2449yr9pt_mppt_operation_mode'],
['v1', 'sensor.v1_mppt_operation_mode'],
];
const M = {
pv: 'sensor.victron_pv_power_system',
u: 'sensor.victron_battery_voltage',
i: 'sensor.victron_battery_current',
conso: 'sensor.victron_consumption_power_l1',
grid: 'sensor.victron_grid_power_l1',
soc: 'sensor.victron_battery_soc',
dvcc_a: 'sensor.victron_max_charge_current_setting',
dvcc_v: 'sensor.victron_max_charge_voltage_setting',
acin: 'sensor.victron_ac_in1_available',
edf: 'switch.edf_general_ok_switch',
mode: 'input_text.victron_charge_mode',
};
const HYST = 'input_boolean.victron_grid_hysteresis_enabled';
const LATCH = 'input_boolean.victron_grid_hysteresis_latch';
const PHASE_SEC = Number(process.argv[2] || 180);
const SAMPLE_SEC = Number(process.argv[3] || 15);
const PHASES = ['OFF_1', 'ON_1', 'OFF_2', 'ON_2', 'FIN_OFF'];
const stamp = () => new Date().toLocaleTimeString('fr-FR', { timeZone: 'Europe/Paris' });
const out = [];
const say = (l) => { console.log(l); out.push(l); };
// --- restauration ------------------------------------------------------------
let initial = null;
let restored = false;
async function restore(why) {
if (restored || !initial) return;
restored = true;
say(`>>> RESTAURATION (${why})`);
try {
await call('switch.turn_off', { entity_id: M.edf });
await call(`input_boolean.turn_${initial.latch}`, { entity_id: LATCH });
await call(`input_boolean.turn_${initial.hyst}`, { entity_id: HYST });
say(`>>> etat restaure : edf off | latch ${initial.latch} | hysteresis ${initial.hyst}`);
} catch (e) {
say(`!!! ECHEC RESTAURATION : ${e.message} — VERIFIER A LA MAIN ${M.edf}, ${LATCH}, ${HYST}`);
}
}
process.on('SIGINT', async () => { await restore('Ctrl-C'); process.exit(130); });
// --- deroule -----------------------------------------------------------------
initial = {
hyst: (await get(HYST)) === 'on' ? 'on' : 'off',
latch: (await get(LATCH)) === 'on' ? 'on' : 'off',
edf: await get(M.edf),
};
say(`TEST ALTERNE EDF <-> MPPT — ${new Date().toLocaleString('fr-FR', { timeZone: 'Europe/Paris' })}`);
say(`phases ${PHASE_SEC}s, echantillon ${SAMPLE_SEC}s, sequence ${PHASES.join(' / ')}`);
say(`etat initial : edf ${initial.edf} | latch ${initial.latch} | hysteresis ${initial.hyst}`);
say(`consigne reseau ${await get('number.gx_device_ac_power_setpoint')} W | SOC min ESS ${await get('number.gx_device_ess_min_soc_limit')} % | limite active ${await get('sensor.gx_device_active_soc_limit')} %`);
say(`MPPT ordre: ${MPPT.map((m) => m[0]).join(' ')} (MPPT=cherche le max, lim_=se retient)`);
say('');
try {
await call('input_boolean.turn_off', { entity_id: HYST });
await call('switch.turn_off', { entity_id: M.edf });
await sleep(2000);
for (const phase of PHASES) {
const want = phase.startsWith('ON') ? 'on' : 'off';
if ((await get(M.edf)) !== want) {
say(`>>> EDF ${want.toUpperCase()}`);
await call(`switch.turn_${want}`, { entity_id: M.edf });
await sleep(3000);
}
const t0 = Date.now();
while (Date.now() - t0 < PHASE_SEC * 1000) {
const v = {};
await Promise.all(Object.entries(M).map(async ([k, id]) => { v[k] = await get(id); }));
const modes = await Promise.all(MPPT.map(async ([, id]) => {
const s = await get(id);
return s === 'mppt_active' ? 'MPPT' : (s || 'n/a').slice(0, 4).padEnd(4);
}));
const n = (x, d = 0) => (Number.isFinite(Number(x)) ? Number(x).toFixed(d) : String(x));
say(
`${stamp()} | ${phase.padEnd(7)}| PV ${n(v.pv).padStart(5)} | U ${n(v.u, 2).padStart(5)}` +
` | I ${n(v.i, 1).padStart(6)} | conso ${n(v.conso).padStart(5)} | grid ${n(v.grid).padStart(5)}` +
` | SOC ${n(v.soc)} | DVCC ${n(v.dvcc_a)}A/${n(v.dvcc_v, 1)}V | acin ${v.acin} | edf ${v.edf}` +
` | ${modes.join(' ')}`
);
await sleep(SAMPLE_SEC * 1000);
}
}
} catch (e) {
say(`!!! ERREUR : ${e.message}`);
} finally {
await restore('fin de campagne');
}
// Le nom porte la date ET l'heure : deux campagnes le meme jour ne doivent pas
// s'ecraser l'une l'autre (piege rencontre le 31/08).
const now = new Date();
const hhmm = now.toLocaleTimeString('fr-FR', { timeZone: 'Europe/Paris', hour: '2-digit', minute: '2-digit' }).replace(':', '');
const dest = path.join(ROOT, 'docs/mesures', `${now.toISOString().slice(0, 10).replace(/-/g, '')}-${hhmm}-test-edf-alterne.log`);
fs.writeFileSync(dest, out.join('\n') + '\n');
console.log(`\nJournal : ${dest}`);