diff --git a/.gitignore b/.gitignore index 44d0d23..666c390 100644 --- a/.gitignore +++ b/.gitignore @@ -26,6 +26,8 @@ workspace/* !workspace/bourse-config.json # code du concierge véhicule (aucun secret : lit les tokens depuis des fichiers ignorés) !workspace/concierge-*.js +# lecteur SQL lecture-seule de la session de charge en cours (aucun secret) +!workspace/airtria-charge-session.js # moniteur LLM/RAM + brouillons de config HA (aucun secret) !workspace/llm-monitor.js !workspace/*.yaml.draft diff --git a/workspace/AGENTS.md b/workspace/AGENTS.md index 6e5fd66..a37bc2c 100644 --- a/workspace/AGENTS.md +++ b/workspace/AGENTS.md @@ -60,6 +60,22 @@ Pour vérifier qu'un PNG est correct, utiliser **`du -b`** (taille en octets) vi Ne JAMAIS utiliser `view_image` ni `read` sur un `.png` : c'est lent, coûteux en contexte, et inutile. Un PNG de graphe valide fait > 5000 octets. +### 1.7 Mesures : ne JAMAIS substituer une grandeur absente, vérifier `last_changed` + +Pour toute question chiffrée (énergie, SOC, puissance, prix). Ces règles ont manqué le +16/09 (« SOC de la VW ? » : la grandeur n'existe pas ; Airtria l'a dit, puis a servi les +grandeurs voisines comme si elles répondaient → 5 affirmations fausses sur 6). + +- **Ne jamais SUBSTITUER.** Grandeur demandée absente ou illisible → le dire et S'ARRÊTER. + Une grandeur voisine ne se propose qu'EXPLICITEMENT étiquetée comme autre chose + (« je n'ai pas X ; j'ai Y, qui est différent »), jamais comme la réponse. Le remplacement + silencieux est pire qu'un « je ne sais pas » : il change une surveillance en fausse + réassurance. +- **Vérifier `last_changed`** (donné par `/api/states/`) avant de citer une valeur + comme ACTUELLE : figée depuis des heures ≠ « maintenant » / « cette nuit ». +- **Grandeur directionnelle** (une batterie monte/descend) : ne jamais publier la valeur + sans le SIGNE de la puissance associée, sinon on affirme « ça monte » quand ça descend. + --- ## 2. Démarrage de session et mémoire @@ -308,6 +324,34 @@ en attente), lance via `exec` : Ne jamais deviner ni inventer un véhicule : seul le script publie, et uniquement sur une réponse reconnue. +## 5ter. Questions énergie / batterie / véhicule — OÙ LIRE QUOI + +Référence EVCS (propriétaire du système EVCS), 16/09. Utiliser CES entités et appliquer +§1.7 (ne pas substituer, vérifier `last_changed`). + +- **SOC de la voiture (VW/JEEP)** : N'EXISTE PAS (aucun capteur véhicule). Le dire et + s'arrêter — seule source = le propriétaire (objet de la question « km restants » au + branchement). Ne jamais le déduire d'autre chose. +- **SOC batterie maison, AVEC SON SENS** : `sensor.victron_battery_soc` (valeur) ET + `sensor.victron_battery_power` (signe : négatif = elle DONNE/décharge, positif = + PREND/charge). Ne jamais publier l'un sans l'autre — l'oubli a produit le faux « et ça + monte » alors qu'elle descendait. +- **Ce que fait le système MAINTENANT** : `input_text.victron_evcs_source_mode` (ex. + « Assistance batterie nuit » = voiture alimentée par le solaire stocké la veille, EDF + ouvert). Ne pas confondre un PROFIL / une limite (ce qui est PERMIS : `night_slow`, + DVCC 30 A) avec l'ACTIVITÉ (ce qui se passe). +- **Cible SOC de la nuit** : `input_number.victron_evcs_night_target_soc` (valeur VIVANTE + qui DÉCROÎT au fil de la nuit ; jamais « 100 % », jamais un nombre en dur). +- **Énergie prise par la voiture, session en cours** : via `exec`, + `node /home/node/.openclaw/workspace/airtria-charge-session.js` (SQL lecture seule). Il + imprime véhicule, kWh de la session, dont réseau, heure de début, mode. `dont_reseau = 0` + = la voiture ne coûte rien au réseau. S'il échoue : le dire, ne pas substituer. +- **COMPTEURS EMPOISONNÉS — ne JAMAIS lire comme un delta** : `sensor.gx_device_pv_energy`, + `…_dc_battery_charge_energy`, `…_dc_battery_discharge_energy` (`state_class: total` sans + `last_reset` : ils se figent et sautent de ±centaines de kWh — le 16/09 l'un affichait + 12,11 kWh, figé depuis 8 h). Cumul sain seulement : les `*_total_yield` des chargeurs + solaires et `sensor.evcs_hq2239dnt7p_total_energy` (borne, monotone). + --- ## 6. Workspace et outils système diff --git a/workspace/airtria-charge-session.js b/workspace/airtria-charge-session.js new file mode 100644 index 0000000..c5d7fed --- /dev/null +++ b/workspace/airtria-charge-session.js @@ -0,0 +1,33 @@ +// airtria-charge-session.js — lecture seule : la session de charge EN COURS. +// ----------------------------------------------------------------------------- +// Réutilise makeClient de concierge-detection.js (rôle airtria_ro, résolution du mot de +// passe, PG_BASE) : aucun autre droit, un seul SELECT. Airtria l'appelle via `exec` pour +// répondre « combien la voiture a pris cette nuit » sans SUBSTITUER un compteur HA figé +// (cf. AGENTS.md §1.7 et §5ter). En cas d'échec : le dire, ne rien inventer. +// SQL fourni par EVCS (16/09) ; `dont_reseau = 0` = la voiture ne coûte rien au réseau. +// ----------------------------------------------------------------------------- +'use strict'; +const { makeClient } = require('./concierge-detection.js'); + +const SQL = ` + SELECT vehicule, + round(energie_kwh::numeric, 2) AS kwh_session, + round(energie_reseau_kwh::numeric, 2) AS dont_reseau, + to_char(debut, 'HH24:MI') AS depuis, + source_mode + FROM session_charge + WHERE NOT terminee + ORDER BY debut DESC + LIMIT 1`; + +(async () => { + const c = makeClient(); + await c.connect(); + try { + const r = await c.query(SQL); + if (!r.rows.length) { console.log('Aucune session de charge en cours.'); return; } + const s = r.rows[0]; + console.log(`${s.vehicule} : ${s.kwh_session} kWh pris cette session ` + + `(dont ${s.dont_reseau} kWh du réseau), depuis ${s.depuis}. Mode : ${s.source_mode}.`); + } finally { await c.end(); } +})().catch(e => { console.error('[charge-session]', e.message); process.exit(1); });