- 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>
112 lines
3.7 KiB
Dart
112 lines
3.7 KiB
Dart
import 'dart:async';
|
|
import 'package:flutter/foundation.dart';
|
|
import '../services/nymea_service.dart';
|
|
|
|
enum SchedulerStrategy { rulesBased, manual, aiPro }
|
|
|
|
extension SchedulerStrategyExt on SchedulerStrategy {
|
|
String get label => switch (this) {
|
|
SchedulerStrategy.rulesBased => 'Basée sur les règles',
|
|
SchedulerStrategy.manual => 'Manuelle',
|
|
SchedulerStrategy.aiPro => 'AI (Pro)',
|
|
};
|
|
bool get isPro => this == SchedulerStrategy.aiPro;
|
|
}
|
|
|
|
class SchedulerConfig {
|
|
final double priceThreshold; // €/kWh
|
|
final double minSurplus; // W
|
|
final int planningHorizon; // heures
|
|
final int recalcInterval; // minutes
|
|
final double selfSufficiencyGoal; // %
|
|
|
|
const SchedulerConfig({
|
|
this.priceThreshold = 0.08,
|
|
this.minSurplus = 200,
|
|
this.planningHorizon = 24,
|
|
this.recalcInterval = 15,
|
|
this.selfSufficiencyGoal = 70,
|
|
});
|
|
|
|
SchedulerConfig copyWith({
|
|
double? priceThreshold,
|
|
double? minSurplus,
|
|
int? planningHorizon,
|
|
int? recalcInterval,
|
|
double? selfSufficiencyGoal,
|
|
}) => SchedulerConfig(
|
|
priceThreshold: priceThreshold ?? this.priceThreshold,
|
|
minSurplus: minSurplus ?? this.minSurplus,
|
|
planningHorizon: planningHorizon ?? this.planningHorizon,
|
|
recalcInterval: recalcInterval ?? this.recalcInterval,
|
|
selfSufficiencyGoal: selfSufficiencyGoal ?? this.selfSufficiencyGoal,
|
|
);
|
|
}
|
|
|
|
enum SchedulerStatus { ok, degraded, error }
|
|
|
|
class SchedulerState {
|
|
final SchedulerStatus status;
|
|
final String reason;
|
|
final DateTime? lastPlanning;
|
|
final DateTime? nextPlanning;
|
|
|
|
const SchedulerState({
|
|
this.status = SchedulerStatus.ok,
|
|
this.reason = '',
|
|
this.lastPlanning,
|
|
this.nextPlanning,
|
|
});
|
|
}
|
|
|
|
/// Gère la stratégie, la configuration et l'état du scheduler EMS.
|
|
class SchedulerProvider extends ChangeNotifier {
|
|
SchedulerStrategy _strategy = SchedulerStrategy.rulesBased;
|
|
SchedulerConfig _config = const SchedulerConfig();
|
|
SchedulerState _state = const SchedulerState();
|
|
bool _loading = false;
|
|
|
|
SchedulerStrategy get strategy => _strategy;
|
|
SchedulerConfig get config => _config;
|
|
SchedulerState get state => _state;
|
|
bool get loading => _loading;
|
|
|
|
// ── Chargement depuis nymea (stub — à brancher sur RPC réel) ────────────────
|
|
Future<void> load(NymeaService service) async {
|
|
_loading = true;
|
|
notifyListeners();
|
|
|
|
await Future.delayed(const Duration(milliseconds: 300));
|
|
_state = SchedulerState(
|
|
status: SchedulerStatus.ok,
|
|
reason: 'TariffManager: aWATTar AT actif',
|
|
lastPlanning: DateTime.now().subtract(const Duration(minutes: 8)),
|
|
nextPlanning: DateTime.now().add(const Duration(minutes: 7)),
|
|
);
|
|
_loading = false;
|
|
notifyListeners();
|
|
}
|
|
|
|
// ── Mutations ────────────────────────────────────────────────────────────────
|
|
void setStrategy(SchedulerStrategy s) {
|
|
_strategy = s;
|
|
notifyListeners();
|
|
// TODO: _sendRequest('Energy.SetSchedulerStrategy', ...)
|
|
}
|
|
|
|
void updateConfig(SchedulerConfig c) {
|
|
_config = c;
|
|
notifyListeners();
|
|
// TODO: _sendRequest('Energy.SetSchedulerConfig', ...)
|
|
}
|
|
|
|
Future<void> forceRecalc(NymeaService service) async {
|
|
_loading = true;
|
|
notifyListeners();
|
|
await Future.delayed(const Duration(seconds: 1));
|
|
_state = _state; // Mettre à jour depuis la réponse RPC
|
|
_loading = false;
|
|
notifyListeners();
|
|
}
|
|
}
|