docs(banc): protocole de qualification d'un plugin de borne, et son outil

Tiré de la campagne V2C du 2026-08-28, mais écrit pour TOUTE borne — Keba,
go-e et les suivantes. Une demi-heure par borne, et le défaut ne se découvre
pas chez un client.

Trois questions dont aucune ne se lit dans la documentation :

1. sessionEnergy est-il publié, et QUAND est-il remis à zéro — au branchement,
   à l'arrêt de la charge, ou jamais ? Une borne peut publier un compteur exact
   et pourtant inutilisable, parce qu'il n'est pas conservé : c'est le cas de la
   V2C, effacement à chaque arrêt de charge, câble encore branché. Ne se voit
   qu'en débranchant. Séparer exactitude et conservation.
2. pluggedIn clignote-t-il ? Neuf secondes de faux débranchement mesurées sur la
   V2C au redémarrage de la borne. Toute logique déclenchée par un débranchement
   doit être confirmée sur plusieurs polls RÉUSSIS — et un poll en échec ne doit
   pas compter comme une absence, sinon la coupure réseau fabrique le
   débranchement qu'on filtrait.
3. currentPower est-il une mesure ou la consigne renvoyée ? Symptôme : une
   valeur trop belle, qui suit la commande sans retard. C'est ce que
   measurement.source distingue côté moteur (INTERFACE.md, LM-1105).

Deux pièges de lecture payés pendant la campagne, écrits pour n'être payés
qu'une fois : un délai de confirmation se compte en polls et non en secondes
(3 polls à 30 s = 60 s, pas 90) ; et sur lien dégradé la durée perd son sens
(à 70 % de perte, 3 polls réussis d'affilée demandent ~26 min en espérance).

tools/qualifier-borne.sh est le squelette : il suit le journal, n'imprime que
les transitions, horodate, et refuse de tourner si la catégorie de log du plugin
n'est pas active — sans quoi il tournerait en silence et on conclurait à tort
que la borne ne fait rien. Aucune adresse codée en dur (cf. § Miroir public).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A41CTzMvir1Y5ABPXW8xpB
This commit is contained in:
Patrick Schurig 2026-08-28 14:37:37 +02:00
parent fd94362e27
commit c54718d337

59
tools/qualifier-borne.sh Executable file
View File

@ -0,0 +1,59 @@
#!/usr/bin/env bash
# qualifier-borne.sh — squelette de qualification d'un plugin de borne sur banc.
#
# Suit le journal nymead et n'imprime que les TRANSITIONS : les événements de
# branchement vus par le moteur, et les traces du plugin qualifié. Horodate
# chaque ligne pour qu'on puisse mesurer les écarts (délai de confirmation d'un
# débranchement, durée d'un faux positif, latence d'une consigne).
#
# Il ne conclut rien : il rend le cycle LISIBLE. Les trois questions auxquelles
# il sert à répondre sont dans AGENTS.md § QUALIFIER UN PLUGIN DE BORNE.
#
# ./qualifier-borne.sh <hôte> <catégorie-de-log> [utilisateur]
# ./qualifier-borne.sh 10.0.0.12 V2C
# ./qualifier-borne.sh 10.0.0.12 Keba admin
#
# La catégorie est celle du Q_LOGGING_CATEGORY du plugin (« V2C », « Keba »…) ;
# elle doit être activée côté box, sinon les traces du plugin n'existent pas :
# Environment="QT_LOGGING_RULES=<Catégorie>.debug=true"
# dans un drop-in systemd de nymead, puis daemon-reload + restart.
#
# Aucune adresse n'est codée en dur : cf. AGENTS.md § Miroir public.
set -uo pipefail
HOTE="${1:-}"
CATEGORIE="${2:-}"
UTILISATEUR="${3:-etm}"
if [ -z "$HOTE" ] || [ -z "$CATEGORIE" ]; then
sed -n '2,20p' "$0"
exit 2
fi
SSH=(ssh -o BatchMode=yes -o ConnectTimeout=10 -o ServerAliveInterval=30
"${UTILISATEUR}@${HOTE}")
# Garde-fou : sans la catégorie activée, le script tournerait en silence et on
# conclurait à tort « la borne ne fait rien ». Mieux vaut refuser tout de suite.
if ! "${SSH[@]}" 'systemctl show nymead -p Environment --value' \
| grep -q "${CATEGORIE}.debug=true"; then
echo "!! ${CATEGORIE}.debug n'est PAS actif sur ${HOTE}." >&2
echo " Les traces du plugin ne seront pas journalisées — activer la" >&2
echo " catégorie dans un drop-in systemd de nymead, puis relancer." >&2
exit 1
fi
echo "=== qualification : ${CATEGORIE} sur ${HOTE} — Ctrl-C pour arrêter ==="
echo " cycle à jouer : brancher → charger → ARRÊTER LA CHARGE (câble en"
echo " place) → débrancher → rebrancher. Relever les valeurs à chaque"
echo " transition ; les écarts de temps se lisent dans l'horodatage."
echo
# « plugged in / unplugged » viennent du MOTEUR : c'est ce que verrait un
# consommateur naïf de pluggedIn. Les comparer aux traces du plugin est
# précisément ce qui révèle un faux positif de débranchement.
"${SSH[@]}" 'journalctl -u nymead -f -n0 --no-pager' 2>&1 \
| grep --line-buffered -iE "${CATEGORIE}|plugged in|unplugged" \
| while IFS= read -r ligne; do
printf '%s | %s\n' "$(date '+%T')" "$ligne"
done