import 'dart:async'; import 'dart:convert'; import 'dart:io'; // §7-1 — aller-retour neutre : GetLoadConfig -> SetLoadConfig verbatim -> GetLoadConfig. // // ⚠️ SEUL SCRIPT DE tools/rpc/ QUI ÉCRIT SUR LA BOX. // `SetLoadConfig` remplace l'ENSEMBLE des charges et déclenche une réévaluation // des adaptateurs. Le contenu renvoyé est identique à ce qui vient d'être lu, donc // l'opération est neutre — mais elle reste une écriture sur une installation vivante. // Le drapeau --yes est obligatoire, précisément pour qu'elle ne parte jamais par // réflexe de flèche haut dans un terminal. // // Usage : dart tools/rpc/loadconfig_roundtrip.dart --yes Future main(List args) async { if (!args.contains('--yes')) { stderr.writeln('Ce script ÉCRIT sur la box (NymeaEnergy.SetLoadConfig).'); stderr.writeln('Relancer avec --yes pour confirmer :'); stderr.writeln(' dart tools/rpc/loadconfig_roundtrip.dart ' '${args.isNotEmpty ? args[0] : "192.168.1.75"} --yes'); exitCode = 2; return; } final host = args.isNotEmpty && !args.first.startsWith('--') ? args.first : '192.168.1.75'; final ws = await WebSocket.connect('ws://$host:4444'); var id = 0; final pending = >>{}; final notifs = []; ws.listen((raw) { final m = jsonDecode(raw as String) as Map; final rid = m['id']; if (rid is int && pending.containsKey(rid)) { pending.remove(rid)!.complete(m); } else if (m['notification'] != null) { notifs.add(m['notification'] as String); } }); Future> call(String me, [Map p = const {}]) { final i = ++id; final c = Completer>(); pending[i] = c; ws.add(jsonEncode({'id': i, 'method': me, 'params': p})); return c.future.timeout(const Duration(seconds: 20)); } await call('JSONRPC.Hello', {'locale': 'fr_FR'}); await call('JSONRPC.SetNotificationStatus', {'enabled': true}); final before = await call('NymeaEnergy.GetLoadConfig'); final cfgBefore = before['params']['loadConfigs'] as List; final jsonBefore = const JsonEncoder.withIndent(' ').convert(cfgBefore); print('--- AVANT ---\n$jsonBefore\n'); print('--- SetLoadConfig VERBATIM (aucune modification) ---'); final set = await call('NymeaEnergy.SetLoadConfig', {'loadConfigs': cfgBefore}); print('réponse: ${jsonEncode(set)}\n'); await Future.delayed(const Duration(seconds: 3)); final after = await call('NymeaEnergy.GetLoadConfig'); final cfgAfter = after['params']['loadConfigs'] as List; final jsonAfter = const JsonEncoder.withIndent(' ').convert(cfgAfter); print('--- notifications reçues pendant l\'opération ---'); print(notifs.isEmpty ? '(aucune)' : notifs.join('\n')); print('\n--- VERDICT ---'); if (jsonBefore == jsonAfter) { print('IDENTIQUE — aller-retour neutre OK'); } else { print('DIVERGENCE :'); print('APRES:\n$jsonAfter'); } await ws.close(); }