EMHASS: An Energy Management for Home Assistant

There are a few approaches suitable for a water heater.

In many cases you maybe better off having your heater scheduled at different times rather than one individual block so it can reheat after consumption, rather than waiting until the next 24 hour block.

Another approach is to have a temperature sensor on schedule the def_hours based on how quickly your heater recovers. So if you water temp is 50° and it requires 2 hours to heat to 60°. Then maybe when it is 50° it would only require 1 hour.

11 kW is very large consumption, my domestic hot water heat pump draws 600W and my three phase pool heat pump draws 5 kW. I have fixed run times for both of those systems and I rely on the thermostat to switch off when the set point is reached.

    - name: def_total_hours_pool_filter
      unique_id: 326ca07d-fb97-4977-8821-78d5c5e0a7b5
      state: >-
        {{
          (is_state('automation.p_deferable0_automation', 'on') | int(0)) *
            states('sensor.pv_forecast_energy') | int(0) / 10
        }}


    - name: def_total_hours_pool_heatpump
      unique_id: ad586a0f-d16a-4ab9-841d-96b753612709
      state: "{{is_state('automation.p_deferable1_automation','on')|int
               * max(0,((state_attr('sensor.amber_feed_in_forecast', 'forecasts')|selectattr('descriptor','eq','extremely_low')|list|count)/2)
                        )}}"
    - name: def_total_hours_hws
      unique_id: ffff343f-d08d-4cbf-b783-3c8c116f0fd3
      state: "{{is_state('automation.p_deferrable_4','on')|int
               * max(6,((state_attr('sensor.amber_feed_in_forecast', 'forecasts')|selectattr('descriptor','eq','extremely_low')|list|count)/2))|int(0)}}"

Finally, if you can control the set point via automation then you could define this as continuous (not semi continuous) and allow EMHASS to schedule power levels between 0-11 kW. Then create a mapping from the desired power level to the setpoint.

For example:
At 0 W set point = current temp
At 2000W set point = current temp +5
At 11000 W set point = 65 °

Do you have any power monitoring on your device that you could share the power curve?

Those each MPC calls are individual optimization tasks.
So in the window of time between your MPC call and the prediction horizon you should see only one startup for your deferrable load if you set that parameter to true

Thanks for your suggestions.

At the water heater (powered by my heating pump which is also my heating/cooling and air filter system) I can set a ECO and COMFORT mode and I can set temperatures for each of these. For both modes i can set a time schedule. But as we have dynamic pricing I set the schedule to always be in ECO mode and then setting the ECO temperature up to a certain temperature if the price is low. There is also a fallback because the ECO temp is always set to 43°C. So if the temperature falls below that the water heater gets activated nevertheless. Most of the hot water use is at the early evening (where the prices mostly the highest :smiley: ).

That being sad, since last week I got my solar panels and now I’m looking forward to convert the solar energy and make use of it. Therefore I like to “overheat” the system. There are so called Smart Grid switches which can be activated to force the water heater to heat up the water with a target temperature of e.g. 55°C. (internally the temperature will be set to this value for both modes). I like to do so if enough solar power is available.

On the other hand it doesn’t make so much sense to force the water heater to heat up multiple times a day. The goal is to only heat up once a day to allow a longer life for the compressor.

Next i share some figures. The heat-up process always takes something between 90 and 120 min. But the lower the temperature the more energy will be used. There are also other things that have influce like outside temperature etc.) And therefore it can be that there is 11kW peak.

  1. example:


  2. example (lower energy use):


  3. example (fallback was activated because of rapid hot water consumption)


To sum it up:

I like to activate the Smart Grid switch to overheat the water if there is enough solar power. If not I like to schedule on the lowest price (or best profit, solar+grid). And for - hopefully - rare cases where the hot water temperature decreases rapidly there is the fallback at the ECO programm available.

Nice,

I have a Stiebel Electron WWK 305, which doesn’t have the ISG interface so I can’t get any data, but being German it has a Smart Grid (SG) signal line. I am using a Shelly relay which switches the SG signal when EMHASS wants to power the device.


What does treat_def_as_semi_cont really do? I’m not sure I understand what semi-continuous means…

Unfortunately it is a bit of mathematical torture of the English language. Sorry @davidusb .

semi_cont true means the device can only take descrete values such as 0 or max W. An example if a 1500 W pump can be set to on 1500W or off 0W.

semi_cont false means the device can take a range of values between 0 and max (ie continuous) an example of this is EV charging where your EV can charge at values between 5-32 Amps.

2 Likes

