EMHASS: An Energy Management for Home Assistant

First, huge thanks to David and others for such a fantastic tool! It takes a lot of effort to set it up, but I’m sure, the reward will be there.

I have a silly issue which I am not able to solve myself. All the basic stuff are fully functional and I get impressive optimisation schedules which are mostly rational as well, however with one caveat. The electricity price is wrong in relation to timestamps.

I live in Finland and use Nordpool to extract price data. Solcast integration is set for solar prediction modeling. Nordpool has hourly data whereas Solcast 30 min. I would much prefer to widen Nordpool data to a template sensor with price in 30 min or even 15 min intervals compared to dampening Solcast data to hourly format. Reason being that Finnish pricing system is getting more dynamic all the time and netting for solar production is already performed in 15 min intervals. I suppose, a prection model with more detailed data would overcome some of complexity. Yes, I probably need to set up a functional mpc to fully solve this, but still.

So how have you solved this? Here’s my current command, but this leads to wrong timestamps and a large error in modeling.

trigger_nordpool_forecast:
  url: http://homeassistant.local:5000/action/dayahead-optim
  method: POST
  content_type: 'application/json'
  payload: >-
    {
      "pv_power_forecast":{{ 
        ([states('sensor.inverter_input_power') | int(0)]) + 
        (state_attr('sensor.solcast_pv_forecast_forecast_today', 'detailedForecast') | 
        selectattr('period_start', 'gt', utcnow()) | map(attribute='pv_estimate') 
        |map('multiply', 1000) | map('int') | list + 
        state_attr('sensor.solcast_pv_forecast_forecast_tomorrow', 'detailedForecast') | 
        selectattr('period_start', 'gt', utcnow()) | map(attribute='pv_estimate') | 
        map('multiply', 1000) | map('int') | 
        list)[:(state_attr('sensor.nordpool_kwh_fi_eur_3_095_024', 'raw_today') | 
        map(attribute='value') | list  + 
        state_attr('sensor.nordpool_kwh_fi_eur_3_095_024', 'raw_tomorrow') | 
        map(attribute='value') | list)[now().hour:][:24] | length]
      }}, 
      "load_cost_forecast":{{
        ((state_attr('sensor.nordpool_kwh_fi_eur_3_095_024', 'raw_today') | map(attribute='value') | list  + 
        state_attr('sensor.nordpool_kwh_fi_eur_3_095_024', 'raw_tomorrow') | map(attribute='value') | list))[now().hour:][:24]
      }}, 
      "prod_price_forecast":{{
        ((state_attr('sensor.nordpool_kwh_fi_eur_3_10_024', 'raw_today') | map(attribute='value') | list + 
        state_attr('sensor.nordpool_kwh_fi_eur_3_10_024', 'raw_tomorrow') | map(attribute='value') | list))[now().hour:][:24]
      }}
    }

This is the ChatGPT-interpretation of a similar problem, but it doesn’t work because list.extend and list.append are forbidden commands in HASS environment.

