SDB : capteur muet et garde batterie (workflow sous controle du depot) ; alertes de piles des capteurs
This commit is contained in:
52
tools/piles.mjs
Normal file
52
tools/piles.mjs
Normal file
@@ -0,0 +1,52 @@
|
||||
// =====================================================================
|
||||
// PILES DES CAPTEURS (10/10/2026, demande du proprietaire)
|
||||
// Le capteur temperature/humidite de la SDB est reste muet six jours (piles)
|
||||
// sans que personne ne le sache. Ce module repere, parmi les etats HA, les
|
||||
// capteurs d'APPAREILS a pile dont la pile est faible ou qui ne publient plus ;
|
||||
// le service d'historisation publie sensor.evcs_piles et SPARK previent par
|
||||
// WhatsApp. Fonction pure (tests : tests/piles/run.mjs).
|
||||
// =====================================================================
|
||||
|
||||
export const SEUIL_PCT = 20; // pile faible a 20 % et moins
|
||||
export const MUET_H = 24; // indisponible depuis plus de 24 h
|
||||
// Pas des piles de capteurs : parc Victron, voiture, telephones, reglages GX.
|
||||
const EXCLUS = /^(sensor|number|binary_sensor)\.(victron_|gx_device_|airtria_8_|jeep_|iphone_|ipad_|samsung_)/;
|
||||
|
||||
/**
|
||||
* @param {Array} etats liste des etats HA ({entity_id, state, attributes, last_changed})
|
||||
* @param {number} maintenantMs
|
||||
* @param {string[]} ignorees entites que le proprietaire a demande d'ignorer
|
||||
*/
|
||||
export function pilesAAlerter(etats, maintenantMs, ignorees = []) {
|
||||
const ign = new Set(ignorees.map((x) => x.trim()).filter(Boolean));
|
||||
const alertes = [];
|
||||
for (const s of etats) {
|
||||
const id = s.entity_id;
|
||||
if (!id.startsWith('sensor.') || EXCLUS.test(id) || ign.has(id)) continue;
|
||||
const a = s.attributes || {};
|
||||
const enPct = a.device_class === 'battery' && (a.unit_of_measurement === '%' || a.unit_of_measurement === undefined);
|
||||
const enEnum = /_etat_batterie$/.test(id);
|
||||
if (!enPct && !enEnum) continue;
|
||||
const nom = String(a.friendly_name || id).replace(/\s+/g, ' ').trim();
|
||||
const v = String(s.state ?? '').trim().toLowerCase();
|
||||
const depuisMs = Date.parse(s.last_changed);
|
||||
if (v === 'unavailable' || v === 'unknown' || v === '') {
|
||||
const h = Number.isFinite(depuisMs) ? (maintenantMs - depuisMs) / 3600000 : Infinity;
|
||||
if (h > MUET_H) alertes.push({ entite: id, nom, statut: 'muet', niveau: null, depuis: s.last_changed,
|
||||
texte: `${nom} ne publie plus depuis ${Number.isFinite(h) ? Math.round(h / 24) + ' j' : 'longtemps'} (pile vide ou appareil hors ligne)` });
|
||||
continue;
|
||||
}
|
||||
if (enPct) {
|
||||
const n = Number(v);
|
||||
if (Number.isFinite(n) && n <= SEUIL_PCT) alertes.push({ entite: id, nom, statut: 'faible', niveau: n, depuis: s.last_changed,
|
||||
texte: `${nom} : pile a ${n} %` });
|
||||
} else if (v === 'low') {
|
||||
alertes.push({ entite: id, nom, statut: 'faible', niveau: 'low', depuis: s.last_changed, texte: `${nom} : pile faible` });
|
||||
}
|
||||
}
|
||||
alertes.sort((x, y) => (x.statut === y.statut ? x.nom.localeCompare(y.nom) : x.statut === 'faible' ? -1 : 1));
|
||||
return {
|
||||
alertes,
|
||||
texte: alertes.length ? alertes.map((x) => `- ${x.texte}`).join('\n') : 'Toutes les piles des capteurs sont bonnes.',
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user