fix(flux): la production restait négative dans le DÉTAIL, et le tableau de bord ignorait la config

Deux défauts trouvés en vérifiant la correction précédente à l'écran.

1. « -1.3 kW · Solaire » dans « Production — détail ». La correction du
   2026-09-05 n'avait redressé QUE le nœud de la vue d'ensemble : la même
   grandeur est rendue à deux endroits, et le grep qui avait servi cherchait
   `pvPower.abs` — donc il montrait la ligne déjà corrigée et cachait l'autre.
   Un test couvre désormais le détail, en éprouvant l'ABSENCE du signe.

2. PAC et « Eau chaude » affichaient « non publié » alors que la box publie
   `{powerW: 0, source: "meter"}` pour les deux. `LoadConfigProvider.load()`
   n'était appelé que par l'écran des rôles : sur le tableau de bord la
   configuration est vide, aucun `domain` ne se rattache, et la carte reste sans
   valeur. Une absence CÔTÉ APP présentée comme une absence côté box — le défaut
   qu'on venait de corriger, reproduit un cran plus loin, et trompeur de la même
   façon : on en conclurait que la box ne publie rien.

Vérifié à l'écran entre les deux : « non publié » est lisible dans les cercles,
« Autres » a disparu, et le détail production ne montre plus d'onduleurs
fabriqués mais « Détail par source non publié par cette box ».

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GKM8FDNHZWogAsjjfB8pSw
This commit is contained in:
Patrick Schurig 2026-09-06 13:24:53 +02:00
parent c261b22c8c
commit cd202840f1
3 changed files with 36 additions and 2 deletions

View File

@ -484,7 +484,12 @@ class _NodeLayerState extends State<_NodeLayer>
icon: Icons.wb_sunny_rounded,
color: solar,
label: 'Solaire',
value: '${(d.pvPower / 1000).toStringAsFixed(1)} kW',
// ⚠️ `.abs()` ICI AUSSI. La correction du 2026-09-05 n'avait redressé que le
// nœud de la vue d'ensemble : le hub du détail production affichait toujours
// « -1.3 kW », vu sur appareil le 2026-09-06. Une même grandeur rendue à deux
// endroits, corrigée à un seul — le grep qui a servi cherchait `pvPower.abs`
// et non `pvPower`, donc il a montré la ligne déjà corrigée et caché l'autre.
value: '${(d.pvPower.abs() / 1000).toStringAsFixed(1)} kW',
borderColor: EtmTokens.lineOf(context),
),
)),

View File

@ -48,7 +48,18 @@ class _DashboardScreenState extends State<DashboardScreen> {
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) => _lireBilan());
WidgetsBinding.instance.addPostFrameCallback((_) {
_lireBilan();
// ⚠️ La configuration des charges n'était chargée QUE par l'écran des rôles. Le
// détail de consommation en a besoin — c'est elle qui porte le `domain` de chaque
// charge — et sans elle il affichait « non publié » sur des charges que la box
// publiait bel et bien. Une absence côté app présentée comme une absence côté box :
// le défaut qu'on vient de corriger, reproduit un cran plus loin.
final svc = context.read<NymeaService>();
context.read<LoadConfigProvider>()
..attach(svc)
..load();
});
_tick = Timer.periodic(_periode, (_) => _lireBilan());
}

View File

@ -39,6 +39,24 @@ void main() {
reason: 'un client lirait « mes panneaux consomment 9 kW »');
});
testWidgets('le DÉTAIL production ne montre pas non plus un signe négatif',
(tester) async {
// La correction du 2026-09-05 n'avait redressé que la vue d'ensemble. Le hub du
// détail affichait toujours « -1.3 kW », vu sur appareil le lendemain : une même
// grandeur rendue à deux endroits, corrigée à un seul.
await _poser(tester, const EnergyData(pvPower: -1349.0, homePower: 3252));
await tester.tap(find.text('Solaire'));
await tester.pump(const Duration(seconds: 2));
// Deux nœuds portent la valeur pendant la transition (vue d'ensemble et hub du
// détail) : c'est l'ABSENCE du signe qui est éprouvée ici, pas le compte.
expect(find.text('1.3 kW'), findsWidgets);
expect(find.text('-1.3 kW'), findsNothing);
// Et surtout : plus d'onduleurs fabriqués.
expect(find.textContaining('Onduleur'), findsNothing);
expect(find.textContaining('non publié par cette box'), findsOneWidget);
});
testWidgets('zéro reste zéro — et ne prouve rien', (tester) async {
// L'état du banc à 17:03, celui qui a rendu la correction invisible à l'écran.
await _poser(tester,