If interested, it works in combination with the automation. Iām passing the parameters from there.
It looks scary but actually itās not.
BEWARE: you have to create the automation in a dedicated file YAML, otherwise itās not going to work (my experience at least).
When changing something you just reload the automations.
- id: 'mpc_optim_rolling_window'
alias: "mpc_optim_rolling_window"
description: "mpc_optim_rolling_window"
trigger:
- platform: time_pattern
minutes: /30
condition: []
action:
- service: rest_command.emhass_publish_data #publishing latest available data, useful if EMHASS can't run for any reason but I have data from previous executions I can use in the meantime
data:
publish_prefix: ''
- service: homeassistant.update_entity
data: {}
target:
entity_id:
- sensor.forecast_solar_estimate_watts
- sensor.forecast_solar_estimate_watt_hours_period
- sensor.forecast_solar_estimate_watt_hours
- sensor.forecast_solar_estimate_watt_hours_day
- sensor.forecast_solar_estimate_message
# The integration takes too long to automatically reload and the first hour after a change to/from a bank holiday usually shows wrong cost values
- binary_sensor.giorno_lavorativo
- binary_sensor.giorno_festivo
- service: rest_command.emhass_mpc_optim
data:
num_def_loads: 1 #if you don't have any it's still better to set this to something and then set the power to 0
P_deferrable_nom: [0]
def_total_hours: [1] #if you don't have any it's still better to set this to something and then set the power to 0
treat_def_as_semi_cont: [1]
set_def_constant: [0]
def_start_timestep: [0]
def_end_timestep: [0]
alpha: 0.25
beta: 0.75
model_type: 'KNN' # this parameter is ignored unless you use mlforecaster in the config file
soc_init: >-
{{ (states('sensor.sonnen_usoc_filtered')|float(0)) / 100 }}
soc_final: 0.3
prediction_horizon: >-
{# this is almost the same code to calculate "load_cost_forecast"/"prod_price_forecast" - I use it to be sure to get the right number of items in the list, till the end of the day #}
{% set ns_load_cost_forecast_size = namespace(load_cost_forecast_size = 0) %}
{% for item in states.sensor|selectattr('entity_id', 'search', 'pun_oggi_')|sort(attribute='entity_id', reverse= false )|map(attribute='entity_id')|list %}
{% if (now().time()) <= strptime(state_attr(item,'end'),'%H:%M:%S').time() %} {# I'm using start so the retrieved number is for the next hours, with end the current one is included as well. It works in combination with "latest" timestamp rounding of EMHASS and coputation triggered before the hour, with end you could keep "first" and computation at the hour.#}
{#% set ns_load_cost_forecast.load_cost_forecast = ns_load_cost_forecast.load_cost_forecast + [item] %#} {# this is for debugging and check which sensors I'm using in the loop - (un)comment as needed #}
{% set ns_load_cost_forecast_size.load_cost_forecast_size = ns_load_cost_forecast_size.load_cost_forecast_size + 1 %} {# this is for 24h forecasts with 1h resolution #}
{% endif %}
{% if (now().time()) <= strptime(state_attr(item,'end')|replace(":59:", ":29:"),'%H:%M:%S').time() %} {# I'm using start so the retrieved number is for the next hours, with end the current one is included as well. It works in combination with "latest" timestamp rounding of EMHASS and coputation triggered before the hour, with end you could keep "first" and computation at the hour. If you use 'end' you also have to replace :59:, instead of :00:, with :29:#}
{% set ns_load_cost_forecast_size.load_cost_forecast_size = ns_load_cost_forecast_size.load_cost_forecast_size + 1 %} {# this is for 24h forecasts with 30min resolution #}
{% endif %}
{% endfor %}
{% for item in states.sensor|selectattr('entity_id', 'search', 'pun_domani_')|sort(attribute='entity_id', reverse= false )|map(attribute='entity_id')|list %}
{% if (now().time()) >= strptime(state_attr(item,'end'),'%H:%M:%S').time() %} {# I'm using start so the retrieved number is for the next hours, with end the current one is included as well. It works in combination with "latest" timestamp rounding of EMHASS and coputation triggered before the hour, with end you could keep "first" and computation at the hour.#}
{#% set ns_load_cost_forecast.load_cost_forecast = ns_load_cost_forecast.load_cost_forecast + [item] %#} {# this is for debugging and check which sensors I'm using in the loop - (un)comment as needed #}
{% set ns_load_cost_forecast_size.load_cost_forecast_size = ns_load_cost_forecast_size.load_cost_forecast_size + 1 %} {# this is for 24h forecasts with 1h resolution #}
{% endif %}
{% if (now().time()) >= strptime(state_attr(item,'end')|replace(":59:", ":29:"),'%H:%M:%S').time() %} {# I'm using start so the retrieved number is for the next hours, with end the current one is included as well. It works in combination with "latest" timestamp rounding of EMHASS and coputation triggered before the hour, with end you could keep "first" and computation at the hour. If you use 'end' you also have to replace :59:, instead of :00:, with :29:#}
{% set ns_load_cost_forecast_size.load_cost_forecast_size = ns_load_cost_forecast_size.load_cost_forecast_size + 1 %} {# this is for 24h forecasts with 30min resolution #}
{% endif %}
{% endfor %}
{{ ns_load_cost_forecast_size.load_cost_forecast_size }}
pv_power_forecast: >-
{% set ns_production_forecast2days = namespace(production_forecast2days = []) %}
{% for i in range (0,48) %} {# 48 elements are the max covered by the free Forecast.solar - 2 days @ 1h resolution #}
{% for item in state_attr('sensor.forecast_solar_estimate_watts','watts').items() %}
{% if item[0] == (as_timestamp(now().strftime('%Y-%m-%d 00:00:00')) + (i*3600))| timestamp_custom("%Y-%m-%d %H:%M:00", True) %}
{% set ns_production_forecast2days.production_forecast2days = ns_production_forecast2days.production_forecast2days + [item[1]] %}
{% endif %}
{% endfor %}
{% if ns_production_forecast2days.production_forecast2days|length == i %}
{% set ns_production_forecast2days.production_forecast2days = ns_production_forecast2days.production_forecast2days + [0] %}
{% endif %}
{% endfor %}
{% set ns_production_forecast48 = namespace(production_forecast48 = []) %}
{% for i in range(0,(ns_production_forecast2days.production_forecast2days|length)*2) %}
{% if not(i%2) %}
{% set ns_production_forecast48.production_forecast48 = ns_production_forecast48.production_forecast48 + [(ns_production_forecast2days.production_forecast2days[(i/2)|int])] %}
{% else %}
{% set ns_production_forecast48.production_forecast48 = ns_production_forecast48.production_forecast48 +
[
(
(
(ns_production_forecast2days.production_forecast2days[(((i-1)/2)|round(0,'floor'))])
+
(ns_production_forecast2days.production_forecast2days[(i/2)|round(0,'ceil')])|default((ns_production_forecast2days.production_forecast2days[(((i-1)/2)|round(0,'floor'))]))
)/2
)|round
]
%}
{%endif %}
{% endfor %}
{{ ns_production_forecast48.production_forecast48[(((now().hour * 60 + now().minute)/30)|round(0,'floor')+0):(((now().hour * 60 + now().minute)/30)|round(0,'floor')+0)+48] }} {# +1 if I want to start with the next time slot, +0 if I want to start with the current one #}
load_cost_forecast: >-
{% set ns_load_cost_forecast = namespace(load_cost_forecast=[]) %}
{% for item in states.sensor|selectattr('entity_id', 'search', 'pun_oggi_')|sort(attribute='entity_id', reverse= false )|map(attribute='entity_id')|list %}
{% if (now().time()) <= strptime(state_attr(item,'end'),'%H:%M:%S').time() %} {# I'm using start so the retrieved number is for the next hours, with end the current one is included as well. It works in combination with "latest" timestamp rounding of EMHASS and coputation triggered before the hour, with end you could keep "first" and computation at the hour.#}
{#% set ns_load_cost_forecast.load_cost_forecast = ns_load_cost_forecast.load_cost_forecast + [item] %#} {# this is for debugging and check which sensors I'm using in the loop - (un)comment as needed #}
{% set ns_load_cost_forecast.load_cost_forecast = ns_load_cost_forecast.load_cost_forecast +
[(
(states('input_number.switch_prezzo_fisso_pun')|float)
*
(
(states(item)|float)
*
( 1 + ( states('input_number.lambda_fattore_correzione_fornitura_energia')|float ) )
)
+
(states('input_number.corrispettivo_fornitura_energia')|float)
)|round(6)] %} {# this is for 24h forecasts with 1h resolution #}
{% endif %}
{% if (now().time()) <= strptime(state_attr(item,'end')|replace(":59:", ":29:"),'%H:%M:%S').time() %} {# I'm using start so the retrieved number is for the next hours, with end the current one is included as well. It works in combination with "latest" timestamp rounding of EMHASS and coputation triggered before the hour, with end you could keep "first" and computation at the hour. If you use 'end' you also have to replace :59:, instead of :00:, with :29:#}
{#% set ns_load_cost_forecast.load_cost_forecast = ns_load_cost_forecast.load_cost_forecast + [item] %#} {# this is for debugging and check which sensors I'm using in the loop - (un)comment as needed #}
{% set ns_load_cost_forecast.load_cost_forecast = ns_load_cost_forecast.load_cost_forecast +
[(
(states('input_number.switch_prezzo_fisso_pun')|float)
*
(
(states(item)|float)
*
( 1 + ( states('input_number.lambda_fattore_correzione_fornitura_energia')|float ) )
)
+
(states('input_number.corrispettivo_fornitura_energia')|float)
)|round(6)] %} {# this is for 24h forecasts with 30min resolution #}
{% endif %}
{% endfor %}
{% for item in states.sensor|selectattr('entity_id', 'search', 'pun_domani_')|sort(attribute='entity_id', reverse= false )|map(attribute='entity_id')|list %}
{% if (now().time()) >= strptime(state_attr(item,'end'),'%H:%M:%S').time() %} {# I'm using start so the retrieved number is for the next hours, with end the current one is included as well. It works in combination with "latest" timestamp rounding of EMHASS and coputation triggered before the hour, with end you could keep "first" and computation at the hour.#}
{#% set ns_load_cost_forecast.load_cost_forecast = ns_load_cost_forecast.load_cost_forecast + [item] %#} {# this is for debugging and check which sensors I'm using in the loop - (un)comment as needed #}
{% set ns_load_cost_forecast.load_cost_forecast = ns_load_cost_forecast.load_cost_forecast +
[(
(states('input_number.switch_prezzo_fisso_pun')|float)
*
(
(states(item)|float)
*
( 1 + ( states('input_number.lambda_fattore_correzione_fornitura_energia')|float ) )
)
+
(states('input_number.corrispettivo_fornitura_energia')|float)
)|round(6)] %} {# this is for 24h forecasts with 1h resolution #}
{% endif %}
{% if (now().time()) >= strptime(state_attr(item,'end')|replace(":59:", ":29:"),'%H:%M:%S').time() %} {# I'm using start so the retrieved number is for the next hours, with end the current one is included as well. It works in combination with "latest" timestamp rounding of EMHASS and coputation triggered before the hour, with end you could keep "first" and computation at the hour. If you use 'end' you also have to replace :59:, instead of :00:, with :29:#}
{#% set ns_load_cost_forecast.load_cost_forecast = ns_load_cost_forecast.load_cost_forecast + [item] %#} {# this is for debugging and check which sensors I'm using in the loop - (un)comment as needed #}
{% set ns_load_cost_forecast.load_cost_forecast = ns_load_cost_forecast.load_cost_forecast +
[(
(states('input_number.switch_prezzo_fisso_pun')|float)
*
(
(states(item)|float)
*
( 1 + ( states('input_number.lambda_fattore_correzione_fornitura_energia')|float ) )
)
+
(states('input_number.corrispettivo_fornitura_energia')|float)
)|round(6)] %} {# this is for 24h forecasts with 30min resolution #}
{% endif %}
{% endfor %}
{{ ns_load_cost_forecast.load_cost_forecast }}
prod_price_forecast: >
{% set ns_prod_price_forecast = namespace(prod_price_forecast=[]) %}
{% for item in states.sensor|selectattr('entity_id', 'search', 'prezzo_zonale_oggi_')|sort(attribute='entity_id', reverse= false )|map(attribute='entity_id')|list %}
{% if (now().time()) <= strptime(state_attr(item,'end'),'%H:%M:%S').time() %} {# I'm using start so the retrieved number is for the next hours, with end the current one is included as well. It works in combination with "latest" timestamp rounding of EMHASS and coputation triggered before the hour, with end you could keep "first" and computation at the hour.#}
{#% set ns_prod_price_forecast.prod_price_forecast = ns_prod_price_forecast.prod_price_forecast + [item] %#} {# this is for debugging and check which sensors I'm using in the loop - (un)comment as needed #}
{% set ns_prod_price_forecast.prod_price_forecast = ns_prod_price_forecast.prod_price_forecast +
[(
max((states(item)|float),0)
*
(states('input_number.coefficiente_di_perdita_rete_rid')|float)
)|round(6)] %} {# this is for 24h forecasts with 1h resolution #}
{% endif %}
{% if (now().time()) <= strptime(state_attr(item,'end')|replace(":59:", ":29:"),'%H:%M:%S').time() %} {# I'm using start so the retrieved number is for the next hours, with end the current one is included as well. It works in combination with "latest" timestamp rounding of EMHASS and coputation triggered before the hour, with end you could keep "first" and computation at the hour. If you use 'end' you also have to replace :59:, instead of :00:, with :29:#}
{#% set ns_prod_price_forecast.prod_price_forecast = ns_prod_price_forecast.prod_price_forecast + [item] %#} {# this is for debugging and check which sensors I'm using in the loop - (un)comment as needed #}
{% set ns_prod_price_forecast.prod_price_forecast = ns_prod_price_forecast.prod_price_forecast +
[(
max((states(item)|float),0)
*
(states('input_number.coefficiente_di_perdita_rete_rid')|float)
)|round(6)] %} {# this is for 24h forecasts with 30min resolution #}
{% endif %}
{% endfor %}
{% for item in states.sensor|selectattr('entity_id', 'search', 'prezzo_zonale_domani_')|sort(attribute='entity_id', reverse= false )|map(attribute='entity_id')|list %}
{% if (now().time()) >= strptime(state_attr(item,'end'),'%H:%M:%S').time() %} {# I'm using start so the retrieved number is for the next hours, with end the current one is included as well. It works in combination with "latest" timestamp rounding of EMHASS and coputation triggered before the hour, with end you could keep "first" and computation at the hour.#}
{#% set ns_prod_price_forecast.prod_price_forecast = ns_prod_price_forecast.prod_price_forecast + [item] %#} {# this is for debugging and check which sensors I'm using in the loop - (un)comment as needed #}
{% set ns_prod_price_forecast.prod_price_forecast = ns_prod_price_forecast.prod_price_forecast +
[(
max((states(item)|float),0)
*
(states('input_number.coefficiente_di_perdita_rete_rid')|float)
)|round(6)] %} {# this is for 24h forecasts with 1h resolution #}
{% endif %}
{% if (now().time()) >= strptime(state_attr(item,'end')|replace(":59:", ":29:"),'%H:%M:%S').time() %} {# I'm using start so the retrieved number is for the next hours, with end the current one is included as well. It works in combination with "latest" timestamp rounding of EMHASS and coputation triggered before the hour, with end you could keep "first" and computation at the hour. If you use 'end' you also have to replace :59:, instead of :00:, with :29:#}
{#% set ns_prod_price_forecast.prod_price_forecast = ns_prod_price_forecast.prod_price_forecast + [item] %#} {# this is for debugging and check which sensors I'm using in the loop - (un)comment as needed #}
{% set ns_prod_price_forecast.prod_price_forecast = ns_prod_price_forecast.prod_price_forecast +
[(
max((states(item)|float),0)
*
(states('input_number.coefficiente_di_perdita_rete_rid')|float)
)|round(6)] %} {# this is for 24h forecasts with 30min resolution #}
{% endif %}
{% endfor %}
{{ ns_prod_price_forecast.prod_price_forecast }}
- service: rest_command.emhass_publish_data
data:
publish_prefix: ''
mode: restart