1) « Vers réseau » — TROIS défauts, dont un seul était visible.
La valeur aberrante (9,10184409403335e+33 kWh) ne vient PAS de l'app : Energy.GetPowerBalance
la publie telle quelle sur .75. Trois des quatre compteurs cumulés sont corrompus
(totalReturn 9,1e+33, totalAcquisition 7,5e+33, totalConsumption -1,6e+33) alors que
totalProduction reste sain, et que les états du Thing compteur sont tous plausibles
(1429 kWh importés, 88 kWh exportés). C'est donc l'accumulation de l'experience-plugin
énergie qui déraille, côté box — signalé, pas corrigé ici.
Les deux autres défauts étaient bien dans l'app :
- « Depuis réseau » lisait l'OPPOSÉ du compteur d'export au lieu de totalAcquisition,
qui a son propre compteur. Dès que l'export était positif, la tuile affichait
0,0 kWh en permanence, quelle que soit l'électricité réellement achetée ;
- les deux tuiles étaient libellées « aujourd'hui » alors que ces compteurs sont
CUMULÉS depuis l'origine, jamais remis à zéro.
Corrigé : EnergyData porte gridExportKwh / gridImportKwh, transportés tels quels — l'app
ne maquille pas une donnée que la box publie fausse. Un plafond de plausibilité
(10 GWh, ~3000 ans de consommation) distingue « mesure » de « compteur cassé » : au-delà
la tuile affiche « — · compteur box invalide ». Imprimer le nombre le présenterait comme
une mesure ; l'effacer laisserait croire à zéro.
2) Thème : 126 sites basculés des constantes claires vers les variantes contextuelles
(EtmTokens.bg → bgOf(context), card → surfaceOf, ink → inkOf, muted → mutedOf,
faint → faintOf, line → lineOf) dans ac_screen, things_screen, energy_screen,
favorites_screen, main_drawer, ev_charging_card, energy_flow_widget. Ces écrans
restaient en palette claire quel que soit le sélecteur.
9 sites RESTENT en constante, et c'est délibéré : ce sont des tables statiques et des
helpers de haut niveau (categoryInfoMap, _options des favoris, _modeColor, peintres du
flux) où la couleur est une identité d'icône et où aucun BuildContext n'est en portée.
Les faire suivre le thème demande de threader le contexte jusqu'à ces tables — un
refactor à part entière, pas un correctif de fin de soirée.
Tests 80/80, analyze 0 erreur.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HajXLUczEyZd22JeewRfff
167 lines
6.0 KiB
Dart
167 lines
6.0 KiB
Dart
class EnergyData {
|
|
final double pvPower; // Watts - production solaire
|
|
final double homePower; // Watts - consommation maison
|
|
final double batteryPower; // Watts - puissance batterie (+ charge, - décharge)
|
|
final double gridPower; // Watts - réseau (+ injection, - soutif)
|
|
final double batterySOC; // % - état de charge batterie
|
|
final double temperature; // °C
|
|
final String weatherIcon;
|
|
|
|
// Journée
|
|
final double dayProductionWh;
|
|
final double daySelfConsumptionWh;
|
|
final double dayGridInjectionWh;
|
|
/// Compteurs CUMULÉS de la box (kWh), tels qu'elle les publie — pas des totaux du jour.
|
|
///
|
|
/// `Energy.GetPowerBalance` rend `totalReturn` (exporté) et `totalAcquisition`
|
|
/// (importé). Ils sont **cumulés depuis toujours**, pas remis à zéro chaque nuit : les
|
|
/// afficher sous un libellé « aujourd'hui » serait faux.
|
|
///
|
|
/// `NaN` signifie **valeur non exploitable**, et c'est un état à part entière : le banc
|
|
/// `.75` publie des compteurs manifestement corrompus (7,5e+33 kWh importés) alors que
|
|
/// `totalProduction` reste sain. L'app ne les corrige pas — elle refuse de les
|
|
/// présenter comme une mesure (cf. [gridExportKwhOrNull]).
|
|
final double gridExportKwh;
|
|
final double gridImportKwh;
|
|
|
|
final double selfConsumptionRate; // %
|
|
final double autonomyRate; // %
|
|
final double dayGains; // €
|
|
|
|
// Borne de recharge
|
|
final ChargingMode chargingMode;
|
|
final double chargingPower; // kW
|
|
final double solarSourcePercent; // %
|
|
final bool gridLimitOk;
|
|
|
|
const EnergyData({
|
|
this.pvPower = 0,
|
|
this.homePower = 0,
|
|
this.batteryPower = 0,
|
|
this.gridPower = 0,
|
|
this.batterySOC = 0,
|
|
this.temperature = 0,
|
|
this.weatherIcon = 'cloud_snow',
|
|
this.dayProductionWh = 0,
|
|
this.daySelfConsumptionWh = 0,
|
|
this.dayGridInjectionWh = 0,
|
|
this.gridExportKwh = 0,
|
|
this.gridImportKwh = 0,
|
|
this.selfConsumptionRate = 0,
|
|
this.autonomyRate = 0,
|
|
this.dayGains = 0,
|
|
this.chargingMode = ChargingMode.pv,
|
|
this.chargingPower = 3.6,
|
|
this.solarSourcePercent = 82,
|
|
this.gridLimitOk = true,
|
|
});
|
|
|
|
EnergyData copyWith({
|
|
double? pvPower,
|
|
double? homePower,
|
|
double? batteryPower,
|
|
double? gridPower,
|
|
double? batterySOC,
|
|
double? temperature,
|
|
String? weatherIcon,
|
|
double? dayProductionWh,
|
|
double? daySelfConsumptionWh,
|
|
double? dayGridInjectionWh,
|
|
double? gridExportKwh,
|
|
double? gridImportKwh,
|
|
double? selfConsumptionRate,
|
|
double? autonomyRate,
|
|
double? dayGains,
|
|
ChargingMode? chargingMode,
|
|
double? chargingPower,
|
|
double? solarSourcePercent,
|
|
bool? gridLimitOk,
|
|
}) {
|
|
return EnergyData(
|
|
pvPower: pvPower ?? this.pvPower,
|
|
homePower: homePower ?? this.homePower,
|
|
batteryPower: batteryPower ?? this.batteryPower,
|
|
gridPower: gridPower ?? this.gridPower,
|
|
batterySOC: batterySOC ?? this.batterySOC,
|
|
temperature: temperature ?? this.temperature,
|
|
weatherIcon: weatherIcon ?? this.weatherIcon,
|
|
dayProductionWh: dayProductionWh ?? this.dayProductionWh,
|
|
daySelfConsumptionWh: daySelfConsumptionWh ?? this.daySelfConsumptionWh,
|
|
dayGridInjectionWh: dayGridInjectionWh ?? this.dayGridInjectionWh,
|
|
gridExportKwh: gridExportKwh ?? this.gridExportKwh,
|
|
gridImportKwh: gridImportKwh ?? this.gridImportKwh,
|
|
selfConsumptionRate: selfConsumptionRate ?? this.selfConsumptionRate,
|
|
autonomyRate: autonomyRate ?? this.autonomyRate,
|
|
dayGains: dayGains ?? this.dayGains,
|
|
chargingMode: chargingMode ?? this.chargingMode,
|
|
chargingPower: chargingPower ?? this.chargingPower,
|
|
solarSourcePercent: solarSourcePercent ?? this.solarSourcePercent,
|
|
gridLimitOk: gridLimitOk ?? this.gridLimitOk,
|
|
);
|
|
}
|
|
|
|
/// Plafond de plausibilité pour un compteur d'énergie domestique cumulé, en kWh.
|
|
///
|
|
/// 10 GWh, soit environ **trois mille ans** de consommation d'une maison. Aucune
|
|
/// installation résidentielle ne l'atteindra ; tout ce qui le dépasse est un compteur
|
|
/// cassé, pas un record. Le seuil est volontairement absurde-haut : il ne s'agit pas de
|
|
/// juger une valeur, seulement d'attraper les corrompues.
|
|
static const double kPlausibleMaxKwh = 1e7;
|
|
|
|
/// Vrai si [v] peut être présenté comme une mesure.
|
|
static bool isPlausibleKwh(double v) =>
|
|
v.isFinite && v >= 0 && v <= kPlausibleMaxKwh;
|
|
|
|
/// Export cumulé, ou `null` si la box publie une valeur inexploitable.
|
|
double? get gridExportKwhOrNull =>
|
|
isPlausibleKwh(gridExportKwh) ? gridExportKwh : null;
|
|
|
|
/// Import cumulé, ou `null` si la box publie une valeur inexploitable.
|
|
double? get gridImportKwhOrNull =>
|
|
isPlausibleKwh(gridImportKwh) ? gridImportKwh : null;
|
|
}
|
|
|
|
enum ChargingMode { pv, minPv, boost }
|
|
|
|
class HistoryPoint {
|
|
final DateTime time;
|
|
final double pvWh;
|
|
final double homeWh;
|
|
final double gridWh;
|
|
final double batteryWh;
|
|
|
|
const HistoryPoint({
|
|
required this.time,
|
|
this.pvWh = 0,
|
|
this.homeWh = 0,
|
|
this.gridWh = 0,
|
|
this.batteryWh = 0,
|
|
});
|
|
|
|
}
|
|
|
|
// ── Entrée Energy.GetPowerBalanceLogs ─────────────────────────────────────────
|
|
class PowerBalanceEntry {
|
|
final DateTime timestamp;
|
|
final double productionW; // puissance PV (valeur absolue, W)
|
|
final double consumptionW; // consommation maison (W)
|
|
final double acquisitionW; // import réseau (W, positif)
|
|
final double storageW; // batterie : +charge / -décharge (W)
|
|
final double totalProductionWh; // cumulé depuis l'origine (Wh)
|
|
final double totalConsumptionWh;
|
|
final double totalReturnWh; // injection réseau cumulée (Wh)
|
|
final double totalAcquisitionWh;
|
|
|
|
const PowerBalanceEntry({
|
|
required this.timestamp,
|
|
this.productionW = 0,
|
|
this.consumptionW = 0,
|
|
this.acquisitionW = 0,
|
|
this.storageW = 0,
|
|
this.totalProductionWh = 0,
|
|
this.totalConsumptionWh = 0,
|
|
this.totalReturnWh = 0,
|
|
this.totalAcquisitionWh = 0,
|
|
});
|
|
|
|
} |