EMHASS: An Energy Management for Home Assistant

That’s the issue. I can charge the battery overnight at a cost but will the spike eventuate? It didn’t (again). So I’ve once again charged the battery at an inflated cost (42c) and now it’s discharging at a loss so it can charge again from the sun for an even worse spike this evening. My battery is a bit tired at 6 years old and only contains about 7 or 8kWh and now it has to cover this tonight:

I’ll have to sit under an electric blanket all night. Can’t run the aircon if the price is this high and it’s probably more likely to occur tonight. Seems the morning forecasts are furphies.

Sorry, furphy, Australian colloquialism for false report or improbable story; rumor .

1 Like

Hello everyone,
thank you so much for this awesome piece of software!

I know this has been discussed in the past but I just cannot get it to work.
So here is the deal:
I am running the lastes docker image of EMHASS:

htpc:~# docker inspect emhass | grep -i version
                "io.hass.base.version": "2024.03.0",
                "io.hass.version": "2024.03.0",
                "org.opencontainers.image.version": "v0.10.1"
htpc:/etc/emhass# docker pull davidusb/emhass-docker-standalone
Digest: sha256:607300ff655fa7e69b63890e64e77aec6f8726a1bf829a774976631a14ca8d68
Status: Image is up to date for davidusb/emhass-docker-standalone:latest

and this is the configuration I use:

retrieve_hass_conf:
  freq: 30 # The time step to resample retrieved data from hass in minutes
  days_to_retrieve: 2 # We will retrieve data from now and up to days_to_retrieve days
  var_PV: 'sensor.sw29_power' # Photovoltaic produced power sensor in Watts
  var_load: 'sensor.power_load_no_var_loads' # Household power consumption sensor in Watts (deferrable loads should be substracted)
  load_negative: False # Set to True if the retrived load variable is negative by convention
  set_zero_min: True # A special treatment for a minimum value saturation to zero. Values below zero are replaced by nans
  var_replace_zero: # A list of retrived variables that we would want  to replace nans with zeros
  - 'sensor.sw29_power'
  var_interp: # A list of retrived variables that we would want to interpolate nan values using linear interpolation
  - 'sensor.sw29_power'
  - 'sensor.power_load_no_var_loads'
  method_ts_round: 'nearest' # Set the method for timestamp rounding, options are: first, last and nearest
  continual_publish: False # Save published sensor data and check for state change every freq minutes

optim_conf:
  set_use_battery: False # consider a battery storage
  delta_forecast: 1 # days
  num_def_loads: 2
  P_deferrable_nom: # Watts
  - 450.0
  - 60.0
  def_total_hours: # hours
  - 5
  - 3.5
  def_start_timestep: # timesteps
  - 0
  - 0
  def_end_timestep: # timesteps
  - 40
  - 19
  treat_def_as_semi_cont: # treat this variable as semi continuous 
  - True
  - True
  set_def_constant: # set as a constant fixed value variable with just one startup for each 24h
  - False
  - True
#  weather_forecast_method: 'solcast' # options are 'scrapper', 'csv', 'list', 'solcast' and 'solar.forecast'
  weather_forecast_method: 'scrapper' # options are 'scrapper', 'csv', 'list', 'solcast' and 'solar.forecast'
  load_forecast_method: 'csv' # options are 'csv' to load a custom load forecast from a CSV file or 'naive' for a persistance model
  load_cost_forecast_method: 'hp_hc_periods' # options are 'hp_hc_periods' for peak and non-peak hours contracts and 'csv' to load custom cost from CSV file 
  list_hp_periods: # list of different tariff periods (only needed if load_cost_forecast_method='hp_hc_periods')
  - period_hp_1:
    - start: '00:00'
    - end: '23:59'
  load_cost_hp: 0.41 # peak hours load cost in €/kWh (only needed if load_cost_forecast_method='hp_hc_periods')
  load_cost_hc: 0.41 # non-peak hours load cost in €/kWh (only needed if load_cost_forecast_method='hp_hc_periods')
  prod_price_forecast_method: 'constant' # options are 'constant' for constant fixed value or 'csv' to load custom price forecast from a CSV file
  prod_sell_price: 0.0 # power production selling price in €/kWh (only needed if prod_price_forecast_method='constant')
  set_total_pv_sell: False # consider that all PV power is injected to the grid (self-consumption with total sell)
  lp_solver: 'default' # set the name of the linear programming solver that will be used. Options are 'PULP_CBC_CMD', 'GLPK_CMD' and 'COIN_CMD'. 
  lp_solver_path: 'empty' # set the path to the LP solver, COIN_CMD default is /usr/bin/cbc
  set_nocharge_from_grid: False # avoid battery charging from the grid
  set_nodischarge_to_grid: True # avoid battery discharging to the grid
  set_battery_dynamic: False # add a constraint to limit the dynamic of the battery power in power per time unit
  battery_dynamic_max: 0.9 # maximum dynamic positive power variation in percentage of battery maximum power
  battery_dynamic_min: -0.9 # minimum dynamic negative power variation in percentage of battery maximum power
  weight_battery_discharge: 0.0 # weight applied in cost function to battery usage for discharge
  weight_battery_charge: 0.0 # weight applied in cost function to battery usage for charge