{% set original_list = [1, 2, 3, 4, 5] %}  {# Example original list #}
{% set repeated_list = [] %}

{% for num in original_list %}
    {% set _ = repeated_list.extend([num, num]) %}
{% endfor %}

Original List: {{ original_list }}
Repeated List: {{ repeated_list }}
Original List: [1, 2, 3, 4, 5]
Repeated List: [1, 1, 2, 2, 3, 3, 4, 4, 5, 5]

… and answering to myself. So typical to spend endless time searching answers in the wrong places or parts of this thread when necessary hints are just above.

This seems to do the intended trick:

- sensor:
  - name: "Nordpool 30min"
    unique_id: nordpool_30min
    state: >
      {{ 'Nordpool 30min' }}
    attributes:
      prices: >-
        {%- set data = ((state_attr('sensor.nordpool_kwh_fi_eur_3_095_024', 'raw_today') | map(attribute='value') | list  + state_attr('sensor.nordpool_kwh_fi_eur_3_095_024', 'raw_tomorrow') | map(attribute='value') | list))[now().hour:] -%}
        {%- set repeated_list = namespace(h=[]) %}
        {%- for num in data %}
            {%- set repeated_list.h = repeated_list.h + [ num , num ] %}
        {%- endfor %}
        {{ repeated_list.h }}

Only thing is to remove first item of the list based on the minutes of the current hour. Similar thing, Erik above did. Thanks for that!

4 Likes

what do your automations look like when it comes to charging vs discharging the battery

You mean me? I actually don’t have a battery. So far system only includes floor heating for basement, water boiler and EV. All defined as regular deferrable loads. Biggest challenge will be to maximize usage of solar usage and battery would help, obviously. Two years back I had the idea about buying a V2G-charger to do the similar thing, but currently that technology with a sensible price seems to be as far away as it was then.

This is the latest optimization plan. To me it is already “correct” so basic functionality is as it should be, I guess. I’m trying to tackle the challenge of maximizing usage of solar production by smart EV charging througout the day and probably adding some HVAC control there as well. Problem is that netting is in 15 min intervals and weather is often partly cloudy over here so solar production is unpredictable. Currently I’m hoping to find a good enough solution without battery.

Now I’m stuck in my thinking.
load_negative: false
Should I set it to true or false?
When I consume power from the grid, I get - values. But when I have overproduction, I get + values.
Batteries on the other hand when it discharges it is - and when it charges it is + values.
The same thing then applies to my sensor.power_load_no_var_loads, you have to remove your consumers, that means that I have to change the code to + Brainfreeze her now.
But as I can see in emhass when it comes to the battery, + is discharging and - is charging.

- platform: template
  sensors:
    power_load_no_var_loads:
      friendly_name: "Power Load (no Var Loads)"
      unit_of_measurement: "W"
      device_class: "power"
      unique_id: fbfeef21-1aa3-4a54-b781-426f46fef597
      value_template: >
        {% set powerload = states('sensor.huset_i_watt_fran_grid') | float(default=0) %}
        {% set tvatt_power = states('sensor.tvattmaskin_energy_power') | float(default=0) %}
        {% set disk_power = states('sensor.nous_1_energy_power') | float(default=0) %}
        {% set value = (powerload + tvatt_power + disk_power) | round(1) %}
        {{ value }}

Hi No, I meant it as a general question in the thread.

The load is the power consumption of your house p_load. It is only from power consumer devices, no power generation devices, so it always has the same sign. Either you can express it by all negative values or by all positive values. Hence the load_negative=true or false.

This is what we call p_grid which can effectively change signs depending on over consumption or over production. Not to be confused with the p_load which cannot change signs

I use Node Red. You can kind of follow the flows if you look at the nodes in the attached image. Its also documented here.

I Was hoping for a little asistant to be able to calculate the amount of solar predicted before 2pm that day. I havnt been able to figure this out at all.

So my retail rates change after 2pm so i want the forcast to predict full charge before 2pm and if the forcast is not greater the 40kwh i need to force charge so i dont touch the grid overnight or schedule charging batteries so i can charge the car after 8pm. The application is endless.

I have the solcast push data over and then this pushes into emhass perfect. I just need to calculate this myself.

Does anybody use EVCC for solar EV charging and cheap dynamic prices?
Any advice on how to combine EVCC and EMHASS logic?

Use a template sensor. Use a for to loop into the PV forecast and then cumulate the energy in kWh up until 2pm.
As the PV forecasted power is given in W and supposing a 30min time step the loop pseudo-algorithm could be something like:

energy = 0
delta_t = 30/60 # The time step in hours
for i in range(len(p_pv)):
    energy = energy + p_pv[i]*delta_t/1000 # This will be in kWh
    if timestamp[i].hour == '14:00':
        break

Could you elaborate a bit more?
If you want to plan your EV charging just suppose that it is a deferrable load and that’s it. Probably add the start and end hours functionalities to have more control on when you need your EV to be charged. If you know your EV SOC you could also build a sensor to dynamically compute the number of hours for that EV deferrable load in order to charge to a desired SOC.

@davidusb
I switched load_forecast_method from naive to mlforecaster, because I had a issue with my load sensor in HA since yesterday 6AM and because of that load forecast was pretty much zero for today and tomorrow. I used delta_forecast: 2 before.

Now i did ML forecast Fit with 15 days of data and load_forecast_method from naive to mlforecaster gave me a logical forecast for today and tomorrow.

Just two questions:

  1. Should I run ML forecast fit now time to time so it will be up to date or emhass does it automatically? If not how often should i run it? Daily?
  2. How can i be sure load_forecast_method is using the correct model in dayahead and MPC. Default is sensor.power_load_no_var_loads but my correct model is sensor.ss_load_power

I note the freq (timestep to resample) is defaulted to 30 min and I know the recommendation is not to set it too low or we may run into memory issues.
However, our energy market is in 5 min intervals so I would like to supply electricity costs as 288 intervals of 5 min.
I tried setting it the freq to 5 but got an error that the minimum is 10. Setting it to 10 minute timesteps (and prediction interval to 144) made the mpc_optim process in 4 seconds (instead of 1 second when running 30 min timesteps)
Would you please enable the next version allow a minimum of 5 minute intervals and 288 prediction horizons? Thanks.

You should do this yourself. EMHASS will not do this automatically.
Just setup an automation to refit your model. I’ve setup mine to do it daily.

The load forecast will use whatever sensor you tell it to use.
It is just that the default value is sensor.power_load_no_var_loads.
You can change this default either by modifying your configuration file in the add-on configuration pane. Or by passing a custom name for your sensor as additional params to your curl call. In this last case you override the value set in the configuration file.

1 Like

Yes no problem. We could set the hard coded minimum to 1 min.
Could you please open a new issue to add this to the to do kanboard column?
Open a new issue here: Issues · davidusb-geek/emhass · GitHub

Thanks.

Created Feature Request Issue but I don’t think I have permission to add to the project To Do.

@davidusb , Should i do the ML Forecast model Fit or ML Forecast model Predict daily or both?

Done! Just added it to the project list

1 Like

Just the fit. The predict task is called automatically on optimization if you have chosen the MLForecaster as a method for load forecast

1 Like