From d64b634a66aa0f6659d98a0e8ff5698cc0cebda1 Mon Sep 17 00:00:00 2001 From: Tallagrand Thierry Date: Fri, 25 Sep 2026 00:07:28 +0200 Subject: [PATCH] =?UTF-8?q?D=C3=A9tail=20cellule=20expos=C3=A9=20en=203=20?= =?UTF-8?q?helpers=20HA=20pour=20l'agent=20vocal=20OpenClaw?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Les trames BMS cellule de HA sont mortes depuis le 15/09 ; le relevé série est la source vivante. Le service publie evcs_cell_spread_max_mv, evcs_cell_weakest_module et evcs_cell_releve_age_min à chaque cycle (publierCellulesHelpers). L'âge donne à l'agent la discipline anti-valeur-figée (comme le gel GX). Vérifié en réel : 21 mV, âge 1 min, K220803C30160323. Package evcs_cellules.yaml (hors dépôt, HA). Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01GwpFpy2aQ2rJok6tNQSbVj --- HANDOFF.md | 22 ++++++++++++++++++++ tools/historise-evcs.mjs | 43 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/HANDOFF.md b/HANDOFF.md index ce96231..ba7175a 100644 --- a/HANDOFF.md +++ b/HANDOFF.md @@ -501,3 +501,25 @@ Regle-cle : bridage NORMAL ⇒ import nul ; substitution ANORMALE ⇒ import ~ c --- *Document mis a jour le : 24/09/2026 — banc PV 9/9 pour OpenClaw (source de verite + discrimination bridage/vraie baisse/substitution), la source vit dans MANUEL §0* + +## 78. Session du 24-25/09/2026 — Détail cellule exposé en helpers HA pour l'agent vocal + +Les trames BMS cellule de HA sont mortes depuis le 15/09 (§69) ; le relevé série +(table `cellule`, sur le NAS depuis §75) est la seule source vivante. Pour que +l'agent vocal OpenClaw lise le détail cellule en direct sans taper PostgreSQL, le +service d'historisation publie désormais trois helpers HA à chaque cycle, depuis +le dernier relevé série : +- `input_number.evcs_cell_spread_max_mv` — écart max du pack (mV) +- `input_text.evcs_cell_weakest_module` — code-barres du module le plus sensible +- `input_number.evcs_cell_releve_age_min` — âge du dernier relevé (min) + +L'âge permet à l'agent la même discipline que pour le gel GX : frais → il donne +la valeur, vieux → il dit « muet ». `publierCellulesHelpers()` dans +`tools/historise-evcs.mjs` (SQL sur les modules du dernier lot, à ±5 min du +max(ts)), appelée après l'ingestion. Package `evcs_cellules.yaml` (sans +`initial:` — réécrits chaque cycle), rechargé sans redémarrage. Vérifié en réel +le 25/09 : écart 21 mV, âge 1 min, module K220803C30160323 (le plus ancien du +pack 2). SPARK bascule l'agent dessus (fiche + gamme G13 live). + +--- +*Document mis a jour le : 25/09/2026 — détail cellule publié en helpers HA (source série vivante), agent vocal câblé* diff --git a/tools/historise-evcs.mjs b/tools/historise-evcs.mjs index 3a8b233..62bf13b 100644 --- a/tools/historise-evcs.mjs +++ b/tools/historise-evcs.mjs @@ -1792,6 +1792,43 @@ async function ecrireHelperTexte(entite, valeur) { } catch { /* le helper reste a sa valeur, on reessaiera au prochain cycle */ } } +async function ecrireHelperNombre(entite, valeur) { + if (DRY || valeur === null || valeur === undefined || !Number.isFinite(valeur)) return; + try { + await fetch(`${HA_URL}/api/services/input_number/set_value`, { + method: 'POST', + headers: { Authorization: `Bearer ${HA_TOKEN}`, 'Content-Type': 'application/json' }, + body: JSON.stringify({ entity_id: entite, value: valeur }), + signal: AbortSignal.timeout(8000), + }); + } catch { /* on reessaiera au prochain cycle */ } +} + +// Publie le detail cellule (relevé serie, table `cellule`) dans des helpers HA, +// pour que l'agent vocal OpenClaw le lise sans taper PostgreSQL. Les trames BMS +// cellule de HA sont mortes depuis le 15/09 (§69) : ce relevé serie est la seule +// source vivante. On expose l'ECART max du pack, le module extreme, et l'AGE du +// dernier relevé — c'est l'age qui permet a l'agent d'appliquer la meme +// discipline que pour le gel GX (frais -> il le donne, vieux -> il dit muet). +async function publierCellulesHelpers(client) { + if (DRY || !client) return 0; + const { rows: [r] } = await client.query( + `WITH mx AS (SELECT max(ts) AS t FROM cellule), + recent AS (SELECT DISTINCT ON (module) module, ts FROM cellule + WHERE ts > (SELECT t FROM mx) - interval '5 minutes' ORDER BY module, ts DESC), + spreads AS (SELECT c.module, max(c.mv) - min(c.mv) AS ecart + FROM cellule c JOIN recent rc ON rc.module = c.module AND rc.ts = c.ts + GROUP BY c.module) + SELECT (SELECT max(ecart) FROM spreads) AS spread_max, + (SELECT module FROM spreads ORDER BY ecart DESC NULLS LAST LIMIT 1) AS weakest, + (SELECT round(EXTRACT(EPOCH FROM (now() - t)) / 60)::int FROM mx) AS age_min`); + if (!r || r.age_min === null) return 0; // table cellule vide : rien a publier + await ecrireHelperNombre('input_number.evcs_cell_spread_max_mv', r.spread_max === null ? null : Number(r.spread_max)); + await ecrireHelperNombre('input_number.evcs_cell_releve_age_min', Number(r.age_min)); + await ecrireHelperTexte('input_text.evcs_cell_weakest_module', r.weakest || 'indisponible'); + return 1; +} + async function cycle(client) { // En blanc, on compte ce qu'on ECRIRAIT. Un essai a blanc qui renvoie // toujours zero ne verifie rien — c'est le piege classique du test qui ne @@ -1840,6 +1877,12 @@ async function cycle(client) { console.error(`ingestion cellules en echec : ${e.message}`); return 0; }), + // Publie le detail cellule dans des helpers HA (pour l'agent vocal), APRES + // l'ingestion pour utiliser le relevé qui vient d'arriver. + cellulesHelpers: DRY ? 0 : await publierCellulesHelpers(client).catch((e) => { + console.error(`publication helpers cellule en echec : ${e.message}`); + return 0; + }), }; const total = r.mesures + r.bilan + r.decision + r.prevision + r.evenement + r.session + r.cellules + r.observation + r.etiquette + (r.rapport || 0); if (total > 0 || ONCE) {