EMHASS add-on: An energy management optimization add-on for Home Assistant OS and supervised

Nice and thanks for sharing! :+1:


Its almost perfekt. Forcast start alitlebit early. Could this be the azimuth be adjusted to fix?

Is your time zone in /config/general correctly defined?

Yes. In settings general.

Ok, so you wrote about the azimuth, are sure about thosz values. Double check tilt and azimuth parameters. You should have two different set of values for each of those parameters.

A third method uses the Solar.Forecast service. You will need to set method=solar.forecast and use just one parameter solar_forecast_kwp (the PV peak installed power in kW) that should be passed at runtime.

I need som help to setup up the Solar.Forecast service. I get errors in the Emhass log when I do a Day-Ahead optimization. I am using this shell command:

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

  trigger_nordpool_forecast: 'curl -i -H "Content-Type: application/json" -X POST -d ''{"solar_forecast_kwp":5,"load_cost_forecast":{{((state_attr(''sensor.nordpool'', ''raw_today'') | map(attribute=''value'') | list  + state_attr(''sensor.nordpool'', ''raw_tomorrow'') | map(attribute=''value'') | list))[now().hour:][:24] }},"prod_price_forecast":{{((state_attr(''sensor.nordpool'', ''raw_today'') | map(attribute=''value'') | list  + state_attr(''sensor.nordpool'', ''raw_tomorrow'') | map(attribute=''value'') | list))[now().hour:][:24]}}}'' http://localhost:5000/action/dayahead-optim'

The log gives these errors:

Traceback (most recent call last):
  File "/usr/local/lib/python3.9/dist-packages/flask/app.py", line 2525, in wsgi_app
    response = self.full_dispatch_request()
  File "/usr/local/lib/python3.9/dist-packages/flask/app.py", line 1822, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/usr/local/lib/python3.9/dist-packages/flask/app.py", line 1820, in full_dispatch_request
    rv = self.dispatch_request()
  File "/usr/local/lib/python3.9/dist-packages/flask/app.py", line 1796, 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 135, 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 81, in set_input_data_dict
    df_weather = fcst.get_weather_forecast(method=optim_conf['weather_forecast_method'])
  File "/usr/local/lib/python3.9/dist-packages/emhass/forecast.py", line 248, in get_weather_forecast
    "/"+str(self.plant_conf["surface_tilt"])+"/"+str(self.plant_conf["surface_azimuth"]-180)+\
TypeError: unsupported operand type(s) for -: 'list' and 'int'
[2023-02-06 20:13:46,801] INFO in command_line: Setting up needed data
[2023-02-06 20:13:46,804] ERROR in utils: ERROR: The passed data is either not a list or the length is not correct, length should be 24
[2023-02-06 20:13:46,805] ERROR in utils: Passed type is <class 'list'> and length is 24
[2023-02-06 20:13:46,806] ERROR in utils: ERROR: The passed data is either not a list or the length is not correct, length should be 24
[2023-02-06 20:13:46,806] ERROR in utils: Passed type is <class 'list'> and length is 24
[2023-02-06 20:13:46,812] INFO in forecast: Retrieving weather forecast data using method = solar.forecast
[2023-02-06 20:13:46,813] ERROR in app: Exception on /action/dayahead-optim [POST]
Traceback (most recent call last):
  File "/usr/local/lib/python3.9/dist-packages/flask/app.py", line 2525, in wsgi_app
    response = self.full_dispatch_request()
  File "/usr/local/lib/python3.9/dist-packages/flask/app.py", line 1822, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/usr/local/lib/python3.9/dist-packages/flask/app.py", line 1820, in full_dispatch_request
    rv = self.dispatch_request()
  File "/usr/local/lib/python3.9/dist-packages/flask/app.py", line 1796, 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 135, 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 81, in set_input_data_dict
    df_weather = fcst.get_weather_forecast(method=optim_conf['weather_forecast_method'])
  File "/usr/local/lib/python3.9/dist-packages/emhass/forecast.py", line 248, in get_weather_forecast
    "/"+str(self.plant_conf["surface_tilt"])+"/"+str(self.plant_conf["surface_azimuth"]-180)+\
TypeError: unsupported operand type(s) for -: 'list' and 'int'

The config for the solar panels, microinverter, azimuth, angle are publish here:

You may have just found a bug. I’ll check this and solve it if is a bug indeed as soon as I can. Please open a github issue

Thanks. I make a github issue now.

How many array are supported? Beacause i’ve got one inverter for each panel and 3 different direction with 15panel :sweat_smile: :sweat_smile: I didn’t figure it out how to setup…

Yes it is possible, no problem at all. Do you have micro-inverters?
Provide your data as lists.
The plant_conf part of your configuration will look something like this, this is an example of a total of 9 PV modules with micro inverters and three different orientations. You have to adapt to your case but you get the idea:

plant_conf:
  - module_model: # The PV module model
    - '<your_pv_module_model>'
    - '<your_pv_module_model>'
    - '<your_pv_module_model>'
    - '<your_pv_module_model>'
    - '<your_pv_module_model>'
    - '<your_pv_module_model>'
    - '<your_pv_module_model>'
    - '<your_pv_module_model>'
    - '<your_pv_module_model>'
  - inverter_model: # The PV inverter model
    - '<your_micro_inverter_model>'
    - '<your_micro_inverter_model>'
    - '<your_micro_inverter_model>'
    - '<your_micro_inverter_model>'
    - '<your_micro_inverter_model>'
    - '<your_micro_inverter_model>'
    - '<your_micro_inverter_model>'
    - '<your_micro_inverter_model>'
    - '<your_micro_inverter_model>'
  - surface_tilt: # The tilt angle of your solar panels
    - 30
    - 30
    - 30
    - 30
    - 30
    - 30
    - 30
    - 30
    - 30
  - surface_azimuth: # The azimuth angle of your PV installation
    - 245
    - 245
    - 245
    - 180
    - 180
    - 180
    - 155
    - 155
    - 155
  - modules_per_string: # The number of modules per string
    - 1
    - 1
    - 1
    - 1
    - 1
    - 1
    - 1
    - 1
    - 1
  - strings_per_inverter: # The number of used strings per inverter
    - 1
    - 1
    - 1
    - 1
    - 1
    - 1
    - 1
    - 1
    - 1
hass_url: empty
long_lived_token: empty
costfun: profit
optimization_time_step: 30
historic_days_to_retrieve: 2
method_ts_round: nearest
set_total_pv_sell: false
lp_solver: COIN_CMD
lp_solver_path: /usr/bin/cbc
set_nocharge_from_grid: false
load_forecast_method: naive
sensor_power_photovoltaics: sensor.envoy_122148032805_current_power_production
sensor_power_load_no_var_loads: sensor.power_load_no_var_loads
number_of_deferrable_loads: 1
list_nominal_power_of_deferrable_loads:
  - nominal_power_of_deferrable_loads: 500
list_operating_hours_of_each_deferrable_load:
  - operating_hours_of_each_deferrable_load: 8
list_peak_hours_periods_start_hours:
  - peak_hours_periods_start_hours: "08:00"
list_peak_hours_periods_end_hours:
  - peak_hours_periods_end_hours: "18:30"
list_treat_deferrable_load_as_semi_cont:
  - treat_deferrable_load_as_semi_cont: true
load_peak_hours_cost: 0.428
load_offpeak_hours_cost: 0.409
photovoltaic_production_sell_price: 0.065
maximum_power_from_grid: 4500
list_pv_module_model:
  - pv_module_model: Hyundai_Heavy_Industries_Green_Energy_Co__HiS_S360RI
  - pv_module_model: Hyundai_Heavy_Industries_Green_Energy_Co__HiS_S360RI
  - pv_module_model: Hyundai_Heavy_Industries_Green_Energy_Co__HiS_S360RI
  - pv_module_model: Hyundai_Heavy_Industries_Green_Energy_Co__HiS_S360RI
  - pv_module_model: Hyundai_Heavy_Industries_Green_Energy_Co__HiS_S360RI
  - pv_module_model: Hyundai_Heavy_Industries_Green_Energy_Co__HiS_S360RI
  - pv_module_model: Hyundai_Heavy_Industries_Green_Energy_Co__HiS_S360RI
  - pv_module_model: Hyundai_Heavy_Industries_Green_Energy_Co__HiS_S360RI
  - pv_module_model: Hyundai_Heavy_Industries_Green_Energy_Co__HiS_S360RI
  - pv_module_model: Hyundai_Heavy_Industries_Green_Energy_Co__HiS_S360RI
  - pv_module_model: Hyundai_Heavy_Industries_Green_Energy_Co__HiS_S360RI
  - pv_module_model: Hyundai_Heavy_Industries_Green_Energy_Co__HiS_S360RI
  - pv_module_model: Hyundai_Heavy_Industries_Green_Energy_Co__HiS_S360RI
  - pv_module_model: Hyundai_Heavy_Industries_Green_Energy_Co__HiS_S360RI
  - pv_module_model: Hyundai_Heavy_Industries_Green_Energy_Co__HiS_S360RI
