Files
EVCS/deploy/historisation/README.md
Tallagrand Thierry 931e07eca9 Le service d historisation consigne lui-meme les evenements qu il constate
Une courbe sans ses evenements ne s interprete pas. Le service voit passer les
etats toutes les minutes : autant qu il en tire les conclusions plutot que d
attendre que quelqu un y pense.

Douze etats DISCRETS suivis — contacteur EDF, session reseau de nuit, verrou
hysteresis, vehicule branche, strategie, vehicule selectionne, etat BatteryLife,
mode de l Auto Charge Manager, reseau necessaire, vigilance orage, production
bridee. Les grandeurs continues restent dans mesure et les decisions dans
decision : un evenement qui double une autre table est du bruit. Une lecture
unavailable n est pas une transition mais une absence de lecture, elle n est pas
consignee.

Le redemarrage de Home Assistant est detecte sans capteur d uptime, qui n existe
pas ici : au redemarrage HA restaure ses helpers et leur pose un last_changed
neuf. Le 04/09 a 07:28:49, 352 entites partageaient la seconde du redemarrage
dont 183 input_number. Le service prend donc le mode des last_changed des
input_number — aucune entite codee en dur, et l estimation se corrige d
elle-meme puisque entre deux redemarrages seuls les helpers reellement ecrits s
ecartent du mode. Sous dix helpers d accord, la signature est jugee trop faible
et rien n est affirme.

Un episode d indisponibilite de Home Assistant est journalise AU RETOUR avec sa
duree : au moment de la panne, la base n est peut-etre pas joignable non plus.

Au premier cycle l etat est enregistre SANS rien journaliser, sinon chaque
redemarrage du service produirait douze fausses transitions ; seul le demarrage
du service est consigne.

Verifie de bout en bout en conditions reelles et non seulement a blanc : essai a
blanc avec cycle court, bascule reelle du selecteur de vehicule puis
restauration. Amorcage sans fausse transition, cycle sans changement a zero
evenement, les deux bascules relevees, etat restaure.

Documente aussi le GRANT INSERT sur la seule table evenement pour le role d
analyse — insert seulement, ni update ni delete : on ajoute une annotation,
jamais on ne reecrit ni n efface les precedentes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-09-04 07:43:49 +02:00

172 lines
7.1 KiB
Markdown

