Chaque transition dit desormais QUI l a provoquee
Le 12/09, le contacteur reseau a bascule six fois en dix minutes. Trouver le coupable a demande sept requetes enchainees — executions n8n des deux workflows, liste des ecrivains, puis automations.yaml — parce que la table des evenements disait QUE ca avait bascule, jamais PAR QUI. Home Assistant le savait pourtant. Son logbook resout le contexte d un changement d etat et nomme l auteur. Sur la coupure de 06:29:44 : auteur : automation.victron_grid_off_si_soc_35 declencheur : triggered by numeric state of sensor.victron_battery_soc Un appel par transition REELLE — quelques-uns par jour, pas par cycle. Echec de lecture => pas d auteur, la ligne est ecrite quand meme : on ne devine jamais. ⚠️ L auteur est colle au RESUME, pas seulement au detail jsonb. C est le resume que Grafana affiche en annotation sur TOUS les tableaux et dans les panneaux « journal des evenements », et que le rapport de nuit reprend. Le mettre la le rend visible partout sans toucher a un seul tableau. remonte l auteur et son declencheur : l enquete de ce matin tient desormais en UNE commande, et l observateur pourra nommer le coupable au lieu de dire « un des trois ». Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GwpFpy2aQ2rJok6tNQSbVj
This commit is contained in:
@@ -155,6 +155,47 @@ const num = (v) => {
|
||||
};
|
||||
const txt = (s) => (s ?? '').toString().trim();
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// QUI A PROVOQUE CETTE TRANSITION (12/09/2026)
|
||||
// ---------------------------------------------------------------------
|
||||
// Le 12/09, le contacteur reseau a bascule six fois en dix minutes. Trouver le
|
||||
// coupable a demande sept requetes enchainees — executions n8n des deux
|
||||
// workflows, liste des ecrivains, puis automations.yaml — parce que la table
|
||||
// des evenements disait QUE ca avait bascule, jamais PAR QUI.
|
||||
//
|
||||
// Home Assistant le sait pourtant : son logbook resout le contexte d un
|
||||
// changement d etat et nomme l automatisation, le script ou l utilisateur qui
|
||||
// l a declenche. Pour la coupure de 06:29:44 il rend :
|
||||
// context_entity_id : automation.victron_grid_off_si_soc_35
|
||||
// context_message : triggered by numeric state of sensor.victron_battery_soc
|
||||
//
|
||||
// Un appel par transition reelle — quelques-uns par jour, pas par cycle. En cas
|
||||
// d echec on n invente rien : pas d auteur, et la ligne est ecrite quand meme.
|
||||
async function auteurDeLaTransition(entite, horodatageHa) {
|
||||
try {
|
||||
const t = Date.parse(horodatageHa);
|
||||
if (!Number.isFinite(t)) return null;
|
||||
const debut = new Date(t - 5000).toISOString();
|
||||
const fin = new Date(t + 5000).toISOString();
|
||||
const r = await fetch(
|
||||
`${HA_URL}/api/logbook/${debut}?end_time=${encodeURIComponent(fin)}&entity_id=${encodeURIComponent(entite)}`,
|
||||
{ headers: { Authorization: `Bearer ${HA_TOKEN}` }, signal: AbortSignal.timeout(8000) },
|
||||
);
|
||||
if (!r.ok) return null;
|
||||
const lignes = await r.json();
|
||||
const l = (Array.isArray(lignes) ? lignes : []).find((x) => x.entity_id === entite && x.context_name);
|
||||
if (!l) return null;
|
||||
return {
|
||||
auteur: l.context_entity_id || l.context_name,
|
||||
nom: l.context_name,
|
||||
type: l.context_domain || l.context_event_type || null,
|
||||
declencheur: l.context_message || null,
|
||||
};
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async function etats() {
|
||||
const r = await fetch(`${HA_URL}/api/states`, {
|
||||
headers: { Authorization: `Bearer ${HA_TOKEN}` },
|
||||
@@ -332,9 +373,17 @@ async function detecterEvenements(sql, st) {
|
||||
const prec = memoire.valeurs.get(id);
|
||||
if (prec === undefined) { memoire.valeurs.set(id, cur); continue; }
|
||||
if (prec === cur) continue;
|
||||
await journaliser(sql, genre, `${libelle} : ${prec} -> ${cur}`, {
|
||||
const qui = await auteurDeLaTransition(id, e.last_changed);
|
||||
// L auteur est colle au RESUME, pas seulement au detail : c est le resume
|
||||
// que Grafana affiche en annotation sur tous les tableaux et dans les
|
||||
// panneaux « journal des evenements », et que le rapport de nuit reprend.
|
||||
// Le mettre la le rend visible partout sans toucher a un seul tableau.
|
||||
const resume = `${libelle} : ${prec} -> ${cur}`
|
||||
+ (qui ? ` — par ${qui.nom}` : '');
|
||||
await journaliser(sql, genre, resume, {
|
||||
entite: id, avant: prec, apres: cur,
|
||||
horodatage_ha: e.last_changed,
|
||||
...(qui ? { auteur: qui.auteur, auteur_nom: qui.nom, auteur_type: qui.type, declencheur: qui.declencheur } : {}),
|
||||
});
|
||||
memoire.valeurs.set(id, cur);
|
||||
n++;
|
||||
|
||||
Reference in New Issue
Block a user