EMHASS: An Energy Management for Home Assistant

Just a caveat: be careful, even if you succeed in the installation, a Pi 3b may not be enough to properly run EMHASS. When I started I ran it as a HAOS add-on on a Pi4 and it had serious performance issues.

Anybody here using Solax equipment?

Yes, you can change your optimization time step to 15 minutes. Same in NL, however for the time being there will be no price difference within the hour - will be a matter of time so good to prep.

Looks great, for consideration: multiple price sensors would be great, at least for selling and buying but probably also as a fall back (eg. entso-e has been acting up a few times this month… good to fall over to a second provider).

mpc optimizer started giving me “Infeasible”. Anyone here that can point me in the right direction how to find out why? I know I pass a lot of runtime parameters but that is because I set them (deferable load info and bettery settings etc) from the lovelace ui or trough auttomation (input_number or input_select in home assistant).
The resulting parameters being passed to the naive-mpc-optim api call you can see in the log below.
load cost forecast, prod_price_forecast and pv_power_forecast all seem fine. I use a prediction horizon of max 24hrs depending on how many hours of load_cost_forecast I have available. Next day prices typicaly arrive around 1pm, so worst case prediction horizon is 24 (12 hours).

INFO - web_server - Passed runtime parameters: {'entity_save': True, 'publish_prefix': 'mpc_', 'prediction_horizon': 48, 'load_cost_forecast': [0.1921, 0.1921, 0.2013, 0.2013, 0.198, 0.198, 0.1725, 0.1725, 0.1617, 0.1617, 0.1517, 0.1517, 0.1361, 0.1361, 0.1155, 0.1155, 0.1263, 0.1263, 0.1198, 0.1198, 0.1056, 0.1056, 0.1021, 0.1021, 0.0991, 0.0991, 0.1098, 0.1098, 0.1273, 0.1273, 0.1488, 0.1488, 0.1619, 0.1619, 0.1548, 0.1548, 0.1371, 0.1371, 0.1313, 0.1313, 0.1294, 0.1294, 0.1303, 0.1303, 0.1376, 0.1376, 0.1634, 0.1634], 'prod_price_forecast': [0.0781, 0.0781, 0.0864, 0.0864, 0.0834, 0.0834, 0.0602, 0.0602, 0.0505, 0.0505, 0.0414, 0.0414, 0.0273, 0.0273, 0.0086, 0.0086, 0.0184, 0.0184, 0.0126, 0.0126, -0.0004, -0.0004, -0.0035, -0.0035, -0.0062, -0.0062, 0.0035, 0.0035, 0.0193, 0.0193, 0.0388, 0.0388, 0.0507, 0.0507, 0.0442, 0.0442, 0.0282, 0.0282, 0.0229, 0.0229, 0.0213, 0.0213, 0.0221, 0.0221, 0.0286, 0.0286, 0.0521, 0.0521], 'pv_power_forecast': [80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 296, 420, 512, 858, 1207, 1132, 946, 926, 992, 1183, 1162, 577, 203, 280, 308], 'soc_init': 0.11, 'soc_final': 0.3, 'alpha': 1, 'beta': 0, 'operating_hours_of_each_deferrable_load': [0, 0, 0], 'start_timesteps_of_each_deferrable_load': [0, 0, 0], 'end_timesteps_of_each_deferrable_load': [0, 0, 0], 'optimization_time_step': 30, 'historic_days_to_retrieve': 9, 'sensor_power_photovoltaics': 'sensor.sec_pac_solar', 'sensor_power_load_no_var_loads': 'sensor.sec_pac_non_deferable', 'num_def_loads': 3, 'nominal_power_of_deferrable_loads': [0, 0, 0], 'treat_deferrable_load_as_semi_cont': [True, False, False], 'set_deferrable_load_single_constant': [True, False, False], 'set_deferrable_startup_penalty': [0, 0, 0], 'maximum_power_from_grid': 4000, 'maximum_power_to_grid': 7000, 'inverter_is_hybrid': False, 'compute_curtailment': True, 'battery_discharge_power_max': 2500, 'battery_charge_power_max': 2500, 'battery_discharge_efficiency': 0.95, 'battery_charge_efficiency': 0.95, 'battery_nominal_energy_capacity': 5120, 'battery_maximum_state_of_charge': 0.99, 'battery_minimum_state_of_charge': 0.12, 'battery_target_state_of_charge': 0.3, 'weight_battery_discharge': 0.07, 'weight_battery_charge': 0.0, 'set_battery_dynamic': False, 'battery_dynamic_max': 0.9, 'battery_dynamic_min': -0.9, 'set_nocharge_from_grid': False, 'set_nodischarge_to_grid': True, 'costfun': 'profit', 'lp_solver': 'default', 'load_forecast_method': 'mlforecaster'}
INFO - web_server -  >> Setting input data dict
INFO - web_server - Setting up needed data
INFO - web_server - Retrieve hass get data method initiated...
INFO - web_server - Retrieving weather forecast data using method = list
INFO - web_server - Retrieving data from hass for load forecast using method = mlforecaster
INFO - web_server - Retrieve hass get data method initiated...
DEBUG - web_server - Number of ML predict forcast data generated (lags_opt): 48
DEBUG - web_server - Number of forcast dates obtained: 48
INFO - web_server -  >> Performing naive MPC optimization...
INFO - web_server - Performing naive MPC optimization
INFO - web_server - Perform an iteration of a naive MPC controller
DEBUG - web_server - Deferrable load 0: Proposed optimization window: 0 --> 0
DEBUG - web_server - Deferrable load 0: Validated optimization window: 0 --> 0
DEBUG - web_server - Deferrable load 1: Proposed optimization window: 0 --> 0
DEBUG - web_server - Deferrable load 1: Validated optimization window: 0 --> 0
DEBUG - web_server - Deferrable load 2: Proposed optimization window: 0 --> 0
DEBUG - web_server - Deferrable load 2: Validated optimization window: 0 --> 0
WARNING - web_server - Solver default unknown, using default
INFO - web_server - Status: Infeasible
INFO - web_server - Total value of the Cost function = 0.16
INFO - web_server - Publishing data to HASS instance
INFO - web_server - Successfully posted to sensor.mpc_p_pv_forecast = 80
DEBUG - web_server - Saved sensor.mpc_p_pv_forecast to json file
INFO - web_server - Successfully posted to sensor.mpc_p_load_forecast = 825.86
DEBUG - web_server - Saved sensor.mpc_p_load_forecast to json file
INFO - web_server - Successfully posted to sensor.mpc_p_pv_curtailment = 0.0
DEBUG - web_server - Saved sensor.mpc_p_pv_curtailment to json file
INFO - web_server - Successfully posted to sensor.mpc_p_deferrable0 = -2126.91
DEBUG - web_server - Saved sensor.mpc_p_deferrable0 to json file
INFO - web_server - Successfully posted to sensor.mpc_p_deferrable1 = 0.0
DEBUG - web_server - Saved sensor.mpc_p_deferrable1 to json file
INFO - web_server - Successfully posted to sensor.mpc_p_deferrable2 = 0.0
DEBUG - web_server - Saved sensor.mpc_p_deferrable2 to json file
INFO - web_server - Successfully posted to sensor.mpc_p_batt_forecast = -1301.05
DEBUG - web_server - Saved sensor.mpc_p_batt_forecast to json file
INFO - web_server - Successfully posted to sensor.mpc_soc_batt_forecast = 23.07
DEBUG - web_server - Saved sensor.mpc_soc_batt_forecast to json file
INFO - web_server - Successfully posted to sensor.mpc_p_grid_forecast = -80.0
DEBUG - web_server - Saved sensor.mpc_p_grid_forecast to json file
INFO - web_server - Successfully posted to sensor.mpc_total_cost_fun_value = 0.16
DEBUG - web_server - Saved sensor.mpc_total_cost_fun_value to json file
INFO - web_server - Successfully posted to sensor.mpc_optim_status = Infeasible
DEBUG - web_server - Saved sensor.mpc_optim_status to json file
INFO - web_server - Successfully posted to sensor.mpc_unit_load_cost = 0.1921
DEBUG - web_server - Saved sensor.mpc_unit_load_cost to json file
INFO - web_server - Successfully posted to sensor.mpc_unit_prod_price = 0.0781
DEBUG - web_server - Saved sensor.mpc_unit_prod_price to json file

