EMHASS: An Energy Management for Home Assistant

So I have a situation like this now where their’s a plan to charge the battery after 3pm which is inside the demand tariff window:


I think what I’ll do is intercept any command to charge the battery between 3 and 8:30 and change it to a command to put the battery into self management mode where it will charge if there is available PV production only.

Current node red flow:

Demand tariff change:

It’s not perfect but not sure how I can change the charge calculation to take into account the costs of the demand tariff?

Does this sound logical?

What you’re proposing here is what I initially did and logically correct. However what happened is EMHASS thought it was going to charge from the grid at 15:00 when the price was really low (don’t get me started about super low prices during the demand window…) in preparation for discharging from the grid in the evening but my intervention stopped it from doing so and was not as ready for the peak period as it thought it would be.

I think I worked out a solution above (EMHASS: An Energy Management for Home Assistant - #2484 by altonius) that basically changes the prices in the demand window to $1 per kWh. So EMHASS modeling doesn’t even consider charging from the grid during that time.
Short version of what it does is:

  1. Compare the current time and work out which window (From 0-48) the start and end times will be for the demand window
  2. Capture the list of the next 48 load prices from Amber
  3. If demand window has already started swap out the from 0 to the end period with “1.00”, then copy the amber prices from end to the start period, then do from the start period to 48 with “1.00”.
  4. Elseif for 0 to the start period copy the amber prices, then from start to end period swap with “1.00”, then from end period to 48 with the amber prices.

Then I pass the new list to my MPC optimisation I run each minute (instead of the usual amber list)

2 Likes

yes I see what you mean. I’ll have a look at you code or implement somehting to charge to 100% between 2 and 3. Your solution might be cleaner though.

this is how I do it with deye inverters. just chnage soc time of use and if delay solar charge set amps 0:

getting an odd error when upgrading the add-in to 0.10.6

1 Like

Same here.

You can try now, it should be solved.
For some unknown reason the github automatic build failed. I’ve manually launched the rebuild and now worked fine.
However it is still failing for arm architectures (Raspberry Pis)

2 Likes

evcc has a realy nice user interface specficly for EV charging and integrates nicely with home assistant (runs as an add-on and since recently also has an integration to control evething trough Home Assistant. Have a look at UI here evcc It controls charging power (solar, net) and has a templating system in place that allow you to easily connect to chargers (OCPP or modbus or API), EV’s, invertors, home batteries, power meters directly or trough home assistant. It also comes with a “planner” that allows you to set a desired SoC at a moment in the future and it wil create the plan taking solar and dynamic pricing into account. I am currently also looking for the best way to get this integrated in a way that evcc can be used to set the plan but EMHASS does it’s thing taking into account all other deferrable loads around the house. So basicly a translation of the plan (the number of kwh’s it needs) to a deferable load definition in EMHASS and an automation of to set charging according to the plublished EMHASS deferable load planning and let evcc (trough HA) do it’s thing with charging power limits.

Charging plan UI

The evcc HA integration

Another nice feature in evcc that is missing in emhass (or I haven’t found it in the docs yet) at the moment is to optimise charging depending on CO2 emissions instead of only looking at energy prices.

So basicly why evcc? : the UI and the nice integrations with specific charging stations etc that are not always availalbe as an integration in Home Assistant directly…

Thanks, worked perfectly now!

Some nice user interfaces to specify the operating parameters for deferrable loads would be useful, it should be relatively straight forward to convert the inputs from EVCC into something that can be injected into EMHASS. As you point it the strength of EMHASS is that it will integrate multiple loads for an optional solution. EMHASS could also then potentially call EVCC for the charging commands and abstract things like OCPP and the like.

EMHASS is very flexible with what you use as costs for the optimisation calculation, traditionally people are using financial costs, but I have also configured EMHASS cost using CO2 intensity from the Electricity Maps integration, that way you end up with an optimisation that minimises the carbon intensity of your household.

3 Likes

What is EVCC? HA integration? How to get it in HA?

1 Like

Working on that right now

I have requested a trial subscription to their paid plan. The free tier doesn’t include predictions. My guess is that, in Belgium at least, most days there will be a big correlation with dynamic pricing as these go/up down mainly with wind and solar availability…

yes, sure. I can use the Forecast.solar Integration 4 times and add the values together in HA, but that gives only a single value, not a forecast list. I can’t find a way to call forecast.solar 4 times in EMHASS

solar.forecast

A third method uses the Solar.Forecast service. You will need to set method=solar.forecast and use just one parameter solar_forecast_kwp (the PV peak installed power in kW) that should be passed at runtime. This will be using the free public Solar.Forecast account with 12 API requests per hour, per IP, and 1h data resolution. As with Solcast, there are paid account services that may results in better forecasts.

For example, for a 5 kWp installation:

curl -i -H "Content-Type:application/json" -X POST -d '{"solar_forecast_kwp":5}' http://localhost:5000/action/dayahead-optim

I do have forecast variables for “today” and “tomorrow” for each of the 4 roofs in HA using the integration “Open-Meteo Solar Forecast”, so two entities per roof
they look like this:

entity: sensor.energy_production_today_6 
state: 30.66
attributes:
watts:
  "2024-07-16T00:00:00+02:00": 0
  "2024-07-16T00:15:00+02:00": 0
  "2024-07-16T00:30:00+02:00": 0
  "2024-07-16T00:45:00+02:00": 0
  "2024-07-16T01:00:00+02:00": 0
  "2024-07-16T01:15:00+02:00": 0
  "2024-07-16T01:30:00+02:00": 0
  "2024-07-16T01:45:00+02:00": 0
  "2024-07-16T02:00:00+02:00": 0
  "2024-07-16T02:15:00+02:00": 0
  "2024-07-16T02:30:00+02:00": 0
  "2024-07-16T02:45:00+02:00": 0
  "2024-07-16T03:00:00+02:00": 0
  "2024-07-16T03:15:00+02:00": 0
  "2024-07-16T03:30:00+02:00": 0
  "2024-07-16T03:45:00+02:00": 0
  "2024-07-16T04:00:00+02:00": 0
  "2024-07-16T04:15:00+02:00": 0
  "2024-07-16T04:30:00+02:00": 0
  "2024-07-16T04:45:00+02:00": 0
  "2024-07-16T05:00:00+02:00": 0
  "2024-07-16T05:15:00+02:00": 0
  "2024-07-16T05:30:00+02:00": 0
  "2024-07-16T05:45:00+02:00": 0
  "2024-07-16T06:00:00+02:00": 0
  "2024-07-16T06:15:00+02:00": 33
  "2024-07-16T06:30:00+02:00": 178
  "2024-07-16T06:45:00+02:00": 652
[....]
wh_period:
  "2024-07-16T00:00:00+02:00": 0
  "2024-07-16T01:00:00+02:00": 0
  "2024-07-16T02:00:00+02:00": 0
  "2024-07-16T03:00:00+02:00": 0
  "2024-07-16T04:00:00+02:00": 0
  "2024-07-16T05:00:00+02:00": 0
  "2024-07-16T06:00:00+02:00": 197.5
  "2024-07-16T07:00:00+02:00": 2433.5
  "2024-07-16T08:00:00+02:00": 2009.75
  "2024-07-16T09:00:00+02:00": 2886.5
  "2024-07-16T10:00:00+02:00": 5319.5
  "2024-07-16T11:00:00+02:00": 5122.75
  "2024-07-16T12:00:00+02:00": 1810
  "2024-07-16T13:00:00+02:00": 858
  "2024-07-16T14:00:00+02:00": 2903.75
  "2024-07-16T15:00:00+02:00": 3054.5
  "2024-07-16T16:00:00+02:00": 1797.75
  "2024-07-16T17:00:00+02:00": 1124.25
  "2024-07-16T18:00:00+02:00": 552.75
  "2024-07-16T19:00:00+02:00": 337.75
  "2024-07-16T20:00:00+02:00": 229
  "2024-07-16T21:00:00+02:00": 23.5
  "2024-07-16T22:00:00+02:00": 0
  "2024-07-16T23:00:00+02:00": 0
unit_of_measurement: kWh
device_class: energy
friendly_name: Meteo-Solar-Forecast-Dach vorne Ost Geschätzte Energieproduktion – heute
entity: sensor.energy_production_tomorrow_6
state: 27.805
attributes:
watts:
  "2024-07-17T00:00:00+02:00": 0
  "2024-07-17T00:15:00+02:00": 0
  "2024-07-17T00:30:00+02:00": 0
  "2024-07-17T00:45:00+02:00": 0
  "2024-07-17T01:00:00+02:00": 0
  "2024-07-17T01:15:00+02:00": 0
  "2024-07-17T01:30:00+02:00": 0
  "2024-07-17T01:45:00+02:00": 0
  "2024-07-17T02:00:00+02:00": 0
  "2024-07-17T02:15:00+02:00": 0
  "2024-07-17T02:30:00+02:00": 0
  "2024-07-17T02:45:00+02:00": 0
  "2024-07-17T03:00:00+02:00": 0
  "2024-07-17T03:15:00+02:00": 0
  "2024-07-17T03:30:00+02:00": 0
  "2024-07-17T03:45:00+02:00": 0
  "2024-07-17T04:00:00+02:00": 0
  "2024-07-17T04:15:00+02:00": 0
  "2024-07-17T04:30:00+02:00": 0
  "2024-07-17T04:45:00+02:00": 0
  "2024-07-17T05:00:00+02:00": 0
  "2024-07-17T05:15:00+02:00": 0
  "2024-07-17T05:30:00+02:00": 23
  "2024-07-17T05:45:00+02:00": 73
  "2024-07-17T06:00:00+02:00": 127
  "2024-07-17T06:15:00+02:00": 158
  "2024-07-17T06:30:00+02:00": 207
  "2024-07-17T06:45:00+02:00": 272
[...]
  "2024-07-17T23:45:00+02:00": 0
wh_period:
  "2024-07-17T00:00:00+02:00": 0
  "2024-07-17T01:00:00+02:00": 0
  "2024-07-17T02:00:00+02:00": 0
  "2024-07-17T03:00:00+02:00": 0
  "2024-07-17T04:00:00+02:00": 0
  "2024-07-17T05:00:00+02:00": 25.25
  "2024-07-17T06:00:00+02:00": 171
  "2024-07-17T07:00:00+02:00": 712.5
  "2024-07-17T08:00:00+02:00": 2917.25
  "2024-07-17T09:00:00+02:00": 3681
  "2024-07-17T10:00:00+02:00": 1174.75
  "2024-07-17T11:00:00+02:00": 1269.75
  "2024-07-17T12:00:00+02:00": 4377.25
  "2024-07-17T13:00:00+02:00": 3703.5
  "2024-07-17T14:00:00+02:00": 2426.25
  "2024-07-17T15:00:00+02:00": 2001.25
  "2024-07-17T16:00:00+02:00": 1963.75
  "2024-07-17T17:00:00+02:00": 1290.75
  "2024-07-17T18:00:00+02:00": 989
  "2024-07-17T19:00:00+02:00": 716.25
  "2024-07-17T20:00:00+02:00": 358
  "2024-07-17T21:00:00+02:00": 27.5
  "2024-07-17T22:00:00+02:00": 0
  "2024-07-17T23:00:00+02:00": 0
unit_of_measurement: kWh
device_class: energy
friendly_name: Meteo-Solar-Forecast-Dach vorne Ost Geschätzte Energieproduktion – morgen

so the “watts” attribute is a list in 15-minutes steps with pairs of (timestamp, forecast in watt).

but how to extrakt it?

now I’m trying to follow: The forecast module — emhass 0.10.6 documentation (example-using-solcast-forecast-amber-prices)

but of course I do have a different data structure (no “forecasts” atrribute in that entity, but a second list named “wh_period”, which I don’t need)

I can’t construct the equivalent to

  - platform: template
    sensors:
      solcast_24hrs_forecast :
        value_template: >-
          {%- set power = state_attr('sensor.solcast_forecast_data', 'forecasts') | map(attribute='pv_estimate') | list %}
          {%- set values_all = namespace(all=[]) %}
          {% for i in range(power | length) %}
           {%- set v = (power[i] | float |multiply(1000) ) | int(0) %}
            {%- set values_all.all = values_all.all + [ v ] %}
          {%- endfor %} {{ (values_all.all)[:48] }}

(apart from the fact that I have 72 value pairs per day, not 48, so 144 pairs total per roof)

so I would need 4 such templates (each for one roof), or even 8 (each roof, one for today, one for tomorrow)

Once I got those, I can then hopefully combine all of those (per day) like

    solcast_24hrs_forecast:
      value_template: >-
        {% set a = states("sensor.solcast_24hrs_forecast_garage")[1:-1].split(',') | map('int') | list %}
        {% set b = states("sensor.solcast_24hrs_forecast_huis")[1:-1].split(',') | map('int') | list %}
        {% set ns = namespace(items = []) %}
        {% for i in range(a | length) %}
          {% set ns.items = ns.items + [ a[i]  + b[i]  ] %}
        {% endfor %}
        {{ ns.items }}

with a, b, c, and d instead of just a and b
(but I’m not sure about the split parameters either).

and finally concatinate the days together
'{\"load_cost_forecast\":{{((state_attr('sensor.nordpool', 'raw_today') | map(attribute='value') | list + state_attr('sensor.nordpool', 'raw_tomorrow') | map(attribute='value') | list))[now().hour:][:24] }},\"prod_price_forecast\":{{((state_attr('sensor.nordpool', 'raw_today') | map(attribute='value') | list + state_attr('sensor.nordpool', 'raw_tomorrow') | map(attribute='value') | list))[now().hour:][:24]}}}

But only similar, using pv_power_forecast - but I have a list of (timestamp, value), not just a list of values - so again I’m a bit lost

So, I hope that I understand the principle, but I’m totally lost with the template syntax and how to stitch it all together …

sorry for the dump questions

Great! That should help!

Can you provide the yaml code to me instead of the screenshots? That would really help a lot!

Yes, I did see that - I do have different data structures and therefor that does not really help.

Again, it’s not the concept of what to do where I’m struggling: it’s the translation of that into templates and YAML code.

For the prices I have an EPEX spot sensor (modified to meet the prices e.g. Tibber without using their API), which provides this

entity: sensor.epex_spot_data_net_price_2
state: 19.016
attributes:
state_class: measurement
data:
  - start_time: "2024-07-16T00:00:00+02:00"
    end_time: "2024-07-16T01:00:00+02:00"
    price_ct_per_kwh: 28.404
  - start_time: "2024-07-16T01:00:00+02:00"
    end_time: "2024-07-16T02:00:00+02:00"
    price_ct_per_kwh: 26.879
  - start_time: "2024-07-16T02:00:00+02:00"
    end_time: "2024-07-16T03:00:00+02:00"
    price_ct_per_kwh: 25.536
  - start_time: "2024-07-16T03:00:00+02:00"
    end_time: "2024-07-16T04:00:00+02:00"
    price_ct_per_kwh: 23.671
[...]
  - start_time: "2024-07-17T09:00:00+02:00"
    end_time: "2024-07-17T10:00:00+02:00"
    price_ct_per_kwh: 28.47
  - start_time: "2024-07-17T10:00:00+02:00"
    end_time: "2024-07-17T11:00:00+02:00"
    price_ct_per_kwh: 26.215
  - start_time: "2024-07-17T11:00:00+02:00"
    end_time: "2024-07-17T12:00:00+02:00"
    price_ct_per_kwh: 24.258
  - start_time: "2024-07-17T12:00:00+02:00"
    end_time: "2024-07-17T13:00:00+02:00"
    price_ct_per_kwh: 23.168
  - start_time: "2024-07-17T13:00:00+02:00"
    end_time: "2024-07-17T14:00:00+02:00"
    price_ct_per_kwh: 21.89
  - start_time: "2024-07-17T14:00:00+02:00"
    end_time: "2024-07-17T15:00:00+02:00"
    price_ct_per_kwh: 20.575
  - start_time: "2024-07-17T15:00:00+02:00"
    end_time: "2024-07-17T16:00:00+02:00"
    price_ct_per_kwh: 20.893
  - start_time: "2024-07-17T16:00:00+02:00"
    end_time: "2024-07-17T17:00:00+02:00"
    price_ct_per_kwh: 23.917
  - start_time: "2024-07-17T17:00:00+02:00"
    end_time: "2024-07-17T18:00:00+02:00"
    price_ct_per_kwh: 26.63
  - start_time: "2024-07-17T18:00:00+02:00"
    end_time: "2024-07-17T19:00:00+02:00"
    price_ct_per_kwh: 29.159
  - start_time: "2024-07-17T19:00:00+02:00"
    end_time: "2024-07-17T20:00:00+02:00"
    price_ct_per_kwh: 32.01
  - start_time: "2024-07-17T20:00:00+02:00"
    end_time: "2024-07-17T21:00:00+02:00"
    price_ct_per_kwh: 41.656
  - start_time: "2024-07-17T21:00:00+02:00"
    end_time: "2024-07-17T22:00:00+02:00"
    price_ct_per_kwh: 36.363
  - start_time: "2024-07-17T22:00:00+02:00"
    end_time: "2024-07-17T23:00:00+02:00"
    price_ct_per_kwh: 32.964
  - start_time: "2024-07-17T23:00:00+02:00"
    end_time: "2024-07-18T00:00:00+02:00"
    price_ct_per_kwh: 30.334
unit_of_measurement: ct/kWh
icon: mdi:currency-eur
friendly_name: EPEX Spot Data Net Price

so the data is there, but I have no idea how to build a template sensor to get the data in the correct format and pass that to EMHAA (via curl)

I’ve just upgraded my HA and EMHASS to the latest versions (since my initial installation in January or so). Now the curl command gives an ‘internal server error’. Below is the format of the command I use, and below that the error reported by the Services Dev Tool. Did something change in the supported format?

Shell command defined in configuration.yaml:

shell_command:
  mpc_optim_emhass: >
    curl -i -H "Content-Type: application/json" -X POST -d '{
      "load_cost_forecast": [{% for item in states('sensor.load_cost_forecast').split(',') %}{% if not loop.first %},{% endif %}{{ item }},{{ item }}{% endfor %}],
      "prod_price_forecast": [{% for item in states('sensor.prod_price_forecast').split(',') %}{% if not loop.first %},{% endif %}{{ item }},{{ item }}{% endfor %}],
      "pv_power_forecast":{{ states('sensor.pv_power_forecast_halfhourly') }},
      "load_power_forecast":[{% for item in states('sensor.load_power_forecast').split(',') %}{% if not loop.first %},{% endif %}{{item}},{{item}}{% if loop.last %}]{% endif %}{% endfor %},
      "prediction_horizon":48,
      "soc_init":{{ (states('sensor.battery_state_of_capacity')|float(0))/100 }},
      "soc_final":0.6,
      "def_total_hours":[0]
    }' http://localhost:5000/action/naive-mpc-optim

Resulting string of this syntax from the Template Dev Tool:

    curl -i -H "Content-Type: application/json" -X POST -d '{
      "load_cost_forecast": [0.1271,0.1271,0.1096,0.1096,0.0967,0.0967,0.0957,0.0957,0.0991,0.0991,0.1116,0.1116,0.1315,0.1315,0.1502,0.1502,0.1613,0.1613,0.188,0.188,0.225,0.225,0.2175,0.2175,0.1852,0.1852,0.1661,0.1661,0.1661,0.1661,0.1661,0.1661,0.1661,0.1661,0.1661,0.1661,0.1661,0.1661,0.1661,0.1661,0.1661,0.1661,0.1661,0.1661,0.1661,0.1661,0.1661,0.1661],
      "prod_price_forecast": [0.0652,0.0652,0.0487,0.0487,0.0366,0.0366,0.0357,0.0357,0.0388,0.0388,0.0506,0.0506,0.0694,0.0694,0.0871,0.0871,0.0976,0.0976,0.1228,0.1228,0.1576,0.1576,0.1506,0.1506,0.1201,0.1201,0.102,0.102,0.102,0.102,0.102,0.102,0.102,0.102,0.102,0.102,0.102,0.102,0.102,0.102,0.102,0.102,0.102,0.102,0.102,0.102,0.102,0.102],
      "pv_power_forecast":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
      "load_power_forecast":[700,700,700,700,1000,1000,700,700,700,700,700,700,1000,1000,1000,1000,1000,1000,1500,1500,1500,1500,1000,1000,500,500,300,300,300,300,300,300,300,300,300,300,300,300,300,300,1000,1000,1000,1000,1000,1000,700,700],
      "prediction_horizon":48,
      "soc_init":0.16,
      "soc_final":0.6,
      "def_total_hours":[0]
    }' http://localhost:5000/action/naive-mpc-optim

