Signalé sur banc après changement de matériel : Fronius SunSpec retiré, Eastron SDM72 posé en rootMeter et SDM120 en compteur de production. L'écran affichait le SDM72 dans les DEUX rôles, avec « auto · lecture seule » — donc sans moyen de le corriger. La box était juste (`GetRootMeter` rend bien le SDM72) et les interfaces distinguaient les deux sans ambiguïté : Grid / sdm72 : energymeter, smartmeter, connectable PV / sdm120Producer : smartmeterproducer, smartmeter, connectable C'est notre liste qui ne discriminait pas : le rôle solaire acceptait `energymeter`, `meter` et `smartmeter` — portées par TOUT compteur, réseau compris — et ignorait `smartmeterproducer`, la seule qui dise « ce compteur mesure une production ». Deux corrections, la seconde tenant même si une future classe déclare des interfaces trop larges : - le rôle solaire exige désormais une interface de production ; - le Thing acté comme compteur RACINE n'est plus candidat à aucun autre rôle. Reste ouvert, et c'est le vrai fond du signalement : une détection automatique ne devrait pas être un cul-de-sac. Les lignes de compteur n'ont aujourd'hui AUCUN geste — pas de sélecteur, quel que soit l'état. Le badge « lecture seule » est honnête, mais une inférence fausse doit pouvoir se corriger. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GKM8FDNHZWogAsjjfB8pSw
61 lines
2.7 KiB
Dart
61 lines
2.7 KiB
Dart
/// **Le sens du flux réseau** — signalé sur appareil, pas trouvé en test.
|
||
///
|
||
/// Le 2026-09-06 : 4,9 kW de production, 3,3 kW de consommation, le simulateur affichant
|
||
/// `Grid -1980 W` — donc une installation qui **injecte** — et l'app annonçait « consommation
|
||
/// réseau », flèche à l'envers.
|
||
///
|
||
/// La cause n'était pas un calcul mais une **convention écrite deux fois, en sens opposés** :
|
||
///
|
||
/// | endroit | ce qu'il disait | juste ? |
|
||
/// |---|---|---|
|
||
/// | `EnergyData.gridPower` (commentaire) | « + injection, − soutirage » | **non** |
|
||
/// | `energy_flow_widget.dart:180` | « gridPower > 0 = soutirage » | oui |
|
||
/// | `energy_flow_card.dart` (le code à l'écran) | + = injection | **non** |
|
||
///
|
||
/// Vérifié à la sonde : `currentPowerAcquisition` vaut **−2 511 W** pendant que la production
|
||
/// (5,76 kW) dépasse la consommation (3,25 kW) de 2,5 kW. Le signe négatif est donc l'export,
|
||
/// et sa valeur absolue la puissance injectée.
|
||
///
|
||
/// Ces tests portent sur les accesseurs nommés plutôt que sur le widget : c'est là que la
|
||
/// convention vit désormais, et c'est ce qui empêche qu'un troisième lecteur la réinvente.
|
||
library;
|
||
|
||
import 'package:etm_powersync_app/models/energy_data.dart';
|
||
import 'package:flutter_test/flutter_test.dart';
|
||
|
||
void main() {
|
||
group('la convention est celle de la BOX : + soutiré, − injecté', () {
|
||
test('export : le relevé du 2026-09-06', () {
|
||
// production 5 763 W, maison 3 252 W -> 2 511 W injectés.
|
||
const d = EnergyData(pvPower: -5763, homePower: 3252, gridPower: -2511);
|
||
expect(d.gridExportW, 2511);
|
||
expect(d.gridImportW, 0, reason: 'rien n\'est soutiré pendant qu\'on injecte');
|
||
});
|
||
|
||
test('import : le cas du soir, production nulle', () {
|
||
const d = EnergyData(pvPower: 0, homePower: 3250, gridPower: 3250);
|
||
expect(d.gridImportW, 3250);
|
||
expect(d.gridExportW, 0);
|
||
});
|
||
|
||
test('zéro : ni l\'un ni l\'autre — et surtout pas les deux', () {
|
||
const d = EnergyData(gridPower: 0);
|
||
expect(d.gridImportW, 0);
|
||
expect(d.gridExportW, 0);
|
||
});
|
||
|
||
test('les deux parts ne sont JAMAIS non nulles ensemble', () {
|
||
// C'est la garde qui aurait attrapé l'inversion : le code fautif calculait
|
||
// `import = -gridPower` et `export = gridPower`, donc l'un des deux était toujours
|
||
// faux — mais chacun pris seul restait plausible.
|
||
for (final w in [-9000.0, -1.0, 0.0, 1.0, 9000.0]) {
|
||
final d = EnergyData(gridPower: w);
|
||
expect(d.gridImportW * d.gridExportW, 0,
|
||
reason: 'à $w W, une seule direction peut être active');
|
||
expect(d.gridImportW + d.gridExportW, w.abs(),
|
||
reason: 'et leur somme est la puissance échangée');
|
||
}
|
||
});
|
||
});
|
||
}
|