EMHASS: An Energy Management for Home Assistant

I asked this a while ago, but I can’t choose ‘profit’ as an option in the config with v0.11.2, anyone has the same or did I miss it that this is a bug? It always jumps back to self-consumption as costfun, even after I saved the config.

Is there a remnant of the costfun from the config prior to upgrading?
Check the Emhass Add On config (not the web ui) per "Battery settings for the add-on incorrect" in HA Supervisor logs · Issue #103 · davidusb-geek/emhass-add-on · GitHub

What kind of card is it?

Is there an option to force the battery to always discharge/charge at full capacity? I do see often that the end soc wasn’t be reached, I think that’s related because the discharging/charging isn’t with the maximum wattage.

Let’s use an example: in the current output of EMHASS it’s charging 3400 watt per hour to get to the 100% SOC by tomorrow 6AM. I think tomorrow morning the SOC is around 95%. In the next hour it’s charging with only 2000 watt or 0 because of the price difference.

The capacity is properly configured, but can it be something else?

Could it be it is already charging as fast as it can, but especially at the end of the charging, the speed goes down because of the battery limitation? Perhaps a solution could be to let EMHASS believe the max speed is actually lower than in reality, but you ask the battery the maximum? Or an offset compared to requested by EMHASS (so e.g. max speed actual is 2000W, you tell EMHASS 1500W max, when EMHASS asks 1500, you multiply it by 1,333 and tell your battery 2000W.

Well in this case it looks like EMHASS don’t calculate the correct “charge time”, as you can see in the picture below the battery soc forecast from EMHASS is different than the actual SOC.

So after a few days of struggling with EMHASS (my second attempt) I can see result of day ahead optimization and it seems good, I believe. Pred_ entities are matching partly with my sensors and if I understand right so I have to run ML forecast models to learn and improve EMHASS. But when I run some of those ML models I get this: “• ERROR - web_server - The retrieved JSON is empty, A sensor:sensor.power_load_no_var_loads may have 0 days of history, passed sensor may not be correct, or days to retrieve is set too heigh”
I believe it is about database but I am a real begginer at this point. I have checked homeassistant_V2.db but it seems to be locked. I need help! Have I make a new database? Can I use this db or have I make an external db?




@markpurcell I’ve set up node_red API calls to download both 30 MS and 5 MS data and split the data into similar sensors as the amber integration. I can share those flows if anybody is interested.

I notice that the API data is 30 min behind the amber integration for some reason. Perhaps I’ve just got the formula wrong?


Would running MPC every 60 sec with the 30 MS forecasts prefixed with the 5 MS prices achieve the a reasonable outcome?

Will the Amber Integration be updated to include both 5MS and 30MS data?

I haven’t been able to get the publish_prefix working although I’m trying to use it to produce two MPC calculations for comparison reasons (Amber integration data vs API data processin).

{
  "prod_price_forecast": {{
    ([states('sensor.amber_feedin_price_current')|float(0)] +
    (state_attr('sensor.amber_feedin_price_forecast', 'forecast')|map(attribute='perKwh')|list))
    | tojson 
  }},
  "load_cost_forecast": {{
    ([states('sensor.amber_general_price_current')|float(0)] + 
    (state_attr('sensor.amber_general_price_forecast', 'forecast') |map(attribute='perKwh')|list)) 
    | tojson 
  }},
  "load_power_forecast": {{"[500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500]" 
  }},
  "prediction_horizon": {{
    min(48, (state_attr('sensor.amber_feedin_price_forecast', 'forecast')|map(attribute='per_kwh')|list|length)+1)
  }},
  "num_def_loads": 2,
  "def_total_hours": [4, 4],
  "P_deferrable_nom": [1300, 7300],
  "treat_def_as_semi_cont": [1, 0],
  "set_def_constant": [0, 0],
  "soc_init": {{ (states('sensor.sonnenbatterie_84324_state_charge_user')|int(0))/100 }},
  "soc_final": 0,
  "alpha": 1,
  "beta": 0,
  "publish_prefix": "ncp_"
}

This doesn’t result in a successfull publish however if I delete the last line it works ok?

Have you fix it?

Hey EMHASS community, I’m using the EMHASS Addon on Homeassistant to optimize my setup of PV(East + West), Battery, and currently just one deferrable load (more are planned). unfortunately, I’m not able to get the day ahead or MPC to provide a optimal result. It always shows infeasible even if the schedule looks promising.
I tried to change a lot of parameters for battery and deferrable loads, but the only way to get the status to optimal is when I disable the battery. also with default battery it become infeasible.
I need help.

here is my config. (my actual inverter is a 8kW Gen24, but its not available)

{
  "battery_charge_efficiency": 0.95,
  "battery_charge_power_max": 7680,
  "battery_discharge_efficiency": 0.95,
  "battery_discharge_power_max": 7680,
  "battery_dynamic_max": 0.8,
  "battery_dynamic_min": -0.8,
  "battery_maximum_state_of_charge": 1,
  "battery_minimum_state_of_charge": 0.15,
  "battery_nominal_energy_capacity": 7680,
  "battery_target_state_of_charge": 0.6,
  "compute_curtailment": false,
  "continual_publish": false,
  "costfun": "profit",
  "delta_forecast_daily": 1,
  "end_timesteps_of_each_deferrable_load": [
    0,
    0
  ],
  "historic_days_to_retrieve": 9,
  "inverter_is_hybrid": true,
  "load_cost_forecast_method": "hp_hc_periods",
  "load_forecast_method": "naive",
  "load_negative": false,
  "load_offpeak_hours_cost": 0.25,
  "load_peak_hour_periods": {
    "period_hp_1": [
      {
        "start": "00:00"
      },
      {
        "end": "02:59"
      }
    ],
    "period_hp_2": [
      {
        "start": "05:00"
      },
      {
        "end": "23:59"
      }
    ]
  },
  "load_peak_hours_cost": 0.35,
  "logging_level": "INFO",
  "lp_solver": "COIN_CMD",
  "lp_solver_path": "/usr/bin/cbc",
  "maximum_power_from_grid": 9000,
  "maximum_power_to_grid": 9000,
  "method_ts_round": "nearest",
  "modules_per_string": [
    14,
    11
  ],
  "nominal_power_of_deferrable_loads": [
    1600
  ],
  "number_of_deferrable_loads": 1,
  "operating_hours_of_each_deferrable_load": [
    1
  ],
  "optimization_time_step": 60,
  "photovoltaic_production_sell_price": 0.082,
  "production_price_forecast_method": "constant",
  "pv_inverter_model": [
    "Fronius_International_GmbH__Primo_GEN24_6_0_208_240_Plus__240V_"
  ],
  "pv_module_model": [
    "AXITEC_AC_400MH_144S"
  ],
  "sensor_linear_interp": [
    "sensor.haus_ohne_gesteuerte_lasten_power"
  ],
  "sensor_power_load_no_var_loads": "sensor.haus_ohne_gesteuerte_lasten_power",
  "sensor_power_photovoltaics": "sensor.pv_leistung",
  "sensor_replace_zero": [
    "sensor.pv_leistung"
  ],
  "set_battery_dynamic": true,
  "set_deferrable_load_single_constant": [
    true,
    true
  ],
  "set_deferrable_startup_penalty": [
    0,
    0
  ],
  "set_nocharge_from_grid": false,
  "set_nodischarge_to_grid": true,
  "set_total_pv_sell": false,
  "set_use_battery": true,
  "set_zero_min": true,
  "start_timesteps_of_each_deferrable_load": [
    0,
    0
  ],
  "strings_per_inverter": [
    2
  ],
  "surface_azimuth": [
    90,
    270
  ],
  "surface_tilt": [
    45,
    45
  ],
  "treat_deferrable_load_as_semi_cont": [
    true,
    true
  ],
  "weather_forecast_method": "scrapper",
  "weight_battery_charge": 0.05,
  "weight_battery_discharge": 0.05
}

on runtime I pass

"curl -i -H \"Content-Type:application/json\" -X POST -d '
    {
    \"entity_save\": true, 
    \"publish_prefix\":\"emhass_dah_\",
    \"load_cost_forecast\":{{((state_attr('sensor.electricity_price', 'future') |map(attribute='total')|list)[:24]) }}
    }' http://localhost:5000/action/dayahead-optim"

I think your call lacks parameters; I reckon the current SoC needs to be provided.
And maybe more, here’s what I have:

  - service: shell_command.emhass_dayahead_optim
    data:
      payload: >
        {"entity_save": true, "publish_prefix": "dh_", "battery_maximum_state_of_charge": {{ soc_max }}, "battery_minimum_state_of_charge": {{ soc_min }}, "battery_target_state_of_charge": {{ soc_init }}, "battery_discharge_power_max": {{ pd_max }}, "battery_charge_power_max": {{ pc_max }}, "weather_forecast_cache": true, "pv_power_forecast": {{ pv_p_fc }}, "load_cost_forecast": {{ load_cost_forecast }} }

thank your for your Idea. for whatever reason I got it meanwhile without changing the runtime parameters. I’m quite curious whether this will remain a running solution. I was also able to add a second deferrable load without crashing the optimizer.

I identified some additional list items for deferrable load parameters. 2 items listed for whatever reason even if I had selected number of deferrable loads 2. maybe a bug with the config page?

I set up a real second deferrable load and set the “set_nodischarge_to_grid”: false,
If it remain working I will try to set it back to true again. lets see

update: it seems really linked to the option “set_nodischarge_to_grid”. when I switch it back to true my optimizer fail - I will open an bug issue

{
  "battery_charge_efficiency": 0.95,
  "battery_charge_power_max": 7680,
  "battery_discharge_efficiency": 0.95,
  "battery_discharge_power_max": 7680,
  "battery_dynamic_max": 0.8,
  "battery_dynamic_min": -0.8,
  "battery_maximum_state_of_charge": 1,
  "battery_minimum_state_of_charge": 0.15,
  "battery_nominal_energy_capacity": 7680,
  "battery_target_state_of_charge": 0.6,
  "compute_curtailment": false,
  "continual_publish": false,
  "costfun": "profit",
  "delta_forecast_daily": 1,
  "end_timesteps_of_each_deferrable_load": [
    0,
    0
  ],
  "historic_days_to_retrieve": 9,
  "inverter_is_hybrid": true,
  "load_cost_forecast_method": "hp_hc_periods",
  "load_forecast_method": "naive",
  "load_negative": false,
  "load_offpeak_hours_cost": 0.25,
  "load_peak_hour_periods": {
    "period_hp_1": [
      {
        "start": "00:00"
      },
      {
        "end": "02:59"
      }
    ],
    "period_hp_2": [
      {
        "start": "05:00"
      },
      {
        "end": "23:59"
      }
    ]
  },
  "load_peak_hours_cost": 0.35,
  "logging_level": "INFO",
  "lp_solver": "COIN_CMD",
  "lp_solver_path": "/usr/bin/cbc",
  "maximum_power_from_grid": 12000,
  "maximum_power_to_grid": 12000,
  "method_ts_round": "nearest",
  "modules_per_string": [
    14,
    11
  ],
  "nominal_power_of_deferrable_loads": [
    1600,
    300
  ],
  "number_of_deferrable_loads": 2,
  "operating_hours_of_each_deferrable_load": [
    1,
    2
  ],
  "optimization_time_step": 60,
  "photovoltaic_production_sell_price": 0.082,
  "production_price_forecast_method": "constant",
  "pv_inverter_model": [
    "Fronius_International_GmbH__Primo_GEN24_6_0_208_240_Plus__240V_"
  ],
  "pv_module_model": [
    "AXITEC_AC_400MH_144S"
  ],
  "sensor_linear_interp": [
    "sensor.haus_ohne_gesteuerte_lasten_power"
  ],
  "sensor_power_load_no_var_loads": "sensor.haus_ohne_gesteuerte_lasten_power",
  "sensor_power_photovoltaics": "sensor.pv_leistung",
  "sensor_replace_zero": [
    "sensor.pv_leistung"
  ],
  "set_battery_dynamic": true,
  "set_deferrable_load_single_constant": [
    true,
    true
  ],
  "set_deferrable_startup_penalty": [
    0,
    0
  ],
  "set_nocharge_from_grid": false,
  "set_nodischarge_to_grid": false,
  "set_total_pv_sell": false,
  "set_use_battery": true,
  "set_zero_min": true,
  "start_timesteps_of_each_deferrable_load": [
    0,
    0
  ],
  "strings_per_inverter": [
    2
  ],
  "surface_azimuth": [
    90,
    270
  ],
  "surface_tilt": [
    45,
    45
  ],
  "treat_deferrable_load_as_semi_cont": [
    true,
    true
  ],
  "weather_forecast_method": "scrapper",
  "weight_battery_charge": 0.05,
  "weight_battery_discharge": 0.05
}

image

Just upgraded to 0.11.3 and had to restore my 0.11.2 backup. I could be doing something wrong, but from the logs it looks like the prediction_horizon runtime param wasn’t understood.

Raised an issue in github.

Looking into this one now :+1:
Also we are aware of a log duplication bug and a optimization_time_step runtime parameter bug. for 0.11.3
These will be fixed soon from PR: treat_runtimeparams fix optimization_time_step timedelta by GeoDerp · Pull Request #396 · davidusb-geek/emhass · GitHub

2 Likes

Merry Christmas Eve / Merry Christmas Everyone!
I hope that your Christmas is full of low load cost price, and high PV. :+1::pray:

6 Likes

Thank you John, for you too, Merry Christmas!

4 Likes

Just updated the Add-On to 0.11.4.
Everything seems to be working fine now! Only one “FutureWarning” left in the logs:

@davidusb, @GeoDerp and all others: many thanks for developing this very nice project.
I’m using it fore about a year now and really like it. Still working on the thermal model though…

Everyone Merry Xmas and a fine Newyear!!

4 Likes

Hi @erikh , I am using your solution for deferrable loads, however I want to use one deferrable load between 18.00 - 7.00, so start time is 18.00 end end time 7.00. I am using MPC on a rolling window, so there will be a situation when price data aren’t available and the optimisation ends as infeasible. I am struggling how to solve this, maybe you have an idea? Thanks you

2024-12-26 07:40:00,968 - web_server - INFO - Passed runtime parameters: {'prediction_horizon': 33, 'pv_power_forecast': [0, 0, 0, 0, 211, 259, 315, 369, 417, 454, 485, 521, 570, 643, 736, 804, 797, 667, 435, 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, 265, 440, 625, 793, 924, 1020, 1095, 1137, 1151, 1122, 1050, 930, 775, 581, 371, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 'num_def_loads': 2, 'P_deferrable_nom': [2500, 0], 'def_total_hours': [7, 0], 'treat_def_as_semi_cont': [1, 1], 'set_def_constant': [1, 1], 'def_start_timestep': [20, 0], 'def_end_timestep': [48, 48], 'soc_init': 0.97, 'soc_final': 0.9, 'load_cost_forecast': [0.2563, 0.2634, 0.2634, 0.2623, 0.2623, 0.257, 0.257, 0.2493, 0.2493, 0.2511, 0.2511, 0.2471, 0.2471, 0.2532, 0.2532, 0.2649, 0.2649, 0.2727, 0.2727, 0.2831, 0.2831, 0.2833, 0.2833, 0.2808, 0.2808, 0.2738, 0.2738, 0.2651, 0.2651, 0.2679, 0.2679, 0.2609, 0.2609], 'prod_price_forecast': [0.1036, 0.1102, 0.1102, 0.1092, 0.1092, 0.1042, 0.1042, 0.097, 0.097, 0.0987, 0.0987, 0.0948, 0.0948, 0.1006, 0.1006, 0.1117, 0.1117, 0.119, 0.119, 0.1288, 0.1288, 0.129, 0.129, 0.1267, 0.1267, 0.1201, 0.1201, 0.1118, 0.1118, 0.1144, 0.1144, 0.1079, 0.1079], 'alpha': 1, 'beta': 0, 'load_power_forecast': [2388, 2700, 2600, 2000, 2000, 1600, 2000, 1600, 1500, 1500, 1300, 1200, 1200, 1200, 200, 300, 200, 200, 700, 1600, 1200, 900, 1400, 1900, 1700, 1800, 1700, 1600, 1400, 400, 500, 400, 400, 400, 2600, 400, 2400, 400, 500, 500, 400, 400, 400, 800, 600, 700, 2400, 200]}
2024-12-26 07:40:00,969 - web_server - INFO -  >> Setting input data dict
2024-12-26 07:40:00,969 - web_server - INFO - Setting up needed data
2024-12-26 07:40:00,975 - web_server - INFO - Retrieve hass get data method initiated...
2024-12-26 07:40:01,235 - web_server - INFO - Retrieving weather forecast data using method = list
2024-12-26 07:40:01,237 - web_server - INFO -  >> Performing naive MPC optimization...
2024-12-26 07:40:01,237 - web_server - INFO - Performing naive MPC optimization
2024-12-26 07:40:01,240 - web_server - INFO - Perform an iteration of a naive MPC controller
2024-12-26 07:40:01,291 - web_server - WARNING - Deferrable load 0 : Available timeframe is shorter than the specified number of hours to operate. Optimization will fail.
2024-12-26 07:40:01,322 - web_server - INFO - Status: Infeasible
2024-12-26 07:40:01,322 - web_server - INFO - Total value of the Cost function = -10.40
2024-12-26 07:40:01,435 - web_server - INFO -  >> Obtaining params: 
2024-12-26 07:40:01,435 - web_server - INFO - Passed runtime parameters: {'publish_prefix': ''}
2024-12-26 07:40:01,436 - web_server - INFO -  >> Setting input data dict
2024-12-26 07:40:01,436 - web_server - INFO - Setting up needed data
2024-12-26 07:40:01,437 - web_server - INFO -  >> Publishing data...
2024-12-26 07:40:01,437 - web_server - INFO - Publishing data to HASS instance
2024-12-26 07:40:01,443 - web_server - INFO - Successfully posted to sensor.p_pv_forecast = 0
2024-12-26 07:40:01,447 - web_server - INFO - Successfully posted to sensor.p_load_forecast = 2388
2024-12-26 07:40:01,450 - web_server - INFO - Successfully posted to sensor.p_hybrid_inverter = -111.0
2024-12-26 07:40:01,453 - web_server - INFO - Successfully posted to sensor.p_deferrable0 = 1.0
2024-12-26 07:40:01,457 - web_server - INFO - Successfully posted to sensor.p_deferrable1 = 0.0
2024-12-26 07:40:01,461 - web_server - INFO - Successfully posted to sensor.p_batt_forecast = -111.0
2024-12-26 07:40:01,464 - web_server - INFO - Successfully posted to sensor.soc_batt_forecast = 97.37
2024-12-26 07:40:01,468 - web_server - INFO - Successfully posted to sensor.p_grid_forecast = 2500.0
2024-12-26 07:40:01,470 - web_server - INFO - Successfully posted to sensor.total_cost_fun_value = -9.42
2024-12-26 07:40:01,473 - web_server - INFO - Successfully posted to sensor.optim_status = Infeasible
2024-12-26 07:40:01,475 - web_server - INFO - Successfully posted to sensor.unit_load_cost = 0.2563
2024-12-26 07:40:01,478 - web_server - INFO - Successfully posted to sensor.unit_prod_price = 0.1036
2024-12-26 07:40:15,919 - web_server - INFO - EMHASS server online, serving index.html...

I’m not using def loads but I also have a moment when the price data is not available for the next day (I’m using rolling MPC as well). What I do is to keep using the latest available (as I think it’s the best possible approximation) till the newer is available. You could think of similar approaches (average or so on) if this works for you or there aren’t better suggestions (to which I would be open as well :slight_smile: )

I was thinking about both next day prices as well as PV forecast for the next day in a similiar situation. Could be a solution to run separately load, PV and price optimization when available and put it together in dayahead-optim? Something like this:

load_power_forecast: >
  curl -i -H "Content-Type: application/json" -X POST -d '{"load_power_forecast":{{[states('sensor.power_load_no_var_loads')|int] +(states('input_text.fi_fo_buffer').split(',')|map('int')|list)[1:48]}}' http://localhost:5000/action/dayahead-optim

trigger_nordpool_forecast: >
  curl -i -H "Content-Type: application/json" -X POST -d '{
    "load_cost_forecast": {{ ((state_attr("sensor.nordpool_cost", "raw_today") | map(attribute="value") | list) + (state_attr("sensor.nordpool_cost", "raw_tomorrow") | map(attribute="value") | list))[now().hour:][:24] | tojson }},
    "prod_price_forecast": {{ ((state_attr("sensor.nordpool_sell", "raw_today") | map(attribute="value") | list) + (state_attr("sensor.nordpool_sell", "raw_tomorrow") | map(attribute="value") | list))[now().hour:][:24] | tojson }},
  }' http://localhost:5000/action/dayahead-optim

solcast_optim: >
  curl -i -H \"Content-Type:application/json\" -X POST -d '{\"pv_power_forecast\":{{states('sensor.solcast_pv_forecast_forecast_next_x_hours')}}}' http://localhost:5000/action/dayahead-optim