Skip to content

Instantly share code, notes, and snippets.

@mathieucarbou
Last active May 29, 2025 19:41
Show Gist options
  • Save mathieucarbou/382556f1279d612962e03232544692d1 to your computer and use it in GitHub Desktop.
Save mathieucarbou/382556f1279d612962e03232544692d1 to your computer and use it in GitHub Desktop.
Automatically limit inverters based on grid excess with Home Assistant and OpenDTU

Automatically limit inverters based on grid excess with Home Assistant and OpenDTU

Here is my Home Assistant OpenDTU dsashboard:

Capture d’écran 2025-05-29 à 21 08 39

I sometimes need to be able to limit by production excess around a number to avoid retruning too much energy to the grid.

So I did a Home Assistant automation that is looking at the grid_power sensor to automatically adjutst the inverters' limit in order to keep the returned power at a specifed amount (setpoint).

The code supports also 3ERL API to limit the production when asked by 3ERL.

Zoom on the toolbar:

Capture d’écran 2025-05-29 à 21 11 29
  • Inverters: the number of inverters you have

  • Nominal: the nominal power of the inverters (400W, 500W, 1000W, etc)

  • Today: today's production in kWh as reported by OpenDTU

  • Lifetime: total production over time in kWh as reported by OpenDTU

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

  • 3ERL Limit: status activated (on) when 3ERL asks to limit the production (see their API at https://3erl.fr/api.json)

  • Setpoint: this is my desired level of excess to stick around. There are 2 setpoint: when the limiter is on, and when it is off. If set to 0, there will be a little excess and consumption. Setting it to -500W for example let me return little energy to the grid and also keep a buffer to start a VE charge for example. When limiter is off, I allow -2000W of excess, and when on, I allow -300W. But if my EV is plugged, I allow -600W to allow it to start a charge.

  • Limit: this is an input where I can type (in manual mode) a limit to apply to all inverters. When in auto mode, this value is automatically computed by the algorithm depending on the excess.

  • Producing: the number of inverters producing AC power

  • Produced Power: the produced AC power as reported by OpenDTU

  • Lost Power: when the limiter is on, computes the lost power that the inverters could have prodced if they were not limited. BE CAREFUL: this value is just an approximation but is not accurate! For example, let's say your inverter has a nominal power of 400W, is producing currently 300W, and the limiter is trurned on, and it limits the inverters to 50% (200W). There is no way to know how much power is exactly lost! So I assume that if the limit was turned off, the inverter could product its full nominal power of 400W, so 200W is lost in this case. In reality, only 100W is lost. So why having this sensor ? This sensor could be used as a hint to start appliances (like a VE charging box) depending on the lost power.

Installation

Putting that in place is super easy.

Make sure you have configured Home Assistant to support packages.

homeassistant:
  packages: !include_dir_named packages

Put the file opendtu.yaml in the packages folder:

image

Edit opendtu.yaml according to your needs and especially your sensor names, especially for:

  • sensor.grid_power => your grid power
  • sensor.inverter_1_power, sensor.inverter_2_power, sensor.inverter_3_power, etc: your inverters power. Note that I am only using that to compute a more accurate available number of active inverters. You could replace that by the number of inverters you have, the correction will take more minutes to apply.

Create a new dashboard view, edit its yaml and paste the content of view.yaml. It is possible that you'll need to install some missing UI components.

Capture d’écran 2025-05-29 à 21 32 53
# https://www.home-assistant.io/integrations/input_number
input_number:
# Inverters nominal power, usually 400W, 500W, 1000W, etc
inverters_nominal_power:
name: Inverters Nominal Power
unit_of_measurement: W
min: 0
max: 2000
step: 50
mode: slider
# Manual control of the production limit of inverters
inverters_power_limit:
name: Inverters Power Limit
unit_of_measurement: W
min: 0
max: 500
step: 1
mode: slider
# Target excess or import to stay close to
inverters_excess_setpoint:
name: Inverters Excess Setpoint
unit_of_measurement: W
min: -2000
max: 2000
step: 100
mode: slider
# Target excess or import to stay close to, when 3ERL asks to limit the solar production
inverters_excess_setpoint_limiter:
name: Inverters Excess Setpoint With Limiter
unit_of_measurement: W
min: -1000
max: 1000
step: 100
mode: slider
# Total number of inverters. Inverters should be named Inverter 1, Inverter 2, etc
inverters_count:
name: Inverters Count
min: 0
max: 30
step: 1
mode: slider
# https://www.home-assistant.io/integrations/rest
rest:
# Get the 3ERL trend (https://3erl.fr) for 3ERL subscribers
- resource: https://3erl.fr/api.json
scan_interval: 60
binary_sensor:
- name: "3ERL: Bridage Demandé"
icon: "mdi:car-speed-limiter"
unique_id: 347A6F4D-6B09-4A20-9C2C-D611ED23EF4B
value_template: "{{ value_json['Bridage'] }}"
sensor:
- name: "3ERL: Tendance du jour"
icon: "mdi:trending-up"
unique_id: 31F1BED4-8100-44A4-88BA-DB45450611CF
# multiply by 10 because the value is in c€/kWh
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 %}
# Get the electricity market price trend from RTE
- 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Ă©: 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"
value_template: "{{ value_json['values'][0]['pre']['positive'] | float }}"
- name: "ÉlectricitĂ©: Prix de rĂšglement des Ă©carts nĂ©gatifs"
icon: "mdi:currency-eur"
unique_id: 95AE2165-7E9A-40BA-A555-1C7B7B93B26D
value_template: "{{ value_json['values'][0]['pre']['negative'] | float }}"
state_class: measurement
unit_of_measurement: "€/MWh"
mqtt:
# https://www.home-assistant.io/integrations/sensor.mqtt
sensor:
- name: Inverters YieldTotal
unique_id: D6A6659B-EE6A-4C3F-91F4-C0FBD46E8CF5
state_class: total_increasing
device_class: energy
unit_of_measurement: "kWh"
state_topic: "opendtu/ac/yieldtotal"
value_template: "{{ value|float }}"
# availability_topic: "opendtu/ac/is_valid"
# payload_available: "1"
# payload_not_available: "0"
- name: Inverters YieldDay
unique_id: "01e37eed-3045-4eee-a786-1249567fe310"
state_class: total_increasing
device_class: energy
unit_of_measurement: "kWh"
state_topic: "opendtu/ac/yieldday"
value_template: "{{ value|float / 1000.0 }}"
# availability_topic: "opendtu/ac/is_valid"
# payload_available: "1"
# payload_not_available: "0"
- name: Inverters Produced PowerDC
unique_id: "01e37eed-3045-4eee-a786-1249567fe316"
state_class: measurement
device_class: power
unit_of_measurement: W
state_topic: "opendtu/dc/power"
value_template: "{{ value|int }}"
availability_topic: "opendtu/dc/is_valid"
payload_available: "1"
payload_not_available: "0"
- name: Inverters Produced Power
unique_id: "01e37eed-3045-4eee-a786-1249567fe315"
state_class: measurement
device_class: power
unit_of_measurement: W
state_topic: "opendtu/ac/power"
value_template: "{{ value|int }}"
availability_topic: "opendtu/ac/is_valid"
payload_available: "1"
payload_not_available: "0"
# https://www.home-assistant.io/integrations/utility_meter/
utility_meter:
# Compute the daily yield of all inverters
inverters_energy_meter_daily:
name: Inverters Energy Meter Daily
unique_id: 4C4D8D06-C9D2-4408-B21A-1274A6E0F041
source: sensor.inverters_yieldday
cycle: daily
template:
# https://www.home-assistant.io/integrations/sensor/
- sensor:
- name: Inverters Energy
unique_id: 6E14EC86-0965-463E-BFBF-6008B61B56AF
state_class: total_increasing
device_class: energy
unit_of_measurement: "kWh"
state: "{{ [states('sensor.inverters_yieldtotal')|float(0), states('sensor.inverters_energy')|float(0) ] | max }}"
# Compute the quantity of power that is not produced when inverters are limited
- name: Inverters Lost Power
unique_id: B1C00B87-BC48-4801-ABF0-AC10ABF28B0B
state_class: measurement
device_class: power
unit_of_measurement: "W"
state: >-
{% set sum = namespace(value=0) %}
{% set count = states('input_number.inverters_count')|int(0) %}
{% for i in range(1, count + 1) %}
{% set p = states('sensor.inverter_' + i|string + '_power')|float(0) %}
{% set l = [0, [100, states('number.inverter_' + i|string + '_limit_nonpersistent_relative')|float(100)]|min]|max %}
{% set loss = 0 if l == 0 else p * (100 - l) / l %}
{% set sum.value = sum.value + loss %}
{% endfor %}
{{ sum.value }}
# Compute the quantity of power that inverters would produce
- name: Inverters Total Power
unique_id: BA5A10EE-CD10-4DF8-80AE-287D1CBAFD30
state_class: measurement
device_class: power
unit_of_measurement: "W"
state: >-
{% set sum = namespace(value=0) %}
{% set count = states('input_number.inverters_count')|int(0) %}
{% for i in range(1, count + 1) %}
{% set p = states('sensor.inverter_' + i|string + '_power')|float(0) %}
{% set l = [0, [100, states('number.inverter_' + i|string + '_limit_nonpersistent_relative')|float(100)]|min]|max %}
{% set total = 0 if l == 0 else p * 100 / l %}
{% set sum.value = sum.value + total %}
{% endfor %}
{{ sum.value }}
# Compute the number of inverters currently producing power
- name: Inverters Producing Count
unique_id: 7FAAECB4-2105-4F86-B63E-A1962F7FC81E
state: >-
{% set count = states('input_number.inverters_count')|int(0) %}
{{ range(1, count + 1)|map('regex_replace', '(\d+)', "sensor.inverter_\\1_power")|map('states')|map('is_number')|reject("false")|list|count }}
# https://www.home-assistant.io/docs/automation/
automation:
# Detect changes to "Inverters Power Limit" input and propagate it to imverters
- id: "0000000000038"
alias: "Inverters: Update Power Limit"
trigger:
- trigger: state
entity_id:
- input_number.inverters_power_limit
condition: []
action:
- action: number.set_value
data:
value: "{{[states.input_number.inverters_nominal_power.state|int, [0, states.input_number.inverters_power_limit.state|int]|max]|min}}"
target:
entity_id:
- number.inverter_1_limit_nonpersistent_absolute
- number.inverter_2_limit_nonpersistent_absolute
- number.inverter_3_limit_nonpersistent_absolute
- number.inverter_4_limit_nonpersistent_absolute
- number.inverter_5_limit_nonpersistent_absolute
- number.inverter_6_limit_nonpersistent_absolute
# Each 2 minutes, compute the new limit to set to inverters
- id: "0000000000039"
alias: "Inverters: Auto Update Power Limit"
trigger:
- trigger: time_pattern
minutes: /2
condition:
- condition: state
entity_id: binary_sensor.opendtu_status
state: "on"
- condition: template
value_template: |
{{['sensor.grid_power']|map('states')|map('is_number')|min}}
- condition: template
value_template: |
{% set count = states('input_number.inverters_count')|int(0) %}
{{ range(1, count + 1)|map('regex_replace', '(\d+)', "sensor.inverter_\\1_power")|map('states')|map('is_number')|reject("false")|list|count > 0 }}
action:
- variables:
new_limit: >-
{% set available = states('sensor.inverters_producing_count')|float(0) %}
{% set nominalPower = states('input_number.inverters_nominal_power')|float(0) %}
{% set setpointWithoutLimiter = states('input_number.inverters_excess_setpoint')|float(0) %}
{% set setpointWithLimiter = states('input_number.inverters_excess_setpoint_limiter')|float(0) %}
{% set limiterEnabled = states('binary_sensor.3erl_bridage_demande') == 'on' %}
{% set setpoint = setpointWithLimiter if limiterEnabled else setpointWithoutLimiter %}
{% set grid = states('sensor.grid_power')|float %}
{% set error = ((grid - setpoint) / available) | int if available > 0 else 0 %}
{{ [nominalPower, [10, states.input_number.inverters_power_limit.state|int + error]|max]|min }}
- action: input_number.set_value
data:
value: "{{ new_limit }}"
target:
entity_id:
- input_number.inverters_power_limit
# For 3ERL subscribers, activate or deactivate the automation to automatically limit the inverters when 3ERL asks for it
- id: "0000000000040"
alias: "Inverters: Auto Activate 3ERL Limit"
triggers:
- trigger: state
entity_id:
- binary_sensor.3erl_bridage_demande
- trigger: homeassistant
event: start
conditions: []
actions:
- if:
- condition: state
entity_id: binary_sensor.3erl_bridage_demande
state: "on"
then:
- action: automation.turn_on
target:
entity_id: automation.inverters_auto_update_power_limit
else:
- action: automation.turn_off
target:
entity_id: automation.inverters_auto_update_power_limit
- action: input_number.set_value
data:
value: "{{ states.input_number.inverters_nominal_power.state }}"
target:
entity_id: input_number.inverters_power_limit
# For those having OpenEVSE car charger, when vehicule is connected, automatically increase the excess so that the EV can start charging
- id: "0000000000041"
alias: "Inverters: Auto Update Setpoint"
triggers:
- trigger: state
entity_id:
- binary_sensor.openevse_vehicle_connected
- sensor.openevse_vehicle_battery_level
conditions: []
actions:
- 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: -600
target:
entity_id: input_number.inverters_excess_setpoint_limiter
else:
- action: input_number.set_value
metadata: {}
data:
value: -300
target:
entity_id: input_number.inverters_excess_setpoint_limiter
type: sections
max_columns: 3
title: Solaire
path: solar
icon: mdi:solar-panel-large
sections:
- type: grid
cards:
- type: custom:bar-card
title: Live Limit
direction: right
height: 25
positions:
icon: "off"
indicator: inside
name: inside
value: inside
entities:
- entity: number.inverter_1_limit_nonpersistent_absolute
name: "#1: 112184727305"
- entity: number.inverter_2_limit_nonpersistent_absolute
name: "#2: 112184727286"
- entity: number.inverter_3_limit_nonpersistent_absolute
name: "#3: 112183225593"
- entity: number.inverter_4_limit_nonpersistent_absolute
name: "#4: 112183226560"
- entity: number.inverter_5_limit_nonpersistent_absolute
name: "#5: 112183226985"
- entity: number.inverter_6_limit_nonpersistent_absolute
name: "#6: 112183219226"
min: 0
max: 400
- type: custom:bar-card
title: Live Power
direction: right
height: 25
positions:
icon: "off"
indicator: inside
name: inside
value: inside
entities:
- entity: sensor.inverter_1_power
name: "#1: 112184727305"
- entity: sensor.inverter_2_power
name: "#2: 112184727286"
- entity: sensor.inverter_3_power
name: "#3: 112183225593"
- entity: sensor.inverter_4_power
name: "#4: 112183226560"
- entity: sensor.inverter_5_power
name: "#5: 112183226985"
- entity: sensor.inverter_6_power
name: "#6: 112183219226"
min: 0
max: 400
- type: custom:bar-card
title: Live Energy
direction: right
height: 25px
positions:
icon: "off"
indicator: inside
name: inside
value: inside
entities:
- entity: sensor.inverter_1_yieldday
name: "#1: 112184727305"
- entity: sensor.inverter_2_yieldday
name: "#2: 112184727286"
- entity: sensor.inverter_3_yieldday
name: "#3: 112183225593"
- entity: sensor.inverter_4_yieldday
name: "#4: 112183226560"
- entity: sensor.inverter_5_yieldday
name: "#5: 112183226985"
- entity: sensor.inverter_6_yieldday
name: "#6: 112183219226"
min: 0
max: 2800
- type: custom:bar-card
title: Live Temperature
direction: right
height: 25px
positions:
icon: "off"
indicator: inside
name: inside
value: inside
entities:
- entity: sensor.inverter_1_temperature
name: "#1: 112184727305"
- entity: sensor.inverter_2_temperature
name: "#2: 112184727286"
- entity: sensor.inverter_3_temperature
name: "#3: 112183225593"
- entity: sensor.inverter_4_temperature
name: "#4: 112183226560"
- entity: sensor.inverter_5_temperature
name: "#5: 112183226985"
- entity: sensor.inverter_6_temperature
name: "#6: 112183219226"
min: 0
max: 80
- type: custom:config-template-card
variables:
- entity: sensor.inverter_1_yieldtotal
- entity: sensor.inverter_2_yieldtotal
- entity: sensor.inverter_3_yieldtotal
- entity: sensor.inverter_4_yieldtotal
- entity: sensor.inverter_5_yieldtotal
- entity: sensor.inverter_6_yieldtotal
entities:
- sensor.inverter_1_yieldtotal
- sensor.inverter_2_yieldtotal
- sensor.inverter_3_yieldtotal
- sensor.inverter_4_yieldtotal
- sensor.inverter_5_yieldtotal
- sensor.inverter_6_yieldtotal
element:
type: custom:bar-card
title: >-
${'Total Energy (' + Math.round(vars.map(v =>
states[v.entity].state).filter(v => v != 'unavailable').reduce((sum,
v) => sum + parseFloat(v), 0)) + ' kWh)' }
entities:
- entity: sensor.inverter_1_yieldtotal
name: "#1: 112184727305"
- entity: sensor.inverter_2_yieldtotal
name: "#2: 112184727286"
- entity: sensor.inverter_3_yieldtotal
name: "#3: 112183225593"
- entity: sensor.inverter_4_yieldtotal
name: "#4: 112183226560"
- entity: sensor.inverter_5_yieldtotal
name: "#5: 112183226985"
- entity: sensor.inverter_6_yieldtotal
name: "#6: 112183219226"
direction: right
height: 25px
positions:
icon: "off"
indicator: inside
name: inside
value: inside
min: 0
max: >-
${ Math.max(...vars.map(v => states[v.entity].state).filter(v => v
!= 'unavailable'))}
- type: grid
cards:
- type: horizontal-stack
cards:
- type: custom:plotly-graph
title: PRE
refresh_interval: auto
hours_to_show: 12h
defaults:
entity:
connectgaps: true
line:
shape: spline
layout:
yaxis9:
visible: false
fixedrange: true
entities:
- entity: sensor.electricite_prix_de_reglement_des_ecarts_negatifs
name: PRE-
- entity: sensor.electricite_prix_de_reglement_des_ecarts_positifs
name: PRE+
- entity: binary_sensor.3erl_bridage_demande
name: Bridage
showlegend: true
yaxis: y9
filters:
- map_y: "y === 'on' ? 1 : 0"
fill: tozeroy
line:
color: grey
shape: hv
connectgaps: false
width: 0
grid_options:
columns: full
- type: horizontal-stack
cards:
- type: custom:plotly-graph
title: Limits
refresh_interval: 10
hours_to_show: 12h
entities:
- entity: number.inverter_1_limit_persistent_absolute
name: "#1"
- entity: number.inverter_2_limit_persistent_absolute
name: "#2"
- entity: number.inverter_3_limit_persistent_absolute
name: "#3"
- entity: number.inverter_4_limit_persistent_absolute
name: "#4"
- entity: number.inverter_5_limit_persistent_absolute
name: "#5"
- entity: number.inverter_6_limit_persistent_absolute
name: "#6"
grid_options:
columns: full
- type: horizontal-stack
cards:
- type: custom:plotly-graph
title: Inverter Powers
refresh_interval: 10
hours_to_show: 12h
entities:
- entity: sensor.inverter_1_power
name: "#1"
- entity: sensor.inverter_2_power
name: "#2"
- entity: sensor.inverter_3_power
name: "#3"
- entity: sensor.inverter_4_power
name: "#4"
- entity: sensor.inverter_5_power
name: "#5"
- entity: sensor.inverter_6_power
name: "#6"
grid_options:
columns: full
- type: horizontal-stack
cards:
- type: custom:plotly-graph
title: Energy
refresh_interval: 5m
hours_to_show: 12h
layout:
barmode: relative
xaxis:
rangeselector:
"y": 1.2
buttons:
- count: 12
step: hour
- count: 1
step: day
- count: 7
step: day
defaults:
entity:
statistic: sum
type: bar
unit_of_measurement: Wh
period: auto
entities:
- entity: sensor.inverters_energy_meter_daily
name: Solar
marker:
color: "#ff8c00"
filters:
- multiply: 1000
- delta
- entity: sensor.grid_energy
name: Grid
marker:
color: "#0000FF"
filters:
- multiply: 1000
- delta
- entity: sensor.home_consumed_energy
name: Consumption
marker:
color: "#A52A2A"
filters:
- multiply: -1000
- delta
- entity: sensor.grid_energy_returned
name: Excess
marker:
color: "#FFFF00"
filters:
- multiply: -1000
- delta
- entity: sensor.openevse_energy
name: OpenEVSE
type: line
line:
color: "#00FF00"
width: 1
filters:
- multiply: 1000
- delta
grid_options:
columns: full
- type: horizontal-stack
cards:
- type: custom:plotly-graph
title: Energy
refresh_interval: 5m
hours_to_show: 2d
layout:
barmode: relative
xaxis:
rangeselector:
"y": 1.2
buttons:
- count: 2
step: day
- count: 7
step: day
defaults:
entity:
statistic: sum
type: bar
unit_of_measurement: kWh
period: hour
entities:
- entity: sensor.inverters_energy_meter_daily
name: Solar
marker:
color: "#ff8c00"
filters:
- multiply: 1
- delta
- entity: sensor.grid_energy
name: Grid
marker:
color: "#0000FF"
filters:
- multiply: 1
- delta
- entity: sensor.home_consumed_energy
name: Consumption
marker:
color: "#A52A2A"
filters:
- multiply: -1
- delta
- entity: sensor.grid_energy_returned
name: Excess
marker:
color: "#FFFF00"
filters:
- multiply: -1
- delta
- entity: sensor.openevse_energy
name: OpenEVSE
type: line
line:
color: "#00FF00"
width: 1
filters:
- multiply: 1
- delta
grid_options:
columns: full
- type: horizontal-stack
cards:
- type: custom:plotly-graph
title: Inverter Temperatures
refresh_interval: 10
hours_to_show: 12h
entities:
- entity: sensor.inverter_1_temperature
name: "#1"
- entity: sensor.inverter_2_temperature
name: "#2"
- entity: sensor.inverter_3_temperature
name: "#3"
- entity: sensor.inverter_4_temperature
name: "#4"
- entity: sensor.inverter_5_temperature
name: "#5"
- entity: sensor.inverter_6_temperature
name: "#6"
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_nominal_power
name: Nominal
- type: entity
show_name: true
show_state: true
show_icon: true
entity: sensor.inverters_energy_meter_daily
name: Today
- type: entity
show_name: true
show_state: true
show_icon: true
entity: sensor.inverters_energy
name: Lifetime
icon: mdi:counter
- type: entity
show_name: true
show_state: true
show_icon: true
entity: sensor.3erl_tendance_du_jour
name: Trend
- type: entity
show_name: true
show_state: false
show_icon: true
entity: binary_sensor.3erl_bridage_demande
name: 3ERL Limit
- type: entity
show_name: true
show_state: false
show_icon: true
entity: automation.inverters_auto_update_power_limit
name: Auto Limiter
icon: mdi:car-speed-limiter
tap_action:
action: toggle
- type: entity
show_name: true
show_state: true
show_icon: true
entity: input_number.inverters_excess_setpoint
icon: mdi:bullseye-arrow
name: Setpoint
visibility:
- condition: state
entity: automation.inverters_auto_update_power_limit
state: "off"
- type: entity
show_name: true
show_state: true
show_icon: true
entity: input_number.inverters_excess_setpoint_limiter
icon: mdi:bullseye-arrow
name: Setpoint
visibility:
- condition: state
entity: automation.inverters_auto_update_power_limit
state: "on"
- type: entity
show_name: true
show_state: true
show_icon: true
entity: input_number.inverters_power_limit
icon: ""
name: Limit
- type: entity
show_name: true
show_state: true
show_icon: true
entity: sensor.inverters_producing_count
name: Producing
- type: entity
show_name: true
show_state: true
show_icon: true
entity: sensor.inverters_produced_power
name: Produced Power
visibility:
- condition: numeric_state
entity: sensor.inverters_producing_count
above: 0
- type: entity
show_name: true
show_state: true
show_icon: true
entity: sensor.inverters_lost_power
name: Lost Power
visibility:
- condition: numeric_state
entity: sensor.inverters_producing_count
above: 0
- type: entity
show_name: true
show_state: true
show_icon: true
entity: sensor.inverters_total_power
name: Total Power
visibility:
- condition: numeric_state
entity: sensor.inverters_producing_count
above: 0
@mathieucarbou
Copy link
Author

  • Bridage up to 14h00
  • 12h00: VE goes out => limiter auto-limit production to lower export
  • 13h00: VE goes back to charge => limiter update production

