diff --git a/HANDOFF.md b/HANDOFF.md index e5ba0a6..7936e42 100644 --- a/HANDOFF.md +++ b/HANDOFF.md @@ -1023,6 +1023,12 @@ fermer le contacteur a midi n'y gagnerait rien et etoufferait le solaire. justifie », jamais vers la batterie videe). `ZERO` ajoute au selecteur + heure de depart du matin (P9) ; ⚠️ creee a 00:00, recalee sur 08:50 (VW) sinon P9 ouvrait une fenetre vers minuit. Bilan 64/64, golden 123/123. Deploye 14:04. +- **VW et ZERO repartent aussi l'apres-midi, sans jours fixes** (proprietaire, 28/09) -> + **depart ponctuel** `input_datetime.victron_evcs_departure_ponctuel` (« il repart + aujourd'hui a 16:00 ») : retenu s'il est pour aujourd'hui, a venir et saisi depuis ce + branchement (1 h de tolerance) ; le plus proche du calendrier et du ponctuel gagne. + Teste en reel hors fenetre HC (16:00 pris avec le bon fuseau, ignore une fois passe). + ZERO : 15 kWh annonces, 200 km, ~3,5 kW en pointe (a mesurer sur une charge complete). - Agent vocal (SPARK, accord du proprietaire) : script d'ecriture limite au selecteur `victron_evcs_vehicle` puis au niveau (jamais `target_vehicle`, helper mort ; jamais `level_ref_kwh`). Saisie IDENTIQUE corrigee (14:08) : HA ne change ni l'etat ni diff --git a/dashboards/evcs_master.yaml b/dashboards/evcs_master.yaml index 7e208bd..246f244 100755 --- a/dashboards/evcs_master.yaml +++ b/dashboards/evcs_master.yaml @@ -223,6 +223,8 @@ views: name: Heure départ ZERO - entity: input_number.victron_evcs_vehicle_level_pct name: 🔋 Niveau du véhicule branché (à saisir au branchement) + - entity: input_datetime.victron_evcs_departure_ponctuel + name: 🕒 Repart aujourd'hui à (départ ponctuel, VW / ZERO) - entity: input_datetime.victron_evcs_jeep_midday_departure name: JEEP repart après midi à - entity: input_text.victron_evcs_jeep_midday_departure_days diff --git a/docs/MANUEL_COMPLET.md b/docs/MANUEL_COMPLET.md index c875945..e50d7fa 100644 --- a/docs/MANUEL_COMPLET.md +++ b/docs/MANUEL_COMPLET.md @@ -281,10 +281,19 @@ A faire a ce moment-la, et rien avant : **FAIT le 28/09/2026** (points 1 et 2) : `ZERO` est une option du selecteur, `input_datetime.victron_evcs_departure_time_zero` existe (cale provisoirement sur 08:50, l'heure de la VW, en attendant la sienne) et `INPUT_PARSE` la retient -quand la ZERO est selectionnee (golden `p9-depart-zero-*`). **Reste a donner** : -sa capacite mesuree (`input_number.victron_evcs_capacity_zero_kwh`, 0 = inconnue) -et sa puissance de charge (`..._charger_kw_zero`) ; tant qu'elles valent 0, la -regle de midi se tait pour la moto. +quand la ZERO est selectionnee (golden `p9-depart-zero-*`). Donnees du +proprietaire (28/09) : batterie **15 kWh**, autonomie **200 km**, charge +**~3,5 kW en pointe** (comparable aux voitures — donc PAS forcement discernable +electriquement, contrairement a ce qu'on esperait plus haut). Poses dans +`input_number.victron_evcs_capacity_zero_kwh` et `..._charger_kw_zero` ; 15 kWh +est la valeur annoncee, a remplacer par ce que mesure la borne sur une charge +complete. + +**Departs l'apres-midi (28/09)** : la **VW** et la **ZERO** peuvent aussi repartir +l'apres-midi, mais sans jours fixes. Elles passent donc par un **depart +ponctuel** saisi au branchement (`input_datetime.victron_evcs_departure_ponctuel`, +« il repart aujourd'hui a 16:00 ») ; la JEEP garde son calendrier (15:30 +mar/mer/ven/sam). Le plus proche des deux departs l'emporte. ⚠️ Une moto a une batterie bien plus petite qu'une voiture (une SR/F est de l'ordre de 14 a 17 kWh) et un chargeur embarque plus faible. **C'est donc diff --git a/packages/victron_evcs_vehicles.yaml b/packages/victron_evcs_vehicles.yaml index 8c5b457..07bbdff 100755 --- a/packages/victron_evcs_vehicles.yaml +++ b/packages/victron_evcs_vehicles.yaml @@ -56,6 +56,15 @@ input_datetime: name: EVCS - Heure de départ ZERO après midi has_date: false has_time: true + # Depart PONCTUEL (28/09/2026) : la VW et la ZERO repartent certains + # apres-midi sans jours fixes. Saisi au branchement (tableau de bord ou agent + # vocal) : « il repart aujourd'hui a 16:00 ». Retenu seulement s'il est pour + # AUJOURD'HUI, a venir, et saisi au plus 1 h avant le branchement ou apres — + # une saisie d'hier ou d'un autre vehicule ne peut pas servir. + victron_evcs_departure_ponctuel: + name: EVCS - Départ ponctuel du véhicule branché (aujourd'hui) + has_date: true + has_time: true # Instant de la derniere SAISIE du niveau, meme identique (ecrit par # l'automatisation) : HA ne date pas une valeur reecrite a l'identique. victron_evcs_vehicle_level_at: diff --git a/src/energy-balance/HA_SNAPSHOT_TEMPLATE.json.tpl b/src/energy-balance/HA_SNAPSHOT_TEMPLATE.json.tpl index b770ce6..d6e505d 100644 --- a/src/energy-balance/HA_SNAPSHOT_TEMPLATE.json.tpl +++ b/src/energy-balance/HA_SNAPSHOT_TEMPLATE.json.tpl @@ -41,6 +41,17 @@ {%- endif -%} {%- set branche = states.binary_sensor.victron_evcs_vehicle_connected -%} {%- set niveau = states.input_number.victron_evcs_vehicle_level_pct -%} +{#- Depart ponctuel (VW, ZERO : pas de jours fixes) : pour aujourd'hui, a venir, + saisi depuis ce branchement. Le plus proche des deux departs l'emporte. -#} +{%- set ponctuel = states.input_datetime.victron_evcs_departure_ponctuel -%} +{%- if branche is not none and ponctuel is not none and branche.state == 'on' + and ponctuel.state not in ['unknown', 'unavailable', ''] -%} + {%- set p = as_datetime(ponctuel.attributes.timestamp) | as_local -%} + {%- if p.date() == now().date() and p > now() + and as_timestamp(ponctuel.last_changed) >= as_timestamp(branche.last_changed) - 3600 -%} + {%- set vh.dep = p if vh.dep == '' or p < vh.dep else vh.dep -%} + {%- endif -%} +{%- endif -%} {%- if branche is not none and niveau is not none and branche.state == 'on' -%} {#- Date de SAISIE ecrite par l'automatisation, pas last_changed : une saisie identique ne change pas l'etat du helper mais compte comme une saisie. -#} diff --git a/workflows/evcs-energy-balance-v1.json b/workflows/evcs-energy-balance-v1.json index 39ffa2c..b0d3f72 100644 --- a/workflows/evcs-energy-balance-v1.json +++ b/workflows/evcs-energy-balance-v1.json @@ -51,7 +51,7 @@ "parameters": [ { "name": "template", - "value": "{#- Fenetres d'heures creuses (28/09/2026). Le calendrier tarifaire reste dans\n Home Assistant (helpers victron_evcs_hc_*) ; le bilan ne recoit que deux\n instants : la fin de la fenetre HC en cours (vide hors fenetre) et le debut\n de la fenetre HC suivante. Strategie du proprietaire : la batterie doit\n tenir jusqu'a la prochaine fenetre HC. -#}\n{%- set ns = namespace(fin='', suivant='', nuit='', fen=[]) -%}\n{%- for j in [0, 1, 2] -%}\n {%- for a, b, t in [('victron_evcs_hc_night_start', 'victron_evcs_hc_night_stop', 'nuit'), ('victron_evcs_hc_midday_start', 'victron_evcs_hc_midday_stop', 'midi')] -%}\n {%- set d = today_at(states('input_datetime.' ~ a)) + timedelta(days=j) -%}\n {%- set f = today_at(states('input_datetime.' ~ b)) + timedelta(days=j) -%}\n {%- set f = f + timedelta(days=1) if f <= d else f -%}\n {%- set ns.fen = ns.fen + [[d, f, t]] -%}\n {%- endfor -%}\n{%- endfor -%}\n{%- for w in ns.fen | sort(attribute='0') -%}\n {%- if w[0] <= now() < w[1] and ns.fin == '' -%}{%- set ns.fin = w[1] -%}{%- endif -%}\n{%- endfor -%}\n{%- set repere = ns.fin if ns.fin != '' else now() -%}\n{%- for w in ns.fen | sort(attribute='0') -%}\n {%- if w[0] >= repere and ns.suivant == '' -%}{%- set ns.suivant = w[0] -%}{%- endif -%}\n {%- if w[0] >= repere and w[2] == 'nuit' and ns.nuit == '' -%}{%- set ns.nuit = w[0] -%}{%- endif -%}\n{%- endfor -%}\n{#- Vehicule branche a midi (28/09/2026) — JEEP, VW ou ZERO, selon le\n selecteur. Pour chacun, HA porte le calendrier (jours et heure de depart\n apres le dejeuner), la capacite et la puissance de charge MESUREES ; le\n bilan recoit un instant de depart, vide si le vehicule ne repart pas\n aujourd'hui. Le niveau saisi n'est retenu que s'il date de ce branchement\n (tolerance 1 h avant). Capacite ou puissance a 0 = inconnue. -#}\n{%- set vh = namespace(dep='', valide=false, cap=none, kw=none) -%}\n{%- set jours = ['lun', 'mar', 'mer', 'jeu', 'ven', 'sam', 'dim'] -%}\n{%- set cle = {'JEEP': 'jeep', 'VW': 'vw', 'ZERO': 'zero'}.get(states('input_select.victron_evcs_vehicle')) -%}\n{%- if cle -%}\n {%- set vh.cap = states('input_number.victron_evcs_capacity_' ~ cle ~ '_kwh') -%}\n {%- set vh.kw = states('input_number.victron_evcs_charger_kw_' ~ cle) -%}\n {%- set heure = states('input_datetime.victron_evcs_' ~ cle ~ '_midday_departure') -%}\n {%- if jours[now().weekday()] in states('input_text.victron_evcs_' ~ cle ~ '_midday_departure_days') | lower\n and heure not in ['unknown', 'unavailable', ''] -%}\n {%- set d = today_at(heure) -%}\n {%- if d > now() -%}{%- set vh.dep = d -%}{%- endif -%}\n {%- endif -%}\n{%- endif -%}\n{%- set branche = states.binary_sensor.victron_evcs_vehicle_connected -%}\n{%- set niveau = states.input_number.victron_evcs_vehicle_level_pct -%}\n{%- if branche is not none and niveau is not none and branche.state == 'on' -%}\n {#- Date de SAISIE ecrite par l'automatisation, pas last_changed : une saisie\n identique ne change pas l'etat du helper mais compte comme une saisie. -#}\n {%- set vh.valide = (as_timestamp(states('input_datetime.victron_evcs_vehicle_level_at'), 0)) >= as_timestamp(branche.last_changed) - 3600 -%}\n{%- endif -%}\n{{ {\n \"ts\": now().isoformat(),\n \"vehicle_connected\": is_state(\"binary_sensor.victron_evcs_vehicle_connected\", \"on\"),\n \"vehicle_departure_ms\": (as_timestamp(vh.dep) * 1000) if vh.dep != '' else none,\n \"vehicle_level_pct\": states(\"input_number.victron_evcs_vehicle_level_pct\"),\n \"vehicle_level_valid\": vh.valide,\n \"vehicle_capacity_kwh\": vh.cap,\n \"vehicle_charger_kw\": vh.kw,\n \"vehicle_delivered_since_level_kwh\": ((states(\"sensor.evcs_hq2239dnt7p_total_energy\") | float(0)) - (states(\"input_number.victron_evcs_vehicle_level_ref_kwh\") | float(0))) if states(\"sensor.evcs_hq2239dnt7p_total_energy\") | is_number else none,\n \"hc_window_end_ms\": (as_timestamp(ns.fin) * 1000) if ns.fin != '' else none,\n \"next_hc_start_ms\": (as_timestamp(ns.suivant) * 1000) if ns.suivant != '' else none,\n \"next_night_hc_start_ms\": (as_timestamp(ns.nuit) * 1000) if ns.nuit != '' else none,\n \"nowMs\": as_timestamp(now()) * 1000,\n\n \"balance_enabled\": states(\"input_boolean.evcs_balance_enabled\"),\n \"usable_capacity_kwh\": states(\"input_number.evcs_balance_usable_capacity_kwh\"),\n \"modules_en_service\": states(\"input_number.evcs_balance_modules_en_service\"),\n\n \"consumption_p50_csv\": states(\"input_text.evcs_balance_consumption_p50\"),\n \"consumption_p80_csv\": states(\"input_text.evcs_balance_consumption_p80\"),\n \"envelope_csv\": states(\"input_text.evcs_balance_envelope\"),\n \"censorship_rate_csv\": states(\"input_text.evcs_balance_censorship_rate\"),\n\n \"forecast_source\": states(\"input_select.evcs_balance_forecast_source\"),\n \"forecast_day0\": states(\"input_text.evcs_balance_vrm_day0\") if is_state(\"input_select.evcs_balance_forecast_source\", \"vrm\") else states(\"input_text.evcs_balance_forecast_day0\"),\n \"forecast_today_csv\": states(\"input_text.evcs_balance_vrm_today\") if is_state(\"input_select.evcs_balance_forecast_source\", \"vrm\") else states(\"input_text.evcs_balance_forecast_today\"),\n \"forecast_tomorrow_csv\": states(\"input_text.evcs_balance_vrm_tomorrow\") if is_state(\"input_select.evcs_balance_forecast_source\", \"vrm\") else states(\"input_text.evcs_balance_forecast_tomorrow\"),\n \"forecast_updated\": states(\"input_text.evcs_balance_vrm_updated\") if is_state(\"input_select.evcs_balance_forecast_source\", \"vrm\") else states(\"input_text.evcs_balance_forecast_updated\"),\n \"grid_soc_off\": states(\"input_number.victron_grid_soc_off\"),\n\n \"manual_hc_floor_percent\": states(\"input_number.evcs_battery_manual_hc_floor\"),\n\n \"pv_power_w\": states(\"sensor.victron_pv_power_system\"),\n\n \"house_ac_power_w\": states(\"sensor.victron_consumption_power_l1\"),\n \"vebus_ac_out_l1_power_w\": states(\"sensor.victron_ve_bus_ac_out_l1_power\"),\n \"evcs_ac_power_w\": states(\"sensor.victron_evcs_ac_power\"),\n\n \"soc_percent\": states(\"sensor.victron_battery_soc\"),\n \"battery_current_a\": states(\"sensor.victron_battery_current\"),\n \"battery_voltage_v\": states(\"sensor.victron_battery_voltage\"),\n \"vebus_dc_power_w\": states(\"sensor.victron_ve_bus_dc_power_system\"),\n\n \"grid_switch\": states(\"switch.edf_general_ok_switch\"),\n \"acin1_available\": states(\"sensor.victron_ac_in1_available\"),\n \"grid_power_l1_w\": states(\"sensor.victron_grid_power_l1\"),\n\n \"multiplus_state\": states(\"sensor.airtria_mpii_v1_state\"),\n \"multiplus_overload_alarm\": states(\"sensor.airtria_mpii_v1_overload_alarm\"),\n \"system_state\": states(\"sensor.gx_device_system_state\"),\n \"ess_batterylife_state\": states(\"sensor.gx_device_ess_batterylife_state\"),\n \"dc_battery_state\": states(\"sensor.gx_device_dc_battery_state\"),\n\n \"mppt_1_state\": states(\"sensor.airtria_mppt1_state\"),\n \"mppt_2_state\": states(\"sensor.mppt_450_200_hq2449yr9pt_state\"),\n \"mppt_3_state\": states(\"sensor.v1_state\"),\n\n \"evcs_native_status\": states(\"sensor.evcs_hq2239dnt7p_status\"),\n\n \"forecast_today_remaining_kwh\": states(\"sensor.energy_production_today_remaining\"),\n \"forecast_today_kwh\": states(\"sensor.energy_production_today\"),\n \"forecast_tomorrow_kwh\": states(\"sensor.energy_production_tomorrow\"),\n \"forecast_next_hour_w\": states(\"sensor.power_production_next_hour\"),\n\n \"sun_elevation\": state_attr(\"sun.sun\", \"elevation\"),\n\n \"storm_alert_level\": (states.sensor\n | selectattr('entity_id', 'search', '_weather_alert')\n | map(attribute='state') | list | first) | default('indisponible', true),\n \"storm_alert_detail\": (states.sensor\n | selectattr('entity_id', 'search', '_weather_alert')\n | map(attribute='attributes') | list | first) | default({}, true)\n} | tojson }}\n" + "value": "{#- Fenetres d'heures creuses (28/09/2026). Le calendrier tarifaire reste dans\n Home Assistant (helpers victron_evcs_hc_*) ; le bilan ne recoit que deux\n instants : la fin de la fenetre HC en cours (vide hors fenetre) et le debut\n de la fenetre HC suivante. Strategie du proprietaire : la batterie doit\n tenir jusqu'a la prochaine fenetre HC. -#}\n{%- set ns = namespace(fin='', suivant='', nuit='', fen=[]) -%}\n{%- for j in [0, 1, 2] -%}\n {%- for a, b, t in [('victron_evcs_hc_night_start', 'victron_evcs_hc_night_stop', 'nuit'), ('victron_evcs_hc_midday_start', 'victron_evcs_hc_midday_stop', 'midi')] -%}\n {%- set d = today_at(states('input_datetime.' ~ a)) + timedelta(days=j) -%}\n {%- set f = today_at(states('input_datetime.' ~ b)) + timedelta(days=j) -%}\n {%- set f = f + timedelta(days=1) if f <= d else f -%}\n {%- set ns.fen = ns.fen + [[d, f, t]] -%}\n {%- endfor -%}\n{%- endfor -%}\n{%- for w in ns.fen | sort(attribute='0') -%}\n {%- if w[0] <= now() < w[1] and ns.fin == '' -%}{%- set ns.fin = w[1] -%}{%- endif -%}\n{%- endfor -%}\n{%- set repere = ns.fin if ns.fin != '' else now() -%}\n{%- for w in ns.fen | sort(attribute='0') -%}\n {%- if w[0] >= repere and ns.suivant == '' -%}{%- set ns.suivant = w[0] -%}{%- endif -%}\n {%- if w[0] >= repere and w[2] == 'nuit' and ns.nuit == '' -%}{%- set ns.nuit = w[0] -%}{%- endif -%}\n{%- endfor -%}\n{#- Vehicule branche a midi (28/09/2026) — JEEP, VW ou ZERO, selon le\n selecteur. Pour chacun, HA porte le calendrier (jours et heure de depart\n apres le dejeuner), la capacite et la puissance de charge MESUREES ; le\n bilan recoit un instant de depart, vide si le vehicule ne repart pas\n aujourd'hui. Le niveau saisi n'est retenu que s'il date de ce branchement\n (tolerance 1 h avant). Capacite ou puissance a 0 = inconnue. -#}\n{%- set vh = namespace(dep='', valide=false, cap=none, kw=none) -%}\n{%- set jours = ['lun', 'mar', 'mer', 'jeu', 'ven', 'sam', 'dim'] -%}\n{%- set cle = {'JEEP': 'jeep', 'VW': 'vw', 'ZERO': 'zero'}.get(states('input_select.victron_evcs_vehicle')) -%}\n{%- if cle -%}\n {%- set vh.cap = states('input_number.victron_evcs_capacity_' ~ cle ~ '_kwh') -%}\n {%- set vh.kw = states('input_number.victron_evcs_charger_kw_' ~ cle) -%}\n {%- set heure = states('input_datetime.victron_evcs_' ~ cle ~ '_midday_departure') -%}\n {%- if jours[now().weekday()] in states('input_text.victron_evcs_' ~ cle ~ '_midday_departure_days') | lower\n and heure not in ['unknown', 'unavailable', ''] -%}\n {%- set d = today_at(heure) -%}\n {%- if d > now() -%}{%- set vh.dep = d -%}{%- endif -%}\n {%- endif -%}\n{%- endif -%}\n{%- set branche = states.binary_sensor.victron_evcs_vehicle_connected -%}\n{%- set niveau = states.input_number.victron_evcs_vehicle_level_pct -%}\n{#- Depart ponctuel (VW, ZERO : pas de jours fixes) : pour aujourd'hui, a venir,\n saisi depuis ce branchement. Le plus proche des deux departs l'emporte. -#}\n{%- set ponctuel = states.input_datetime.victron_evcs_departure_ponctuel -%}\n{%- if branche is not none and ponctuel is not none and branche.state == 'on'\n and ponctuel.state not in ['unknown', 'unavailable', ''] -%}\n {%- set p = as_datetime(ponctuel.attributes.timestamp) | as_local -%}\n {%- if p.date() == now().date() and p > now()\n and as_timestamp(ponctuel.last_changed) >= as_timestamp(branche.last_changed) - 3600 -%}\n {%- set vh.dep = p if vh.dep == '' or p < vh.dep else vh.dep -%}\n {%- endif -%}\n{%- endif -%}\n{%- if branche is not none and niveau is not none and branche.state == 'on' -%}\n {#- Date de SAISIE ecrite par l'automatisation, pas last_changed : une saisie\n identique ne change pas l'etat du helper mais compte comme une saisie. -#}\n {%- set vh.valide = (as_timestamp(states('input_datetime.victron_evcs_vehicle_level_at'), 0)) >= as_timestamp(branche.last_changed) - 3600 -%}\n{%- endif -%}\n{{ {\n \"ts\": now().isoformat(),\n \"vehicle_connected\": is_state(\"binary_sensor.victron_evcs_vehicle_connected\", \"on\"),\n \"vehicle_departure_ms\": (as_timestamp(vh.dep) * 1000) if vh.dep != '' else none,\n \"vehicle_level_pct\": states(\"input_number.victron_evcs_vehicle_level_pct\"),\n \"vehicle_level_valid\": vh.valide,\n \"vehicle_capacity_kwh\": vh.cap,\n \"vehicle_charger_kw\": vh.kw,\n \"vehicle_delivered_since_level_kwh\": ((states(\"sensor.evcs_hq2239dnt7p_total_energy\") | float(0)) - (states(\"input_number.victron_evcs_vehicle_level_ref_kwh\") | float(0))) if states(\"sensor.evcs_hq2239dnt7p_total_energy\") | is_number else none,\n \"hc_window_end_ms\": (as_timestamp(ns.fin) * 1000) if ns.fin != '' else none,\n \"next_hc_start_ms\": (as_timestamp(ns.suivant) * 1000) if ns.suivant != '' else none,\n \"next_night_hc_start_ms\": (as_timestamp(ns.nuit) * 1000) if ns.nuit != '' else none,\n \"nowMs\": as_timestamp(now()) * 1000,\n\n \"balance_enabled\": states(\"input_boolean.evcs_balance_enabled\"),\n \"usable_capacity_kwh\": states(\"input_number.evcs_balance_usable_capacity_kwh\"),\n \"modules_en_service\": states(\"input_number.evcs_balance_modules_en_service\"),\n\n \"consumption_p50_csv\": states(\"input_text.evcs_balance_consumption_p50\"),\n \"consumption_p80_csv\": states(\"input_text.evcs_balance_consumption_p80\"),\n \"envelope_csv\": states(\"input_text.evcs_balance_envelope\"),\n \"censorship_rate_csv\": states(\"input_text.evcs_balance_censorship_rate\"),\n\n \"forecast_source\": states(\"input_select.evcs_balance_forecast_source\"),\n \"forecast_day0\": states(\"input_text.evcs_balance_vrm_day0\") if is_state(\"input_select.evcs_balance_forecast_source\", \"vrm\") else states(\"input_text.evcs_balance_forecast_day0\"),\n \"forecast_today_csv\": states(\"input_text.evcs_balance_vrm_today\") if is_state(\"input_select.evcs_balance_forecast_source\", \"vrm\") else states(\"input_text.evcs_balance_forecast_today\"),\n \"forecast_tomorrow_csv\": states(\"input_text.evcs_balance_vrm_tomorrow\") if is_state(\"input_select.evcs_balance_forecast_source\", \"vrm\") else states(\"input_text.evcs_balance_forecast_tomorrow\"),\n \"forecast_updated\": states(\"input_text.evcs_balance_vrm_updated\") if is_state(\"input_select.evcs_balance_forecast_source\", \"vrm\") else states(\"input_text.evcs_balance_forecast_updated\"),\n \"grid_soc_off\": states(\"input_number.victron_grid_soc_off\"),\n\n \"manual_hc_floor_percent\": states(\"input_number.evcs_battery_manual_hc_floor\"),\n\n \"pv_power_w\": states(\"sensor.victron_pv_power_system\"),\n\n \"house_ac_power_w\": states(\"sensor.victron_consumption_power_l1\"),\n \"vebus_ac_out_l1_power_w\": states(\"sensor.victron_ve_bus_ac_out_l1_power\"),\n \"evcs_ac_power_w\": states(\"sensor.victron_evcs_ac_power\"),\n\n \"soc_percent\": states(\"sensor.victron_battery_soc\"),\n \"battery_current_a\": states(\"sensor.victron_battery_current\"),\n \"battery_voltage_v\": states(\"sensor.victron_battery_voltage\"),\n \"vebus_dc_power_w\": states(\"sensor.victron_ve_bus_dc_power_system\"),\n\n \"grid_switch\": states(\"switch.edf_general_ok_switch\"),\n \"acin1_available\": states(\"sensor.victron_ac_in1_available\"),\n \"grid_power_l1_w\": states(\"sensor.victron_grid_power_l1\"),\n\n \"multiplus_state\": states(\"sensor.airtria_mpii_v1_state\"),\n \"multiplus_overload_alarm\": states(\"sensor.airtria_mpii_v1_overload_alarm\"),\n \"system_state\": states(\"sensor.gx_device_system_state\"),\n \"ess_batterylife_state\": states(\"sensor.gx_device_ess_batterylife_state\"),\n \"dc_battery_state\": states(\"sensor.gx_device_dc_battery_state\"),\n\n \"mppt_1_state\": states(\"sensor.airtria_mppt1_state\"),\n \"mppt_2_state\": states(\"sensor.mppt_450_200_hq2449yr9pt_state\"),\n \"mppt_3_state\": states(\"sensor.v1_state\"),\n\n \"evcs_native_status\": states(\"sensor.evcs_hq2239dnt7p_status\"),\n\n \"forecast_today_remaining_kwh\": states(\"sensor.energy_production_today_remaining\"),\n \"forecast_today_kwh\": states(\"sensor.energy_production_today\"),\n \"forecast_tomorrow_kwh\": states(\"sensor.energy_production_tomorrow\"),\n \"forecast_next_hour_w\": states(\"sensor.power_production_next_hour\"),\n\n \"sun_elevation\": state_attr(\"sun.sun\", \"elevation\"),\n\n \"storm_alert_level\": (states.sensor\n | selectattr('entity_id', 'search', '_weather_alert')\n | map(attribute='state') | list | first) | default('indisponible', true),\n \"storm_alert_detail\": (states.sensor\n | selectattr('entity_id', 'search', '_weather_alert')\n | map(attribute='attributes') | list | first) | default({}, true)\n} | tojson }}\n" } ] },