# Mémoire de mesures EVCS
Deux bases sur **10.10.10.22**, décidées le 04/09/2026 : on met les deux en
service et on décide à l'usage s'il faut garder les deux.
| | rôle | source | résolution |
|---|---|---|---|
| **PostgreSQL** | ce que n8n **calcule** — bilan, décisions, prévisions publiées | workflows n8n | cadence des workflows |
| **InfluxDB** | ce que Home Assistant **observe** — tous les états du périmètre énergie | intégration HA | chaque changement d'état |
Le raisonnement complet et le comparatif : `HANDOFF.md` §42 et suivantes.
## Pourquoi pas sur 10.10.10.17
Cette machine porte déjà Home Assistant, n8n, openclaw et open-webui. Une
mémoire hébergée par la machine dont elle documente les pannes ne survit pas à
celles-ci. Le volume n'est pas l'argument : les deux Synology ont des téraoctets
libres.
## Mise en service
### 1. Les deux bases (à faire sur 10.10.10.22)
```sh
cd /volume2/projects/EVCS/EVCS/deploy/historisation
bash preparer-env.sh # génère .env avec des secrets aléatoires
docker compose up -d
docker compose logs -f
```
### D'où viennent les secrets
| secret | origine |
|---|---|
| `HA_TOKEN` | **existe déjà** — repris du `.env` à la racine du dépôt |
| `POSTGRES_PASSWORD` | **créé ici** — la base n'existe pas encore, ce fichier décide de son mot de passe |
| `DOCKER_INFLUXDB_INIT_PASSWORD` | **créé ici**, idem (InfluxDB exige au moins 8 caractères) |
| `DOCKER_INFLUXDB_INIT_ADMIN_TOKEN` | **créé ici** — c'est le jeton que Home Assistant utilisera pour écrire |
Aucun ne s'obtient auprès de quelqu'un, et aucun ne doit être choisi à la main :
personne ne les tape jamais — les conteneurs les lisent dans `.env`, et Home
Assistant lit le jeton dans son propre `secrets.yaml`. Une phrase inventée est
plus courte et plus devinable qu'elle n'en a l'air ; `openssl rand` ne l'est pas.
`preparer-env.sh` refuse d'écraser un `.env` existant : régénérer les mots de
passe d'une base déjà créée la rendrait inaccessible, puisqu'elle continuerait
d'attendre les anciens.
Vérifications :
```sh
docker compose exec postgres psql -U evcs -d evcs -c '\dt'
curl -s http://10.10.10.22:8086/health
docker compose logs historisation --tail 5
```
### Ports : 5433, et pas 5432
DSM fait tourner **son propre PostgreSQL sur 5432**, pour ses services internes.
Notre base est donc publiée sur **5433**. Ce port ne sert qu'à l'analyse depuis
un poste de travail :
```sh
psql -h 10.10.10.22 -p 5433 -U evcs -d evcs
```
Les trois conteneurs, eux, se parlent par le réseau interne du compose et par
nom de service (`postgres:5432`) — ni adresse IP en dur, ni dépendance au port
publié. Vérifier ce qui occupe un port avant de conclure :
```sh
sudo ss -lntp | grep -E '5432|5433|8086'
```
Le schéma (`schema.sql`) est appliqué **une seule fois**, à la création de la
base. Pour le faire évoluer ensuite, écrire une migration et la passer à `psql` :
recréer le volume effacerait l'historique, ce qui est précisément ce qu'on
cherche à ne plus faire.
### 2. Brancher Home Assistant sur InfluxDB
⚠️ **Demande un redémarrage de Home Assistant**, pendant lequel le contrôleur
EVCS ne décide plus rien. **Jamais entre 01:24 et 07:24**, ni pendant une charge.
Le bon créneau est le milieu de matinée.
1. mettre le jeton dans `secrets.yaml` sous la clé `influxdb_token` ;
2. coller le bloc de `ha-influxdb.yaml` dans `configuration.yaml` ;
3. `homeassistant.check_config`, puis redémarrer.
### 3. Alimenter PostgreSQL depuis n8n
À faire après l'étape 1 — n8n a besoin que la base existe pour qu'on y crée
l'identifiant de connexion.
## Événements : détectés par le service, annotés à la main
La table `evenement` existe parce qu'une courbe sans ses événements ne
s'interprète pas : « le rendement a changé le 12 novembre » ne veut rien dire
sans la ligne qui dit qu'un pack a été rebranché ce jour-là.
**Le service consigne seul ce qu'il peut constater** — il voit passer les états
toutes les minutes, autant qu'il en tire les conclusions plutôt que d'attendre
que quelqu'un y pense :
| genre | ce qui est consigné |
|---|---|
| `systeme` | démarrage du service, redémarrage de Home Assistant, épisode d'indisponibilité avec sa durée |
| `reseau` | contacteur EDF, session réseau de nuit, reprise nuit, verrou hystérésis |
| `vehicule` | véhicule branché ou débranché |
| `intervention` | changement de stratégie ou de véhicule sélectionné |
| `ess` | état BatteryLife, mode de l'Auto Charge Manager |
| `bilan` | réseau nécessaire, vigilance orage, production bridée |
On suit des états **discrets** dont chaque changement mérite une ligne. Les
grandeurs continues sont dans `mesure`, les décisions du contrôleur dans
`decision` : un événement qui double une autre table est du bruit. Une lecture
`unavailable` n'est pas une transition mais une absence de lecture — elle n'est
pas consignée.
Le redémarrage de Home Assistant est detecté **sans capteur d'uptime**, qui
n'existe pas sur cette installation : au redémarrage HA restaure ses helpers et
leur pose un `last_changed` neuf. Le 04/09, 352 entités partageaient la seconde
du redémarrage, dont 183 `input_number`. Le service prend donc le **mode** des
`last_changed` des `input_number` — aucune entité codée en dur, et l'estimation
se corrige d'elle-même.
**Les annotations qu'aucun service ne peut deviner** — « pack rebranché »,
« correctif déployé » — s'écrivent à la main. Pour cela le rôle d'analyse a
besoin d'un `INSERT` sur cette seule table :
```sh
sudo docker compose exec -T postgres psql -U evcs -d evcs -c \
"GRANT INSERT ON evenement TO evcs_lecture;
GRANT USAGE, SELECT ON SEQUENCE evenement_id_seq TO evcs_lecture;"
```
`INSERT` seulement : ni `UPDATE`, ni `DELETE`. On peut ajouter une annotation,
jamais réécrire ni effacer les précédentes — y compris les siennes. C'est ce
qu'on attend d'un journal, et ça laisse les tables de mesure hors de portée.
## Accès en lecture pour l'analyse
```sh
sudo bash creer-role-lecture.sh
```
Crée le rôle `evcs_lecture` en **lecture seule** et dépose son mot de passe dans
le `.env` à la racine du dépôt. Le mot de passe est généré, jamais choisi, et
**n'est pas affiché** : il va du générateur au fichier, donc rien à recopier et
rien à exposer dans une capture.
Deux raisons de ne pas analyser avec le compte `evcs` : une mémoire dont tout
l'intérêt est de ne pas être réécrite ne se consulte pas avec un compte qui peut
écrire, et un mot de passe rangé dans un fichier lisible ne doit pas être celui
qui gouverne la base.
Le script est rejouable : si le rôle existe déjà et que son mot de passe est
dans le `.env`, il ne fait rien.
## Ce qu'aucune des deux ne fait
Elles ne remontent pas dans le passé. La mémoire commence le jour où on les
branche : c'est un argument pour les mettre en service vite, pas pour les
mettre en service parfaitement.
## Sauvegarde
Les deux bases vivent dans des volumes Docker nommés, donc **hors du dépôt et
hors des sauvegardes Home Assistant**. Une mémoire non sauvegardée est une
mémoire qu'on perdra une fois — voir `HANDOFF.md` §34, qui raconte la même
histoire pour Home Assistant.