EMHASS: An Energy Management for Home Assistant

I am currently using NetZero to inject the dynamic pricing into the Powerwall TBC mode, then in Home Assistant I switch to TBC mode whenever EMHASS wants to export or import.

I was mucking around with a python script to inject the prices and teslemetery now has a tariff service call that can also inject the prices.

I managed to implement the code for the creation of the sensors :slight_smile:
You use the Public service of forecast.solar?

I have 3 planes, what if I create 3 times these sensors (with adapted names) and combine them in to one sensor by calculation (sum). Would that still work?
Or do I need the professional account plan, so I can do one API call in 3 planes?

How did you implemented the cycle and how does it function? That isn’t clear to me

Yes, I am.
Not sure combining three calls will work, you have to consider they do a check on the IP to limit the number of calls. You can try but I guess you’ll have to go for a paid subscription.

I implemented the cycle directly in my automation code.
Below you can find a rough adaptation of that code, that returns a list you can pass to EMHASS; you should be able to do that using a template sensor or so. Just keep in mind that the state has a limited number of characters available, so you’d maybe better store in the state the current PV forecast and the full list in the attribute, and then pass the latter to EMHASS.

{% set ns_production_forecast2days = namespace(production_forecast2days = []) %}
{% for item in state_attr('sensor.forecast_solar_estimate_watts','watts').items() %}
  {% set ns_production_forecast2days.production_forecast2days = ns_production_forecast2days.production_forecast2days + [item[1]] %}
{% endfor %}
{{ ns_production_forecast2days.production_forecast2days }}
[0, 169, 483, 1135, 2050, 2805, 3881, 5406, 6194, 5270, 4974, 4499, 3720, 2661, 1483, 695, 0, 0, 169, 491, 1000, 1534, 1932, 2245, 2483, 2644, 2635, 2491, 2220, 1830, 1356, 746, 347, 0]

Good to know. If I end up with another house might look at a battery that allows local control.

Not sure if your using solcast but seems it’s been removed from HACS

Search back in this thread; it was mentioned somebody picked it up and is still maintaining the project.
BTW EMHASS natively supports it; check the documentation.

Yep, Found it in another thread.

Is weight_battery_discharge specifically for selling back to the grid? When I set to 0.50 the optimal solution prefers to use the grid (at around 0.30) instead of the battery at all.

Not specifically for selling back to the grid.

Given your settings above it makes sense that it is prioritising using the grid as the grid only costs 0.30 which is a lot less than the ‘cost’ to use the battery which you have set at 0.5 + whatever the prod_price is at that time (maybe 0.2 or 0.3). If you specifically want to use the battery at that time weight_battery_discharge + prod_price should be less than load_cost.

So continuing the example above (load_cost = 0.30 & prod_price = 0.2), then if weight_battery_discharge is less than 0.10 it will discharge the battery but if it is greater than 0.10 it will will supply from the grid, all other things being equal.

If you share your cost table chart we can interpolate a lot better.

Cheers! Yeah that explains it and lines up with exactly what I’m seeing. My cost chart has been through quite a few iterations since that post :).

Now onto how I can shoehorn HVAC as a deferred load.

I required a minor tweak parseFloat

      return entity.attributes.battery_scheduled_soc.map((entry) => { 
        return [new Date(entry.date),  parseFloat(entry.soc_batt_forecast)]; });

Other than this - these charts are solid gold!

1 Like

Summer
HVAC over summer worked quite well for me as it was all about the cooling and the hottest part of the day, was also the highest PV production, so lowest costs.

I defined an input_number for set point (°C) and another input_number for my cooling coefficient (Cooling W / °C).

I set def_hours_hvac using a weather integration to count how many timesteps the outdoor forecast would exceed my set point.

Then for each timestep, I determined the forecast power consumption by multiplying the difference from the set-point by the cooling coefficient. I.e. if my cooling coefficient is 1500 W/ °C, the set-point is 24 °C and the outdoor temp is 26 °C, then the power forecast for that timestep was 3000 W. I then included this power forecast into my load_forecast array.

This approach is good for measurement, but doesn’t adjust my HVAC load according to cost. I.e. when cost is cheap I want to run HVAC hard and when it is expensive I to switch down consumption.

I kindoff having something working that adjusts p_nom_hvac (which adjusts the maximum allowed value) according to my excess solar production and another automation that changes the HVAC setpoint up and down according to the deferrable load forecast. So using the examples above a deferrable load forecast of 3000W would change the HVAC set point to 24 °C (2 degrees below the external temp), a deferrable load forecast of 4500W would change the set point to 23 °C (3 degrees below the external temp), a deferrable load of 0W would change the set point to match the external temp (24 °C), but then if the external temp goes up to 26 °C, the set point would also go up to 26 °C.