plant_conf:
  P_from_grid_max: 9000 # The maximum power that can be supplied by the utility grid in Watts
  P_to_grid_max: 9000 # The maximum power that can be supplied to the utility grid in Watts
  module_model: # The PV module model
  - 'JA_Solar_JAM54S30_415_MR'
  inverter_model: # The PV inverter model
  - 'Hoymiles_Power_Electronics_Inc___HMS_800_2T_NA__240V_'
  surface_tilt: # The tilt angle of your solar panels
  - 30
  surface_azimuth: # The azimuth angle of your PV installation
  - 180
  modules_per_string: # The number of modules per string
  - 1
  strings_per_inverter: # The number of used strings per inverter
  - 2
  inverter_is_hybrid: False # Set if it is a hybrid inverter (PV+batteries) or not

For simplicity reasons I am passing all zeros for load_forecast_method for now.

The two deferrable loads are a warm water heat pump (450W or off) and a dishwasher (~60W), which shall run once a day and be done before 5pm

Here is what I get:

My questions are:

  • Why is the heat pump (light blue) not being turned off (0W) and on (450W) although I am specifying treat_def_as_semi_cont = True ?
  • Why is the dishwasher (cyan) started more than once a day although I am specifying set_def_constant = True ?

I am getting that the optimization assignment is “infeasable” but the device contrainsts cannot be altered, so I would expect the optimization to honor these contrainst given in the configuration file. Can anyone shed some light on this? Any hints are greatly appreaciated! Cheers, Jan

When the assignment is infeasible then the graphs won’t make sense or follow your parameters. It normally means that something isn’t quite right.
My simple guess is becuase your PV never gets above 450w it’s unable to optimise this correctly.
As a next step, I’d try one of the following:

  1. Check that the PV config is correct, it looks like you’re only getting a very low amount of PV being generated (maybe you don’t have enough models or strings to add up to your correct PV array).
  2. If you are only expecting a very low amount of PV, then try running it with just the 60w load and see if you can get an optimal result.

Thanks for the answer @altonius!

I just tried a vanilla config file (emhass/config_emhass.yaml at dd00d438df95d78210fef52638ce472aafaf1805 · davidusb-geek/emhass · GitHub) and I am still getting the “infeasable” flag. Could there any remnants which need deleting prior to trying new parameters?

Try a different weather forecast method.
You will get infeasible results if scrapper returns negative values.

Thanks @stevenwhately !!
That was it: I changed to weather_forecast_method: 'solcast' and now I finally get:

All as expected, thanks again for the help!

1 Like

Hi team, will I always run into issues with 0 days of history everytime I restart HA or is it just me?

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\n","ERROR - web_server - Unable to get sensor power photovoltaics, or sensor power load no var loads. Check HA sensors and their daily data

Yeah, I have that too. Every time I update HA or Emhass. Would have something to do with recorder settings. Somewhere above here it’s explained. I haven’t looked into it yet.

I always had that issue until I implemented an ‘include’ statement to restrict recording to a minimal list of sensors and deleted my recorder database to start afresh.

