etm-powersync-app/lib/models/energy_data.dart
pakutz79 8862dc2a72 feat: historique énergie, navigation Things, actions nymea
É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>
2026-02-23 07:15:48 +01:00

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();
}