There seems to be a gap in the start time for amber data in this graph. Simthing wrong with the time?
Your logs donāt show your MPC optim being called.
There should be a line:
INFO - Perform an iteration of a naive MPC controller
Iām calling it from node-red. Iāll go back to automations.yaml see if that works
- alias: EMHASS day-ahead optimization
trigger:
- minutes: /1
platform: time_pattern
action:
- service: shell_command.post_mpc_optim_solcast
- alias: EMHASS publish data
trigger:
- minutes: /1
platform: time_pattern
action:
- service: shell_command.publish_data
no change
2023-07-17 07:31:00,109 - web_server - INFO - Setting up needed data
2023-07-17 07:31:00,111 - web_server - INFO - >> Publishing data...
2023-07-17 07:31:00,111 - web_server - INFO - Publishing data to HASS instance
2023-07-17 07:31:00,125 - web_server - INFO - Successfully posted to sensor.p_pv_forecast = 23.88
2023-07-17 07:31:00,136 - web_server - INFO - Successfully posted to sensor.p_load_forecast = 563.62
2023-07-17 07:31:00,145 - web_server - INFO - Successfully posted to sensor.p_deferrable0 = 0.0
2023-07-17 07:31:00,156 - web_server - INFO - Successfully posted to sensor.p_batt_forecast = 0.0
2023-07-17 07:31:00,165 - web_server - INFO - Successfully posted to sensor.soc_batt_forecast = 10.0
2023-07-17 07:31:00,174 - web_server - INFO - Successfully posted to sensor.p_grid_forecast = 539.73
2023-07-17 07:31:00,188 - web_server - INFO - Successfully posted to sensor.total_cost_fun_value = -1.68
2023-07-17 07:31:00,198 - web_server - INFO - Successfully posted to sensor.unit_load_cost = 0.1419
2023-07-17 07:31:00,209 - web_server - INFO - Successfully posted to sensor.unit_prod_price = 0.065
I would recommend turning off your automations as they are not working correctly and just focus on getting either your day ahead optimisation functional, in the first instance and then your MPC optimisation functional.
You can call them individually from the developer tools services menu.
Confirm the results are correct in the logs and the :5000 interface before proceeding.
yep working on it. Breaking down the shell commans into its separate sections and looking at output. Trying to call from command line.
One question if I may. For solcast do you call update_forecasts or update_actual_forecasts? THe former makes one call to solcast while the latter makes two.
THakns
Rob
I use auto polling as I have the original 50 API calls.
From the look of GitHub - oziee/ha-solcast-solar: Solcast Integration for Home Assistant
I would suggest update_forecasts would be sufficient.
I had emhass in profit mode, but its costing me money in the morning , the ideal behaviour id like it for it to only discharge to the grid when i can generate a significant profit, right now ill be charging at 20c and discharging at 25c, but often the fit drops below the charging price as the day goes on so i end up loosing money.
Ive changed to to cost to see what happens but it wants to do some weird things, like charging my battery in the evening peak and discharging in the middle of the night.
I dont want to disable grid charging as id like my battery to top it self up on days with crap solar production like today.
Any ideas on what i can adjust to improve performance?
I think Iām on the same boat
I donāt think the ācostā optimization is relevant in Australia. I havenāt been able to understand the use case, I think it is just trying to optimize the cost of grid imports, without regard to solar. Like you I seem to get funny results when I try.
https://emhass.readthedocs.io/en/latest/lpems.html#household-ems-with-lp
EMHASS itself doesnāt thresholds on buy/ sell values, but I generally find a healthy spread.
However if you wanted to limit battery exports to the grid above a certain price then you could achieve this in your battery automation.
Something like:
export_price < threshold
then
battery_export = p_load_forecast - p_pv_forecast
else
battery_export = p_batt_forecast
I regularly see a good margin between the highest buy cost of the day and the lowest sell price. e.g. 31c sell vs 21c buy for today
Here is a better example showing a full 24 hours.
This evening buy at 14c sell at 31c, but overnight buy at 15c and sell in the morning at 20c.
Does the second sell represent value?
I note that later in the day (12:00) the buy price drops to 8c so selling at 20c makes sense, but does it make sense to buy overnight at 15c?
My problem is the sell price rarely seems to match what the prediction says, so i end up buying at 20c with the expectation to sell at 32c but by the time the morning peak comes around the actual sell price is has fallen significantly.
I could maybe get around this by putting a scaler on the fit forecast price.
I thinkā¦ just like today in VICā¦ when it comes to sell timeā¦ the original sell prices did not hold well. its like the difference of about 5cā¦ is it worth itā¦ very subjective.
Its just my second month in Amberā¦ so I donāt have many experience
The Amber API does have a feed_in range_min value, that comes and goes. I have done some experimentation using feed_in forecast for the next 2 hours and range_min for the longer term forecasts.
The rang_min value isnāt always present so it can be a challenge to calculate the EMHASS persistence.
and then a few minutes later I have a full set of range_min
Move the shell commands to node-red. Working find in node-red.
Thanks very much for your help.
I suppose you can establish the POST end points in node red directly so that would give you more control than the curl shell commands.
Yes and it separates the different components of the POST. Makes it a little clearer than trying to compose one long string. I can process returned error messages as well. If not 201 send a message to my phone so I can investigate. Iāve got that set up with all the commands going to the battery as well.
Please share your node red flow
[{"id":"7e7a97b8e68d3389","type":"function","z":"65840aa926d9c567","name":"POST return != 201","func":"var status = msg.statusCode\nif(status != 201)\n{\n return msg\n}\nelse\nreturn","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1490,"y":460,"wires":[["0599d210da9c7483"]]},{"id":"80bd09881d89d374","type":"http request","z":"65840aa926d9c567","name":"POST MPC","method":"POST","ret":"txt","paytoqs":"ignore","url":"http://192.168.99.17:5000/action/naive-mpc-optim","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[{"keyType":"Content-Type","keyValue":"","valueType":"application/json","valueValue":""}],"x":790,"y":780,"wires":[["459be90396eb63a0","7e7a97b8e68d3389","62d9e74bace8efe8"]]},{"id":"0599d210da9c7483","type":"api-call-service","z":"65840aa926d9c567","name":"Notify Robert's iPhones","server":"afc27684.cf6ed8","version":5,"debugenabled":false,"domain":"notify","service":"mobile_app_robsiphone","areaId":[],"deviceId":[],"entityId":[],"data":"{\"title\":\"EMHASS POST to battery failed\",\"message\":\"error: '{{statusCode}}' URL: '{{responseUrl}}'\"}","dataType":"json","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":1510,"y":520,"wires":[[]]},{"id":"035211769c9ed7a4","type":"function","z":"65840aa926d9c567","name":"POST Params","func":"var payload = msg.payload\nmsg.headers = {}\nmsg.headers[\"Content-Type\"] = \"application/json\"\nmsg.url = \"http://192.168.99.17:5000/action/naive-mpc-optim\"\nmsg.payload = payload\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":620,"y":780,"wires":[["80bd09881d89d374"]]},{"id":"459be90396eb63a0","type":"debug","z":"65840aa926d9c567","name":"debug MPC POST","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1510,"y":720,"wires":[]},{"id":"62d9e74bace8efe8","type":"change","z":"65840aa926d9c567","name":"","rules":[{"t":"set","p":"url","pt":"msg","to":"http://192.168.99.17:5000/action/publish-data","tot":"str"},{"t":"set","p":"method","pt":"msg","to":"POST","tot":"str"},{"t":"set","p":"headers","pt":"msg","to":"Content-Type: application/json","tot":"str"},{"t":"set","p":"payload","pt":"msg","to":"{}","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":1000,"y":780,"wires":[["bec2a54eea11d3e8"]]},{"id":"cc56cc8594ded18c","type":"api-render-template","z":"65840aa926d9c567","name":"MPC Array","server":"afc27684.cf6ed8","version":0,"template":"{\"load_cost_forecast\":{{(\n ([states('sensor.cecil_st_general_price')|float(0)] +\n state_attr('sensor.cecil_st_general_forecast', 'forecasts') |map(attribute='per_kwh')|list)[:48])\n }}, \"prod_price_forecast\":{{(\n ([states('sensor.cecil_st_feed_in_price')|float(0)] +\n state_attr('sensor.cecil_st_feed_in_forecast', 'forecasts')|map(attribute='per_kwh')|list)[:48]) \n }},\"pv_power_forecast\":{{([states('sensor.sonnenbatterie_84324_production_w')|int(0)] +\n state_attr('sensor.forecast_today', 'detailedForecast')|selectattr('period_start','gt',utcnow()) | map(attribute='pv_estimate')|map('multiply',2000)|map('int')|list +\n state_attr('sensor.forecast_tomorrow', 'detailedForecast')|selectattr('period_start','gt',utcnow()) | map(attribute='pv_estimate')|map('multiply',2000)|map('int')|list\n )| tojson\n }}, \"prediction_horizon\":{{min(48, (state_attr('sensor.cecil_st_feed_in_forecast', 'forecasts')|map(attribute='per_kwh')|list|length)+1)\n }},\"soc_init\":{{(states('sensor.sonnenbatterie_84324_state_charge_user')|float(0))/100\n }},\"soc_final\":0.05,\"def_total_hours\":[2]}","resultsLocation":"payload","resultsLocationType":"msg","templateLocation":"","templateLocationType":"none","x":450,"y":780,"wires":[["035211769c9ed7a4"]]},{"id":"bec2a54eea11d3e8","type":"http request","z":"65840aa926d9c567","name":"POST Publish data","method":"use","ret":"txt","paytoqs":"ignore","url":"","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":1210,"y":780,"wires":[["459be90396eb63a0"]]},{"id":"be01d6d98c163e23","type":"inject","z":"65840aa926d9c567","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"60","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"str","x":310,"y":780,"wires":[["cc56cc8594ded18c"]]},{"id":"afc27684.cf6ed8","type":"server","name":"Home Assistant","version":5,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":true,"heartbeat":false,"heartbeatInterval":30,"areaSelector":"friendlyName","deviceSelector":"friendlyName","entitySelector":"friendlyName","statusSeparator":"at: ","statusYear":"hidden","statusMonth":"short","statusDay":"numeric","statusHourCycle":"h23","statusTimeFormat":"h:m","enableGlobalContextStore":true}]