EMHASS: An Energy Management for Home Assistant

It is the actuall SOC, and couldn’t be less than 10% which is lowest SOC allowed by the Solax system. I’m not sure if soc_init is correct and why is there “max(0,” becouse I have simply copied it.
I have changed also “cost function” to “cost” and it seems much better. May be I need use “self consumption” during summer whan PV production is high, and “cost” during winter?

Ok but what is the value of this in the Template Editor ?

{{ states("sensor.solax_battery_capacity") }}

It will default to zero if the sensor state is unknown, which seems to be your case

That’s the SOC now.

This should eliminate the 0 value I think:

Hey guys, I’m running out of ideas how to tackle my problem, hope you can help.
Since a few days, I have trouble using EMHASS alltogether. It has been working fine for over a year or so, very happy with it. I think it started when moving to 1.12.4, but also still the case with 1.12.2 (reverted). I’m using a separate server with Docker.
The problem I have:
When calling my day-ahead script (after the new values from Nordpool arrive) it is blocked and times-out in HA. In the Docker log I see the last line, but nothing after that:
Retrieve hass get data method initiated…
So it seems it’s getting a lot of data which might take to long; BUT: when running an MPC optimization, which queries the same data, it works fine (but takes about 2 minutes, so also times-out the 60 second timeout in HA, but still works).
When the day-ahead is ‘blocked’, the EMHASS website is also not available anymore.
The OMV6 server running EMHASS is almost idling at 7% CPU, so not doing a lot.
I tried rebooting everything, but still fails. Could be some update on HA or even OMV6, but I have no idea where to look because EMHASS does not give any error, just stopping the log at the line above. The loglevel is DEBUG.
Any ideas?

The entire log of the day-ahead call:

[2025-01-30 19:41:53 +0100] [10] [INFO] Using core emhass version: 0.12.4

[2025-01-30 19:43:46 +0100] [10] [INFO]  >> Obtaining params: 

[2025-01-30 19:43:46 +0100] [10] [INFO] Passed runtime parameters: {'pv_power_forecast': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 301, 1282, 2520, 3582, 3897, 3430, 2337, 596, 2, 0, 0, 0, 0, 0, 0], 'prediction_horizon': 24, 'soc_init': 0.09, 'soc_final': 0.1, 'weight_battery_discharge': 0.1, 'weight_battery_charge': 0.01, 'def_start_timestep': [0, 0, 0], 'def_end_timestep': [12, 2, 4], 'def_total_hours': [0, 0, 2], 'P_deferrable_nom': [6700, 3000, 1000], 'load_cost_forecast': [0.352, 0.337, 0.317, 0.309, 0.302, 0.302, 0.298, 0.294, 0.291, 0.294, 0.301, 0.314, 0.345, 0.355, 0.344, 0.314, 0.31, 0.302, 0.303, 0.301, 0.331, 0.351, 0.371, 0.38], 'prod_price_forecast': [0.352, 0.337, 0.317, 0.309, 0.302, 0.302, 0.298, 0.294, 0.291, 0.294, 0.301, 0.314, 0.345, 0.355, 0.344, 0.314, 0.31, 0.302, 0.303, 0.301, 0.331, 0.351, 0.371, 0.38]}

[2025-01-30 19:43:46 +0100] [10] [INFO]  >> Setting input data dict

[2025-01-30 19:43:46 +0100] [10] [INFO] Setting up needed data

[2025-01-30 19:43:46 +0100] [10] [DEBUG] setting`passed_data:days_to_retrieve` to 9 for fit/predict/tune

[2025-01-30 19:43:46 +0100] [10] [INFO] Retrieving weather forecast data using method = list

[2025-01-30 19:43:46 +0100] [10] [INFO] Retrieving data from hass for load forecast using method = naive

[2025-01-30 19:43:46 +0100] [10] [INFO] Retrieve hass get data method initiated...

Update: still not able to find out what is happening. Also went back to 0.11.4 but behaviour is rather the same. One thing I noticed that sometimes it works, but could take over 10 minutes to retrieve the hass data. I now created a second ‘power_load_no_var_loads’ and am starting to fill that. After a few days I can switch over to this, perhaps the original has too much data in it.
Still hoping for someone to give me new ideas :slight_smile:

Float-filters require a default, i.e. | float(0)

To prevent issues when the source is unknown/unavailable.

Edit: Nevermind, still trying to understand lifepo4 batteries.

How does EMHASS know the time period associated with solar power forecast data when it is passed as a list to curl calls?

I assume there is some internal program logic going on that uses the last_updated info for the template sensor providing the list of values? Or it just assumes that it is the same time period as when the dayahead_optim is called? But how does that apply to MPC calls?

