`bucketHourly` garde la derniere valeur de chaque heure : le delta entre H-1 et H est l'energie depensee PENDANT H. `deltaSeries` le rangeait sous H-1. Discret sur un compteur dense, catastrophique sur un compteur epars — et les compteurs de cette installation le sont : `ac_in_1_to_ac_out` ne peuple que 57 heures sur 267, `evcs_total` 57 sur 264, parce qu'ils n'emettent que lorsqu'ils avancent. Une heure vide vaut « zero energie », donc toute l'energie d'un intervalle a trou a ete consommee pendant l'heure FINALE. Rangee sous l'heure initiale, l'import reseau de la nuit suivante atterrissait sur la derniere heure de la nuit precedente. Mesure du 25/08 : consumption_p50[8] = 2,90 kWh/h pour 0,80 reellement — six echantillons sur douze portaient un delta etale sur 17 heures. Le bilan reclamait environ deux fois trop d'energie le matin (3,37 kWh annonces a 06 h contre 1,35 mesures), et donc un SOC requis de 44,5 % la ou 31 % suffisait. L'enveloppe de production etait decalee de la meme heure, ce qui a contribue a surestimer la part matinale de la production dans le journal de chantier. Ajoute aussi un statut `degrade` : le bilan publie ses chiffres quand aucun croisement n'apparait sur l'horizon ou quand les heures de deficit reposent sur une forme minoree, mais il ne les presente plus comme fiables. La nuit du 25/08, avant la mise en service de la courbe horaire, il a publie un SOC requis de 100 % avec un statut `ok`. Tests 36 -> 37, dont `compteur-epars-attribution-horaire` (rafale reseau de 1/2/3 kWh a 01/02/03 h : montants distincts pour qu'un decalage d'un cran soit impossible a confondre). Mutation verifiee : l'ancienne attribution le fait echouer. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
215 lines
8.7 KiB
YAML
215 lines
8.7 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: "indisponible"
|
|
card:
|
|
type: markdown
|
|
content: |
|
|
## ⚠️ Bilan indisponible
|
|
|
|
{{ states('input_text.evcs_balance_reason') }}
|
|
|
|
Les contrôleurs fonctionnent sur leurs règles historiques.
|
|
|
|
- type: conditional
|
|
conditions:
|
|
- entity: input_text.evcs_balance_status
|
|
state: "degrade"
|
|
card:
|
|
type: markdown
|
|
content: |
|
|
## 🟠 Bilan dégradé
|
|
|
|
Les chiffres sont publiés, mais ils reposent sur une base
|
|
incomplète : soit aucun croisement production/consommation
|
|
n'apparaît sur l'horizon, soit la forme de production des heures
|
|
de déficit vient d'un repli sur l'enveloppe mesurée.
|
|
|
|
{{ states('input_text.evcs_balance_reason') }}
|
|
|
|
# --- 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`.
|