fix(banc): l'adresse du banc passe à 10.42.60.21 — sondes, tests on-device, consignes

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>
This commit is contained in:
Patrick Schurig 2026-10-13 06:37:33 +02:00
parent d6240984ee
commit bedeabf767
19 changed files with 44 additions and 41 deletions

View File

@ -3,9 +3,12 @@
---
# ssh banc .75
Accès banc `.75` : ssh etm@192.168.1.75 (clé déjà installée).
# ssh banc (ex-`.75`)
Accès banc `hems` : ssh etm@10.42.60.21 (clé déjà installée).
Ni root ni nymea n'existent. Journal : journalctl -u nymead.
Renumérotée le 2026-10-12 (était `192.168.1.75`) : `10.42.60.0/24`, passerelle
`10.42.60.1`, DHCP sur le dongle USB `enxa0cec879e2b1`. Les relevés et fixtures
antérieurs écrivent `.75` / `hems75` — même machine, non réécrits.
---
## Mon rôle
@ -719,9 +722,9 @@ celle qu'on avait regardée.
- Piloter un EV = `NymeaEnergy.SetChargingInfo` (`Energy.SetChargingMode` n'existe pas)
- **Vérifier ce fichier contre `JSONRPC.Introspect` avant chaque lot.** Trois fois le
2026-08-25, la doc locale était en retard sur la machine et a envoyé un agent dans le vide.
La sonde tient en une ligne : `dart tools/rpc/probe.dart 192.168.1.75 JSONRPC.Introspect`
La sonde tient en une ligne : `dart tools/rpc/probe.dart 10.42.60.21 JSONRPC.Introspect`
- **Et vérifier la VERSION POSÉE avant de croire une livraison annoncée**, en une ligne aussi :
`ssh etm@192.168.1.75 'dpkg -l | grep powersync-energy'`. Le 2026-08-30, `+etm31` était
`ssh etm@10.42.60.21 'dpkg -l | grep powersync-energy'`. Le 2026-08-30, `+etm31` était
annoncé sur la box : le code était écrit, le cross-build jamais fait, la box portait `+etm30`
et la clé attendue n'existait pas. **Annoncé ≠ construit ≠ posé** — et un champ absent parce
qu'il n'est pas déployé se lit exactement comme un champ absent parce qu'il est omis.

View File

@ -96,7 +96,7 @@ Trois paquets, tous **présents dans le dépôt apt du banc** (`apt-cache search
le 2026-08-27) :
```sh
ssh etm@192.168.1.75
ssh etm@10.42.60.21
sudo apt install nymea-plugin-generic-heatingcooling \
nymea-plugin-generic-sensors
# optionnel, pour le drapeau WindowOpen :

View File

@ -395,7 +395,7 @@ unitaire qui construit ses deux côtés avec la même convention passe aussi. Tr
dans cet ordre :
1. **Sonder les deux appels côte à côte** et comparer les charges utiles brutes, pas les
modèles Dart — `dart tools/rpc/probe.dart 192.168.1.75 <Méthode>` pour chacun.
modèles Dart — `dart tools/rpc/probe.dart 10.42.60.21 <Méthode>` pour chacun.
2. **Éprouver le rapprochement lui-même**, sur les deux formes réelles. Les tests d'accolades
(`test/merged_config_screen_test.dart`) sont écrits exactement pour ça, avec les deux
graphies de la même borne.

View File

@ -41,7 +41,7 @@ import 'package:integration_test/integration_test.dart';
import 'package:provider/provider.dart';
/// La box de banc. `nymea-dev-rpi` doit être déjà enregistrée sur l'appareil.
const _hote = '192.168.1.75';
const _hote = '10.42.60.21';
/// PIN installateur par défaut, posé au premier démarrage tant qu'aucun n'a été choisi.
const _pinInstallateur = '1234';

View File

@ -30,7 +30,7 @@ import 'package:go_router/go_router.dart';
import 'package:integration_test/integration_test.dart';
import 'package:provider/provider.dart';
const _hote = '192.168.1.75';
const _hote = '10.42.60.21';
Future<void> _attendre(
WidgetTester tester,

View File

@ -45,7 +45,7 @@ import 'package:go_router/go_router.dart';
import 'package:integration_test/integration_test.dart';
import 'package:provider/provider.dart';
const _hote = '192.168.1.75';
const _hote = '10.42.60.21';
const _pinInstallateur = '1234';
/// Cible tactile minimale retenue. Android recommande 48 dp ; 44 est le plancher au-dessous

View File

@ -338,7 +338,7 @@ class _AddManualSheetState extends State<_AddManualSheet> {
child: _Field(
controller: _host,
label: 'Hôte',
hint: '192.168.1.75',
hint: '10.42.60.21',
keyboardType: TextInputType.url,
onSubmitted: (_) => _submit(),
),

View File

@ -10,7 +10,7 @@ qu'une lecture de code ou qu'un `Introspect` recopié de mémoire.
Aucune dépendance hors SDK : `dart:io` + `dart:convert`. Rien à installer.
```bash
dart tools/rpc/<script>.dart [host] [args…] # host par défaut : 192.168.1.75
dart tools/rpc/<script>.dart [host] [args…] # host par défaut : 10.42.60.21
```
## Les scripts
@ -118,10 +118,10 @@ dart tools/rpc/<script>.dart [host] [args…] # host par défaut : 192.168.1
### `probe.dart`
```bash
dart tools/rpc/probe.dart 192.168.1.75 NymeaEnergy.GetLoadConfig
dart tools/rpc/probe.dart 192.168.1.75 JSONRPC.Introspect > introspect.json
dart tools/rpc/probe.dart 192.168.1.75 Integrations.GetThings
dart tools/rpc/probe.dart 192.168.1.75 NymeaEnergy.GetChargingInfos '{"evChargerId":"…"}'
dart tools/rpc/probe.dart 10.42.60.21 NymeaEnergy.GetLoadConfig
dart tools/rpc/probe.dart 10.42.60.21 JSONRPC.Introspect > introspect.json
dart tools/rpc/probe.dart 10.42.60.21 Integrations.GetThings
dart tools/rpc/probe.dart 10.42.60.21 NymeaEnergy.GetChargingInfos '{"evChargerId":"…"}'
```
Le `Hello` part toujours en premier et son contenu va sur **stderr**, la réponse sur
@ -130,7 +130,7 @@ Le `Hello` part toujours en premier et son contenu va sur **stderr**, la répons
### `notifications.dart`
```bash
dart tools/rpc/notifications.dart 192.168.1.75 90 # écoute 90 s
dart tools/rpc/notifications.dart 10.42.60.21 90 # écoute 90 s
```
Utile pour répondre à « est-ce que cette information franchit la frontière RPC ? ». Un
@ -147,7 +147,7 @@ change quelque chose ?** Relevé du 2026-08-25 sur `.75` — sur 784 chaînes af
### `loadconfig_roundtrip.dart` — ⚠️ écrit
```bash
dart tools/rpc/loadconfig_roundtrip.dart 192.168.1.75 --yes
dart tools/rpc/loadconfig_roundtrip.dart 10.42.60.21 --yes
```
`SetLoadConfig` **remplace l'ensemble** des charges. Le contenu renvoyé est identique à ce
@ -159,13 +159,13 @@ Pour confirmer qu'aucune reconstruction d'adaptateurs n'a lieu (ECS-412, `m_buil
`sameHardware()`), lire le journal de la box en parallèle :
```bash
ssh etm@192.168.1.75 'journalctl -u nymead -f'
ssh etm@10.42.60.21 'journalctl -u nymead -f'
```
### `telemetry_watch.dart`
```bash
dart tools/rpc/telemetry_watch.dart 192.168.1.75 240 # écoute 240 s
dart tools/rpc/telemetry_watch.dart 10.42.60.21 240 # écoute 240 s
```
Répond à deux questions que la lecture de code ne tranche pas : **une trame arrive-t-elle
@ -177,7 +177,7 @@ d'une minute, et une trame de changement significatif dans la foulée.
### `evcharger_watch.dart`
```bash
dart tools/rpc/evcharger_watch.dart 192.168.1.75 600 V2C # 600 s, bornes dont le nom contient « V2C »
dart tools/rpc/evcharger_watch.dart 10.42.60.21 600 V2C # 600 s, bornes dont le nom contient « V2C »
```
`telemetry_watch.dart` ne montre une borne que si elle est **arbitrée** ; sans véhicule
@ -195,7 +195,7 @@ deux ne doit être affiché tant que le plugin n'a pas publié `sessionEnergy` e
### `measurement_check.dart`
```bash
dart run tools/rpc/measurement_check.dart 192.168.1.75
dart run tools/rpc/measurement_check.dart 10.42.60.21
```
⚠️ `dart run` : la sonde **importe le modèle de l'app** (`LoadTelemetryEntry.fromJson`)
@ -211,8 +211,8 @@ sont en `meter` (1 500 W et 800 W), la V2C est absente — pas `none`.
### `domain_assign.dart` — ⚠️ écrit
```bash
dart run tools/rpc/domain_assign.dart 192.168.1.75 --set chauffe-eau=ecs --set pac-terrain=hvac --yes
dart run tools/rpc/domain_assign.dart 192.168.1.75 --clear --yes # tout déclasser
dart run tools/rpc/domain_assign.dart 10.42.60.21 --set chauffe-eau=ecs --set pac-terrain=hvac --yes
dart run tools/rpc/domain_assign.dart 10.42.60.21 --clear --yes # tout déclasser
```
⚠️ `dart run` et non `dart` : ce script **importe le code de l'app**
@ -224,9 +224,9 @@ est réelle.
### `fault_probe.dart` — ⚠️ écrit, et ajoute une charge fictive
```bash
dart run tools/rpc/fault_probe.dart 192.168.1.75 --yes
dart run tools/rpc/fault_probe.dart 192.168.1.75 --yes --dump fixtures_defaut
dart run tools/rpc/fault_probe.dart 192.168.1.75 --restore-only --yes
dart run tools/rpc/fault_probe.dart 10.42.60.21 --yes
dart run tools/rpc/fault_probe.dart 10.42.60.21 --yes --dump fixtures_defaut
dart run tools/rpc/fault_probe.dart 10.42.60.21 --restore-only --yes
```
Ajoute une charge `etmvariableload` dont le ThingId n'existe pas, attend deux cycles,
@ -264,5 +264,5 @@ menti deux secondes plus tard.
| Cible | Particularité |
|---|---|
| `192.168.1.75` | **ouverte** (`authenticationRequired: false`) — aucune auth à gérer dans les sondes. Deux charges depuis le plugin `1.15.2+etm15` : `chauffe-eau` (relay-router, `ecs`) et `pac-terrain` (sg-ready, `hvac`). |
| `10.42.60.21` | **ouverte** (`authenticationRequired: false`) — aucune auth à gérer dans les sondes. Deux charges depuis le plugin `1.15.2+etm15` : `chauffe-eau` (relay-router, `ecs`) et `pac-terrain` (sg-ready, `hvac`). |
| `192.168.1.120` | **auth requise** — ces sondes ne gèrent PAS `Authenticate`. À étendre avant usage. |

View File

@ -19,7 +19,7 @@ import 'package:etm_powersync_app/services/load_priority.dart';
// moteur n'en dépend. L'écriture reste réelle et déclenche une réévaluation des
// adaptateurs — d'où le --yes, et d'où l'intérêt de lire le journal en parallèle :
//
// ssh etm@192.168.1.75 'journalctl -u nymead -f'
// ssh etm@10.42.60.21 'journalctl -u nymead -f'
//
// Usage :
// dart run tools/rpc/domain_assign.dart <host> --set chauffe-eau=ecs --set pac-terrain=hvac --yes
@ -62,7 +62,7 @@ Future<void> main(List<String> args) async {
}
final host =
args.isNotEmpty && !args.first.startsWith('--') ? args.first : '192.168.1.75';
args.isNotEmpty && !args.first.startsWith('--') ? args.first : '10.42.60.21';
final ws = await WebSocket.connect('ws://$host:4444')
.timeout(const Duration(seconds: 8));

View File

@ -21,9 +21,9 @@ import 'dart:io';
// N'ÉCRIT RIEN : ni action, ni configuration. Elle s'abonne et regarde.
//
// Usage : dart tools/rpc/evcharger_watch.dart [host] [durée_s] [filtre_nom]
// dart tools/rpc/evcharger_watch.dart 192.168.1.75 600 V2C
// dart tools/rpc/evcharger_watch.dart 10.42.60.21 600 V2C
Future<void> main(List<String> args) async {
final host = args.isNotEmpty ? args[0] : '192.168.1.75';
final host = args.isNotEmpty ? args[0] : '10.42.60.21';
final seconds = args.length > 1 ? int.parse(args[1]) : 300;
final filtre = args.length > 2 ? args[2].toLowerCase() : '';

View File

@ -67,7 +67,7 @@ Future<void> main(List<String> args) async {
}
final restoreOnly = args.contains('--restore-only');
final host =
args.isNotEmpty && !args.first.startsWith('--') ? args.first : '192.168.1.75';
args.isNotEmpty && !args.first.startsWith('--') ? args.first : '10.42.60.21';
final di = args.indexOf('--dump');
final dumpPrefix = (di >= 0 && di + 1 < args.length) ? args[di + 1] : null;

View File

@ -17,13 +17,13 @@ Future<void> main(List<String> args) async {
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');
'${args.isNotEmpty ? args[0] : "10.42.60.21"} --yes');
exitCode = 2;
return;
}
final host = args.isNotEmpty && !args.first.startsWith('--')
? args.first
: '192.168.1.75';
: '10.42.60.21';
final ws = await WebSocket.connect('ws://$host:4444');
var id = 0;
final pending = <int, Completer<Map<String, dynamic>>>{};

View File

@ -60,7 +60,7 @@ Future<void> sample(Rpc rpc, String tag) async {
}
Future<void> main(List<String> args) async {
final host = args.isNotEmpty ? args[0] : '192.168.1.75';
final host = args.isNotEmpty ? args[0] : '10.42.60.21';
print('=== 1. Deux connexions SIMULTANÉES, locales différentes ===');
final de = await open(host, 'de_DE');

View File

@ -44,7 +44,7 @@ void flatten(dynamic node, String path, Map<String, String> out) {
}
Future<void> main(List<String> args) async {
final host = args.isNotEmpty ? args[0] : '192.168.1.75';
final host = args.isNotEmpty ? args[0] : '10.42.60.21';
final locales = ['en_US', 'de_DE', 'fr_FR', 'it_IT', 'es_ES', 'nl_NL'];
final maps = <String, Map<String, String>>{};

View File

@ -16,7 +16,7 @@ import 'package:etm_powersync_app/models/load_telemetry.dart';
//
// LECTURE SEULE. Usage : dart run tools/rpc/measurement_check.dart [host]
Future<void> main(List<String> args) async {
final host = args.isNotEmpty ? args[0] : '192.168.1.75';
final host = args.isNotEmpty ? args[0] : '10.42.60.21';
final ws = await WebSocket.connect('ws://$host:4444')
.timeout(const Duration(seconds: 8));
final done = Completer<Map<String, dynamic>>();

View File

@ -3,7 +3,7 @@ import 'dart:convert';
import 'dart:io';
Future<void> main(List<String> args) async {
final host = args.isNotEmpty ? args[0] : '192.168.1.75';
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;

View File

@ -5,7 +5,7 @@ import 'dart:io';
// Sonde JSON-RPC read-only contre le HEMS .75.
// Usage: dart probe.dart <host> <method> [jsonParams]
Future<void> main(List<String> args) async {
final host = args.isNotEmpty ? args[0] : '192.168.1.75';
final host = args.isNotEmpty ? args[0] : '10.42.60.21';
final method = args.length > 1 ? args[1] : 'NymeaEnergy.GetLoadConfig';
final params = args.length > 2
? jsonDecode(args[2]) as Map<String, dynamic>

View File

@ -10,7 +10,7 @@ import 'dart:io';
import 'package:etm_powersync_app/models/energy_ratios_snapshot.dart';
Future<void> main(List<String> args) async {
final host = args.isNotEmpty ? args[0] : '192.168.1.75';
final host = args.isNotEmpty ? args[0] : '10.42.60.21';
final ws = await WebSocket.connect('ws://$host:4444')
.timeout(const Duration(seconds: 8));
var id = 0;

View File

@ -17,7 +17,7 @@ import 'dart:io';
//
// Usage : dart tools/rpc/telemetry_watch.dart [host] [durée_s]
Future<void> main(List<String> args) async {
final host = args.isNotEmpty ? args[0] : '192.168.1.75';
final host = args.isNotEmpty ? args[0] : '10.42.60.21';
final seconds = args.length > 1 ? int.parse(args[1]) : 180;
final ws = await WebSocket.connect('ws://$host:4444')