Jeep identifiee par Uconnect : etiquette du branchement, selecteur et niveau poses automatiquement
This commit is contained in:
@@ -1131,6 +1131,9 @@ const HOUSEHOLD = new Set(['VW', 'JEEP']);
|
||||
// un canal inconnu ne doit pas valoir confirmation par defaut. `regle-puissance`
|
||||
// n'y est pas et n'y sera jamais — c'est une deduction, pas une parole.
|
||||
const CANAUX_HUMAINS = new Set(['whatsapp', 'proprietaire']);
|
||||
// Sources qui CONFIRMENT un vehicule : l'humain, ou la voiture elle-meme
|
||||
// (04/10/2026 : la Jeep se declare branchee via Uconnect).
|
||||
const CANAUX_SURS = new Set([...CANAUX_HUMAINS, 'uconnect']);
|
||||
const LABELS = new Set(['VW', 'JEEP', 'MEGANE', 'INVITE', 'ZERO']);
|
||||
let dernierBlancVu = null; // anti-repetition du journal en essai a blanc
|
||||
|
||||
@@ -1196,7 +1199,7 @@ async function piloterSelecteurVehicule(sql, st, label, source) {
|
||||
return 1;
|
||||
}
|
||||
await journaliser(sql, 'vehicule',
|
||||
`Selecteur vehicule pilote par le concierge : ${actuel || 'inconnu'} -> ${label}`,
|
||||
`Selecteur vehicule pilote par ${source === 'uconnect' ? 'la Jeep (Uconnect)' : 'le concierge'} : ${actuel || 'inconnu'} -> ${label}`,
|
||||
{ origine: 'airtria', source_airtria: source, label, avant: actuel,
|
||||
entite: 'input_select.victron_evcs_vehicle',
|
||||
motif: 'la reponse du proprietaire fait foi, et le controleur lit le selecteur' });
|
||||
@@ -1394,6 +1397,45 @@ async function appliquerEtiquetteConcierge(sql, client, st) {
|
||||
// debranchement suivant — l invariant « un cable, un vehicule ». Les 2 secondes
|
||||
// de tolerance sur la borne basse sont celles du 09/09 : une session s ouvre
|
||||
// jusqu a 62 ms AVANT que sa transition de branchement soit journalisee.
|
||||
// LA JEEP SE DECLARE ELLE-MEME (04/10/2026, accord du proprietaire). Appelee par
|
||||
// ingererJeep a la premiere mise a jour Uconnect qui suit un branchement de la
|
||||
// borne, Jeep « branchee ». Trois gestes, une fois par branchement :
|
||||
// 1. etiquette JEEP du branchement (source uconnect, confirmee) — SANS ecraser
|
||||
// une etiquette deja donnee par le proprietaire (ON CONFLICT DO NOTHING) ;
|
||||
// 2. selecteur sur JEEP (heure de depart, regles du controleur) ;
|
||||
// 3. niveau « saisi » du vehicule = niveau lu, sauf saisie humaine depuis le
|
||||
// branchement - 1 h (l'automatisation HA recale la reference du compteur).
|
||||
// Le concierge ne doit alors plus poser sa question : il lit etiquette_branchement.
|
||||
async function etiqueterJeepUconnect(sql, client, st, branche, niveau) {
|
||||
if (DRY) return 0;
|
||||
const { rowCount } = await client.query(
|
||||
`INSERT INTO etiquette_branchement (branchement, label, source_airtria, confirmed_at)
|
||||
VALUES ($1, 'JEEP', 'uconnect', $2) ON CONFLICT (branchement) DO NOTHING`,
|
||||
[branche, new Date().toISOString()]);
|
||||
if (!rowCount) return 0; // deja etiquete (le proprietaire a repondu) : on ne touche a rien
|
||||
await journaliser(sql, 'vehicule', `Branchement identifie : JEEP (la voiture se declare branchee, Uconnect), niveau ${niveau} %`,
|
||||
{ origine: 'uconnect', label: 'JEEP', branchement: branche.toISOString(), niveau });
|
||||
let n = 1 + await piloterSelecteurVehicule(sql, st, 'JEEP', 'uconnect');
|
||||
const saisieA = Number(st.get('input_datetime.victron_evcs_vehicle_level_at')?.attributes?.timestamp) * 1000;
|
||||
if (!(saisieA >= branche.getTime() - 3600000)) {
|
||||
try {
|
||||
const r = 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: 'input_number.victron_evcs_vehicle_level_pct', value: niveau }),
|
||||
signal: AbortSignal.timeout(8000),
|
||||
});
|
||||
if (!r.ok) throw new Error(`HTTP ${r.status}`);
|
||||
await journaliser(sql, 'vehicule', `Niveau du vehicule branche pose a ${niveau} % (lu par la Jeep)`,
|
||||
{ origine: 'uconnect', niveau, entite: 'input_number.victron_evcs_vehicle_level_pct' });
|
||||
n++;
|
||||
} catch (e) {
|
||||
await journaliser(sql, 'vehicule', `Niveau JEEP NON pose (${e.message})`, { origine: 'uconnect', niveau });
|
||||
}
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
async function appliquerEtiquettesEnAttente(sql, client) {
|
||||
if (DRY) return 0;
|
||||
const { rows } = await client.query(
|
||||
@@ -1401,7 +1443,7 @@ async function appliquerEtiquettesEnAttente(sql, client) {
|
||||
WHERE branchement > now() - interval '48 hours' ORDER BY branchement`);
|
||||
let n = 0;
|
||||
for (const e of rows) {
|
||||
const sur = CANAUX_HUMAINS.has(e.source_airtria);
|
||||
const sur = CANAUX_SURS.has(e.source_airtria);
|
||||
const { rowCount } = await sql(
|
||||
`UPDATE session_charge s SET vehicule = $2, vehicule_sur = $3
|
||||
WHERE s.debut >= $1::timestamptz - interval '2 seconds'
|
||||
@@ -2140,7 +2182,8 @@ async function cycle(client) {
|
||||
console.error(`releves km en echec : ${e.message}`); return 0;
|
||||
}) + await ingererNiveauSaisi(sql, st).catch((e) => {
|
||||
console.error(`niveau saisi en echec : ${e.message}`); return 0;
|
||||
}) + await ingererJeep(sql, (q, v) => client.query(q, v), st, journaliser).catch((e) => {
|
||||
}) + await ingererJeep(sql, (q, v) => client.query(q, v), st, journaliser,
|
||||
(branche, niveau) => etiqueterJeepUconnect(sql, client, st, branche, niveau)).catch((e) => {
|
||||
console.error(`jeep uconnect en echec : ${e.message}`); return 0;
|
||||
}),
|
||||
pvDiagnostic: DRY ? 0 : await publierDiagnosticPv(st).catch((e) => {
|
||||
|
||||
@@ -276,7 +276,10 @@ export const JEEP = {
|
||||
branchee: 'binary_sensor.jeep_renegade_phev_ev_charger',
|
||||
};
|
||||
|
||||
export async function ingererJeep(sql, lire, st, journaliser) {
|
||||
// `etiqueter(branche, niveau)` (fourni par le service) : pose l'etiquette JEEP
|
||||
// du branchement, le selecteur et le niveau « saisi » — appelee UNE fois par
|
||||
// branchement, a la premiere mise a jour Uconnect qui le confirme.
|
||||
export async function ingererJeep(sql, lire, st, journaliser, etiqueter = null) {
|
||||
const km = Number(st.get(JEEP.odometre)?.state);
|
||||
const niv = Number(st.get(JEEP.niveau)?.state);
|
||||
const t = Date.parse(st.get(JEEP.majA)?.state ?? '');
|
||||
@@ -317,6 +320,7 @@ export async function ingererJeep(sql, lire, st, journaliser) {
|
||||
n++;
|
||||
await journaliser(sql, 'vehicule', `Niveau JEEP au branchement : ${niveau} % (lu par Uconnect)`,
|
||||
{ niveau, ts: ts.toISOString(), branchement: branche.toISOString() });
|
||||
if (etiqueter) n += await etiqueter(branche, niveau);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user