EMHASS: An Energy Management for Home Assistant

Update on my issue:
The optimization worked this morning 7:00. So the issue seems to be fixed with 0.8.2.

Thank you very much!

1 Like

Iā€™m running EMHASS in docker and looks like after update something is broken:

Log:

NameError: name 'options_json' is not defined
Traceback (most recent call last):
  File "<frozen runpy>", line 198, in _run_module_as_main
  File "<frozen runpy>", line 88, in _run_code
  File "/usr/local/lib/python3.11/dist-packages/emhass/web_server.py", line 243, in <module>
    if options_json.exists():
       ^^^^^^^^^^^^
NameError: name 'options_json' is not defined

Iā€™m usinf docker-compose and the latest from image: davidusb/emhass-docker-standalone is v0.8.2

Edit. Changerd the image to davidusb/emhass-docker-standalone:0.8.3 and now it works

1 Like

Yes this was the bug with v0.8.2, fixed in v0.8.3

Why is EMHASS not able to get the load forecast data from long term statistics (LTS)?

I would not like to have purge_keep_days so high just because of EMHASS. As only hourly data is needed LTS would be enough.

Would be nice to get 0.8.3 from davidusb/emhass-docker-standalone without adding :0.8.3

This has been discussed before here, the official HA API does not have an endpoint to fetch those LTS, otherwise yes it would be nice to use those instead.
However I donā€™t see the issue of setting up properly the recorder and specifying a list of entities to record so that you DB doesnā€™t grow too high. Thatā€™s what I do and works just fine.

This should pull the latest image:

docker pull davidusb/emhass-docker-standalone:latest

Hi Rick,
Yes that is the case. Iā€™ve put it on discharge, not on charge; 0.10 to have 10 cents difference. I only have a fake battery (yet), but indeed itā€™s working.

Hello again
Now trying to get new grips with emhass but running into something that I canā€™t solve. When I go in and look at the data, I see that unit_load_cost matches well with the current electricity price. But as soon as I press the Day-ahead Optimization button, it drops the electricity price to the default found in the config file. Can anyone tell me what is wrong or should it be like that?
I am attaching my config and my shell commands

logging_level: INFO
data_path: default
costfun: self-consumption
sensor_power_photovoltaics: sensor.input_power_with_efficiency_loss
sensor_power_load_no_var_loads: sensor.power_load_no_var_loads
set_total_pv_sell: false
set_nocharge_from_grid: false
set_nodischarge_to_grid: false
maximum_power_from_grid: 9000
number_of_deferrable_loads: 1
list_nominal_power_of_deferrable_loads:
  - nominal_power_of_deferrable_loads: 1300
list_operating_hours_of_each_deferrable_load:
  - operating_hours_of_each_deferrable_load: 5
list_start_timesteps_of_each_deferrable_load:
  - start_timesteps_of_each_deferrable_load: 0
list_end_timesteps_of_each_deferrable_load:
  - end_timesteps_of_each_deferrable_load: 0
list_peak_hours_periods_start_hours:
  - peak_hours_periods_start_hours: "05:00"
list_peak_hours_periods_end_hours:
  - peak_hours_periods_end_hours: "23:59"
list_treat_deferrable_load_as_semi_cont:
  - treat_deferrable_load_as_semi_cont: true
list_set_deferrable_load_single_constant:
  - set_deferrable_load_single_constant: false
load_peak_hours_cost: 0.1907
load_offpeak_hours_cost: 0.1419
photovoltaic_production_sell_price: 0.065
list_pv_module_model:
  - pv_module_model: CSUN_Eurasia_Energy_Systems_Industry_and_Trade_CSUN295_60M
list_pv_inverter_model:
  - pv_inverter_model: Huawei_Technologies_Co___Ltd___SUN2000_10KTL_USL0__240V_
list_surface_tilt:
  - surface_tilt: 18
list_surface_azimuth:
  - surface_azimuth: 230
list_modules_per_string:
  - modules_per_string: 23
list_strings_per_inverter:
  - strings_per_inverter: 1
