Le banc `hems` est renuméroté (192.168.1.75 → 10.42.60.21). Portés : les 11 sondes `tools/rpc/*` et leur README, les 3 tests on-device, le `hint` de l'écran Installations, les procédures de CLAUDE.md et des deux documents de cadrage. Ce qui n'est PAS touché, et c'est délibéré : les relevés datés (RELEVE_LOTC, RECAP, Prompt 3g2, maquettes) et les fixtures `hems75_*.json`. Un relevé daté dit ce qui a été observé ce jour-là ; le réécrire échange une trace contre une cohérence de surface. CLAUDE.md porte la note qui fait le lien : `.75` et `hems75` désignent la même machine. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
56 lines
1.7 KiB
Dart
56 lines
1.7 KiB
Dart
import 'dart:async';
|
|
import 'dart:convert';
|
|
import 'dart:io';
|
|
|
|
Future<void> main(List<String> args) async {
|
|
final host = args.isNotEmpty ? args[0] : '10.42.60.21';
|
|
final secs = args.length > 1 ? int.parse(args[1]) : 90;
|
|
final ws = await WebSocket.connect('ws://$host:4444');
|
|
var id = 0;
|
|
final pending = <int, Completer<Map<String, dynamic>>>{};
|
|
final counts = <String, int>{};
|
|
final samples = <String, String>{};
|
|
|
|
ws.listen((raw) {
|
|
final m = jsonDecode(raw as String) as Map<String, dynamic>;
|
|
final rid = m['id'];
|
|
if (rid is int && pending.containsKey(rid)) {
|
|
pending.remove(rid)!.complete(m);
|
|
return;
|
|
}
|
|
final n = m['notification'] as String?;
|
|
if (n != null) {
|
|
counts[n] = (counts[n] ?? 0) + 1;
|
|
samples.putIfAbsent(n, () => jsonEncode(m['params']));
|
|
}
|
|
});
|
|
|
|
Future<Map<String, dynamic>> call(String meth, [Map<String, dynamic> p = const {}]) {
|
|
final i = ++id;
|
|
final c = Completer<Map<String, dynamic>>();
|
|
pending[i] = c;
|
|
ws.add(jsonEncode({'id': i, 'method': meth, 'params': p}));
|
|
return c.future.timeout(const Duration(seconds: 15));
|
|
}
|
|
|
|
await call('JSONRPC.Hello');
|
|
final r = await call('JSONRPC.SetNotificationStatus', {'enabled': true});
|
|
print('Namespaces abonnés: ${r['params']['namespaces']}');
|
|
print('Écoute ${secs}s…\n');
|
|
|
|
await Future<void>.delayed(Duration(seconds: secs));
|
|
|
|
print('--- notifications reçues en ${secs}s ---');
|
|
final keys = counts.keys.toList()..sort();
|
|
for (final k in keys) {
|
|
print('${counts[k]!.toString().padLeft(4)} $k');
|
|
}
|
|
print('\n--- premier échantillon par type ---');
|
|
for (final k in keys) {
|
|
var s = samples[k]!;
|
|
if (s.length > 260) s = '${s.substring(0, 260)}…';
|
|
print('$k\n $s');
|
|
}
|
|
await ws.close();
|
|
}
|