# Mémoire de mesures EVCS — à déployer sur le SECOND Synology (10.10.10.22). # # Deux bases, deux rôles distincts, décidés le 04/09/2026 : # # postgres (proposition A) — ce que n8n CALCULE : sorties du bilan, # décisions du contrôleur, prévision telle qu'elle a été publiée. # Relationnel, donc capable de stocker un vecteur de 24 valeurs, # une raison en texte, un événement daté — et de les JOINDRE. # # influxdb (proposition B) — ce que Home Assistant OBSERVE : chaque # changement d'état, à la résolution native, y compris les entités # auxquelles personne n'a encore pensé. C'est ce qui a manqué le # 03/09, quand les modes des chargeurs MPPT se sont révélés être le # bon signal alors que personne ne les enregistrait. # # ⚠️ NE PAS héberger sur 10.10.10.17 : cette machine porte déjà Home Assistant, # n8n, openclaw et open-webui. Une mémoire qui meurt avec la machine qu'elle # documente ne sert à rien (cf. HANDOFF §32). # # Mise en service : # cd /volume2/projects/EVCS/EVCS/deploy/historisation # bash preparer-env.sh (genere .env avec des secrets aleatoires) # docker compose up -d # docker compose logs -f # # Vérification : # docker compose exec postgres psql -U evcs -d evcs -c '\dt' # curl -s http://10.10.10.22:8086/health # # Volumes NOMMÉS et non bind-mounts : le démon Docker de DSM refuse un # bind-mount dont le dossier hôte est absent, et une base de données sur un # partage réseau est une mauvaise idée (verrouillage, latence, fsync). services: postgres: image: postgres:16-alpine container_name: evcs-postgres restart: always ports: # 5433 et non 5432 : DSM fait deja tourner son propre PostgreSQL sur le # port standard, pour ses services internes. On ne le deloge pas — on se # met a cote. Ce port n'est publie que pour l'analyse depuis un poste de # travail ; l'historisation, elle, passe par le reseau interne. - "5433:5432" env_file: - .env environment: - TZ=Europe/Paris - POSTGRES_USER=evcs - POSTGRES_DB=evcs # POSTGRES_PASSWORD vient de historisation.env - PGDATA=/var/lib/postgresql/data/pgdata volumes: - evcs-pgdata:/var/lib/postgresql/data # Appliqué UNE SEULE FOIS, à la création de la base. Pour faire évoluer # le schéma ensuite, écrire une migration et la passer à psql. - ./schema.sql:/docker-entrypoint-initdb.d/10-schema.sql:ro healthcheck: test: ["CMD-SHELL", "pg_isready -U evcs -d evcs"] interval: 1m timeout: 10s retries: 5 influxdb: image: influxdb:2.7-alpine container_name: evcs-influxdb restart: always ports: # Home Assistant, sur 10.10.10.17, écrit ici. - "8086:8086" env_file: - .env environment: - TZ=Europe/Paris - DOCKER_INFLUXDB_INIT_MODE=setup - DOCKER_INFLUXDB_INIT_ORG=airtria - DOCKER_INFLUXDB_INIT_BUCKET=evcs # Rétention 0 = illimitée sur le seau brut. Le sous-échantillonnage se # fait par tâches (voir README), pas en jetant la donnée d'entrée. - DOCKER_INFLUXDB_INIT_RETENTION=0 # DOCKER_INFLUXDB_INIT_USERNAME / _PASSWORD / _ADMIN_TOKEN : env file volumes: - evcs-influx-data:/var/lib/influxdb2 - evcs-influx-config:/etc/influxdb2 healthcheck: test: ["CMD", "influx", "ping"] interval: 1m timeout: 10s retries: 5 # Alimentation de PostgreSQL depuis Home Assistant. Volontairement PAS # depuis n8n : tout ce que n8n calcule, il le publie deja dans des helpers HA # — les lire ici donne la meme information sans toucher aux trois workflows # de production ni creer d'identifiant dans n8n. historisation: image: node:22-alpine container_name: evcs-historisation restart: always working_dir: /app depends_on: postgres: condition: service_healthy volumes: # Depot en LECTURE SEULE : ce service n'ecrit que dans la base. - /volume2/projects/EVCS/EVCS:/app:ro env_file: - .env environment: - TZ=Europe/Paris - HA_URL=http://10.10.10.17:8123 # Nom de service sur le reseau interne du compose : ni IP en dur, ni # dependance au port publie sur l'hote. - PGHOST=postgres - PGPORT=5432 - PGUSER=evcs - PGDATABASE=evcs # Reprise du mot de passe unique par substitution : il n'y a qu'un seul # secret PostgreSQL a renseigner, pas deux a tenir egaux a la main. - PGPASSWORD=${POSTGRES_PASSWORD} - HISTORISE_INTERVAL_S=60 command: ["node", "tools/historise-evcs.mjs"] # Consultation des DEUX bases au meme endroit. Grafana ne stocke rien de la # mesure : il interroge PostgreSQL et InfluxDB a la demande. Le perdre ne # perd aucune donnee — c'est une fenetre, pas un coffre. grafana: image: grafana/grafana-oss:11.3.0 container_name: evcs-grafana restart: always depends_on: # Ordre de demarrage SEULEMENT, volontairement pas `service_healthy` : # Grafana n'a pas besoin de PostgreSQL pour demarrer, seulement pour # repondre a une requete. Le rendre otage de la sante d'une autre base, # c'est ajouter un mode de panne sans contrepartie — et un outil de # diagnostic doit surtout etre disponible quand quelque chose va mal. - postgres ports: # 3001 et NON 3000 : quelque chose ecoute deja sur 3000 sur cette # machine (verifie avant d'ecrire cette ligne, comme le port 5432 deja # pris par le PostgreSQL interne de DSM). - "3001:3000" env_file: # Deux fichiers : les secrets de la pile (mot de passe admin Grafana, # mot de passe PostgreSQL) et ceux du depot (role de lecture, jeton # InfluxDB). Aucun secret n'est duplique — c'etait le piege du # POSTGRES_PASSWORD/PGPASSWORD tenus egaux a la main. - .env - ../../.env environment: - TZ=Europe/Paris - GF_SECURITY_ADMIN_USER=admin - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_ADMIN_PASSWORD} # Rien ne sort de la maison : ni telemetrie, ni verification de version, # ni recuperation de plugins. Cette installation doit fonctionner # pendant une coupure Internet d'orage (HANDOFF §32). - GF_ANALYTICS_REPORTING_ENABLED=false - GF_ANALYTICS_CHECK_FOR_UPDATES=false - GF_ANALYTICS_CHECK_FOR_PLUGIN_UPDATES=false - GF_NEWS_NEWS_FEED_ENABLED=false - GF_USERS_ALLOW_SIGN_UP=false - GF_DATE_FORMATS_DEFAULT_TIMEZONE=Europe/Paris volumes: # Provisionnement en LECTURE SEULE : sources de donnees et tableaux de # bord viennent du depot git, comme le code des nodes n8n (regle R2). - ./grafana/provisioning:/etc/grafana/provisioning:ro - ./grafana/dashboards:/var/lib/grafana/dashboards:ro # Base interne de Grafana : sessions, preferences, copies de travail. - evcs-grafana-data:/var/lib/grafana healthcheck: test: ["CMD-SHELL", "wget -q -O- http://localhost:3000/api/health || exit 1"] interval: 1m timeout: 10s retries: 5 volumes: evcs-pgdata: evcs-influx-data: evcs-influx-config: evcs-grafana-data: