It would be good if you could provide an example.
Charging the value for time stamp rounding in the configuration also impacts when the value is applied in the time sequence.
It would be good if you could provide an example.
Charging the value for time stamp rounding in the configuration also impacts when the value is applied in the time sequence.
thanks. did not know about this one. will try to change this. And provide an example later if its not helping
I changes the SOC to what emhass forecast, when I do this the battery will charge to this from the grid if soc is lower. If higher the inverter will just grid peak shave and recharge to the set soc. If there is lots of pv it will charge untill 100% thats why I need to limit the charge amps.
There is also a grid meter the inveter uses to compancate the buy energy to 0 at all times if the soc is higher than the set soc. if lower grid energy will be used.
Mabey its badly explained but Im trying
you can see it explained here 3:50:
https://www.google.com/search?q=deye+hybrid&safe=active&rlz=1C1GCEB_enNO1039NO1039&sxsrf=APwXEdewuScwcjzU2dkCRIWeyhfMO34rtA:1685097442261&source=lnms&tbm=vid&sa=X&ved=2ahUKEwjfw9ST5ZL_AhWQbPEDHQMqAIwQ_AUoAnoECAEQBA&biw=1920&bih=969&dpr=1#fpstate=ive&vld=cid:fa44e90e,vid:V6hs4P4SVJ8
what I set from emhass is the time of use soc.
have tried them all. Cant find anything about this in the documentation explaining how they work. Seems like the profit works best for me exept that it wants to export to grid sometimes from the battery. I do not want this so I rather just feed my grid to 0 watts as long as there is enough energy and the soc is over the soc emhass recommends.
Are you still using solcast to forecast solar? And, are you calling the EMHASS API to update the forecast throughout the day/night?
If so, how are you handling passing in the correct number of samples to ensure your end battery SoC is correctly calculated? It looks like your graph extends for 24hrs into the future from when you took the screenshot.
At the moment I’m using the following, inspired by the docs, which appear to have been based on your post above in the first place. However I’m only calling this once a day (at 23:30), when my lower import rate starts. Since I don’t get any money for exporting, I’m storing all that I can use, and having to export the rest… This is today for example:
I’d like to keep the solar forecast up-to-date. It looks like you are still plotting a 24hr window constantly? Or are you also only calling it once?
Here’s my current config API calls:
publish_data: 'curl -i -H "Content-Type:application/json" -X POST -d ''{}'' http://localhost:5000/action/publish-data'
post_mpc_optim_solcast: 'curl -i -H "Content-Type: application/json" -X POST -d ''{"prediction_horizon":48,"pv_power_forecast":{{ states("sensor.solcast_24hrs_forecast") }}, "soc_init":{{ (states("sensor.battery_soc")|float(0))/100 }}}'' http://localhost:5000/action/naive-mpc-optim'
The optimisation call is run at 2330, and the publish just after that.
My EMHASS config uses the following for the SoC defaults:
battery_minimum_state_of_charge: 0.3
battery_maximum_state_of_charge: 0.9
battery_target_state_of_charge: 0.35
Also, I assume you’re doing something clever with your car, to ensure that it doesn’t drain from the powerwall (or maybe Tesla just does that all for you). I’ve also got an EV, but since we aren’t charging every day, I’ve set the deferrable load hrs to 0, so that it doesnt show up. At present I’m just changing my battery state to not discharge whenever the car is charging (it’s an MG4 with an Ohme charger, so I’ve got no smart control over it via Home Assistant)
Thanks!
Yes, I continue to employ Solcast for solar predictions, and I am indeed invoking the EMHASS API to update these forecasts around the clock.
I’m implementing a complex template formula for the PV forecast that leverages Solcast, as illustrated in the YAML code below:
\"pv_power_forecast\":{{[states('sensor.APF_Generation_Entity')|int(0)]
+ state_attr('sensor.solcast_forecast_today', 'detailedForecast')|selectattr('period_start','gt',utcnow())
| map(attribute='pv_estimate')|map('multiply',2000)|map('int')|list
+ state_attr('sensor.solcast_forecast_tomorrow', 'detailedForecast')|selectattr('period_start','gt',utcnow())
| map(attribute='pv_estimate')|map('multiply',2000)|map('int')|list}}
[states('sensor.APF_Generation_Entity')|int(0)]
Live Data
[4136]
This data is the first entry since I’m running the EMHASS MPC optimization every minute. Therefore, I use the live data for all my forecast variables (like load, price, cost, and PV). If you’re implementing a daily optimization process, injecting live data isn’t necessary.
Today’s Forecast
+ state_attr('sensor.solcast_forecast_today', 'detailedForecast')|selectattr('period_start','gt',utcnow())
| map(attribute='pv_estimate')|map('multiply',2000)|map('int')|list
Tomorrow’s Forecast
+ state_attr('sensor.solcast_forecast_tomorrow', 'detailedForecast')|selectattr('period_start','gt',utcnow())
| map(attribute='pv_estimate')|map('multiply',2000)|map('int')|list
Add in forecast_tomorrow in case forecast_today after utcnow is less than the required 48
I’m doing three things with my car, unfortunately charging the car still drains the household battery by default, even with all Tesla. To overcome this I have an automation to set the Powerwall backup reserve to the SOC_forecast from EMHASS when charging the EV. The Powerwall won’t discharge below this backup reserve so when I’m charging my EV it pulls from excess solar and the grid, which is what I want.
The second thing I do is have a complex template to calculate the def_hours for EV charging to inject into EMHASS.
- name: def_total_hours_ev
state: "{{is_state('automation.p_deferable2_automation','on')|abs
* (is_state('device_tracker.duka_location_tracker','home')|abs)
* (is_state('binary_sensor.duka_charger', 'on') | abs)
* (((states('number.duka_charge_limit')|int(0) - states('sensor.duka_battery')|int(0))/10+0.9)|int(0))|int(0)}}"
Here’s a more detailed breakdown of the calculation:
is_state('automation.p_deferable2_automation','on')|abs
: This checks if the automation p_deferable2_automation
is currently on. This confirms that I actually have my EV charging automation switched on.is_state('device_tracker.duka_location_tracker','home')|abs
: This checks if the device duka_location_tracker
is currently at home. This confirms the car is at home.is_state('binary_sensor.duka_charger', 'on') | abs
: This checks if the binary sensor duka_charger
is currently on. This confirms the location tracker for the car is home.(((states('number.duka_charge_limit')|int(0) - states('sensor.duka_battery')|int(0))/10+0.9)|int(0))|int(0)
: This calculates the number of hours needed to charge the EV based on the current battery level (sensor.duka_battery
) and the charge limit (number.duka_charge_limit
). The difference between the charge limit and the current battery level is divided by 10
(because the charger adds 10 units of charge per hour), then rounded up to the nearest whole number by adding 0.9
and converting to an integer.The result of each of these four parts is then multiplied together to get the final state of the def_total_hours_ev
sensor. If any of the conditions are not met (i.e., the automation is off, the device tracker is not at home, or the charging cable is not plugged in), then the state will be 0
. Otherwise, it will be the calculated number of hours needed to charge the EV to the specified limit.
The final piece is to set the EV charging_amps to match the EMHASS forecast for EV charging (deferrable load 2).
Thank you! I appreciate the detailed explaination
One question outstanding I think, was about the final battery SoC. If you’re calling the model evey minute, what are you doing for the soc_final value? Surely if you’re forecasting the next 24hrs every minute, that end SoC value will be all over the place?
Can I see your current shell command template that you’re using to call the EMHASS API please?
Thanks
No problem, as soc_final is so far away it has little impact on the initial forecasts, so I set it to zero to see the maximum that EMHASS could return over the full 24 hours.
Warning. My full mpc_optimisation call is quite complex and I don’t recommend people start here with this level of complexity. I actually have five different shell commands that I can set from the straight forward day-ahead to the complex MPC, so if things go wrong I can easily roll back to a working configuration.
post_mpc_optim: "curl -i -H \"Content-Type: application/json\" -X POST -d '{\"load_cost_forecast\":{{(
([states('sensor.amber_general_price')|float(0)] +
state_attr('sensor.amber_general_forecast', 'forecasts') |map(attribute='per_kwh')|list)[:48])
}}, \"load_power_forecast\":{{
[states('sensor.power_load_no_var_loads')|int] +(states('input_text.fi_fo_buffer').split(', ')|map('multiply',1000)|map('int')|list)[1:]
}}, \"prod_price_forecast\":{{(
([states('sensor.amber_feed_in_price')|float(0)] +
(state_attr('sensor.amber_feed_in_forecast', 'forecasts')|map(attribute='per_kwh')|list)))
}}, \"pv_power_forecast\":{{[min(15000,(states('sensor.APF_Generation_Entity')|int(0)
/(states('sensor.solaredge_i1_active_power_limit')|int(0)
+states('sensor.solaredge_i2_active_power_limit')|int(0))*200)|int(0))]
+ state_attr('sensor.solcast_forecast_today', 'detailedForecast')|selectattr('period_start','gt',utcnow())
| map(attribute='pv_estimate')|map('multiply',2000)|map('int')|list
+ state_attr('sensor.solcast_forecast_tomorrow', 'detailedForecast')|selectattr('period_start','gt',utcnow())
| map(attribute='pv_estimate')|map('multiply',2000)|map('int')|list
}}, \"prediction_horizon\":{{min(48,
(state_attr('sensor.amber_feed_in_forecast', 'forecasts')|map(attribute='per_kwh')|list|length)+1)
}}, \"alpha\":1, \"beta\":0, \"soc_init\":{{(states('sensor.filtered_powerwall_soc')|int(0))/100
}}, \"soc_final\":0.0, \"def_total_hours\":[{{states('sensor.def_total_hours_pool_filter')
}},{{states('sensor.def_total_hours_pool_heatpump')
}},{{states('sensor.def_total_hours_ev')
}},{{states('sensor.def_total_hours_hvac')
}},{{states('sensor.def_total_hours_hws')
}}]}' http://localhost:5000/action/naive-mpc-optim"
Here’s a breakdown of each part of the JSON payload:
Thanks again
Minimal configuration to inject Amber Electric prices:
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 "
post_amber_forecast: "curl -i -H 'Content-Type: application/json' -X POST -d '{\"prod_price_forecast\":{{(
state_attr('sensor.amber_feed_in_forecast', 'forecasts')|map(attribute='per_kwh')|list)
}},\"load_cost_forecast\":{{(
state_attr('sensor.amber_general_forecast', 'forecasts') |map(attribute='per_kwh')|list)
}},\"prediction_horizon\":33}' http://localhost:5000/action/dayahead-optim"
Which should return something like:
post_amber_forecast: "curl -i -H 'Content-Type: application/json' -X POST -d '{\"prod_price_forecast\":[-0.04, 0.01, 0.02, 0.04, 0.03, 0.07, 0.14, 0.16, 0.21, 0.4, 0.34, 0.33, 0.19, 0.19, 0.19, 0.17, 0.16, 0.1, 0.12, 0.14, 0.14, 0.12, 0.1, 0.1, 0.1, 0.07, 0.07, 0.07, 0.07, 0.07, 0.05, 0.06, 0.08, 0.1, 0.13, 0.44, 0.37, 0.29, 0.09, 0.07, 0.07, 0.04, 0.02, 0.02, 0.0, -0.01, -0.01, 0.01],\"load_cost_forecast\":[0.03, 0.08, 0.1, 0.12, 0.11, 0.15, 0.23, 0.25, 0.31, 0.51, 0.45, 0.44, 0.28, 0.29, 0.29, 0.26, 0.25, 0.18, 0.22, 0.24, 0.24, 0.22, 0.19, 0.2, 0.19, 0.16, 0.16, 0.16, 0.16, 0.16, 0.14, 0.15, 0.18, 0.19, 0.22, 0.57, 0.48, 0.39, 0.18, 0.15, 0.15, 0.12, 0.1, 0.1, 0.08, 0.07, 0.07, 0.08],\"prediction_horizon\":33}' http://localhost:5000/action/dayahead-optim"
Try this on your command line to see if it is working correctly.
Bit of a weird one today… I’m assuming this is a bug.
The max charge rate of my battery is set to 3300W. However the model today seems to be suggesting a charge rate of 5.3KW
I’m passing in a SoC of 0.11 (which is what it is), but the graph is refusing to believe me and is showing 0.3 instead:
My guess is that it doesn’t expect the battery to every be below 30% (my settings). However in reality today it discharged beyond 30%, even though I don’t want EMHASS to allow this as part of the prediction
Battery config is:
set_use_battery: true
battery_discharge_power_max: 3000
battery_charge_power_max: 3300
battery_discharge_efficiency: 0.95
battery_charge_efficiency: 0.95
battery_nominal_energy_capacity: 12000
battery_minimum_state_of_charge: 0.1
battery_maximum_state_of_charge: 0.9
battery_target_state_of_charge: 0.35
And my new shell command:
curl -i -H "Content-Type: application/json" -X POST -d ''{"prediction_horizon":{{ state_attr("sensor.populate_solcast_forecast", "steps_left") }},"pv_power_forecast":{{ states("sensor.solcast_24hrs_forecast") }}, "soc_init":{{ (states("sensor.battery_soc")|float(0))/100 }}}'' http://localhost:5000/action/naive-mpc-optim
Check the logs for the optimization status. Maybe you are falling under an infeasible condition due to that low initial SOC? Check that status in the logs. If the optimization is feasible then all your constraints should be respected, including those SOC min/max constraints.
Yep, I think it did say infeasible. What’s the suggested way to handle this?
tried to activate no_discharge_to_grid:
Traceback (most recent call last):
File "/usr/lib/python3.9/runpy.py", line 197, in _run_module_as_main
return _run_code(code, main_globals, None,
File "/usr/lib/python3.9/runpy.py", line 87, in _run_code
exec(code, run_globals)
File "/usr/local/lib/python3.9/dist-packages/emhass/web_server.py", line 331, in <module>
params = build_params(params, options, args.addon)
File "/usr/local/lib/python3.9/dist-packages/emhass/web_server.py", line 125, in build_params
params['optim_conf'][19]['set_nodischarge_to_grid'] = options['set_nodischarge_to_grid']
IndexError: list index out of range
Not able to open web gui after this, not able to revert config to get it working again.
this is after upgrading to 11
Yes there were some issues on the latest release. They are solved now. Search for updates and install the latest version.
I had problem with starting the service since a couple of days. So I started from clean, only changed the long live token with a correct one and tried to run the service with the standard values in the configuration file. But still receive these kinds of 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
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/lib/python3.9/runpy.py", line 197, in _run_module_as_main
return _run_code(code, main_globals, None,
File "/usr/lib/python3.9/runpy.py", line 87, in _run_code
exec(code, run_globals)
File "/usr/local/lib/python3.9/dist-packages/emhass/web_server.py", line 314, in <module>
config_hass = response.json()
File "/usr/local/lib/python3.9/dist-packages/requests/models.py", line 975, in json
raise RequestsJSONDecodeError(e.msg, e.doc, e.pos)
requests.exceptions.JSONDecodeError: Extra data: line 1 column 4 (char 3)
Any idea what I am doing wrong? Used the standard model and inverter in the standard config file and didn’t changed anything.
The first step is to understand why it is not converging. Sometimes it is just one of the input data that didn’t have correct values. On occasions with the passed input values we are able to conclude that the problem is truly infeasible. For example if you have not much PV production and you are demanding your battery to store energy but in fact there is not enough energy to store. You can maybe do these check ups and try to understand the root cause. Most of the time we are able to explain infeasible conditions.
Are you using the add-on? If this is the case there is no need for the long lived access token. Or are you trying to set the docker standalone mode ?