Screenshot 2025-0
3-09 at 18 28 19

@Mancier34
Copy link

Mancier34 commented May 1, 2025

Salut ! Vraiment trĂšs intĂ©ressante cette crĂ©ation ! Ayant actuellement 3,5kWc d’onduleurs hoymiles, un openDTU que j’ai confectionnĂ©, un home assistant sur un nuc, ainsi qu’un routeur solaire, je me heurt dĂ©sormais Ă  un petit soucis. Avec les beaux jours je me retrouve Ă  faire pas mal d’injection sur le rĂ©seau

Ta solution me semble parfaite dans mon cas mais pas simple à mettre en place, aurais-tu un " tuto " pas à pas pour faire la mise en place sur HA ? Ou encore mieux une vidéo YouTube ?
il faut copier / coller le fichier " opendtu.yaml " dans le fichier " configuration.yaml " de mon home assistant ? ( bien sûr en mettant à jour les différents sensors )
merci par avance de ton aide

@Mancier34
Copy link

Pas si simple que cela pour un novice en automatisation pour mettre la solution en place. Un petit coup de pouce ne serait pas de trop 😅

@T4rb6
Copy link

T4rb6 commented May 5, 2025

Meme un peu d'aide ne serait pas de refus j'ai tous mis dans config package comme explique plus bas dans le gith mais ca fonctionne pas

