Victron Mobile refait en lecture seule (alertes reelles, energie du jour, nuit, borne, chauffe-eau, cellules) ; chauffe-eau coupe = 0 W

This commit is contained in:
Tallagrand Thierry
2026-10-07 07:35:12 +02:00
parent ad48de1c75
commit c8560e914b
4 changed files with 193 additions and 329 deletions

View File

@@ -1,3 +1,12 @@
# =====================================================================
# VICTRON MOBILE — refait le 07/10/2026 (demande du proprietaire).
# Une colonne, de haut en bas : alertes, batterie, reseau, energie du jour,
# nuit, borne, chauffe-eau, cellules, flux des 4 dernieres heures.
# ⚠️ LECTURE SEULE : aucun appui ne commande le contacteur EDF, la borne ou
# le chauffe-eau (une fiche « more-info » de switch permet de les basculer en
# deux appuis ; les automates en sont les seuls proprietaires).
# Ancienne version : victron_mobile.yaml.bak-20261007.
# =====================================================================
views: views:
- title: Mobile - title: Mobile
path: default_view path: default_view
@@ -5,40 +14,60 @@ views:
cards: cards:
- type: vertical-stack - type: vertical-stack
cards: cards:
- type: custom:mushroom-title-card # ---------- 1. ALERTES (seulement quand quelque chose ne va pas) ----------
title: Victron Mobile # « EDF ouvert » n'est PAS une alerte : c'est l'etat normal ici.
subtitle: Vue rapide iPhone / écran étroit
- type: conditional - type: conditional
conditions: conditions:
- entity: input_boolean.victron_auto_charge_enabled - condition: or
conditions:
- condition: state
entity: sensor.evcs_reseau
state: mesure_muette
- condition: state
entity: sensor.evcs_reseau
state: incoherent
card:
type: markdown
content: |
## ⚠️ Réseau : {{ states('sensor.evcs_reseau') | replace('_', ' ') }}
{{ state_attr('sensor.evcs_reseau', 'explication') or '' }}
- type: conditional
conditions:
- condition: or
conditions:
- condition: state
entity: sensor.evcs_cellules
state: perime
- condition: state
entity: sensor.evcs_cellules
state: muet
card:
type: markdown
content: |
## ⚠️ Cellules : {{ states('sensor.evcs_cellules') }}
Modules lus : {{ state_attr('sensor.evcs_cellules', 'modules_lus') }} sur 9.
- type: conditional
conditions:
- condition: state
entity: input_boolean.victron_auto_charge_enabled
state: "off" state: "off"
card: card:
type: markdown type: markdown
content: | content: |
## ⚠️ Auto batterie OFF ## ⚠️ Auto batterie OFF
- type: conditional - type: conditional
conditions: conditions:
- entity: input_boolean.victron_charge_override_enabled - condition: state
entity: input_boolean.victron_charge_override_enabled
state: "on" state: "on"
card: card:
type: markdown type: markdown
content: | content: |
## 🖐️ Override actif ## 🖐️ Override actif
- type: conditional # ---------- 2. BATTERIE ----------
conditions:
- entity: switch.edf_general_ok_switch
state: "off"
card:
type: markdown
content: |
## ⚠️ Réseau EDF OFF
- type: custom:vertical-stack-in-card - type: custom:vertical-stack-in-card
mode: vertical card_mod: &carte
card_mod:
style: | style: |
ha-card { ha-card {
border-radius: 20px; border-radius: 20px;
@@ -48,7 +77,7 @@ views:
cards: cards:
- type: custom:gauge-card-pro - type: custom:gauge-card-pro
entity: sensor.victron_battery_soc entity: sensor.victron_battery_soc
header: SOC Batterie header: Batterie
min: 0 min: 0
max: 100 max: 100
needle: true needle: true
@@ -61,323 +90,146 @@ views:
color: "#fdd835" color: "#fdd835"
- from: 75 - from: 75
color: "#43a047" color: "#43a047"
- type: custom:mushroom-template-card - type: custom:mushroom-template-card
entity: sensor.victron_battery_soc primary: >-
primary: Batterie {% set p = states('sensor.victron_battery_power') | float(0) %}
secondary: > {{ 'Charge' if p > 30 else ('Décharge' if p < -30 else 'Au repos') }}
{{ states('sensor.victron_battery_soc') | float(0) | round(1) }} % {{ p | abs | round(0) }} W ({{ states('sensor.victron_battery_current') | float(0) | round(1) }} A)
• {{ states('sensor.victron_battery_power') | float(0) | round(0) }} W secondary: >-
• {{ states('input_text.victron_charge_mode') }} Cible du matin {{ states('input_number.victron_evcs_night_target_soc') | float(0) | round(1) }} %
• requis maintenant {{ states('input_number.evcs_balance_required_soc') | float(0) | round(1) }} %
multiline_secondary: true multiline_secondary: true
icon: mdi:battery icon: mdi:battery-charging
icon_color: > tap_action:
{% set s = states('sensor.victron_battery_soc') | float(0) %} action: none
{% if s < 25 %} red
{% elif s < 50 %} orange
{% elif s < 75 %} yellow
{% else %} green
{% endif %}
- type: custom:vertical-stack-in-card
mode: vertical
card_mod:
style: |
ha-card {
border-radius: 20px;
border: 1px solid rgba(255,255,255,0.10);
box-shadow: 0 6px 16px rgba(0,0,0,0.18);
}
cards:
- type: custom:mushroom-title-card
title: Énergie
subtitle: Instantané
# ---------- 3. RESEAU (lecture seule) ----------
- type: custom:mushroom-template-card - type: custom:mushroom-template-card
primary: Production PV card_mod: *carte
secondary: > primary: >-
{{ states('sensor.victron_pv_power_system') | float(0) | round(0) }} W {% set r = states('sensor.evcs_reseau') %}
icon: mdi:solar-power {{ {'non_raccorde': 'EDF ouvert (normal)', 'raccorde': 'EDF fermé', 'etablissement': 'EDF en cours de fermeture',
icon_color: > 'mesure_muette': 'EDF : mesure muette', 'incoherent': 'EDF : incohérent'}.get(r, 'EDF : ' ~ r) }}
{% set pv = states('sensor.victron_pv_power_system') | float(0) %} {% if is_state('switch.edf_general_ok_switch', 'on') %} — {{ states('sensor.victron_grid_power_l1') | float(0) | round(0) }} W{% endif %}
{% if pv < 300 %} grey secondary: >-
{% elif pv < 1500 %} yellow Acheté aujourd'hui : {{ states('sensor.evcs_import_jour_kwh') }} kWh
{% else %} green
{% endif %}
- type: custom:mushroom-template-card
primary: Maison
secondary: >
{{ states('sensor.victron_consumption_power_l1') | float(0) | round(0) }} W
icon: mdi:home-lightning-bolt
icon_color: blue
- type: custom:mushroom-template-card
primary: Réseau
secondary: >
{{ states('sensor.victron_grid_power_l1') | float(0) | round(0) }} W
icon: mdi:transmission-tower icon: mdi:transmission-tower
icon_color: > icon_color: "{{ 'blue' if is_state('switch.edf_general_ok_switch', 'on') else 'grey' }}"
{% set g = states('sensor.victron_grid_power_l1') | float(0) %} tap_action:
{% if g > 0 %} red action: none
{% elif g < 0 %} green
{% else %} blue # ---------- 4. ENERGIE DU JOUR ----------
- type: markdown
card_mod: *carte
content: |
{% set vt = states('input_text.evcs_balance_vrm_today').split(',') %}
{% set ns = namespace(tot=0, reste=0) %}
{% if vt | length == 24 %}{% for i in range(24) %}{% set v = vt[i] | float(0) %}{% set ns.tot = ns.tot + v %}{% if i > now().hour %}{% set ns.reste = ns.reste + v %}{% elif i == now().hour %}{% set ns.reste = ns.reste + v * (1 - now().minute / 60) %}{% endif %}{% endfor %}{% endif %}
### Aujourd'hui
| | |
|---|---:|
| ☀️ Produit | **{{ states('sensor.evcs_production_jour_kwh') }} kWh** |
| ☀️ Prévu (VRM) / reste | {{ ns.tot | round(1) }} / {{ ns.reste | round(1) }} kWh |
| 🏠 Consommé | {{ states('sensor.evcs_consommation_jour_kwh') }} kWh |
| ⚡ Acheté EDF | {{ states('sensor.evcs_import_jour_kwh') }} kWh |
| 🔎 Solaire maintenant | {{ states('sensor.victron_pv_power_system') | float(0) | round(0) }} W — {{ states('sensor.evcs_pv_diagnostic') | replace('_', ' ') }} |
{% if state_attr('sensor.evcs_historisation_heartbeat', 'statut') != 'ok' %}
**⚠️ Service d'historisation : {{ state_attr('sensor.evcs_historisation_heartbeat', 'statut') }}** — les capteurs calculés sont figés.
{% endif %} {% endif %}
- type: custom:vertical-stack-in-card # ---------- 5. LA NUIT ----------
mode: vertical # Le soir : la prevision ; le matin : le bilan de la nuit ecoulee.
card_mod: - type: markdown
style: | card_mod: *carte
ha-card { content: |
border-radius: 20px; {% if now().hour >= 14 or now().hour < 2 %}
border: 1px solid rgba(255,255,255,0.10); ### 🌙 Cette nuit
box-shadow: 0 6px 16px rgba(0,0,0,0.18); {{ state_attr('sensor.evcs_prevision_nuit', 'texte_rapport') or states('sensor.evcs_prevision_nuit') }}
} {% else %}
cards: ### 🌙 La nuit dernière
- type: custom:mushroom-title-card {{ state_attr('sensor.evcs_bilan_nuit', 'texte_rapport') or states('sensor.evcs_bilan_nuit') }}
title: Charges pilotées {% endif %}
subtitle: États clés
Charge de la voiture la nuit : **{{ {'sans_edf': 'sans EDF', 'complete': 'complète'}.get(states('input_select.victron_evcs_night_charge_mode'), states('input_select.victron_evcs_night_charge_mode')) }}**
# ---------- 6. BORNE / VEHICULE ----------
- type: custom:mushroom-template-card - type: custom:mushroom-template-card
entity: sensor.victron_evcs_status card_mod: *carte
primary: EVCS primary: >-
secondary: > {{ states('sensor.victron_evcs_status_fr') }}
{{ states('sensor.victron_evcs_status') }} {% if is_state('binary_sensor.victron_evcs_vehicle_connected', 'on') %} — {{ states('input_select.victron_evcs_vehicle') }}{% endif %}
• {{ states('sensor.victron_evcs_current') | float(0) | round(0) }} A secondary: >-
{% set w = states('sensor.victron_evcs_ac_power') | float(0) %}
{% if w > 50 %}{{ w | round(0) }} W • {{ states('input_text.victron_evcs_source_mode') }} • {{ states('sensor.evcs_hq2239dnt7p_last_session_energy') }} kWh
{% else %}{{ (states('input_text.victron_evcs_surplus_reason').split('|') | first) | trim }}{% endif %}
{% if is_state('input_select.victron_evcs_vehicle', 'JEEP') %} • Jeep {{ states('sensor.jeep_renegade_phev_hvbattery_charge') }} %{% endif %}
multiline_secondary: true multiline_secondary: true
icon: mdi:ev-station icon: mdi:ev-station
icon_color: > icon_color: >-
{% if is_state('switch.victron_evcs_charging', 'on') %} {% if states('sensor.victron_evcs_ac_power') | float(0) > 50 %}green
green {% elif is_state('binary_sensor.victron_evcs_vehicle_connected', 'on') %}blue{% else %}grey{% endif %}
{% elif is_state('binary_sensor.victron_evcs_vehicle_connected', 'on') %} tap_action:
blue action: none
{% else %}
grey
{% endif %}
# ---------- 7. CHAUFFE-EAU ----------
- type: custom:mushroom-template-card - type: custom:mushroom-template-card
entity: switch.tt_chauffe_eau_pleumeur_switch card_mod: *carte
primary: Chauffe-eau primary: >-
secondary: > Chauffe-eau {{ 'sous tension' if is_state('switch.tt_chauffe_eau_pleumeur_switch', 'on') else 'coupé' }}
{{ states('input_select.victron_water_heater_recommended_mode') }} {% set w = states('input_number.victron_water_heater_observed_power_w') | float(0) %}{% if w > 50 %} — {{ w | round(0) }} W{% endif %}
secondary: >-
{% set p = states('input_text.evcs_balance_ecs_nuit_jour').split('|') %}
{% if p | length >= 3 and p[0] == now().strftime('%Y-%m-%d') %}{{ 'Jour faible : eau chaude en heures creuses' if p[1] == 'on' else 'Jour normal : eau chaude au solaire' }}
{% else %}Décision du jour après 07:24{% endif %}
• {{ states('sensor.evcs_chauffe_eau_jour_kwh') }} kWh depuis 07:24
multiline_secondary: true multiline_secondary: true
icon: mdi:water-boiler icon: mdi:water-boiler
icon_color: > icon_color: "{{ 'orange' if is_state('switch.tt_chauffe_eau_pleumeur_switch', 'on') else 'grey' }}"
{% if is_state('switch.tt_chauffe_eau_pleumeur_switch', 'on') %} tap_action:
orange action: none
{% else %}
grey
{% endif %}
# ---------- 8. CELLULES ----------
- type: custom:mushroom-template-card - type: custom:mushroom-template-card
entity: switch.clim_hygro_socket_1 card_mod: *carte
primary: Garage primary: >-
secondary: > Cellules : écart {{ states('sensor.evcs_cellules') }}{{ ' mV' if states('sensor.evcs_cellules') | is_number else '' }}
{{ states('input_text.garage_clim_state') }} secondary: >-
multiline_secondary: true {{ state_attr('sensor.evcs_cellules', 'modules_lus') }} modules sur 9
icon: mdi:air-conditioner • le plus sensible : n°{{ state_attr('sensor.evcs_cellules', 'repere_le_plus_sensible') }}
icon_color: > icon: mdi:battery-heart-variant
{% if is_state('switch.clim_hygro_socket_1', 'on') %} icon_color: "{{ 'green' if states('sensor.evcs_cellules') | is_number else 'orange' }}"
cyan
{% else %}
grey
{% endif %}
- type: custom:vertical-stack-in-card
mode: vertical
card_mod:
style: |
ha-card {
border-radius: 20px;
border: 1px solid rgba(255,255,255,0.10);
box-shadow: 0 6px 16px rgba(0,0,0,0.18);
}
cards:
- type: custom:mushroom-title-card
title: Actions rapides
subtitle: Contrôle direct
- type: grid
columns: 2
square: false
cards:
- type: custom:button-card
entity: switch.victron_evcs_charging
name: EVCS
icon: mdi:ev-station
show_state: true
state_display: >
[[[
if (!entity) return 'Inconnu';
if (entity.state === 'on') return 'ON';
if (entity.state === 'off') return 'OFF';
return entity.state;
]]]
tap_action: tap_action:
action: more-info action: none
styles:
card:
- border-radius: 18px
- padding: 10px
name:
- font-size: 14px
- font-weight: 600
state:
- font-size: 12px
state:
- value: "on"
color: "#43a047"
- value: "off"
color: "#757575"
- type: custom:button-card
entity: switch.tt_chauffe_eau_pleumeur_switch
name: ECS
icon: mdi:water-boiler
show_state: true
state_display: >
[[[
if (!entity) return 'Inconnu';
if (entity.state === 'on') return 'ON';
if (entity.state === 'off') return 'OFF';
return entity.state;
]]]
tap_action:
action: more-info
styles:
card:
- border-radius: 18px
- padding: 10px
name:
- font-size: 14px
- font-weight: 600
state:
- font-size: 12px
state:
- value: "on"
color: "#fb8c00"
- value: "off"
color: "#757575"
- type: custom:button-card
entity: switch.edf_general_ok_switch
name: Réseau
icon: mdi:transmission-tower
show_state: true
state_display: >
[[[
if (!entity) return 'Inconnu';
if (entity.state === 'on') return 'ON';
if (entity.state === 'off') return 'OFF';
return entity.state;
]]]
tap_action:
action: more-info
styles:
card:
- border-radius: 18px
- padding: 10px
name:
- font-size: 14px
- font-weight: 600
state:
- font-size: 12px
state:
- value: "on"
color: "#42a5f5"
- value: "off"
color: "#e53935"
- type: custom:button-card
entity: switch.clim_hygro_socket_1
name: Garage
icon: mdi:air-conditioner
show_state: true
state_display: >
[[[
if (!entity) return 'Inconnu';
if (entity.state === 'on') return 'ON';
if (entity.state === 'off') return 'OFF';
return entity.state;
]]]
tap_action:
action: more-info
styles:
card:
- border-radius: 18px
- padding: 10px
name:
- font-size: 14px
- font-weight: 600
state:
- font-size: 12px
state:
- value: "on"
color: "#26c6da"
- value: "off"
color: "#757575"
- type: custom:vertical-stack-in-card
mode: vertical
card_mod:
style: |
ha-card {
border-radius: 20px;
border: 1px solid rgba(255,255,255,0.10);
box-shadow: 0 6px 16px rgba(0,0,0,0.18);
}
cards:
- type: custom:mushroom-title-card
title: Verdict rapide
subtitle: Automatisation
- type: entities
show_header_toggle: false
entities:
- entity: input_boolean.victron_advice_evcs_ok
name: EVCS OK
- entity: input_boolean.victron_advice_water_heater_ok
name: ECS OK
- entity: input_boolean.victron_advice_garage_clim_ok
name: Garage OK
- entity: input_boolean.victron_advice_sdb_heater_ok
name: SDB OK
- entity: input_select.victron_water_heater_recommended_mode
name: Mode ECS
- entity: input_text.victron_grid_control_state
name: État réseau
- type: custom:vertical-stack-in-card
mode: vertical
card_mod:
style: |
ha-card {
border-radius: 20px;
border: 1px solid rgba(255,255,255,0.10);
box-shadow: 0 6px 16px rgba(0,0,0,0.18);
}
cards:
- type: custom:mushroom-title-card
title: Historique court
subtitle: 4 dernières heures
# ---------- 9. FLUX DES 4 DERNIERES HEURES ----------
- type: custom:apexcharts-card - type: custom:apexcharts-card
card_mod: *carte
graph_span: 4h graph_span: 4h
header: header:
show: true show: true
title: Flux énergie title: Flux d'énergie (4 h)
show_states: false show_states: false
series: series:
- entity: sensor.victron_pv_power_system - entity: sensor.victron_pv_power_system
name: PV name: Solaire
color: "#fdd835" color: "#fdd835"
- entity: sensor.victron_consumption_power_l1 - entity: sensor.victron_consumption_power_l1
name: Maison name: Maison
color: "#42a5f5" color: "#42a5f5"
- entity: sensor.victron_grid_power_l1 - entity: sensor.victron_grid_power_l1
name: Réseau name: EDF
color: "#ef5350" color: "#ef5350"
- entity: sensor.victron_battery_power - entity: sensor.victron_battery_power
name: Batterie name: Batterie
color: "#ab47bc" color: "#ab47bc"
# ---------- 10. AUTRES CHARGES ----------
- type: custom:mushroom-template-card
card_mod: *carte
primary: "Garage : {{ states('input_text.garage_clim_state') | replace('_', ' ') }}"
secondary: "Clim {{ 'en marche' if is_state('switch.clim_hygro_socket_1', 'on') else 'arrêtée' }}"
icon: mdi:air-conditioner
icon_color: "{{ 'cyan' if is_state('switch.clim_hygro_socket_1', 'on') else 'grey' }}"
tap_action:
action: none

View File

@@ -139,7 +139,11 @@ const sampleIsUsable =
Number.isFinite(energyDeltaKwh); Number.isFinite(energyDeltaKwh);
let observedPowerW = 0; let observedPowerW = 0;
if (sampleIsUsable) { // Coupe = 0 W (07/10/2026) : le compteur Tuya remonte avec retard, et la
// derniere chauffe apparaissait apres la coupure (« arret — 1595 W »).
if (!waterHeaterSwitchOn) {
observedPowerW = 0;
} else if (sampleIsUsable) {
observedPowerW = Math.max(0, (energyDeltaKwh * 60000) / sampleDurationMin); observedPowerW = Math.max(0, (energyDeltaKwh * 60000) / sampleDurationMin);
} else if (waterHeaterSwitchOn && observedPowerPrevW > 0) { } else if (waterHeaterSwitchOn && observedPowerPrevW > 0) {
observedPowerW = observedPowerPrevW; observedPowerW = observedPowerPrevW;

View File

@@ -73,6 +73,14 @@ for (const c of cas) {
if (!own) erreurs.push('helper de propriete absent des appels'); if (!own) erreurs.push('helper de propriete absent des appels');
if (erreurs.length) { ko++; console.log(`❌ ${c.id} | ${erreurs.join(' ; ')}`); } else { ok++; console.log(`✅ ${c.id}`); } if (erreurs.length) { ko++; console.log(`❌ ${c.id} | ${erreurs.join(' ; ')}`); } else { ok++; console.log(`✅ ${c.id}`); }
} }
// Coupe = 0 W meme si le compteur remonte en retard (07/10 : « arret — 1595 W »).
{
const stamp = new Date(Date.now() - 5 * 60000).toLocaleString('sv-SE', { timeZone: 'Europe/Paris' });
const s = executer({ ...BASE, water_heater_switch: 'off', water_heater_energy_total_kwh: '18.88', energy_total_prev_kwh: '18.75', energy_prev_at: stamp });
const o = s.OBSERVATION[0].json.observation;
if (o.observedPowerW === 0 && o.observedRegime === 'off') { ok++; console.log('✅ coupe-zero-watt'); }
else { ko++; console.log(`❌ coupe-zero-watt | ${o.observedPowerW} W ${o.observedRegime}`); }
}
// Prevision forte = le reste du jour seulement (06/10 : demain fort ne rend plus forte une journee faible). // Prevision forte = le reste du jour seulement (06/10 : demain fort ne rend plus forte une journee faible).
{ {
const s = executer({ ...BASE, ecs_nuit: 'off', today_remaining_kwh: '8', tomorrow_kwh: '30' }); const s = executer({ ...BASE, ecs_nuit: 'off', today_remaining_kwh: '8', tomorrow_kwh: '30' });

File diff suppressed because one or more lines are too long