EMHASS: An Energy Management for Home Assistant

thanks guys - with your examples I managed to set up my battery optimization; just before holidays so family is grateful I think :slight_smile:

Few questions, perhaps some of you have solved for this before:

1./ my only deferable load is the car; it is currently fully charged but still taken into account for scheduling. is it possible to dynamically set number of hours to 0 (or 1, 2 ,3 etc) depending on the state of charge?

Note - for now I adjusted the deferable load to 1 hour and a rather low kW mitigate impact on battery schedule

2./ In an earlier post I mentioned the wish to take into account a minimum cost for usage of the battery. Rather than solving for this with an automation (preventing discharge if delta between purchase and sell price < 4 cents) would it be possible to deduct 4 cents from the nordpool array which feeds into prod_price_forecast? Or perhaps easier to set up a second nordpool integration with a different pricing structure?

Great addon; I have been pondering setting it up for the past year, glad I finally did!

Thanks for the information,
I changed now the dayahead_optim:

dayahead_optim: "curl -i -H \"Content-Type:application/json\" -X POST -d '\"pv_power_forecast\":{{([states('sensor.solaredge_ac_power')|int(0)] + state_attr('sensor.forecast_today', 'detailedForecast')|selectattr('period_start','gt',utcnow()) | map(attribute='pv_estimate')|map('multiply',2000)|map('int')|list + state_attr('sensor.forecast_tomorrow', 'detailedForecast')|selectattr('period_start','gt',utcnow()) | map(attribute='pv_estimate')|map('multiply',2000)|map('int')|list)[:48]| tojson }}}' http://localhost:5000/action/dayahead-optim"

The daily price doesnā€™t matter for the moment cause I have a variabel tarrif wich changing just every 3 months. (maybe later I changing to a dynamic price)

and my EV is indeed capable of varying the rate so this I changed to false.

But now I see this all the time for p_batt_forecast and Soc_batt_forecast:
sensor.p_batt_forecast = 0.0
sensor.soc_batt_forecast = 60.0

It make sense because its taking al the time the PV_power to the EV charger.
But how can I make now the best automation? because this is just a prediction about tomorrow, but I know now that my EV is not always plugged in on this times, but than I want to take my PV energie to the batterie.

One additional question, my shell command is the following:

trigger_nordpool_forecast: "curl -i -H \"Content-Type: application/json\" -X POST -d '{
  \"load_cost_forecast\":{{((state_attr('sensor.nordpool_kwh_nl_eur_3_10_0', 'raw_today') | map(attribute='value') | list  + state_attr('sensor.nordpool_kwh_nl_eur_3_10_0', 'raw_tomorrow') | map(attribute='value') | list))[now().hour:][:24] }},
  \"prod_price_forecast\":{{((state_attr('sensor.nordpool_kwh_nl_eur_3_10_0', 'raw_today') | map(attribute='value') | list  + state_attr('sensor.nordpool_kwh_nl_eur_3_10_0', 'raw_tomorrow') | map(attribute='value') | list))[now().hour:][:24]}},
  \"soc_init\":{{((states('sensor.growatt_growatt_battery_soc') | float(0))) / 100 }},
  \"soc_final\":0.1
  }' http://localhost:5000/action/dayahead-optim"

{{((states('sensor.growatt_growatt_battery_soc') | float(0))) / 100 }} yields 1.0, for some reason though emhass assumes my battery is empty; any thoughts? some syntax error? No issues flagged in the log file.

I changed it to a fixed value - eg. \"soc_init\":1.0, but same issueā€¦

It is working with the MPC version; just to confirm, is this functionality only implemented within MPC?

Iā€™m not sure how this method works. @davidusb will know. I suspect that one list makes the calculation look for the other lists? Perhaps experiment with inluding your static tariffs in a list of 48 1/2 hour elements.
Something like this?

