|
########## |
|
# 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 |
|
# Sell price defined for selling electricity to neighbouhood in ACC mode |
|
# Default to 8c/kWh |
|
electricite_acc_sell_price: |
|
name: "Électricité: ACC Gross Sell Price" |
|
icon: mdi:currency-eur |
|
min: 0 |
|
max: 100 |
|
step: 0.01 |
|
mode: box |
|
unit_of_measurement: "c€/kWh" |
|
|
|
# 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 %} |
|
|
|
# https://www.home-assistant.io/integrations/command_line |
|
command_line: |
|
# Prix equilibre RTE: https://www.services-rte.com/fr/visualisez-les-donnees-publiees-par-rte/equilibrage.html |
|
- sensor: |
|
name: "Électricité: PREP Timeslot" |
|
unique_id: 1D93CA5A-BED5-499D-A164-15609D78657F |
|
device_class: timestamp |
|
# 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 https://www.services-rte.com/cms/open_data/v1/price/table?startDate={{ now().strftime('%d%%2F%m%%2F%Y') }} | jq -c '{values: [.values[] | {d: .date, v: .pre.positive|tonumber}]}' |
|
availability: "{{ value_json and value_json['values'] and value_json['values']|length > 0 }}" |
|
value_template: "{{ value_json['values'][0]['d'] }}" |
|
json_attributes: |
|
- values |
|
# 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-j1 |
|
- sensor: |
|
name: "Électricité: PRD3 Timeslot" |
|
unique_id: AF7BFE5B-5AA0-42F7-8323-D2166F8EA4E3 |
|
device_class: timestamp |
|
# 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" | jq -c '{values: [.[] | {d: .horodate, v: .coefficient_dynamique_j_1}]}' |
|
availability: "{{ value_json and value_json['values'] and value_json['values']|length > 0 }}" |
|
value_template: "{{ value_json['values'][0]['d'] }}" |
|
json_attributes: |
|
- values |
|
|
|
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', 'values')[0]['v']|float }}" |
|
attributes: |
|
last_reset: "{{ now() }}" |
|
date: "{{ (states('sensor.electricite_prep_timeslot')|as_datetime|as_local).isoformat() }}" |
|
timeslot: "{{ (states('sensor.electricite_prep_timeslot')|as_datetime|as_local).strftime('%H:%M') }}" |
|
|
|
# Sensor to use in Eenrgy view to keep track of ompensation cost for excess |
|
# The net sell price used for exported kWh in ACC mode |
|
# Accounts for -1 c/kWh taken by 3ERL for each exportd kWh |
|
# Accounts for -1 c/kWh taken by SISol for each sold kWh within the ACC |
|
- name: "Électricité: Prix de vente du surplus" |
|
icon: "mdi:currency-eur" |
|
unique_id: 98CAC0C7-D49F-45F6-9A48-40BEC12AAD77 |
|
state_class: measurement |
|
unit_of_measurement: "€/kWh" |
|
availability: "{{ states('sensor.electricite_prep_timeslot') not in ['unavailable', 'unknown'] }}" |
|
state: >- |
|
{% set prep = state_attr('sensor.electricite_prep_timeslot', 'values')[0]['v']|float / 1000.0 %} |
|
{% set acc_sell_price = states('input_number.electricite_acc_sell_price')|float(8) / 100.0 %} |
|
{{ prep - 0.01 if prep > acc_sell_price else acc_sell_price - 0.02 }} |
|
attributes: |
|
last_reset: "{{ now() }}" |
|
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é: PRD3 Factor" |
|
unique_id: CB8D1FF5-8C46-4E8C-B142-B877688AB456 |
|
state_class: measurement |
|
availability: "{{ states('sensor.electricite_prd3_timeslot') not in ['unavailable', 'unknown'] }}" |
|
state: "{{ state_attr('sensor.electricite_prd3_timeslot', 'values')[0]['v']|float }}" |
|
attributes: |
|
last_reset: "{{ now() }}" |
|
date: "{{ (states('sensor.electricite_prd3_timeslot')|as_datetime|as_local).isoformat() }}" |
|
timeslot: "{{ (states('sensor.electricite_prd3_timeslot')|as_datetime|as_local).strftime('%H:%M') }}" |
|
|
|
# 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: "{{ states('sensor.electricite_prep_timeslot') not in ['unavailable', 'unknown'] and states('sensor.electricite_prd3_timeslot') not in ['unavailable', 'unknown'] }}" |
|
state: >- |
|
{% set prep_timeslot = (states('sensor.electricite_prep_timeslot')|as_datetime|as_local).strftime('%H:%M') %} |
|
{% set prd3_timeslot = (states('sensor.electricite_prd3_timeslot')|as_datetime|as_local).strftime('%H:%M') %} |
|
{% set prep_values = state_attr('sensor.electricite_prep_timeslot', 'values') %} |
|
{% set prd3_values = state_attr('sensor.electricite_prd3_timeslot', 'values') %} |
|
{% if prep_timeslot == prd3_timeslot and prep_values|length == prd3_values|length %} |
|
{% set sum = namespace(prep_adjusted=0, prd3_factors=0) %} |
|
{% for i in range(prep_values|length) %} |
|
{% set prd3_factor = prd3_values[i]['v']|float %} |
|
{% set sum.prd3_factors = sum.prd3_factors + prd3_factor %} |
|
{% set prep_adjusted = prep_values[i]['v']|float * prd3_factor %} |
|
{% set sum.prep_adjusted = sum.prep_adjusted + prep_adjusted %} |
|
{% endfor %} |
|
{{ sum.prep_adjusted / sum.prd3_factors }} |
|
{% else %} |
|
{{ states('sensor.electricite_prep_daily_estimation') }} |
|
{% endif %} |
|
attributes: |
|
last_reset: "{{ now() }}" |
|
date: "{{ (states('sensor.electricite_prep_timeslot')|as_datetime|as_local).isoformat() }}" |
|
timeslot: "{{ (states('sensor.electricite_prep_timeslot')|as_datetime|as_local).strftime('%H:%M') }}" |
|
|
|
# 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 hours |
|
grid_energy_returned_meter_quarter_hourly: |
|
name: Grid Energy Returned Meter Quarter Hourly |
|
unique_id: 798D017B-F9E8-4131-AABA-BB645DAFCFC4 |
|
source: sensor.linky_energie_injectee |
|
cycle: quarter-hourly |
|
|
|
# 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_prd3_timeslot') in ['unavailable', 'unknown'] or now() - states('sensor.electricite_prd3_timeslot')|as_datetime - timedelta(days=2) > timedelta(minutes=30) }}" |
|
then: |
|
- action: homeassistant.update_entity |
|
data: |
|
entity_id: |
|
- sensor.electricite_prd3_timeslot |