set_use_battery: true
battery_nominal_energy_capacity: 10000
optimization_time_step: 60
weather_forecast_method: scrapper
battery_maximum_state_of_charge: 1
battery_target_state_of_charge: 1
battery_minimum_state_of_charge: 0.2
battery_charge_power_max: 3200
battery_discharge_power_max: 2000
method_ts_round: first
weight_battery_discharge: 0.04

Triggers every /5 miutes

naive_mpc_optim:
  url: http://localhost:5000/action/naive-mpc-optim
  method: POST
  content_type: "application/json"
  payload: >-
    {
      "pv_power_forecast": {{ [states('sensor.inverter_input_power') | int(0)] + 
        state_attr('sensor.solcast_pv_forecast_forecast_today', 'detailedForecast') | selectattr('period_start', 'gt', utcnow()) | map(attribute='pv_estimate') | map('multiply', 1000) | map('int') | list +
        state_attr('sensor.solcast_pv_forecast_forecast_tomorrow', 'detailedForecast') | selectattr('period_start', 'gt', utcnow()) | map(attribute='pv_estimate') | map('multiply', 1000) | map('int') | list
      }},
      "load_cost_forecast": {{
        ([states('sensor.nordpool_kwh_se3_sek_3_10_025')|float(0)] + 
        state_attr('sensor.nordpool_kwh_se3_sek_3_10_025', 'raw_today') |map(attribute='value')|list) 
        | tojson 
      }},
      "prod_price_forecast": {{
        ([states('sensor.nordpool')|float(0)] +
        (state_attr('sensor.nordpool_kwh_se3_sek_3_10_025', 'raw_today')|map(attribute='value')|list))
        | tojson 
      }},
      "num_def_loads": 1,
      "def_total_hours": [5],
      "P_deferrable_nom": [1300],
      "treat_def_as_semi_cont": [1]
    }
publish_data:
  url: http://localhost:5000/action/publish-data
  method: POST
  content_type: "application/json"
  payload: "{}"

Triggers 05:50

dayahead_optim: 'curl -i -H "Content-Type:application/json" -X POST -d ''{}'' http://localhost:5000/action/dayahead-optim'

triggered every 10 minutes

#Publish data
publish_data: 'curl -i -H "Content-Type:application/json" -X POST -d ''{}'' http://localhost:5000/action/publish-data'

Do you press the day-ahead button from the website or do you trigger the automation from HA? I think the latter would be the route to take.
Edit: ah sorry, I assumed in the curl command for day-ahead you would also specify the costs, but you didnā€™t? This is something to also pass within the curl command, like with the MPC-optim,

I saw this error this morning. After the update to 0.8.3
Any ideas?

INFO - web_server - Performing perfect forecast optimization
INFO - web_server - Perform optimization for perfect forecast scenario
INFO - web_server - Solving for day: 4-3-2024
ERROR - web_server - Exception on /action/perfect-optim [POST]
Traceback (most recent call last):
  File "/usr/local/lib/python3.11/dist-packages/flask/app.py", line 1463, in wsgi_app
    response = self.full_dispatch_request()
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/flask/app.py", line 872, in full_dispatch_request
    rv = self.handle_user_exception(e)
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/flask/app.py", line 870, in full_dispatch_request
    rv = self.dispatch_request()
         ^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/flask/app.py", line 855, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)  # type: ignore[no-any-return]
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/emhass/web_server.py", line 119, in action_call
    opt_res = perfect_forecast_optim(input_data_dict, app.logger)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/emhass/command_line.py", line 207, in perfect_forecast_optim
    opt_res = input_data_dict['opt'].perform_perfect_forecast_optim(df_input_data, input_data_dict['days_list'])
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/emhass/optimization.py", line 538, in perform_perfect_forecast_optim
    data_tp = df_input_data.copy().loc[pd.date_range(start=day_start, end=day_end, freq=self.freq)]
              ~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/pandas/core/indexing.py", line 1103, in __getitem__
    return self._getitem_axis(maybe_callable, axis=axis)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/pandas/core/indexing.py", line 1332, in _getitem_axis
    return self._getitem_iterable(key, axis=axis)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/pandas/core/indexing.py", line 1272, in _getitem_iterable
    keyarr, indexer = self._get_listlike_indexer(key, axis)
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/pandas/core/indexing.py", line 1462, in _get_listlike_indexer
    keyarr, indexer = ax._get_indexer_strict(key, axis_name)
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/pandas/core/indexes/base.py", line 5877, in _get_indexer_strict
    self._raise_if_missing(keyarr, indexer, axis_name)
  File "/usr/local/lib/python3.11/dist-packages/pandas/core/indexes/base.py", line 5941, in _raise_if_missing
    raise KeyError(f"{not_found} not in index")
