powersync-energy-plugin-etm/integration_app_examples/examples_usage.dart

272 lines
12 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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