Winter

We are now heading into winter and the problem is reversed as it is now all about heating and the coldest part of the day is generally overnight and just before sunrise, but morning high peak prices are occurring at the same time (as the grid has high demand at this time).

I can see my HVAC heating captured in my load power forecast, running from around 1800-0800 each night at a constant 2 kW, with a spike at 0600 the morning when I switch the thermostat from night (18 °C) to morning (20 °C). The def_end_timestep will be useful here as I can schedule my HVAC to complete by 0800, and then potentially modulate my HVAC setpoint to heat during the cheapest timesteps. But I don’t really need it ramping up the heating at 0300 just because it is the cheapest time overnight, but somehow I want to hit that 20 °C at 0700 and avoid the 0600 morning price peak.

I’m quite interested in how others are optimising for the winter overnight heating problem.

Okay that is intense and i’m going to have to do some thinking. I don’t have a sensor to measure the consumption of HVAC so I’m not even sure how to subtract the HVAC load (anywhere from 2kw to 8kw) from var_load.

I could see a naïve HVAC needs 4kWh (or whatever the calculated spike load will be) between 6 and 7am possibly working. Where the spike loading is the deferred load and the constant 2kw is just ‘normal house’ load?

PS what’s the logic to derive savings vs DMO?

I came across the post

Can you share your template formula for the PV forecast, as to build the pv_forecast array? I am trying to figure out how to build the array so I can use it for forecast.solar.
thank you

Happy to help, but the post you linked to has the template which I’m using.

What else were you hoping to get?

I have coded this now:

\"pv_power_forecast\":{{[states('sensor.inverter_ingangsvermogen')|int(0)]
            + state_attr('sensor.template_test_solar_forecast','values_list')|selectattr('period_start','gt',utcnow())
              | map(attribute='pv_estimate')|map('multiply',2000)|map('int')|list }}

Resulting in this:

UndefinedError: 'int object' has no attribute 'period_start'

Can you tell me where to define the attributes period_start and pv_estimate

selectattr('period_start','gt',utcnow()

and

map(attribute='pv_estimate')

Clearly I am missing something here. thx

period_start is part of the output of this (in my setup):
state_attr(‘sensor.solcast_pv_forecast_forecast_today’, ‘detailedHourly’)
It gives this:
[{‘period_start’: datetime.datetime(2024, 6, 17, 0, 0, tzinfo=zoneinfo.ZoneInfo(key=‘Europe/Amsterdam’)), ‘pv_estimate’: 0.0, ‘pv_estimate10’: 0.0, ‘pv_estimate90’: 0.0}, {‘period_start’: datetime.datetime(2024, 6, 17, 1, 0, tzinfo=zoneinfo.ZoneInfo(key=‘Europe/Amsterdam’)), ‘pv_estimate’: 0.0, ‘pv_estimate10’: 0.0, ‘pv_estimate90’: 0.0}, {‘period_start’: datetime.datetime(2024, 6, 17, 2, 0, tzinfo=zoneinfo.ZoneInfo(key=‘Europe/Amsterdam’)),
So most likely your ‘state_attr(‘sensor.template_test_solar_forecast’,‘values_list’)’ does not contain the correct information. Is this also retrieved with the solcast integration?

Ah, that must be the issue. I am using Forecast.Solar now, so this won’t work then.
Maybe go for solcast instead of forecast.solar to make things easy for me.

The solcast integration is having some issues at the moment.

Forecast solar should work you just need to get the data in a use able format.

The developer tools template editor is your friend.

1 Like

So far my setup using the MPC is working well, I did lose out this morning but Amber smartshift was going to do the same thing EMHASS wanted to do.

Going to look at the ML fit model. It is possbile to use both MPC and ML at the same time?

In my case I am trying to account for morning spikes that never eventuate.

1 Like

Yes you can use MPC & ML to get a comprehensive solution.

The morning false peaks are problematic as it drives EMHASS to hold back (or even charge overnight). A useful compromise I have is to set battery_discarge_weight to 0.15 (charge weight 0.00), which tends to hold charge overnight for morning peak rather than fully discharging at night, then recharging overnight at a high price.

One of the great things about EMHASS is you can tune/ modify the inputs so you can apply an 20% reduction to future price forecasts, or when Amber publish the advanced forecasts via the API we can use those.

1 Like