KeyError: "[Timestamp('2024-03-04 05:00:00+0100', tz='UTC+01:00'), Timestamp('2024-03-04 05:30:00+0100', tz='UTC+01:00'), Timestamp('2024-03-04 06:00:00+0100', tz='UTC+01:00'), Timestamp('2024-03-04 06:30:00+0100', tz='UTC+01:00'), Timestamp('2024-03-04 07:00:00+0100', tz='UTC+01:00'), Timestamp('2024-03-04 07:30:00+0100', tz='UTC+01:00'), Timestamp('2024-03-04 08:00:00+0100', tz='UTC+01:00'), Timestamp('2024-03-04 08:30:00+0100', tz='UTC+01:00')] not in index"
image: davidusb/emhass-docker-standalone:latest

This pulls v0.8.2

image: davidusb/emhass-docker-standalone:0.8.3

This works

I have an issue. In my config_emhass.yaml i have defined
var_load: 'sensor.ss_load_power'

When I click ā€œML forecast fitā€ in UI I get the result Forecasting variable sensor.power_load_no_var_loads not sensor.ss_load_power

I can overcome this by setting input parameters

then i get t

My questions:

  1. Will it use sensor.ss_load_power now in the model now?
  2. What should i change to do it without input parameters. My assumption was that changing var_load in config_emhass.yaml will do it.

Background is that i used to use sensor.power_load_no_var_loads prevously and this sensor still exists, but for now iā€™m running emhass without deferaable loads and hence want to use sensor.ss_load_power. I future i will switch back using deferrable loads.

Has anybody got an idea how to schedule heating and hot water of a heatpump?

The current strategy is to have 2 constant schedules for heating. One during day (usually PV peak) and one during night (usually somewhen after midnight, when price is low). I just adjust the timeframe depending on outside and inside temperature.
This works quite good.
In addition, I scheduled to make hot water somewhen between 12:00-15:00, independet from EMHASS.
But of course this is not ideal, because, in some cases this would reduce the time for heating, as the heatpump could not do both simultanously.
So my idea is now to use a second deferrable, but I think this is not easy:

On sunny days (PV peaks up to 20kW), it would try to schedule both at the same time, as I cannot separate it (or is there any option?)
If I reduce maximum_power_from_grid, I get a status of ā€œinfeasibleā€, when PV forecast is higher.
Is this maybe a bug?
Would it be an option to have 2 settings like:
maximum_power_from_grid
maximum_power_to_grid

The ideal solution (however this could be made) would be to have a single constant load, where I could use the ā€œbestā€ hour (in terms of profit) for hot water. But is there any indicator?

I waited for my automations to run but it didnā€™t get any better.

This will be added on upcoming future releases

This is normal, if you want to change the default values then it is done by passing custom params as you did then when setting input parameters inside those text boxes on the webui.

The webui is just there for visualizing results and for quick testing functionalities.
To use that task as you want on a regular basis just define a new entity using HAā€™s rest command or a shell command integrations and when doing this you can define your desired custom params.

The answer to your questions:

  1. Yes
  2. Do what I just explained before

Mmmm no.

This should pull the latest available version on dockerhub:

docker pull davidusb/emhass-docker-standalone:latest

Already figured that out. Was a docker cache issue