dayahead_optim: "curl -i -H \"Content-Type:application/json\" -X POST -d '\"load_cost_forecast\":{{"[" + "0.32, " * 47 + "0.32]"}}\"prod_price_forecast\":{{"[" + "0.22, " * 47 + "0.22]"}},\"pv_power_forecast\":{{
([states('sensor.solaredge_ac_power')|int(0)] + state_attr('sensor.forecast_today', 'detailedForecast')|selectattr('period_start','gt',utcnow()) | map(attribute='pv_estimate')|map('multiply',2000)|map('int')|list + state_attr('sensor.forecast_tomorrow', 'detailedForecast')|selectattr('period_start','gt',utcnow()) | map(attribute='pv_estimate')|map('multiply',2000)|map('int')|list)[:48]| tojson 
}}}' http://localhost:5000/action/dayahead-optim"

No, you can get away without passing any data as list, thatā€™s actually how I use it myself. EMHASS proposed default methods internally for these 4 needed forecasts so that you donā€™t need to pass anything by default. However passing data as list is extremely useful when you want to use external forecast provider data as AMBER, etc.

1 Like

When using the dayahead-optim endpoint the battery SOC can be set using the SOCtarget parameter that can be set either on the add-on configuration pane or directly in your shell command call template on the passed JSON that follows the -d flag.
For dayahead-optim we suppose that SOCinit=SOCtarget because it is a common approach when optimizing a complete day of energy flows.

If you are using the naive-mpc-optim then you will be able to set custom values for soc_init and soc_final. When using this MPC method you are also able to set the prediction_horizon and the def_total_hours parameters.

Here is the list of the other additional dictionary keys that can be passed at runtime on your shell command template for any endpoint method:

  • num_def_loads for the number of deferrable loads to consider.
  • P_deferrable_nom for the nominal power for each deferrable load in Watts.
  • def_total_hours for the total number of hours that each deferrable load should operate.
  • treat_def_as_semi_cont to define if we should treat each deferrable load as a semi-continuous variable.
  • set_def_constant to define if we should set each deferrable load as a constant fixed value variable with just one startup for each optimization task.
  • solcast_api_key for the SolCast API key if you want to use this service for PV power production forecast.
  • solcast_rooftop_id for the ID of your rooftop for the SolCast service implementation.
  • solar_forecast_kwp for the PV peak installed power in kW used for the solar.forecast API call.
  • SOCtarget for the desired target value of initial and final SOC.
  • publish_prefix use this key to pass a common prefix to all published data. This will add a prefix to the sensor name but also to the forecasts attributes keys within the sensor.
3 Likes

many thanks!

Out of curiosity, do you yourself also use this to plan dishwasher, dryer and laundry machine as deferable load? If so, how do you go about the power profile? For instance, my dishwasher peaks for 15 minutes at 2kw (water heating) after which for 1.5 hrs it consumes 20 - 50 watt; followed by 20 minutes at 2kw (drying) - in this case would you take the average consumption over 3.5hours? or instead use the peak usage?

And for an EV, letā€™s say it needs to run for 4 hours at 11kw but the charge speed is scalable, eg is could also opt for 8 hours at 5.5kw - can emhass play around with this?

1 Like

1./ The way Iā€™d try to do it is change ā€œdef_total_hoursā€:[2] to something like this (assume 10 hr is your max). But I donā€™t know how advisable it is to do this:

"def_total_hours":[{% set hours = (10 - states('sensor.car_battery_perdentage_charged')|float(0) / 10)|int(0) %} {{- hours -}}]

2./ Not sure about nordpool but I assume you can manipulate the output with jinja. Would have to see what the data looks like.

I created a second sensor with a 5 cents cost build in for production cost / charge losses. Oddly though this leads to some weird outcomes. Looking at the below table it appears based on this data set EMHASS recommends self consumption; is my conclusion correct? In other words, if I penalize selling to grid by 5 cents rather than not charging the battery the conclusion is to charge moderately and consume later. Obviously not entirely what I had in mind.