Now I’ve constructed a variable called input_text.fifo_buffer to pass into the MPC calculation as the load_power_forecast dictionary key, like Mark does. This avoids using the recorder database altogether.

THe way Mark does it is documeneted above (just search for fifo in this topic) and the way I do it using Node-Red is documented in my configuration doco here.

1 Like

Hi Guys, I came across this thread while looking for a solution to maximise the use of my solar production to heat the house. I have a 6 zone HVAC unit which i am trying to control with this EMS.

We normally set the HVAC to turn on in the living room and one of the bedrooms to 20°C. As the sun rises, i’ve noticed the bulk of the solar is getting exported back to the grid. Rather than send it back to the grid, i want the HVAC to utilize it by increasing the HVAC temperature gradually till it gets to about 23°C and then later in the afternoon as the sun begins to set, i want the HVAC to start dropping the temperature back to 20°C. This will allow me to maximize the consumption of the solar production for our comfort rather than send it back to the grid for peanuts.

i installed EMSHaas and done the initial configuration to set the optimization schedule, but how should i proceed from here?

I’ve borrowed some parts of your code in node-red and been running for a while now. It’s running fine from what I can see.

1 Like

Is it possible to have a Deferrable load start immediately, and then stay on until it is turned off?

Getting some crazy numbers, but still claiming to be optimal ;-(

Very hard to debug which constraint is causing this issue.

2024-06-23 11:56:30,195 - web_server - INFO - Passed runtime parameters: {'prod_price_forecast': [-0.02, -0.02, -0.01, -0.01, 0.08, 0.1, 0.09, 0.21, 0.24, 0.31, 0.4, 0.49, 0.53, 0.5, 0.45, 0.4, 0.4, 0.39, 0.33, 0.3, 0.27, 0.28, 0.28, 0.16, 0.15, 0.11, 0.15, 0.11, 0.11, 0.08, 0.09, 0.09], 'load_cost_forecast': [0.05, 0.05, 0.06, 0.06, 0.16, 0.18, 0.18, 0.31, 0.48, 0.56, 0.66, 0.76, 0.8, 0.77, 0.71, 0.66, 0.66, 0.65, 0.44, 0.41, 0.37, 0.39, 0.39, 0.25, 0.25, 0.2, 0.25, 0.21, 0.2, 0.17, 0.18, 0.18], 'prediction_horizon': 31, 'alpha': 0, 'beta': 1, 'soc_init': 0.578, 'def_start_timestep': [0, 0, 19], 'def_end_timestep': [0, 0, 34], 'def_total_hours': [1, 0, 6], 'soc_final': 0.08}
2024-06-23 11:56:30,196 - web_server - INFO -  >> Setting input data dict
2024-06-23 11:56:30,197 - web_server - INFO - Setting up needed data
2024-06-23 11:56:30,207 - web_server - INFO - Retrieve hass get data method initiated...
2024-06-23 11:56:35,571 - web_server - INFO - Retrieving weather forecast data using method = scrapper
2024-06-23 11:56:40,408 - web_server - INFO - Retrieving data from hass for load forecast using method = naive
2024-06-23 11:56:40,411 - web_server - INFO - Retrieve hass get data method initiated...
2024-06-23 11:56:52,887 - web_server - INFO -  >> Performing naive MPC optimization...
2024-06-23 11:56:52,888 - web_server - INFO - Performing naive MPC optimization
2024-06-23 11:56:52,953 - web_server - INFO - Perform an iteration of a naive MPC controller
2024-06-23 11:56:53,137 - web_server - DEBUG - Deferrable load 0: Proposed optimization window: 0 --> 0
2024-06-23 11:56:53,138 - web_server - DEBUG - Deferrable load 0: Validated optimization window: 0 --> 0
2024-06-23 11:56:53,161 - web_server - DEBUG - Deferrable load 1: Proposed optimization window: 0 --> 0
2024-06-23 11:56:53,162 - web_server - DEBUG - Deferrable load 1: Validated optimization window: 0 --> 0
2024-06-23 11:56:53,185 - web_server - DEBUG - Deferrable load 2: Proposed optimization window: 19 --> 34
2024-06-23 11:56:53,185 - web_server - DEBUG - Deferrable load 2: Validated optimization window: 19 --> 31
2024-06-23 11:56:54,372 - web_server - INFO - Status: Optimal
2024-06-23 11:56:54,373 - web_server - INFO - Total value of the Cost function = 10251017.19
2024-06-23 11:56:55,556 - web_server - INFO - Passed runtime parameters: {'custom_unit_load_cost_id': {'entity_id': 'sensor.unit_load_cost', 'unit_of_measurement': '$/kWh', 'friendly_name': 'Load Cost'}, 'custom_unit_prod_price_id': {'entity_id': 'sensor.unit_prod_price', 'unit_of_measurement': '$/kWh', 'friendly_name': 'Prod Price'}}
2024-06-23 11:56:55,557 - web_server - INFO -  >> Setting input data dict
2024-06-23 11:56:55,558 - web_server - INFO - Setting up needed data
2024-06-23 11:56:55,567 - web_server - INFO -  >> Publishing data...
2024-06-23 11:56:55,567 - web_server - INFO - Publishing data to HASS instance
2024-06-23 11:56:55,655 - web_server - INFO - Successfully posted to sensor.p_pv_forecast = 6684.58
2024-06-23 11:56:55,718 - web_server - INFO - Successfully posted to sensor.p_load_forecast = 1017.38
2024-06-23 11:56:55,755 - web_server - INFO - Successfully posted to sensor.p_pv_curtailment = 0.0
2024-06-23 11:56:55,795 - web_server - INFO - Successfully posted to sensor.p_deferrable0 = 3600.0
2024-06-23 11:56:55,834 - web_server - INFO - Successfully posted to sensor.p_deferrable1 = 0.0
2024-06-23 11:56:55,871 - web_server - INFO - Successfully posted to sensor.p_deferrable2 = 125012500000.0
2024-06-23 11:56:55,909 - web_server - INFO - Successfully posted to sensor.p_batt_forecast = 50004992000.0
2024-06-23 11:56:55,952 - web_server - INFO - Successfully posted to sensor.soc_batt_forecast = -92782642.2
2024-06-23 11:56:55,990 - web_server - INFO - Successfully posted to sensor.p_grid_forecast = -25002494000.0
2024-06-23 11:56:56,024 - web_server - INFO - Successfully posted to sensor.total_cost_fun_value = 10251020.84
2024-06-23 11:56:56,056 - web_server - INFO - Successfully posted to sensor.optim_status = Optimal
2024-06-23 11:56:56,093 - web_server - INFO - Successfully posted to sensor.unit_load_cost = 0.05
2024-06-23 11:56:56,130 - web_server - INFO - Successfully posted to sensor.unit_prod_price = -0.02

Fixed: Reduced battery_minimum_state_of_charge from 0.05 to 0 and numbers are sensible again…

Seeing some odd def_end_timestep optimisations with my 600 W heat pump, which I want to complete a 6 hour run by sunset.

p_nom is 600W, but then just before the def_end_timestep it tries to schedule 4800W for this load?

I have been using EMHASS for two years now and it works perfectly for me. However, PPVmix with the coefficients alpha and beta (tried all variants) simply does not work for me (the values do not change at all). Here, for example a mpc call, with a prediction horizon of 10, first value in the array is the actual PV Power Sensor .
Input:
“pv_power_forecast”: [3569, 8171, 7695, 6282, 5381, 4683, 3723, 2635, 1803, 1344]
Output:

No errors in the log, status: optimal

I’ll answer myself if anyone else finds it useful-
It is no more difficult than taking the time it should be on, which in my case is the washing machine for 1 hour. Then send mpc-optim

"def_end_timestep": [1, 0, 0]

I think I have asked of this earlier. But im almost completed a Geothermal Heat Pump at home with a big accumulation tank.

Any suggestions on how we can use emhass to control this?

What setting did you set for this load on treat_def_as_semi_cont ? I believe I had similar behaviour (charging my car with 6000*6 watts…), but this did not happen after I set the treat_def_as_semi_cont to true.

treat_def_as_semi_cont is true