1 Like

Thanks for the reply and explanation.

Probably ML model Fit is not something that you do oftern.

At the moment I have two shell commands:

Dayahead:

  dayahead_optim: "curl -i -H \"Content-Type:application/json\" -X POST -d '{
    \"load_cost_forecast\":{{((state_attr('sensor.nordpool_with_vat_and_tarifss', 'raw_today') | map(attribute='value') | list  + state_attr('sensor.nordpool_with_vat_and_tarifss', 'raw_tomorrow') | map(attribute='value') | list))[now().hour:][:24] }},
    \"prod_price_forecast\":{{((state_attr('sensor.nordpool_kwh_ee_eur_3_10_0', 'raw_today') | map(attribute='value') | list  + state_attr('sensor.nordpool_kwh_ee_eur_3_10_0', 'raw_tomorrow') | map(attribute='value') | list))[now().hour:][:24] }}, 
    \"prediction_horizon\":{{min(24, (((state_attr('sensor.nordpool_kwh_ee_eur_3_10_0', 'raw_today')|map(attribute='value')|list + state_attr('sensor.nordpool_kwh_ee_eur_3_10_0', 'raw_tomorrow') | map(attribute='value')| list)[now().hour:][:48]|list|length)))}},    
    \"pv_power_forecast\":{{([states('sensor.solcast_pv_forecast_power_now')|int(0)] + state_attr('sensor.solcast_pv_forecast_forecast_today', 'detailedHourly')|selectattr('period_start','gt',utcnow()) | map(attribute='pv_estimate')|map('multiply',1000)|map('int')|list + state_attr('sensor.solcast_pv_forecast_forecast_tomorrow', 'detailedHourly')|selectattr('period_start','gt',utcnow()) | map(attribute='pv_estimate')|map('multiply',1000)|map('int')|list)| tojson}},
    \"delta_forecast\":2
    }' http://192.168.1.35:5001/action/dayahead-optim"

mpc

  mpc: "curl -i -H \"Content-Type:application/json\" -X POST -d '{
    \"load_cost_forecast\":{{((state_attr('sensor.nordpool_with_vat_and_tarifss', 'raw_today') | map(attribute='value') | list  + state_attr('sensor.nordpool_with_vat_and_tarifss', 'raw_tomorrow') | map(attribute='value') | list))[now().hour:][:24] }},
    \"prod_price_forecast\":{{((state_attr('sensor.nordpool_kwh_ee_eur_3_10_0', 'raw_today') | map(attribute='value') | list  + state_attr('sensor.nordpool_kwh_ee_eur_3_10_0', 'raw_tomorrow') | map(attribute='value') | list))[now().hour:][:24] }}, 
    \"prediction_horizon\":{{min(24, (((state_attr('sensor.nordpool_kwh_ee_eur_3_10_0', 'raw_today')|map(attribute='value')|list + state_attr('sensor.nordpool_kwh_ee_eur_3_10_0', 'raw_tomorrow') | map(attribute='value')| list)[now().hour:][:48]|list|length)))}},    
    \"pv_power_forecast\":{{([states('sensor.solcast_pv_forecast_power_now')|int(0)] + state_attr('sensor.solcast_pv_forecast_forecast_today', 'detailedHourly')|selectattr('period_start','gt',utcnow()) | map(attribute='pv_estimate')|map('multiply',1000)|map('int')|list + state_attr('sensor.solcast_pv_forecast_forecast_tomorrow', 'detailedHourly')|selectattr('period_start','gt',utcnow()) | map(attribute='pv_estimate')|map('multiply',1000)|map('int')|list)| tojson}},
    \"delta_forecast\":2
    }' http://192.168.1.35:5001/action/naive-mpc-optim"

Should I define somewhere that it uses the sensor.ss_load_power as load forecast or if I have done the ML model fit with it and itā€™s defined as var_load in config_emhass.yaml itā€™s already using it?

Also if delta_forecast: 2 is correct? I have copy-d it from someones configuration, but tom be honest i dont know what it does.