Files
EVCS/dashboards/bilan_energetique.yaml
Tallagrand Thierry 686578ef9d Dashboard : corrige le rendu des tableaux markdown
Les cartes markdown utilisaient un bloc YAML replie (content: >), qui remplace
les retours a la ligne par des espaces : les tableaux markdown perdaient leur
structure et s'affichaient comme une ligne de texte avec des barres verticales.
Passage en bloc litteral (content: |) sur les six cartes, et le tableau des
profils emet desormais chaque ligne sur la meme ligne que la boucle, sinon
Jinja intercale une ligne vide entre chaque rangee et casse le tableau.
Ajout d'un repli lisible quand les profils ne sont pas encore publies.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
2026-08-24 22:36:57 +02:00

199 lines
8.1 KiB
YAML

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(',') %}
{% set ok = p50 | length == 24 and p80 | length == 24 and env | length == 24 and cen | length == 24 %}
{% if not ok %}Profils indisponibles — le recalcul quotidien n'a pas encore publié.
{% else %}
| h | conso typique | conso prudente | production max | censure |
|---:|---:|---:|---:|---:|
{% for i in range(24) %}| {{ '%02d' | format(i) }} | {{ p50[i] }} | {{ p80[i] }} | {{ env[i] }} | {{ (cen[i] | float(1) * 100) | round(0) }} % |
{% endfor %}{% endif %}
*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`.