Another questionā€¦ I now adjusted battery efficiency to 90% on both legs, effectively simulating a 20% loss; this has the desired effect. However the outcome triggers a new question, should I also treat my batter as a deferable load? Looking at the above table the assumption is now ca. 14.5kwh household loan between 2 and 4 am (coincidentally the time I charged the battery last night).

This is exactly how I charge my EV with EMHASS.

image

I set def_total hours to the number of hours (3 hrs) it will take a maximum charging rate (11 kW) to get from the current SOC to the SOC charge limit. EMHASS then schedules the charging sometimes using maximum rate (see 12-3pm today) when it is cheap to charge from the grid and scaleable charging rates (see after 10am tomorrow).

I can slide the Charge Limit (currently 90%) if I want to charge less in a day. Ideally I would automatically set charge limit based on how much driving I am doing in the next couple of days, or how cheap the energy is for the next couple of days (maybe 50% during the week when energy is higher and 90% on the weekends when it is cheaper)

image

You donā€™t need to treat your battery as a deferrable load, but the power consumption of your battery shouldnā€™t be included in the power_load_no_var_loads sensor. The power_load_no_var_loads needs to measure the consumption of your household, regardless if it is supplied from your battery, solar or grid. It looks like you maybe just using your grid consumption figure, which doesnā€™t take into account those other sources.
https://emhass.readthedocs.io/en/latest/intro.html#configuration-and-installation

You are right, I now defined it as ā€œgrid consumption - ev chargerā€ should then also deduct/add back "battery charge/discharge as well as add pv generation and deduct amounts returned to grid.

I use https://github.com/jonasbkarlsson/ev_smart_charging

for planning my charges. Works perfectly as it allows me to set a max price I want to pay for charging. Have the flexibility to wait.

My battery (Powerwall) has four sensors, so I can access household load directly.

image

Ideally you have access to your household load, but otherwise you can calculate the same value, via a series of methods.

You also need to consider PV generation to battery.

The calculations, especially with a battery can become quite complex, especially when you account for all the powerflows in multiple directions.

I set a max price (effectively) by setting the charging hours to the number of hours that are below the max price, which I use for my 5 kW pool heat pump, it only runs when the prices is less than 5c/ kWh.

The real benefit with EMHASS is when you have multiple deferrable loads, in my case home battery, 2x EVs, hot water heatpump and pool filters & heatpump so I get the optimal plan for the household, not just one device.

1 Like

So stupid I didnā€™t think of that - my growatt battery also has a household load sensorā€¦ thanks!

1 Like

Question, why do you add 1 to the length? Should the prediction horizon not be equal to the number of elements in the array? In my case I have hourly prices which are published at 14:00 until 24:00 the next day, its now 10 am, so I have 14 prices left, if I add 1 it would assume a prediction horizon of 15 right?

Another question - my log reports ā€œinfeasibleā€ - looking at previous messages on this forum this suggests that something is wrong in the calculations? What does this mean exactly and where should I start to fix it?

For the record, the outcome looks pretty ok - It proposes to charge my battery on the two cheapest hours and discharge on the 2 most expensive hours.


2023-08-01 10:29:34,553 - web_server - INFO - Setting up needed data
2023-08-01 10:29:34,566 - web_server - INFO - Retrieve hass get data method initiated...
2023-08-01 10:29:37,308 - web_server - INFO - Retrieving weather forecast data using method = scrapper
2023-08-01 10:29:38,247 - web_server - INFO - Retrieving data from hass for load forecast using method = naive
2023-08-01 10:29:38,248 - web_server - INFO - Retrieve hass get data method initiated...
2023-08-01 10:29:47,348 - web_server - INFO -  >> Performing naive MPC optimization...
2023-08-01 10:29:47,348 - web_server - INFO - Performing naive MPC optimization
2023-08-01 10:29:47,363 - web_server - INFO - Perform an iteration of a naive MPC controller
2023-08-01 10:29:47,418 - web_server - INFO - Status: Infeasible
2023-08-01 10:29:47,418 - web_server - INFO - Total value of the Cost function = -0.34
2023-08-01 10:30:00,283 - web_server - INFO - Setting up needed data