@davidusb , I think I found a small bug by the way. I have ‘sensor_power_load_no_var_loads’ set as ‘sensor.sec_pac_non_deferable’ in the emhass config. But if I don’t pass my sensor name as the “var_model” runtime parameter to the forecast-model-fit api call I get an error that my, non existing, sensor.power_load_no_var_loads has no data
´´´
ERROR - web_server - The retrieved JSON is empty, A sensor:sensor.power_load_no_var_loads may have 0 days of history, passed sensor may not be correct, or days to retrieve is set too heigh
´´´
Probably everybody uses the default sensor.power_load_no_var_loads

I think your SoC is currently below the minimum. EMHASS doesn’t like that. Charge your battery or lower the minimum for a bit.

1 Like

Hi all,

Since the last update I have some problems with EMHASS. Its seems to do nothing anymore, I got the following logs:

Superviser:

2025-01-27 11:06:45.039 WARNING (MainThread) [supervisor.addons.options] Option ‘sensor_power_photovoltaics’ does not exist in the schema for EMHASS (5b918bf2_emhass)

2025-01-27 11:06:45.039 WARNING (MainThread) [supervisor.addons.options] Option ‘sensor_power_load_no_var_loads’ does not exist in the schema for EMHASS (5b918bf2_emhass)

2025-01-27 11:06:45.039 WARNING (MainThread) [supervisor.addons.options] Option ‘set_total_pv_sell’ does not exist in the schema for EMHASS (5b918bf2_emhass)

