Skip to content

Instantly share code, notes, and snippets.

@mathieucarbou
Last active May 1, 2026 07:44
Show Gist options
  • Select an option

  • Save mathieucarbou/8d83d25247821e85a693dea61fe4f0d2 to your computer and use it in GitHub Desktop.

Select an option

Save mathieucarbou/8d83d25247821e85a693dea61fe4f0d2 to your computer and use it in GitHub Desktop.
3ERL Zero-Inject Instructions and Daily PRE+ Estimate

3ERL Zero-Inject Instructions and Daily PRE+ Estimate

Capture d’écran 2026-03-11 à 21 41 07

Overview

This HA package allows you to follow the PRE+ prices and 3ERL Zero-Inject instruction and also override it. It will display 2 graphs for 2 modes.

"ACI" mode (default mode when subscribing to 3ERL)

This graph displays:

  • PRD3 sunlight profile from the selected day in the past
  • PRE+ values for each 1/4h
  • PRE+ value adjusted with the PRD3 factor of the same 1/4h
  • The currently estimated daily PRE+ value
  • Zero-Inject: the 3ERL instruction to activated Zero-Inject adds a grey area on the graph

In "ACI" mode, which is by default when subscribing to 3ERL only, we need to activate zero-inject when asked by 3ERL. 3ERL is doing some approximation of the final PRE+ price that Enedis will use.

How it works behind the scene:

  1. PRE+: Enedis tracks all the PRE+ values for each 1/4h
  2. PRD3: Enedis also builds up a PRD3 profile for the current day based on sunlight. So we do not know this profile in advance. It is made available the day after in the morning.
  3. Enedis ccomputes for each 1/4h the Adjusted PRE+ for this slot which is: PRE+ x PRD3_Factor
  4. Enedis computes at the end of the day a Daily PRE+ value which is: SUM( All Adjusted PRE+ ) / SUM( All PRD3_Factor )
  5. Enedis will then multiply the Daily PRE+ value to the total excess energy for the day

Since we do not know yet the PRD3 profile of the current day (2), we use the one from a past day which is made public.

From that, we can graph:

  • The PRD3 profile of the day (in red here)
  • The adjusted PRE+ values (in orange here). We can see that the PRE+ values have no impact before 9 AM and after 6 PM here because the PRD3 factors are nearly zero.
  • The Daily Estimation of the final PRE+ (in green). We can see that it is highly impacted during the day but settles at around 2 - 4 PM because adding or removing more data has nearly no impact anymore on the average.

The Daily Estimation of the final PRE+ is the important metric to track.

"ACC" mode (when subscribing to SISOL)

This graph displays:

  • PRE+ values for each 1/4h
  • Zero-Inject: the 3ERL instruction to activated Zero-Inject adds a grey area on the graph

In "ACC" mode, this is easier: each 1/4h, the excess energy is multiplied by the PRE+ price for this time slot. So we avoid any excess when prices are going negative and we allow excess when prices are positive.

OpenDTU Intgeration for automatic inverter control

This package can be used with the following integration:

OpenDTU Zero-Injection: Automatically limit inverters based on grid excess power with Home Assistant and OpenDTU up to a configurable Setpoint

Toolbar

image image

The toolbar lets you view and control the main configuration and state:

  • PRD3 Day: the profile of the day in the past to use for the PRD factors. Set to -2 (2 days before) by default because the PRD3 profile for yesterday is only made available late in the morning.

  • Mode: Zero-Inject mode. Mainly used with the OpenDTU Integration

    • Auto: 3ERL API flags are used to control zero-inject
    • On: Zero-Inject is enabled (forced ON)
    • Off: Zero-Inject is disabled (forced OFF)
  • Zero-Inject: status when Zero-Inject is ON

  • 3ERL Trend: 3ERL trend of the day as reported at https://3erl.fr/PREP_Profile.php

Installation

package-3erl.yaml

Make sure you have configured Home Assistant to support packages.

homeassistant:
  packages: !include_dir_named packages

Put the file package-3erl.yaml in the packages folder:

image

Edit package-3erl.yaml according to your needs.

view.yaml

  • Edit your current dashboard
  • Add a new view
  • Click on the 3 points on the right to display the yaml of the view
  • Paste the content of view.yaml
Capture d’écran 2025-05-29 à 21 32 53

To work properly, you will need to install these frontend plugins from HACS:

