perhaps anyone can share his experience about this question? Thanks!
I’d say it depends on your needs.
Can you run it with different horizons, depending on your needs?
Run it with an 8 hour horizon to see when the EV should charge, if you need it sooner than that. Then schedule the EV charge according to it.
Run the longer horizon prediction if you don’t need the EV that soon.
Maybe I was just assuming something apparent, and my apologies if so, but I’m not sure what your point is? Is it that the use of jinja template variables allow you to construct parts of the REST JSON?
In many cases it’s needed for other reasons as well. The sensor state limit of 255 characters you mention is one reason many sensors use attributes to store larger and more complex data, e.g. the Nordpool integration. In order to create a list from those attributes, you need a jinja template construct. However, it’s usually not required to store this in a variable as you can create the data on the fly in the call.
But in the case you need to apply a modification to a list in Homeassistant templates, like adding or multiplying values, you need a more complex namespace construct as you now did. In this case, and for readability, I agree that using variables to store data before creating the actual call is good practice.
For anyone using the Solcast Custom Integration, please be aware it has breaking changes in v4.0 and you will need to change your template for pv_forecast. Thanks to @anon7821378 for maintaining this integration which gives EMHASS access to great solar forecasts.
Here is my updated template:
"pv_power_forecast": {{
([states('sensor.solcast_pv_forecast_power_now')|int(0)] +
state_attr('sensor.solcast_pv_forecast_forecast_today', 'detailedForecast')|selectattr('period_start','gt',utcnow()) | map(attribute='pv_estimate')|map('multiply',1000)|map('int')|list +
state_attr('sensor.solcast_pv_forecast_forecast_tomorrow', 'detailedForecast')|selectattr('period_start','gt',utcnow()) | map(attribute='pv_estimate')|map('multiply',1000)|map('int')|list
)| tojson
}},
The sensor names have changed and the detailed forecast is now reporting power over 30 minutes in kW, so now needs to be multiplied by 1000 (not 2000 as previously required).
As always, please check your own configuration in the developer tools.
Hi all,
Im pritty new with coding and im more of a hobiest trying to make a complex system work.
Ive tried implimenting the emhass into my system and im following allong the link A real study case — emhass 0.5.0 documentation
The simplest thing and i cant seem to find as there isnt really a step guide.
- Ive got the emhass download
- Ive implimented the recommended shell commands i pasted this into configurations.yaml as directed
shell_command:
dayahead_optim: “curl -i -H “Content-Type:application/json” -X POST -d ‘{}’ http://localhost:5000/action/dayahead-optim”
publish_data: “curl -i -H “Content-Type:application/json” -X POST -d ‘{}’ http://localhost:5000/action/publish-data”
Also did the basic automation command.
- Ive filled the config file
hass_url: empty
long_lived_token: empty
costfun: self-consumption
logging_level: INFO
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
set_nodischarge_to_grid: false
set_battery_dynamic: false
battery_dynamic_max: 0.9
battery_dynamic_min: -0.9
load_forecast_method: list
sensor_power_photovoltaics: sensor.solar_total
sensor_power_load_no_var_loads: sensor.house_consumption
number_of_deferrable_loads: 1
list_nominal_power_of_deferrable_loads:- nominal_power_of_deferrable_loads: 3000
list_operating_hours_of_each_deferrable_load: - operating_hours_of_each_deferrable_load: 5
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: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: 9000
list_pv_module_model: - pv_module_model: CSUN_Eurasia_Energy_Systems_Industry_and_Trade_CSUN295_60M
list_pv_inverter_model: - pv_inverter_model: Fronius_International_GmbH__Fronius_Primo_5_0_1_208_240__240V_
list_surface_tilt: - surface_tilt: 30
list_surface_azimuth: - surface_azimuth: 205
list_modules_per_string: - modules_per_string: 16
list_strings_per_inverter: - strings_per_inverter: 1
set_use_battery: true
battery_discharge_power_max: 11600
battery_charge_power_max: 11600
battery_discharge_efficiency: 0.95
battery_charge_efficiency: 0.95
battery_nominal_energy_capacity: 40000
battery_minimum_state_of_charge: 0.2
battery_maximum_state_of_charge: 0.9
battery_target_state_of_charge: 0.6
- nominal_power_of_deferrable_loads: 3000
Simple part i would assume now push button and it would display graphs? This is the part im now lost and dont know were my info is haha,
Please go easy on me im new and learning
this is my log file
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-09-10 10:40:21,914 - web_server - INFO - Launching the emhass webserver at: http://0.0.0.0:5000
2023-09-10 10:40:21,915 - web_server - INFO - Home Assistant data fetch will be performed using url: http://supervisor/core/api
2023-09-10 10:40:21,915 - web_server - INFO - The data path is: /share
2023-09-10 10:40:21,916 - web_server - INFO - Using core emhass version: 0.5.0
waitress INFO Serving on http://0.0.0.0:5000
2023-09-10 10:40:37,932 - web_server - INFO - EMHASS server online, serving index.html…
2023-09-10 10:40:37,937 - web_server - WARNING - The data container dictionary is empty… Please launch an optimization task
2023-09-10 10:40:40,214 - web_server - INFO - Setting up needed data
2023-09-10 10:40:40,272 - web_server - INFO - Retrieving weather forecast data using method = scrapper
2023-09-10 10:40:42,278 - web_server - ERROR - Exception on /action/dayahead-optim [POST]
Traceback (most recent call last):
File “/usr/local/lib/python3.9/dist-packages/flask/app.py”, line 2190, in wsgi_app
response = self.full_dispatch_request()
File “/usr/local/lib/python3.9/dist-packages/flask/app.py”, line 1486, in full_dispatch_request
rv = self.handle_user_exception(e)
File “/usr/local/lib/python3.9/dist-packages/flask/app.py”, line 1484, in full_dispatch_request
rv = self.dispatch_request()
File “/usr/local/lib/python3.9/dist-packages/flask/app.py”, line 1469, 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 179, 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 91, in set_input_data_dict
P_load_forecast = fcst.get_load_forecast(method=optim_conf[‘load_forecast_method’])
File “/usr/local/lib/python3.9/dist-packages/emhass/forecast.py”, line 640, in get_load_forecast
if len(data_list) < len(self.forecast_dates) and self.params[‘passed_data’][‘prediction_horizon’] is None:
TypeError: object of type ‘NoneType’ has no len()
2023-09-10 10:40:51,600 - web_server - INFO - Setting up needed data
2023-09-10 10:40:51,605 - web_server - INFO - >> Publishing data…
2023-09-10 10:40:51,606 - web_server - INFO - Publishing data to HASS instance
2023-09-10 10:40:51,606 - web_server - ERROR - File not found error, run an optimization task first.
Hi
It’s always best to quote logs and code using the </> tool above, in the toolbar. This presents your data in a scrollable box and makes it easier to read.
This this where your code and logs shoud go .....................................................
Try going going to the UI on port 5000 and select the optimisation buttons. What do you see in the graph below.
It doesnt do anything.
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
OMG IGNORE ME its working haha. i turned it off and back on and reconfigured it, rebooted my device,
checked all config was there then booted. its now printing the values.
Woohooo
now my time to play around and put into apex cards
I do need to ask how do you get the sensors to be printed now from the optimisations?
Ive got the optimisation to work but i cant find it printing my sensor. Ive found a few automations to call for the change and i belive thats working but i cant find the sensor
Yes i want to do that,
If done the exact shell commands
Im reciving this errors
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-09-10 18:37:40,957 - web_server - INFO - Launching the emhass webserver at: http://0.0.0.0:5000
2023-09-10 18:37:40,957 - web_server - INFO - Home Assistant data fetch will be performed using url: http://supervisor/core/api
2023-09-10 18:37:40,957 - web_server - INFO - The data path is: /share
2023-09-10 18:37:40,958 - web_server - INFO - Using core emhass version: 0.5.0
waitress INFO Serving on http://0.0.0.0:5000
2023-09-10 18:37:43,624 - web_server - INFO - EMHASS server online, serving index.html...
2023-09-10 18:37:50,128 - web_server - INFO - Setting up needed data
2023-09-10 18:37:50,149 - web_server - INFO - Retrieve hass get data method initiated...
2023-09-10 18:37:51,566 - web_server - INFO - >> Performing perfect optimization...
2023-09-10 18:37:51,566 - web_server - INFO - Performing perfect forecast optimization
2023-09-10 18:37:51,569 - web_server - INFO - Perform optimization for perfect forecast scenario
2023-09-10 18:37:51,570 - web_server - INFO - Solving for day: 8-9-2023
2023-09-10 18:37:51,716 - web_server - INFO - Status: Optimal
2023-09-10 18:37:51,716 - web_server - INFO - Total value of the Cost function = 0.52
2023-09-10 18:37:51,723 - web_server - INFO - Solving for day: 9-9-2023
2023-09-10 18:37:51,864 - web_server - INFO - Status: Optimal
2023-09-10 18:37:51,864 - web_server - INFO - Total value of the Cost function = 0.8
2023-09-10 18:37:52,685 - web_server - INFO - Setting up needed data
2023-09-10 18:37:52,690 - web_server - INFO - Retrieving weather forecast data using method = scrapper
2023-09-10 18:37:54,760 - web_server - ERROR - Exception on /action/dayahead-optim [POST]
Traceback (most recent call last):
File "/usr/local/lib/python3.9/dist-packages/flask/app.py", line 2190, in wsgi_app
response = self.full_dispatch_request()
File "/usr/local/lib/python3.9/dist-packages/flask/app.py", line 1486, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/usr/local/lib/python3.9/dist-packages/flask/app.py", line 1484, in full_dispatch_request
rv = self.dispatch_request()
File "/usr/local/lib/python3.9/dist-packages/flask/app.py", line 1469, 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 179, 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 91, in set_input_data_dict
P_load_forecast = fcst.get_load_forecast(method=optim_conf['load_forecast_method'])
File "/usr/local/lib/python3.9/dist-packages/emhass/forecast.py", line 640, in get_load_forecast
if len(data_list) < len(self.forecast_dates) and self.params['passed_data']['prediction_horizon'] is None:
TypeError: object of type 'NoneType' has no len()
2023-09-10 18:37:56,913 - web_server - INFO - Setting up needed data
2023-09-10 18:37:56,917 - web_server - INFO - >> Publishing data...
2023-09-10 18:37:56,918 - web_server - INFO - Publishing data to HASS instance
2023-09-10 18:37:56,918 - web_server - ERROR - File not found error, run an optimization task first.
I do have to ask, do you need to setup your own sensors or the shell command does this?
Ive looked through the instructions and this entire thread and its not really mentioned, it kinda is done only through the publish data shell command.
Ive done the basics of just using
shell_command:
dayahead_optim: "curl -i -H \"Content-Type:application/json\" -X POST -d '{}' http://localhost:5000/action/dayahead-optim"
publish_data: "curl -i -H \"Content-Type:application/json\" -X POST -d '{}' http://localhost:5000/action/publish-data"
This still doesnt publish the data.
This was put in the configurations.yaml folder as required in the document
So it looks like you are passing no data.
if len(data_list) < len(self.forecast_dates) and self.params['passed_data']['prediction_horizon'] is None:
I’m no expert at this but the {} part of the dayahead-optim POST should have the data you want the system to process.
My post command looks like this:
{"load_cost_forecast":{{(([states('sensor.cecil_st_general_price')|float(0)] + state_attr('sensor.cecil_st_general_forecast', 'forecasts') |map(attribute='per_kwh')|list)[:48])
}},"prod_price_forecast":{{(([states('sensor.cecil_st_feed_in_price')|float(0)] + state_attr('sensor.cecil_st_feed_in_forecast', 'forecasts')|map(attribute='per_kwh')|list)[:48])
}},"pv_power_forecast":{{([states('sensor.sonnenbatterie_84324_production_w')|int(0)] +
state_attr('sensor.forecast_today', 'detailedForecast')|selectattr('period_start','gt',utcnow()) | map(attribute='pv_estimate')|map('multiply',2000)|map('int')|list +
state_attr('sensor.forecast_tomorrow', 'detailedForecast')|selectattr('period_start','gt',utcnow()) | map(attribute='pv_estimate')|map('multiply',2000)|map('int')|list)[:48]| tojson
}}}
You can see I’m using a template to pass data for the following:
- load_cost_forecast for the Load cost forecast.
- prod_price_forecast for the PV production selling price forecast.
- pv_power_forecast for the PV power production forecast.
This produces the following list:
{"load_cost_forecast":[0.47, 0.22, 0.28, 0.27, 0.21, 0.25, 0.26, 0.27, 0.26, 0.25, 0.23, 0.21, 0.2, 0.2, 0.2, 0.18, 0.18, 0.2, 0.2, 0.21, 0.21, 0.27, 0.28, 0.17, 0.11, 0.12, 0.19, 0.16, 0.12, 0.07, 0.04, 0.06, 0.04, 0.06, 0.06, 0.06, 0.06, 0.33, 0.35, 0.36, 0.35, 0.35, 0.43, 0.59, 0.78, 1.2, 1.2, 0.82],"prod_price_forecast":[0.37, 0.12, 0.17, 0.16, 0.11, 0.14, 0.16, 0.16, 0.15, 0.15, 0.13, 0.11, 0.09, 0.09, 0.09, 0.08, 0.08, 0.09, 0.09, 0.11, 0.11, 0.16, 0.17, 0.07, 0.02, 0.02, 0.09, 0.07, 0.03, -0.04, -0.07, -0.05, -0.07, -0.05, -0.05, -0.05, -0.05, 0.25, 0.27, 0.28, 0.27, 0.27, 0.34, 0.49, 0.66, 1.04, 1.04, 0.7],"pv_power_forecast":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 333, 845, 1389, 1925, 2486, 2917, 3257, 3545, 3768, 3895, 3968, 3963, 3901, 3743, 3526, 3258, 2893, 2451, 1874, 1354, 797, 245, 5, 0, 0, 0]}
I send this data between the curly brackets in the post command.
See this part of the manual here.
Have you got any experience with jinja templates?
By the way, you may only need to list the pv_power_forecast data if your feed-in tariff and supply tariff are static and included in the EMHASS configuration file (I think).
My tariffs change every 30 minutes, hence the lists of data for load_cost_forecast and prod_price_forecast. My electricity retailer provides this data.
Perhaps this will help. This is how I’ve configured my system:
My Setup
The only sensor you have to set up is the home consumption less any deferrable loads you want to manage. This sensor is then added to the EMHASS configuration file in the sensor_power_load_no_var_loads: line.
So the major issue im having is that my configuration is 4 different batteries. 2 x lg chem with solaredge. and 2 sperate sonnen batteries.
Im trying to somehow make sense of it and get the sensors to work.
Just add them together so you have a total storage value and a total max charge & discharge value.
So im going to post all my commands and setup, Ive managed to do a hole lot since the weekend and my first post including debugging my setup. ( It is soooo sensitive and ive copies someones value and wouldnt post anything)
So to start.
shell_command:
dayahead_optim: "curl -i -H \"Content-Type: application/json\" -X POST -d '{}' http://localhost:5000/action/dayahead-optim"
publish_data: "curl -i -H \"Content-Type: application/json\" -X POST -d '{}' http://localhost:5000/action/publish-data "
rest_command:
naive_mpc_optim:
url: http://localhost:5000/action/naive-mpc-optim
method: POST
content_type: 'application/json'
payload: >-
{
"prod_price_forecast": {{
([states('sensor.home_feed_in_price')|float(0)] +
(state_attr('sensor.home_feed_in_forecast', 'forecasts')|map(attribute='per_kwh')|list))
| tojson
}},
"load_cost_forecast": {{
([states('sensor.home_general_price')|float(0)] +
state_attr('sensor.home_general_forecast', 'forecasts') |map(attribute='per_kwh')|list)
| tojson
}},
"pv_power_forecast": {{
([states('sensor.solar_total')|int(0)] +
state_attr('sensor.solcast_pv_forecast_forecast_today', 'detailedForecast')|selectattr('period_start','gt',utcnow()) | map(attribute='pv_estimate')|map('multiply',2000)|map('int')|list +
state_attr('sensor.solcast_pv_forecast_forecast_tomorrow', 'detailedForecast')|selectattr('period_start','gt',utcnow()) | map(attribute='pv_estimate')|map('multiply',2000)|map('int')|list
)| tojson
}},
"prediction_horizon": {{
min(48, (state_attr('sensor.home_feed_in_forecast', 'forecasts')|map(attribute='per_kwh')|list|length)+1)
}},
"num_def_loads": 1,
"def_total_hours": [1,],
"P_deferrable_nom": [1300,],
"treat_def_as_semi_cont": [1,],
"set_def_constant": [0,],
"soc_init": {{(states('sensor.battery_total_2')|int(0))/100 }},
"soc_final": 0.2
}
Ive combined all my sensor battery values for SOC into the sensor battery total. The issue is that it displays a 400% value.
hass_url: empty
long_lived_token: empty
costfun: profit
logging_level: INFO
optimization_time_step: 30
historic_days_to_retrieve: 2
method_ts_round: first
set_total_pv_sell: false
lp_solver: COIN_CMD
lp_solver_path: /usr/bin/cbc
set_nocharge_from_grid: false
set_nodischarge_to_grid: false
set_battery_dynamic: false
battery_dynamic_max: 0.9
battery_dynamic_min: -0.9
load_forecast_method: naive
sensor_power_photovoltaics: sensor.solar_total
sensor_power_load_no_var_loads: sensor.house_consumption
number_of_deferrable_loads: 1
list_nominal_power_of_deferrable_loads:
- nominal_power_of_deferrable_loads: 1
list_operating_hours_of_each_deferrable_load:
- operating_hours_of_each_deferrable_load: 5
list_peak_hours_periods_start_hours:
- peak_hours_periods_start_hours: "10:00"
list_peak_hours_periods_end_hours:
- peak_hours_periods_end_hours: "16:00"
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: 20000
list_pv_module_model:
- pv_module_model: CSUN_Eurasia_Energy_Systems_Industry_and_Trade_CSUN295_60M
list_pv_inverter_model:
- pv_inverter_model: Fronius_International_GmbH__Fronius_Primo_5_0_1_208_240__240V_
list_surface_tilt:
- surface_tilt: 22
list_surface_azimuth:
- surface_azimuth: 75
list_modules_per_string:
- modules_per_string: 20
list_strings_per_inverter:
- strings_per_inverter: 1
set_use_battery: true
battery_discharge_power_max: 6600
battery_charge_power_max: 6600
battery_discharge_efficiency: 0.95
battery_charge_efficiency: 0.95
battery_nominal_energy_capacity: 40000
battery_minimum_state_of_charge: 0.1
battery_maximum_state_of_charge: 1
battery_target_state_of_charge: 0.1