2025-01-27 11:06:45.039 WARNING (MainThread) [supervisor.addons.options] Option ‘set_nocharge_from_grid’ does not exist in the schema for EMHASS (5b918bf2_emhass)

2025-01-27 11:06:45.039 WARNING (MainThread) [supervisor.addons.options] Option ‘set_nodischarge_to_grid’ does not exist in the schema for EMHASS (5b918bf2_emhass)

2025-01-27 11:06:45.039 WARNING (MainThread) [supervisor.addons.options] Option ‘maximum_power_from_grid’ does not exist in the schema for EMHASS (5b918bf2_emhass)

2025-01-27 11:06:45.039 WARNING (MainThread) [supervisor.addons.options] Option ‘maximum_power_to_grid’ does not exist in the schema for EMHASS (5b918bf2_emhass)

2025-01-27 11:06:45.039 WARNING (MainThread) [supervisor.addons.options] Option ‘number_of_deferrable_loads’ does not exist in the schema for EMHASS (5b918bf2_emhass)

2025-01-27 11:06:45.039 WARNING (MainThread) [supervisor.addons.options] Option ‘list_nominal_power_of_deferrable_loads’ does not exist in the schema for EMHASS (5b918bf2_emhass)

2025-01-27 11:06:45.039 WARNING (MainThread) [supervisor.addons.options] Option ‘list_operating_hours_of_each_deferrable_load’ does not exist in the schema for EMHASS (5b918bf2_emhass)

2025-01-27 11:06:45.039 WARNING (MainThread) [supervisor.addons.options] Option ‘list_start_timesteps_of_each_deferrable_load’ does not exist in the schema for EMHASS (5b918bf2_emhass)

2025-01-27 11:06:45.039 WARNING (MainThread) [supervisor.addons.options] Option ‘list_end_timesteps_of_each_deferrable_load’ does not exist in the schema for EMHASS (5b918bf2_emhass)

2025-01-27 11:06:45.039 WARNING (MainThread) [supervisor.addons.options] Option ‘list_peak_hours_periods_start_hours’ does not exist in the schema for EMHASS (5b918bf2_emhass)

2025-01-27 11:06:45.039 WARNING (MainThread) [supervisor.addons.options] Option ‘list_peak_hours_periods_end_hours’ does not exist in the schema for EMHASS (5b918bf2_emhass)

2025-01-27 11:06:45.039 WARNING (MainThread) [supervisor.addons.options] Option ‘list_treat_deferrable_load_as_semi_cont’ does not exist in the schema for EMHASS (5b918bf2_emhass)

2025-01-27 11:06:45.039 WARNING (MainThread) [supervisor.addons.options] Option ‘list_set_deferrable_load_single_constant’ does not exist in the schema for EMHASS (5b918bf2_emhass)

2025-01-27 11:06:45.039 WARNING (MainThread) [supervisor.addons.options] Option ‘list_set_deferrable_startup_penalty’ does not exist in the schema for EMHASS (5b918bf2_emhass)

2025-01-27 11:06:45.040 WARNING (MainThread) [supervisor.addons.options] Option ‘load_peak_hours_cost’ does not exist in the schema for EMHASS (5b918bf2_emhass)

2025-01-27 11:06:45.040 WARNING (MainThread) [supervisor.addons.options] Option ‘load_offpeak_hours_cost’ does not exist in the schema for EMHASS (5b918bf2_emhass)

2025-01-27 11:06:45.040 WARNING (MainThread) [supervisor.addons.options] Option ‘photovoltaic_production_sell_price’ does not exist in the schema for EMHASS (5b918bf2_emhass)

