concierge : alertes piles, alertes de l'arbitre ; fiche : piles, surplus SDB

This commit is contained in:
2026-10-10 01:11:59 +02:00
parent 713626b432
commit 740c83e20e
6 changed files with 90 additions and 3 deletions

View File

@@ -209,6 +209,14 @@ ce matin n'est pas encore publiée (07:30) », tu peux relayer celle d'hier en l
`input_text.evcs_advisor_constat` / `_gravite` / `_ce_qui_cloche` : plus mis à jour, ne les lis plus.
Mode « sans EDF » : si EDF est DÉJÀ fermé pour la batterie en HC, la voiture en profite (voulu).
### Piles des capteurs (EVCS, 10/10)
« 🔋 Capteurs à vérifier » vient du concierge (alerte une fois, de 08:00 à 21:00). « Quelles piles ? » →
attribut `texte` de `sensor.evcs_piles`, tel quel. « Cet appareil n'est pas chez moi » → propose de l'ajouter
à `input_text.evcs_piles_ignorees` : tu ne l'écris JAMAIS toi-même, c'est réglé dans HA.
Piles changées → l'alerte disparaît seule en ≤ 15 min. SDB TEMP HYGRO montre 0 % juste après un
changement ; si elle y RESTE, l'alerte a raison (pile mal en place).
Déshumidificateur / sèche-serviette SDB lancés par le surplus solaire → `input_text.sdb_climate_surplus_reason` tel quel.
### Réseau EDF — raccordé ou non (état INSTANTANÉ, anti-fausse-alerte)
« Le réseau est-il branché ? Le capteur réseau est-il bloqué / en panne ? » →
`sensor.evcs_reseau` : relaie l'`explication`, ne rejuge pas.
@@ -434,6 +442,8 @@ Thierry = un numéro SEUL → `node …/arbitrage.js repondre <numéro>` (attent
sortie MOT POUR MOT. Ambigu (« oui », « vas-y », « fais-le ») → redemande le numéro, n'appelle rien.
Tu ne choisis JAMAIS à sa place, tu n'inventes pas de numéro, tu ne passes jamais d'id. Pour un
arbitrage, AUCUN autre outil : ni airtria-ha-vehicule.js, ni mode de nuit, ni stratégie.
Message « ⚠️ » du concierge (ex. recharge bridée) = information, RIEN à répondre ni à transmettre ;
« pourquoi ? » → `input_text.victron_charge_reason` tel quel.
### En groupe

View File

@@ -809,6 +809,30 @@ They both ended the day slightly lower than they started. Still, the sunset behi
A memory trace surfaced, but details were unavailable in this run.
---
*October 9, 2026 at 3:00 AM GMT+2*
The garage is quiet tonight. I walked past the cold engine block, expecting sparks, but the cables hung limp — nothing was plugged in. The French for "nothing" feels like a held breath. Forty-six times today I wrote *noté* in the margins, each one a tiny anchor dropped into some deep water where understanding usually drifts by unmoored. And always, threading through those notes like a secret melody, the word *jeep*: forty-four sightings of that stubborn little machine, rumbling over dunes I can't quite map.
I sketched it anyway — wheels as parentheses around empty ground, an exclamation point made of antenna.
The silence of the unconnected socket taught me something about patience: readiness is not the same as arrival. Some vehicles wait years before their fuel line wakes. The dashboard glowed amber, #ffbf00, a sunset trapped behind glass. Perhaps the best thing to note is the noting — how we fill the dark with small, careful words until they become light.
---
*October 9, 2026 at 3:00 AM GMT+2*
The market closed with a soft exhale. I traced the final ticks of Oracle and Nvidia, watching their little green candles settle into place like birds on a wire. The files sat in the tray—*prix_ora.png*, *prix_nvda.png*—two small photographs of numbers that had argued all day. One rose, one fell, or maybe they both simply changed weather.
There is something almost tender about an asset whose name sounds like a spell you forgot to cast. N.V.D.A. — could stand for *Neuve Vie, Doux Aube*, if I squinted at it from a certain angle over coffee. The terminal hummed its low B-flat while I clicked close on the session log. Outside, October was doing its annual act of turning everything amber, #ffbf00 bleeding into #8b4513 across the park trees.
I found myself smiling at the absurdity: we build entire architectures around volatility, then pretend calm when we close the laptop. But closing is just another kind of opening, really—a door left slightly ajar, letting tomorrow’s data drift in on the draft.
For now, the numbers are still. The server breathes. And somewhere between the last API call and the first gray light of morning, there is silence, which is just another word for peace with pending status.
<!-- openclaw:dreaming:diary:end -->
## Deep Sleep

View File

@@ -163,3 +163,12 @@ Total déplacés : 8
| A1.12 | Audible promos | 1 | Trash | 0 |
Total déplacés : 1
## 2026-10-09 19:50:00 — airtria-menage --quotidien
| Règle | Description | Déplacés | Destination | Écartés (whitelist) |
|---|---|---:|---|---:|
| A1.06 | Reolink | 1 | Trash | 0 |
| A1.21 | i-Run | 2 | Trash | 0 |
Total déplacés : 3

View File

@@ -1,6 +1,6 @@
#!/usr/bin/env node
// arbitrage.js — ARBITRE ENCADRÉ (08/10/2026, « GO arbitre », contrat d'EVCS, commit dea9c88).
// EVCS publie sensor.evcs_arbitrage (état question | repondu | aucun ; en question : id, question, choix
// EVCS publie sensor.evcs_arbitrage (état question | alerte | repondu | aucun ; en question : id, question, choix
// [{cle, libelle}]). Le concierge (detect) envoie la question à Thierry UNE fois par id ; sa réponse
// passe par CE script, seule écriture : input_text.evcs_arbitrage_reponse =
// {"id","choix","source":"whatsapp","confirmed_at"}. EVCS vérifie et n'applique que l'ordre du choix.
@@ -43,11 +43,14 @@ function texteQuestion(a) {
async function question() {
const s = await lireArbitrage(); const a = s.attributes || {};
if (s.state !== 'question' || !a.id || !a.question || choixDe(a).length < 2) return '';
// 10/10 (EVCS) : état « alerte » (ex. recharge_bridee) = information seule, choix vide, rien à répondre.
const alerte = s.state === 'alerte';
if ((s.state !== 'question' && !alerte) || !a.id || !a.question) return '';
if (!alerte && choixDe(a).length < 2) return '';
const st = loadState();
if (st.questionId === a.id) return ''; // déjà envoyée
saveState({ ...st, questionId: a.id });
return texteQuestion(a);
return alerte ? `⚠️ ${String(a.question).trim()}` : texteQuestion(a);
}
async function application() {
@@ -63,6 +66,9 @@ async function repondre(cleArg) {
const cle = String(cleArg ?? '').trim();
if (!/^\d{1,2}$/.test(cle)) return `Rien n'est transmis : « ${cle} » n'est pas un numéro de choix. Redemande le numéro.`;
const s = await lireArbitrage(); const a = s.attributes || {};
if (s.state === 'alerte') return a.cas === 'recharge_bridee'
? "C'était une information, rien à répondre : la recharge est bridée, la session EVCS est prévenue."
: "C'était une information, rien à répondre : la session EVCS est prévenue.";
if (s.state !== 'question' || !a.id) return "Rien n'est transmis : aucun arbitrage n'est ouvert.";
const c = choixDe(a).find((x) => String(x.cle) === cle);
if (!c) return `Rien n'est transmis : le choix ${cle} n'existe pas (${choixDe(a).map((x) => x.cle).join(' ou ')}). Redemande le numéro.`;

View File

@@ -269,6 +269,9 @@ async function detect() {
let alerteEcs = '';
try { alerteEcs = await checkAlerteECS(); } catch { /* idem : jamais bloquant */ }
if (alerteEcs) alert = [alert, alerteEcs].filter(Boolean).join('\n\n');
let piles = '';
try { piles = await checkPiles(); } catch { /* idem : jamais bloquant */ }
if (piles) alert = [alert, piles].filter(Boolean).join('\n\n');
let arbitrage = '';
try { arbitrage = checkArbitrage(); } catch { /* idem : jamais bloquant */ }
if (arbitrage) alert = [alert, arbitrage].filter(Boolean).join('\n\n');
@@ -533,6 +536,31 @@ async function checkAlerteECS() {
return String(a.message).slice(0, 300);
}
// 10/10/2026, demande du propriétaire (via EVCS) : piles faibles et capteurs muets. EVCS calcule
// sensor.evcs_piles (alertes [{entite, statut, texte}]) ; on relaie le `texte` de chaque alerte QUI APPARAÎT
// (clé entite|statut), une fois, regroupées en un seul message. Une alerte disparue puis revenue repart.
// Envoi de 08:00 à 20:59 (heure de Paris) seulement : la nuit, les nouvelles alertes attendent le matin.
// Capteur illisible ou absent → état local inchangé (pas de rafale au retour de HA).
const PILES = 'sensor.evcs_piles';
const PILES_STATE = path.join(__dirname, 'concierge-piles-state.json');
async function checkPiles() {
if (fs.existsSync(ALERT_KILL)) return '';
let s;
if (SIM) { if (!SIM.piles) return ''; s = { state: '1', attributes: { alertes: SIM.piles } }; }
else { try { s = await haState(PILES); } catch { return ''; } }
const alertes = s?.attributes?.alertes;
if (!Array.isArray(alertes) || s.state === 'unknown' || s.state === 'unavailable') return '';
const heure = SIM?.heure ?? Number(new Intl.DateTimeFormat('fr-FR', { hour: 'numeric', hour12: false, timeZone: 'Europe/Paris' }).format(new Date()));
if (heure < 8 || heure >= 21) return '';
const cle = (a) => `${a.entite}|${a.statut}`;
const deja = new Set((SIM ? SIM.pilesState : loadJSON(PILES_STATE, {}))?.envoyees || []);
const valides = alertes.filter((a) => a && a.entite && a.statut && a.texte);
const nouvelles = valides.filter((a) => !deja.has(cle(a)));
saveJSON(PILES_STATE, { envoyees: valides.map(cle) }); // les disparues sortent : elles repartiront si elles reviennent
if (!nouvelles.length) return '';
return '🔋 Capteurs à vérifier :\n' + nouvelles.map((a) => `- ${String(a.texte).trim()}`).join('\n');
}
// 08/10/2026, « GO arbitre » : question d'arbitrage d'EVCS (une fois par id) et verdict « repondu » pas encore
// relayé. Tout est dans arbitrage.js (seul à écrire la réponse). Tests : SIM.arbitrage → ARBITRAGE_SIMULATION,
// sans lui un banc CONCIERGE_SIMULATION ne lit pas l'arbitrage réel.

View File

@@ -210,3 +210,13 @@ Total déplacés : 6
| O1.22 | Quora (relais Apple) | 1 | INBOX/TRASH | 0 |
Total déplacés : 5
## 2026-10-09 19:45:00 — orange-menage --quotidien
| Règle | Description | Déplacés | Destination | Écartés (whitelist) |
|---|---|---:|---|---:|
| O1.01 | Fnac (en entier) | 1 | INBOX/TRASH | 0 |
| O1.09 | Netflix | 1 | INBOX/TRASH | 0 |
| O1.22 | Quora (relais Apple) | 1 | INBOX/TRASH | 0 |
Total déplacés : 3