Énergie : - Écran Énergie reécrit : line chart (production/conso/autoconso/batterie) et bar chart (bilan Wh par période) avec onglets 15 min / 1 h / 1 j / 1 sem - Datepicker pour sélectionner une période historique (chip dismissible) - Timelines des deux graphiques alignées (même x=i → data[i].timestamp) - PowerBalanceEntry + fetchPowerBalanceLogs() + simulation sinusoïdale - Overflow fixes : energy_flow_widget (Expanded sur titre), production_card Things : - Navigation 3 niveaux : ThingsScreen → CategoryOverviewScreen → ThingDetailScreen - Catégorie Cars ajoutée, carrousel corrigé (clamp RangeError) - ThingDetailScreen : executeAction, setStateValue, activeThumbColor fix - NymeaTile widget, state_history_chart widget (générique Logging.GetLogEntries) Modèles / service : - HistoryEntry, PowerBalanceEntry ajoutés - fetchHistory(), fetchPowerBalanceLogs() dans NymeaService - interfaceToCategoryMap étendu (Cars, etc.) - AppTheme : nouvelles couleurs (accentTeal, boostRed, pvGreen, minPvBlue…) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
132 lines
4.3 KiB
Dart
132 lines
4.3 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;
|
|
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.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? 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,
|
|
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,
|
|
);
|
|
}
|
|
}
|
|
|
|
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,
|
|
});
|
|
|
|
/// Autoconsommation instantanée (W) = production locale non injectée au réseau.
|
|
double get autoconsommationW =>
|
|
(consumptionW + (storageW > 0 ? storageW : 0))
|
|
.clamp(0.0, productionW)
|
|
.toDouble();
|
|
} |