2025-01-27 11:06:45.040 WARNING (MainThread) [supervisor.addons.options] Option ‘list_pv_module_model’ does not exist in the schema for EMHASS (5b918bf2_emhass)

2025-01-27 11:06:45.040 WARNING (MainThread) [supervisor.addons.options] Option ‘list_pv_inverter_model’ does not exist in the schema for EMHASS (5b918bf2_emhass)

2025-01-27 11:06:45.040 WARNING (MainThread) [supervisor.addons.options] Option ‘list_surface_tilt’ does not exist in the schema for EMHASS (5b918bf2_emhass)

2025-01-27 11:06:45.040 WARNING (MainThread) [supervisor.addons.options] Option ‘list_surface_azimuth’ does not exist in the schema for EMHASS (5b918bf2_emhass)

2025-01-27 11:06:45.040 WARNING (MainThread) [supervisor.addons.options] Option ‘list_modules_per_string’ does not exist in the schema for EMHASS (5b918bf2_emhass)

2025-01-27 11:06:45.040 WARNING (MainThread) [supervisor.addons.options] Option ‘list_strings_per_inverter’ does not exist in the schema for EMHASS (5b918bf2_emhass)

2025-01-27 11:06:45.040 WARNING (MainThread) [supervisor.addons.options] Option ‘inverter_is_hybrid’ does not exist in the schema for EMHASS (5b918bf2_emhass)

2025-01-27 11:06:45.040 WARNING (MainThread) [supervisor.addons.options] Option ‘compute_curtailment’ does not exist in the schema for EMHASS (5b918bf2_emhass)

2025-01-27 11:06:45.040 WARNING (MainThread) [supervisor.addons.options] Option ‘set_use_battery’ does not exist in the schema for EMHASS (5b918bf2_emhass)

2025-01-27 11:06:45.040 WARNING (MainThread) [supervisor.addons.options] Option ‘battery_nominal_energy_capacity’ does not exist in the schema for EMHASS (5b918bf2_emhass)

2025-01-27 11:06:45.040 WARNING (MainThread) [supervisor.addons.options] Option ‘optimization_time_step’ does not exist in the schema for EMHASS (5b918bf2_emhass)

2025-01-27 11:06:45.040 WARNING (MainThread) [supervisor.addons.options] Option ‘historic_days_to_retrieve’ does not exist in the schema for EMHASS (5b918bf2_emhass)

2025-01-27 11:06:45.040 WARNING (MainThread) [supervisor.addons.options] Option ‘method_ts_round’ does not exist in the schema for EMHASS (5b918bf2_emhass)

2025-01-27 11:06:45.040 WARNING (MainThread) [supervisor.addons.options] Option ‘lp_solver’ does not exist in the schema for EMHASS (5b918bf2_emhass)

2025-01-27 11:06:45.040 WARNING (MainThread) [supervisor.addons.options] Option ‘lp_solver_path’ does not exist in the schema for EMHASS (5b918bf2_emhass)

2025-01-27 11:06:45.040 WARNING (MainThread) [supervisor.addons.options] Option ‘set_battery_dynamic’ does not exist in the schema for EMHASS (5b918bf2_emhass)

EMHASS LOG:

/app/src/emhass/forecast.py:629: FutureWarning: Setting an item of incompatible dtype is deprecated and will raise an error in a future version of pandas. Value ‘513.5768484907121’ has dtype incompatible with int64, please explicitly cast to a compatible dtype first.
df_forecast.iloc[0] = first_fcst

I post every 30 seconds this MPC post:

