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

Feel like nothing is working now. Tried to change the shell command but i do not think that one is working eather.

hass_url: empty
long_lived_token: empty
costfun: profit
optimization_time_step: 60
historic_days_to_retrieve: 2
method_ts_round: nearest
set_total_pv_sell: true
lp_solver: COIN_CMD
lp_solver_path: /usr/bin/cbc
sensor_power_photovoltaics: sensor.power_pv_all
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: 2000
list_operating_hours_of_each_deferrable_load:
  - operating_hours_of_each_deferrable_load: 6
list_peak_hours_periods_start_hours:
  - peak_hours_periods_start_hours: "02:54"
  - peak_hours_periods_start_hours: "17:24"
list_peak_hours_periods_end_hours:
  - peak_hours_periods_end_hours: "15:24"
  - peak_hours_periods_end_hours: "20:24"
list_treat_deferrable_load_as_semi_cont:
  - treat_deferrable_load_as_semi_cont: true
load_peak_hours_cost: 0.1907
load_offpeak_hours_cost: 0.1419
photovoltaic_production_sell_price: 0.065
maximum_power_from_grid: 4900
list_pv_module_model:
  - pv_module_model: Phono_Solar_Technology_Co__Ltd__PS360MH_24_T
  - pv_module_model: Phono_Solar_Technology_Co__Ltd__PS360MH_24_T
list_pv_inverter_model:
  - pv_inverter_model: Fronius_International_GmbH__Fronius_Primo_5_0_1_208_240__240V_
  - pv_inverter_model: Fronius_International_GmbH__Fronius_Primo_5_0_1_208_240__240V_
list_surface_tilt:
  - surface_tilt: 22
  - surface_tilt: 22
list_surface_azimuth:
  - surface_azimuth: 135
  - surface_azimuth: 135
list_modules_per_string:
  - modules_per_string: 12
  - modules_per_string: 12
list_strings_per_inverter:
  - strings_per_inverter: 1
  - strings_per_inverter: 1
set_use_battery: true
battery_discharge_power_max: 10000
battery_charge_power_max: 10000
battery_discharge_efficiency: 0.95
battery_charge_efficiency: 0.95
battery_nominal_energy_capacity: 18000
battery_minimum_state_of_charge: 0.3
battery_maximum_state_of_charge: 0.9
battery_target_state_of_charge: 0.6

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

  post_nordpool_forecast:
    'curl -i -H ''Content-Type: application/json'' -X POST -d ''{"load_cost_forecast":{{(
    (state_attr(''sensor.nordpool_kwh_krsand_nok_3_095_025'', ''raw_tomorrow'')|map(attribute=''value'')|list)[:24])
    }},"prod_price_forecast":{{(
    (state_attr(''sensor.nordpool_kwh_krsand_nok_3_10_0'', ''raw_tomorrow'')|map(attribute=''value'')|list)[:24])}}}'' http://localhost:5000/action/dayahead-optim'

Ok, so with that shell command what is the complete error log when you try to trigger post_nordpool_forecast?

Also check the data that you’re passing for load_cost_forecast and prod_price_forecast. Use the template editor to check for valid values.

Hard to say. we will wait to 23:57 again to see. since emhass cannot be restarted and published in the middle of the day since we are not parsing time and date we are only able to test this 23:57

You should be able to launch forecasts whenever you want. I understand that nordpool forecast are updated just one time a day but you should be able to manage that data and concatenate a list of values with the correct length expected by EMHASS.
You should be able to do that with templates and then trigger an optimization whenever you want.

aha, i see that now. I think its working again now. the price forcast would bee grat if we found a solution on from the nordpool?

Edit: seems like the forcast of grid comes in the wrong times and date when running on the middle of the day and not running 23:57?

For nordpool you have to concate today and tomorrow data list, so you definetly have 24h of to pass to EMHASS at any given time of the day.

Here is an option to append lists: [SOLVED] How to append items to list using Template?

Of course, because you’re only using “tomorrow” values. So if you run it at 23:57 everything is ok. But if you want to run it in the middle of the day then you should concatenate “today” + “tomorrow” values.

OK. thank you very much. I will try to understand this and will post an update on it when i figure it out. :slight_smile:

Is it something like this?

Only thing is that we need to remove everyting before current hour? and change null to 0?

{% set raw_today = state_attr('sensor.nordpool_kwh_krsand_nok_3_10_0', 'raw_today') %}
{% set raw_tomorrow = state_attr('sensor.nordpool_kwh_krsand_nok_3_10_0', 'raw_tomorrow') %}

{% set combined_list = raw_today|map(attribute='value')|list + raw_tomorrow|map(attribute='value')|list %}

{{ (combined_list | list)[:24] }}

edit, tested and woring. Including today and tomrow prices. removes expired prices and limit to 24. Worked for me mabey someone else also like to use it.

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

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

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