EMHASS: An Energy Management for Home Assistant

With the Ausgrid two-way trial tariff some considerations required:

Quote
There are some considerations to keep in mind when looking to make the most of this tariff.

There is a 26.58 c/kWh (excl. GST) network charge for buying power from the grid between 2-8PM on top of the wholesale price of energy.

We do not expect this to significantly impact most Amber battery customers, as your solar and stored energy should usually cover household usage at these times. Generally, we see batteries optimised by SmartShiftā„¢ export power to create value during this period instead.

There is a 2.19 c/kWh (incl. GST)charge for solar exports between 10-2PM. Load-shifting is key to minimising exports during this period, as with any other period with low feed-in tariffs.
There are no differences between seasons or shoulder periods for the Two-way tariff trial.

End quote
However Iā€™ve also noticed that EMHASS does not alway correclty analyse data so Iā€™m trying to build in some ground rules like no discharging between 10am and 2pm and no charging between 2pm and 8pm.

[{"id":"3268c2b16eaa7414","type":"inject","z":"65840aa926d9c567","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":120,"y":2420,"wires":[["16b27b4bf4a2ede5"]]},{"id":"16b27b4bf4a2ede5","type":"time-range-switch","z":"65840aa926d9c567","name":"","lat":"-33.7971621672968","lon":"151.0986226273335","startTime":"010:00","endTime":"14:00","startOffset":0,"endOffset":0,"x":300,"y":2420,"wires":[["fc6d04ecabfbd91a"],["ada71e681fe334bf"]]},{"id":"26ba461bbb0f2d05","type":"api-current-state","z":"65840aa926d9c567","name":"p_batt_forecast","server":"afc27684.cf6ed8","version":3,"outputs":1,"halt_if":"","halt_if_type":"str","halt_if_compare":"is","entity_id":"sensor.p_batt_forecast","state_type":"num","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":560,"y":2520,"wires":[["cab16b27b4a64132","f2a947d71485142f"]]},{"id":"fc6d04ecabfbd91a","type":"api-current-state","z":"65840aa926d9c567","name":"p_batt_forecast","server":"afc27684.cf6ed8","version":3,"outputs":1,"halt_if":"","halt_if_type":"str","halt_if_compare":"is","entity_id":"sensor.p_batt_forecast","state_type":"num","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":560,"y":2400,"wires":[["c481f5db555d72ca"]]},{"id":"cab16b27b4a64132","type":"debug","z":"65840aa926d9c567","name":"debug 1","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":980,"y":2360,"wires":[]},{"id":"c481f5db555d72ca","type":"api-render-template","z":"65840aa926d9c567","name":"","server":"afc27684.cf6ed8","version":0,"template":"{% set grid_feedin = states.sensor.sonnenbatterie_84324_state_grid_inout.state|float(0) %}\n{% set batt_forecast = states.sensor.p_batt_forecast.state|float(0) %}\n{% set pos_feedin = ((grid_feedin + batt_forecast) > 0)|bool %}\n{% set zero = (0)|float(0)|default(0) %}\n{% set rescharge = batt_forecast|float(0) %}\n{% if pos_feedin %}\n{% set rescharge = zero|float(0) %}\n{% else %}\n{% set rescharge = batt_forecast|float(0) %}\n{% endif %}\n{{ rescharge|int() }}","resultsLocation":"payload","resultsLocationType":"msg","templateLocation":"","templateLocationType":"none","x":760,"y":2400,"wires":[["cab16b27b4a64132","ad6df5eba5cd703a"]]},{"id":"ad6df5eba5cd703a","type":"link out","z":"65840aa926d9c567","name":"link out adjusted charge","mode":"link","links":["93beed478696134e"],"x":925,"y":2400,"wires":[]},{"id":"ada71e681fe334bf","type":"time-range-switch","z":"65840aa926d9c567","name":"","lat":"-33.7971621672968","lon":"151.0986226273335","startTime":"014:00","endTime":"20:00","startOffset":0,"endOffset":0,"x":300,"y":2500,"wires":[["6ebfdbd9b9cfa958"],["26ba461bbb0f2d05"]]},{"id":"6ebfdbd9b9cfa958","type":"api-current-state","z":"65840aa926d9c567","name":"p_batt_forecast","server":"afc27684.cf6ed8","version":3,"outputs":1,"halt_if":"","halt_if_type":"str","halt_if_compare":"is","entity_id":"sensor.p_batt_forecast","state_type":"num","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":560,"y":2460,"wires":[["d65ef605e29630d6"]]},{"id":"d65ef605e29630d6","type":"api-render-template","z":"65840aa926d9c567","name":"","server":"afc27684.cf6ed8","version":0,"template":"{% set grid_feedin = states.sensor.sonnenbatterie_84324_state_grid_inout.state|float(0) %}\n{% set batt_forecast = states.sensor.p_batt_forecast.state|float(0) %}\n{% set neg_feedin = ((grid_feedin + batt_forecast) < 0)|bool %}\n{% set zero = (0)|float(0)|default(0) %}\n{% set rescharge = batt_forecast|float(0) %}\n{% if neg_feedin %}\n{% set rescharge = zero|float(0) %}\n{% else %}\n{% set rescharge = batt_forecast|float(0) %}\n{% endif %}\n{{ rescharge|int() }}","resultsLocation":"payload","resultsLocationType":"msg","templateLocation":"","templateLocationType":"none","x":760,"y":2460,"wires":[["cab16b27b4a64132","e141d12a92ab5773"]]},{"id":"1c7d785a53cd2053","type":"comment","z":"65840aa926d9c567","name":"Ausgrid -2.19c on FiT","info":"","x":300,"y":2380,"wires":[]},{"id":"5385a46d2cd4892a","type":"comment","z":"65840aa926d9c567","name":"Ausgrid +26.58c on FiT","info":"","x":300,"y":2560,"wires":[]},{"id":"c71f62cc34968214","type":"comment","z":"65840aa926d9c567","name":"Not ok to discharge AM","info":"","x":760,"y":2360,"wires":[]},{"id":"fed8abdc502539fe","type":"comment","z":"65840aa926d9c567","name":"Not ok to charge PM","info":"","x":770,"y":2520,"wires":[]},{"id":"db2c0a119c510f09","type":"link in","z":"65840aa926d9c567","name":"link in adjusted charge/discharge","links":[],"x":105,"y":2480,"wires":[["16b27b4bf4a2ede5"]]},{"id":"e141d12a92ab5773","type":"link out","z":"65840aa926d9c567","name":"link out adjusted discharge","mode":"link","links":[],"x":925,"y":2460,"wires":[]},{"id":"1583a885818be654","type":"link out","z":"65840aa926d9c567","name":"link out 1","mode":"link","links":[],"x":925,"y":2520,"wires":[]},{"id":"d32ba786df56b857","type":"link out","z":"65840aa926d9c567","name":"link out 2","mode":"link","links":[],"x":925,"y":2580,"wires":[]},{"id":"f2a947d71485142f","type":"switch","z":"65840aa926d9c567","name":"","property":"payload","propertyType":"msg","rules":[{"t":"lt","v":"0","vt":"num"},{"t":"gt","v":"0","vt":"num"}],"checkall":"true","repair":false,"outputs":2,"x":750,"y":2560,"wires":[["1583a885818be654"],["d32ba786df56b857"]]},{"id":"85a5838316958742","type":"comment","z":"65840aa926d9c567","name":"discharge adjusted to 0","info":"","x":1060,"y":2400,"wires":[]},{"id":"70f2963ab704c122","type":"comment","z":"65840aa926d9c567","name":"charge adjusted to 0","info":"","x":1050,"y":2460,"wires":[]},{"id":"39cbb99fb9a73dc3","type":"comment","z":"65840aa926d9c567","name":"charge passed through","info":"","x":1060,"y":2520,"wires":[]},{"id":"a6ad54984bd41b4e","type":"comment","z":"65840aa926d9c567","name":"discharge passed through","info":"","x":1070,"y":2580,"wires":[]},{"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}]

When I test this flow Iā€™ll sit it between the switch and the POST/PUT calls.

I would advise against hard coding these rules as these prices are included in the price calculations that EMHASS uses to determine the optimal plan.

Even with the AusGrid tariff there will still be occasions where you get a price spike (> $10/ kWh) between 10am-2pm and you would want to discharge. Less common but still possible you can get a price plunge (<$0/ kWh) between 2pm-8pm at which point you would want to charge from the grid.

Can you identify where EMHASS does not analyse the data correctly so it can be fixed?

However I keep seeing this type of behaviour where FiT is 1c and battery is discharging. It will go -1c and still discharge. I understand you have to trust the system but itā€™s difficult.

Your graphic only shows the battery discharging to the grid between 17:00 - 21:00 when the FIT is high.

Might have just missed it. There was a period of discharge ending just as the chart begins.
In any case youā€™re advising to allow they system to make the decisions. Iā€™ll take your advice. See how we go.
Thanks for all your help.

So Iā€™ve left the system to its own devices and I come back to see a FiT of $11.92 /kWh and the system is only discharging at 697W? ?
I have to overide it and force the battery to discharge at max kW
Nope missed the spike. Its back to $1.17 now.
Its hard to trust this system when it misses a FiT of over $11/kWh

Now its pushed up to over 3kW when the price has gone down to 45c

Can you share the table of values, I find it hard to follow on your charts?

Also the past values history chart for tonight would also be useful to understand what when on?

EMHASS isnā€™t aware of the Amber 30 minute settlement so you will get some inaccuracy there. That is a problem all the automations have including SmartSmart, if they see a price spike early in the 30 minute window they will export madly, but then the spike might reduce and not exist. What you had tonight was pusuedo spike, is only the final price at the end of the 30 minutes that you get paid for.

What did the Amber app say the final price was for the window?

I also have an alert sent to my phone from Home Assistant during a spike so I can see what is going on.


I think I know what the issue is. The FiT forecast is not coming to fruition and Iā€™m reacting to false data.

1 Like

Ah, ha,

That explains some things, the reason it reduced down to 600W was it was saving the battery power for the price spike in the next 30 minute forecast. Maybe a similar issue with your 1Ā¢ FIT earlier in the day.

I have a dashboard which I check first with the current/ now/ values of everything. The Apex card doesnā€™t actually show the current/ now values only future forecasts.

1 Like

I have two deferrable where:
P_deferrable0 (water resistance): treat as continuous false
P_deferrable1 (EV car): treat as continuous true
image

However EMHASS is estimating for P_deferrable0 variable loads.
Is this expected?
image

I think its the other way around.

For constant wattage water heater:

- treat_deferrable_load_as_semi_cont: true 

For variable wattage car charger:

- treat_deferrable_load_as_semi_cont: false

Confusing wording.

2 Likes

Thatā€™s what is actually called by mathematicians, a semi continuous variable is a variable that takes either zero or a constant value. So in our case yes that will be constant wattage. But I agree is a bit confusing.

2 Likes

I think itā€™s appropriate to use the official or industry term. Just needs an explanation for laypeople. Wonder where we could collate these as we come across them?

Hi,

Is there a way to limit export to 5KW im EMHASS? I have this restriction

Hi David, I canā€™t figure out this validation error I am getting. This is preventing the MPC optimiser from generating a forecast for p_deferrable0.

2023-07-22 12:20:01,916 - web_server - INFO - Setting up needed data
2023-07-22 12:20:01,917 - web_server - ERROR - ERROR: The passed data is either not a list or the length is not correct, length should be 48
2023-07-22 12:20:01,917 - web_server - ERROR - Passed type is <class 'list'> and length is 48
2023-07-22 12:20:01,918 - web_server - INFO - Retrieve hass get data method initiated...
2023-07-22 12:20:02,103 - web_server - INFO - Retrieving weather forecast data using method = list
2023-07-22 12:20:02,104 - web_server - INFO - Retrieving data from hass for load forecast using method = naive
2023-07-22 12:20:02,104 - web_server - INFO - Retrieve hass get data method initiated...
2023-07-22 12:20:02,382 - web_server - INFO -  >> Performing naive MPC optimization...
2023-07-22 12:20:02,382 - web_server - INFO - Performing naive MPC optimization
2023-07-22 12:20:02,387 - web_server - INFO - Perform an iteration of a naive MPC controller
2023-07-22 12:20:02,481 - web_server - INFO - Status: Optimal
2023-07-22 12:20:02,481 - web_server - INFO - Total value of the Cost function = 2.81
2023-07-22 12:20:02,790 - web_server - INFO - Setting up needed data
2023-07-22 12:20:02,791 - web_server - INFO -  >> Publishing data...
2023-07-22 12:20:02,791 - web_server - INFO - Publishing data to HASS instance
2023-07-22 12:20:02,801 - web_server - INFO - Successfully posted to sensor.p_pv_forecast = 6337
2023-07-22 12:20:02,809 - web_server - INFO - Successfully posted to sensor.p_load_forecast = 1719.35
2023-07-22 12:20:02,815 - web_server - INFO - Successfully posted to sensor.p_deferrable0 = 0.0
2023-07-22 12:20:02,822 - web_server - INFO - Successfully posted to sensor.p_batt_forecast = 0.0
2023-07-22 12:20:02,828 - web_server - INFO - Successfully posted to sensor.soc_batt_forecast = 100.0
2023-07-22 12:20:02,836 - web_server - INFO - Successfully posted to sensor.p_grid_forecast = -4617.65
2023-07-22 12:20:02,842 - web_server - INFO - Successfully posted to sensor.total_cost_fun_value = 2.81
2023-07-22 12:20:02,849 - web_server - INFO - Successfully posted to sensor.unit_load_cost = 0.1682
2023-07-22 12:20:02,855 - web_server - INFO - Successfully posted to sensor.unit_prod_price = 0.05

I had a look at the code and I canā€™t tell which of the runtime params it is complaining about. Also the fact is complaining is strange because the type and length seem to match what is required. I have had a look at the data from from HASS and it all looks good.

It might be good to add the runtime param name to the error message.

EDIT
Back up and running after deleting the injection_dict.pkl file from the shared folder and restarting EMHASS. Post left here for any future users with a similar issue.


A random error has started at some point during today. There have been no updates to my home assistant or other add ons. Any thoughts? I have uninstalled and reinstalled EMHASS with no success.

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/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 289, in <module>
    injection_dict = pickle.load(fid)

Cheers
Tom

1 Like

Hi, the type and length of passed list were the most common source of error when this error message was conceived. In your case there must be a problem elsewhere with your passed data.
Actually I was just looking at the code and there is a flagrant error in the message (sorry about that), the passed length of the list is not correct calculated in the code. I will fix this error message but I guess that that should be your problem, your list length is not exactly what is expected by EMHASS. Youā€™re passing a longer list while EMHASS is expecting a list of exactly 48 elements in length.

Thanks David. It seems that it was a transient issue (sorryā€¦). The car charge was plugged in but the sensors providing def_total_hours_ev were not working. I think this was contributing to the missing data.

Ok, no problem. This allowed to debug that faulty error message nevertheless. Already fixed that and merged here: https://github.com/davidusb-geek/emhass/pull/99