Range dans tools/rpc/ les sondes qui vivaient dans un scratchpad volatil : probe (appel RPC quelconque), notifications (abonnement + comptage), locale et locale_diff (comportement o:locale et son effet réel), loadconfig_roundtrip (aller-retour neutre §7-1). README avec usages. loadconfig_roundtrip est le SEUL qui écrit sur la box : garde --yes ajouté pour qu'un SetLoadConfig ne parte jamais par réflexe de flèche haut. analysis_options : tools/** et les classes l10n générées sortent de l'analyse — flutter analyze revient à 25 issues (ligne de base). Fixtures : le lot plugin télémétrie EST déployé sur .75 depuis ce matin (20 méthodes / 14 notifications). Capturé avant que ça ne se reperde : - loadtelemetry_hems75.json : dump réel de GetLoadTelemetry - loadconfig_hems75_v2.json : GetLoadConfig avec la clé 'domain' - schema_hems75_v2.json : schémas SET + télémétrie introspectés Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
71 lines
2.5 KiB
Dart
71 lines
2.5 KiB
Dart
import 'dart:async';
|
|
import 'dart:convert';
|
|
import 'dart:io';
|
|
|
|
Future<Map<String, dynamic>> dump(String host, String? locale) async {
|
|
final ws = await WebSocket.connect('ws://$host:4444');
|
|
var id = 0;
|
|
final pending = <int, Completer<Map<String, dynamic>>>{};
|
|
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);
|
|
});
|
|
Future<Map<String, dynamic>> call(String m, [Map<String, dynamic> p = const {}]) {
|
|
final i = ++id;
|
|
final c = Completer<Map<String, dynamic>>();
|
|
pending[i] = c;
|
|
ws.add(jsonEncode({'id': i, 'method': m, 'params': p}));
|
|
return c.future.timeout(const Duration(seconds: 20));
|
|
}
|
|
await call('JSONRPC.Hello', locale == null ? {} : {'locale': locale});
|
|
final tc = await call('Integrations.GetThingClasses', {});
|
|
final vd = await call('Integrations.GetVendors', {});
|
|
final pl = await call('Integrations.GetPlugins', {});
|
|
await ws.close();
|
|
return {'tc': tc['params'], 'vd': vd['params'], 'pl': pl['params']};
|
|
}
|
|
|
|
/// Aplatit TOUTES les chaînes affichables en chemin -> valeur.
|
|
void flatten(dynamic node, String path, Map<String, String> out) {
|
|
if (node is Map) {
|
|
for (final e in node.entries) {
|
|
final k = e.key.toString();
|
|
if (k == 'displayName' || k == 'displayNames' || k == 'displayMessage') {
|
|
if (e.value is String) out['$path.$k'] = e.value as String;
|
|
}
|
|
flatten(e.value, '$path.$k', out);
|
|
}
|
|
} else if (node is List) {
|
|
for (var i = 0; i < node.length; i++) {
|
|
flatten(node[i], '$path[$i]', out);
|
|
}
|
|
}
|
|
}
|
|
|
|
Future<void> main(List<String> args) async {
|
|
final host = args.isNotEmpty ? args[0] : '192.168.1.75';
|
|
final locales = ['en_US', 'de_DE', 'fr_FR', 'it_IT', 'es_ES', 'nl_NL'];
|
|
final maps = <String, Map<String, String>>{};
|
|
|
|
for (final l in locales) {
|
|
final d = await dump(host, l);
|
|
final f = <String, String>{};
|
|
flatten(d, 'root', f);
|
|
maps[l] = f;
|
|
print('$l : ${f.length} chaînes affichables');
|
|
}
|
|
|
|
final ref = maps['en_US']!;
|
|
print('\n--- différences par rapport à en_US ---');
|
|
for (final l in locales.where((e) => e != 'en_US')) {
|
|
final m = maps[l]!;
|
|
final diffs = <String>[];
|
|
for (final k in ref.keys) {
|
|
if (m.containsKey(k) && m[k] != ref[k]) diffs.add('$k : "${ref[k]}" -> "${m[k]}"');
|
|
}
|
|
print('$l : ${diffs.length} chaîne(s) différente(s)');
|
|
for (final d in diffs.take(12)) print(' $d');
|
|
}
|
|
}
|