##########
# Automatically limit inverters based on grid excess with Home Assistant and OpenDTU
# Ref: https://gist.github.com/mathieucarbou/382556f1279d612962e03232544692d1
#
# SPDX-License-Identifier: MIT
# Copyright (C) Mathieu Carbou
##########
# https://www.home-assistant.io/integrations/input_number
input_number:
# 🖐️ Number of inverters
inverters_count:
name: Inverters Count
min: 0
max: 20
step: 1
mode: box
# 🖐️ Inverters nominal power, usually 400W, 500W, 1000W, etc
inverters_nominal_power:
name: Inverters Nominal Power
unit_of_measurement: W
min: 0
max: 2000
step: 1
mode: box
# 🖐️ Inverters minimal power, usually 50W, 100W. Has to be more than 10W to keep the iverters workimng
# This should be such that minimalPowerLimit * number of inverters == minimal home consumption
# Default: 50W
inverters_minimal_power:
name: Inverters Minimal Power
unit_of_measurement: W
min: 10
max: 2000
step: 1
mode: box
# 🖐️ This is the setpoint to use when we must activate Zero-Inject (limit the excess)
# Default: 0W
inverters_zero_inject_setpoint:
name: Inverters Zero-Inject Setpoint
unit_of_measurement: W
min: -10000
max: 10000
step: 1
mode: box
# Target excess or import to stay close to
# Will be automatically set based on below automations but can also beset manually
# Default is 0
# Limit sent to inverters. Will be automatically computed but can be manually set also.
inverters_power_limit:
name: Inverters Power Limit
unit_of_measurement: W
min: 0
max: 2000
step: 1
mode: box
inverters_excess_setpoint:
name: Inverters Excess Setpoint
unit_of_measurement: W
min: -10000
max: 10000
step: 1
mode: box
template:
# https://www.home-assistant.io/integrations/template/#sensor
- sensor:
# Get the maximum voltage of inverters to detect potential risk of production stop
# 🖐️ Put your inverter S/N in this list in lowercase, any order
- name: Max Inverter Voltage
unique_id: 42D1A95B-7A70-46CF-9734-497CDDCE5674
state_class: measurement
device_class: voltage
unit_of_measurement: V
state: >-
{{ ['1410a01ec916', '1410a01ed6ca', '1410a01ed5a9', '1410a01ed5f0', '1410a01f092d', '1410a01ed604', '1410a01f010c', '1410a01e2cdd']|map('regex_replace', '(.+)', "sensor.inverter_\\1_voltage")|map('states')|map('float', 0)|max }}
# Get the maximum temeprature of inverters to detect potential risk of production stop
# 🖐️ Put your inverter S/N in this list in lowercase, any order
- name: Max Inverter Temperature
unique_id: 272E179C-3A11-44A1-B674-8C5A603033A0
state_class: measurement
device_class: temperature
unit_of_measurement: "°C"
state: >-
{{ ['1410a01ec916', '1410a01ed6ca', '1410a01ed5a9', '1410a01ed5f0', '1410a01f092d', '1410a01ed604', '1410a01f010c', '1410a01e2cdd']|map('regex_replace', '(.+)', "sensor.inverter_\\1_temperature")|map('states')|map('float', 0)|max }}
# This sensor computes your inverters energy and makes sure it does not reset to 0
# 🖐️ Put your OpenDTU YieldTotal sensor or Shelly sensors
- name: Inverters Energy
unique_id: "011F19F7-E337-488E-B52E-3CC75CBD816A"
state_class: total_increasing
device_class: energy
unit_of_measurement: kWh
# CHOICE #1: Use Shelly (could miss data if Shelly's are down - but more reliable)
state: >-
{% set c = states('sensor.inverters_energy')|float(0) %}
{% set gA = states('sensor.solar_plant_group_a_total_active_energy')|float(0) %}
{% set gB = states('sensor.solar_plant_group_b_total_active_energy')|float(0) %}
{{ [c, gA + gB] | max }}
# CHOICE #2: Use energy counters stored in inverters from OpenDTU (could miss data if inverters are unreachable - which can sometimes happen while the yare producing)
# state: >-
# {% set c = states('sensor.inverters_energy')|float(0) %}
# {% set e = states('sensor.opendtu_ff4930_yield_total')|float(0) %}
# {{ [c, e] | max }}
# Total Solar Production Power
# 🖐️ Make sure you have a sensor called Solar Production Power which reflects your total plant production power.
# In my case, I have 2 production groups, so I create a sensor which summarizes both here.
- name: Solar Production Power
unique_id: "01e37eed-3045-4eee-a786-1249567fe300"
state_class: measurement
device_class: power
unit_of_measurement: W
availability: "{{ has_value('sensor.solar_plant_group_a_power') and has_value('sensor.solar_plant_group_b_power') }}"
state: "{{ states('sensor.solar_plant_group_a_power')|float + states('sensor.solar_plant_group_b_power')|float }}"
# Home Consumed Power: power consumed by your house == the produced power plus the measured grid power
# 🖐️ Configure your sensor measuring your grid power here. Mine is a Shelly and is called: sensor.grid_power
- name: Home Consumed Power
unique_id: BE34D1AD-AB8E-4909-ACE0-BBA7D3877105
state_class: measurement
device_class: power
unit_of_measurement: W
availability: "{{ has_value('sensor.solar_production_power') and has_value('sensor.grid_power') }}"
state: "{{ states('sensor.solar_production_power')|float + states('sensor.grid_power')|float }}"
# Solar Consumed Power: This is the produced power consumed by your house
- name: Solar Consumed Power
unique_id: "01e37eed-3045-4eee-a786-1249567fe303"
state_class: measurement
device_class: power
unit_of_measurement: W
availability: "{{ has_value('sensor.solar_production_power') and has_value('sensor.grid_power') }}"
state: "{{ [states('sensor.solar_production_power')|float + [states('sensor.grid_power')|float, 0] | min, 0] | max }}"
# Daily energy used from solar production (C = P - E)
- name: Solar Consumed Energy Meter Daily
unique_id: "01e37eed-3045-4eee-a786-1249567fe305"
state_class: total_increasing
device_class: energy
unit_of_measurement: kWh
availability: "{{ has_value('sensor.inverters_energy_meter_daily') and has_value('sensor.grid_energy_returned_meter_daily') }}"
state: >-
{% set p = states('sensor.inverters_energy_meter_daily')|float(0) %}
{% set e = states('sensor.grid_energy_returned_meter_daily')|float(0) %}
{% set c = states('sensor.solar_consumed_energy_meter_daily')|float(0) %}
{{ [0 if p == 0 or p < c or p < e else c, [0, p - e] | max] | max }}
# Daily energy consumed by home (H = P + I - E)
- name: Home Consumed Energy Meter Daily
unique_id: A03E558E-DF44-4DAB-852D-0847287DEDDB
state_class: total_increasing
device_class: energy
unit_of_measurement: kWh
availability: "{{ has_value('sensor.inverters_energy_meter_daily') and has_value('sensor.grid_energy_meter_daily') and has_value('sensor.grid_energy_returned_meter_daily') }}"
state: >-
{% set p = states('sensor.inverters_energy_meter_daily')|float(0) %}
{% set i = states('sensor.grid_energy_meter_daily')|float(0) %}
{% set e = states('sensor.grid_energy_returned_meter_daily')|float(0) %}
{% set h = states('sensor.home_consumed_energy_meter_daily')|float(0) %}
{{ [0, p + i - e] | max if p == 0 or i == 0 or p < e else [h, p + i - e] | max }}
# https://www.home-assistant.io/integrations/utility_meter/
utility_meter:
# Grid Energy Returned Meter Daily: Daily meter for the grid returned energy.
# Mine comes from a Linky key which is far more reliable than a Shelly since reads the counters directly stored in the Linky
# 🖐️ Set your grid returned energy sensor here
grid_energy_returned_meter_daily:
name: Grid Energy Returned Meter Daily
unique_id: 454B7731-375D-4C90-AFC0-42EAB23DF11D
source: sensor.linky_energie_injectee
cycle: daily
# Inverters Energy Meter Daily
inverters_energy_meter_daily:
name: Inverters Energy Meter Daily
unique_id: 4C4D8D06-C9D2-4408-B21A-1274A6E0F041
source: sensor.inverters_energy
cycle: daily
# https://www.home-assistant.io/docs/automation/
automation:
# Automatically propagate changes in power limit input number to inverters
- id: "0000000000038"
alias: "Solar: Update Inverter Power Limit"
trigger:
- trigger: state
entity_id:
- input_number.inverters_power_limit
condition: []
action:
- action: number.set_value
data:
value: >-
{% set minimalPowerLimit = states('input_number.inverters_minimal_power')|int(50) %}
{% set nominalPower = states('input_number.inverters_nominal_power')|int(minimalPowerLimit) %}
{% set powerLimit = states('input_number.inverters_power_limit')|float(nominalPower) %}
{{ powerLimit / nominalPower * 100.0 }}
target:
entity_id:
- number.inverter_1410a01e2cdd_limit_nonpersistent_relative
- number.inverter_1410a01ec916_limit_nonpersistent_relative
- number.inverter_1410a01ed6ca_limit_nonpersistent_relative
- number.inverter_1410a01ed5a9_limit_nonpersistent_relative
- number.inverter_1410a01ed5f0_limit_nonpersistent_relative
- number.inverter_1410a01f092d_limit_nonpersistent_relative
- number.inverter_1410a01ed604_limit_nonpersistent_relative
- number.inverter_1410a01f010c_limit_nonpersistent_relative
# Runs at a frequent interval to update the inverters limit
# 🖐️ set your Grid Power sensor for `sensor.grid_power`
# 🖐️ Update the list of entity IDs matching your inverters S/N: these sensors come from OpenDTU
- id: "0000000000039"
alias: "Solar: Auto update power limits"
trigger:
- trigger: time_pattern
#minutes: /1
seconds: /30
condition:
- condition: state
entity_id: binary_sensor.opendtu_ff4930_status
state: "on"
action:
- action: input_number.set_value
data:
value: >-
{% set minimalPowerLimit = states('input_number.inverters_minimal_power')|int(50) %}
{% set grid = states('sensor.grid_power')|float(0) %}
{% set setpoint = states('input_number.inverters_excess_setpoint')|int(0) %}
{% set nominalPower = states('input_number.inverters_nominal_power')|int(minimalPowerLimit) %}
{% set powerLimit = states('input_number.inverters_power_limit')|float(nominalPower) %}
{% set count = states('input_number.inverters_count')|int(0) %}
{% set missedPower = (grid - setpoint) / count if count > 0 else nominalPower %}
{{ [nominalPower, [minimalPowerLimit, powerLimit + missedPower|round(0, "ceil")]|max]|min|round }}
target:
entity_id:
- input_number.inverters_power_limit
# Update the setpoint depending on events
# 🖐️ set your events accordingly. For example, `binary_sensor.openevse_vehicle_connected` and `sensor.openevse_vehicle_battery_level` and `binary_sensor.openevse_vehicle_charge` are for my EV car charger. You might not need them.
# 🖐️ update the conditions: here, I need a special condition that sets the setpoint to -600 when my EV si connected so that it has enough excess to start charging. If you do not have an EV, then put -200 or -100 or 0.
# The value of -5500 is because with single phase in France you cannot divert to the grid more than 6kVA. So this is a safety value in case your home is consuming less, the script will reduce the soalr production ot make sure it does not feed teh grid with more than 5.5kW.
- id: "0000000000041"
alias: "Solar: Auto update Setpoint"
triggers:
- trigger: state
entity_id:
- binary_sensor.inverters_zero_inject
- binary_sensor.openevse_vehicle_connected
- sensor.openevse_vehicle_battery_level
- binary_sensor.openevse_vehicle_charge
- input_number.inverters_zero_inject_setpoint
- trigger: homeassistant
event: start
conditions: []
actions:
- if:
- condition: state
entity_id: binary_sensor.inverters_zero_inject
state: "on"
then:
- if:
- condition: state
entity_id: binary_sensor.openevse_vehicle_connected
state: "on"
- condition: numeric_state
entity_id: sensor.openevse_vehicle_battery_level
below: 100
then:
- action: input_number.set_value
metadata: {}
data:
value: "{{ [states('input_number.inverters_zero_inject_setpoint')|int(0), -600]|min }}"
target:
entity_id: input_number.inverters_excess_setpoint
else:
- action: input_number.set_value
metadata: {}
data:
value: "{{ states('input_number.inverters_zero_inject_setpoint')|int(0) }}"
target:
entity_id: input_number.inverters_excess_setpoint
- if:
- condition: state
entity_id: binary_sensor.inverters_zero_inject
state: "off"
then:
- action: input_number.set_value
metadata: {}
data:
value: -6000
target:
entity_id: input_number.inverters_excess_setpoint
# Notification in case a high grid volatge is detected
# This is optional and require you to know how to setup HA notifications.
- id: "0000000000042"
alias: "Solar: Notify of high grid voltage"
trigger:
- trigger: numeric_state
entity_id:
- sensor.grid_voltage
above: 250
action:
- action: notify.whatsapp_mathieu
data:
message: "[GRID] High Voltage (> 250V)"
- delay:
hours: 0
minutes: 1
seconds: 0
milliseconds: 0
type: sections
max_columns: 3
title: Solaire
path: solar
icon: mdi:solar-panel-large
sections:
- type: grid
cards:
- type: custom:power-flow-card-plus
entities:
grid:
entity: sensor.grid_power
display_state: one_way
secondary_info:
entity: sensor.grid_voltage
unit_of_measurement: V
display_zero: true
color_value: false
decimals: 1
use_metadata: false
color_value: false
color_icon: true
solar:
entity: sensor.solar_production_power
display_zero_state: true
color_value: false
color_icon: true
secondary_info:
entity: sensor.max_inverter_voltage
unit_of_measurement: V
display_zero: true
color_value: false
decimals: 1
home:
entity: sensor.home_consumed_power
color_value: false
color_icon: true
secondary_info: {}
individual:
- entity: sensor.openevse_power
display_zero: true
icon: mdi:car-electric
name: OpenEVSE
color_value: false
color_icon: true
secondary_info:
entity: sensor.renault_zoe_battery_level
unit_of_measurement: "%"
display_zero: true
unit_white_space: true
display_zero_state: true
unit_white_space: true
- entity: sensor.chauffe_eau_power
display_zero: true
color_value: false
color_icon: true
secondary_info: {}
name: Chauffe-eau
icon: mdi:water-boiler
calculate_flow_rate: false
display_zero_state: true
unit_white_space: true
- entity: sensor.total_deshumidificateur_power
display_zero: true
color_value: false
color_icon: true
secondary_info: {}
name: Déshumidificateurs
icon: mdi:air-filter
display_zero_state: true
calculate_flow_rate: false
unit_white_space: true
- entity: sensor.total_pac_power
display_zero: true
color_value: false
color_icon: true
secondary_info: {}
name: PAC
icon: mdi:air-conditioner
display_zero_state: true
unit_white_space: true
clickable_entities: true
display_zero_lines:
mode: show
transparency: 50
grey_color:
- 189
- 189
- 189
use_new_flow_rate_model: true
max_expected_power: 12000
watt_threshold: 12000
kw_decimals: 2
min_flow_rate: 0.5
max_flow_rate: 3
- type: entities
entities:
- type: custom:entity-progress-card
entity: sensor.inverter_1410a01e2cdd_power
decimal: 0
min_value: 0
max_value: 1000
name: "#1: 1410A01E2CDD"
hold_action:
action: more-info
tap_action:
action: perform-action
perform_action: button.press
target:
entity_id: button.inverter_1410a01e2cdd_restart_inverter
layout: horizontal
force_circular_background: true
bar_size: medium
icon: mdi:restart
theme: optimal_when_high
grid_options:
columns: 12
rows: 1
- type: custom:entity-progress-card
entity: sensor.inverter_1410a01ec916_power
decimal: 0
min_value: 0
max_value: 1000
name: "#2: 1410A01EC916"
hold_action:
action: more-info
tap_action:
action: perform-action
perform_action: button.press
target:
entity_id: button.inverter_1410a01ec916_restart_inverter
layout: horizontal
force_circular_background: true
bar_size: medium
icon: mdi:restart
theme: optimal_when_high
grid_options:
columns: 12
rows: 1
- type: custom:entity-progress-card
entity: sensor.inverter_1410a01ed6ca_power
decimal: 0
min_value: 0
max_value: 1000
name: "#3: 1410A01ED6CA"
hold_action:
action: more-info
tap_action:
action: perform-action
perform_action: button.press
target:
entity_id: button.inverter_1410a01ed6ca_restart_inverter
layout: horizontal
force_circular_background: true
bar_size: medium
icon: mdi:restart
theme: optimal_when_high
grid_options:
columns: 12
rows: 1
- type: custom:entity-progress-card
entity: sensor.inverter_1410a01ed5a9_power
decimal: 0
min_value: 0
max_value: 1000
name: "#4: 1410A01ED5A9"
hold_action:
action: more-info
tap_action:
action: perform-action
perform_action: button.press
target:
entity_id: button.inverter_1410a01ed5a9_restart_inverter
layout: horizontal
force_circular_background: true
bar_size: medium
icon: mdi:restart
theme: optimal_when_high
grid_options:
columns: 12
rows: 1
- type: custom:entity-progress-card
entity: sensor.inverter_1410a01ed5f0_power
decimal: 0
min_value: 0
max_value: 1000
name: "#5: 1410A01ED5F0"
hold_action:
action: more-info
tap_action:
action: perform-action
perform_action: button.press
target:
entity_id: button.inverter_1410a01ed5f0_restart_inverter
layout: horizontal
force_circular_background: true
bar_size: medium
icon: mdi:restart
theme: optimal_when_high
grid_options:
columns: 12
rows: 1
- type: custom:entity-progress-card
entity: sensor.inverter_1410a01f092d_power
decimal: 0
min_value: 0
max_value: 1000
name: "#7: 1410A01F092D"
hold_action:
action: more-info
tap_action:
action: perform-action
perform_action: button.press
target:
entity_id: button.inverter_1410a01f092d_restart_inverter
layout: horizontal
force_circular_background: true
bar_size: medium
icon: mdi:restart
theme: optimal_when_high
grid_options:
columns: 12
rows: 1
- type: custom:entity-progress-card
entity: sensor.inverter_1410a01ed604_power
decimal: 0
min_value: 0
max_value: 1000
name: "#8: 1410A01ED604"
hold_action:
action: more-info
tap_action:
action: perform-action
perform_action: button.press
target:
entity_id: button.inverter_1410a01ed604_restart_inverter
layout: horizontal
force_circular_background: true
bar_size: medium
icon: mdi:restart
theme: optimal_when_high
grid_options:
columns: 12
rows: 1
- type: custom:entity-progress-card
entity: sensor.inverter_1410a01f010c_power
decimal: 0
min_value: 0
max_value: 1000
name: "#9: 1410A01F010C"
hold_action:
action: more-info
tap_action:
action: perform-action
perform_action: button.press
target:
entity_id: button.inverter_1410a01f010c_restart_inverter
layout: horizontal
force_circular_background: true
bar_size: medium
icon: mdi:restart
theme: optimal_when_high
grid_options:
columns: 12
rows: 1
title: Inverter Power
- type: entities
entities:
- type: custom:entity-progress-card
entity: number.inverter_1410a01e2cdd_limit_nonpersistent_relative
decimal: 1
name: "#1: 1410A01E2CDD"
hold_action:
action: more-info
tap_action:
action: perform-action
perform_action: number.set_value
data:
value: 100
target:
entity_id: number.inverter_1410a01e2cdd_limit_nonpersistent_relative
layout: horizontal
force_circular_background: true
bar_size: medium
icon: mdi:restart
theme: optimal_when_high
grid_options:
columns: 12
rows: 1
- type: custom:entity-progress-card
entity: number.inverter_1410a01ec916_limit_nonpersistent_relative
decimal: 1
name: "#2: 1410A01EC916"
hold_action:
action: more-info
tap_action:
action: perform-action
perform_action: number.set_value
data:
value: 100
target:
entity_id: number.inverter_1410a01ec916_limit_nonpersistent_relative
layout: horizontal
force_circular_background: true
bar_size: medium
icon: mdi:restart
theme: optimal_when_high
grid_options:
columns: 12
rows: 1
- type: custom:entity-progress-card
entity: number.inverter_1410a01ed6ca_limit_nonpersistent_relative
decimal: 1
name: "#3: 1410A01ED6CA"
hold_action:
action: more-info
tap_action:
action: perform-action
perform_action: number.set_value
data:
value: 100
target:
entity_id: number.inverter_1410a01ed6ca_limit_nonpersistent_relative
layout: horizontal
force_circular_background: true
bar_size: medium
icon: mdi:restart
theme: optimal_when_high
grid_options:
columns: 12
rows: 1
- type: custom:entity-progress-card
entity: number.inverter_1410a01ed5a9_limit_nonpersistent_relative
decimal: 1
name: "#4: 1410A01ED5A9"
hold_action:
action: more-info
tap_action:
action: perform-action
perform_action: number.set_value
data:
value: 100
target:
entity_id: number.inverter_1410a01ed5a9_limit_nonpersistent_relative
layout: horizontal
force_circular_background: true
bar_size: medium
icon: mdi:restart
theme: optimal_when_high
grid_options:
columns: 12
rows: 1
- type: custom:entity-progress-card
entity: number.inverter_1410a01ed5f0_limit_nonpersistent_relative
decimal: 1
name: "#5: 1410A01ED5F0"
hold_action:
action: more-info
tap_action:
action: perform-action
perform_action: number.set_value
data:
value: 100
target:
entity_id: number.inverter_1410a01ed5f0_limit_nonpersistent_relative
layout: horizontal
force_circular_background: true
bar_size: medium
icon: mdi:restart
theme: optimal_when_high
grid_options:
columns: 12
rows: 1
- type: custom:entity-progress-card
entity: number.inverter_1410a01f092d_limit_nonpersistent_relative
decimal: 1
name: "#7: 1410A01F092D"
hold_action:
action: more-info
tap_action:
action: perform-action
perform_action: number.set_value
data:
value: 100
target:
entity_id: number.inverter_1410a01f092d_limit_nonpersistent_relative
layout: horizontal
force_circular_background: true
bar_size: medium
icon: mdi:restart
theme: optimal_when_high
grid_options:
columns: 12
rows: 1
- type: custom:entity-progress-card
entity: number.inverter_1410a01ed604_limit_nonpersistent_relative
decimal: 1
name: "#8: 1410A01ED604"
hold_action:
action: more-info
tap_action:
action: perform-action
perform_action: number.set_value
data:
value: 100
target:
entity_id: number.inverter_1410a01ed604_limit_nonpersistent_relative
layout: horizontal
force_circular_background: true
bar_size: medium
icon: mdi:restart
theme: optimal_when_high
grid_options:
columns: 12
rows: 1
- type: custom:entity-progress-card
entity: number.inverter_1410a01f010c_limit_nonpersistent_relative
decimal: 1
name: "#9: 1410A01F010C"
hold_action:
action: more-info
tap_action:
action: perform-action
perform_action: number.set_value
data:
value: 100
target:
entity_id: number.inverter_1410a01f010c_limit_nonpersistent_relative
layout: horizontal
force_circular_background: true
bar_size: medium
icon: mdi:restart
theme: optimal_when_high
grid_options:
columns: 12
rows: 1
title: Inverter Limit
- type: custom:bar-card
title: Inverter Voltage
direction: right
height: 25
positions:
icon: "off"
indicator: inside
name: inside
value: inside
entities:
- entity: sensor.inverter_1410a01e2cdd_voltage
name: "#1: 1410A01E2CDD"
- entity: sensor.inverter_1410a01ec916_voltage
name: "#2: 1410A01EC916"
- entity: sensor.inverter_1410a01ed6ca_voltage
name: "#3: 1410A01ED6CA"
- entity: sensor.inverter_1410a01ed5a9_voltage
name: "#4: 1410A01ED5A9"
- entity: sensor.inverter_1410a01ed5f0_voltage
name: "#5: 1410A01ED5F0"
- entity: sensor.inverter_1410a01f092d_voltage
name: "#7: 1410A01F092D"
- entity: sensor.inverter_1410a01ed604_voltage
name: "#8: 1410A01ED604"
- entity: sensor.inverter_1410a01f010c_voltage
name: "#9: 1410A01F010C"
min: 207
max: 253
- type: custom:bar-card
title: Inverter Temperature
direction: right
height: 25px
positions:
icon: "off"
indicator: inside
name: inside
value: inside
entities:
- entity: sensor.inverter_1410a01e2cdd_temperature
name: "#1: 1410A01E2CDD"
- entity: sensor.inverter_1410a01ec916_temperature
name: "#2: 1410A01EC916"
- entity: sensor.inverter_1410a01ed6ca_temperature
name: "#3: 1410A01ED6CA"
- entity: sensor.inverter_1410a01ed5a9_temperature
name: "#4: 1410A01ED5A9"
- entity: sensor.inverter_1410a01ed5f0_temperature
name: "#5: 1410A01ED5F0"
- entity: sensor.inverter_1410a01f092d_temperature
name: "#7: 1410A01F092D"
- entity: sensor.inverter_1410a01ed604_temperature
name: "#8: 1410A01ED604"
- entity: sensor.inverter_1410a01f010c_temperature
name: "#9: 1410A01F010C"
min: 0
max: 80
- type: grid
cards:
- type: horizontal-stack
grid_options:
columns: full
cards:
- type: custom:plotly-graph
title: Grid and Solar Power
refresh_interval: 60
hours_to_show: 8
layout:
height: 440
yaxis9:
visible: false
fixedrange: true
xaxis:
rangeselector:
"y": 1.3
bgcolor: grey
buttons:
- count: 1
step: hour
- count: 2
step: hour
- count: 4
step: hour
- count: 8
step: hour
- count: 12
step: hour
entities:
- entity: sensor.home_consumed_power
name: Consumption
line:
color: "#A52A2A"
width: 1
- entity: sensor.openevse_power
name: OpenEVSE
line:
color: "#00AA00"
width: 1
- entity: sensor.grid_power
name: Grid
line:
color: "#0000FF"
width: 1
filters:
- map_y_numbers: "y >= 0 ? y : 0"
- entity: sensor.solar_production_power
name: Solar
line:
color: "#ff8c00"
width: 1
- entity: sensor.grid_power
name: Excess
line:
color: "#FFFF00"
width: 1
filters:
- map_y_numbers: "y <= 0 ? y : 0"
- entity: binary_sensor.inverters_zero_inject
name: Zero-Inject
showlegend: true
yaxis: y9
filters:
- map_y: "y === 'on' ? 1 : 0"
fill: tozeroy
line:
color: rgba(100,100,100,0.1)
shape: hv
connectgaps: false
width: 0
- type: horizontal-stack
cards:
- type: custom:plotly-graph
title: Energy
refresh_interval: 1m
hours_to_show: 8
layout:
height: 440
barmode: relative
yaxis9:
visible: false
fixedrange: true
xaxis:
rangeselector:
"y": 1.3
bgcolor: grey
buttons:
- count: 8
step: hour
- count: 12
step: hour
- count: 1
step: day
- count: 7
step: day
entities:
- entity: sensor.inverters_energy
name: Solar
statistic: sum
type: bar
unit_of_measurement: Wh
period: auto
marker:
color: "#ff8c00"
filters:
- multiply: 1000
- delta
- entity: sensor.grid_total_active_energy
name: Grid
statistic: sum
type: bar
unit_of_measurement: Wh
period: auto
marker:
color: "#0000FF"
filters:
- multiply: 1000
- delta
- entity: sensor.home_consumed_energy_meter_daily
name: Consumption
statistic: sum
type: bar
unit_of_measurement: Wh
period: auto
marker:
color: "#A52A2A"
filters:
- multiply: -1000
- delta
- entity: sensor.linky_energie_injectee
name: Excess
statistic: sum
type: bar
unit_of_measurement: Wh
period: auto
marker:
color: "#FFFF00"
filters:
- multiply: -1000
- delta
- entity: binary_sensor.inverters_zero_inject
name: Zero-Inject
showlegend: true
yaxis: y9
filters:
- map_y: "y === 'on' ? 1 : 0"
fill: tozeroy
line:
color: rgba(100,100,100,0.1)
shape: hv
connectgaps: false
width: 0
grid_options:
columns: full
- type: horizontal-stack
cards:
- type: custom:plotly-graph
title: Inverter Limit
refresh_interval: 60
hours_to_show: 8
layout:
height: 440
barmode: relative
yaxis:
autorange: max
rangemode: tozero
yaxis9:
visible: false
fixedrange: true
xaxis:
rangeselector:
"y": 1.1
bgcolor: grey
buttons:
- count: 1
step: hour
- count: 2
step: hour
- count: 4
step: hour
- count: 8
step: hour
- count: 12
step: hour
entities:
- entity: input_number.inverters_power_limit
- entity: binary_sensor.inverters_zero_inject
name: Bridage
showlegend: true
yaxis: y9
filters:
- map_y: "y === 'on' ? 1 : 0"
fill: tozeroy
line:
color: rgba(100,100,100,0.1)
shape: hv
connectgaps: false
width: 0
grid_options:
columns: 24
rows: auto
- type: horizontal-stack
cards:
- type: custom:plotly-graph
title: Inverter Temperatures
refresh_interval: 60
hours_to_show: 8
layout:
height: 440
barmode: relative
yaxis:
autorange: max
rangemode: tozero
yaxis9:
visible: false
fixedrange: true
xaxis:
rangeselector:
"y": 1.3
bgcolor: grey
buttons:
- count: 1
step: hour
- count: 2
step: hour
- count: 4
step: hour
- count: 8
step: hour
- count: 12
step: hour
entities:
- entity: sensor.inverter_1410a01e2cdd_temperature
name: "#1"
- entity: sensor.inverter_1410a01ec916_temperature
name: "#2"
- entity: sensor.inverter_1410a01ed6ca_temperature
name: "#3"
- entity: sensor.inverter_1410a01ed5a9_temperature
name: "#4"
- entity: sensor.inverter_1410a01ed5f0_temperature
name: "#5"
- entity: sensor.inverter_1410a01f092d_temperature
name: "#7"
- entity: sensor.inverter_1410a01ed604_temperature
name: "#8"
- entity: sensor.inverter_1410a01f010c_temperature
name: "#9"
- entity: binary_sensor.inverters_zero_inject
name: Bridage
showlegend: true
yaxis: y9
filters:
- map_y: "y === 'on' ? 1 : 0"
fill: tozeroy
line:
color: rgba(100,100,100,0.1)
shape: hv
connectgaps: false
width: 0
grid_options:
columns: full
- type: horizontal-stack
cards:
- type: custom:plotly-graph
title: Energy (hourly)
refresh_interval: 5m
hours_to_show: 7d
layout:
height: 440
barmode: relative
yaxis9:
visible: false
fixedrange: true
xaxis:
rangeselector:
"y": 1.3
bgcolor: grey
buttons:
- count: 1
step: day
- count: 3
step: day
- count: 7
step: day
entities:
- entity: sensor.inverters_energy
name: Solar
statistic: sum
type: bar
unit_of_measurement: kWh
period: hour
marker:
color: "#ff8c00"
filters:
- multiply: 1
- delta
- entity: sensor.grid_total_active_energy
name: Grid
statistic: sum
type: bar
unit_of_measurement: kWh
period: hour
marker:
color: "#0000FF"
filters:
- multiply: 1
- delta
- entity: sensor.home_consumed_energy_meter_daily
name: Consumption
statistic: sum
type: bar
unit_of_measurement: kWh
period: hour
marker:
color: "#A52A2A"
filters:
- multiply: -1
- delta
- entity: sensor.linky_energie_injectee
name: Excess
statistic: sum
type: bar
unit_of_measurement: kWh
period: hour
marker:
color: "#FFFF00"
filters:
- multiply: -1
- delta
- entity: sensor.openevse_total_active_energy
name: OpenEVSE
statistic: sum
unit_of_measurement: kWh
period: hour
type: line
line:
color: "#00FF00"
width: 1
filters:
- multiply: 1
- delta
- entity: binary_sensor.inverters_zero_inject
name: Bridage
showlegend: true
yaxis: y9
filters:
- map_y: "y === 'on' ? 1 : 0"
fill: tozeroy
line:
color: rgba(100,100,100,0.1)
shape: hv
connectgaps: false
width: 0
grid_options:
columns: full
column_span: 2
cards: []
badges:
- type: entity
show_name: true
show_state: true
show_icon: true
entity: input_number.inverters_count
name: Inverters
- type: entity
show_name: true
show_state: true
show_icon: true
entity: input_number.inverters_minimal_power
name: Min
- type: entity
show_name: true
show_state: true
show_icon: true
entity: input_number.inverters_nominal_power
name: Max
- type: entity
show_name: true
show_state: true
show_icon: true
entity: input_number.inverters_power_limit
name: Limit
- type: entity
show_name: true
show_state: true
show_icon: true
entity: input_number.inverters_zero_inject_setpoint
icon: mdi:bullseye-arrow
name: Zero-Inject
- type: entity
show_name: true
show_state: true
show_icon: true
entity: input_number.inverters_excess_setpoint
icon: mdi:bullseye-arrow
name: Setpoint
- type: entity
show_name: true
show_state: true
show_icon: true
entity: sensor.inverters_energy
name: Production
visible:
- user: 8b29665394c74237a7759b784fc5232e
header:
layout: center
badges_position: bottom
badges_wrap: wrap
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment