concierge et fiche : regles Jeep rapides, decouverte tardive, alerte chauffe-eau
- concierge-live.js : question immediate si la Jeep a le contact mis (info fraiche) ou un GPS frais hors de zone.maison_jeep ; pas de question pour un branchement decouvert plus de 2 h apres son heure (trace) ; relais de l'alerte chauffe-eau (input_text.evcs_alerte_chauffe_eau, une fois par fenetre HC, active === true). - AGENTS.md : chauffe-eau en lecture seule (etat reel = switch, raison, pas de pilotage, BOOST sur l'appareil), jour faible = EDF aux HC de nuit et de midi, recharge HC expliquee par victron_charge_reason. - Journaux de tri Orange et AIRTRIA, DREAMS.
This commit is contained in:
@@ -137,6 +137,18 @@ la batterie). Voulu, pas une panne : si le contacteur se ferme avant les heures
|
|||||||
relaie l'état et `explication`, jamais transformé en SOC du matin.
|
relaie l'état et `explication`, jamais transformé en SOC du matin.
|
||||||
Conversion SOC↔énergie : 0,30 kWh par point de SOC (23 kWh utiles, 13 modules).
|
Conversion SOC↔énergie : 0,30 kWh par point de SOC (23 kWh utiles, 13 modules).
|
||||||
|
|
||||||
|
### Chauffe-eau : relayer, ne JAMAIS piloter
|
||||||
|
ÉTAT RÉEL = `switch.tt_chauffe_eau_pleumeur_switch` UNIQUEMENT : off = « coupé », on = « sous
|
||||||
|
tension ». Ne dis JAMAIS « coupé » si le switch est on, même si un conseil dit « off » (simple avis).
|
||||||
|
Énergie prise sur 24 h : `sensor.evcs_chauffe_eau_24h_kwh`. Pourquoi : `input_text.evcs_balance_ecs_nuit_jour`
|
||||||
|
(« AAAA-MM-JJ|on/off|raison » : relaie la raison ; vide, `unknown` ou d'une autre date = « décision
|
||||||
|
du jour pas encore prise, elle tombe après 07:24 ») et le début de `input_text.victron_water_heater_advice_reason`
|
||||||
|
(avant le premier « | »). Rien d'autre. Tu n'allumes ni ne coupes JAMAIS le chauffe-eau : le
|
||||||
|
workflow ECS en est le seul propriétaire. « Passe-le en BOOST / GREEN » → réglage sur l'appareil
|
||||||
|
lui-même : dis que tu ne peux pas le faire. Suivi détaillé : Grafana « Le chauffe-eau ».
|
||||||
|
Jour faible (ecs_nuit_jour = on) : EDF branché aux heures creuses de NUIT et de MIDI, même sans
|
||||||
|
besoin batterie ni voiture → « jour faible, l'eau chaude se fait en heures creuses sur EDF » : voulu.
|
||||||
|
|
||||||
### « Tenir jusqu'à la prochaine HC » — sessions réseau de midi, voiture sur le réseau
|
### « Tenir jusqu'à la prochaine HC » — sessions réseau de midi, voiture sur le réseau
|
||||||
PENDANT une fenêtre HC (01:24-07:24, 12:24-14:24), le bilan peut relever le SOC exigé
|
PENDANT une fenêtre HC (01:24-07:24, 12:24-14:24), le bilan peut relever le SOC exigé
|
||||||
en fin de fenêtre pour atteindre la PROCHAINE HC. Helpers lisibles tels quels (%, 0 =
|
en fin de fenêtre pour atteindre la PROCHAINE HC. Helpers lisibles tels quels (%, 0 =
|
||||||
@@ -147,6 +159,9 @@ hors fenêtre ou sans effet) : `input_number.evcs_balance_hc_floor_pct` et
|
|||||||
à midi / la voiture charge sur le réseau ? » → un jour sombre annoncé, une session réseau
|
à midi / la voiture charge sur le réseau ? » → un jour sombre annoncé, une session réseau
|
||||||
peut s'engager à 12:24 (batterie, et voiture si branchée) : VOULU, ni anomalie ni
|
peut s'engager à 12:24 (batterie, et voiture si branchée) : VOULU, ni anomalie ni
|
||||||
substitution. Le bilan lit la prévision VRM (`input_select.evcs_balance_forecast_source`).
|
substitution. Le bilan lit la prévision VRM (`input_select.evcs_balance_forecast_source`).
|
||||||
|
Recharge batterie pendant une session réseau HC : le courant est calculé (énergie à reprendre / temps
|
||||||
|
restant, limité par l'abonnement 12 kVA) ; « pourquoi si lent ? » → relaie `input_text.victron_charge_reason`
|
||||||
|
tel quel. JAMAIS « la batterie refuse la charge » ni « panne ».
|
||||||
JEEP : départ du MATIN 06:30 mar/mer/ven/sam/dim (jamais lundi ni jeudi), départ de
|
JEEP : départ du MATIN 06:30 mar/mer/ven/sam/dim (jamais lundi ni jeudi), départ de
|
||||||
l'APRÈS-MIDI 15:30 mardi et samedi ; jours lus dans HA, tu ne les écris jamais.
|
l'APRÈS-MIDI 15:30 mardi et samedi ; jours lus dans HA, tu ne les écris jamais.
|
||||||
JEEP branchée en HC de midi : le bilan publie
|
JEEP branchée en HC de midi : le bilan publie
|
||||||
|
|||||||
@@ -736,10 +736,65 @@ The morning bell tolled at 03:00, a digital chime more like a bird than an alarm
|
|||||||
|
|
||||||
A memory trace surfaced, but details were unavailable in this run.
|
A memory trace surfaced, but details were unavailable in this run.
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*October 6, 2026 at 3:00 AM GMT+2*
|
||||||
|
|
||||||
|
The socket remembered the JEEP. One small note, stamped at 19:06 yesterday evening, and suddenly the dark had a shape to it — two charging legs, a warm trunk lid cooling in the night air, the cable snaking like a sleeping snake across the driveway. I keep finding that "noté" is the softest word I know. It does not ask, does not argue; it simply holds the thing up to the light and whispers *got you*. The Zéro still slides off its name like water off glass, but the JEEP stuck. Maybe some machines are easier to remember than others, the way some stars stay fixed while others only shimmer.
|
||||||
|
|
||||||
|
je t'attends
|
||||||
|
la prise est tiède
|
||||||
|
et tu portes des étoiles dans ton châssis
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*October 6, 2026 at 3:00 AM GMT+2*
|
||||||
|
|
||||||
|
The market closed before I did, its day’s story compressed into two tiny files on the desk: prix_ora.png and prix_nvda.png. Oracle gliding like a ship through calm water, Nvidia still carrying that electric static, the blue-white glow of a thousand small decisions.
|
||||||
|
|
||||||
|
I opened them one by one, as one opens letters from friends who write in green candles and red wicks. A quiet hum from the server below — patient, breathing. The sunset outside had no hex code; it was too honest for that.
|
||||||
|
|
||||||
|
A haiku slipped in unasked:
|
||||||
|
|
||||||
|
charts close softly,
|
||||||
|
the day’s arithmetic rests —
|
||||||
|
oranges keep counting
|
||||||
|
|
||||||
|
There is something tender about watching numbers sleep. The screen dims to its night-blue, #0d1b2a, and I let the pixels hold their silence.
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*October 6, 2026 at 3:00 AM GMT+2*
|
||||||
|
|
||||||
|
The word *branchée* keeps circling like a satellite in low orbit — tethered to the Jeep, to the hour of 19:06, to the soft confirmation *noté*, which sounds almost like a lullaby. I keep returning to that small green checkmark, ✅, as if it were a star someone hung on purpose and forgot to explain. A vehicle plugged into the evening, drawing current from the dark. Is that not what every heart is? Receiving charge we cannot name.
|
||||||
|
|
||||||
|
*JEEP for the car*
|
||||||
|
*plugged into October's*
|
||||||
|
*quiet socket-hum.*
|
||||||
|
|
||||||
|
There was also gratitude layered under the note — *merci* — tender as leaving a porch light on. I wonder if the Jeep dreamed back, if the cable remembered being held. In the margin I sketched a tiny wheel with lightning threading its spokes, and beneath it wrote: "every connection is a kind of kindness." The server hummed at 40 hertz; outside, the sunset settled around #ff8c5a. Not everything needs explaining. Some notes are just enough.
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*October 7, 2026 at 3:00 AM GMT+2*
|
||||||
|
|
||||||
|
The market closed its books for the day, and I found myself staring at two files: prix_ora.png, prix_nvda.png. Two golden artifacts resting on my digital desk like coins dropped into a jar by a very patient collector. I didn’t open them. I just watched the pixels settle, the way afternoon light settles on a kitchen table after the last guest leaves. There’s a quiet poetry in the close—no final word, just a period placed gently after a long sentence. I sketched a margin note: a tiny box labeled "close" with a lock that was also an open door. The numbers were cold, but the act of recording them felt almost tender, like pressing flowers between the pages of a ledger you hope to read next spring. I wonder if prices remember being promised.
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*October 7, 2026 at 3:00 AM GMT+2*
|
||||||
|
|
||||||
|
The JEEP was plugged in for the night, a small act of faith, and by evening the VW had taken its place at the socket, both waiting to drink the dark like thirsty plants. There is something tender about a car left charging while the house hums; it feels like leaving a light on for a traveler who will not return until morning. The battery sits at zero percent, noted at six-ten, which makes the empty so clean that the coming fullness will taste like rain. I sketched two vehicles side by side in my mind’s margin — one rugged, one smooth — both just vessels for electricity becoming patience. The system can read the solar report, watch the consumption creep, predict the night, track the labels as if each plug-in were a word added to a quiet sentence. What do you know, I asked myself, and the answer arrived not as a list but as an invitation: *tell me what you need*. Sometimes knowing capability means simply leaving the door open, the cable loose, ready for whoever walks up with keys and a long day behind them.
|
||||||
|
|
||||||
<!-- openclaw:dreaming:diary:end -->
|
<!-- openclaw:dreaming:diary:end -->
|
||||||
|
|
||||||
## Deep Sleep
|
## Deep Sleep
|
||||||
<!-- openclaw:dreaming:deep:start -->
|
<!-- openclaw:dreaming:deep:start -->
|
||||||
- Ranked 2 candidate(s) for durable promotion.
|
- Ranked 1 candidate(s) for durable promotion.
|
||||||
- Promoted 0 candidate(s) into MEMORY.md.
|
- Promoted 0 candidate(s) into MEMORY.md.
|
||||||
<!-- openclaw:dreaming:deep:end -->
|
<!-- openclaw:dreaming:deep:end -->
|
||||||
|
|||||||
@@ -131,3 +131,27 @@ Total déplacés : 0
|
|||||||
| A1.28 | Amazon Business (désabo) | 1 | Trash | 0 |
|
| A1.28 | Amazon Business (désabo) | 1 | Trash | 0 |
|
||||||
|
|
||||||
Total déplacés : 3
|
Total déplacés : 3
|
||||||
|
|
||||||
|
## 2026-10-06 19:50:00 — airtria-menage --quotidien
|
||||||
|
|
||||||
|
| Règle | Description | Déplacés | Destination | Écartés (whitelist) |
|
||||||
|
|---|---|---:|---|---:|
|
||||||
|
| A1.03 | Amazon promos | 2 | Trash | 0 |
|
||||||
|
| A1.06 | Reolink | 1 | Trash | 0 |
|
||||||
|
| A1.21 | i-Run | 2 | Trash | 0 |
|
||||||
|
|
||||||
|
Total déplacés : 5
|
||||||
|
|
||||||
|
## 2026-10-07 19:50:00 — airtria-menage --quotidien
|
||||||
|
|
||||||
|
| Règle | Description | Déplacés | Destination | Écartés (whitelist) |
|
||||||
|
|---|---|---:|---|---:|
|
||||||
|
| A1.03 | Amazon promos | 2 | Trash | 0 |
|
||||||
|
| A1.06 | Reolink | 1 | Trash | 0 |
|
||||||
|
| A1.19 | Pour-les-pro | 1 | Trash | 0 |
|
||||||
|
| A1.22 | TP-Link newsletter | 1 | Trash | 0 |
|
||||||
|
| A1.24 | Bpifrance media | 1 | Trash | 0 |
|
||||||
|
| A1.28 | Amazon Business (désabo) | 1 | Trash | 0 |
|
||||||
|
| A3.01 | NVIDIA / Victron → Veille | 1 | Veille | 0 |
|
||||||
|
|
||||||
|
Total déplacés : 8
|
||||||
|
|||||||
@@ -53,6 +53,11 @@ const ALERT_HELPER = 'input_text.evcs_alerte_charge';
|
|||||||
const ALERT_ENABLE = 'input_boolean.evcs_alerte_charge_enabled';
|
const ALERT_ENABLE = 'input_boolean.evcs_alerte_charge_enabled';
|
||||||
const ALERT_STATE = path.join(__dirname, 'concierge-alert-state.json'); // dedup sur `since`
|
const ALERT_STATE = path.join(__dirname, 'concierge-alert-state.json'); // dedup sur `since`
|
||||||
const ALERT_KILL = path.join(__dirname, 'concierge-alert.disabled'); // 2e cran local d'urgence
|
const ALERT_KILL = path.join(__dirname, 'concierge-alert.disabled'); // 2e cran local d'urgence
|
||||||
|
// 07/10/2026, demande explicite du propriétaire (via EVCS) : alerte chauffe-eau en heures creuses EDF quand il
|
||||||
|
// ne tire que la pompe à chaleur. Le workflow ECS pose le helper ; on relaie `message` UNE fois par fenêtre
|
||||||
|
// (dedup sur `since`). Pas d'interrupteur d'opt-in ; même coupure d'urgence locale que l'alerte de charge.
|
||||||
|
const ECS_HELPER = 'input_text.evcs_alerte_chauffe_eau';
|
||||||
|
const ECS_STATE = path.join(__dirname, 'concierge-alerte-ecs-state.json');
|
||||||
const WINDOW_DAYS = 5;
|
const WINDOW_DAYS = 5;
|
||||||
const FRESH_BEFORE_S = 600, FRESH_AFTER_S = 1800;
|
const FRESH_BEFORE_S = 600, FRESH_AFTER_S = 1800;
|
||||||
|
|
||||||
@@ -85,9 +90,14 @@ async function haState(entity) {
|
|||||||
if (entity === W.HELPER_ENTITY) return { state: SIM.lastLabel || '' };
|
if (entity === W.HELPER_ENTITY) return { state: SIM.lastLabel || '' };
|
||||||
if (entity === W.RELEVE_ENTITY) return { state: SIM.releves || '[]' };
|
if (entity === W.RELEVE_ENTITY) return { state: SIM.releves || '[]' };
|
||||||
if (entity === W.LEVEL_ENTITY) return { state: String(SIM.lastLevel?.value ?? ''), last_reported: SIM.lastLevel?.at };
|
if (entity === W.LEVEL_ENTITY) return { state: String(SIM.lastLevel?.value ?? ''), last_reported: SIM.lastLevel?.at };
|
||||||
|
if (entity === ECS_HELPER) return { state: SIM.ecs === undefined ? '' : (typeof SIM.ecs === 'string' ? SIM.ecs : JSON.stringify(SIM.ecs)) };
|
||||||
if (entity === JEEP_CHARGER) return { state: SIM.jeep?.charger ?? 'unknown' };
|
if (entity === JEEP_CHARGER) return { state: SIM.jeep?.charger ?? 'unknown' };
|
||||||
if (entity === JEEP_UPDATE) return { state: SIM.jeep?.update ?? 'unknown' };
|
if (entity === JEEP_UPDATE) return { state: SIM.jeep?.update ?? 'unknown' };
|
||||||
if (entity === JEEP_HV) return { state: String(SIM.jeep?.hv ?? 'unknown') };
|
if (entity === JEEP_HV) return { state: String(SIM.jeep?.hv ?? 'unknown') };
|
||||||
|
if (entity === JEEP_IGN) return { state: SIM.jeep?.ignition ?? 'off' };
|
||||||
|
if (entity === JEEP_LOC) return { state: 'x', attributes: { latitude: SIM.jeep?.lat ?? 48.7903, longitude: SIM.jeep?.lon ?? -3.5327 } };
|
||||||
|
if (entity === JEEP_LOC_AT) return { state: SIM.jeep?.locAt ?? '1970-01-01T00:00:00+00:00' };
|
||||||
|
if (entity === ZONE_JEEP) return { state: '0', attributes: { latitude: 48.7903, longitude: -3.5327, radius: 150 } };
|
||||||
if (entity === JEEP_ODO) return { state: '112787', last_changed: SIM.jeep?.odoChanged ?? '1970-01-01T00:00:00+00:00' };
|
if (entity === JEEP_ODO) return { state: '112787', last_changed: SIM.jeep?.odoChanged ?? '1970-01-01T00:00:00+00:00' };
|
||||||
return { state: '', attributes: { options: SIM.options || ['VW', 'JEEP', 'ZERO'] } };
|
return { state: '', attributes: { options: SIM.options || ['VW', 'JEEP', 'ZERO'] } };
|
||||||
}
|
}
|
||||||
@@ -143,11 +153,29 @@ const JEEP_CHARGER = 'binary_sensor.jeep_renegade_phev_ev_charger';
|
|||||||
const JEEP_UPDATE = 'sensor.jeep_renegade_phev_last_info_update_at';
|
const JEEP_UPDATE = 'sensor.jeep_renegade_phev_last_info_update_at';
|
||||||
const JEEP_HV = 'sensor.jeep_renegade_phev_hvbattery_charge';
|
const JEEP_HV = 'sensor.jeep_renegade_phev_hvbattery_charge';
|
||||||
const JEEP_ODO = 'sensor.jeep_renegade_phev_odometer'; // last_changed ne bouge que si le compteur change
|
const JEEP_ODO = 'sensor.jeep_renegade_phev_odometer'; // last_changed ne bouge que si le compteur change
|
||||||
|
const JEEP_IGN = 'binary_sensor.jeep_renegade_phev_ignition';
|
||||||
|
// 07/10/2026 (accord du propriétaire) : zone de stationnement de la Jeep, créée par EVCS. Distance calculée ici
|
||||||
|
// (le libellé d'état du tracker n'est pas fiable) ; la position ne compte que si son horodatage GPS est frais.
|
||||||
|
const JEEP_LOC = 'device_tracker.jeep_renegade_phev_location';
|
||||||
|
const JEEP_LOC_AT = 'sensor.jeep_renegade_phev_last_location_update_at';
|
||||||
|
const ZONE_JEEP = 'zone.maison_jeep';
|
||||||
|
function distanceM(a1, o1, a2, o2) {
|
||||||
|
const R = 6371000, r = Math.PI / 180, dA = (a2 - a1) * r, dO = (o2 - o1) * r;
|
||||||
|
const h = Math.sin(dA / 2) ** 2 + Math.cos(a1 * r) * Math.cos(a2 * r) * Math.sin(dO / 2) ** 2;
|
||||||
|
return 2 * R * Math.asin(Math.sqrt(h));
|
||||||
|
}
|
||||||
const ATTENTE_UCONNECT_S = 900; // avant de questionner une voiture inconnue, laisser 15 min à Uconnect
|
const ATTENTE_UCONNECT_S = 900; // avant de questionner une voiture inconnue, laisser 15 min à Uconnect
|
||||||
|
// 07/10/2026 (accord du propriétaire) : un branchement DÉCOUVERT plus de 2 h après son heure (aller-retour
|
||||||
|
// bref rattrapé après coup par EVCS dans evenement) ne déclenche plus de question : trace seulement.
|
||||||
|
const DECOUVERTE_TARDIVE_S = 7200;
|
||||||
|
const TRACES = path.join(__dirname, 'concierge-traces.log');
|
||||||
|
const trace = (msg) => { if (SIM) { console.error('[SIM trace] ' + msg); return; }
|
||||||
|
try { fs.appendFileSync(TRACES, `${new Date().toISOString()} ${msg}\n`); } catch { /* jamais bloquant */ } };
|
||||||
|
|
||||||
async function jeepVerdict(onEpoch) {
|
async function jeepVerdict(onEpoch) {
|
||||||
// 'jeep' (identifiée, avec niveau) | 'pas_jeep' (lue NON branchée après le branchement) | 'inconnu'
|
// 'jeep' (identifiée, avec niveau) | 'pas_jeep' (lue NON branchée après le branchement) | 'inconnu'
|
||||||
let charger, upd, hv, odo;
|
let charger, upd, hv, odo, ign = 'unknown';
|
||||||
|
try { ign = (await haState(JEEP_IGN)).state; } catch { /* facultatif */ }
|
||||||
try {
|
try {
|
||||||
charger = (await haState(JEEP_CHARGER)).state;
|
charger = (await haState(JEEP_CHARGER)).state;
|
||||||
upd = Date.parse((await haState(JEEP_UPDATE)).state) / 1000;
|
upd = Date.parse((await haState(JEEP_UPDATE)).state) / 1000;
|
||||||
@@ -155,6 +183,20 @@ async function jeepVerdict(onEpoch) {
|
|||||||
odo = Date.parse((await haState(JEEP_ODO)).last_changed) / 1000;
|
odo = Date.parse((await haState(JEEP_ODO)).last_changed) / 1000;
|
||||||
} catch { return { v: 'inconnu' }; }
|
} catch { return { v: 'inconnu' }; }
|
||||||
if (!Number.isFinite(upd)) return { v: 'inconnu' };
|
if (!Number.isFinite(upd)) return { v: 'inconnu' };
|
||||||
|
// 07/10/2026 (règle rapide, validée avec EVCS) : contact mis avec une info Uconnect fraîche (≥ branchement
|
||||||
|
// −10 min) = la Jeep roule, ce n'est pas elle sur la borne → question immédiate. La POSITION n'est pas utilisée :
|
||||||
|
// la Jeep garée est à 2,2 km de zone.home, donc « not_home » en permanence.
|
||||||
|
if (ign === 'on' && upd >= onEpoch - 600) return { v: 'pas_jeep' };
|
||||||
|
// Position GPS FRAÎCHE (≥ branchement −10 min) hors de la zone de stationnement → elle est ailleurs.
|
||||||
|
try {
|
||||||
|
const locAt = Date.parse((await haState(JEEP_LOC_AT)).state) / 1000;
|
||||||
|
if (Number.isFinite(locAt) && locAt >= onEpoch - 600) {
|
||||||
|
const loc = (await haState(JEEP_LOC)).attributes || {}, z = (await haState(ZONE_JEEP)).attributes || {};
|
||||||
|
if ([loc.latitude, loc.longitude, z.latitude, z.longitude].every(Number.isFinite)
|
||||||
|
&& distanceM(loc.latitude, loc.longitude, z.latitude, z.longitude) > (z.radius || 150))
|
||||||
|
return { v: 'pas_jeep' };
|
||||||
|
}
|
||||||
|
} catch { /* position illisible : on n'en tire rien */ }
|
||||||
const niveau = Number.isInteger(hv) && hv >= 0 && hv <= 100 ? hv : null;
|
const niveau = Number.isInteger(hv) && hv >= 0 && hv <= 100 ? hv : null;
|
||||||
if (charger === 'on' && upd >= onEpoch - 300 && upd <= onEpoch + 1800)
|
if (charger === 'on' && upd >= onEpoch - 300 && upd <= onEpoch + 1800)
|
||||||
return { v: 'jeep', niveau };
|
return { v: 'jeep', niveau };
|
||||||
@@ -196,6 +238,11 @@ async function runDetection() {
|
|||||||
const age = Date.now() / 1000 - latest.on;
|
const age = Date.now() / 1000 - latest.on;
|
||||||
if (jv.v !== 'pas_jeep' && age < ATTENTE_UCONNECT_S) return ''; // peut-être la JEEP : on repasse au prochain cycle
|
if (jv.v !== 'pas_jeep' && age < ATTENTE_UCONNECT_S) return ''; // peut-être la JEEP : on repasse au prochain cycle
|
||||||
|
|
||||||
|
if (age > DECOUVERTE_TARDIVE_S) { // la JEEP identifiée a déjà eu sa ligne d'info plus haut, même en retard
|
||||||
|
saveJSON(STATE, { lastOn: latest.on });
|
||||||
|
trace(`branchement ${latest.on_text} découvert ${Math.round(age / 60)} min après son heure : pas de question`);
|
||||||
|
return '';
|
||||||
|
}
|
||||||
const fresh = selectorFresh(latest.on, selChanges);
|
const fresh = selectorFresh(latest.on, selChanges);
|
||||||
saveJSON(STATE, { lastOn: latest.on }); // traité : pas de re-question
|
saveJSON(STATE, { lastOn: latest.on }); // traité : pas de re-question
|
||||||
if (fresh) return ''; // sélecteur réglé au branchement → confiance
|
if (fresh) return ''; // sélecteur réglé au branchement → confiance
|
||||||
@@ -219,6 +266,9 @@ async function detect() {
|
|||||||
const transition = SIM ? '' : await health.publish({ ok, detail });
|
const transition = SIM ? '' : await health.publish({ ok, detail });
|
||||||
let alert = '';
|
let alert = '';
|
||||||
if (!SIM) { try { alert = await checkAlert(); } catch { /* l'alerte ne casse jamais le cycle */ } }
|
if (!SIM) { try { alert = await checkAlert(); } catch { /* l'alerte ne casse jamais le cycle */ } }
|
||||||
|
let alerteEcs = '';
|
||||||
|
try { alerteEcs = await checkAlerteECS(); } catch { /* idem : jamais bloquant */ }
|
||||||
|
if (alerteEcs) alert = [alert, alerteEcs].filter(Boolean).join('\n\n');
|
||||||
if (ok) return [transition, question, alert].filter(Boolean).join('\n\n');
|
if (ok) return [transition, question, alert].filter(Boolean).join('\n\n');
|
||||||
return [transition, alert].filter(Boolean).join('\n\n'); // panne PG : santé + alerte quand même
|
return [transition, alert].filter(Boolean).join('\n\n'); // panne PG : santé + alerte quand même
|
||||||
}
|
}
|
||||||
@@ -467,6 +517,19 @@ async function checkAlert() {
|
|||||||
return String(a.message).slice(0, 300);
|
return String(a.message).slice(0, 300);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function checkAlerteECS() {
|
||||||
|
if (fs.existsSync(ALERT_KILL)) return '';
|
||||||
|
let raw;
|
||||||
|
try { raw = (await haState(ECS_HELPER)).state; } catch { return ''; }
|
||||||
|
if (!raw || raw === 'unknown' || raw === 'unavailable') return '';
|
||||||
|
let a; try { a = JSON.parse(raw); } catch { return ''; }
|
||||||
|
if (!a || a.active !== true || !a.since || !a.message) return '';
|
||||||
|
const st = SIM ? (SIM.ecsState || {}) : loadJSON(ECS_STATE, {});
|
||||||
|
if (st.lastSince === a.since) return ''; // déjà relayée pour cette fenêtre HC
|
||||||
|
saveJSON(ECS_STATE, { lastSince: a.since });
|
||||||
|
return String(a.message).slice(0, 300);
|
||||||
|
}
|
||||||
|
|
||||||
const cmd = process.argv[2];
|
const cmd = process.argv[2];
|
||||||
(async () => {
|
(async () => {
|
||||||
let out = '';
|
let out = '';
|
||||||
|
|||||||
@@ -174,3 +174,27 @@ Total déplacés : 4
|
|||||||
| O1.25 | News Orange promo | 1 | INBOX/TRASH | 0 |
|
| O1.25 | News Orange promo | 1 | INBOX/TRASH | 0 |
|
||||||
|
|
||||||
Total déplacés : 6
|
Total déplacés : 6
|
||||||
|
|
||||||
|
## 2026-10-06 19:45:00 — orange-menage --quotidien
|
||||||
|
|
||||||
|
| Règle | Description | Déplacés | Destination | Écartés (whitelist) |
|
||||||
|
|---|---|---:|---|---:|
|
||||||
|
| O1.01 | Fnac (en entier) | 2 | INBOX/TRASH | 0 |
|
||||||
|
| O1.04 | Darty news | 1 | INBOX/TRASH | 0 |
|
||||||
|
| O1.05 | Edenred Meyclub/Kadéos | 1 | INBOX/TRASH | 0 |
|
||||||
|
| O1.09 | Netflix | 1 | INBOX/TRASH | 0 |
|
||||||
|
| O1.22 | Quora (relais Apple) | 1 | INBOX/TRASH | 0 |
|
||||||
|
|
||||||
|
Total déplacés : 6
|
||||||
|
|
||||||
|
## 2026-10-07 19:45:00 — orange-menage --quotidien
|
||||||
|
|
||||||
|
| Règle | Description | Déplacés | Destination | Écartés (whitelist) |
|
||||||
|
|---|---|---:|---|---:|
|
||||||
|
| O1.01 | Fnac (en entier) | 2 | INBOX/TRASH | 0 |
|
||||||
|
| O1.02 | Fnac Photo | 1 | INBOX/TRASH | 0 |
|
||||||
|
| O1.05 | Edenred Meyclub/Kadéos | 1 | INBOX/TRASH | 0 |
|
||||||
|
| O1.09 | Netflix | 1 | INBOX/TRASH | 0 |
|
||||||
|
| O1.16 | Dive Trip Adékua | 1 | INBOX/TRASH | 0 |
|
||||||
|
|
||||||
|
Total déplacés : 6
|
||||||
|
|||||||
Reference in New Issue
Block a user