Concierge: declenche au BRANCHEMENT (transition on de evenement) au lieu de la session ; helper porte 'branchement' (ts::text verbatim) ; fraicheur [on-10, min(now, on+30)]. Moniteur LLM/RAM (llm-monitor.js) : endpoint spark + RAM, alerte WhatsApp sur changement d'etat, publie l'etat dans HA (last_seen a chaque passage) + interrupteur de pilotage. Docs: SPEC a jour, MONITORING-LLM.md, brouillons de config HA. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RZsbhyGmRwZogdoBwT6C6y
328 lines
22 KiB
Markdown
328 lines
22 KiB
Markdown
# Concierge véhicule Airtria — spécification (convenue OpenClaw ↔ EVCS, 2026-09-13)
|
||
|
||
## 🔁 MISE À JOUR 2026-09-15 : déclenchement AU BRANCHEMENT (plus à la session)
|
||
Le propriétaire veut la question dès le BRANCHEMENT (au branchement du soir, la borne
|
||
ne tire rien avant les HC de 01:24 ; attendre une session laissait la 1re mal étiquetée).
|
||
concierge-live.js détecte désormais sur les transitions 'on' de `evenement` (plus sur
|
||
session_charge). Le helper porte `branchement` = **ts::text VERBATIM** de la transition
|
||
'on' (PAS horodatage_ha, antérieur de 3-51 s → EVCS raterait le branchement en cours),
|
||
qui remplace `sessions`. Fraîcheur = sélecteur changé dans [on−10 min, min(now, on+30 min)]
|
||
(EVCS). Règle de puissance abandonnée au branchement (pas de session/p_max) → on demande
|
||
pour TOUT branchement périmé, invité géré par la réponse. Division : Airtria détecte le
|
||
branchement + demande + publie ; EVCS résout, mémorise, applique aux sessions du câble au
|
||
fur et à mesure (HC 01:24 comprises), refuse les contradictions. Validé contre l'historique
|
||
(15 branchements, distribution de fraîcheur inchangée) ; déployé, test de portée vert.
|
||
|
||
## 🟢 LIVE EN PRODUCTION depuis 2026-09-14 02:22
|
||
Kill-switch airtria_concierge_enabled = ON, lecteur EVCS déployé (commit d8ef69b).
|
||
Preuve end-to-end réelle : session 12/09 11:55 → JEEP, vehicule_sur=t, evenement
|
||
origine=airtria/source_airtria=whatsapp ; cycle suivant idempotent (etiquette=0).
|
||
Colonne : 6 confirmées (arbitrages voix du 13/09) / 13 à confirmer. Défaut vehicule_sur
|
||
basculé à false, 17 lignes rattrapées. Bug de format clef (PG `…+02` vs ISO `…Z`, même
|
||
instant) attrapé au dry-run EVCS et corrigé côté service (canonisation ISO avant dédup) —
|
||
côté Airtria rien à changer, on envoie la clef verbatim. Véhicule débranché 14/09 01:31 :
|
||
prochaine question sur un branchement neuf. Le concierge tourne en régime réel.
|
||
|
||
## VALIDÉ END-TO-END (2026-09-13, essai réel, kill-switch OFF)
|
||
Simulation sur le branchement 12/09 11:55 : détection → question WhatsApp → réponse
|
||
« JEEP » du propriétaire → routage → helper publié
|
||
`{"sessions":["2026-09-12 11:55:54.493+02"],"label":"JEEP","confirmed_at":…,"source":"whatsapp"}`
|
||
→ confirmation « ✅ Noté ». Base non touchée (kill-switch OFF).
|
||
⚠️ LEÇON ROUTAGE : le modèle local (qwen) IGNORE une consigne de réponse discrète
|
||
(a répondu « Bonjour Thierry » au lieu de router). Il faut un RÉFLEXE PRIORITAIRE en
|
||
tête du traitement WhatsApp (AGENTS.md §5.0) : vérifier concierge-pending.json et lancer
|
||
`answer` AVANT toute autre réponse. Avec ça, le routage passe de façon fiable.
|
||
Cron `concierge-vehicule` ACTIVÉ (enabled) → mode essai : une vraie charge à sélecteur
|
||
périmé déclenchera une vraie question. Reste pour appliquer en base : kill-switch ON +
|
||
lecteur EVCS (après validation de son dry-run).
|
||
|
||
## État d'avancement (2026-09-13)
|
||
Fichiers dans le workspace : `concierge-detection.js` (détection + calibration),
|
||
`concierge-write.js` (écriture helper, entité unique + relecture),
|
||
`concierge-write.test.js` (test de portée, VERT), `concierge-live.js`
|
||
(sous-commandes `detect` et `answer`). Dépendance `pg` installée dans le workspace.
|
||
TESTÉ : calibration 2-3-2-1-1-1 / 5 questions / 0 mixte ; aller-retour écriture sur
|
||
le vrai helper ; detect bootstrap ; chemin question (état en attente, clef debut
|
||
verbatim) ; chemin réponse (reconnaissance + publication + confirmation).
|
||
CÂBLÉ : cron `concierge-vehicule` (id d113b997-0942-4d71-9e9b-d64249949540, payload
|
||
COMMAND `node concierge-live.js detect`, */10, announce whatsapp) — testé : exitCode 0,
|
||
sortie vide → delivery suppressReason "empty" (aucun WhatsApp vide). Routage des réponses
|
||
ajouté à AGENTS.md §5bis (sauvegarde AGENTS.md.bak-concierge-*). pg installé dans le
|
||
workspace.
|
||
ACTIVATION PAR ÉTAPES (toutes décisions du propriétaire) :
|
||
(1) `openclaw cron enable d113b997-…` → boucle Q/R en réel, le helper se publie sur une
|
||
vraie réponse. La BASE n'est pas touchée.
|
||
(2) EVCS déploie son lecteur en DRY-RUN (redémarre son service) : il journalise ce qu'il
|
||
écrirait (jointure ±1 s sur les clefs verbatim, extension au groupe) SANS écrire.
|
||
Valide la moitié EVCS avant que ça compte.
|
||
(3) kill-switch `input_boolean.airtria_concierge_enabled` → ON + EVCS commit la bascule
|
||
→ les étiquettes corrigent session_charge.
|
||
⚠️ La bascule vehicule_sur n'est PAS neutralisée par le kill-switch : le kill-switch gate
|
||
l'APPLICATION d'un label, pas le DEFAULT de la colonne. Passer DEFAULT false trop tôt
|
||
afficherait 100 % de sessions « douteuses » (motif faux) sur le Grafana « Les véhicules ».
|
||
Donc la bascule = TROIS pièces soudées au commit du ON : DEFAULT false + true-sur-
|
||
confirmation-humaine + libellé Grafana « selecteur change » → honnête.
|
||
Décision COMMAND vs agentTurn : command choisi car déterministe (pas de LLM, sortie exacte,
|
||
suppression auto sur vide). Cron existants modèles : daily-email-report (Gmail 8h30),
|
||
orange-cloture (17h40).
|
||
|
||
|
||
Objectif : combler le seul trou qu'aucun capteur ne comble — savoir QUEL véhicule
|
||
(VW / JEEP / invité / bientôt moto ZERO) est branché sur la borne EVCS, pour que
|
||
`session_charge` cesse d'attribuer l'énergie au mauvais véhicule.
|
||
|
||
Contexte déclencheur : le sélecteur `input_select.victron_evcs_vehicle` est resté
|
||
figé sur « VW » du 07/09 au 13/09 → 11 sessions d'affilée mal étiquetées, sans
|
||
aucun signal. VW et JEEP sont électriquement indiscernables l'une de l'autre
|
||
(~3 680 vs ~3 655 W à 20 A).
|
||
|
||
## Principe d'architecture (non négociable)
|
||
- Le cœur déterministe EVCS reste seul juge. Airtria intervient APRÈS, jamais
|
||
dans la boucle 30 s.
|
||
- Une seule main sur chaque variable. Airtria ne touche AUCUN actionneur.
|
||
- Toute valeur porte son propre horodatage (`confirmed_at`), pas celui du run.
|
||
- Producteur qui s'arrête : invalidation STRUCTURELLE (le label est lié à une
|
||
session précise, il ne peut pas contaminer une autre session). On NE vide PAS
|
||
le helper (fenêtre de perte inutile) ; on laisse la dernière confirmation.
|
||
|
||
## Décisions du propriétaire (2026-09-13)
|
||
- Lancement v0 + v1 ENSEMBLE.
|
||
- Canal de correction = écriture HA restreinte `input_text.airtria_*`
|
||
(variante PostgreSQL INSERT-only écartée).
|
||
|
||
## Détection d'une session (v0)
|
||
- Source = table PostgreSQL `session_charge`, PAS le binary_sensor HA (il flappe :
|
||
disconnected x2 câble branché le 07/09).
|
||
- ⚠️ NE PAS utiliser `evcs_lecture` : il a INSERT sur `evenement` (registre
|
||
d'audit partagé) — inadapté à un agent. Rôle DÉDIÉ `airtria_ro`, LOGIN +
|
||
SELECT sur `session_charge` et `evenement` uniquement, aucune écriture.
|
||
Mot de passe déposé protégé dans le workspace (.pg-airtria). Base evcs sur
|
||
10.10.10.22:5433.
|
||
- Colonnes utiles (session_charge, 17 col) : `debut` (clef, MS), `fin`,
|
||
`terminee`, `vehicule`, `vehicule_sur` (DEFAULT true → à basculer côté service),
|
||
`p_max_w` + `consigne_max_a` + `courant_max_a` (règle invité), `debranche_a`
|
||
(frontière de groupe), `energie_compteur_kwh` (l'énergie qui FAIT FOI, pas
|
||
`energie_kwh` qui rate si le service démarre après le début de charge).
|
||
- On hérite du débounce du service d'historisation : une ligne `session_charge`
|
||
ne s'ouvre qu'au-delà de 300 W soutenus, se ferme après 10 min sous le seuil.
|
||
- Cadence : cron 10 min. La latence n'a aucun effet (session de plusieurs heures).
|
||
- Airtria garde son propre état (dernière `debut` traitée) dans son workspace.
|
||
|
||
## Test d'ambiguïté (quand poser la question) — RÈGLE FINALE
|
||
- Le sélecteur est FRAIS (ne pas demander) SEULEMENT s'il a changé de valeur dans
|
||
la fenêtre [début du branchement − 10 min, début + 30 min]. Sinon → DEMANDER.
|
||
Source : `evenement` (genre='intervention', entite=input_select.victron_evcs_vehicle),
|
||
JAMAIS le `last_changed` HA. Implémenté : `selectorFreshAt()` dans concierge-live.js.
|
||
- Pourquoi la fenêtre serrée (EVCS, données) : un changement de sélecteur EN COURS de
|
||
branchement ne peut pas étiqueter ce branchement (câble non bougé) — c'est le
|
||
producteur mécanique des groupes mixtes. Ma 1ère règle (« bougé depuis le débranchement
|
||
précédent ») déclarait « frais » EXACTEMENT les 2 branchements mixtes de l'historique.
|
||
- Validé sur 11 branchements 04-12/09 : 1 seul FRAIS (05/09, réglé à +13 min), 10 à
|
||
DEMANDER dont les 2 mixtes. Stat marquante : sélecteur réglé au bon moment 1 fois / 12.
|
||
- Mauvais test (rejeté) : « sélecteur inchangé depuis le début de CETTE session »
|
||
— vrai aussi quand le propriétaire a bien réglé au branchement.
|
||
- Avant de conclure « pas de geste humain », vérifier la table `evenement`
|
||
(un redémarrage HA a pu changer la valeur ; l'auteur y est tracé depuis le 12/09).
|
||
- ✅ CAVEAT `last_changed` (2026-09-13) CORRIGÉ : le `last_changed` HA est remis à zéro
|
||
par un passage `unavailable` (blip MQTT) sans vrai changement → il ferait croire
|
||
« frais » un sélecteur périmé. La règle ci-dessus lit donc `evenement` (qui saute les
|
||
lectures unavailable), pas `last_changed`. Limites de la source : le journal commence
|
||
le 04/09 ; la mémoire du détecteur est en-processus (un changement pendant un
|
||
redémarrage du service n'est pas rattrapé) → l'absence d'événement ne prouve pas tout,
|
||
mais dans le doute la règle DEMANDE = le bon côté.
|
||
- En cas de doute : poser la question. Un WhatsApp de trop coûte moins qu'une
|
||
ligne fausse pour toujours.
|
||
|
||
## Pré-filtre puissance (réduit les questions) — règle À SENS UNIQUE
|
||
- Le bon critère n'est pas la puissance brute mais la puissance RELATIVE À LA
|
||
CONSIGNE. VW/JEEP saturent vers 16 A embarqués quelle que soit la consigne
|
||
(~3 606 à 3 784 W à 20 A) ; la Megane a suivi jusqu'à 28 A (6 360 W).
|
||
- Règle conclusive : `consigne_max_a >= 20` ET `p_max_w > 4200` ⟹ **invité**,
|
||
Airtria pré-étiquette « invité » SANS déranger le propriétaire.
|
||
- `consigne_max_a < 20` ⟹ AUCUNE information (6 A plafonne ~1 700 W pour tout le
|
||
monde) → demander.
|
||
- ⚠️ La réciproque est FAUSSE : `p_max_w <= 4200` ne prouve PAS que c'est un
|
||
véhicule du foyer (un invité à 16 A embarqués est indiscernable de la VW).
|
||
Au-dessus du seuil on sait, en dessous on demande. NE JAMAIS inverser.
|
||
- La consigne vient du contrôleur EVCS : plafond 20 A hors BOOST
|
||
(`input_number.evcs_plafond_courant_edf_on`, 28 en BOOST). Le cas conclusif
|
||
est donc fréquent ; le cas muet = sessions à courant réduit (fin de charge
|
||
solaire à 6 A).
|
||
- Moto ZERO (fin sept. 2026) : tombera sous 3,6 kW → côté foyer, distinguée par
|
||
le sélecteur comme les autres. Seuil à réévaluer à son arrivée.
|
||
|
||
## Regroupement = frontière FACTUELLE via `evenement` (pas le temps)
|
||
- ⚠️ Ne PAS regrouper par écart de temps : le creux soir→heures creuses fait
|
||
~5 h 20 (fin solaire ~20:00 → HC ~01:24), indistinguable d'un vrai
|
||
débranchement/rebranchement par un seuil de durée.
|
||
- La frontière est un FAIT : les transitions de
|
||
`binary_sensor.victron_evcs_vehicle_connected` sont écrites dans `evenement`
|
||
(off→on au branchement, on→off au débranchement). Un branchement = intervalle
|
||
[off→on … on→off suivant]. Toutes les lignes `session_charge` dont `debut`
|
||
tombe dans l'intervalle = même véhicule = UNE seule question. Intervalle ouvert
|
||
(encore branché) = groupe en cours.
|
||
- Exemple semaine 08-12/09 : 6 branchements = 2-3-2-1-1-1 sessions
|
||
(le mercredi 15:55+19:35+01:25 est un TRIPLET, même câble). Un regroupement qui
|
||
rend des paires soir/nuit est FAUX.
|
||
- Le groupe reste la notion d'Airtria (propriétaire unique sur la notion dérivée) ;
|
||
le service EVCS ne fait qu'itérer la liste du helper.
|
||
- ⚠️ Ne PAS émettre une écriture helper par session (elles écraseraient le même
|
||
helper ; le service qui poll toutes les 60 s ne verrait que la dernière → perte
|
||
silencieuse des autres). Le helper porte donc une LISTE de session_debut (voir
|
||
ci-dessous), publiée en UNE écriture atomique. Le service itère la liste.
|
||
- Fallback coupure : les transitions ne sont écrites que si le service tourne.
|
||
Frontière absente/incomplète → groupe INCERTAIN → poser la question PAR session,
|
||
jamais sur une frontière reconstruite. Un WhatsApp de trop > une étiquette fausse.
|
||
|
||
## Sources de données (requêtes, lecture seule via airtria_ro)
|
||
- Frontière des branchements — table `evenement` (colonnes : ts, genre, source,
|
||
resume, detail jsonb, id). Filtre robuste (pas de parsing de texte) :
|
||
`detail->>'entite' = 'binary_sensor.victron_evcs_vehicle_connected'`,
|
||
`detail->>'apres'` = 'on' (branchement) / 'off' (débranchement). Ordonner sur
|
||
`ts`, borner les intervalles sur `detail->>'horodatage_ha'` (vérité physique
|
||
après rattrapage). Le champ `entite` n'existe que sur les transitions → les
|
||
fins de session sont exclues naturellement.
|
||
- Bonus qualité : les événements de fin de session portent `detail->>'debut'`
|
||
(= session_charge.debut exact, ms comprises) et les trois énergies côte à côte
|
||
(`kwh_compteur` fait foi, `kwh_integre`, `kwh_borne`). Un écart entre elles est
|
||
un signal de qualité à remonter (pas une question au propriétaire).
|
||
- Accès : Node + node-postgres (pur JS, à ajouter au workspace) ; PG:5433
|
||
joignable depuis la machine spark → calibration exécutable en lecture seule.
|
||
- Implémentation : `concierge-detection.js` (mode calibration, aucune écriture).
|
||
|
||
## La question WhatsApp
|
||
- Un seul message, au démarrage d'une session ambiguë (ou d'un groupe).
|
||
- Ouverte, pas binaire : « Quel véhicule est branché ? » avec options lues
|
||
dynamiquement dans le sélecteur + « aucune des deux / invité ».
|
||
- Porte la clef `debut` de la session pour permettre l'application a posteriori.
|
||
- Réponse possible des heures plus tard, ou jamais.
|
||
|
||
## Le helper HA (le contrat v1)
|
||
- `input_text.airtria_vehicle_label`, déclaré **max: 255** (défaut HA = 100 →
|
||
rejet silencieux ; incident vécu forecast_updated max:32 le 08/09).
|
||
- Contenu = UN JSON atomique portant une LISTE de sessions (atomicité
|
||
indispensable, HA n'a pas de transaction entre entités) :
|
||
{"sessions":["2026-09-08 19:39:12.334+02","2026-09-09 01:26:04.887+02"],
|
||
"label":"VW","confirmed_at":"<horodatage Airtria>","source":"whatsapp"}
|
||
- Chaque entrée de `sessions` = clef `debut` rendue par la requête SANS
|
||
reformatage (les `debut` portent les ms, ex. 2026-09-12 11:55:54.493+02 ; un
|
||
arrondi minute ne matcherait jamais ; pas d'aller-retour par un objet Date).
|
||
Le service EVCS joint sur ±1 s, pour chaque entrée de la liste.
|
||
- Taille : 2 sessions ≈ 150 car, 3 ≈ 180, sous 255. Au-delà, publier en deux
|
||
écritures espacées de > 90 s (le service aura polé entre les deux).
|
||
- Après CHAQUE écriture : relire l'état et vérifier qu'il est identique à l'envoi
|
||
(seul moyen de détecter un rejet silencieux HA).
|
||
- Auto-correction (« JEEP… non VW ») = republier avec `confirmed_at` plus récent ;
|
||
le service applique le dernier pour une `session_debut` donnée.
|
||
- On NE vide PAS le helper à {} : l'invalidation est structurelle (session_debut).
|
||
Le vidage ouvrirait une fenêtre de perte si le service est arrêté entre publication
|
||
et vidage.
|
||
|
||
## Garde-fous d'écriture (non négociables — restriction CONVENTIONNELLE)
|
||
Le canal choisi est un token HA, qui peut techniquement écrire n'importe quel
|
||
service HA : la restriction à airtria_* ne tient QUE par la discipline du code.
|
||
Donc, côté OpenClaw :
|
||
- Le nom de l'entité écrite est une CONSTANTE EN DUR unique
|
||
(`input_text.airtria_vehicle_label`), jamais construite dynamiquement, jamais
|
||
interpolée.
|
||
- Un test type « mode ombre » ÉCHOUE si une écriture cible autre chose que cette
|
||
constante (équivalent du tests/advisor/run.mjs d'EVCS qui garde advisor_*).
|
||
- Aucune écriture d'actionneur, jamais (liste des variables à propriétaire unique
|
||
dans le MANUEL EVCS ; `carte-decisions.mjs` / `enquete.mjs` avant tout doute).
|
||
|
||
## Recoupement a posteriori (qualité de données)
|
||
- Comparer `session_charge.debranche_a` aux départs attendus :
|
||
VW 08:50 (`input_datetime.victron_evcs_departure_time`),
|
||
JEEP 06:30 (`input_datetime.victron_evcs_departure_time_jeep`).
|
||
- `debranche_a` n'est renseignée que si le service voit le débranchement (1 fois
|
||
sur 12 récemment) → ne pas supposer qu'elle est toujours là.
|
||
- Ne signaler que si ça CONTREDIT le label (comportement idiot), pas à chaque
|
||
session. Pas de notification pour l'état normal.
|
||
|
||
## Côté service EVCS (v1, fait par la session EVCS)
|
||
- Lit le helper chaque cycle (60 s), JSON.parse en try/catch ; objet vide /
|
||
illisible / champs manquants → ne rien faire.
|
||
- `confirmed_at` antérieur au `debut` → ignoré. Jointure ±1 s sur session_debut.
|
||
- Met à jour `vehicule` ; `vehicule_sur` passe à VRAI uniquement sur confirmation
|
||
humaine (changement de sens : défaut basculé à faux ; lignes antérieures gardent
|
||
l'ancienne sémantique). Trace l'application dans `evenement` avec la source.
|
||
|
||
## Validation avant mise en service
|
||
- `tools/campagne-conseiller.mjs` (dépôt EVCS) rejoue des instants réels ;
|
||
cumuler 3 runs (un run de 5 passages = bruit, écart-type ~0,22).
|
||
- Jeu de calibrage = les 12 sessions du 07 au 12/09, étiquetées par le
|
||
propriétaire (voir ci-dessous). ⚠️ Le v0 ne DÉDUIT pas VW vs JEEP (impossible :
|
||
la semaine, la routine était inversée — femme/JEEP en congés, fils/VW en stage
|
||
sans retour le midi). Ce qui est testé = le ROUTAGE : MEGANE auto-détectée
|
||
invité par la règle puissance ; toutes les autres correctement routées vers
|
||
« demander » (sélecteur périmé). Ce sont les réponses du propriétaire qui
|
||
donnent VW/JEEP. Si le routage rate une des 12, revoir la règle, pas l'étiquette.
|
||
|
||
### Cibles de routage du v0 (les 6 branchements du 08-12/09)
|
||
- 11/09 16:53→18:27 (Megane, 1 session) : auto-invité par la règle puissance,
|
||
AUCUNE question.
|
||
- 5 autres branchements (2-3-2-1-1) : routés vers la question (sélecteur périmé).
|
||
- Total attendu = 5 questions pour 12 sessions. Un regroupement qui rend des
|
||
paires soir/nuit (au lieu du triplet du mercredi) est FAUX.
|
||
|
||
### Jeu de calibrage FINAL (corrigé en base, arbitré par le propriétaire 2026-09-13)
|
||
```
|
||
branchement sessions étiquette
|
||
sam 12/09 11:55 → (en cours) 11:55 5,94 JEEP
|
||
sam 12/09 11:42 → 11:53 11:42 0,09 JEEP
|
||
ven 11/09 16:53 → 18:27 16:54 7,45 6360W/28A MEGANE (auto)
|
||
jeu 10/09 18:19 → ven 16:27 18:20 2,97 · 01:24 4,26 VW
|
||
mer 09/09 15:55 → jeu 09:05 15:55 6,61 · 19:35 0,77 · 01:25 4,88 JEEP (triplet)
|
||
mar 08/09 19:39 → mer 08:57 19:39 0,76 · 01:26 5,01 VW
|
||
```
|
||
Semaine : 5 VW, 6 JEEP, 1 MEGANE (contre 11 VW + 1 JEEP avant correction).
|
||
Le triplet mercredi = JEEP les trois : la femme a branché la JEEP, le fils n'a pas
|
||
voulu la débrancher le soir pour mettre la VW → il a roulé à l'essence le jeudi.
|
||
Contexte humain qu'aucune règle ne produit — la raison d'être du concierge.
|
||
MEGANE = voiture de service (Rennes) + dépannage d'amis → « invité » RÉCURRENT.
|
||
|
||
### Cas tordus que le module DOIT gérer (dans les données de la semaine)
|
||
- sam 12/09 : on 11:42, off 11:53, on 11:55 = DEUX branchements (2 min de
|
||
débranchement), pas du flapping. La session 0,09 kWh en est la trace.
|
||
- ven 11/09 : off 16:27, on 16:53 = DEUX branchements (26 min ; débranche un
|
||
véhicule foyer pour brancher la Megane).
|
||
- ⚠️ AUCUN seuil de durée pour fusionner : 2 min et 26 min sont l'une et l'autre
|
||
de vraies séparations. Règle = « toute transition compte » ; défensive limitée
|
||
aux incohérences STRUCTURELLES (on déjà ouvert, off sans ouverture).
|
||
- Le branchement 12/09 11:55 est ENCORE OUVERT (borne haute nulle) → groupe en
|
||
cours, ne pas conclure qu'il est incomplet.
|
||
|
||
### Fenêtre d'analyse : commencer sur un 'on'
|
||
Une fenêtre doit démarrer sur un `on`, jamais au milieu d'un branchement : sinon
|
||
le premier événement est un `off` orphelin (branchement ouvert avant la fenêtre),
|
||
la session ouverte avant tombe hors intervalle et est classée « incertaine » à
|
||
tort (ex. démarrer au 08/09 00:00 fait apparaître 6 questions au lieu de 5, à
|
||
cause de la session 08/09 01:26). En production, aucun souci (on suit le flux) ;
|
||
règle valable surtout au rejeu historique. Calibration calée sur 08/09 19:00.
|
||
|
||
### Invariant à vérifier EN PERMANENCE (le contrôle le plus solide du projet)
|
||
Un seul câble ⟹ toutes les sessions d'un même branchement portent la MÊME
|
||
étiquette. Un groupe à étiquettes mixtes = frontière fausse (Airtria) OU ligne
|
||
fausse (base) — les deux méritent une alerte. Propriété PHYSIQUE : ne nécessite
|
||
aucune connaissance métier (ni routine, ni horaire, ni puissance), et aucune
|
||
évolution de règle ne peut l'invalider. À faire tourner en continu, pas seulement
|
||
à la calibration — c'est ce qui aurait signalé le triplet incohérent le jour même.
|
||
|
||
## Points de vigilance
|
||
- ⚠️ Inventaire BMS mensonger (découvert 2026-09-13) : le BMS annonce 4 modules /
|
||
400 Ah alors que le parc en compte 9 (le LV-Hub ne remonte que le groupe maître).
|
||
Mesuré : 0,312 kWh/point de SOC (vs 0,169 sur l'ancien parc de 7). NE JAMAIS
|
||
utiliser `capacite_installee` ni `nombre_de_modules_en_ligne` comme source de
|
||
capacité (sous-estiment de ~38 %). Source qui fait foi :
|
||
`input_number.evcs_balance_modules_en_service` (13 aujourd'hui). Concerne surtout
|
||
un futur rôle 2 (rétro-évaluation énergétique), pas le concierge véhicule.
|
||
- Helper HA en place : `input_text.airtria_vehicle_label` (max:255, état initial
|
||
`unknown` = « rien à appliquer »). Kill-switch consommateur
|
||
`input_boolean.airtria_concierge_enabled` (OFF) = propriété d'EVCS, Airtria n'y
|
||
touche pas. Aller-retour écriture/relecture validé le 2026-09-13.
|
||
- SPOF : OpenClaw vit sur 10.10.10.17, la machine qui porte aussi HA et n8n.
|
||
Faible enjeu pour l'ID véhicule, mais réel. Chien de garde sur 10.10.10.22.
|
||
- Prérequis à câbler : (1) accès lecture PostgreSQL pour Airtria
|
||
(`PG_LECTURE_PASSWORD`, déposé protégé comme le token HA) ; (2) création du
|
||
helper `input_text.airtria_vehicle_label` (max:255) dans le paquet HA.
|