|
########## |
|
# 3ERL Zero-Inject Instructions and Daily PRE+ Estimate |
|
# Ref: https://gist.github.com/mathieucarbou/8d83d25247821e85a693dea61fe4f0d2 |
|
# |
|
# SPDX-License-Identifier: MIT |
|
# Copyright (C) Mathieu Carbou |
|
########## |
|
|
|
# https://www.home-assistant.io/integrations/input_number |
|
input_number: |
|
# 🖐️ PRD3 (Sunlight) Profile to use to estimate the daily PRE+ value in ACI (not ACC) |
|
# -1 means yesterday (yesterday curve is only ade available in the morning, so some data will be missed but not a lot) |
|
# -2 means 2 days ago |
|
# -7 means same day last week |
|
# Default: -2 |
|
electricite_profil_dynamique_prd3_day: |
|
name: "Électricité: Profil Dynamique PRD3 Jour" |
|
unit_of_measurement: d |
|
min: -7 |
|
max: -1 |
|
step: 1 |
|
mode: slider |
|
|
|
# https://www.home-assistant.io/integrations/input_select/ |
|
input_select: |
|
inverters_zero_inject_mode: |
|
name: Inverters Zero-Inject mode |
|
options: |
|
- "Auto" |
|
- "On" |
|
- "Off" |
|
|
|
# https://www.home-assistant.io/integrations/rest |
|
rest: |
|
# Get the 3ERL trend (https://3erl.fr) and limit status and expose them in sensors |
|
- resource: https://3erl.fr/api.json |
|
scan_interval: 30 |
|
binary_sensor: |
|
- name: "3ERL: Bridage Demandé" |
|
icon: "mdi:car-speed-limiter" |
|
unique_id: 347A6F4D-6B09-4A20-9C2C-D611ED23EF4B |
|
value_template: "{{ value_json['Bridage'] }}" |
|
- name: "3ERL: Bridage CDC Demandé" |
|
icon: "mdi:car-speed-limiter" |
|
unique_id: B6DC9FBF-DDD0-423F-B9A2-A46CF52EC8CA |
|
value_template: "{{ value_json['Bridage_CDC'] }}" |
|
sensor: |
|
- name: "3ERL: Tendance du jour" |
|
icon: "mdi:trending-up" |
|
unique_id: 31F1BED4-8100-44A4-88BA-DB45450611CF |
|
value_template: | |
|
{% set data = value_json['PREP_Profile'] %} |
|
{% if data == '3+' %} 🟢🟢🟢 |
|
{% elif data == '2+' %} 🟢🟢 |
|
{% elif data == '1+' %} 🟢 |
|
{% elif data == '0' %} ⚠️ |
|
{% elif data == '1-' %} ⛔️ |
|
{% elif data == '2-' %} ⛔️⛔️ |
|
{% elif data == '3-' %} ⛔️⛔️⛔️ |
|
{% else %} ⁉️ |
|
{% endif %} |
|
# # For 3ERL: Heure_Update is the last time of the time slot |
|
# - name: "Électricité: PREP Timeslot" |
|
# icon: "mdi:clock" |
|
# unique_id: 1D93CA5A-BED5-499D-A164-15609D78657F |
|
# device_class: timestamp |
|
# value_template: >- |
|
# {# value is something like: 03/03/2026 10:45 #} |
|
# {% set value = value_json['Heure_Update'] %} |
|
# {% set y = value[6:10] %} |
|
# {% set m = value[3:5] %} |
|
# {% set d = value[0:2] %} |
|
# {% set hm = value[11:16] %} |
|
# {{ ((y + '-' + m + '-' + d + 'T' + hm) | as_datetime | as_local - timedelta(minutes=15)).isoformat() }} |
|
# json_attributes: |
|
# - Dernier_PREP |
|
# Prix equilibre RTE: https://www.services-rte.com/fr/visualisez-les-donnees-publiees-par-rte/equilibrage.html |
|
- resource_template: https://www.services-rte.com/cms/open_data/v1/price/table?startDate={{ now().strftime('%d%%2F%m%%2F%Y') }} |
|
scan_interval: 60 |
|
sensor: |
|
- name: "Électricité: PREP Timeslot" |
|
icon: "mdi:clock" |
|
unique_id: 1D93CA5A-BED5-499D-A164-15609D78657F |
|
device_class: timestamp |
|
availability: "{{ value_json['values'] and value_json['values']|length > 0 }}" |
|
value_template: "{{ value_json['values'][0]['date'] }}" |
|
json_attributes_path: "$.values[0]" |
|
json_attributes: |
|
- pre |
|
|
|
# https://www.home-assistant.io/integrations/command_line |
|
command_line: |
|
# Get the Enedis PRD3 profiling curve applied to the PRE+ prices to get an approximation. |
|
# This PRD3 curve depends only on sunlight, so we better take the closest day available. |
|
# This sensors keeps the sum of all factors from mignight, plus as attributes the last values (last quarter of hour and last factor) |
|
# See: https://data.enedis.fr/pages/coefficients-de-profils-dynamiques-jplus1-contenu/ |
|
# See: https://opendata.enedis.fr/datasets/coefficients-de-profils-dynamiques-anticipes-en-j1en-j1 |
|
- sensor: |
|
name: "Électricité: Profil Dynamique PRD3" |
|
unique_id: 18F026A2-7F17-4B09-9074-EE5F9D888A12 |
|
state_class: measurement |
|
# scan_interval is high on purpose: the sensors are updated on-demande through an automations that |
|
# is only calling the API every 20 sec past the quarter of hour until the update is received |
|
scan_interval: 86400 |
|
command: >- |
|
curl |
|
-s |
|
-X POST |
|
-d "action=exports" |
|
-d "output=exportDirect" |
|
-d "format=json" |
|
-d "dataset=koumoul://7okolrt07nor9cv103spkfzc" |
|
-d "apikey=false" |
|
-d "datefield=horodate" |
|
-d "select=horodate, coefficient_dynamique_j_1" |
|
-d "where=(sous_profil='PRD3_BASE') AND horodate >= '{{ (states('sensor.electricite_prep_timeslot')|as_datetime|as_local + timedelta(days = states('input_number.electricite_profil_dynamique_prd3_day')|int(-2))).strftime('%Y-%m-%d') }}T00:00:00' AND horodate <= '{{ (states('sensor.electricite_prep_timeslot')|as_datetime|as_local + timedelta(days = states('input_number.electricite_profil_dynamique_prd3_day')|int(-2))).strftime('%Y-%m-%dT%H:%M') }}:00'" |
|
-d "group=" |
|
-d "order=horodate desc" |
|
"https://openservices.enedis.fr/php/opendata.php" |
|
availability: "{{ value_json|length > 0 and value_json | sum(attribute='coefficient_dynamique_j_1') > 0 }}" |
|
value_template: "{{ value_json | sum(attribute='coefficient_dynamique_j_1') }}" |
|
json_attributes_path: "$[0]" |
|
json_attributes: |
|
- horodate |
|
- coefficient_dynamique_j_1 |
|
|
|
template: |
|
# https://www.home-assistant.io/integrations/template/#binary-sensor |
|
- binary_sensor: |
|
# Determines whether we should limit the inverters |
|
- name: Inverters Zero-Inject |
|
unique_id: "12E68C95-83ED-41EF-86E6-A0295FC2458C" |
|
state: >- |
|
{% set mode = states('input_select.inverters_zero_inject_mode') %} |
|
{% set aci = states('binary_sensor.3erl_bridage_demande') %} |
|
{% set acc = states('binary_sensor.3erl_bridage_cdc_demande') %} |
|
{{ "on" if mode == "On" or (mode == "Auto" and aci == "on") else "off" }} |
|
|
|
# https://www.home-assistant.io/integrations/template/#sensor |
|
- sensor: |
|
# The last PRE_ value extracted from REST response |
|
- name: "Électricité: Prix de règlement des écarts positifs" |
|
icon: "mdi:currency-eur" |
|
unique_id: EA2D2A8C-5327-47C8-92EF-C16E9BE7A4C5 |
|
state_class: measurement |
|
unit_of_measurement: "€/MWh" |
|
availability: "{{ states('sensor.electricite_prep_timeslot') not in ['unavailable', 'unknown'] }}" |
|
state: "{{ state_attr('sensor.electricite_prep_timeslot', 'pre')['positive']|float }}" |
|
attributes: |
|
date: "{{ (states('sensor.electricite_prep_timeslot')|as_datetime|as_local).isoformat() }}" |
|
timeslot: "{{ (states('sensor.electricite_prep_timeslot')|as_datetime|as_local).strftime('%H:%M') }}" |
|
|
|
# The PRD3 factor for the current quarter of hour. Used for graph. |
|
- name: "Électricité: Profil Dynamique PRD3 Factor" |
|
unique_id: "D6A61828-CBA3-41CA-A7AF-9E1AF79F6029" |
|
state_class: measurement |
|
availability: "{{ has_value('sensor.electricite_profil_dynamique_prd3') }}" |
|
state: "{{ state_attr('sensor.electricite_profil_dynamique_prd3', 'coefficient_dynamique_j_1')|float }}" |
|
attributes: |
|
date: "{{ (state_attr('sensor.electricite_profil_dynamique_prd3', 'horodate')|as_datetime|as_local).isoformat() }}" |
|
timeslot: "{{ (state_attr('sensor.electricite_profil_dynamique_prd3', 'horodate')|as_datetime|as_local).strftime('%H:%M') }}" |
|
|
|
# The PRD3 timeslot for the current quarter of hour. |
|
- name: "Électricité: Profil Dynamique PRD3 Timeslot" |
|
unique_id: "AF7BFE5B-5AA0-42F7-8323-D2166F8EA4E3" |
|
device_class: timestamp |
|
availability: "{{ has_value('sensor.electricite_profil_dynamique_prd3') }}" |
|
state: "{{ state_attr('sensor.electricite_profil_dynamique_prd3', 'horodate') }}" |
|
|
|
# Current PRE+ value for the quarter of hour multiplied by the current PRD3 factor for this quarter of hour |
|
- name: "Électricité: PREP by PRD3 Factor" |
|
unique_id: "B0B14D4E-EDEF-4D18-8FE9-F5B087FA364C" |
|
state_class: measurement |
|
unit_of_measurement: "€/MWh" |
|
availability: "{{ has_value('sensor.electricite_prix_de_reglement_des_ecarts_positifs') and has_value('sensor.electricite_profil_dynamique_prd3_factor') }}" |
|
state: >- |
|
{% set last_sensor_value = states('sensor.electricite_prep_by_prd3_factor')|float(0) %} |
|
{% set prep_timeslot = state_attr('sensor.electricite_prix_de_reglement_des_ecarts_positifs', 'timeslot') %} |
|
{% set prep_value = states('sensor.electricite_prix_de_reglement_des_ecarts_positifs')|float %} |
|
{% set prd3_timeslot = state_attr('sensor.electricite_profil_dynamique_prd3_factor', 'timeslot') %} |
|
{% set prd3_value = states('sensor.electricite_profil_dynamique_prd3_factor')|float %} |
|
{{ last_sensor_value if prep_timeslot != prd3_timeslot else prep_value * prd3_value }} |
|
attributes: |
|
date: "{{ state_attr('sensor.electricite_prix_de_reglement_des_ecarts_positifs', 'date') }}" |
|
timeslot: "{{ state_attr('sensor.electricite_prix_de_reglement_des_ecarts_positifs', 'timeslot') }}" |
|
|
|
# This is the currently estimated PRE+ ratio for the day based on the selectd PRD3 curve |
|
- name: "Électricité: PREP Daily Estimation" |
|
unique_id: "AA659353-C08D-4C92-943A-2F44933E768D" |
|
state_class: measurement |
|
unit_of_measurement: "€/MWh" |
|
availability: "{{ has_value('sensor.electricite_prep_by_prd3_factor') and has_value('sensor.electricite_prep_by_prd3_daily_running_sum') and has_value('sensor.electricite_profil_dynamique_prd3') and states('sensor.electricite_profil_dynamique_prd3')|float(0) > 0 }}" |
|
state: >- |
|
{# running sum (meter) #} |
|
{% set running_sum = states('sensor.electricite_prep_by_prd3_daily_running_sum')|float(0) %} |
|
{% set running_sum_last_changed = states.sensor.electricite_prep_by_prd3_daily_running_sum.last_changed %} |
|
{# PRD3 sum #} |
|
{% set prd3_sum = states('sensor.electricite_profil_dynamique_prd3')|float %} |
|
{% set prd3_timeslot = (state_attr('sensor.electricite_profil_dynamique_prd3', 'horodate')|as_datetime|as_local).strftime('%H:%M') %} |
|
{% set prd3_sum_last_changed = states.sensor.electricite_profil_dynamique_prd3.last_changed %} |
|
{# PRD3 factor #} |
|
{% set prd3_factor_timeslot = state_attr('sensor.electricite_prep_by_prd3_factor', 'timeslot') %} |
|
{% set prd3_factor_last_changed = states.sensor.electricite_prep_by_prd3_factor.last_changed %} |
|
{% if prd3_timeslot == prd3_factor_timeslot and running_sum_last_changed > prd3_sum_last_changed and running_sum_last_changed > prd3_factor_last_changed %} |
|
{{ running_sum / prd3_sum }} |
|
{% elif has_value('sensor.electricite_prep_daily_estimation') %} |
|
{{ states('sensor.electricite_prep_daily_estimation')|float }} |
|
{% else %} |
|
{{ states('sensor.electricite_prep_daily_estimation') }} |
|
{% endif %} |
|
attributes: |
|
date: "{{ state_attr('sensor.electricite_prep_by_prd3_factor', 'date') }}" |
|
timeslot: "{{ state_attr('sensor.electricite_prep_by_prd3_factor', 'timeslot') }}" |
|
|
|
# https://www.home-assistant.io/integrations/utility_meter/ |
|
utility_meter: |
|
# This is the running sum during the day of all PRE+ * PRD3 for each quarter of hour |
|
electricite_prep_by_prd3_daily_running_sum: |
|
name: "Électricité: PREP by PRD3 Daily Running Sum" |
|
unique_id: 0EEB33DF-C2C1-4912-BE78-23F3B65D967B |
|
source: sensor.electricite_prep_by_prd3_factor |
|
cycle: daily |
|
net_consumption: true |
|
delta_values: true |
|
|
|
# https://www.home-assistant.io/docs/automation/ |
|
automation: |
|
# Notification in case zero-inject order is changed |
|
# This is optional and require you to know how to setup HA notifications. |
|
- id: "0000000000040" |
|
alias: "Solar: Notify Zero-Inject State Change" |
|
triggers: |
|
- trigger: state |
|
entity_id: |
|
- binary_sensor.inverters_zero_inject |
|
to: "on" |
|
- trigger: state |
|
entity_id: |
|
- binary_sensor.inverters_zero_inject |
|
from: "on" |
|
to: "off" |
|
- trigger: homeassistant |
|
event: start |
|
conditions: [] |
|
actions: |
|
- if: |
|
- condition: state |
|
entity_id: binary_sensor.inverters_zero_inject |
|
state: "on" |
|
then: |
|
- action: notify.whatsapp_mathieu |
|
data: |
|
message: "[SOLAR] Zero-Inject: ON" |
|
- if: |
|
- condition: state |
|
entity_id: binary_sensor.inverters_zero_inject |
|
state: "off" |
|
then: |
|
- action: notify.whatsapp_mathieu |
|
data: |
|
message: "[SOLAR] Zero-Inject: OFF" |
|
|
|
- id: "0000000000043" |
|
alias: "Solar: Update PRE+ and PRD3" |
|
triggers: |
|
- event: start |
|
trigger: homeassistant |
|
- trigger: time_pattern |
|
seconds: /20 |
|
minutes: /3 |
|
conditions: [] |
|
actions: |
|
- if: |
|
- condition: template |
|
value_template: "{{ states('sensor.electricite_prep_timeslot') in ['unavailable', 'unknown'] or now() - states('sensor.electricite_prep_timeslot')|as_datetime > timedelta(minutes=30) }}" |
|
then: |
|
- action: homeassistant.update_entity |
|
data: |
|
entity_id: |
|
- sensor.electricite_prep_timeslot |
|
- if: |
|
- condition: template |
|
value_template: "{{ states('sensor.electricite_profil_dynamique_prd3') in ['unavailable', 'unknown'] or now() - state_attr('sensor.electricite_profil_dynamique_prd3', 'horodate')|as_datetime - timedelta(days=2) > timedelta(minutes=30) }}" |
|
then: |
|
- action: homeassistant.update_entity |
|
data: |
|
entity_id: |
|
- sensor.electricite_profil_dynamique_prd3 |