docs: recalage sur la rév. 3 du contrat charge pilotée
Le miroir INTERFACE_etmvariableload.md est passé en rév. 3 pendant la session (corps
identique au canonique du dépôt plugin, vérifié). Son §10 s'adresse nommément à l'agent
app — et il RATIFIE les maquettes dessinées aujourd'hui : relays[] = {thingId, powerW}
pour l'ECS relais, maxPowerW seul pour le continu, powerLevels absents de la config et
dérivés par le routeur.
Trois recalages :
- Le picker de relais filtre sur l'interface nymea « power » et présente les things par
NOM — nommé dans la maquette, il ne l'était pas.
- Le point 4 du brief plugin est tranché par la rév. 3 : la duplication de la
combinatoire est voulue (l'app dérive pour montrer, le routeur pour exécuter). La
demande devient donc un moyen de détecter la divergence — la télémétrie publie déjà
maxStageW, l'app peut y confronter le maximum de sa propre liste.
- En-tête du pont VM Service, que le commit précédent avait laissé dans sa forme brute.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XPUo3RMr8SzK6qbFtfBm8H
This commit is contained in:
parent
a4487324dc
commit
eac1dde4ee
@ -129,9 +129,22 @@ combinatoire de `relayrouter.cpp` (toutes les combinaisons 2^N, doublons écart
|
||||
16 relais). Deux implémentations d'une même règle divergeront : à la première correction
|
||||
côté moteur, l'app annoncera des paliers que la box n'atteint plus.
|
||||
|
||||
**Demande.** Exposer la liste — soit dans la télémétrie (`mechanism.stagesW: [...]`), soit en
|
||||
retour d'un `GetLoadConfig` enrichi. À défaut, **le dire explicitement**, et l'app
|
||||
documentera sa dérivation comme un miroir à resynchroniser.
|
||||
**⚠️ Tranché par la rév. 3 du contrat, arrivée pendant la rédaction de ce brief.**
|
||||
`INTERFACE_etmvariableload.md` §10 dit désormais : l'assistant calcule et **affiche** les
|
||||
paliers atteignables côté app, et ces `powerLevels` ne sont **pas** envoyés — ils sont
|
||||
« dérivés côté plugin ». La duplication est donc **voulue et contractuelle** : l'app dérive
|
||||
pour montrer, le routeur dérive pour exécuter.
|
||||
|
||||
**Ce qui reste, et qui devient la vraie demande :** un moyen de vérifier que les deux
|
||||
dérivations n'ont pas divergé. Il existe déjà à moitié — la télémétrie publie
|
||||
`mechanism.maxStageW`. L'app peut donc comparer **le maximum de sa propre liste** à celui que
|
||||
la box annonce, et se taire si ça correspond, alerter sinon. Ça ne couvre pas les paliers
|
||||
intermédiaires, mais ça attrape le cas qui compte : une règle de combinatoire changée d'un
|
||||
côté seulement.
|
||||
|
||||
**Demande minimale** : confirmer que `maxStageW` reste bien le maximum atteignable et non un
|
||||
plafond de sécurité — sinon la comparaison ne vaut rien. **Demande confortable** : publier la
|
||||
liste complète (`mechanism.stagesW: [...]`), et l'app cessera de dériver.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@ -288,6 +288,9 @@
|
||||
créent pas de palier supplémentaire — les doublons sont écartés.</em>
|
||||
</div>
|
||||
|
||||
<div class="mode-hint"><b>Le picker liste les things par NOM</b>, filtrés sur
|
||||
l'interface nymea <code>power</code> — taper un UUID au doigt est une erreur
|
||||
garantie. Il résout nom → ThingId et n'ajoute aucun champ au contrat.</div>
|
||||
<div class="mode-hint"><b>Un ECS simple, c'est un seul relais</b> — deux paliers, 0 et P. Une
|
||||
résistance multipalier en déclare 2, 3 ou 4. La puissance saisie est celle de la
|
||||
<b>résistance</b>, pas le calibre du contacteur : rien dans nymea ne dit ce qu'un relais
|
||||
|
||||
@ -2,14 +2,32 @@ import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
// Capte les traces `dart:developer log()` de l'app en cours d'exécution.
|
||||
// Pont VM Service — rend visibles les traces `dart:developer log()` de l'app.
|
||||
//
|
||||
// `flutter run` ne les imprime PAS sur stdout (elles partent au VM Service, pas à
|
||||
// stdout ni à logcat). Sans ce pont, tout ce que `NymeaService._log()` journalise est
|
||||
// invisible depuis le poste — donc les traces de locale, de télémétrie et d'écriture
|
||||
// aussi.
|
||||
// ## Pourquoi ce fichier existe
|
||||
//
|
||||
// Usage : dart vm_logs.dart ws://127.0.0.1:PORT/TOKEN=/ws
|
||||
// `flutter run` **n'imprime pas** ces traces sur stdout : elles partent au VM Service, ni sur
|
||||
// la console, ni dans `logcat`. Tout ce que `NymeaService._log()` journalise — locale demandée
|
||||
// et retenue, aller-retours RPC, séquence d'écriture, télémétrie poussée — est donc invisible
|
||||
// depuis le poste tant qu'on n'est pas branché ici.
|
||||
//
|
||||
// Éprouvé le 2026-08-25, premier passage de l'app sur appareil (Redmi Note 9S) : sans ce pont,
|
||||
// aucun constat du journal de vérification n'était atteignable.
|
||||
//
|
||||
// ## Usage
|
||||
//
|
||||
// flutter run -d <device> --use-application-binary=build/app/outputs/flutter-apk/app-debug.apk
|
||||
// # relever « A Dart VM Service on … is available at: http://127.0.0.1:PORT/TOKEN=/ »
|
||||
// dart tools/devlog/vm_logs.dart 'ws://127.0.0.1:PORT/TOKEN=/ws'
|
||||
//
|
||||
// Le `/ws` final est obligatoire, et les guillemets aussi — le jeton contient un `=`.
|
||||
//
|
||||
// ## Le piège d'horodatage, déjà payé une fois
|
||||
//
|
||||
// Le VM Service livre **l'historique bufférisé d'un coup** au moment du `streamListen`.
|
||||
// Horodater à la réception écrase donc toute la chronologie sous une seule seconde — c'est ce
|
||||
// qui est arrivé au premier essai. On lit `event.timestamp`, jamais `DateTime.now()`.
|
||||
|
||||
Future<void> main(List<String> args) async {
|
||||
final uri = args.first;
|
||||
final ws = await WebSocket.connect(uri);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user