EMHASS: An Energy Management for Home Assistant

Nope, spoke too soon. EMHASS gets the right prices if i run the command manually from developer tools, but not if i run the tasks from the buttons in the web interface.

I barely understand half of that text, really need the dummies version I guess…

When you run with the buttons in the webinterface no parameteres are passed. The shell_command is like this:

shell_command:
  dayahead_optim: "curl -i -H \"Content-Type:application/json\" -X POST -d '{}' http://localhost:5000/action/dayahead-optim"
  publish_data: "curl -i -H \"Content-Type:application/json\" -X POST -d '{}' http://localhost:5000/action/publish-data"

You must automate the day-ahead forecast every day with rest_commands. Your automation is using shell_command. Do it like this

alias: "Emhass: Dayahead optimisering klokken 13:45"
description: ""
trigger:
  - platform: time
    at: "13:45:00"
condition: []
action:
  - service: rest_command.trigger_dayahead_1345_forecast
    data: {}
mode: single

Hi all, love the idea of this but really struggling to get it to work!

I have 30min dynamic pricing, solar and battery, with no need to export to the grid (old UK feed in tariff where they assume what you feed in, rather than actually count it).

I have setup the shell commands, and a daily automation to run the dayahead, and a 5min run of publishing, which are successfully populating the UI.

My issues are that the 30min pricing information is not populating, it is only using the peak hours/periods from the config below (but I can’t remove those in that config?). Additionally the battery SOC in the forecast is 60% permanently (I appreciate that that is the target but it isn’t flexing up or down at all?). Also not sure why I need a deferable load - is that meant to be the battery charge?

Assume I’m missing something simple, any help would be appreciated, thanks!

shell_command:
  dayahead_optim: "curl -i -H \"Content-Type:application/json\" -X POST -d '{\"load_cost_forecast\": {{((state_attr('sensor.octopus_energy_electricity_current_rate', 'all_rates')|map(attribute='value_inc_vat')|list)[:48])}}' http://localhost:5000/action/dayahead-optim"
  publish_data: "curl -i -H \"Content-Type:application/json\" -X POST -d '{}' http://localhost:5000/action/publish-data"

Where

{{((state_attr('sensor.octopus_energy_electricity_current_rate', 'all_rates')|map(attribute='value_inc_vat')|list)[:48])}}

is returning 48 30min comma energy prices.

My configuration is currently:

hass_url: empty
long_lived_token: empty
costfun: cost
logging_level: INFO
optimization_time_step: 30
historic_days_to_retrieve: 2
method_ts_round: nearest
set_total_pv_sell: false
lp_solver: COIN_CMD
lp_solver_path: /usr/bin/cbc
set_nocharge_from_grid: false
set_nodischarge_to_grid: false
set_battery_dynamic: false
battery_dynamic_max: 0.9
battery_dynamic_min: -0.9
load_forecast_method: naive
sensor_power_photovoltaics: sensor.production_today
sensor_power_load_no_var_loads: sensor.consumed_today
number_of_deferrable_loads: 2
list_nominal_power_of_deferrable_loads:
  - nominal_power_of_deferrable_loads: 3000
  - nominal_power_of_deferrable_loads: 750
list_operating_hours_of_each_deferrable_load:
  - operating_hours_of_each_deferrable_load: 5
  - operating_hours_of_each_deferrable_load: 8
list_peak_hours_periods_start_hours:
  - peak_hours_periods_start_hours: "02:54"
  - peak_hours_periods_start_hours: "17:24"
list_peak_hours_periods_end_hours:
  - peak_hours_periods_end_hours: "15:24"
  - peak_hours_periods_end_hours: "20:24"
list_treat_deferrable_load_as_semi_cont:
  - treat_deferrable_load_as_semi_cont: true
  - treat_deferrable_load_as_semi_cont: true
load_peak_hours_cost: 0.1907
load_offpeak_hours_cost: 0.1419
photovoltaic_production_sell_price: 0
maximum_power_from_grid: 9000
list_pv_module_model:
  - pv_module_model: CSUN_Eurasia_Energy_Systems_Industry_and_Trade_CSUN295_60M
