EMHASS: An Energy Management for Home Assistant

I have done this, how have you provided the EMHASS the visabilty of the export limiting?

i have mine see the total average production or the solaredge values usuing templates, these are verry acurate and 90% of time are the same as my app, but yet the EMHASS doesnt realise i export most days and this is common and tries to export battery rather then calculate this.

Thatā€™s how I use MPC. Or, actually as a combination of those. The reason behind this is that my electricity prices for the next day are updated daily at 13:00. Prices have an hourly resolution and change much from day to day.
So at the beginning of a day, I have 24 hours of forecasts for prices, solar power and consumption. As the day progresses, I have to reduce the MPC horizon until at 13:00, when itā€™s at its shortest 11 hours. At 14:00 (or just before), I receive updated Nordpool prices and can then use a full 24 hour sliding window horizon until midnight.
The advantage for me is that I can quickly adapt to changes in solar power if the forecast turned out inaccurate, or unpredictable electricity usage, so I can frequently recalculate my optimizations based on current soc. I always use a target SOC of 50%. Not that it really matters, because those 50% are always at least 11 hours away, so I can still optimize the battery use up to that point.

In progress/TODO in my setup:
Make a better solar power prediction based on local weather cloud density data.
Start making use of deferable loads. Just the PHEV, but still good to know whenā€™s a good time to charge it.
Make a more ā€œnaturalā€ battery control logic to use more of the inverterā€™s automatic setting

3 Likes

Can you perhaps share your prediction_horizon code, still looking to solve this. ThankS

Optimisation with negative sell price and buy costs

We are fairly lucky in Australia with an abundance of renewable energy which means most days the grid has an oversupply issue which drives the prices down, often negative. Today for example I have negative production prices until 16:00

I have a very light load today and my home battery will be full by 14:00, so what happens then. EMHASS optimisation addresses this by selling into a negative price market at the cheapest times to minimise the total negative pricing.

In reality what I do is turn on export control (zero export) in my solar inverter so I donā€™t actually export anything when the prices are negative. When the costs are negative (rarely) I switch my inverter to production control (zero production) as I am getting paid to consume energy from the grid.

So the current EMHASS optimisation is correct but there is a more optimal solution available by considering export and production control. Now I could just artificially set my solar forecast during these windows to my forecast load, but I still want to encourage EMHASS to switch on any additional loads as the energy is available for free.

I realise this is a ā€˜niceā€™ problem to have but am interested in thoughts from others?

1 Like

Iā€™m wondering if this is because of the target SOC, which is a strict requirement, so it tries to minimise the impact of negative prices to reach that value, even though in this case itā€™s not optimal.
As you are runing the optim very often maybe being able to switch the ā€œno grid exportā€ on when you have negative prices ahead could be helpful?

How are you running EMHASS? profit/cost/self-consumption?

EMHASS is making the correct calculations, in the absence of curtailment. Iā€™m optimising for profit.

If I have to export 20 kWh, it maximises profit to export now at -1Ā¢/ kWh rather than later at -6Ā¢/ kWh.

This isnā€™t dependent on my battery SOC final, rather the best way to maximise profit when I have an oversupply of solar production for the day.

Hi
I seem to be getting an error with EMHASS:

2023-09-30 20:40:17,173 - web_server - ERROR - Exception on /action/naive-mpc-optim [POST]
Traceback (most recent call last):
  File "/usr/local/lib/python3.9/dist-packages/flask/app.py", line 2190, in wsgi_app
    response = self.full_dispatch_request()
  File "/usr/local/lib/python3.9/dist-packages/flask/app.py", line 1486, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/usr/local/lib/python3.9/dist-packages/flask/app.py", line 1484, in full_dispatch_request
    rv = self.dispatch_request()
  File "/usr/local/lib/python3.9/dist-packages/flask/app.py", line 1469, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
  File "/usr/local/lib/python3.9/dist-packages/emhass/web_server.py", line 204, in action_call
    opt_res = naive_mpc_optim(input_data_dict, app.logger)
  File "/usr/local/lib/python3.9/dist-packages/emhass/command_line.py", line 265, in naive_mpc_optim
    df_input_data_dayahead = input_data_dict['fcst'].get_load_cost_forecast(
  File "/usr/local/lib/python3.9/dist-packages/emhass/forecast.py", line 705, in get_load_cost_forecast
    forecast_out = self.get_forecast_out_from_csv(
  File "/usr/local/lib/python3.9/dist-packages/emhass/forecast.py", line 522, in get_forecast_out_from_csv
    forecast_out = pd.DataFrame(
  File "/usr/local/lib/python3.9/dist-packages/pandas/core/frame.py", line 694, in __init__
    mgr = ndarray_to_mgr(
  File "/usr/local/lib/python3.9/dist-packages/pandas/core/internals/construction.py", line 351, in ndarray_to_mgr
    _check_values_indices_shape_match(values, index, columns)
  File "/usr/local/lib/python3.9/dist-packages/pandas/core/internals/construction.py", line 422, in _check_values_indices_shape_match
    raise ValueError(f"Shape of passed values is {passed}, indices imply {implied}")
ValueError: Shape of passed values is (9, 1), indices imply (7, 1)

Any idea what the cause might be?
Thanks
Rob

It would help if you could post your MPC payload that causes this error.

@davidusb it would also help debugging if the payload received for MPC was printed in the logs.

Thanks Mark

{"load_cost_forecast":[0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.13, 0.13, 0.13, 0.13, 0.12, 0.12, 0.12, 0.12, 0.12, 0.1, 0.04, 0.03, 0.03, 0.02, 0.02, -0.01, -0.02, -0.04, -0.04, -0.05, -0.05, -0.02, -0.01, 0.27, 0.28, 0.28, 0.28, 0.29, 0.3, 0.32, 0.39, 0.42, 0.51, 0.48, 0.51, 0.26, 0.26, 0.2, 0.18, 0.18],"prod_price_forecast":[0.06, 0.06, 0.07, 0.06, 0.06, 0.06, 0.06, 0.06, 0.04, 0.04, 0.04, 0.03, 0.03, 0.02, 0.03, 0.02, 0.02, 0.01, -0.05, -0.05, -0.06, -0.06, -0.07, -0.11, -0.12, -0.14, -0.14, -0.15, -0.15, -0.12, -0.11, 0.19, 0.2, 0.2, 0.21, 0.21, 0.22, 0.24, 0.3, 0.33, 0.41, 0.39, 0.42, 0.15, 0.15, 0.1, 0.08, 0.08],"pv_power_forecast":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 160, 627, 1147, 1697, 2249, 2685, 3066, 3385, 3632, 3800, 3903, 3929, 3905, 3827, 3701, 3498, 3237, 2904, 2499, 1909, 1366, 828, 302, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],"prediction_horizon":48,"soc_init":0.19,"soc_final":0.11,"num_def_loads":2,"def_total_hours":[3,4],"P_deferrable_nom":[1300,7360],"treat_def_as_semi_cont":[1, 0],"set_def_constant": [0, 0]}

Iā€™ve been having trouble with reading Tesla data. Would only register 5kW charging to day when actual was 7kW. Iā€™ve now upgraded the Tesla HACS in the hope that fixes the issue.

Still using solcast 3.1.6. Havenā€™t upgraded to 4.0.8.

I basically just take the shortest length of the available forecast lists.

    {%- set horizon = [nordpool_sell.values|length, nordpool_buy.values|length, solcast|length]|min %}

I already know the lists are at most 24 values. If you donā€™t, just add the constant 24 to the min filter.

Im failry certian the tesla can not charge at 7kw. It has the function for constant of 5kw and 7kw surge load only,

Is your app showing 7kw charge??

Ive been install about 2 a week since the rebate and ive never seen a 7kw charge. And i have over 40 sites i manage.

I almost always see charging at 5 kW per powerwall, I think I have only seen it surge to 7 kW for a few seconds.

Hi guys,

So for the verification. The prediction_horizon in the MPC, should it contain only the value for the day or would the day after that also be good enough?

In the Netherlands the pricing for the next day will be published around 13.00/13.30 hours. So the prediction_horizon will be less between 00.00-13.00 every day.

See my MPC:

    {
      "prod_price_forecast": {{
      ((state_attr('sensor.nordpool_kwh_nl_eur_3_09_0', 'raw_today') | map(attribute='value') | list  + state_attr('sensor.nordpool_kwh_nl_eur_3_09_0', 'raw_tomorrow') | map(attribute='value') | list))[now().hour:][:24]
        | tojson
      }},
      "load_cost_forecast": {{
      ((state_attr('sensor.nordpool_kwh_nl_eur_3_09_0', 'raw_today') | map(attribute='value') | list + state_attr('sensor.nordpool_kwh_nl_eur_3_09_0', 'raw_tomorrow') | map(attribute='value') | list))[now().hour:][:24]
        | tojson
      }},
      "pv_power_forecast": {{
        ([states('sensor.solaredge_ac_power')|int(0)] +
        state_attr('sensor.solcast_pv_forecast_forecast_today', 'detailedHourly')|selectattr('period_start','gt',utcnow()) | map(attribute='pv_estimate')|map('multiply',1000)|map('int')|list +
        state_attr('sensor.solcast_pv_forecast_forecast_tomorrow', 'detailedHourly')|selectattr('period_start','gt',utcnow()) | map(attribute='pv_estimate')|map('multiply',1000)|map('int')|list
        )| tojson
      }},
      "prediction_horizon": {{
          min(24, (((state_attr('sensor.nordpool_kwh_nl_eur_3_09_0', 'raw_today')|map(attribute='value')|list + state_attr('sensor.nordpool_kwh_nl_eur_3_09_0', 'raw_tomorrow') | map(attribute='value')| list)[now().hour:][:24]|list|length)))
        }},
      "alpha": 1,
      "beta": 0,
      "num_def_loads": 2,
      "def_total_hours": [{{states('input_number.def_total_hours_ww')}},{{states('input_number.def_total_hours_ev')}}],
      "treat_def_as_semi_cont": [1,0],
      "set_def_constant": [1,0],
      "soc_init": {{ (states('sensor.sofarcontroller_battery_soc')|int(0))/100 }}
    }

Current output:

{
  "prod_price_forecast": [
    0.302,
    0.286,
    0.284,
    0.281,
    0.281,
    0.284,
    0.301,
    0.329,
    0.416,
    0.471,
    0.368,
    0.319,
    0.303,
    0.295
  ],
  "load_cost_forecast": [
    0.302,
    0.286,
    0.284,
    0.281,
    0.281,
    0.284,
    0.301,
    0.329,
    0.416,
    0.471,
    0.368,
    0.319,
    0.303,
    0.295
  ],
  "pv_power_forecast": [
    3359,
    1829,
    3389,
    3095,
    2697,
    2333,
    1506,
    615,
    119,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    5,
    114,
    400,
    720,
    951,
    992,
    986,
    1071,
    1156,
    1050,
    691,
    183,
    0,
    0,
    0,
    0,
    0
  ],
  "prediction_horizon": 14,
  "alpha": 1,
  "beta": 0,
  "num_def_loads": 2,
  "def_total_hours": [
    0,
    0
  ],
  "treat_def_as_semi_cont": [
    1,
    0
  ],
  "set_def_constant": [
    1,
    0
  ],
  "soc_init": 0.17
}

Iā€™m talking about my car, not a PW. My home battery is a sonnen.

As I previously mentioned, I have the same situation in Sweden with Nordpool prices. I have the same setup where I use a 24 hour prediction horizon when available. My Nordpool integration is updated at around 14:00 every day, so from that time, I use a 24 hour horizon that stretches into the next day. Since I donā€™t focus on having a specific target SOC at a specific time, I just let the MPC do the optimization for as far as it can, towards a 50% SOC. TBH, I wouldnā€™t mind allowing the MPC to try o optimize even further to the end of next day, since I have the forecast data to do it, but it has a hard-coded limit of 24 hours.
And as you mention, from 00:00, until next update of Nordpool prices, my horizon shrinks below 24 hours to, at its shortest, 10 hours just before Nordpool sensor is updated again.

Sometimes, if the Nordpool integration acts up, it can be even less. I even have an automation to reload the Nordpool integration if I havenā€™t received updated prices at 15:00.

Your code looks good. Does it work?

Sure it works perfectly. But reading the documentation about MPC itā€™s explaining that MPC works the best in the full day.

Thatā€™s why Iā€™m asking around.

I was talking about the car. The Tesla Model Y was charging at 32 amps but only reporting 5 kW through the Tesla HACS integration.
Iā€™ve also notices the sonnen home battery slowly drops input and output as the heat goes up. Doesnā€™t like staying at full performance for long periods.
This seems to cause some corruption and neither dayahead nore MPC would run with the error I posted above.

ValueError: Shape of passed values is (9, 1), indices imply (7, 1)

I updated the Tesla custom integration and upgraded HA and the solcast integration (and a number of other components).
Had to leave it for 24 hours before dayahead started to work again but MPC would not run for 48 hours, but it always does that. Canā€™t run MPC for 48 hours after a restart or upgrade.
MPC just started working again an hour ago.

Ideally you are optimizing 00:00-23:59 but I guess the 24h can start when you want, depending on your preference, data availability and so on. The idea about the 24h and reducing horizon is that you would like to know when you want to reach the soc_final. But itā€™s an idea, maybe like some of us you are not really interested in discharging (for profit maybe) the battery to reach that value at the end of the 24h. There is still room for a lot of personal and specific considerations, once you get the original idea behind it.

You can also refer to this answer from David: https://community.home-assistant.io/t/emhass-an-energy-management-for-home-assistant/338126/1231?u=110hs

3 Likes

Agree with 110hs here. It depends on what your purpose is with the optimization.
If your goal is to reach a specific target SOC at a specific time, you should reduce your horizon for every recalculation so you keep the target time.

In my scenario, I donā€™t really care what SOC I have at midnight, or at any other time. I only care about optimizing charging, discharging, buying and selling, in order to maximize profit. I may change to a higher min SOC later in order to keep some backup power in the battery in case of a blackout, but I havenā€™t installed the backup solution yet. So for now, I just optimize for profit, and knowing what happens in hour 23 of a 24 hour horizon may change the battery strategy.

1 Like

I echo that. Just to share with everybody (maybe this inspires somebody or somebody will inspire me) what Iā€™m planning to do: Iā€™m mostly interested in self-consumption so I hope (ā€œWinter is comingā€ in EU :wink: ) EMHASS will let me know the maximum I have to charge the battery at night (low prices) in order to be able to cover my household consumption of the next day, in combination with the expected solar production (wich in this season is not enough to cover everything). Iā€™m using MPC only (for its flexibility in setting the initial SOC) with a still reducing horizon, as I may want to have a backup of 20% (I hope I can get at the least possible price) to be sure to partially cover the consumption of the following night (basically I do not plan to discharge my battery but only charge it as needed).

2 Likes