And, what is the “time” of the expected value? The beginning of the 30-minute period? The end? The mid-point?

Its very simple.
It depends on the timestep value defined in your configuration.
Let’s suppose that you have the default 30 minutes timestep.
The first value of the list is the now value, so the current value of the solar forecast. The second value of the list is the value 30 minutes from now in the future. The third value of the list is the value 60 minutes from now in the future, and so on…

Let’s suppose that now you change the timestep setting to 10 minutes.
The first value of the list is the now value, the 2nd value of the list is the value 10 minutes from now in the future, the 3rd of the list is the value 20 minutes from now in the future, and so on…

Ah great, thanks @davidusb ! And well done on an amazing project. It’s greatly appreciated.

1 Like

I tryed to uppdate from 10.5 to the latest version of emhass. Getting following error? Any ides what to do?

2025-02-04 19:14:45 +0200] [19] [INFO] Starting gunicorn 23.0.0
[2025-02-04 19:14:45 +0200] [19] [INFO] Listening at: http://0.0.0.0:5000 (19)
[2025-02-04 19:14:45 +0200] [19] [INFO] Using worker: gthread
[2025-02-04 19:14:45 +0200] [20] [INFO] Booting worker with pid: 20
/app/src/emhass/command_line.py:1621: SyntaxWarning: invalid escape sequence ‘.’
config_file_ending = re.findall(“(?<=.).*$”, str(config_path))
[2025-02-04 19:14:54 +0200] [20] [INFO] Obtaining parameters from config.json:
[2025-02-04 19:14:54 +0200] [20] [INFO] Launching the emhass webserver at: http://0.0.0.0:5000
[2025-02-04 19:14:54 +0200] [20] [INFO] Home Assistant data fetch will be performed using url: http://supervisor/core/api
[2025-02-04 19:14:54 +0200] [20] [INFO] The data path is: /app/data
[2025-02-04 19:14:54 +0200] [20] [INFO] The logging is: INFO
[2025-02-04 19:14:54 +0200] [20] [INFO] Using core emhass version: 0.12.5
[2025-02-04 19:15:05 +0200] [20] [INFO] >> Obtaining params:
[2025-02-04 19:15:05 +0200] [20] [INFO] Passed runtime parameters: {‘prediction_horizon’: 24, ‘soc_init’: 0.1, ‘soc_final’: 1, ‘num_def_loads’: 6, ‘def_total_hours’: [2, 1, 1, 1, 1, 1], ‘P_deferrable_nom’: [2000, 1000, 1100, 1500, 500, 500], ‘treat_def_as_semi_cont’: [True, True, True, True, False, False], ‘def_start_timestep’: [0, 0, 0, 0, 0, 0], ‘def_end_timestep’: [12, 12, 12, 12, 6, 6], ‘set_def_constant’: [False, False, False, False, True, True], ‘load_cost_forecast’: [0.0846, 0.08399, 0.08289, 0.08265, 0.08197, 0.08081, 0.08046, 0.07982, 0.0797, 0.07971, 0.08091, 0.08223, 0.08242, 0.08312, 0.08375, 0.08384, 0.08403, 0.08384, 0.08366, 0.08344, 0.08337, 0.08341, 0.0834, 0.08365], ‘prod_price_forecast’: [0.0013, 0.00081, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.00012, 0.00062, 0.00069, 0.00084, 0.00069, 0.00055, 0.00037, 0.00032, 0.00035, 0.00034, 0.00054], ‘pv_power_forecast’: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 22, 27, 28, 25, 16, 1, 0, 0], ‘alpha’: 0.2, ‘beta’: 0.8}
[2025-02-04 19:15:05 +0200] [20] [INFO] >> Setting input data dict
[2025-02-04 19:15:05 +0200] [20] [INFO] Setting up needed data
[2025-02-04 19:15:05 +0200] [20] [ERROR] Use COIN_CMD solver name if you want to set a path for the LP solver
[2025-02-04 19:15:05 +0200] [20] [INFO] Retrieve hass get data method initiated…
[2025-02-04 19:15:06 +0200] [20] [INFO] Retrieving weather forecast data using method = list
[2025-02-04 19:15:06 +0200] [20] [ERROR] Exception on /action/naive-mpc-optim [POST]
Traceback (most recent call last):
File “/app/.venv/lib/python3.12/site-packages/flask/app.py”, line 1511, in wsgi_app
response = self.full_dispatch_request()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “/app/.venv/lib/python3.12/site-packages/flask/app.py”, line 919, in full_dispatch_request
rv = self.handle_user_exception(e)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “/app/.venv/lib/python3.12/site-packages/flask/app.py”, line 917, in full_dispatch_request
rv = self.dispatch_request()
^^^^^^^^^^^^^^^^^^^^^^^
File “/app/.venv/lib/python3.12/site-packages/flask/app.py”, line 902, in dispatch_request
return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args) # type: ignore[no-any-return]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “/app/src/emhass/web_server.py”, line 414, in action_call
input_data_dict = set_input_data_dict(
^^^^^^^^^^^^^^^^^^^^
File “/app/src/emhass/command_line.py”, line 282, in set_input_data_dict
P_load_forecast = fcst.get_load_forecast(
^^^^^^^^^^^^^^^^^^^^^^^
File “/app/src/emhass/forecast.py”, line 1071, in get_load_forecast
with open(data_path, “rb”) as fid:
^^^^^^^^^^^^^^^^^^^^^
FileNotFoundError: [Errno 2] No such file or directory: ‘/app/data/data_train_load_clustering.pkl’
[2025-02-04 19:15:21 +0200] [20] [INFO] >> Obtaining params:
[2025-02-04 19:15:21 +0200] [20] [INFO] Passed runtime parameters: {}
[2025-02-04 19:15:21 +0200] [20] [INFO] >> Setting input data dict
[2025-02-04 19:15:21 +0200] [20] [INFO] Setting up needed data
[2025-02-04 19:15:21 +0200] [20] [ERROR] Use COIN_CMD solver name if you want to set a path for the LP solver
[2025-02-04 19:15:21 +0200] [20] [INFO] >> Publishing data…
[2025-02-04 19:15:21 +0200] [20] [INFO] Publishing data to HASS instance
[2025-02-04 19:15:21 +0200] [20] [ERROR] Exception on /action/publish-data [POST]
Traceback (most recent call last):
File “/app/.venv/lib/python3.12/site-packages/pandas/core/arrays/datetimelike.py”, line 2124, in _validate_frequency
raise ValueError
ValueError
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File “/app/.venv/lib/python3.12/site-packages/flask/app.py”, line 1511, in wsgi_app
response = self.full_dispatch_request()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “/app/.venv/lib/python3.12/site-packages/flask/app.py”, line 919, in full_dispatch_request
rv = self.handle_user_exception(e)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “/app/.venv/lib/python3.12/site-packages/flask/app.py”, line 917, in full_dispatch_request
rv = self.dispatch_request()
^^^^^^^^^^^^^^^^^^^^^^^
File “/app/.venv/lib/python3.12/site-packages/flask/app.py”, line 902, in dispatch_request
return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args) # type: ignore[no-any-return]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “/app/src/emhass/web_server.py”, line 439, in action_call
_ = publish_data(input_data_dict, app.logger)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “/app/src/emhass/command_line.py”, line 1098, in publish_data
opt_res_latest.index.freq = input_data_dict[“retrieve_hass_conf”][
^^^^^^^^^^^^^^^^^^^^^^^^^
File “/app/.venv/lib/python3.12/site-packages/pandas/core/indexes/datetimelike.py”, line 106, in freq
self._data.freq = value # type: ignore[misc]
^^^^^^^^^^^^^^^
File “/app/.venv/lib/python3.12/site-packages/pandas/core/arrays/datetimelike.py”, line 2054, in freq
self._validate_frequency(self, value)
File “/app/.venv/lib/python3.12/site-packages/pandas/core/arrays/datetimelike.py”, line 2135, in _validate_frequency
raise ValueError(
ValueError: Inferred frequency 30min from passed values does not conform to passed frequency h

Hi! Quick question, I don’t see it in the documentation:
Does the power_load_no_var_loads sensor include the battery charging/discharging power?

I remove it from the load, both charging and discharging is excluded.
Meaning that when I discharge the battery, it adds to the load of the home.

    - name: "Power Consumed by Home"
      state: "{{ states('sensor.power_from_grid_net_sum') | float(0) + states('sensor.solar_panels_total_output_power') | float(0) }}"
    - name: "Power load no var loads"
      unique_id: b699a98f-80bb-480d-bc7d-64489d271b77
      unit_of_measurement: W
      device_class: power
      state: >
        {% set powerload = states('sensor.power_consumed_by_home') | float(default=0) %}
        {% set battery_prod = states('sensor.powerstream_6588_inverter_output_watts') | int(0) %}
        {% set battery_cons = states('sensor.home_battery_power_usage_corrected') | float(default=0) %}
        {% set value = ( powerload + battery_prod - battery_cons) | round(1,default=0) %}
        {{ value }}