list_pv_inverter_model:
  - pv_inverter_model: Fronius_International_GmbH__Fronius_Primo_5_0_1_208_240__240V_
list_surface_tilt:
  - surface_tilt: 30
list_surface_azimuth:
  - surface_azimuth: 205
list_modules_per_string:
  - modules_per_string: 16
list_strings_per_inverter:
  - strings_per_inverter: 1
set_use_battery: true
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.1
battery_maximum_state_of_charge: 0.9
battery_target_state_of_charge: 0.6

Oh, fixed that now. If I trigger the automations EMHASS seems to work as it should.

So if I understand this right, the prices will only update if the automation is triggered? I Can not use the buttons in the web interface to test if everything is working? Now wonder I’ve been struggling then…

1 Like

You need to add Rest commands to send the info, Currently your using shell commands to send it.

Change you commands to suit your sensors

shell_command:
  dayahead_optim: "curl -i -H \"Content-Type: application/json\" -X POST -d '{}' http://localhost:5000/action/dayahead-optim"
  publish_data: "curl -i -H \"Content-Type: application/json\" -X POST -d '{}' http://localhost:5000/action/publish-data "

rest_command:
  naive_mpc_optim:
    url: http://localhost:5000/action/naive-mpc-optim
    method: POST
    content_type: 'application/json'
    payload: >-
      {
        "prod_price_forecast": {{
          ([states('sensor.home_feed_in_price')|float(0)] +
          (state_attr('sensor.home_feed_in_forecast', 'forecasts')|map(attribute='per_kwh')|list))
          | tojson 
        }},
        "load_cost_forecast": {{
          ([states('sensor.home_general_price')|float(0)] + 
          state_attr('sensor.home_general_forecast', 'forecasts') |map(attribute='per_kwh')|list) 
          | tojson 
        }},
        "pv_power_forecast": {{
          ([states('sensor.solar_total')|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
          )| tojson
        }},
        "prediction_horizon": {{
          min(48, (state_attr('sensor.home_feed_in_forecast', 'forecasts')|map(attribute='per_kwh')|list|length)+1)
        }},
        "soc_init": {{(states('sensor.battery_total_2')|int(0))/400 }},
        "soc_final": 0.2
      } 
1 Like

I’ve got some weird results when running this MPC:

curl -i -H "Content-Type: application/json" -X POST -d '{
        "load_cost_forecast": [0.1616, 0.1604, 0.1604, 0.1612, 0.1612, 0.1591, 0.1591, 0.1596, 0.1596, 0.1593, 0.1593, 0.1587, 0.1587, 0.1589, 0.1589, 0.1602, 0.1602, 0.1613, 0.1613, 0.1722, 0.1722, 0.1859, 0.1859, 0.1626, 0.1626, 0.1613, 0.1613, 0.1602, 0.1602, 0.16, 0.16, 0.1597, 0.1597, 0.1612, 0.1612, 0.1621, 0.1621, 0.2413, 0.2413, 0.3016, 0.3016, 0.316, 0.316, 0.2767, 0.2767, 0.2633, 0.2633, 0.2501],
        "prediction_horizon": 48,
        "pv_power_forecast": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 511, 677, 839, 1090, 1311, 1574, 2072, 2605, 3306, 3893, 4433, 4769, 5023, 5196, 5251, 5016, 4708, 3979, 3103, 2079, 1035, 889, 0, 0, 0, 0, 0, 0, 0],
        "alpha": 0.75,
        "beta": 0.25,
        "num_def_loads": 3,
        "def_total_hours": [0,3,0],
        "P_deferrable_nom":  [
            2250,
            2000,2000
          ],
        "treat_def_as_semi_cont": [false, false, false],
        "set_def_constant": [true, true, true]
      }' http://localhost:5000/action/naive-mpc-optim

It splits up the load into more then 3 hours.

This won’t be better if running for two deferrable loads (3h each).