list_pv_inverter_model:
  - pv_inverter_model: Enphase_Energy_Inc___IQ7PLUS_72_x_US__240V_
  - pv_inverter_model: Enphase_Energy_Inc___IQ7PLUS_72_x_US__240V_
  - pv_inverter_model: Enphase_Energy_Inc___IQ7PLUS_72_x_US__240V_
  - pv_inverter_model: Enphase_Energy_Inc___IQ7PLUS_72_x_US__240V_
  - pv_inverter_model: Enphase_Energy_Inc___IQ7PLUS_72_x_US__240V_
  - pv_inverter_model: Enphase_Energy_Inc___IQ7PLUS_72_x_US__240V_
  - pv_inverter_model: Enphase_Energy_Inc___IQ7PLUS_72_x_US__240V_
  - pv_inverter_model: Enphase_Energy_Inc___IQ7PLUS_72_x_US__240V_
  - pv_inverter_model: Enphase_Energy_Inc___IQ7PLUS_72_x_US__240V_
  - pv_inverter_model: Enphase_Energy_Inc___IQ7PLUS_72_x_US__240V_
  - pv_inverter_model: Enphase_Energy_Inc___IQ7PLUS_72_x_US__240V_
  - pv_inverter_model: Enphase_Energy_Inc___IQ7PLUS_72_x_US__240V_
  - pv_inverter_model: Enphase_Energy_Inc___IQ7PLUS_72_x_US__240V_
  - pv_inverter_model: Enphase_Energy_Inc___IQ7PLUS_72_x_US__240V_
  - pv_inverter_model: Enphase_Energy_Inc___IQ7PLUS_72_x_US__240V_
list_surface_tilt:
  - surface_tilt: 25
  - surface_tilt: 25
  - surface_tilt: 25
  - surface_tilt: 25
  - surface_tilt: 25
  - surface_tilt: 25
  - surface_tilt: 25
  - surface_tilt: 25
  - surface_tilt: 25
  - surface_tilt: 25
  - surface_tilt: 25
  - surface_tilt: 25
  - surface_tilt: 25
  - surface_tilt: 25
  - surface_tilt: 25
list_surface_azimuth:
  - surface_azimuth: 90
  - surface_azimuth: 90
  - surface_azimuth: 90
  - surface_azimuth: 90
  - surface_azimuth: 180
  - surface_azimuth: 180
  - surface_azimuth: 180
  - surface_azimuth: 180
  - surface_azimuth: 270
  - surface_azimuth: 270
  - surface_azimuth: 270
  - surface_azimuth: 270
  - surface_azimuth: 270
  - surface_azimuth: 270
  - surface_azimuth: 270
list_modules_per_string:
  - modules_per_string: 1
  - modules_per_string: 1
  - modules_per_string: 1
  - modules_per_string: 1
  - modules_per_string: 1
  - modules_per_string: 1
  - modules_per_string: 1
  - modules_per_string: 1
  - modules_per_string: 1
  - modules_per_string: 1
  - modules_per_string: 1
  - modules_per_string: 1
  - modules_per_string: 1
  - modules_per_string: 1
  - modules_per_string: 1
list_strings_per_inverter:
  - strings_per_inverter: 1
  - strings_per_inverter: 1
  - strings_per_inverter: 1
  - strings_per_inverter: 1
  - strings_per_inverter: 1
  - strings_per_inverter: 1
  - strings_per_inverter: 1
  - strings_per_inverter: 1
  - strings_per_inverter: 1
  - strings_per_inverter: 1
  - strings_per_inverter: 1
  - strings_per_inverter: 1
  - strings_per_inverter: 1
  - strings_per_inverter: 1
  - strings_per_inverter: 1