The ‘pv_power_forecast’ has all zeros, probably because the Solcast API call did not return properly, but the format is what counts I suppose.

Here is the error message:

stdout: "HTTP/1.1 500 INTERNAL SERVER ERROR\r\nContent-Length: 265\r\nContent-Type: text/html; charset=utf-8\r\nDate: Thu, 18 Jul 2024 08:12:00 GMT\r\nServer: waitress\r\n\r\n<!doctype html>\n<html lang=en>\n<title>500 Internal Server Error</title>\n<h1>Internal Server Error</h1>\n<p>The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application.</p>"
stderr: "% Total    % Received % Xferd  Average Speed   Time    Time     Time  Current\n                                 Dload  Upload   Total   Spent    Left  Speed\n\r  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0\r100  1418  100   265  100  1153    840   3659 --:--:-- --:--:-- --:--:--  4501"
returncode: 0

Thanks for any advise in getting this working again!

… which I can’t get to work with 4 roofs … I can’t construct the correct templates :frowning:

so back to find similar entries from the pvlib database.

What values do I have to look at? Just the max PV power of the modules (bifacial, 430W)? And the max power of the hybrid inverter (10 kW)? Anything else?

my first guesses are:

Risen_Energy_Co__Ltd__RSM144_7_430BMDG
Ginlong_Technologies_Co___Ltd___RHI_1P10K_HVES_5G__240V_

does that make any sense, or are there better choices?

the real inverters are:
Deye SUN-10K-SG01HP3-EU-AM2

the real modules are
JA Solar JAM5-4D41-430/LB

Don’t look any further, those are fine. We just need similar nominal powers. You’ve found two models with equals values to your real equipment, it should be good enough.
Now follow the documentation, you should be able to configure those 4 roofs easily.

1 Like

Looks great.

Can you share the 4 scripts as well? That would be really helpful!