When I change back to “Naive”, it is fine again (only on 0.5.3.)
Question: is EMHASS capable of working with forecasts that go beyond 24h from now?
Context:
In Belgium, the day-ahead market prices are published around 14h on day D-1. From that point on, I have all price information until end of the next day (day D), so I could envision to optimize a time window of max 34h:
I tried to run a naive MPC optimization, providing all required input timeseries as runtime parameters:
Note: I use 30min timesteps, which explains why prediction horizon is that long.
This is taken at 20h50 on day D-1, so there are 55 remaining half hours until end of day D. For each of these half hours, I provided price and power inputs.
Running the naive MPC optimization results in following output:
2024-01-04 20:38:58,064 - web_server - INFO - Setting up needed data
2024-01-04 20:38:58,069 - web_server - INFO - Retrieve hass get data method initiated…
2024-01-04 20:39:55,330 - web_server - INFO - Retrieving weather forecast data using method = list
2024-01-04 20:39:55,341 - web_server - ERROR - Exception on /action/naive-mpc-optim [POST]
Traceback (most recent call last):
File “/usr/local/lib/python3.11/dist-packages/flask/app.py”, line 1455, in wsgi_app
response = self.full_dispatch_request()File “/usr/local/lib/python3.11/dist-packages/flask/app.py”, line 869, in full_dispatch_request
rv = self.handle_user_exception(e)File “/usr/local/lib/python3.11/dist-packages/flask/app.py”, line 867, in full_dispatch_request
rv = self.dispatch_request()File “/usr/local/lib/python3.11/dist-packages/flask/app.py”, line 852, in dispatch_request
return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)File “/usr/local/lib/python3.11/dist-packages/emhass/web_server.py”, line 181, in action_call
input_data_dict = set_input_data_dict(config_path, str(data_path), costfun,File “/usr/local/lib/python3.11/dist-packages/emhass/command_line.py”, line 127, in set_input_data_dict
df_input_data_dayahead = copy.deepcopy(df_input_data_dayahead
[df_input_data_dayahead.index[0]:df_input_data_dayahead.index[prediction_horizon-1]]File “/usr/local/lib/python3.11/dist-packages/pandas/core/indexes/base.py”, line 5175, in getitem
return getitem(key)File “/usr/local/lib/python3.11/dist-packages/pandas/core/arrays/datetimelike.py”, line 370, in getitem
“Union[DatetimeLikeArrayT, DTScalarOrNaT]”, super().getitem(key)File “/usr/local/lib/python3.11/dist-packages/pandas/core/arrays/_mixins.py”, line 272, in getitem
result = self._ndarray[key]IndexError: index 54 is out of bounds for axis 0 with size 48
It seems that the dataframe “df_input_data_dayahead” only has a size of 48, even though the provided input timeseries for load and PV power forecast were sufficiently long for the prediction_horizon of 55.
Why doesn’t the optimizer accept prediction horizons longer than 24 hours?
Mine is ok again. I changed the new charges option from 1 to 0 and that solved it. Dont have time for further tweaking today but suspect this triggered the weird behavior.
Am on 2024.01 and emhass 5.4
I believe you can run the day-ahead optimisation with more than 24 hours (48 entries), but the MPC is limited to 48 entries.
So in your case, I would suggest when you receive the full 34 hour forecast run the day-ahead optimisation with your full data and then run your MPC optimisation with a shorter time frame.
My half hour prices (Amber Electric) are updated every 5 minutes, are your half hour prices updated after the initial publication?
Another strategy you may want to try (if not already doing - I am) in addition to Marks’s suggestion is to run MPC on a rolling 48-timestamps window.
David,
What value EMHASS assign to PV that top’s up battery?
I am trying to establish why EMHASS trying to trade power at loss. It seem to purchase at higher price than selling back to grid. Charge/Discharge Weights set to +0.1
Thanks. Great work. I think that fixed it.
Now I can get back to figuring out how to load my peak and low tariff hours.
I have trouble understanding how to do it.
Indeed that fixed it.
I don’t understand this weight.
If I try to understand, it adds 1 unit/kwh for the costs.
So if my electricity price is 0.25 euro/kwh, it will make it 1.25 euro/kwh? Or is for each cycle.
But then if it is as pre-configured 1 and 1, it should not start to charge and discharge all the time. Or does it has to be negative values?
I added
"curl -i -H \"Content-Type:application/json\" -X POST -d '{\"set_def_constant\":[true, true], \"load_cost_forecast\":[{{(
([states('sensor.energy_buy_price')|float(0)] +
state_attr('sensor.energy_buy_price', 'forecasts') |map(attribute='per_kwh')|list)[:24])
}}]}' http://localhost:5000/action/dayahead-optim"
to the config and wanted to adapt the sensor.energy_buy_price to
- platform: template
sensors:
energy_buy_price:
friendly_name: "Energy buy price"
unit_of_measurement: "€"
value_template: >-
{% set weekdays = [0, 1, 2, 3, 4] %}
{% set entry1_to_7 = [0.1777] * 7 %}
{% set entry8_to_23 = [0.2162] * 16 %}
{% set entry24 = [0.1777] * 1 %}
{% if now().weekday() in weekdays %}
{% if now().hour < 8 %}
{{ entry1_to_7 }}
{% elif now().hour > 22 %}
{{ entry24 }}
{% else %}
{{ entry1_to_7 + entry8_to_23 }}
{% endif %}
{% else %}
{{ [0.1777] * 24 }}
{% endif %}
But that doesn’t work. What am I doing wrong? In the development section this seems to work but the sensor doesn’t return a list if I implement it.
I am at an equal point… still trying to figure this out!
You are trying to create a sensor that is meant to hold a single value as state but actually you are trying to make it contain a list, which is not intended for. And in any case there is a strict limit on the amount of characters a sensor state can contain, which will soon make this approach fail.
In the previous examples people were mapping the information contained in the attributes, from a sensor that actually contained it.
You can’t copy-paste the same code and just change the name of the sensor as it will not work.
What you could do is to create a sensor that contains the current cost and in the attributes the forecast if this is the approach you want to take.
I whish I’ld understand what you mean by this.
What you could do is to create a sensor that contains the current cost and in the attributes the forecast if this is the approach you want to take.
I had this sensor but I don’t know how to get the data into a list for emhass.
- platform: template
sensors:
energy_buy_price:
friendly_name: "Energy buy price"
unit_of_measurement: "€"
value_template: >
{% if states('sensor.electricity_meter_active_tariff')|string == 'low' %}
0.1777
{% else %}
0.2162
{% endif %}
Dear all,
I am testing EMHASS as an add-on to HA and I am seeing some weird behaviour of my battery. It looks like it’s charging although I am having almost no production from my PV here in dark Europe these days. If there is some production this is instantly consumed by the current home loads I have active.
Below are extracts from my config file showing the battery parameters and some graphs of the result of todays dah ahead optimisation.
“hass_url”: “empty”,
“long_lived_token”: “empty”,
“costfun”: “cost”,
“logging_level”: “DEBUG”,
“optimization_time_step”: 60,
“historic_days_to_retrieve”: 2,
“method_ts_round”: “nearest”,
“set_total_pv_sell”: false,
“lp_solver”: “COIN_CMD”,
“lp_solver_path”: “/usr/bin/cbc”,
“set_nocharge_from_grid”: true,
“set_nodischarge_to_grid”: true,
“set_battery_dynamic”: false,
“battery_dynamic_max”: 0.9,
“battery_dynamic_min”: -0.9,
“weight_battery_discharge”: 1.0,
“weight_battery_charge”: 1.0,
“load_forecast_method”: “naive”,
….
“set_use_battery”: true,
“battery_discharge_power_max”: 3840,
“battery_charge_power_max”: 3840,
“battery_discharge_efficiency”: 0.95,
“battery_charge_efficiency”: 0.95,
“battery_nominal_energy_capacity”: 10515,
“battery_minimum_state_of_charge”: 0.05,
“battery_maximum_state_of_charge”: 1.0,
“battery_target_state_of_charge”: 0.05
ts | P_PV | P_Load | P_deferrable0 | P_deferrable1 | P_grid_pos | P_grid_neg | P_grid | P_batt | SOC_opt | unit_load_cost | unit_prod_price | cost_profit | cost_fun_cost | optim_status |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
2024-01-06 00:00:00+01:00 | 0 | 1656.0 | 0.0 | 0.0 | 1656.0 | 0.0 | 1656.0 | 0.0 | 0.05 | 0.21 | 0.09 | -0.34 | -0.34 | Optimal |
2024-01-06 01:00:00+01:00 | 0 | 1765.0 | 0.0 | 0.0 | 1765.0 | 0.0 | 1765.0 | 0.0 | 0.05 | 0.20 | 0.08 | -0.36 | -0.36 | Optimal |
2024-01-06 02:00:00+01:00 | 0 | 1716.0 | 0.0 | 0.0 | 1716.0 | 0.0 | 1716.0 | 0.0 | 0.05 | 0.20 | 0.08 | -0.34 | -0.34 | Optimal |
2024-01-06 03:00:00+01:00 | 0 | 1737.0 | 0.0 | 0.0 | 1737.0 | 0.0 | 1737.0 | 0.0 | 0.05 | 0.20 | 0.08 | -0.34 | -0.34 | Optimal |
2024-01-06 04:00:00+01:00 | 0 | 1666.0 | 2300.0 | 700.0 | 4666.0 | 0.0 | 4666.0 | 0.0 | 0.05 | 0.19 | 0.07 | -0.90 | -0.90 | Optimal |
2024-01-06 05:00:00+01:00 | 0 | 1705.0 | 2300.0 | 700.0 | 4705.0 | 0.0 | 4705.0 | 0.0 | 0.05 | 0.19 | 0.07 | -0.91 | -0.91 | Optimal |
2024-01-06 06:00:00+01:00 | 0 | 1701.0 | 2300.0 | 0.0 | 4001.0 | 0.0 | 4001.0 | 0.0 | 0.05 | 0.19 | 0.07 | -0.78 | -0.78 | Optimal |
2024-01-06 07:00:00+01:00 | 0 | 2122.0 | 0.0 | 0.0 | 2122.0 | 0.0 | 2122.0 | 0.0 | 0.05 | 0.19 | 0.08 | -0.41 | -0.41 | Optimal |
2024-01-06 08:00:00+01:00 | 0 | 2072.0 | 0.0 | 0.0 | 2072.0 | 0.0 | 2072.0 | 0.0 | 0.05 | 0.20 | 0.08 | -0.42 | -0.42 | Optimal |
2024-01-06 09:00:00+01:00 | 140 | 1914.0 | 0.0 | 0.0 | 1914.0 | 0.0 | 1914.0 | -140.0 | 0.06 | 0.21 | 0.09 | -0.40 | -0.40 | Optimal |
2024-01-06 10:00:00+01:00 | 502 | 1905.0 | 0.0 | 0.0 | 1905.0 | 0.0 | 1905.0 | -502.0 | 0.11 | 0.21 | 0.09 | -0.41 | -0.41 | Optimal |
2024-01-06 11:00:00+01:00 | 990 | 2004.0 | 0.0 | 0.0 | 2004.0 | 0.0 | 2004.0 | -990.0 | 0.20 | 0.22 | 0.10 | -0.44 | -0.44 | Optimal |
2024-01-06 12:00:00+01:00 | 1203 | 2184.0 | 0.0 | 0.0 | 2184.0 | 0.0 | 2184.0 | -1203.0 | 0.31 | 0.22 | 0.10 | -0.48 | -0.48 | Optimal |
2024-01-06 13:00:00+01:00 | 1203 | 1946.0 | 0.0 | 0.0 | 1946.0 | 0.0 | 1946.0 | -1203.0 | 0.41 | 0.22 | 0.10 | -0.43 | -0.43 | Optimal |
2024-01-06 14:00:00+01:00 | 941 | 1911.0 | 0.0 | 0.0 | 1911.0 | 0.0 | 1911.0 | -941.0 | 0.50 | 0.21 | 0.09 | -0.41 | -0.41 | Optimal |
2024-01-06 15:00:00+01:00 | 456 | 1876.0 | 0.0 | 0.0 | 1876.0 | 0.0 | 1876.0 | -456.0 | 0.54 | 0.21 | 0.09 | -0.40 | -0.40 | Optimal |
2024-01-06 16:00:00+01:00 | 93 | 1841.0 | 0.0 | 0.0 | 1841.0 | 0.0 | 1841.0 | -93.0 | 0.55 | 0.21 | 0.09 | -0.39 | -0.39 | Optimal |
2024-01-06 17:00:00+01:00 | 0 | 1817.0 | 0.0 | 0.0 | 1817.0 | 0.0 | 1817.0 | 0.0 | 0.55 | 0.21 | 0.09 | -0.38 | -0.38 | Optimal |
2024-01-06 18:00:00+01:00 | 0 | 1850.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1850.0 | 0.36 | 0.23 | 0.10 | -0.00 | -0.00 | Optimal |
2024-01-06 19:00:00+01:00 | 0 | 2018.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 2018.0 | 0.16 | 0.22 | 0.10 | -0.00 | -0.00 | Optimal |
2024-01-06 20:00:00+01:00 | 0 | 2657.0 | 0.0 | 0.0 | 1538.0 | 0.0 | 1538.0 | 1119.0 | 0.05 | 0.22 | 0.10 | -0.34 | -0.34 | Optimal |
2024-01-06 21:00:00+01:00 | 0 | 2192.0 | 0.0 | 0.0 | 2192.0 | 0.0 | 2192.0 | 0.0 | 0.05 | 0.21 | 0.09 | -0.47 | -0.47 | Optimal |
2024-01-06 22:00:00+01:00 | 0 | 2023.0 | 0.0 | 0.0 | 2023.0 | 0.0 | 2023.0 | 0.0 | 0.05 | 0.21 | 0.09 | -0.42 | -0.42 | Optimal |
2024-01-06 23:00:00+01:00 | 0 | 2029.0 | 0.0 | 0.0 | 2029.0 | 0.0 | 2029.0 | 0.0 | 0.05 | 0.21 | 0.09 | -0.42 | -0.42 | Optimal |
So bottom line I don’t understand why my battery charges to 50%, which explains the discharge around 18h.
Thanks
Yves
You forecast a decent amount of pv generation. Your system assumes to store this for usage later in the day deu to price differential. Tweak your efficiency (eg to 90% instead of 95%) this way the algorithm will not optimize at a mere 2 c difference.
Alternatively you can play with the weight, bot are now at 1, would put discharge to 0 and charge to for example 0.05 or 0.1, assuming a cost of 5c or 10c to charge the battery.
That should result in the PV being used directly to load instead of storing it.
@davidusb
Additional function for consideration somewhere in battery settings “Maximize battery life” switch.
This can include activation of following constrains:
- Limit battery MAX discharge to 10%
- Limit battery max charge to 90%
- Include compulsory 10 min pause between charge/discharge mode switches. This allows battery chemistry to stabilise (applicable for Li chemistry) between current reversal.
- Charge current reduction to 50% after battery reaches 80% (this one not as critical)
I don’t want my battery to export to the grid for less than around $0.15/ kWh.
I had to change two things to make this happen.
I was setting soc_finsl to 0 to map a full discharge cycle, but this was forcing EMHASS see at all prices.
I have now set soc_final to min(20, currentSOC).
I was setting both the discharge and charge penalty weighting to 0.15, but it was still cycling the battery.
I have now set the discharge weighting to 0.15 and the charging weighting to 0 and it seems to be the behavior I’m after.
Some of this can be programmed through automations right? For instance, if charge/ discharge is initiated you can include a wait in the automation prior to action. Node red has similar functionality.
What would be nice is if we can expand the number of parameters we can feed through a shell command or rest command. Eg max charge/discharge in watts, charge from grid, profit /cost/ self consumption. That way you can achieve everything you mention through automations and with mpc see the results right away.
I have one question: Would it be possible to use EMHass as a trigger to swtich my battery loading strategy?
To the background: I have a tibber energy tariff which is on an hourly basis. Normally, when sun is shining good. The energy prices are low. In these times I would like to set my solar bat strategy to Battery Load first, so that I can use that energy when prices are high.
What I would need from EMHass would be a switch or a trigger to use in my node red automation (or in HA).
Can I do that with this integration?
When p_batt_forecast output is negative the battery is supposed to charge. This can happen via PV or grid (positive).
You can combine them to create a template sensor or so.