EMHASS: An Energy Management for Home Assistant

Excellent,

Can you describe what a weighting of 1 actually means?

If you mean soc_init in the naive-mpc-optim post, I use the sonnen user’s SOC sensor (as opposed to the real state of charge).

These are the other sensors relating to capacity in Wh but I don’t use them. They are directly proportional to the above. It appears the maximum capacity (10000Wh and 9300Wh) don’t change with age so degradation is represented by an inability to reach zero as can be seen above where at 7AM user SOC is still 11%.

So I’ll just add a few Watts to the p_batt_forecast to boost the charge. I would have thought the system would compensate for that and reduce remaining charge in response?

Do you pass p_batt_forecast (W) value to your inverter directly?

Some people pass soc_forecast to inverter (%).

Some people switch inverter to charging mode is p_batt_forecast (W) is greater than charging threshold (say 5 kw).

Yes, well directly to the battery, not the inverter. Sonnen battery API will take a value in Watts in a POST to charge (or discharge). So I can pass p_batt_forecast value directly to the battery to change charge/discharge rate.

All I have to do is add some number of Watts to p_batt_forecast before passing it to the battery. I have to come up with some formular to increase the charge rate, in the below, to guide towards 100%.

pospayload = Math.abs(msg.payload)
msg.headers = {}
msg.headers['Auth-Token'] = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
msg.headers ["Content-Type"] = "application/x-www-form-urlencoded"
msg.url = "http://192.168.99.168:80/api/v2/setpoint/charge/" + pospayload.toString()
return msg;

Perhaps:

pospayload = Math.abs(msg.payload);

// Check if pospayload is below 2800 
if (pospayload < 2800) {
  // Increase pospayload by 200
  pospayload += 200;
}

msg.headers = {};
msg.headers['Auth-Token'] = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
msg.headers ["Content-Type"] = "application/x-www-form-urlencoded";
msg.url = "http://192.168.99.168:80/api/v2/setpoint/charge/" + pospayload.toString();
return msg;

These weights have the same units as the energy cost, so “currency”/kWh.
A value of 1 will surely have an impact on your battery schedule. These can be used to directly penalize battery usage and account for battery degradation. Set it to zero to avoid using them if you have a battery. Maybe it could be a good idea to set it to zero by default, I may change that in a future release.
This value could be set to a real value that could be computed using the CAPEX cost of the battery and knowing the degradation rate per kWh output. Unfortunately this information is not easy to come by and it will depend on the specific battery chemistry and characteristics.

Battery cycle cost examples:
General info below based on LiFePo, CATL/EVE/BYD or equivalent.

Battery from China, Chinese inverter, all in.
Battery life from 100% to 80%(considered as dead) is about AUD$1.0 per cycle.
Battery life from 100% to 60%(considered as dead) is about AUD$0.5 per cycle.
When considering the real life cycling, DoD is rarely 100% (on larger batteries especially), so the actual cycle cost will be less than half of the above numbers.

Above as of today, prices are falling.

1 Like

What’s missing here is the size of the battery. My assumption is 6000 cycles economic life (in line with typical warranty arrangements). On a 12k investment (EUR) that gets me to 2 EUR per cycle, 15kwh battery of which 13.5kwh usable → ca 0.15c per kWh

That will however not result in any charging/discharging; especially not when adding an additional 10% battery and inverter loss. Not surprised, after all a home battery is still not economical here due to government subsidies on PV (net metering) - instead I would probably put it around 0.07.

Thanks David!

1 Like


I loaded penalty as -0.09 on both charge/discharge cycles. Still get some activity in the form of grid charging discharging.

1 Like

David,
Would it be better to replace discharge ‘weights’ with user selectable “Minimum profit margin” measured in cents per kwh (let user decide cycle cost)?
This way decision, sell/no sell power can be calculated as:
Money spent charging battery / kWh stored in battery (SOC) + Minimum Profit Margin. If result is < that FiT then sell.
Thoughts?

Thanks for those figures. The relative and most important part is that main assumption of 6000 cycles, it will be highly variable depending on chemistry, DOD, etc…

This is kind of what’s already there in the cost function.
See the code here to see if what you say translates to the current profit cost function: https://github.com/davidusb-geek/emhass/blob/56913605ad36a4b674c294c48a90ea1d2a6fdb7b/src/emhass/optimization.py#L197

@davidusb , is there some sort of auto update feature built in? I do not have auto update activated yet my emhass includes the new config options resulting in very erratic behavior.

Charging and discharging continuously…

In the changelog of hass os it also shows 19-12…

I changed the value to zero. Now the addon crashes…

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 "<frozen runpy>", line 198, in _run_module_as_main
  File "<frozen runpy>", line 88, in _run_code
  File "/usr/local/lib/python3.11/dist-packages/emhass/web_server.py", line 296, in <module>
    injection_dict = pickle.load(fid)
                     ^^^^^^^^^^^^^^^^
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x95 in position 3601184: invalid start byte
s6-supervise emhass: warning: unable to spawn ./finish: Permission denied
Traceback (most recent call last):
  File "<frozen runpy>", line 198, in _run_module_as_main
  File "<frozen runpy>", line 88, in _run_code
  File "/usr/local/lib/python3.11/dist-packages/emhass/web_server.py", line 296, in <module>
    injection_dict = pickle.load(fid)
                     ^^^^^^^^^^^^^^^^

Update, tried everything, reverting back to emhass 5.3, clean install of 5.4 - cant get the server to run. It continues to spit out the above error.

Might be a side effect of upgrading HA core to 2024.01? Cant roll that one back unfortunately… destroys my recorder settings.

Just erase the temporary *.pkl files in the shared folder of your HA instance. Then restart the add-on.

1 Like

No there is not such thing. You auto-update using that Supervisor setting, there are no built in updates.
Check your optimization status.

Thanks, that helped!

There is an auto update switch available on the add on page.

For EMHASS I have this switched to off.

1 Like

Me too; have it turned off for all addons. think its the new HA version. This pushes a “you are not on the latest version message” in your face. Must have clicked through it unintentionally

Thanks for this feature.

This now makes sense if the penalty is in [€,$]/ kWh.

Agreed have the default as 1 [€,$]/ kWh is too harsh and does dramatically effect the scheduling, setting the default to 0, which mirrors current behaviour would be a good default.

I have the same issue as above.
EMHASS is continuously charging and discharging.
I reverted to 0.5.3 and deleted this temporary pkl files. (and restart)
No effect.

I assume it has to do with the new HA 2024.01