concierge: JEEP identifiee aussi par sa fin de trajet (odometre change)

- detect : chargeur off, last_info_update_at dans [branchement -10 min, branchement] et odometer.last_changed dans [-10 min, +20 min] (heure de relecture HA) -> ligne d'info JEEP, niveau a l'arrivee, sans question. Une Jeep garee qui republie sans rouler est exclue.
- Journaux de tri Orange et AIRTRIA, DREAMS.
This commit is contained in:
2026-10-06 01:36:31 +02:00
parent 4cd3615172
commit 55e469e103
4 changed files with 81 additions and 3 deletions

View File

@@ -88,6 +88,7 @@ async function haState(entity) {
if (entity === JEEP_CHARGER) return { state: SIM.jeep?.charger ?? '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_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'] } };
}
const r = await fetch(`${HA_BASE}/api/states/${entity}`, { headers: { Authorization: `Bearer ${haToken()}` } });
@@ -141,19 +142,33 @@ async function loadWindow() {
const JEEP_CHARGER = 'binary_sensor.jeep_renegade_phev_ev_charger';
const JEEP_UPDATE = 'sensor.jeep_renegade_phev_last_info_update_at';
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 ATTENTE_UCONNECT_S = 900; // avant de questionner une voiture inconnue, laisser 15 min à Uconnect
async function jeepVerdict(onEpoch) {
// 'jeep' (identifiée, avec niveau) | 'pas_jeep' (lue NON branchée après le branchement) | 'inconnu'
let charger, upd, hv;
let charger, upd, hv, odo;
try {
charger = (await haState(JEEP_CHARGER)).state;
upd = Date.parse((await haState(JEEP_UPDATE)).state) / 1000;
hv = Number((await haState(JEEP_HV)).state);
odo = Date.parse((await haState(JEEP_ODO)).last_changed) / 1000;
} catch { return { v: 'inconnu' }; }
if (!Number.isFinite(upd)) return { v: 'inconnu' };
const niveau = Number.isInteger(hv) && hv >= 0 && hv <= 100 ? hv : null;
if (charger === 'on' && upd >= onEpoch - 300 && upd <= onEpoch + 1800)
return { v: 'jeep', niveau: Number.isInteger(hv) && hv >= 0 && hv <= 100 ? hv : null };
return { v: 'jeep', niveau };
// 05/10/2026 (règle EVCS, accord du propriétaire) : la Jeep a FINI UN TRAJET dans les 10 min avant le
// branchement (dernière mise à jour Uconnect dans [branchement −10 min, branchement], chargeur encore off).
// Le soir en « sans EDF » sa charge ne démarre pas et elle ne republie rien : c'est sa fin de trajet qui
// l'identifie. Niveau = celui de l'arrivée. Risque accepté : une autre voiture branchée juste après.
// + COMPTEUR CHANGÉ : une mise à jour d'une Jeep restée garée ne suffit pas (sinon on annoncerait JEEP au
// branchement de la VW alors qu'EVCS n'étiquette pas). last_changed de l'odomètre est l'heure où HA a RELU
// le cloud (jusqu'à 15 min après le trajet : 05/10, trajet fini 19:05, vu par HA 19:19) : fenêtre
// [branchement −10 min, branchement +20 min] ; l'heure du trajet reste testée par last_info_update_at.
if (charger === 'off' && upd >= onEpoch - 600 && upd <= onEpoch
&& Number.isFinite(odo) && odo >= onEpoch - 600 && odo <= onEpoch + 1200)
return { v: 'jeep', niveau, arrivee: true };
if (charger === 'off' && upd > onEpoch) return { v: 'pas_jeep' };
return { v: 'inconnu' };
}
@@ -174,7 +189,8 @@ async function runDetection() {
const jv = await jeepVerdict(latest.on);
if (jv.v === 'jeep') {
saveJSON(STATE, { lastOn: latest.on });
return `🔌 JEEP branchée à ${hhmm(latest.on)}` + (jv.niveau !== null ? `, ${jv.niveau} % (lu par la voiture)` : ' (identifiée par la voiture)') +
return `🔌 JEEP branchée à ${hhmm(latest.on)}` +
(jv.niveau !== null ? `, ${jv.niveau} % (lu par la voiture${jv.arrivee ? ' à son arrivée' : ''})` : ' (identifiée par la voiture)') +
`. Rien à faire ; si ce n'est pas elle, réponds avec le bon véhicule.`;
}
const age = Date.now() / 1000 - latest.on;