set_use_battery: false
battery_discharge_power_max: 1000
battery_charge_power_max: 1000
battery_discharge_efficiency: 0.95
battery_charge_efficiency: 0.95
battery_nominal_energy_capacity: 5000
battery_minimum_state_of_charge: 0.3
battery_maximum_state_of_charge: 0.9
battery_target_state_of_charge: 0.6

I set like your example but looking at the max forecast power it seems to take only 4 inverters or panel.
I have 15 enphase iq7 plus at 290W max power. I can reach over 3kW but i’ve never seen such forecast power. The forecast peak at 1270W.

This works, it has been fully tested before.
That 1270W is may be just what it is no? You will have a not so good PV production day…

Thanks for your help if you say that this configuration is fine. I’ll wait and see if it will improve. You have made a great job.

Thanks.
Ok there is a way to check this. Plot that PV forecast using APEX charts (look for the examples in the APEX charts topic). If the resulting forecast is a clear-sky bell like shaped graph that peaks at 1270W then we have a problem. Otherwise if it seems like a typical cloudy day then it should be ok. And you’re right check on the following days to see if it is performing well in the long term.

Hi, so slowly I do not know what to do. I have four deferrables, of which I want three to be constant and one not. But something very strange happens.

with “set_def_constant: false false false false” the following happens:

but with “set_def_constant: true, true, true, false” the following happens.
(all deferabbles set to true are packed to the end of the chart, where they don’t make any sense)

could someone check if this is the case for you too?

my config:

hass_url: empty
long_lived_token: empty
costfun: profit
optimization_time_step: 60
historic_days_to_retrieve: 8
method_ts_round: nearest
set_total_pv_sell: false
lp_solver: COIN_CMD
lp_solver_path: /usr/bin/cbc
set_nocharge_from_grid: false
load_forecast_method: naive
sensor_power_photovoltaics: sensor.scb_ac_power
sensor_power_load_no_var_loads: sensor.emhass_var_no_load_without_unknown
number_of_deferrable_loads: 4
list_nominal_power_of_deferrable_loads:
  - nominal_power_of_deferrable_loads: 2000
  - nominal_power_of_deferrable_loads: 2100
  - nominal_power_of_deferrable_loads: 800
  - nominal_power_of_deferrable_loads: 3000
list_operating_hours_of_each_deferrable_load:
  - operating_hours_of_each_deferrable_load: 1
  - operating_hours_of_each_deferrable_load: 2
  - operating_hours_of_each_deferrable_load: 1
  - operating_hours_of_each_deferrable_load: 2
list_peak_hours_periods_start_hours:
  - peak_hours_periods_start_hours: "02:54"
list_peak_hours_periods_end_hours:
  - peak_hours_periods_end_hours: "15:55"
list_treat_deferrable_load_as_semi_cont:
  - treat_deferrable_load_as_semi_cont: true
  - treat_deferrable_load_as_semi_cont: true
  - treat_deferrable_load_as_semi_cont: true
  - treat_deferrable_load_as_semi_cont: true
load_peak_hours_cost: 0.2741
load_offpeak_hours_cost: 0.2741
photovoltaic_production_sell_price: 0.1592
maximum_power_from_grid: 11000
list_pv_module_model:
  - pv_module_model: JA_Solar_JAP6_60_245_MP
list_pv_inverter_model:
  - pv_inverter_model: HiQ_Solar__TSXL480_10k__480V_
list_surface_tilt:
  - surface_tilt: 30
list_surface_azimuth:
  - surface_azimuth: 125
list_modules_per_string:
  - modules_per_string: 30
list_strings_per_inverter:
  - strings_per_inverter: 1
set_use_battery: false
battery_discharge_power_max: 5000
battery_charge_power_max: 2560
battery_discharge_efficiency: 0.95
battery_charge_efficiency: 0.95
battery_nominal_energy_capacity: 5000
battery_minimum_state_of_charge: 0.3
battery_maximum_state_of_charge: 0.9
battery_target_state_of_charge: 0.6