Hey again, Following my question of yesterday I was able to set up a ML model to predict a temperature sensor. However, I was unable to publish the predicted data to a HA sensor. my curl commands are:

  emhass_ml_temperature_fit: 'curl -i -H ''Content-Type:application/json'' -X POST -d ''{"var_model": "sensor.room_temperature", "days_to_retrieve": 30}'' http://localhost:5000/action/forecast-model-fit'
  emhass_ml_temperature_predict: 'curl -i -H ''Content-Type:application/json'' -X POST -d ''{"var_model": "sensor.room_temperature", "days_to_retrieve": 30}'' http://localhost:5000/action/forecast-model-predict'

I tried to do this as explained within the documentation but when I add the runtimeparams to the curl command the predict endpoint does not work.
Here’s my curl command to enable the publish task:

 emhass_ml_temperature_predict: 'curl -i -H ''Content-Type:application/json'' -X POST -d ''{"var_model": "sensor.room_temperature", "days_to_retrieve": 30, "model_predict_publish": True, "model_predict_entity_id": "sensor.p_temperature_forecast_model", "model_predict_unit_of_measurement": "°C", "model_predict_friendly_name": "Room Temperature Forecast custom ML model"}'' http://localhost:5000/action/forecast-model-predict'

Am I missing something guys?
EDIT: I use EMHASS for HA OS and Supervised users.

I think that it is just a problem with quote marks. It could help if you show the error thrown by that command but in the meantime you can try this:

emhass_ml_temperature_predict: "curl -i -H \"Content-Type:application/json\" -X POST -d '{\"var_model\": \"sensor.room_temperature\", \"days_to_retrieve\": 30, \"model_predict_publish\": True, \"model_predict_entity_id\": \"sensor.p_temperature_forecast_model\", \"model_predict_unit_of_measurement\": \"°C\", \"model_predict_friendly_name\": \"Room Temperature Forecast custom ML model\"}' http://localhost:5000/action/forecast-model-predict"

This formatting is what works fine for me.

I have the logger level set up to ERROR and then to DEBUG, None of them showed any error when calling the predict endpoint. The logger is working as intended when calling the fit endpoint

Also, the predict endpoint is working properly when I only use "var_model": "sensor.room_temperature" and "days_to_retrieve": 30 parameters!

The EMHASS logger won’t log anything if the endpoint is not even reached because of errors in the curl command. Look for HA core or Supervisor logs. Or open a terminal and try your curl command from there. The returned response will be shown in that terminal.
Did you applied the correct formatting?

Also you need to provide the model_type otherwise we don’t what model you’re trying to fit/predict.

I did all the changes you suggested including the model_type, and still not starting the predict endpoint. I tried to run the command through the Terminal and this is the message I’ve got: curl: (7) Failed to connect to localhost 5000 after 1 ms: Couldn't connect to server I looked into the HA supervisor and core logs and I couldn’t see anything related to EMHASS.

Hey again david, I upgraded my HA to 2023.10 and now I can see the response of every service I ran. Here’s the response I got after running the predict endpoint command

stdout: "HTTP/1.1 400 BAD REQUEST\r\nContent-Length: 167\r\nContent-Type: text/html; charset=utf-8\r\nDate: Fri, 06 Oct 2023 19:26:10 GMT\r\nServer: waitress\r\n\r\n<!doctype html>\n<html lang=en>\n<title>400 Bad Request</title>\n<h1>Bad Request</h1>\n<p>The browser (or proxy) sent a request that this server could not understand.</p>"
stderr: "% Total    % Received % Xferd  Average Speed   Time    Time     Time  Current\n                                 Dload  Upload   Total   Spent    Left  Speed\n\r  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0\r100   494  100   167  100   327  11686  22883 --:--:-- --:--:-- --:--:-- 35285"
returncode: 0

Hope it’s clear now.

Finally, I’ve managed to get it to work after updating my HA instance and tweaking the quote marks. Here’s the curl command that worked for me:

emhass_ml_temperature_predict: 'curl -i -H ''Content-Type:application/json'' -X POST -d ''{"model_type": "load_forecast", "var_model": "sensor.room_temperature", "days_to_retrieve": 30, "model_predict_publish": true, "model_predict_entity_id": "sensor.p_room_temperature_forecast_model", "model_predict_unit_of_measurement": "°C", "model_predict_friendly_name": "Room Temperature Forecast custom ML model"}'' http://localhost:5000/action/forecast-model-predict'

Thanks again david, Cheers.

1 Like

Great. Yes those quote marks are a pain.
However if you’re also using EMHASS for energy optimization then you need to change the model_type parameter to something else, otherwise you will overwrite your power load forecast model.

Change that for the fit, predict and tune calls to something else like this: "model_type": "room_temperature_forecast"

1 Like

