Files
EVCS/packages/llm_monitor.yaml
Tallagrand Thierry 9fb73415b4 Surveillance du modele local : le brouillon avait un angle mort
Le paquet propose par la session Airtria portait trois entites — interrupteur
d alertes, RAM disponible, libelle d etat. Il lui manquait celle sans laquelle
les trois autres mentent : un horodatage ecrit a chaque passage.

Sans lui, un moniteur mort est indiscernable d un systeme sain. Les trois
entites gardent leur derniere valeur, qui dit « tout va bien », indefiniment.
C est exactement l incident du 08/09 sur la prevision solaire, ou 4 h 45 de
panne n ont laisse aucune trace. Et on ne peut PAS deduire la fraicheur du
last_updated des autres entites : Home Assistant ne rafraichit pas l horodatage
d un helper reecrit a l identique — une RAM stable une heure produirait la meme
illusion.

Ajoutes : l horodatage, le modele charge, un capteur d age, et deux alarmes —
moniteur muet, RAM sous le seuil ou earlyoom tue le plus gourmand.

Defaut trouve et corrige apres creation : l alarme RAM se declenchait avant que
le moniteur ait tourne une seule fois, une valeur jamais ecrite valant zero.
Une mesure qu on n a pas recue n est pas une mesure basse. Elle est desormais
conditionnee a la fraicheur.

Tableau separe des tableaux energie : ce qu il montre n a aucun rapport avec le
photovoltaique.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GwpFpy2aQ2rJok6tNQSbVj
2026-09-14 21:50:07 +02:00

109 lines
4.5 KiB
YAML
Executable File

# Surveillance du modele local sur la Spark (10.10.10.8)
#
# Ce paquet N'A RIEN A VOIR avec le systeme photovoltaique. Il vit ici parce que
# c'est le seul endroit ou des entites Home Assistant peuvent exister, pas parce
# qu'il appartient au domaine energie. Ne pas melanger ses entites a celles de
# `evcs_*` / `victron_*`, et ne rien cabler de l'energie dessus.
#
# Ce que surveille le moniteur (script externe, cron sur 10.10.10.17) :
# - le point d'acces du modele repond-il
# - la RAM disponible de la Spark, qu'earlyoom peut faire tomber en tuant
# le modele autour de 6 %
#
# ⚠️ AUCUN `initial:` DANS CE FICHIER. Declarer `initial:` DESACTIVE la
# restauration d'etat : le helper est force a cette valeur a CHAQUE demarrage de
# Home Assistant. Le 06/09/2026 cinq reglages manuels du projet se
# reinitialisaient ainsi en silence, dont deux toggles de cablage. Le
# kill-switch ci-dessous doit garder la position choisie par le proprietaire.
input_boolean:
llm_monitor_enabled:
name: "LLM monitor — alertes WhatsApp"
icon: mdi:bell-ring
input_number:
llm_mem_avail_pct:
name: "Spark — RAM disponible"
min: 0
max: 100
step: 0.1
unit_of_measurement: "%"
mode: box
icon: mdi:memory
input_text:
# ⚠️ `max` DOIT couvrir le plus long MESSAGE D'ERREUR, pas la valeur nominale.
# Le 08/09/2026, `evcs_balance_forecast_updated` etait declare `max: 32` : ses
# messages d'echec faisaient 43 caracteres, Home Assistant les REJETAIT EN
# SILENCE, et une panne de 4 h 45 n'a laisse aucune trace. 255 est la valeur
# sure pour un champ d'etat.
llm_monitor_status:
name: "LLM monitor — état"
max: 255
icon: mdi:robot-outline
llm_monitor_model:
name: "LLM monitor — modèle chargé"
max: 100
icon: mdi:chip
input_datetime:
# ⚠️ LE CAPTEUR LE PLUS IMPORTANT DU PAQUET, et celui qui manquait au
# brouillon. Sans horodatage ecrit A CHAQUE PASSAGE, un moniteur mort est
# indiscernable d'un systeme sain : les trois autres entites gardent leur
# derniere valeur, qui dit « tout va bien », indefiniment.
#
# Et il ne faut PAS deduire la fraicheur du `last_updated` des autres
# entites : Home Assistant NE RAFRAICHIT PAS l'horodatage d'un helper reecrit
# a l'identique. Constate le 01/09/2026 — un etat paraissait fige depuis
# 2 440 s alors que le controleur tournait normalement. Une RAM stable a
# 12,3 % pendant une heure produirait exactement la meme illusion.
llm_monitor_last_seen:
name: "LLM monitor — dernière vérification"
has_date: true
has_time: true
template:
- sensor:
- name: "LLM monitor — âge du dernier passage"
unique_id: llm_monitor_age_min
unit_of_measurement: "min"
state: >
{% set t = states('input_datetime.llm_monitor_last_seen') %}
{% if t not in ['unknown','unavailable',''] %}
{{ ((as_timestamp(now()) - as_timestamp(t, 0)) / 60) | round(0) }}
{% else %}unknown{% endif %}
- binary_sensor:
# Le moniteur tourne toutes les 2 minutes. Au-dela de 10, il ne tourne
# plus — et c'est une information a part entiere, pas une absence.
- name: "LLM monitor — muet"
unique_id: llm_monitor_muet
device_class: problem
state: >
{% set t = states('input_datetime.llm_monitor_last_seen') %}
{% if t in ['unknown','unavailable',''] %}on
{% else %}
{{ (as_timestamp(now()) - as_timestamp(t, 0)) > 600 }}
{% endif %}
# earlyoom tue le processus le plus gourmand quand la memoire s'effondre,
# et sur cette machine le plus gourmand est le modele. Le seuil est celui
# que le proprietaire a nomme.
#
# ⚠️ CONDITIONNE A LA FRAICHEUR DU MONITEUR. Une valeur jamais ecrite vaut
# 0 — le minimum du helper — et serait lue comme « 0 % de RAM libre »,
# donc comme une alarme permanente avant meme que le moniteur ait tourne
# une fois. Une mesure qu'on n'a pas recue n'est pas une mesure basse :
# c'est `llm_monitor_muet` qui doit le dire, et lui seul.
- name: "Spark — RAM critique"
unique_id: spark_ram_critique
device_class: problem
state: >
{% set t = states('input_datetime.llm_monitor_last_seen') %}
{% if t in ['unknown','unavailable',''] %}off
{% elif (as_timestamp(now()) - as_timestamp(t, 0)) > 600 %}off
{% else %}
{{ states('input_number.llm_mem_avail_pct') | float(100) < 8 }}
{% endif %}