272 lines
12 KiB
Dart
272 lines
12 KiB
Dart
// ============================================================
|
||
// examples_usage.dart
|
||
// Exemples d'utilisation du NymeaClient depuis etm_powersync_app
|
||
// ============================================================
|
||
|
||
import 'nymea_client.dart';
|
||
|
||
// UUIDs des stateTypes du chargeur mock (interface evcharger)
|
||
// À remplacer par les UUIDs réels de votre plugin d'intégration
|
||
const kStatePluggedIn = '13f8f008-aa70-4772-9fb8-81a9674dd6ad';
|
||
const kStateCharging = '63879844-6342-45ed-8e97-276e0f3092e5';
|
||
const kStatePower = '13672543-9344-4d55-afd6-6393ae052f18';
|
||
const kStateMaxCurrent = 'e7566b5b-8258-486e-b0ed-42a1bee332d9';
|
||
|
||
// UUID fournisseurs spot market
|
||
const kProviderAwattarAustria = '5196b3cc-b2ee-46d6-b63a-7af2cf70ba67';
|
||
const kProviderAwattarGermany = '0ca6ad88-e243-438d-a0f8-986cecf61834';
|
||
|
||
// ─────────────────────────────────────────────────────────────
|
||
// EXEMPLE 1 — Connexion et authentification complète
|
||
// ─────────────────────────────────────────────────────────────
|
||
Future<NymeaClient?> example1_connect() async {
|
||
print('\n=== Exemple 1 : Connexion à nymea ===');
|
||
|
||
final client = NymeaClient(host: '192.168.1.100', port: 2222);
|
||
|
||
try {
|
||
await client.connect();
|
||
|
||
// Première utilisation : créer l'utilisateur
|
||
// await client.createUser('admin@etm.local', 'MonMotDePasse!');
|
||
|
||
// Authentification (récupère un token)
|
||
final token = await client.authenticate(
|
||
'admin@etm.local',
|
||
'MonMotDePasse!',
|
||
'etm_powersync_app',
|
||
);
|
||
|
||
if (token == null) {
|
||
print('Échec de l\'authentification');
|
||
return null;
|
||
}
|
||
|
||
// Conserver le token en stockage sécurisé (FlutterSecureStorage, etc.)
|
||
// await secureStorage.write(key: 'nymea_token', value: token);
|
||
|
||
print('Connecté avec succès ! Token : ${token.substring(0, 8)}...');
|
||
return client;
|
||
} catch (e) {
|
||
print('Erreur : $e');
|
||
return null;
|
||
}
|
||
}
|
||
|
||
// ─────────────────────────────────────────────────────────────
|
||
// EXEMPLE 2 — Récupérer tous les chargeurs VE du plugin
|
||
// ─────────────────────────────────────────────────────────────
|
||
Future<void> example2_getEvChargers(NymeaClient client) async {
|
||
print('\n=== Exemple 2 : Récupération des chargeurs VE ===');
|
||
|
||
// Récupère tous les Things qui implémentent l'interface "evcharger"
|
||
final chargers = await client.getThingsByInterface('evcharger');
|
||
|
||
print('${chargers.length} chargeur(s) trouvé(s) :');
|
||
for (final charger in chargers) {
|
||
print(' - ${charger['name']} (id: ${charger['id']})');
|
||
print(' thingClassId: ${charger['thingClassId']}');
|
||
}
|
||
|
||
// Récupère les infos de smart charging via NymeaEnergy
|
||
final chargingInfos = await client.getChargingInfos();
|
||
print('\nInfos de charge :');
|
||
for (final info in chargingInfos) {
|
||
print(' Chargeur ${info.evChargerId}');
|
||
print(' Mode : ${info.chargingMode}');
|
||
print(' État : ${info.chargingState}');
|
||
print(' Spot market: ${info.spotMarketChargingEnabled}');
|
||
print(' Cible : ${info.targetPercentage}%');
|
||
}
|
||
}
|
||
|
||
// ─────────────────────────────────────────────────────────────
|
||
// EXEMPLE 3 — Lire un State spécifique (puissance actuelle)
|
||
// ─────────────────────────────────────────────────────────────
|
||
Future<void> example3_readState(NymeaClient client, String chargerId) async {
|
||
print('\n=== Exemple 3 : Lecture d\'un State ===');
|
||
|
||
// Lire si une voiture est branchée
|
||
final pluggedIn = await client.getStateValue(chargerId, kStatePluggedIn);
|
||
print('Voiture branchée : $pluggedIn');
|
||
|
||
// Lire l'état de charge
|
||
final charging = await client.getStateValue(chargerId, kStateCharging);
|
||
print('En charge : $charging');
|
||
|
||
// Lire la limite de courant max configurée par le SmartChargingManager
|
||
final maxCurrent = await client.getStateValue(chargerId, kStateMaxCurrent);
|
||
print('Courant max actuel : ${maxCurrent}A');
|
||
|
||
// Lire la limite de phase via NymeaEnergy
|
||
final phasePowerLimit = await client.getPhasePowerLimit();
|
||
print('Limite par phase : ${phasePowerLimit}A');
|
||
}
|
||
|
||
// ─────────────────────────────────────────────────────────────
|
||
// EXEMPLE 4 — Exécuter des Actions et configurer le smart charging
|
||
// ─────────────────────────────────────────────────────────────
|
||
Future<void> example4_executeActions(NymeaClient client, String chargerId) async {
|
||
print('\n=== Exemple 4 : Exécution d\'Actions ===');
|
||
|
||
// 4a) Définir la limite de puissance par phase (25A)
|
||
var result = await client.setPhasePowerLimit(25);
|
||
print('SetPhasePowerLimit(25A) → $result');
|
||
|
||
// 4b) Activer le mode Eco avec heure cible pour un chargeur
|
||
result = await client.setChargingInfo(
|
||
evChargerId: chargerId,
|
||
mode: ChargingMode.ecoWithTargetTime,
|
||
targetPercentage: 80,
|
||
// Heure cible : demain matin 7h00
|
||
endDateTime: DateTime.now()
|
||
.copyWith(hour: 7, minute: 0, second: 0)
|
||
.add(const Duration(days: 1))
|
||
.toIso8601String(),
|
||
spotMarketEnabled: true,
|
||
dailySpotMarketPercentage: 80,
|
||
);
|
||
print('SetChargingInfo(EcoWithTargetTime) → $result');
|
||
|
||
// 4c) Activer le spot market avec aWATTar Autriche
|
||
result = await client.setSpotMarketConfiguration(
|
||
enabled: true,
|
||
providerId: kProviderAwattarAustria,
|
||
);
|
||
print('SetSpotMarketConfiguration(aWATTar AT) → $result');
|
||
|
||
// 4d) Exécuter une Action native nymea sur un Thing
|
||
// (ex : forcer l'activation de la charge via le state writable "power")
|
||
final actionResult = await client.executeAction(
|
||
thingId: chargerId,
|
||
actionTypeId: kStatePower, // stateTypeId writable = actionTypeId implicite
|
||
params: {kStatePower: true}, // activer la charge
|
||
);
|
||
print('ExecuteAction(power=true) → $actionResult');
|
||
}
|
||
|
||
// ─────────────────────────────────────────────────────────────
|
||
// EXEMPLE 5 — Écouter les Events en temps réel (WebSocket push)
|
||
// ─────────────────────────────────────────────────────────────
|
||
Future<void> example5_listenToEvents(NymeaClient client) async {
|
||
print('\n=== Exemple 5 : Écoute des Events en temps réel ===');
|
||
|
||
// S'abonner aux namespaces qui nous intéressent
|
||
await client.subscribeToNotifications(['NymeaEnergy', 'Integrations']);
|
||
|
||
// Écouter les changements de config de charge
|
||
client.onChargingInfoChanged.listen((info) {
|
||
print('[EVENT] ChargingInfoChanged:');
|
||
print(' Chargeur : ${info.evChargerId}');
|
||
print(' Nouvel état : ${info.chargingState}');
|
||
print(' Mode : ${info.chargingMode}');
|
||
});
|
||
|
||
// Écouter les mises à jour des prix spot
|
||
client.onSpotMarketScoreEntriesChanged.listen((entries) {
|
||
print('[EVENT] SpotMarketScoreEntriesChanged: ${entries.length} créneaux');
|
||
// Trouver le meilleur créneau (weighting le plus élevé)
|
||
if (entries.isNotEmpty) {
|
||
final best = entries.reduce((a, b) => a.weighting > b.weighting ? a : b);
|
||
print(' Meilleur créneau: ${best.startDateTime} → ${best.endDateTime}');
|
||
print(' Score: ${best.weighting.toStringAsFixed(2)} / Prix: ${best.value}€/MWh');
|
||
}
|
||
});
|
||
|
||
// Écouter les changements de plannings de charge
|
||
client.onChargingSchedulesChanged.listen((schedules) {
|
||
print('[EVENT] ChargingSchedulesChanged: ${schedules.length} créneaux planifiés');
|
||
for (final s in schedules) {
|
||
print(' ${s['startDateTime']} → ${s['endDateTime']}');
|
||
}
|
||
});
|
||
|
||
// Écouter toutes les notifications brutes (debug)
|
||
client.notifications.listen((msg) {
|
||
if (msg['notification']?.toString().startsWith('NymeaEnergy') ?? false) {
|
||
// Log toutes les notifs NymeaEnergy
|
||
print('[NOTIF] ${msg['notification']}');
|
||
}
|
||
});
|
||
|
||
print('En écoute... (Ctrl+C pour arrêter)');
|
||
// Dans une vraie app Flutter, cette écoute dure toute la vie du widget
|
||
await Future.delayed(const Duration(minutes: 5));
|
||
}
|
||
|
||
// ─────────────────────────────────────────────────────────────
|
||
// EXEMPLE 6 — Consultation des prix spot + plannings
|
||
// ─────────────────────────────────────────────────────────────
|
||
Future<void> example6_spotMarket(NymeaClient client) async {
|
||
print('\n=== Exemple 6 : Consultation du marché spot ===');
|
||
|
||
// Fournisseurs disponibles
|
||
final providers = await client.getAvailableSpotMarketProviders();
|
||
print('Fournisseurs disponibles :');
|
||
for (final p in providers) {
|
||
print(' ${p['name']} (${p['id']}) — ${p['country']}');
|
||
}
|
||
|
||
// Scores de prix pondérés pour aujourd'hui
|
||
final scores = await client.getSpotMarketScoreEntries();
|
||
print('\n${scores.length} créneaux de prix disponibles :');
|
||
|
||
// Trier par pondération (meilleur en premier)
|
||
scores.sort((a, b) => b.weighting.compareTo(a.weighting));
|
||
for (final s in scores.take(5)) {
|
||
print(
|
||
' ${s.startDateTime.hour}h–${s.endDateTime.hour}h : '
|
||
'${s.value.toStringAsFixed(1)}€/MWh '
|
||
'(score: ${(s.weighting * 100).round()}%)',
|
||
);
|
||
}
|
||
|
||
// Plannings de charge calculés par le SmartChargingManager
|
||
final schedules = await client.getChargingSchedules();
|
||
print('\nPlannings de charge :');
|
||
for (final s in schedules) {
|
||
print(' ${s['startDateTime']} → ${s['endDateTime']}');
|
||
final action = s['action'] as Map<String, dynamic>?;
|
||
if (action != null) {
|
||
print(' Activé: ${action['chargingEnabled']} '
|
||
'Courant: ${action['maxChargingCurrent']}A '
|
||
'Phases: ${action['desiredPhaseCount']}');
|
||
}
|
||
}
|
||
}
|
||
|
||
// ─────────────────────────────────────────────────────────────
|
||
// MAIN — Démonstration complète
|
||
// ─────────────────────────────────────────────────────────────
|
||
Future<void> main() async {
|
||
// 1. Connexion
|
||
final client = await example1_connect();
|
||
if (client == null) return;
|
||
|
||
// 2. Récupération des chargeurs
|
||
await example2_getEvChargers(client);
|
||
|
||
// Pour les exemples suivants, on prend le premier chargeur trouvé
|
||
final chargers = await client.getThingsByInterface('evcharger');
|
||
if (chargers.isEmpty) {
|
||
print('Aucun chargeur trouvé.');
|
||
await client.disconnect();
|
||
return;
|
||
}
|
||
final chargerId = chargers.first['id'] as String;
|
||
|
||
// 3. Lecture d'un state
|
||
await example3_readState(client, chargerId);
|
||
|
||
// 4. Exécution d'actions
|
||
await example4_executeActions(client, chargerId);
|
||
|
||
// 5. Écoute événements
|
||
// await example5_listenToEvents(client);
|
||
|
||
// 6. Spot market
|
||
await example6_spotMarket(client);
|
||
|
||
await client.disconnect();
|
||
}
|