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

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:

EMHASS will function better if you have sensors for these devices, but you can work around.

Powercalc - Virtual power sensors will allow you to setup virtual power sensors that can change depending on the mode of your HVAC

This is what I use:

- platform: powercalc  
  entity_id: climate.daikin_ap33073
  fixed:
    states_power: 
      heat: 4500
      cool: 4000
      dry: 2000
      fan_only: 400

sensor.power_load_no_var_loads needs to be setup to only subtract the load values when the device is operational.

2 Likes

Thanks @markpurcell

That makes good sense. Will give it a go! :grinning:

1 Like

Hi @markpurcell

Thanks again for your help. Iā€™ve had a bit of a challenge with Powercalc, but I did manage to create template sensors for power from the two heat pumps, and a template sensor power_load_no_var_loads.


(Note that ā€œEnergy Useageā€ is mislabeled - that comes from the Sense integration. It should read Powerā€¦).

Iā€™m not sure this is a useful sensor, though, since my heat pumps represent the primary loads most of the time, and since both loads are variable.

In any case, Iā€™m also having difficulty with EMHass - the web UI wonā€™t load, and even though Iā€™m running the required shell command services, I do not see an entity sensor.p_deferrable0. So Iā€™m going to pause for now and watch the development of this Add-On.

Iā€™ll make another topic that discusses how Iā€™m managing my two (heat pump) loads at present. Itā€™s complex enough with just two loads to manage - I do see a need for much more flexibility and look-ahead forecasting.

Thanks again!

Hello everybody,
Iā€™m starting playing around so a newbie on this cool project.
Sorry if Iā€™m asking something obvious to some of you.
My (first) question is if the only allowed PV and inverter models are the one linked in the documentation of the add-on (back from 2019 it seems) or if we can also use the updated lists from the NREL/SAM project mentioned in the ā€œpythonā€ thread (or if there is any plan to update the list accepted by the add-on).
Thanks!

EDIT:
or if we can manually update the list ourselves: it seems there is only one extra column (Manufacturer) in the updated file for PV modules, if compared to the 2019 one.

The PV forecast scrape method is using the PVLib Python module to convert from irradiance to Watts. So as you may understand is out of my hand to keep this database updated.
There have been some updates on PVLib but I donā€™t think that they updated their modules and inverter databases as we can see here: https://github.com/pvlib/pvlib-python/tree/main/pvlib/data
If you donā€™t find a suitable model on this database for you then you can use any of the other methods: Solcast, Forecast.Solar, a custom passed list from another service, etc.

This being said you may ask the PVLib maintainers and you may even try to update the database yourself. If like you said you just want to add a new column I donā€™t see why they will oppose to that.
In the meantime I will just update PVlib to the latest version.

Thank you,
Thatā€™s an option (passing solar forecast) I planned to have a look maybe at a later stage, once I have something running, I gain experience and I can fine tune.

Another question if I mayā€¦ Iā€™m trying to run my first optimization run and as I mentioned I wanted to make the least possible customizations for the moment.
How long does it take in your opinion to perform the optimization?
Iā€™m staying with the defaults (2 days historical data) and Iā€™m running it under a Pi3b+ (with a couple of PV models from the DB) but after two hours it seems nothing is happening/happened.
I also read in older posts that maybe under arm64 I may need to use a different solver, maybe GLPK. Do you think thatā€™s still the point? How do I find the right path of each solver?

This is my log.

Thanks again!

s6-rc: info: service s6rc-oneshot-runner: starting
s6-rc: info: service s6rc-oneshot-runner successfully started
s6-rc: info: service fix-attrs: starting
s6-rc: info: service fix-attrs successfully started
s6-rc: info: service legacy-cont-init: starting
s6-rc: info: service legacy-cont-init successfully started
s6-rc: info: service legacy-services: starting
services-up: info: copying legacy longrun emhass (no readiness notification)
s6-rc: info: service legacy-services successfully started
2023-08-02 13:20:42,324 - web_server - INFO - Launching the emhass webserver at: http://0.0.0.0:5000
2023-08-02 13:20:42,327 - web_server - INFO - Home Assistant data fetch will be performed using url: http://supervisor/core/api
2023-08-02 13:20:42,328 - web_server - INFO - The data path is: /share
2023-08-02 13:20:42,341 - web_server - INFO - Using core emhass version: 0.4.14
waitress   INFO  Serving on http://0.0.0.0:5000
2023-08-02 13:20:44,218 - web_server - INFO - EMHASS server online, serving index.html...
2023-08-02 13:20:44,250 - web_server - WARNING - The data container dictionary is empty... Please launch an optimization task
2023-08-02 13:21:07,184 - web_server - INFO - Setting up needed data
2023-08-02 13:21:07,512 - web_server - INFO - Retrieve hass get data method initiated...
2023-08-02 13:22:11,985 - web_server - INFO - Launching the emhass webserver at: http://0.0.0.0:5000
2023-08-02 13:22:11,987 - web_server - INFO - Home Assistant data fetch will be performed using url: http://supervisor/core/api
2023-08-02 13:22:11,987 - web_server - INFO - The data path is: /share
2023-08-02 13:22:12,033 - web_server - INFO - Using core emhass version: 0.4.14
waitress   INFO  Serving on http://0.0.0.0:5000
2023-08-02 15:35:04,018 - web_server - INFO - EMHASS server online, serving index.html...
2023-08-02 15:35:04,155 - web_server - WARNING - The data container dictionary is empty... Please launch an optimization task

You havenā€™t launch any optimization yet. You just started the add-on and the server is ready waiting for your instructions. You can send instructions to the server via some ā€œendpointsā€ using ā€œcurlā€ commands defined using the shell_command integration from Home Assistant.
Read the documentation and installation method 1 (Add-on) here: Intro / Quick start ā€” emhass 0.4.14 documentation