- Drawer custom (overlay Stack) avec mode installateur PIN SHA-256 - GoRouter + ShellRoute : navigation préservée entre onglets - 6 providers : NavigationProvider, InstallerModeProvider, AppSettingsProvider, EnergySetupProvider, SchedulerProvider, TariffProvider - Écrans Energy Manager : RoleConfigFlow (3 étapes), Scheduler, Tarifs, Timeline - Écrans Paramètres : Apparence, Écrans actifs, AppSettingsScreen - DrawerMenuButton présent dans les 5 AppBars principaux - Simulation : _thingClasses générées avec interfaces EMS pour filtrage des rôles - Compteur solaire : ajout smartmeter aux interfaces compatibles - Thème ETM (etm_theme.dart), ProLockBadge, widgets PowerBar/RoleCard/TimelineSlotCard - Dépendances : go_router, shared_preferences, crypto, url_launcher Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
134 lines
3.8 KiB
Dart
134 lines
3.8 KiB
Dart
import 'package:flutter/foundation.dart';
|
|
import 'package:flutter/material.dart' show TimeOfDay;
|
|
|
|
enum TariffProviderType {
|
|
manual, // Tarif manuel saisi par l'utilisateur
|
|
customJson,
|
|
linkyTIC,
|
|
tibberPro,
|
|
octopusPro,
|
|
entsoe,
|
|
jsonRpc,
|
|
}
|
|
|
|
extension TariffProviderTypeExt on TariffProviderType {
|
|
String get label => switch (this) {
|
|
TariffProviderType.manual => 'Tarif manuel',
|
|
TariffProviderType.customJson => 'Fichier JSON custom',
|
|
TariffProviderType.linkyTIC => 'Linky TIC',
|
|
TariffProviderType.tibberPro => 'Tibber',
|
|
TariffProviderType.octopusPro => 'Octopus',
|
|
TariffProviderType.entsoe => 'ENTSO-E',
|
|
TariffProviderType.jsonRpc => 'JSON-RPC externe',
|
|
};
|
|
bool get isPro => this == TariffProviderType.tibberPro ||
|
|
this == TariffProviderType.octopusPro ||
|
|
this == TariffProviderType.entsoe;
|
|
}
|
|
|
|
enum TariffMode {
|
|
spotMarket,
|
|
hchp, // Heures Creuses / Heures Pleines
|
|
tou, // TOU contractuel
|
|
fixed,
|
|
}
|
|
|
|
extension TariffModeExt on TariffMode {
|
|
String get label => switch (this) {
|
|
TariffMode.spotMarket => 'Spot Market',
|
|
TariffMode.hchp => 'Heures Creuses / Heures Pleines',
|
|
TariffMode.tou => 'TOU contractuel',
|
|
TariffMode.fixed => 'Tarif fixe',
|
|
};
|
|
}
|
|
|
|
class HcHpConfig {
|
|
final double offPeakPrice; // €/kWh HC
|
|
final double peakPrice; // €/kWh HP
|
|
final TimeOfDay offPeakStart;
|
|
final TimeOfDay offPeakEnd;
|
|
|
|
const HcHpConfig({
|
|
this.offPeakPrice = 0.096,
|
|
this.peakPrice = 0.146,
|
|
this.offPeakStart = const TimeOfDay(hour: 22, minute: 0),
|
|
this.offPeakEnd = const TimeOfDay(hour: 6, minute: 0),
|
|
});
|
|
|
|
HcHpConfig copyWith({
|
|
double? offPeakPrice,
|
|
double? peakPrice,
|
|
TimeOfDay? offPeakStart,
|
|
TimeOfDay? offPeakEnd,
|
|
}) => HcHpConfig(
|
|
offPeakPrice: offPeakPrice ?? this.offPeakPrice,
|
|
peakPrice: peakPrice ?? this.peakPrice,
|
|
offPeakStart: offPeakStart ?? this.offPeakStart,
|
|
offPeakEnd: offPeakEnd ?? this.offPeakEnd,
|
|
);
|
|
}
|
|
|
|
class CurrentPrices {
|
|
final double now;
|
|
final double inOneHour;
|
|
final double min24h;
|
|
final double max24h;
|
|
final DateTime? minTime;
|
|
final DateTime? maxTime;
|
|
|
|
const CurrentPrices({
|
|
this.now = 0,
|
|
this.inOneHour = 0,
|
|
this.min24h = 0,
|
|
this.max24h = 0,
|
|
this.minTime,
|
|
this.maxTime,
|
|
});
|
|
}
|
|
|
|
/// Gère le provider tarifaire actif, le mode et les prix courants.
|
|
class TariffProvider extends ChangeNotifier {
|
|
TariffProviderType _activeProvider = TariffProviderType.manual;
|
|
TariffMode _mode = TariffMode.fixed;
|
|
double _manualPrice = 0.25; // €/kWh tarif manuel
|
|
HcHpConfig _hchp = const HcHpConfig();
|
|
CurrentPrices _prices = const CurrentPrices(
|
|
now: 0.092, inOneHour: 0.085,
|
|
min24h: 0.048, max24h: 0.182,
|
|
);
|
|
bool _loading = false;
|
|
|
|
TariffProviderType get activeProvider => _activeProvider;
|
|
TariffMode get mode => _mode;
|
|
HcHpConfig get hchp => _hchp;
|
|
CurrentPrices get prices => _prices;
|
|
bool get loading => _loading;
|
|
double get manualPrice => _manualPrice;
|
|
|
|
Future<void> load() async {
|
|
_loading = true;
|
|
notifyListeners();
|
|
await Future.delayed(const Duration(milliseconds: 200));
|
|
_loading = false;
|
|
notifyListeners();
|
|
// TODO: charger depuis nymea RPC
|
|
}
|
|
|
|
void setProvider(TariffProviderType p) {
|
|
_activeProvider = p; notifyListeners();
|
|
}
|
|
|
|
void setMode(TariffMode m) {
|
|
_mode = m; notifyListeners();
|
|
}
|
|
|
|
void updateHcHp(HcHpConfig c) {
|
|
_hchp = c; notifyListeners();
|
|
}
|
|
|
|
void setManualPrice(double price) {
|
|
_manualPrice = price.clamp(0.001, 9.999);
|
|
notifyListeners();
|
|
}
|
|
}
|