curl -i -H "Content-Type: application/json" -X POST -d '{
        "load_cost_forecast": [0.1616, 0.1604, 0.1604, 0.1612, 0.1612, 0.1591, 0.1591, 0.1596, 0.1596, 0.1593, 0.1593, 0.1587, 0.1587, 0.1589, 0.1589, 0.1602, 0.1602, 0.1613, 0.1613, 0.1722, 0.1722, 0.1859, 0.1859, 0.1626, 0.1626, 0.1613, 0.1613, 0.1602, 0.1602, 0.16, 0.16, 0.1597, 0.1597, 0.1612, 0.1612, 0.1621, 0.1621, 0.2413, 0.2413, 0.3016, 0.3016, 0.316, 0.316, 0.2767, 0.2767, 0.2633, 0.2633, 0.2501],
        "prediction_horizon": 48,
        "pv_power_forecast": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 511, 677, 839, 1090, 1311, 1574, 2072, 2605, 3306, 3893, 4433, 4769, 5023, 5196, 5251, 5016, 4708, 3979, 3103, 2079, 1035, 889, 0, 0, 0, 0, 0, 0, 0],
        "alpha": 0.75,
        "beta": 0.25,
        "num_def_loads": 3,
        "def_total_hours": [0,3,3],
        "P_deferrable_nom":  [
            2250,
            2000,2000
          ],
        "treat_def_as_semi_cont": [false, false, false],
        "set_def_constant": [true, true, true]
      }' http://localhost:5000/action/naive-mpc-optim

If I ran the same command with a prediction_horizon of 36 it seems to produce the right output:

Any ideas?

Furthermore I would expect that one of the loads could already start at 12:30 pm…

Hey, new issue here. Everything seems to be working now, but the entso-e prices are late by one hour. They are correct everywhere else exept in emhass. Any ideas what could cause this?

Try the first/last setting, mine is set to first. Perhaps that helps?

What does your jinja code produce when you test in Developer Tools Template? What does your pricing sensor look like?
My dayahead jinja code looks like this:

{
  "load_cost_forecast": {{
    ([states('sensor.cecil_st_general_price')|float(0)] + 
    state_attr('sensor.cecil_st_general_forecast', 'forecasts') |map(attribute='per_kwh')|list) 
    | tojson 
  }},
  "prod_price_forecast": {{
    ([states('sensor.cecil_st_feed_in_price')|float(0)] +
    (state_attr('sensor.cecil_st_feed_in_forecast', 'forecasts')|map(attribute='per_kwh')|list))
    | tojson 
  }},
  "pv_power_forecast": {{
    ([states('sensor.sonnenbatterie_84324_production_w')|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
    )| tojson
  }},
  "num_def_loads": 2,
  "def_total_hours": [3,0],
  "P_deferrable_nom":  [1300, 7360],
  "treat_def_as_semi_cont": [1, 0]  
}

Result from Developer Tools Template looks like this:

{
  "load_cost_forecast": [
    0.16,
    0.16,
    0.16,
    0.16,
    0.16,
    0.16,
    0.16,
    0.15,
    0.13,
    0.13,
    0.13,
    0.16,
    0.16,
    0.16,
    0.16,
    0.13,
    0.11,
    0.1,
    0.1,
    0.1,
    0.1,
    0.08,
    0.04,
    0.03,
    0.03,
    0.02,
    0.02,
    0.02,
    0.02,
    0.27,
    0.27,
    0.28,
    0.29,
    0.3,
    0.32,
    0.35,
    0.36,
    0.38,
    0.42,
    0.42,
    0.45,
    0.19,
    0.16,
    0.16,
    0.16,
    0.15,
    0.13,
    0.15,
    0.13
  ],
  "prod_price_forecast": [
    0.06,
    0.06,
    0.06,
    0.06,
    0.06,
    0.06,
    0.06,
    0.05,
    0.04,
    0.04,
    0.04,
    0.06,
    0.06,
    0.06,
    0.06,
    0.04,
    0.02,
    0.01,
    0.01,
    0.01,
    0.01,
    -0.03,
    -0.07,
    -0.07,
    -0.08,
    -0.08,
    -0.08,
    -0.08,
    -0.09,
    0.2,
    0.2,
    0.21,
    0.21,
    0.22,
    0.24,
    0.27,
    0.28,
    0.29,
    0.33,
    0.33,
    0.36,
    0.09,
    0.06,
    0.06,
    0.06,
    0.06,
    0.04,
    0.06,
    0.04
  ],
  "pv_power_forecast": [
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    5,
    58,
    345,
    861,
    1411,
    1992,
    2500,
    2941,
    3314,
    3608,
    3856,
    4004,
    4049,
    4064,
    4090,
    4020,
    3854,
    3642,
    3354,
    3020,
    2599,
    2130,
    1554,
    1031,
    503,
    89,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0
  ],
  "num_def_loads": 2,
  "def_total_hours": [
    3,
    0
  ],
  "P_deferrable_nom": [
    1300,
    7360
  ],
  "treat_def_as_semi_cont": [
    1,
    0
  ]
}

My pricing data looks like this:

Deferrable loads are things like EV charging, hot water, pool pump etc. These loads need to be automated so EMHASS can control them and their consumption subtracted from household consumption.
Maybe this might help my doco

1 Like

Thanks, that looks like it works.

I’m still struckling with the battery forecast SOC and the actual SOC of the battery.

I don’t use the forecast soc value in a automation.

The capacity is correctly configured. Any idea how to solve this?

See also the screenshot:

The blue line is the Battery forecast SOC of EMHASS, purple the actual SOC from the inverter.

See my config:

hass_url: empty
long_lived_token: empty
costfun: profit
logging_level: INFO
optimization_time_step: 60
historic_days_to_retrieve: 3
method_ts_round: first
set_total_pv_sell: false
lp_solver: COIN_CMD
lp_solver_path: /usr/bin/cbc
set_nocharge_from_grid: false
set_nodischarge_to_grid: false
set_battery_dynamic: false
battery_dynamic_max: 0.92
battery_dynamic_min: -0.92
load_forecast_method: naive
sensor_power_photovoltaics: sensor.solaredge_ac_power
sensor_power_load_no_var_loads: sensor.house_usage_in_watt
number_of_deferrable_loads: 2
list_nominal_power_of_deferrable_loads:
  - nominal_power_of_deferrable_loads: 800
  - nominal_power_of_deferrable_loads: 10800
list_operating_hours_of_each_deferrable_load:
  - operating_hours_of_each_deferrable_load: 2
  - operating_hours_of_each_deferrable_load: 4
list_peak_hours_periods_start_hours:
  - peak_hours_periods_start_hours: "02:54"
  - peak_hours_periods_start_hours: "17:24"
list_peak_hours_periods_end_hours:
  - peak_hours_periods_end_hours: "15:24"
  - peak_hours_periods_end_hours: "20:24"
list_treat_deferrable_load_as_semi_cont:
  - treat_deferrable_load_as_semi_cont: false
  - treat_deferrable_load_as_semi_cont: false
load_peak_hours_cost: 0.1907
load_offpeak_hours_cost: 0.1419
photovoltaic_production_sell_price: 0.065
maximum_power_from_grid: 17250
list_pv_module_model:
  - pv_module_model: Jinko_Solar_Co___Ltd_JKM410M_72HL
list_pv_inverter_model:
  - pv_inverter_model: SolarEdge_Technologies_Ltd___SE9K__208V_
list_surface_tilt:
  - surface_tilt: 45
list_surface_azimuth:
  - surface_azimuth: 210
list_modules_per_string:
  - modules_per_string: 26
list_strings_per_inverter:
  - strings_per_inverter: 1
set_use_battery: true
battery_discharge_power_max: 3300
battery_charge_power_max: 3300
battery_discharge_efficiency: 0.95
battery_charge_efficiency: 0.95
battery_nominal_energy_capacity: 14500
battery_minimum_state_of_charge: 0.1
battery_maximum_state_of_charge: 1
battery_target_state_of_charge: 0.1

This is mine. Don’t know if it indicates anything is wrong.

I have a powerwall and I use the SOC forecast to set the backup reserve %.

The battery responds like this:

  • set reserve < actual SOC - stores excess solar and discharges battery to meet excess household load.
  • reserve = SOC - stores excess solar and doesn’t discharge battery excess household load is drawn from the grid
  • reserve > SOC - forces battery to charge slowly (5.5 kW) from solar+grid

I also use the p_batt_forecast to change charging rates

  • batt_forecast < -5.5 kW backup reserve % above
  • batt_forecast < -10 kW set mode backup - forces charging at 10 kW
  • batt_forecast < -15 kW set mode time_based_control if battery tou is off_peak - forces charging at 15 kW
  • batt_forecast > 15 kW set mode time_based_control if battery tou is peak - forces discharging at 15 kW

The discharging control is a work around and other batteries have much better controls.

Can you tell us what type of battery you have and what automations you are using to control it?

For sonnen batteries, control is leveraged through POST command to switch between automatic and manual mode.

In manual mode POST commands to charge and discharge at whatever wattage and set backup buffer to whatever percentage of battery SOC. Backup buffer = Battery reserve.

I only use backup buffer to force standby state when in manual mode by switching to 100% standby as there is no stop charge/discharge command.

Automatic mode is self-consumption mode.

Would be good if EMHASS had a sensor for self-consumption as the battery follows house consumption instantly while EMHASS only adjusts to house consumption roughly depending on frequency of POST command to EMHASS.

Max charge or discharge is only 3300 Watts and I notice that the battery drifts from the requested wattage as the temperature rises and will sometimes stop charging altogether on very hot days after a few hours.

Currently I only use the p_batt_forecast level currently. This value will be send to my inverter. As you can see in the chart. The value looks not good enough for some reason.

Which battery do you have?

Maybe include a screen shot showing p_batt_forecast and your actual battery power, your earlier charts look like the battery is following the soc_forecast quite well.

Here is mine.

I have home build battery. LifePo4 16x280A. My inverter requires a -value for discharging and + value for charging. So the chart is the opposite. So the charge/discharge looks the same.

But the SOC is in my opinion not great.

Hi folks, something odd has just started happening with my EMHASS setup. Has anyone seen this?

2023-10-17 09:25:20,077 - web_server - INFO - Setting up needed data
2023-10-17 09:25:20,123 - web_server - INFO - Retrieve hass get data method initiated...
2023-10-17 09:25:20,326 - web_server - INFO - Retrieving weather forecast data using method = list
2023-10-17 09:25:20,330 - web_server - INFO -  >> Performing naive MPC optimization...
2023-10-17 09:25:20,330 - web_server - INFO - Performing naive MPC optimization
2023-10-17 09:25:20,335 - web_server - INFO - Perform an iteration of a naive MPC controller
2023-10-17 09:25:21,542 - web_server - ERROR - It was not possible to find a valid solver for Pulp package
2023-10-17 09:25:21,543 - web_server - INFO - Status: Not Solved
2023-10-17 09:25:21,543 - web_server - WARNING - Cost function cannot be evaluated, probably None
2023-10-17 09:25:21,546 - 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 275, in naive_mpc_optim
    opt_res_naive_mpc = input_data_dict['opt'].perform_naive_mpc_optim(
  File "/usr/local/lib/python3.9/dist-packages/emhass/optimization.py", line 575, in perform_naive_mpc_optim
    self.opt_res = self.perform_optimization(df_input_data, P_PV.values.ravel(), P_load.values.ravel(),
  File "/usr/local/lib/python3.9/dist-packages/emhass/optimization.py", line 418, in perform_optimization
    opt_tp["P_grid"] = [P_grid_pos[i].varValue + P_grid_neg[i].varValue for i in set_I]
  File "/usr/local/lib/python3.9/dist-packages/emhass/optimization.py", line 418, in <listcomp>
    opt_tp["P_grid"] = [P_grid_pos[i].varValue + P_grid_neg[i].varValue for i in set_I]
TypeError: unsupported operand type(s) for +: 'NoneType' and 'NoneType'

Here is the call to the MPC action:

2023-10-17 09:25:21.547 WARNING (MainThread) [homeassistant.components.rest_command] Error. Url: http://localhost:5000/action/naive-mpc-optim. Status code 500. Payload: b'{\n "load_power_forecast":\n [5901, 2206, 2093, 2428, 2246, 6518, 6430, 7149, 7360, 6744, 6559, 5878, 5942, 2502, 1947, 2536, 2013, 2187, 2731, 3890, 3416, 3042, 3175, 3009, 2452, 2029, 2288, 1622, 1276, 5147, 5428, 5503, 5485, 5584, 5446, 5574, 5482, 1200, 975, 1039, 935, 903, 1006, 1269, 1514, 5860, 6162, 6186], \n 
"load_cost_forecast":\n [0.24915, 0.24915, 0.24915, 0.24915, 0.24915, 0.24915, 0.24915, 0.24915, 0.24915, 0.24915, 0.46178, 0.46178, 0.46178, 0.46178, 0.46178, 0.46178, 0.46178, 0.46178, 0.46178, 0.46178, 0.46178, 0.46178, 0.24915, 0.24915, 0.24915, 0.24915, 0.19239, 0.19239, 0.19239, 0.19239, 0.19239, 0.19239, 0.19239, 0.19239, 0.19239, 0.19239, 0.19239, 0.19239, 0.19239, 0.19239, 0.19239, 0.19239, 0.19239, 0.19239, 0.24915, 0.24915, 0.24915, 0.24915], \n 
"pv_power_forecast":\n [4075, 12982, 17000, 17000, 17000, 17000, 16941, 15385, 14479, 14099, 13692, 13145, 12344, 11260, 9803, 8082, 5981, 3706, 1389, 285, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 500, 2118, 4359, 6440, 8178, 9801, 11289, 12653, 13960, 14948, 15643, 16047, 16385, 16389, 16075, 15700, 15153, 14322, 13266, 11637, 9413, 6971, 4469, 1917, 375, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], \n 
"prediction_horizon":\n 48, \n 
"alpha":\n 0.2, \n "beta":\n 0.8, \n "soc_init":\n 0.15, \n "soc_final":\n 0.15, \n 
"set_def_constant":\n ["false","true","true"], \n 
"def_total_hours":\n [ 0, \n 7,\n 3]\n}'

All the newlines come from template formatting. I assume that is not an issue.

When I test the above between the {} at this json test site jsonlint.com I get this:

Invalid JSON!
Error: Parse error on line 1:
{\n "load_power_forec
-^
Expecting 'STRING', '}', got 'undefined'

If I take all the new lines out like this:

{ "load_power_forecast": [5901, 2206, 2093, 2428, 2246, 6518, 6430, 7149, 7360, 6744, 6559, 5878, 5942, 2502, 1947, 2536, 2013, 2187, 2731, 3890, 3416, 3042, 3175, 3009, 2452, 2029, 2288, 1622, 1276, 5147, 5428, 5503, 5485, 5584, 5446, 5574, 5482, 1200, 975, 1039, 935, 903, 1006, 1269, 1514, 5860, 6162, 6186],  
"load_cost_forecast": [0.24915, 0.24915, 0.24915, 0.24915, 0.24915, 0.24915, 0.24915, 0.24915, 0.24915, 0.24915, 0.46178, 0.46178, 0.46178, 0.46178, 0.46178, 0.46178, 0.46178, 0.46178, 0.46178, 0.46178, 0.46178, 0.46178, 0.24915, 0.24915, 0.24915, 0.24915, 0.19239, 0.19239, 0.19239, 0.19239, 0.19239, 0.19239, 0.19239, 0.19239, 0.19239, 0.19239, 0.19239, 0.19239, 0.19239, 0.19239, 0.19239, 0.19239, 0.19239, 0.19239, 0.24915, 0.24915, 0.24915, 0.24915],  
"pv_power_forecast": [4075, 12982, 17000, 17000, 17000, 17000, 16941, 15385, 14479, 14099, 13692, 13145, 12344, 11260, 9803, 8082, 5981, 3706, 1389, 285, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 500, 2118, 4359, 6440, 8178, 9801, 11289, 12653, 13960, 14948, 15643, 16047, 16385, 16389, 16075, 15700, 15153, 14322, 13266, 11637, 9413, 6971, 4469, 1917, 375, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],  
"prediction_horizon": 48,  
"alpha": 0.2,  "beta": 0.8,  "soc_init": 0.15,  "soc_final": 0.15,  
"set_def_constant": ["false","true","true"],  
"def_total_hours": [ 0,  7, 3]}

I get this:

JSON is valid!