@mathieucarbou
Copy link
Author

mathieucarbou commented May 5, 2025

Les packages sont un concept HA pour séparer la config en modules:

image image

Il suffit de mettre en place pour ensuite isoler ses modules dans un dossier packages.

Voir: https://www.home-assistant.io/docs/configuration/packages/#create-a-packages-folder => "Create a packages folder "

@T4rb6
Copy link

T4rb6 commented May 6, 2025

ok merci
j'avais déjà crée la ligne packages dans configuration.yaml
opendtu.yaml se charge je pense car j'ai les capteurs qui se sont crée dans l'aperçu général (non fonctionnel pour la plupart car je n'ai pas modifie leurs id dans votre script)
par contre view.yaml et opendtu_3erl.yaml ne se charge pas ou je ne sait pas par ou y accéder
j'ai la vérifié les .yaml dans outils de développement HA ne trouve pas d'erreur ...

@T4rb6
Copy link

T4rb6 commented May 6, 2025

je vois dans votre copie d'ecran que vous n'avez pas view.yaml dans le dossier package. Il doit se placer ailleurs ?

@mathieucarbou
Copy link
Author

view.yaml c'est le yaml de la vue dashboard: quand on crée une section du dashboard, on peut aller voir son code yaml dans les options. C est ce yaml là.

@T4rb6
Copy link

T4rb6 commented May 6, 2025

ok j'ai crée un Dashboard supplémentaire view
mais quand je copie colle votre code dans l'editeur de configuration j'ai cette erreur a l'enregistrement ....
"Votre configuration n'est pas valide : r: At path: views -- Expected an array value, but received: undefined"....

@mathieucarbou
Copy link
Author

I have updated the gist.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment