Chantier etape 6 : tableau de bord du bilan energetique

Dashboard YAML dedie "bilan-energetique", declare dans configuration.yaml et
copie versionnee dans dashboards/ du depot.

Vue Bilan : la comparaison qui decidera du cablage — seuil calcule, seuil fixe
encore en vigueur, SOC reel — avec un commentaire automatique disant lequel des
deux est trop haut ou trop bas ; la decision immediate ; la prochaine traversee
deficitaire ; une alerte conditionnelle chiffrant la capacite manquante quand
meme une batterie pleine ne passe pas ; l'etat de bridage de la production avec
son motif ; deux graphiques d'historique sur 48 h.

Vue Profils et reglages : tableau horaire des quatre profils avec le taux de
censure par heure, capacite batterie modifiable, kill-switch, statut.

configuration.yaml sauvegarde dans SAVE_CONFIG/ avant modification,
check_config valide, redemarrage HA effectue, journal sans erreur nouvelle.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
This commit is contained in:
Tallagrand Thierry
2026-08-24 16:04:52 +02:00
parent 6dc5ea25cb
commit a413f48f63
2 changed files with 217 additions and 1 deletions

View File

@@ -0,0 +1,205 @@
views:
# ===================================================================
- title: Bilan
path: bilan
icon: mdi:scale-balance
cards:
- type: vertical-stack
cards:
- type: custom:mushroom-title-card
title: Bilan énergétique
subtitle: Mode ombre — observe et publie, ne pilote rien
- type: conditional
conditions:
- entity: input_text.evcs_balance_status
state_not: "ok"
card:
type: markdown
content: >
## ⚠️ Bilan indisponible
{{ states('input_text.evcs_balance_reason') }}
Les contrôleurs fonctionnent sur leurs règles historiques.
# --- LA comparaison qui décidera du câblage ---------------------
- type: markdown
title: Seuil calculé contre seuil fixe
content: >
{% set req = states('input_number.evcs_balance_required_soc') | float(0) %}
{% set fixe = states('input_number.victron_grid_soc_off') | float(0) %}
{% set soc = states('sensor.victron_battery_soc') | float(0) %}
{% set ecart = req - fixe %}
| | |
|---|---:|
| SOC batterie **maintenant** | **{{ soc | round(0) }} %** |
| Seuil **calculé** par le bilan | **{{ req | round(1) }} %** |
| Seuil **fixe** encore en vigueur | {{ fixe | round(0) }} % |
| Écart | {{ '+' if ecart >= 0 else '' }}{{ ecart | round(1) }} points |
{% if req > fixe %}
Le seuil fixe est aujourd'hui **trop bas** : il laisserait la batterie
descendre sous ce qu'il faut pour tenir jusqu'au croisement.
{% elif req < fixe %}
Le seuil fixe est aujourd'hui **trop haut** : il fait importer du
réseau au-delà du nécessaire.
{% else %}
Les deux coïncident.
{% endif %}
*C'est l'accumulation de cet écart, jour après jour, qui décidera si
le bilan prend la main.*
# --- Décision immédiate ----------------------------------------
- type: entities
title: Décision immédiate
state_color: true
entities:
- entity: input_boolean.evcs_balance_grid_needed
name: Réseau nécessaire
- entity: input_text.evcs_balance_crossing_hour
name: Croisement production / consommation
- entity: input_number.evcs_balance_energy_to_cover_kwh
name: Énergie à couvrir d'ici là
- entity: input_number.evcs_balance_grid_energy_needed_kwh
name: Énergie réseau strictement nécessaire
- type: divider
- entity: input_number.evcs_balance_required_soc
name: SOC requis (décision)
- entity: input_number.evcs_balance_required_soc_prudent
name: SOC requis (planification)
# --- La nuit qui vient ------------------------------------------
- type: entities
title: Prochaine traversée déficitaire
entities:
- entity: input_text.evcs_balance_next_deficit_window
name: Fenêtre
- entity: input_number.evcs_balance_next_deficit_kwh
name: Énergie à fournir
- entity: input_number.evcs_balance_next_deficit_required_soc
name: SOC à atteindre avant
- entity: input_number.evcs_balance_storage_shortfall_kwh
name: Capacité de stockage manquante
- type: conditional
conditions:
- entity: input_number.evcs_balance_storage_shortfall_kwh
state_not: "0.0"
card:
type: markdown
content: >
### 🔋 Stockage insuffisant pour cette traversée
Il manque **{{ states('input_number.evcs_balance_storage_shortfall_kwh') }} kWh**
de capacité utile : même chargée à 100 %, la batterie actuelle
({{ states('input_number.evcs_balance_usable_capacity_kwh') }} kWh)
ne passe pas la fenêtre sans réseau.
*Un module US2000C ≈ 2,4 kWh nominal.*
# --- Ce qu'on jette ---------------------------------------------
- type: markdown
title: Production
content: >
{% set bride = is_state('input_boolean.evcs_balance_pv_censored', 'on') %}
{% if bride %}
### 🔻 Production actuellement **bridée**
Motif : *{{ states('input_text.evcs_balance_censor_reason') }}*
Sans injection réseau, l'onduleur ne produit que ce que le système
peut absorber. Le soleil est là, il manque un preneur.
{% else %}
### ☀️ Production **libre**
Rien ne bride l'onduleur en ce moment : la mesure de production
reflète la ressource réelle.
{% endif %}
Surplus attendu pour le véhicule aujourd'hui :
**{{ states('input_number.evcs_balance_vehicle_surplus_kwh') }} kWh**
- type: history-graph
title: SOC réel contre seuil calculé
hours_to_show: 48
entities:
- entity: sensor.victron_battery_soc
name: SOC batterie
- entity: input_number.evcs_balance_required_soc
name: Seuil calculé
- entity: input_number.victron_grid_soc_off
name: Seuil fixe
- type: history-graph
title: Bridage de la production
hours_to_show: 48
entities:
- entity: input_boolean.evcs_balance_pv_censored
name: Production bridée
- entity: switch.edf_general_ok_switch
name: Réseau EDF
# ===================================================================
- title: Profils & réglages
path: profils
icon: mdi:chart-bell-curve
cards:
- type: custom:mushroom-title-card
title: Profils mesurés
subtitle: Recalculés chaque nuit à 03:30 sur l'historique réel
- type: markdown
title: Profil horaire de consommation (kWh/h, hors véhicule)
content: >
{% set p50 = states('input_text.evcs_balance_consumption_p50').split(',') %}
{% set p80 = states('input_text.evcs_balance_consumption_p80').split(',') %}
{% set env = states('input_text.evcs_balance_envelope').split(',') %}
{% set cen = states('input_text.evcs_balance_censorship_rate').split(',') %}
| h | conso typique | conso prudente | production max | censure |
|---:|---:|---:|---:|---:|
{% for i in range(24) %}
| {{ '%02d' | format(i) }} | {{ p50[i] if p50 | length == 24 else '—' }} | {{ p80[i] if p80 | length == 24 else '—' }} | {{ env[i] if env | length == 24 else '—' }} | {{ (cen[i] | float(1) * 100) | round(0) if cen | length == 24 else '—' }} % |
{% endfor %}
*La colonne « censure » indique la part des jours où la batterie était
pleine à cette heure : au-delà de 25 %, la production maximale
observée est minorée et le bilan le signale.*
- type: entities
title: Réglages
entities:
- entity: input_number.evcs_balance_usable_capacity_kwh
name: Capacité batterie utile
- entity: input_boolean.evcs_balance_enabled
name: Bilan actif (kill-switch)
- type: divider
- entity: input_text.evcs_balance_status
name: Statut
- entity: input_text.evcs_balance_last_run
name: Dernière exécution
- entity: input_text.evcs_balance_reason
name: Explication
- type: markdown
content: >
### À propos
Ce bilan remplace des seuils fixes par des grandeurs mesurées. Il
**n'écrit que dans ses propres entités** `evcs_balance_*` : aucun
interrupteur, aucune consigne de borne, aucune stratégie. Cette
garantie est vérifiée par la suite de tests du dépôt, qui échoue si
une écriture sort de ce périmètre.
Détail de la démarche : `docs/CHANTIER_BILAN_ENERGETIQUE.md`.

View File

@@ -211,7 +211,18 @@ calcul en saison basse.
écrêté à 100 %** : au-delà, même une batterie pleine ne passe pas, et l'écart
est publié comme `storage_shortfall_kwh`. C'est le chiffre du dimensionnement
du stockage.
- [ ] Étape 6 — dashboard, après quelques jours d'observation.
- [x] **Étape 6 — tableau de bord** (24/08). Dashboard YAML dédié
`bilan-energetique` (icône balance, barre latérale), copie versionnée dans
`dashboards/bilan_energetique.yaml` du dépôt.
Vue **Bilan** : la comparaison seuil calculé / seuil fixe / SOC réel avec son
commentaire automatique, la décision immédiate, la prochaine traversée
déficitaire, une alerte conditionnelle quand le stockage est insuffisant,
l'état de bridage de la production, et deux graphiques d'historique
(SOC contre seuils, bridage contre réseau EDF).
Vue **Profils & réglages** : le tableau horaire des quatre profils avec le
taux de censure par heure, la capacité batterie (modifiable), le kill-switch.
Déclaré dans `configuration.yaml` (sauvegarde dans `SAVE_CONFIG/`),
redémarrage HA effectué, aucune erreur au journal.
## Backlog