EMHASS: An Energy Management for Home Assistant

Found my way to the config.json-file so now I at least have a way forward (even if it was not the preferred one) and hopefully I’ll learn enough to set up what I want :slight_smile:

Thank you for your kind help, it was much appreciated!

Thanx again for all your effort!
After removing the “” around http://localhost aso. HA accepted the config. But still same log.file error "FileNotFoundError: Errno2 No such file or directory: ‘/data/long_train_data.pkl’

With help from duck.ai figuered out there was a mismatch between the dictionary length; Nordpool 24 and application expecting 72.
Found in the GUI that the input “number of forecasted days” what set to 3. Changed this to 1.
Tried again. Still no go. Checking in developer tools, give me the same output:

content: >
  <!doctype html>

  <html lang=en>

  <title>500 Internal Server Error</title>

  <h1>Internal Server Error</h1>

  <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>
status: 500
headers:
  Server: gunicorn
  Date: Mon, 08 Sep 2025 21:23:01 GMT
  Connection: keep-alive
  Content-Type: text/html; charset=utf-8
  Content-Length: "265"

The logfile still:

FileNotFoundError: [Errno 2] No such file or directory: '/data/long_train_data.pkl'

Duc AI says:

1. Check for Missing File

  • Verify if the file /data/long_train_data.pkl exists. If not, you may need to run a training or optimization task that generates this file.

2. Set LP Solver Path

  • If you are using a specific LP solver like COIN_CMD, ensure that the path to the solver is correctly set in your configuration. You can do this by modifying the relevant configuration file or settings in Home Assistant.

I am clueless.

I can’t see the data your rest command is posting. I think the prediction horizon you are using is wrong (just guessing without looking closely). Prediction horizon needs to match the data length of norepools forecasts or solcast forecast, which ever is the shortest. So if you have 24 tariff values from Nordpool and thats the shortest list then your prediction horizon needs to be 24.

If your data values vary for some reason your prediction horizon needs to vary.

