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

What is not working, is there an error message. If the forecast is not accurate can you show some plots?

Change the PV module to something closer to your module peak power (360W). For example Phono_Solar_Technology_Co__Ltd__PS360MH_24_T. For the inverter the Fronius 5kW should be ok.

On each of your inverters you have panels with different tilt/azimuth?

Depending on your answer you should modify accordingly but your configuration for two inverters should look like this:

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: 25
  - surface_tilt: 25
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

Does not seem to work.

2023-01-20 09:31:58,228] ERROR in app: Exception on /action/perfect-optim [POST]
Traceback (most recent call last):
  File "/usr/local/lib/python3.9/dist-packages/requests/models.py", line 971, in json
    return complexjson.loads(self.text, **kwargs)
  File "/usr/lib/python3.9/json/__init__.py", line 346, in loads
    return _default_decoder.decode(s)
  File "/usr/lib/python3.9/json/decoder.py", line 340, in decode
    raise JSONDecodeError("Extra data", s, end)
json.decoder.JSONDecodeError: Extra data: line 1 column 4 (char 3)
During handling of the above exception, another exception occurred:
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 134, in action_call
    input_data_dict = set_input_data_dict(config_path, str(config_path.parent), costfun,
  File "/usr/local/lib/python3.9/dist-packages/emhass/command_line.py", line 66, in set_input_data_dict
    rh.get_data(days_list, var_list,
  File "/usr/local/lib/python3.9/dist-packages/emhass/retrieve_hass.py", line 121, in get_data
    data = response.json()[0]
  File "/usr/local/lib/python3.9/dist-packages/requests/models.py", line 975, in json
    raise RequestsJSONDecodeError(e.msg, e.doc, e.pos)

Please show your configuration and the shell command that you’re using.
You’re trying to do what is called in EMHASS as “perfect optimization”, this is an optimization based on past historical and known values. If those historical values are not saved by the Home Assistant recorder then you will have this kind of issues.
The “Day-ahead optimization” is working?

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