Hey david, I start predicting my hot water temperature using the KNN. I run the fit endpoint everyday and the tune endpoint every week. I currently use 30 days of data and I noticed that the R² could really help to decide when the tune endpoint should be executed (e.g. an unexpected change in my hot water consumption or outdoor temperature). Therefore, I thought of using R² as an indicator in order to set the frequency at which the tune occurs. Is there anyway we can get the metric as an output?

Also, I made this visualization using Plotly integration for HA showing the future data. For those interested you can find the code here

image

4 Likes

Hi folks! New to emhass noob here… I’m trying to get everything set up, but I’m seem to be running into an issue with it not accepting the inverter model. I have a Solis S5-GC15K-LV, but it’s not in the list so I chose the only other 15kw Solis i could find in the list and input it as “Ningbo_Ginlong_Technologies_Co_0_Ltd_Solis_15K_US”.

2023-10-08 15:18:56,537 - web_server - ERROR - Exception on /action/dayahead-optim [POST]
Traceback (most recent call last):
  File "/usr/local/lib/python3.9/dist-packages/pandas/core/indexes/base.py", line 3621, in get_loc
    return self._engine.get_loc(casted_key)
  File "pandas/_libs/index.pyx", line 136, in pandas._libs.index.IndexEngine.get_loc
  File "pandas/_libs/index.pyx", line 163, in pandas._libs.index.IndexEngine.get_loc
  File "pandas/_libs/hashtable_class_helper.pxi", line 5198, in pandas._libs.hashtable.PyObjectHashTable.get_item
  File "pandas/_libs/hashtable_class_helper.pxi", line 5206, in pandas._libs.hashtable.PyObjectHashTable.get_item
KeyError: 'Ningbo_Ginlong_Technologies_Co_0_Ltd_Solis_15K_US'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
  File "/usr/local/lib/python3.9/dist-packages/flask/app.py", line 2190, in wsgi_app
    response = self.full_dispatch_request()
  File "/usr/local/lib/python3.9/dist-packages/flask/app.py", line 1486, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/usr/local/lib/python3.9/dist-packages/flask/app.py", line 1484, in full_dispatch_request
    rv = self.dispatch_request()
  File "/usr/local/lib/python3.9/dist-packages/flask/app.py", line 1469, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
  File "/usr/local/lib/python3.9/dist-packages/emhass/web_server.py", line 179, in action_call
    input_data_dict = set_input_data_dict(config_path, str(data_path), costfun,
  File "/usr/local/lib/python3.9/dist-packages/emhass/command_line.py", line 90, in set_input_data_dict
    P_PV_forecast = fcst.get_power_from_weather(df_weather)
  File "/usr/local/lib/python3.9/dist-packages/emhass/forecast.py", line 418, in get_power_from_weather
    inverter = cec_inverters[self.plant_conf['inverter_model'][i]]
  File "/usr/local/lib/python3.9/dist-packages/pandas/core/frame.py", line 3505, in __getitem__
    indexer = self.columns.get_loc(key)
  File "/usr/local/lib/python3.9/dist-packages/pandas/core/indexes/base.py", line 3623, in get_loc
    raise KeyError(key) from err
KeyError: 'Ningbo_Ginlong_Technologies_Co_0_Ltd_Solis_15K_US'

Any suggestions on what is wrong here?

(Also, lists linked in the documentation are from 2019 and neither my inverter or panels are in there… Are they not being updated?)

Does the addon work if you turn off the inverter option? Would suggest to work step by step and start with a very basic setup adding features one step at a time - i personally so not use the inverter settings, instead I push solcast pv forecast - based on the advice of @markpurcell

Oh, i got it now. Tried a different inverter and now it works, probably an issue with my formatting. Now i just have to wait two days for the necessary history (i hope).

Hi, me again. Got EMHASS working now (more or less), but I,m not sure I got the prices added in and working right: I use hourly prices from the Entso-E integration. Prices are included by these rest commands, copied from a forum and converted from nordpool to entso-e by me. They do give the correct prices when i test them in the template editor so I think they should work.

rest_command:
  trigger_entsoe_forecast:
    url: http://localhost:5000/action/dayahead-optim
    method: POST
    content_type: "application/json"
    timeout: 300
    payload: >-
      {
      "load_cost_forecast":{{((state_attr('sensor.strompriser_entso_e_nettleie_average_electricity_price_today', 'prices') | list))[now().hour:][:24] }},
      "prod_price_forecast":{{((state_attr('sensor.strompriser_entso_e_salg_average_electricity_price_today', 'prices') | list))[now().hour:][:24] }}
      }


Could someone explain what the four variables in the graph are? I’d think at least one of the blue ones should be the electricity price?