{
  "pv_power_forecast": {{
    ([states('sensor.solar_panel_production_w')|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
    )| tojson
  }},
  "load_power_forecast": {{
          ([states('sensor.power_load_no_var_loads')|int] + (states('input_text.fi_fo_buffer').split(', ')|map('multiply',1000)|map('int')|list)[1:] )| tojson
  }},
  "prediction_horizon": {{
    (24 if now().hour <= 15 else 48) - now().hour
  }},
  "load_cost_forecast": {{
    ((state_attr('sensor.energi_data_service_all_in', 'raw_today') |map(attribute='price') | list + state_attr('sensor.energi_data_service_all_in', 'raw_tomorrow') |map(attribute='price')|list)[now().hour:][:48]| tojson )
  }},
  "prod_price_forecast": {{
    ((state_attr('sensor.energi_data_service_2', 'raw_today') |map(attribute='price') | list + state_attr('sensor.energi_data_service_2', 'raw_tomorrow') |map(attribute='price')|list)[now().hour:][:48]| tojson )
  }},
  "num_def_loads": 1,
  "operating_hours_of_each_deferrable_load": [
    {% set hours = (5 - states('sensor.volvo_battery_charge_level')|float(0) / 20) * (states('sensor.laadpaal_status_2')|float(0))|int(0) %} {{- hours -}}
    ],
  "nominal_power_of_deferrable_loads": [6400],
  "treat_deferrable_load_as_semi_cont": [0],
  "set_deferrable_load_single_constant": [0],
  "start_timesteps_of_each_deferrable_load": {{ [states('sensor.def_0_start_timestep')|int(0)] }},
  "end_timesteps_of_each_deferrable_load": {{ [states('sensor.def_0_end_timestep')|int(0)] }},
  "soc_init": {{ (states('sensor.solaredge_b1_state_of_energy')|int(0))/100 }},
  "soc_final": {{ (states('input_number.soc_final_battery')) }},
  "alpha": 0.75,
  "beta": 0.25
 
}

What give this:


{
  "pv_power_forecast": [
    4441,
    3010,
    3164,
    3045,
    3287,
    4019,
    4021,
    3380,
    2613,
    1837,
    990,
    252,
    13,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    69,
    225,
    461,
    737,
    863,
    982,
    1143,
    1308,
    1485,
    1508,
    1367,
    1154,
    881,
    653,
    449,
    267,
    130,
    13,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0
  ],
  "load_power_forecast": [
    445,
    400,
    500,
    500,
    400,
    400,
    300,
    400,
    400,
    300,
    200,
    300,
    400,
    700,
    500,
    700,
    600,
    600,
    600,
    900,
    700,
    600,
    400,
    400,
    400,
    400,
    300,
    300,
    300,
    300,
    400,
    300,
    300,
    400,
    300,
    300,
    500,
    500,
    400,
    600,
    900,
    800,
    400,
    2200,
    400,
    2300,
    300,
    1000
  ],
  "prediction_horizon": 13,
  "load_cost_forecast": [
    0.192,
    0.19,
    0.191,
    0.198,
    0.223,
    0.238,
    0.259,
    0.259,
    0.246,
    0.236,
    0.228,
    0.224,
    0.21
  ],
  "prod_price_forecast": [
    0.027,
    0.025,
    0.026,
    0.033,
    0.057,
    0.07,
    0.09,
    0.091,
    0.079,
    0.069,
    0.061,
    0.058,
    0.045
  ],
  "num_def_loads": 1,
  "operating_hours_of_each_deferrable_load": [
    0
  ],
  "nominal_power_of_deferrable_loads": [
    6400
  ],
  "treat_deferrable_load_as_semi_cont": [
    0
  ],
  "set_deferrable_load_single_constant": [
    0
  ],
  "start_timesteps_of_each_deferrable_load": [
    -2
  ],
  "end_timesteps_of_each_deferrable_load": [
    44
  ],
  "soc_init": 0.31,
  "soc_final": 0.6,
  "alpha": 0.75,
  "beta": 0.25
}

Is there someone who can help me with this?

Thanks.

I also had problems, nothing happened so I had to go back to the previous version.

Me to. The EMHASS log is reporting things I have never seen before:

2025-01-26 20:45:15,272 - web_server - INFO - Successfully posted to sensor.p_pv_forecast = -0.16
2025-01-26 20:45:15,295 - web_server - INFO - Successfully posted to sensor.p_load_forecast = 531.08
2025-01-26 20:45:15,315 - web_server - INFO - Successfully posted to sensor.p_deferrable0 = 0.0
2025-01-26 20:45:15,336 - web_server - INFO - Successfully posted to sensor.p_deferrable1 = 0.0
2025-01-26 20:45:15,356 - web_server - INFO - Successfully posted to sensor.p_deferrable2 = 0.0
2025-01-26 20:45:15,376 - web_server - INFO - Successfully posted to sensor.p_deferrable3 = 0.0
2025-01-26 20:45:15,398 - web_server - INFO - Successfully posted to sensor.p_grid_forecast = 531.24
2025-01-26 20:45:15,415 - web_server - INFO - Successfully posted to sensor.total_cost_fun_value = -2.67
2025-01-26 20:45:15,430 - web_server - INFO - Successfully posted to sensor.optim_status = Optimal
2025-01-26 20:45:15,450 - web_server - INFO - Successfully posted to sensor.unit_load_cost = 0.259
2025-01-26 20:45:15,471 - web_server - INFO - Successfully posted to sensor.unit_prod_price = 0.259
Uninstalled 1 package in 8ms
Installed 1 package in 5ms
[2025-01-26 20:47:07 +0100] [22] [INFO] Starting gunicorn 23.0.0
[2025-01-26 20:47:07 +0100] [22] [INFO] Listening at: http://0.0.0.0:5000 (22)
[2025-01-26 20:47:07 +0100] [22] [INFO] Using worker: gthread
[2025-01-26 20:47:07 +0100] [23] [INFO] Booting worker with pid: 23
emhass.web_server INFO  Obtaining parameters from config.json:
[2025-01-26 21:00:35 +0100] [22] [INFO] Handling signal: term
[2025-01-26 21:00:36 +0100] [23] [INFO] Worker exiting (pid: 23)
[2025-01-26 21:00:36 +0100] [22] [INFO] Shutting down: Master
Uninstalled 1 package in 7ms

In HA log I find.

Logger: homeassistant.components.rest_command
Bron: components/rest_command/__init__.py:154
integratie: RESTful Command (documentatie, problemen)
Eerst voorgekomen: 26 januari 2025 om 23:30:14 (296 gebeurtenissen)
Laatst gelogd: 11:45:16

Error. Url: http://localhost:5000/action/naive-mpc-optim. Status code 500. Payload: b'{\n \n \n \n "prod_price_forecast": [0.256, 0.25, 0.228, 0.221, 0.218, 0.219, 0.228, 0.264, 0.28, 0.303, 0.304, 0.287, 0.277, 0.266, 0.263, 0.246],\n "load_cost_forecast": [0.256, 0.25, 0.228, 0.221, 0.218, 0.219, 0.228, 0.264, 0.28, 0.303, 0.304, 0.287, 0.277, 0.266, 0.263, 0.246],\n "prediction_horizon": 16,\n "operating_hours_of_each_deferrable_load": [ 0, 0, 0, 2],\n "start_timesteps_of_each_deferrable_load": [ 0, 0, 0, 0],\n "end_timesteps_of_each_deferrable_load": [ 0, 0, 0, 0],\n "treat_deferrable_load_as_semi_cont": [ false, false, false, false],\n "set_deferrable_load_single_constant": [ true, true, true, true],\n "def_current_state ": [ true, true, true, true],\n "nominal_power_of_deferrable_loads": [ 2400 , 2400 , 11200, 2400], \n "alpha": 0.25,\n "beta": 0.75,\n "continual_publish": false\n }'

Same. I’ve long been running EMHASS on 5001 and it’s worked fine, but the latest update has broken something there.

The docker run command is running EMHASS correctly on 5001, and the UI is accessible on 5001, it’s like EMHASS itself doesn’t know its on TCP/5001 more than anything else. Shell-Commands have always been on 5001 and worked ok (nothing changed with those).

Have been doing a few restarts in the logs as well trying a few things.

[2025-01-27 18:56:01 +1100] [34] [INFO] Handling signal: term
[2025-01-27 18:56:02 +1100] [35] [INFO] Worker exiting (pid: 35)
[2025-01-27 18:56:02 +1100] [34] [INFO] Shutting down: Master
Uninstalled 1 package in 2ms
Installed 1 package in 0.82ms
[2025-01-27 18:56:08 +1100] [34] [INFO] Starting gunicorn 23.0.0
[2025-01-27 18:56:08 +1100] [34] [INFO] Listening at: http://0.0.0.0:5000 (34)
[2025-01-27 18:56:08 +1100] [34] [INFO] Using worker: gthread
[2025-01-27 18:56:08 +1100] [35] [INFO] Booting worker with pid: 35
emhass.web_server INFO  Obtaining parameters from config.json:
[2025-01-27 22:19:58 +1100] [34] [INFO] Handling signal: term
[2025-01-27 22:19:59 +1100] [35] [INFO] Worker exiting (pid: 35)
[2025-01-27 22:19:59 +1100] [34] [INFO] Shutting down: Master
Uninstalled 1 package in 1ms
Installed 1 package in 0.63ms
[2025-01-27 22:20:04 +1100] [34] [INFO] Starting gunicorn 23.0.0
[2025-01-27 22:20:04 +1100] [34] [INFO] Listening at: http://0.0.0.0:5000 (34)
[2025-01-27 22:20:04 +1100] [34] [INFO] Using worker: gthread
[2025-01-27 22:20:04 +1100] [35] [INFO] Booting worker with pid: 35
emhass.web_server INFO  Obtaining parameters from config.json:
emhass.web_server INFO  Obtaining parameters from config.json:
emhass.web_server INFO  Obtaining parameters from config.json:

Dave & GeoDerp’s help is appreciated however as always :slight_smile:

That was indeed the issue @RudolfRendier , thanks for pointing that out

Hi
Whenever I try to run a optimization task EMHASS crashes:
emhass.web_server INFO Obtaining parameters from config.json:

[2025-01-27 19:40:45 +0100] [22] [ERROR] Worker (pid:102) was sent SIGKILL! Perhaps out of memory?

[2025-01-27 19:40:45 +0100] [116] [INFO] Booting worker with pid: 116

emhass.web_server INFO Obtaining parameters from config.json:

[2025-01-27 19:41:10 +0100] [22] [ERROR] Worker (pid:116) was sent SIGKILL! Perhaps out of memory?

[2025-01-27 19:41:10 +0100] [128] [INFO] Booting worker with pid: 128

Thanks guys, 0.12.4 is better (it runs now). It’s started throwing these python errors however where it didn’t used to, hitting the publish-data API endpoint.

[2025-01-28 07:22:45 +1100] [35] [ERROR] Exception on /action/publish-data [POST]
Traceback (most recent call last):
  File "/app/.venv/lib/python3.11/site-packages/pandas/core/indexes/base.py", line 3805, in get_loc
    return self._engine.get_loc(casted_key)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "index.pyx", line 167, in pandas._libs.index.IndexEngine.get_loc
  File "index.pyx", line 196, in pandas._libs.index.IndexEngine.get_loc
  File "pandas/_libs/hashtable_class_helper.pxi", line 7081, in pandas._libs.hashtable.PyObjectHashTable.get_item
  File "pandas/_libs/hashtable_class_helper.pxi", line 7089, in pandas._libs.hashtable.PyObjectHashTable.get_item
KeyError: 'P_hybrid_inverter'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
  File "/app/.venv/lib/python3.11/site-packages/flask/app.py", line 1511, in wsgi_app
    response = self.full_dispatch_request()
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/.venv/lib/python3.11/site-packages/flask/app.py", line 919, in full_dispatch_request
    rv = self.handle_user_exception(e)
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/.venv/lib/python3.11/site-packages/flask/app.py", line 917, in full_dispatch_request
    rv = self.dispatch_request()
         ^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/.venv/lib/python3.11/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 1165, in publish_data
    opt_res_latest["P_hybrid_inverter"],
    ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^
  File "/app/.venv/lib/python3.11/site-packages/pandas/core/frame.py", line 4102, in __getitem__
    indexer = self.columns.get_loc(key)
              ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/.venv/lib/python3.11/site-packages/pandas/core/indexes/base.py", line 3812, in get_loc
    raise KeyError(key) from err
KeyError: 'P_hybrid_inverter'

I’ve finally managed to get my EV charging setup working with both departure time and maximum price constraints. It’s not perfect, but it works! A big thank you to everyone in this thread—I’ve incorporated many ideas and snippets of code from several of you.

3 Likes

Great work on your car charger schedule.

There are some subtle issues with get the end_timestep correct.

Can you share your code please?

Absolutely, but as I wrote earlier, there are still some small bugs. Most of the things are based on the package’s files.

My github

1 Like

My EMHASS runs as a docker standalone.
When I try to start version 0.12.4, I get the following error message:

Attaching to emhass
emhass | error: Failed to spawn: gunicorn
emhass | Caused by: No such file or directory (os error 2)
emhass exited with code 0

image: Package emhass ¡ GitHub

Version 0.12.2 works.

Sorry to hear this.
Please open a github issue so that it can be treated.

I try to find the best setting according my demands. I want to use as much as possible own produced electricity and when production is low as now, I want to load battery from the grid and use it when the price is higer for 1 unit (SEK) the bought. I have tried “self consumption”, but it doesn’t work as planned. It want to buy for 2,11 and sale for 2,47. Beside this it plan SOC 0% although min SOC is 10 %. Should I change to cost instead? Or maybe change “weight_battery_discharge”?

{
  "battery_charge_efficiency": 0.95,
  "battery_charge_power_max": 10000,
  "battery_discharge_efficiency": 0.95,
  "battery_discharge_power_max": 10000,
  "battery_dynamic_max": 0.7,
  "battery_dynamic_min": -0.7,
  "battery_maximum_state_of_charge": 1,
  "battery_minimum_state_of_charge": 0,
  "battery_nominal_energy_capacity": 12000,
  "battery_target_state_of_charge": 0.1,
  "compute_curtailment": false,
  "continual_publish": true,
  "costfun": "self-consumption",
  "delta_forecast_daily": 2,
  "end_timesteps_of_each_deferrable_load": [
    0
  ],
  "historic_days_to_retrieve": 9,
  "inverter_is_hybrid": true,
  "load_cost_forecast_method": "hp_hc_periods",
  "load_forecast_method": "naive",
  "load_negative": false,
  "load_offpeak_hours_cost": 1,
  "load_peak_hour_periods": {
    "period_hp_1": [
      {
        "start": "07:00"
      },
      {
        "end": "10:00"
      }
    ],
    "period_hp_2": [
      {
        "start": "16:00"
      },
      {
        "end": "21:00"
      }
    ]
  },
  "load_peak_hours_cost": 2,
  "logging_level": "DEBUG",
  "lp_solver": "COIN_CMD",
  "lp_solver_path": "/usr/bin/cbc",
  "maximum_power_from_grid": 11000,
  "maximum_power_to_grid": 11000,
  "method_ts_round": "first",
  "modules_per_string": [
    12,
    18
  ],
  "nominal_power_of_deferrable_loads": [
    3000
  ],
  "number_of_deferrable_loads": 1,
  "operating_hours_of_each_deferrable_load": [
    0
  ],
  "optimization_time_step": 60,
  "photovoltaic_production_sell_price": 1,
  "production_price_forecast_method": "constant",
  "pv_inverter_model": [
    "Shenzhen_Growatt_New_Energy_Co___Ltd___MIN_10000TL_XH_US__240V_"
  ],
  "pv_module_model": [
    "Trina_Solar_TSM_400DE09_08"
  ],
  "sensor_linear_interp": [
    "sensor.power_load_no_var_loads"
  ],
  "sensor_power_load_no_var_loads": "sensor.power_load_no_var_loads",
  "sensor_power_photovoltaics": "sensor.solax_pv_power_total",
  "sensor_replace_zero": [
    "sensor.solax_pv_power_total"
  ],
  "set_battery_dynamic": false,
  "set_deferrable_load_single_constant": [
    false
  ],
  "set_deferrable_startup_penalty": [
    0
  ],
  "set_nocharge_from_grid": false,
  "set_nodischarge_to_grid": true,
  "set_total_pv_sell": false,
  "set_use_battery": true,
  "set_zero_min": true,
  "start_timesteps_of_each_deferrable_load": [
    0
  ],
  "strings_per_inverter": [
    2
  ],
  "surface_azimuth": [
    145
  ],
  "surface_tilt": [
    10,
    26
  ],
  "treat_deferrable_load_as_semi_cont": [
    true
  ],
  "weather_forecast_method": "solcast",
  "weight_battery_charge": 0,
  "weight_battery_discharge": 1
}


post_mpc_optim: >
  curl -i -H "Content-Type: application/json" -X POST -d '{
    "load_cost_forecast": {{ ((state_attr("sensor.nordpool_cost", "raw_today") | map(attribute="value") | list) + (state_attr("sensor.nordpool_cost", "raw_tomorrow") | map(attribute="value") | list))[now().hour:][:24] | tojson }},
    "prod_price_forecast": {{ ((state_attr("sensor.nordpool_sell", "raw_today") | map(attribute="value") | list) + (state_attr("sensor.nordpool_sell", "raw_tomorrow") | map(attribute="value") | list))[now().hour:][:24] | tojson }},
    "prediction_horizon": {{ min(24, ((state_attr("sensor.nordpool_kwh_se4_sek_2_00_0", "raw_today") | map(attribute="value") | list + state_attr("sensor.nordpool_kwh_se4_sek_2_00_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 }},
    "weather_forecast_cache": {"weather_forecast_cache_only":true},
    "load_power_forecast": {{ ([states('sensor.power_load_no_var_loads') | int(0)]+(states('input_text.fi_fo_buffer') | default('') | string).split(',') | map('int') | list) [:48]| tojson }},
    "soc_init": {{ max(0, states("sensor.solax_battery_capacity") | int(0)) / 100 }},
    "soc_final": 0.1,
    "P_deferrable_nom": [{{ max(states("sensor.easee_garage_power") | int, 3000) }}, 0],
    "weight_battery_discharge": 1,
    "weight_battery_charge": 0,
    "delta_forecast_daily": 2,
    "alpha": 1,
    "beta": 0
  }' http://localhost:5000/action/naive-mpc-optim

According to that table it is actually buying from the grid when its less expensive, so 2.11 SEK and when its the most expensive 2.47 is actually just discharging the battery to supply your load with no grid import.
The SOC problem seems weird though, what is your SOCinit, it seems 0 ?