In my case Amber (my version of Nordpool) publishes a 24-hour Forecast starting at 12:30 each day with 48 by 30 minute forecasts until 03:30 after which the forecasts stop. So, between 03:30 and 12:30 you have a decreasing number from 48 forecasts. At 12:00 you have the smallest number of forecasts 12:00-03:30 which is 31 by 30 minute forecasts. This applies to the data produced by the amber2MQTT integration. This decreasing horizon is passed to EMHASS in the API call by testing the number of elements in one of the sensors and pass that to EMHASS in the API post as the “prediction_horizon”. To manage this changing prediction horizon I have to use this:

 {#-- Calculate prediction horizon as the shortest data length --#}
  "prediction_horizon": {{
    [prod_price_forecast | length,
     load_cost_forecast | length,
     pv_power_forecast | length,
     load_power_forecast | length] | min -1
  }},

So that my prediction horizon is always the smalest number of predictions I have for all the data dictionaries.

At the moment its only 38 long but that will drop to 31 and then jump to 48 again. I need to vary it because I’m using the MPC method and posting this to EMHASS every 30 seconds.

example:

"prod_price_forecast": [0.1541, 0.0875, 0.0568, 0.0207, 0.0108, 0.0088, 0.0073, 0.006, 0.0067, 0.0092, 0.0142, 0.0205, 0.032, 0.0555, 0.0708, 0.1408, 0.1929, 0.2986, 0.431, 0.4284, 0.3796, 0.3404, 0.3349, 0.3219, 0.3081, 0.211, 0.2022, 0.197, 0.1883, 0.1756, 0.1645, 0.1585, 0.1479, 0.1362, 0.1256, 0.121, 0.118, 0.1132, 0.1128],

"load_cost_forecast": [0.2324, 0.1592, 0.1254, 0.0992, 0.0883, 0.0862, 0.0845, 0.083, 0.0838, 0.0866, 0.0921, 0.099, 0.1116, 0.124, 0.1408, 0.1753, 0.2327, 0.349, 0.4946, 0.4917, 0.4381, 0.395, 0.3889, 0.3746, 0.3595, 0.2951, 0.2853, 0.2797, 0.27, 0.2561, 0.2439, 0.2373, 0.2256, 0.2127, 0.201, 0.196, 0.1927, 0.1874, 0.187],

"pv_power_forecast": [441, 764, 944, 976, 1444, 1904, 2328, 2446, 2419, 2281, 2066, 1841, 1614, 1300, 902, 532, 197, 49, 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, 5, 44, 142, 319, 468, 553, 587, 631, 656, 651, 656, 671, 681, 685, 700, 720, 720, 720, 725, 627, 409, 131, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],

"load_power_forecast": [367, 618, 516, 509, 707, 603, 776, 706, 768, 548, 493, 481, 606, 542, 731, 530, 494, 527, 582, 636, 1034, 756, 602, 556, 608, 551, 484, 539, 518, 338, 326, 391, 308, 329, 323, 287, 335, 294, 318, 306, 313, 313, 320, 356, 286, 450, 445, 419, 391],

"prediction_horizon": 38,

Note that the pv_power_forecast is much longer than 38 but that doesn’t matter.

You don’t need to vary it as you are using dayahead which you only post once a day (usually). But you do need a prediction horizon that matches the data length you are posting.

Also, I think you need to set your time steps correctly in EMHASS config.

Optimization steps per minute (timesteps):
optimization_time_step

Is this 15 minutes for you? This would mean you need 96 elements for 24 hours?

But also your PV forecast data would need to be divided up into 15 min values.

I don’t know. What do other Nordpool users do here?

Is Amber users have two prediction horizons, 30 and 5 minutes time steps with the 30 min data varying from 31 to 48 and the 5 min varying from 12 and 6 I think.

But we stick to the 30 min time step and simply prefix the data with the current 5 min forecast so the system can react to what is happening right now. This is what the alpha and beta values are for if you look at the samples I posted above. These setting tell the system to take notice of the now value. That’s probably too much information but there you go.

@jorbor I had a similar experience with settings not being saved after I had changed the folder path where EMHASS data will be stored (see davidusb sccreenshot above). I managed to get it working by changing back to default and then totally remove and reinstall EMHASS

In the GUI there is no parameter for “prediction horizion” as far as i can tell, but I have added the “prediction_horizon”: 24 in the rest_command to send to API together with the nordpool array.

I currently get 24 nordpool data points, so the timestep is set to 60min in GUI.

I still get the same logs.

Just listening to the rest_command respons in the dev.tools give the respons as above

Trying to run the dayahead optimization manually with no success. LOG as follows.

[2025-09-10 21:20:00 +0200] [25] [INFO]  >> Obtaining params: 
[2025-09-10 21:20:00 +0200] [25] [INFO] Passed runtime parameters: {}
[2025-09-10 21:20:00 +0200] [25] [INFO]  >> Setting input data dict
[2025-09-10 21:20:00 +0200] [25] [INFO] Setting up needed data
[2025-09-10 21:20:00 +0200] [25] [DEBUG] setting`passed_data:days_to_retrieve` to 9 for fit/predict/tune
[2025-09-10 21:20:00 +0200] [25] [ERROR] Use COIN_CMD solver name if you want to set a path for the LP solver
[2025-09-10 21:20:00 +0200] [25] [DEBUG] Initialized Optimization with retrieve_hass_conf: {'optimization_time_step': Timedelta('0 days 01:00:00'), 'historic_days_to_retrieve': 2, 'sensor_power_photovoltaics': 'sensor.solar_panel_production_w', 'sensor_power_photovoltaics_forecast': 'sensor.solcast_pv_forecast_power_now', 'sensor_power_load_no_var_loads': 'sensor.solar_house_consumption_w', 'load_negative': False, 'set_zero_min': True, 'sensor_replace_zero': ['sensor.solar_panel_production_w', 'sensor.solar_house_consumption_w'], 'sensor_linear_interp': ['', ''], 'method_ts_round': 'nearest', 'continual_publish': True, 'hass_url': 'http://supervisor/core/api', 'long_lived_token': '01a136094d2a2cfbdca8fd3e12af03b94cd047295fdec7c7f5722280076fa6f12026fccbf0c3245aeade399076d4adf89f79b5aa9256e8f9', 'time_zone': <DstTzInfo 'Europe/Stockholm' LMT+0:53:00 STD>, 'Latitude': 57.85885, 'Longitude': 14.305337, 'Altitude': 16}
[2025-09-10 21:20:00 +0200] [25] [DEBUG] Optimization configuration: {'costfun': 'profit', 'logging_level': 'DEBUG', 'set_use_pv': True, 'set_use_adjusted_pv': False, 'adjusted_pv_regression_model': 'LassoRegression', 'adjusted_pv_solar_elevation_threshold': 10, 'set_use_battery': True, 'number_of_deferrable_loads': 2, 'nominal_power_of_deferrable_loads': [3000, 750], 'minimum_power_of_deferrable_loads': [0, 0], 'operating_hours_of_each_deferrable_load': [0, 0], 'treat_deferrable_load_as_semi_cont': [True, True], 'set_deferrable_load_single_constant': [False, False], 'set_deferrable_startup_penalty': [0, 0], 'delta_forecast_daily': Timedelta('1 days 00:00:00'), 'load_forecast_method': 'typical', 'load_cost_forecast_method': 'csv', 'load_peak_hours_cost': 0.1907, 'load_offpeak_hours_cost': 0.1419, 'production_price_forecast_method': 'csv', 'photovoltaic_production_sell_price': 0.1419, 'set_total_pv_sell': False, 'lp_solver': 'GLPK_CMD', 'lp_solver_path': '', 'lp_solver_timeout': 45, 'num_threads': 0, 'set_nocharge_from_grid': False, 'set_nodischarge_to_grid': False, 'set_battery_dynamic': False, 'battery_dynamic_max': 0.9, 'battery_dynamic_min': -0.9, 'weight_battery_discharge': 0, 'weight_battery_charge': 0, 'weather_forecast_method': 'open-meteo', 'open_meteo_cache_max_age': 60, 'start_timesteps_of_each_deferrable_load': [0, 0], 'end_timesteps_of_each_deferrable_load': [0, 0], 'load_peak_hour_periods': {'period_hp_1': [{'start': '02:54'}, {'end': '15:24'}]}}
[2025-09-10 21:20:00 +0200] [25] [DEBUG] Plant configuration: {'maximum_power_from_grid': 9000, 'maximum_power_to_grid': 3000, 'pv_module_model': ['Trina_Solar_TSM_490DE18M_II_'], 'pv_inverter_model': ['SolarEdge_Technologies_Ltd___SE10KUS__480V_'], 'surface_tilt': [30], 'surface_azimuth': [205], 'modules_per_string': [8], 'strings_per_inverter': [2], 'inverter_is_hybrid': True, 'inverter_ac_output_max': 1000, 'inverter_ac_input_max': 1000, 'inverter_efficiency_dc_ac': 1, 'inverter_efficiency_ac_dc': 1, 'compute_curtailment': False, 'battery_discharge_power_max': 2000, 'battery_charge_power_max': 2000, 'battery_discharge_efficiency': 0.95, 'battery_charge_efficiency': 0.95, 'battery_nominal_energy_capacity': 5000, 'battery_minimum_state_of_charge': 0.3, 'battery_maximum_state_of_charge': 0.9, 'battery_target_state_of_charge': 0.6}
[2025-09-10 21:20:00 +0200] [25] [DEBUG] Solver configuration: lp_solver=GLPK_CMD, lp_solver_path=
[2025-09-10 21:20:00 +0200] [25] [DEBUG] Number of threads: 4
[2025-09-10 21:20:00 +0200] [25] [INFO]  >> Publishing data...
[2025-09-10 21:20:00 +0200] [25] [INFO] Publishing data to HASS instance
[2025-09-10 21:20:00 +0200] [25] [ERROR] File not found error, run an optimization task first.
[2025-09-10 21:20:30 +0200] [25] [INFO] EMHASS server online, serving index.html...
[2025-09-10 21:20:30 +0200] [25] [INFO] The data container dictionary is empty... Please launch an optimization task
[2025-09-10 21:20:34 +0200] [25] [INFO]  >> Obtaining params: 
[2025-09-10 21:20:34 +0200] [25] [INFO] Passed runtime parameters: {}
[2025-09-10 21:20:34 +0200] [25] [INFO]  >> Setting input data dict
[2025-09-10 21:20:34 +0200] [25] [INFO] Setting up needed data
[2025-09-10 21:20:34 +0200] [25] [DEBUG] setting`passed_data:days_to_retrieve` to 9 for fit/predict/tune
[2025-09-10 21:20:34 +0200] [25] [ERROR] Use COIN_CMD solver name if you want to set a path for the LP solver
[2025-09-10 21:20:34 +0200] [25] [DEBUG] Initialized Optimization with retrieve_hass_conf: {'optimization_time_step': Timedelta('0 days 01:00:00'), 'historic_days_to_retrieve': 2, 'sensor_power_photovoltaics': 'sensor.solar_panel_production_w', 'sensor_power_photovoltaics_forecast': 'sensor.solcast_pv_forecast_power_now', 'sensor_power_load_no_var_loads': 'sensor.solar_house_consumption_w', 'load_negative': False, 'set_zero_min': True, 'sensor_replace_zero': ['sensor.solar_panel_production_w', 'sensor.solar_house_consumption_w'], 'sensor_linear_interp': ['', ''], 'method_ts_round': 'nearest', 'continual_publish': True, 'hass_url': 'http://supervisor/core/api', 'long_lived_token': '01a136094d2a2cfbdca8fd3e12af03b94cd047295fdec7c7f5722280076fa6f12026fccbf0c3245aeade399076d4adf89f79b5aa9256e8f9', 'time_zone': <DstTzInfo 'Europe/Stockholm' LMT+0:53:00 STD>, 'Latitude': 57.85885, 'Longitude': 14.305337, 'Altitude': 16}
[2025-09-10 21:20:34 +0200] [25] [DEBUG] Optimization configuration: {'costfun': 'profit', 'logging_level': 'DEBUG', 'set_use_pv': True, 'set_use_adjusted_pv': False, 'adjusted_pv_regression_model': 'LassoRegression', 'adjusted_pv_solar_elevation_threshold': 10, 'set_use_battery': True, 'number_of_deferrable_loads': 2, 'nominal_power_of_deferrable_loads': [3000, 750], 'minimum_power_of_deferrable_loads': [0, 0], 'operating_hours_of_each_deferrable_load': [0, 0], 'treat_deferrable_load_as_semi_cont': [True, True], 'set_deferrable_load_single_constant': [False, False], 'set_deferrable_startup_penalty': [0, 0], 'delta_forecast_daily': Timedelta('1 days 00:00:00'), 'load_forecast_method': 'typical', 'load_cost_forecast_method': 'csv', 'load_peak_hours_cost': 0.1907, 'load_offpeak_hours_cost': 0.1419, 'production_price_forecast_method': 'csv', 'photovoltaic_production_sell_price': 0.1419, 'set_total_pv_sell': False, 'lp_solver': 'GLPK_CMD', 'lp_solver_path': '', 'lp_solver_timeout': 45, 'num_threads': 0, 'set_nocharge_from_grid': False, 'set_nodischarge_to_grid': False, 'set_battery_dynamic': False, 'battery_dynamic_max': 0.9, 'battery_dynamic_min': -0.9, 'weight_battery_discharge': 0, 'weight_battery_charge': 0, 'weather_forecast_method': 'open-meteo', 'open_meteo_cache_max_age': 60, 'start_timesteps_of_each_deferrable_load': [0, 0], 'end_timesteps_of_each_deferrable_load': [0, 0], 'load_peak_hour_periods': {'period_hp_1': [{'start': '02:54'}, {'end': '15:24'}]}}
[2025-09-10 21:20:34 +0200] [25] [DEBUG] Plant configuration: {'maximum_power_from_grid': 9000, 'maximum_power_to_grid': 3000, 'pv_module_model': ['Trina_Solar_TSM_490DE18M_II_'], 'pv_inverter_model': ['SolarEdge_Technologies_Ltd___SE10KUS__480V_'], 'surface_tilt': [30], 'surface_azimuth': [205], 'modules_per_string': [8], 'strings_per_inverter': [2], 'inverter_is_hybrid': True, 'inverter_ac_output_max': 1000, 'inverter_ac_input_max': 1000, 'inverter_efficiency_dc_ac': 1, 'inverter_efficiency_ac_dc': 1, 'compute_curtailment': False, 'battery_discharge_power_max': 2000, 'battery_charge_power_max': 2000, 'battery_discharge_efficiency': 0.95, 'battery_charge_efficiency': 0.95, 'battery_nominal_energy_capacity': 5000, 'battery_minimum_state_of_charge': 0.3, 'battery_maximum_state_of_charge': 0.9, 'battery_target_state_of_charge': 0.6}
[2025-09-10 21:20:34 +0200] [25] [DEBUG] Solver configuration: lp_solver=GLPK_CMD, lp_solver_path=
[2025-09-10 21:20:34 +0200] [25] [DEBUG] Number of threads: 4
[2025-09-10 21:20:34 +0200] [25] [INFO] Retrieving weather forecast data using method = open-meteo
[2025-09-10 21:20:34 +0200] [25] [WARNING] Open-Meteo forecast_days is too low (1) so defaulting to 3 days
[2025-09-10 21:20:34 +0200] [25] [INFO] Loading existing cached Open-Meteo JSON file: /data/cached-open-meteo-forecast.json
[2025-09-10 21:20:34 +0200] [25] [INFO] The cached Open-Meteo JSON file is recent (age=16m, max_age=60m)
[2025-09-10 21:20:34 +0200] [25] [DEBUG] get_weather_forecast returning:
                           temp_air  relative_humidity  ...   dhi  dni
2025-09-10 21:00:00+02:00      17.2                 76  ...   0.0  0.0
2025-09-10 22:00:00+02:00      16.9                 80  ...   0.0  0.0
2025-09-10 23:00:00+02:00      16.6                 82  ...   0.0  0.0
2025-09-11 00:00:00+02:00      16.8                 81  ...   0.0  0.0
2025-09-11 01:00:00+02:00      16.5                 84  ...   0.0  0.0
2025-09-11 02:00:00+02:00      16.4                 87  ...   0.0  0.0
2025-09-11 03:00:00+02:00      16.5                 89  ...   0.0  0.0
2025-09-11 04:00:00+02:00      16.8                 89  ...   0.0  0.0
2025-09-11 05:00:00+02:00      16.9                 88  ...   0.0  0.0
2025-09-11 06:00:00+02:00      16.9                 89  ...   0.0  0.0
2025-09-11 07:00:00+02:00      16.9                 89  ...   8.1  0.0
2025-09-11 08:00:00+02:00      17.1                 86  ...  27.1  0.6
2025-09-11 09:00:00+02:00      17.4                 85  ...  28.8  1.6
2025-09-11 10:00:00+02:00      17.4                 85  ...  26.2  1.2
2025-09-11 11:00:00+02:00      17.2                 87  ...  32.0  1.1
2025-09-11 12:00:00+02:00      16.4                 91  ...  22.9  0.5
2025-09-11 13:00:00+02:00      16.4                 98  ...  18.8  0.4
2025-09-11 14:00:00+02:00      16.2                 95  ...  10.8  0.3
2025-09-11 15:00:00+02:00      16.0                 97  ...  12.6  0.4
2025-09-11 16:00:00+02:00      15.9                 99  ...  18.2  0.8
2025-09-11 17:00:00+02:00      16.0                 99  ...  23.5  1.2
2025-09-11 18:00:00+02:00      15.9                 97  ...  27.3  1.7
2025-09-11 19:00:00+02:00      15.6                 92  ...  14.7  1.6
2025-09-11 20:00:00+02:00      14.7                 94  ...   0.0  0.0
[24 rows x 8 columns]
[2025-09-10 21:20:38 +0200] [25] [DEBUG] get_power_from_weather returning:
2025-09-10 21:00:00+02:00      0.000000
2025-09-10 22:00:00+02:00      0.000000
2025-09-10 23:00:00+02:00      0.000000
2025-09-11 00:00:00+02:00      0.000000
2025-09-11 01:00:00+02:00      0.000000
2025-09-11 02:00:00+02:00      0.000000
2025-09-11 03:00:00+02:00      0.000000
2025-09-11 04:00:00+02:00      0.000000
2025-09-11 05:00:00+02:00      0.000000
2025-09-11 06:00:00+02:00      0.000000
2025-09-11 07:00:00+02:00     14.784599
2025-09-11 08:00:00+02:00    149.179614
2025-09-11 09:00:00+02:00    163.926671
2025-09-11 10:00:00+02:00    146.624860
2025-09-11 11:00:00+02:00    189.973660
2025-09-11 12:00:00+02:00    122.270088
2025-09-11 13:00:00+02:00     92.478494
2025-09-11 14:00:00+02:00     35.605045
2025-09-11 15:00:00+02:00     48.841495
2025-09-11 16:00:00+02:00     90.554820
2025-09-11 17:00:00+02:00    129.588792
2025-09-11 18:00:00+02:00    157.116972
2025-09-11 19:00:00+02:00     63.854223
2025-09-11 20:00:00+02:00      0.000000
Freq: h, dtype: float64
[2025-09-10 21:20:38 +0200] [25] [ERROR] Exception on /action/dayahead-optim [POST]
Traceback (most recent call last):
  File "/app/.venv/lib/python3.12/site-packages/flask/app.py", line 1511, in wsgi_app
    response = self.full_dispatch_request()
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/.venv/lib/python3.12/site-packages/flask/app.py", line 919, in full_dispatch_request
    rv = self.handle_user_exception(e)
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/.venv/lib/python3.12/site-packages/flask/app.py", line 917, in full_dispatch_request
    rv = self.dispatch_request()
         ^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/.venv/lib/python3.12/site-packages/flask/app.py", line 902, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)  # type: ignore[no-any-return]
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/src/emhass/web_server.py", line 393, in action_call
    input_data_dict = set_input_data_dict(
                      ^^^^^^^^^^^^^^^^^^^^
  File "/app/src/emhass/command_line.py", line 306, in set_input_data_dict
    P_load_forecast = fcst.get_load_forecast(
                      ^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/src/emhass/forecast.py", line 1401, in get_load_forecast
    with open(data_path, "rb") as fid:
         ^^^^^^^^^^^^^^^^^^^^^
FileNotFoundError: [Errno 2] No such file or directory: '/data/long_train_data.pkl'

Without any understanding of this i wonder why the rest_command give the error status 500? Is this not the reason for not being able to run any optimization tasks? Code for rest_command now like this:

rest_command:
  trigger_nordpool_forecast:
    url: http://192.168.10.3:5000/action/dayahead-optim
    method: POST
    headers:
      Content-Type: "application/json"
    payload: >
      {
        "load_cost_forecast": {{ (
          (state_attr('sensor.nordpool_kwh_se3_sek_3_10_025', 'raw_today') | map(attribute='value') | list
          + state_attr('sensor.nordpool_kwh_se3_sek_3_10_025', 'raw_tomorrow') | map(attribute='value') | list
        )[now().hour:][:24] | tojson) }},
        
        "prod_price_forecast": {{ (
          (state_attr('sensor.nordpool_kwh_se3_sek_3_10_025', 'raw_today') | map(attribute='value') | list
          + state_attr('sensor.nordpool_kwh_se3_sek_3_10_025', 'raw_tomorrow') | map(attribute='value') | list
        )[now().hour:][:24] | tojson) }}
        
        "prediction_horizon": 24
      }

I also tried to run the API call as a shell_command, with same error and return from dev.tools:

stdout: "HTTP/1.1 500 INTERNAL SERVER ERROR\r\nServer: gunicorn\r\nDate: Wed, 10 Sep 2025 19:53:01 GMT\r\nConnection: keep-alive\r\nContent-Type: text/html; charset=utf-8\r\nContent-Length: 265\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   418    0     0  100   418      0    347  0:00:01  0:00:01 --:--:--   347\r100   418    0     0  100   418      0    189  0:00:02  0:00:02 --:--:--   189\r100   418    0     0  100   418      0    130  0:00:03  0:00:03 --:--:--   130\r100   418    0     0  100   418      0     99  0:00:04  0:00:04 --:--:--    99\r100   683  100   265  100   418     59     94  0:00:04  0:00:04 --:--:--   154"
returncode: 0

Seems like the prebuitl image for Synology Docker is only at 0.10, so a year out of date. @davidusb any chance to update this?

There is no comma between prod_price_forecast and prediction_horizon.
That makes the JSON invalid.
Try this:

rest_command:
  trigger_nordpool_forecast:
    url: "http://192.168.10.3:5000/action/dayahead-optim"
    method: POST
    headers:
      Content-Type: "application/json"
    payload: >
      {
        "load_cost_forecast": {{ (
          (state_attr('sensor.nordpool_kwh_se3_sek_3_10_025', 'raw_today') | map(attribute='value') | list
          + state_attr('sensor.nordpool_kwh_se3_sek_3_10_025', 'raw_tomorrow') | map(attribute='value') | list
        )[0:24] | tojson }},
        
        "prod_price_forecast": {{ (
          (state_attr('sensor.nordpool_kwh_se3_sek_3_10_025', 'raw_today') | map(attribute='value') | list
          + state_attr('sensor.nordpool_kwh_se3_sek_3_10_025', 'raw_tomorrow') | map(attribute='value') | list
        )[0:24] | tojson }},
        
        "prediction_horizon": 24
      }

I think there is also an issue with the load forecast data. This is the household consumption over the past 48 hours used as a forecast for the next 24 hours.

I think you have load_forecast_method set to ‘typical’? Should be like this:

And EMHASS will try to read the household load data our of the recorder database.

There may still be an issue with this setting.

I used to struggle with reading data from the recorder database. I had to let it run for two days after rebooting EMHASS or HA and it would come good after EMHASS had created a training file. I had to “manage the recorder DB” as well by purging and restricting what data was recorded.

Just to test the rest of the code you can just make up a string and add that in:

load_power_forecast": {{"[0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5]" }},

This represents a flat 500W consumption every 30 mins.
But try setting load_forecast_method to naive first.

In the end I created a Node-Red flow that averages the home consumption every 30 mins and stores that is a string (a FIFO buffer)

FIFO the input text

// Get the values from the previous nodes
let fiFoBuffer = msg.payload.substring(msg.payload.indexOf(',') + 1);
let avgHousePower = flow.get("flowAvgHousePower");
let comerString = ","

// Combine values, and comer and create a string
let newValue = fiFoBuffer.concat(comerString.concat(avgHousePower));

// Set the payload to the new value
msg.payload = newValue;

return msg;

Half hour average

var sumHousePower = parseInt(flow.get("flowSumHousePower")) || 0;
var iterationCount = flow.get("flowIterationCount") || 0;
var avgHousePower = flow.get("flowAvgHousePower") || 0;
var msg1 = { payload: 0 };


iterationCount = iterationCount + 1;
sumHousePower += parseInt(msg.payload);

flow.set("flowSumHousePower", sumHousePower);
flow.set("flowIterationCount", iterationCount);

// Determine exit path based on iteration count
if (iterationCount < 30) {
    var msg2 = { payload: [iterationCount,sumHousePower] };
    return [null, msg2];
    } 
else {
    // Calculate average power consumption
    var averagePower = sumHousePower / 30;

    // Reset flow variables for the next 30 iterations
    sumHousePower = 0;
    iterationCount = 0;
    flow.set("flowSumHousePower", sumHousePower);
    flow.set("flowIterationCount", iterationCount);

    // Send the average power out the first exit
    msg1.payload = parseInt(averagePower);
    flow.set("flowAvgHousePower", msg1.payload.toString());

    return [msg1, null];
    }

But that’s going a bit too far at this stage.

Yes, you were right, the load_forecast_method was set to typical.–> now changed to naive
Have removed the comma.

Tried to run, no go.
Dev.tools give same error for rest_command.

Added your suggested “load_power_forecast” array to the rest_command.

The dev.tools respons still the same (Error 500), but now a change in the log file. to:

FileNotFoundError: [Errno 2] No such file or directory: '/data/data_load_cost_forecast.csv'

I changed the linear programming solver to “COIN_CMD” (had earlier read somewhere this could be a problem with Rpi4, so have run on GLPK-CMD.
No change.

Finally changed the EMHASS konfiguration path to “Shared”.

Voila!

Removed again the “load_power_forecast” dummy value string, and still seem to run!

I once before had set the path to shared, but reverted back to default when i had no go in the process. Is it so that if you once have had the path as shared, you cannot go back to default?

Thanx a million for sticking with me in this so far! Next thing will be to try adding the solcast forecast from HA instead of the internal open meteo generated data.

But atlast i finally got a result!

1 Like

With solcast my free account is limited to 10 API calls per day. This is actually only 5 retrievals of data as each update_forecasts call from Home Assistant uses 2 API calls (one for pv_power_forecast and one for radiation/irradiance forecast). You can go to the trouble of setting up two rooftops and tricking the system into 20 API calls, but I’ve found 10 is ok for MPC method and definitely enough for dayahead as you typically only call the dayahead routine once per day anyway.

I don’t use the internal EMHASS configuration to retrieve this data because I set this flow up before it was available and I haven’t bothered falling back to the EMHASS internal set up.


I don’t know what the benefits of either might be?

Now to monitor the forecast output in your dashboard many people use the Apex Chart HACS.

This is an example:

type: custom:apexcharts-card
experimental:
  color_threshold: true
graph_span: 16h
span:
  start: minute
now:
  show: true
  label: now
  color: red
yaxis:
  - id: first
    decimals: 2
    apex_config:
      forceNiceScale: true
  - id: second
    opposite: true
    min: -4000
    max: 7000
    decimals: 0
    apex_config:
      forceNiceScale: true
header:
  show: true
  title: Energy flow
  show_states: true
  colorize_states: true
series:
  - entity: sensor.amber_30min_forecasts_general_price
    yaxis_id: first
    curve: stepline
    float_precision: 2
    show:
      in_header: after_now
    stroke_width: 1
    name: price kWh
    data_generator: |
      return entity.attributes.Forecasts.map((entry) => {
        return [new Date(entry.start_time), entry.advanced_price_predicted];
      });
  - entity: sensor.amber_30min_forecasts_feed_in_price
    yaxis_id: first
    curve: stepline
    float_precision: 2
    show:
      in_header: after_now
    stroke_width: 1
    name: FiT kWh
    data_generator: |
      return entity.attributes.Forecasts.map((entry) => {
        return [new Date(entry.start_time), -entry.advanced_price_predicted];
      });
  - entity: sensor.p_batt_forecast
    yaxis_id: second
    curve: stepline
    type: area
    show:
      in_header: before_now
    stroke_width: 1
    opacity: 0.2
    color: rgb(0,255,0)
    name: Batt Forecast
    data_generator: |
      return entity.attributes.battery_scheduled_power.map((entry) => {
        return [new Date(entry.date), entry.p_batt_forecast];
      });
  - entity: sensor.p_deferrable0
    yaxis_id: second
    curve: stepline
    stroke_width: 1
    name: Pool
    show:
      in_header: before_now
    data_generator: |
      return entity.attributes.deferrables_schedule.map((entry) => {
        return [new Date(entry.date), entry.p_deferrable0];
      });
  - entity: sensor.p_deferrable1
    yaxis_id: second
    curve: stepline
    stroke_width: 1
    name: Car
    color: white
    show:
      in_header: before_now
    data_generator: |
      return entity.attributes.deferrables_schedule.map((entry) => {
        return [new Date(entry.date), entry.p_deferrable1];
      });
  - entity: sensor.p_pv_forecast
    yaxis_id: second
    curve: stepline
    show:
      in_header: before_now
    stroke_width: 1
    name: PV Forecast
    color: rgb(255,215,0)
    data_generator: |
      return entity.attributes.forecasts.map((entry) => {
        return [new Date(entry.date), entry.p_pv_forecast];
      });
  - entity: sensor.p_load_forecast
    yaxis_id: second
    curve: stepline
    show:
      in_header: before_now
    stroke_width: 1
    name: Load Forecast
    color: rgb(255,0,0)
    data_generator: |
      return entity.attributes.forecasts.map((entry) => {
        return [new Date(entry.date), entry.p_load_forecast];
      });
  - entity: sensor.p_grid_forecast
    yaxis_id: second
    curve: stepline
    opacity: 0.1
    color: rgb(0,255,255)
    type: area
    show:
      in_header: before_now
    stroke_width: 1
    name: Grid Forecast
    data_generator: |
      return entity.attributes.forecasts.map((entry) => {
        return [new Date(entry.date), entry.p_grid_forecast];
      });

and

type: custom:apexcharts-card
experimental:
  color_threshold: true
graph_span: 16h
span:
  start: minute
now:
  show: true
  label: now
  color: red
yaxis:
  - id: first
    min: 0
    max: 100
    decimals: 0
    apex_config:
      forceNiceScale: true
  - id: second
    opposite: true
    decimals: 2
    apex_config:
      forceNiceScale: true
header:
  show: true
  title: Amber2MQTT FiT & ST & SOC Forecast
  show_states: true
  colorize_states: true
series:
  - entity: sensor.soc_batt_forecast
    yaxis_id: first
    float_precision: 2
    curve: stepline
    show:
      in_header: after_now
    stroke_width: 1
    name: SOC Batt
    data_generator: |
      return entity.attributes.battery_scheduled_soc.map((entry) => {
        return [new Date(entry.date), entry.soc_batt_forecast];
      });
  - entity: sensor.amber_30min_forecasts_general_price
    yaxis_id: second
    float_precision: 2
    curve: stepline
    show:
      in_header: after_now
    stroke_width: 1
    name: price kwh
    color: red
    data_generator: |
      return entity.attributes.Forecasts.map((entry) => {
        return [new Date(entry.start_time), entry.advanced_price_predicted];
      });
  - entity: sensor.amber_30min_forecasts_feed_in_price
    yaxis_id: second
    float_precision: 2
    curve: stepline
    show:
      in_header: after_now
    stroke_width: 1
    name: FiT kwh
    color: green
    data_generator: |
      return entity.attributes.Forecasts.map((entry) => {
        return [new Date(entry.start_time), -entry.advanced_price_predicted];
      });

Only day ahead -
I may have a misunderstanding, but are weekdays taken into account when forecasting consumption? The reason is that I only charge my electric car on weekdays, not on weekends. This raises concerns that the forecast on Monday will be based on Sunday’s zero consumption. So I have to split the consumption forecast between weekdays and weekends, I think. But how?

You should use the MLForecaster method for load forecast and this is a perfect use case for the way it is currently coded. Actually the days, day-of-the-week, hours of the day, etc, are currently used as features for the machine learning models. So as long as you provide enough data (that include several weekends) this should work fairly well and the type of regression models we are using should be able to catch those electric car charges on weekdays.

Hi! Does anyone else experience (luckily quite rare) extremely high deferrable load values? Result is Optimal, load is 3000W nominal, but I get this (latest version 0.13.4):

Also the battery is not capable of delivering that (and configured correctly)
Details of the log (not at the exact time as above image, but about 10 minutes before with similar end-result):

[2025-09-12 14:04:09 +0200] [10] [INFO] Perform an iteration of a naive MPC controller

[2025-09-12 14:04:09 +0200] [10] [DEBUG] Battery usage enabled. Initial SOC: 0.82, Final SOC: 0.05

[2025-09-12 14:04:09 +0200] [10] [DEBUG] Processing deferrable load 0

[2025-09-12 14:04:09 +0200] [10] [DEBUG] Deferrable load 0: Proposed optimization window: 0 --> 72

[2025-09-12 14:04:09 +0200] [10] [DEBUG] Deferrable load 0: Validated optimization window: 0 --> 72

[2025-09-12 14:04:09 +0200] [10] [DEBUG] Applying minimum power constraint for deferrable load 0: 6600 W

[2025-09-12 14:04:09 +0200] [10] [DEBUG] Processing deferrable load 1

[2025-09-12 14:04:09 +0200] [10] [DEBUG] Load 1 is standard/non-thermal.

[2025-09-12 14:04:09 +0200] [10] [DEBUG] Load 1: Using total hours constraint: 4

[2025-09-12 14:04:09 +0200] [10] [DEBUG] Load 1: Standard load constraints set.

[2025-09-12 14:04:09 +0200] [10] [DEBUG] Deferrable load 1: Proposed optimization window: 0 --> 16

[2025-09-12 14:04:09 +0200] [10] [DEBUG] Deferrable load 1: Validated optimization window: 0 --> 16

[2025-09-12 14:04:09 +0200] [10] [DEBUG] Applying minimum power constraint for deferrable load 1: 3000 W

[2025-09-12 14:04:09 +0200] [10] [DEBUG] Processing deferrable load 2

[2025-09-12 14:04:09 +0200] [10] [DEBUG] Deferrable load 2: Proposed optimization window: 0 --> 16

[2025-09-12 14:04:09 +0200] [10] [DEBUG] Deferrable load 2: Validated optimization window: 0 --> 16

[2025-09-12 14:04:09 +0200] [10] [DEBUG] Applying minimum power constraint for deferrable load 2: 1000 W

[2025-09-12 14:04:09 +0200] [10] [WARNING] Solver default unknown, using default

[2025-09-12 14:04:10 +0200] [10] [INFO] Status: Optimal

[2025-09-12 14:04:10 +0200] [10] [INFO] Total value of the Cost function = 1.03

[2025-09-12 14:04:10 +0200] [10] [DEBUG] Battery usage enabled. Initial SOC: 0.82, Final SOC: 0.05

[2025-09-12 14:04:10 +0200] [10] [DEBUG] Deferrable load operating hours: [0, 4, 0]

[2025-09-12 14:04:10 +0200] [10] [DEBUG] Deferrable load timesteps: None

[2025-09-12 14:04:10 +0200] [10] [DEBUG] Deferrable load start timesteps: [0, 0, 0]

[2025-09-12 14:04:10 +0200] [10] [DEBUG] Deferrable load end timesteps: [72, 16, 16]

[2025-09-12 14:04:10 +0200] [10] [DEBUG] Selected cost function type: profit

[2025-09-12 14:04:10 +0200] [10] [DEBUG] Solver selected: default

[2025-09-12 14:04:10 +0200] [10] [INFO] Optimization status: Optimal

[2025-09-12 14:04:11 +0200] [10] [INFO]  >> Obtaining params: 

[2025-09-12 14:04:11 +0200] [10] [INFO] Passed runtime parameters: {}

[2025-09-12 14:04:11 +0200] [10] [INFO]  >> Setting input data dict

[2025-09-12 14:04:11 +0200] [10] [INFO] Setting up needed data

[2025-09-12 14:04:11 +0200] [10] [DEBUG] Initialized Optimization with retrieve_hass_conf: {'optimization_time_step': Timedelta('0 days 00:15:00'), 'historic_days_to_retrieve': 9, 'sensor_power_photovoltaics': 'sensor.deye_total_solar_power', 'sensor_power_photovoltaics_forecast': 'sensor.p_pv_forecast', 'sensor_power_load_no_var_loads': 'sensor.power_load_no_var_loads', 'load_negative': False, 'set_zero_min': True, 'sensor_replace_zero': [''], 'sensor_linear_interp': ['sensor.deye_total_solar_power', 'sensor.power_load_no_var_loads'], 'method_ts_round': 'first', 'continual_publish': False, 'hass_url': 'http://homeassistant:8123/', 'long_lived_token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJkYmE2N2Y5NTllNmQ0OWZkOTBjMmU4M2YyM2EyMzJmYiIsImlhdCI6MTcwMzcwMDQwNSwiZXhwIjoyMDE5MDYwNDA1fQ.W9kPfbHrV8kU1qbXFp6xiL3HIJEdJWWmFGbhFVnP2GE', 'time_zone': <DstTzInfo 'Europe/Amsterdam' LMT+0:18:00 STD>, 'Latitude': 45.83, 'Longitude': 6.86, 'Altitude': 4807.8}

[2025-09-12 14:04:11 +0200] [10] [DEBUG] Optimization configuration: {'costfun': 'profit', 'logging_level': 'DEBUG', 'set_use_pv': True, 'set_use_adjusted_pv': False, 'adjusted_pv_regression_model': 'LassoRegression', 'adjusted_pv_solar_elevation_threshold': 10, 'set_use_battery': True, 'number_of_deferrable_loads': 3, 'nominal_power_of_deferrable_loads': [6600, 3000, 1000], 'minimum_power_of_deferrable_loads': [6600, 3000, 1000], 'operating_hours_of_each_deferrable_load': [0, 0, 0], 'treat_deferrable_load_as_semi_cont': [True, True, True], 'set_deferrable_load_single_constant': [False, False, False], 'set_deferrable_startup_penalty': [0, 0, 0], 'delta_forecast_daily': Timedelta('1 days 00:00:00'), 'load_forecast_method': 'naive', 'load_cost_forecast_method': 'hp_hc_periods', 'load_peak_hours_cost': 0.1907, 'load_offpeak_hours_cost': 0.1419, 'production_price_forecast_method': 'constant', 'photovoltaic_production_sell_price': 0.1419, 'set_total_pv_sell': False, 'lp_solver': 'default', 'lp_solver_path': 'empty', 'lp_solver_timeout': 45, 'num_threads': 0, 'set_nocharge_from_grid': False, 'set_nodischarge_to_grid': False, 'set_battery_dynamic': False, 'battery_dynamic_max': 0.9, 'battery_dynamic_min': -0.9, 'weight_battery_discharge': 1, 'weight_battery_charge': 1, 'weather_forecast_method': 'csv', 'open_meteo_cache_max_age': 30, 'start_timesteps_of_each_deferrable_load': [0, 0, 0], 'end_timesteps_of_each_deferrable_load': [0, 0, 0], 'load_peak_hour_periods': {'period_hp_1': [{'start': '02:54'}, {'end': '15:24'}], 'period_hp_2': [{'start': '17:24'}, {'end': '20:24'}]}}

[2025-09-12 14:04:11 +0200] [10] [DEBUG] Plant configuration: {'maximum_power_from_grid': 17250, 'maximum_power_to_grid': 17250, 'pv_module_model': ['CSUN_Eurasia_Energy_Systems_Industry_and_Trade_CSUN295_60M'], 'pv_inverter_model': ['Fronius_International_GmbH__Fronius_Primo_5_0_1_208_240__240V_'], 'surface_tilt': [30], 'surface_azimuth': [205], 'modules_per_string': [15], 'strings_per_inverter': [2], 'inverter_is_hybrid': False, 'inverter_ac_output_max': 1000, 'inverter_ac_input_max': 1000, 'inverter_efficiency_dc_ac': 1, 'inverter_efficiency_ac_dc': 1, 'compute_curtailment': False, 'battery_discharge_power_max': 7680, 'battery_charge_power_max': 7680, 'battery_discharge_efficiency': 0.95, 'battery_charge_efficiency': 0.95, 'battery_nominal_energy_capacity': 9600, 'battery_minimum_state_of_charge': 0.05, 'battery_maximum_state_of_charge': 0.95, 'battery_target_state_of_charge': 0.1}

Sorry. I was too quick to say Hurray :weary:
What i thougth was a final progress, was just that EMHASS found the “test data” in the shared folder i once had used when playing around, trying to set things up in first place. Data was from august…No new optimization task was run. And still same Internal error 500 when running rest command from dev.tools.

So it seems i cant post the Nordpooldata to EMHASS.
Reinstalled the whole package. Still same result.

Question:
Is there any way to look at the CSV file in EMHASS to verify that it is not updated when doing the rest_command?
It states in the log (using open meteo) that it changes forecast from 1 to 3 days automaticly. Might this cause the problem? And Should i try to post the Solcast to EMHASS aswell to get around this?
Wether the internal solcast engine or posting from home assistans is to prefer, i think that since i use the solcast integration for other applications, using the 10 API calls, there would be no left for EMHASS. By posting the information, i could stick with the 10 APIcalls that is used already.

The error 500 usually means that the data you are passing is not in JSON format. If you can reproduce the output from your shell_command or rest_command and past it into a JSON checker (e.g. https://jsonformatter.org/) to confirm its validity, that would be the first thing to do.

Q1 Is there any way to look at the CSV file in EMHASS to verify that it is not updated when doing the rest_command?

Don’t know. I haven’t used CSV files in EMHASS.

Q2 It states in the log (using open meteo) that it changes forecast from 1 to 3 days automaticly. Might this cause the problem?

No I don’t think so. As long as there is more data points than your prediction horizon. If you are already using solcast integration then you will have to format that data in your rest_command. However you can stick with meteo for the time being.

I can’t emphasise enough how important it is to make sure the output is valid JSON format. So focus on that first.

You can take the raw JINJA2 code out of the rest_command and past it into the developer tools template to test it.

You can also check the JSON by posting it manually into EMHASS. This can be done from any PC on your network.
Example Powershell:

curl -X POST http://192.168.10.3:5000/action/dayahead-optim `
     -H "Content-Type: application/json" `
     -d '{
           "load_cost_forecast": [0.45,0.43,0.41,0.39,0.42,0.47,0.50,0.55,0.60,0.58,0.52,0.48,
                                  0.46,0.44,0.42,0.40,0.43,0.49,0.53,0.57,0.59,0.56,0.50,0.47],
           "prod_price_forecast": [0.45,0.43,0.41,0.39,0.42,0.47,0.50,0.55,0.60,0.58,0.52,0.48,
                                   0.46,0.44,0.42,0.40,0.43,0.49,0.53,0.57,0.59,0.56,0.50,0.47],
           "prediction_horizon": 24
         }'

Example Linux:

curl -X POST http://192.168.10.3:5000/action/dayahead-optim \
     -H "Content-Type: application/json" \
     -d '{
           "load_cost_forecast": [0.45,0.43,0.41,0.39,0.42,0.47,0.50,0.55,0.60,0.58,0.52,0.48,
                                  0.46,0.44,0.42,0.40,0.43,0.49,0.53,0.57,0.59,0.56,0.50,0.47],
           "prod_price_forecast": [0.45,0.43,0.41,0.39,0.42,0.47,0.50,0.55,0.60,0.58,0.52,0.48,
                                   0.46,0.44,0.42,0.40,0.43,0.49,0.53,0.57,0.59,0.56,0.50,0.47],
           "prediction_horizon": 24
         }'

Example Mac:

curl -X POST http://192.168.10.3:5000/action/dayahead-optim \
     -H "Content-Type: application/json" \
     -d '{
           "load_cost_forecast": [0.45,0.43,0.41,0.39,0.42,0.47,0.50,0.55,0.60,0.58,0.52,0.48,
                                  0.46,0.44,0.42,0.40,0.43,0.49,0.53,0.57,0.59,0.56,0.50,0.47],
           "prod_price_forecast": [0.45,0.43,0.41,0.39,0.42,0.47,0.50,0.55,0.60,0.58,0.52,0.48,
                                   0.46,0.44,0.42,0.40,0.43,0.49,0.53,0.57,0.59,0.56,0.50,0.47],
           "prediction_horizon": 24
         }'

Assuming that 192.168.10.3 is the IP assress of your HA server and you are using HAOS.

From bottom up:

Manual posting from terminal (mac) using your code (yes, the http:// is correct) give:

^[[A<!doctype html>
<html lang=en>
<title>500 Internal Server Error</title>
<h1>Internal Server Error</h1>
<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>
marst27@mac01308 ~ % curl -X POST http://192.168.10.3:5000/action/dayahead-optim \
     -H "Content-Type: application/json" \
     -d '{
           "load_cost_forecast": [0.45,0.43,0.41,0.39,0.42,0.47,0.50,0.55,0.60,0.58,0.52,0.48,
                                  0.46,0.44,0.42,0.40,0.43,0.49,0.53,0.57,0.59,0.56,0.50,0.47],
           "prod_price_forecast": [0.45,0.43,0.41,0.39,0.42,0.47,0.50,0.55,0.60,0.58,0.52,0.48,
                                   0.46,0.44,0.42,0.40,0.43,0.49,0.53,0.57,0.59,0.56,0.50,0.47],
           "prediction_horizon": 24
         }'


testing the Jinja2 code in dev.tools template give:


(sorry for swedish UI. It says “this template is updated every minute”, “this template listens for the following entities”)

Question: you are not using CSV? I thought this array we created was put in a CSV in EMHASS? My misunderstanding probably. But in the EMHASS GUI there is only to choose from hp_hc periods or CSV. Should this be set to hp_hc? (have been set to CSV). Changed this to hp_hc, no difference, same error. Looks like this in GUI. Does it matter what is stated in GUI when trying to feed in with API post?

So then I have the jsonformatter left to work with…

Not sure if it’s a difference, but in my curl command, the ordering is a bit different:
"curl -i -H \"Content-Type:application/json\" -X POST -d '{ <<< all the variables stuff >>> }' http://nas2:9002/action/dayahead-optim"

Regarding csv, I think it doesn’t matter, I used to have it hc-hc etc, but changed it to csv, but in the end, what you supply on the commandline seems to be the info used

The json.formatter.org is not happy. This is respons:

But testing the full rest_command.yaml in duck ai. claims it is valid. I am still clueless… :sweat_smile:

Thnx. I’ll try to rearrange the curl command order when back on home network tomorrow. I wonder if there could be any other general settings that is blocking me from using the rest_command/curl for sending the API calls? On my router? In homeassistant in general?