By how the optimization is formulated with the current code is very easy to fall into unfeasible situations when playing with set_def_constant. So check the optimization status in the logs to see if that’s the case. This works perfectly with one deferrable load but I may have to dig for a solution with multiple deferrables. I kind of see why this introduces a hard constraint that makes the problem unsolvable but it need to be tested. One option is to add relaxations to the LP formulation. It has been on the road map for a while so it is may be time to dig into it. If the problem is unfeasibility and it persist then please open a github issue to treat it properly.

2 Likes

Very interesting Add-on! I’m eager to see if this will help with my energy optimization. :smiley:

I’m stuck at the beginning - I’ve set up a preliminary configuration and wish to see the Web UI screen and output (if any). Unfortunately, I have not been able to connect to my HA IP address at port 5000. I get a “connection refused” error. :confused:

I have no such difficulty accessing the HA UI on port 8123, so I thought I’d check to see if port 5000 is listening.

netstat shows that 0.0.0.0:5000 is in the LISTEN state, as are other ports such as 8123 and 4357. As a test, I can also access the HA ip address at port 4357 and that works (“Home Assistant Observer”).

I’ve tried binding several other available port numbers in the EMHASS configuration with the same result (netstat confirms that the configured port is in the LISTEN state each time, but I cannot connect to my HA ip on that port).

The log does show a couple of errors such as:

File “/usr/local/lib/python3.9/dist-packages/requests/models.py”, line 439, in prepare_url
raise MissingSchema(
requests.exceptions.MissingSchema: Invalid URL ‘/api/config’: No scheme supplied. Perhaps you meant https:///api/config?

I do have a firewall (OPNsense), but I’ve defined no specific rules based on port numbers. My HA device is on a dedicated IOT VLAN, but I allow traffic from the IOT VLAN to my WAN where I connect my PC.

I’d appreciate advice. Thank you.

Hi, thanks!
This has always been problematic, but that GUI is only used to check that everything is working fine before setting up the automations that will handle the functions of the add-on later.
In my case I’m only able to access it from my LAN using the IP address of my HA instance. So if HA is at for example 192.168.0.50, then access the GUI at http://192.168.0.50:5000/

You are welcome! It looks awesome. :smiley:

I am using my local ip address for HA at 192.168.xx.xxx:5000.

I’ll review the documentation and see what I can do regarding automations. I’m currently controlling use of two heat pumps to make use of solar power generation during peak-rate periods. But when it will be cloudy, I wish to pre-condition the temperature off-peak. On the other hand, when the outdoor temperature will be mild I can be less aggressive and even sell excess solar to the utility.

My current approach is functional but not optimized. I’m eager to see what EMHASS can do!

Thanks again.

I’ve started looking at this again. My apologies for novice issues/questions. :confused:
I am using the Add-On in HAOS installed on an ODROID-N2+.

  1. I restarted EMHass and waited one day. I do not find sensor.p_deferrable0 in my entity list. So I assume I have not configured EMHass correctly. Would it help if I shared my logs or all of my settings?
  2. I do not understand the definition for:

sensor_power_load_no_var_loads: The name of the household power consumption sensor in Watts from Home Assistant. The deferrable loads that we will want to include in the optimization problem should be substracted from this sensor in HASS. For example: ‘sensor.power_load_no_var_loads’

In my case the deferable loads are two air-air heat pumps, and I do not have sensors for these heat pumps. These heat pumps have nominal power draws of 4000 and 2800 watts (but actual power use varies since the heat pumps are modern inverter-based units). Do I need to provide sensor data from these two loads to use EMHass?

I’ve defined the following template sensor, but to be honest I don’t think it’s useful since most of the time it reads “0.” Here I’m subtracting the total of the two nominal deferable loads (fixed 6800 watts) from the home energy use, limiting the minimum to “0.”

 - platform: template
    sensors:
      power_load_no_var_loads: # Power Use minus EMHass variable load total
        friendly_name: "Power without deferable loads"
        unit_of_measurement: "W"
        value_template: >
          {% if (states('sensor.energy_usage') | int(0) - 6800 | int(0)) > 0 %}
            {{ (states('sensor.energy_usage') | int(0) - 6800 | int(0)) }}
          {% else -%}
            0

Modifying this sensor with the actual load values would give a more sensible number, I think.

I would appreciate any guidance. I look forward to experimenting with this awesome add-on! :smiley: