davidusb-geek / emhass-add-on

The Home Assistant Add-on for EMHASS: Energy Management Optimization for Home Assistant
MIT License
96 stars 29 forks source link

Error with MPC #93

Closed RikBast closed 3 weeks ago

RikBast commented 6 months ago

I get this message quite often:

2024-05-01 19:30:00,116 - web_server - INFO - >> Setting input data dict 2024-05-01 19:30:00,116 - web_server - INFO - Setting up needed data 2024-05-01 19:30:00,131 - web_server - INFO - Retrieve hass get data method initiated... 2024-05-01 19:30:00,415 - web_server - INFO - Retrieving weather forecast data using method = scrapper 2024-05-01 19:30:01,606 - web_server - INFO - Retrieving data from hass for load forecast using method = naive 2024-05-01 19:30:01,606 - web_server - INFO - Retrieve hass get data method initiated... 2024-05-01 19:30:01,950 - web_server - ERROR - Exception on /action/naive-mpc-optim [POST] Traceback (most recent call last): File "/usr/local/lib/python3.11/dist-packages/flask/app.py", line 1463, in wsgi_app response = self.full_dispatch_request() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/dist-packages/flask/app.py", line 872, in full_dispatch_request rv = self.handle_user_exception(e) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/dist-packages/flask/app.py", line 870, in full_dispatch_request rv = self.dispatch_request() ^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/dist-packages/flask/app.py", line 855, in dispatch_request return self.ensure_sync(self.view_functions[rule.endpoint])(*view_args) # type: ignore[no-any-return] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/dist-packages/emhass/web_server.py", line 108, in action_call input_data_dict = set_input_data_dict(config_path, str(data_path), costfun, ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/dist-packages/emhass/command_line.py", line 129, in set_input_data_dict df_input_data_dayahead = utils.set_df_index_freq(df_input_data_dayahead) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/dist-packages/emhass/utils.py", line 687, in set_df_index_freq df = df.asfreq(sampling) ^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/dist-packages/pandas/core/frame.py", line 10971, in asfreq return super().asfreq( ^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/dist-packages/pandas/core/generic.py", line 8347, in asfreq return asfreq( ^^^^^^^ File "/usr/local/lib/python3.11/dist-packages/pandas/core/resample.py", line 2232, in asfreq dti = date_range(obj.index.min(), obj.index.max(), freq=freq) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/dist-packages/pandas/core/indexes/datetimes.py", line 945, in date_range dtarr = DatetimeArray._generate_range( ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/dist-packages/pandas/core/arrays/datetimes.py", line 446, in _generate_range i8values = generate_regular_range(start, end, periods, freq, unit=unit) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/dist-packages/pandas/core/arrays/_ranges.py", line 68, in generate_regular_range e = b + (iend - b) // stride stride + stride // 2 + 1


ZeroDivisionError: integer division or modulo by zero

This is my call":

```
  post_mpc_optim: "curl -i -H \"Content-Type: application/json\" -X POST -d '{\"load_cost_forecast\":{{
          (states.sensor.electricity_consumption_price_24h_forecast.state)
          }}, \"prod_price_forecast\":{{
          (states.sensor.electricity_production_price_24h_forecast.state) 
          }}, \"prediction_horizon\":{{min(48,(states.sensor.electricity_consumption_price_24h_forecast.state.split(',')|count))
          }},\"soc_init\":{{states('sensor.battery_batterijpercentage')|float(0)/100}},\"soc_final\":0.9}' http://localhost:5000/action/naive-mpc-optim"
```

Resulting in this:

<img width="1397" alt="Scherm­afbeelding 2024-05-01 om 19 44 22" src="https://github.com/davidusb-geek/emhass-add-on/assets/81705450/be7ebf1d-29ca-4884-8ed4-c6204f362129">
davidusb-geek commented 6 months ago

It is hard to say without more information about your config. But if your \"soc_final\":0.9 is always set to that value it can be problematic? Otherwise your real SOC seems to follow quite well the forecasted SOC, what is the issue in that graph?

davidusb-geek commented 6 months ago

What is your MPC frequency. This problem may (probably) arise if two MPC calls are really close to each other (< 1 min). This needs testing to confirm.

RikBast commented 6 months ago

It is hard to say without more information about your config. But if your \"soc_final\":0.9 is always set to that value it can be problematic? Otherwise your real SOC seems to follow quite well the forecasted SOC, what is the issue in that graph?

Maybe I understood the concept of soc_final wrong, isn't this the target SOC you want to reach? Issue with the graph are the prediction spikes.

Here is the config:

logging_level: INFO
data_path: default
costfun: profit
sensor_power_photovoltaics: sensor.inverter_ingangsvermogen
sensor_power_load_no_var_loads: sensor.power_load_no_var_loads
set_total_pv_sell: false
set_nocharge_from_grid: false
set_nodischarge_to_grid: false
maximum_power_from_grid: 6000
maximum_power_to_grid: 6000
number_of_deferrable_loads: 1
list_nominal_power_of_deferrable_loads:
  - nominal_power_of_deferrable_loads: 0
list_operating_hours_of_each_deferrable_load:
  - operating_hours_of_each_deferrable_load: 2
list_start_timesteps_of_each_deferrable_load:
  - start_timesteps_of_each_deferrable_load: 0
list_end_timesteps_of_each_deferrable_load:
  - end_timesteps_of_each_deferrable_load: 0
list_peak_hours_periods_start_hours:
  - peak_hours_periods_start_hours: "10:00"
list_peak_hours_periods_end_hours:
  - peak_hours_periods_end_hours: "11:30"
list_treat_deferrable_load_as_semi_cont:
  - treat_deferrable_load_as_semi_cont: true
list_set_deferrable_load_single_constant:
  - set_deferrable_load_single_constant: false
load_peak_hours_cost: 0.1907
load_offpeak_hours_cost: 0.1419
photovoltaic_production_sell_price: 0.065
list_pv_module_model:
  - pv_module_model: JA_Solar_JAM72S01_385_PR
  - pv_module_model: JA_Solar_JAM72S01_385_PR
  - pv_module_model: JA_Solar_JAM72S01_385_PR
list_pv_inverter_model:
  - pv_inverter_model: Huawei_Technologies_Co___Ltd___SUN2000_11_4KTL_USL0__240V_
  - pv_inverter_model: Huawei_Technologies_Co___Ltd___SUN2000_11_4KTL_USL0__240V_
  - pv_inverter_model: Huawei_Technologies_Co___Ltd___SUN2000_11_4KTL_USL0__240V_
list_surface_tilt:
  - surface_tilt: 35
  - surface_tilt: 35
  - surface_tilt: 15
list_surface_azimuth:
  - surface_azimuth: 90
  - surface_azimuth: 270
  - surface_azimuth: 180
list_modules_per_string:
  - modules_per_string: 6
  - modules_per_string: 6
  - modules_per_string: 13
list_strings_per_inverter:
  - strings_per_inverter: 1
  - strings_per_inverter: 1
  - strings_per_inverter: 1
set_use_battery: true
battery_nominal_energy_capacity: 15000
battery_discharge_power_max: 5000
battery_charge_power_max: 5000
set_battery_dynamic: true
battery_minimum_state_of_charge: 0.12
battery_maximum_state_of_charge: 1
optimization_time_step: 60
battery_discharge_efficiency: 0.92
battery_charge_efficiency: 0.92
method_ts_round: nearest
battery_target_state_of_charge: 0.9
RikBast commented 6 months ago

What is your MPC frequency. This problem may (probably) arise if two MPC calls are really close to each other (< 1 min). This needs testing to confirm.

Calls are done every 5 minutes

RikBast commented 6 months ago

After changing some settings I still get the error once in a while:

2024-05-02 11:30:00,455 - web_server - INFO - Passed runtime parameters: {'load_cost_forecast': [14.7156, 13.7255, 13.399, 13.4096, 13.9481, 17.3263, 18.9418, 20.129, 21.2759, 21.5261, 20.5063, 19.8385], 'prod_price_forecast': [0.336, -0.598, -0.906, -0.896, -0.388, 2.799, 4.323, 5.443, 6.525, 6.761, 5.799, 5.169], 'prediction_horizon': 12, 'alpha': 1, 'beta': 0, 'soc_init': 0.28, 'soc_final': 0.12} 2024-05-02 11:30:00,457 - web_server - INFO - >> Setting input data dict 2024-05-02 11:30:00,457 - web_server - INFO - Setting up needed data 2024-05-02 11:30:00,476 - web_server - INFO - Retrieve hass get data method initiated... 2024-05-02 11:30:00,751 - web_server - INFO - Retrieving weather forecast data using method = scrapper 2024-05-02 11:30:01,796 - web_server - INFO - Retrieving data from hass for load forecast using method = naive 2024-05-02 11:30:01,797 - web_server - INFO - Retrieve hass get data method initiated... 2024-05-02 11:30:02,310 - web_server - ERROR - Exception on /action/naive-mpc-optim [POST] Traceback (most recent call last): File "/usr/local/lib/python3.11/dist-packages/flask/app.py", line 1463, in wsgi_app response = self.full_dispatch_request() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/dist-packages/flask/app.py", line 872, in full_dispatch_request rv = self.handle_user_exception(e) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/dist-packages/flask/app.py", line 870, in full_dispatch_request rv = self.dispatch_request() ^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/dist-packages/flask/app.py", line 855, in dispatch_request return self.ensure_sync(self.view_functions[rule.endpoint])(*view_args) # type: ignore[no-any-return] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/dist-packages/emhass/web_server.py", line 108, in action_call input_data_dict = set_input_data_dict(config_path, str(data_path), costfun, ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/dist-packages/emhass/command_line.py", line 129, in set_input_data_dict df_input_data_dayahead = utils.set_df_index_freq(df_input_data_dayahead) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/dist-packages/emhass/utils.py", line 687, in set_df_index_freq df = df.asfreq(sampling) ^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/dist-packages/pandas/core/frame.py", line 10971, in asfreq return super().asfreq( ^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/dist-packages/pandas/core/generic.py", line 8347, in asfreq return asfreq( ^^^^^^^ File "/usr/local/lib/python3.11/dist-packages/pandas/core/resample.py", line 2232, in asfreq dti = date_range(obj.index.min(), obj.index.max(), freq=freq) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/dist-packages/pandas/core/indexes/datetimes.py", line 945, in date_range dtarr = DatetimeArray._generate_range( ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/dist-packages/pandas/core/arrays/datetimes.py", line 446, in _generate_range i8values = generate_regular_range(start, end, periods, freq, unit=unit) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/dist-packages/pandas/core/arrays/_ranges.py", line 68, in generate_regular_range e = b + (iend - b) // stride stride + stride // 2 + 1


ZeroDivisionError: integer division or modulo by zero
2024-05-02 11:30:02,325 - web_server - INFO - Passed runtime parameters: {}
2024-05-02 11:30:02,325 - web_server - INFO -  >> Setting input data dict
2024-05-02 11:30:02,325 - web_server - INFO - Setting up needed data
2024-05-02 11:30:02,327 - web_server - INFO -  >> Publishing data...
2024-05-02 11:30:02,327 - web_server - INFO - Publishing data to HASS instance
2024-05-02 11:30:02,338 - web_server - INFO - Successfully posted to sensor.p_pv_forecast = 4033.28
2024-05-02 11:30:02,341 - web_server - INFO - Successfully posted to sensor.p_load_forecast = 228.65
2024-05-02 11:30:02,344 - web_server - INFO - Successfully posted to sensor.p_deferrable0 = 0.0
2024-05-02 11:30:02,347 - web_server - INFO - Successfully posted to sensor.p_batt_forecast = -3804.63
2024-05-02 11:30:02,351 - web_server - INFO - Successfully posted to sensor.soc_batt_forecast = 49.68
2024-05-02 11:30:02,354 - web_server - INFO - Successfully posted to sensor.p_grid_forecast = 0.0
2024-05-02 11:30:02,357 - web_server - INFO - Successfully posted to sensor.total_cost_fun_value = 94.26
2024-05-02 11:30:02,359 - web_server - INFO - Successfully posted to sensor.optim_status = Optimal
2024-05-02 11:30:02,362 - web_server - INFO - Successfully posted to sensor.unit_load_cost = 13.7255
2024-05-02 11:30:02,365 - web_server - INFO - Successfully posted to sensor.unit_prod_price = -0.598
davidusb-geek commented 6 months ago

isn't this the target SOC you want to reach?

That's what it is yes.

Calls are done every 5 minutes

It should be fine to call MPC every 5 mins.

I have not seen this type of error before, we need to figure out a way to reproduce this. Just a guess about databases. How are you managing your HA database/recorder? Are you using the include entities option of the recorder to list the entities that you want to keep in the database? If yes, is the sensor sensor.power_load_no_var_loads included in that list?

RikBast commented 6 months ago

Hi, all is on default for the HA database/recorder. I am runing HA almost for a month now, sensor_power_load_no_var_loads has about 25 days of history only. But I see a lot of spikes (also < 0)

Schermafbeelding 2024-05-02 090246

This sensor is built up like this:

{{states('sensor.inverter_werkelijk_vermogen') | float(default=0) - states('sensor.power_meter_vermogen') | float(default=0) - states('sensor.waskeuken_wasdroger_waskeuken_618_power') | float(default=0) - states('sensor.waskeuken_wasmachine_waskeuken_611_power') | float(default=0)}}

It takes the active power of the Huawei inverter and the power meter active power is substracted, this give the power load no var, I then substract the deferrable loads of the washing machine and the tumble dryer

davidusb-geek commented 6 months ago

Those spikes in the sensor are probably the source of the problems. Try to use some filtering before building the sensor. Up until Apr22 it was a nice smooth curve with no spikes, what changed there?

gieljnssns commented 6 months ago

I think, looking at that picture, before 22-4 the data comes from the long term statistics db.

gieljnssns commented 6 months ago

But I see a lot of spikes (also < 0)

You should check your sensor from not going negative

- trigger:
    - platform: time_pattern
      seconds: "/10"
  sensor:
    - name: Huidig verbruik zonder wp
      unique_id: 664ab9ff-3875-4a45-b53a-685b7a8f7f96
      unit_of_measurement: "W"
      device_class: power
      state: >
        {% if (states("sensor.huidig_verbruik") | float(default=0) -
            states("sensor.wasmachien_vermogen") | float(default=0) -
            states("sensor.droogkast_vermogen") | float(default=0) -
            states("sensor.warmtepompboiler_huidig_verbruik") | float(default=0) -
            states("sensor.warmtepomp_huidig_verbruik") | float(default=0) -
            states("sensor.afwasmachien_vermogen") | float(default=0)) | round(1) > 0 %}
            {{ (states("sensor.huidig_verbruik") | float(default=0) -
                states("sensor.wasmachien_vermogen") | float(default=0) -
                states("sensor.droogkast_vermogen") | float(default=0) -
                states("sensor.warmtepompboiler_huidig_verbruik") | float(default=0) -
                states("sensor.warmtepomp_huidig_verbruik") | float(default=0) -
                states("sensor.afwasmachien_vermogen") | float(default=0)) | round(1)}}
        {% else  %}
            {{ 0 | float(default=0) }}
        {% endif %}
      availability: >
        {{ is_number(states('sensor.huidig_verbruik')) }}
RikBast commented 6 months ago

I think, looking at that picture, before 22-4 the data comes from the long term statistics db.

Yes, correct, I just had a look

RikBast commented 6 months ago

But I see a lot of spikes (also < 0)

You should check your sensor from not going negative

- trigger:
    - platform: time_pattern
      seconds: "/10"
  sensor:
    - name: Huidig verbruik zonder wp
      unique_id: 664ab9ff-3875-4a45-b53a-685b7a8f7f96
      unit_of_measurement: "W"
      device_class: power
      state: >
        {% if (states("sensor.huidig_verbruik") | float(default=0) -
            states("sensor.wasmachien_vermogen") | float(default=0) -
            states("sensor.droogkast_vermogen") | float(default=0) -
            states("sensor.warmtepompboiler_huidig_verbruik") | float(default=0) -
            states("sensor.warmtepomp_huidig_verbruik") | float(default=0) -
            states("sensor.afwasmachien_vermogen") | float(default=0)) | round(1) > 0 %}
            {{ (states("sensor.huidig_verbruik") | float(default=0) -
                states("sensor.wasmachien_vermogen") | float(default=0) -
                states("sensor.droogkast_vermogen") | float(default=0) -
                states("sensor.warmtepompboiler_huidig_verbruik") | float(default=0) -
                states("sensor.warmtepomp_huidig_verbruik") | float(default=0) -
                states("sensor.afwasmachien_vermogen") | float(default=0)) | round(1)}}
        {% else  %}
            {{ 0 | float(default=0) }}
        {% endif %}
      availability: >
        {{ is_number(states('sensor.huidig_verbruik')) }}

Thank you, I will try to implement this, but still wondering the cause for going negative. I don't see it in the Huawei data.

gieljnssns commented 6 months ago

this could happen when the sensors you use in your template don't update on the same time.

RikBast commented 6 months ago

this could happen when the sensors you use in your template don't update on the same time.

I add this to configuration.yaml I presume?

gieljnssns commented 6 months ago

What do you wan't to add?

Paste this in your developer tools

{{states('sensor.inverter_werkelijk_vermogen') | float(default=0) - 
    states('sensor.power_meter_vermogen') | float(default=0) - 
    states('sensor.waskeuken_wasdroger_waskeuken_618_power') | float(default=0) - 
    states('sensor.waskeuken_wasmachine_waskeuken_611_power') | float(default=0)}}
{% if (states('sensor.inverter_werkelijk_vermogen') | float(default=0) - 
        states('sensor.power_meter_vermogen') | float(default=0) - 
        states('sensor.waskeuken_wasdroger_waskeuken_618_power') | float(default=0) - 
        states('sensor.waskeuken_wasmachine_waskeuken_611_power') | float(default=0)) > 0 %}
        {{states('sensor.inverter_werkelijk_vermogen') | float(default=0) - 
          states('sensor.power_meter_vermogen') | float(default=0) - 
          states('sensor.waskeuken_wasdroger_waskeuken_618_power') | float(default=0) - 
          states('sensor.waskeuken_wasmachine_waskeuken_611_power') | float(default=0)}}
{% else %}
  0
{% endif %}
{{states('sensor.inverter_werkelijk_vermogen')}}
{{states('sensor.power_meter_vermogen')}}
{{states('sensor.waskeuken_wasdroger_waskeuken_618_power')}}
{{states('sensor.waskeuken_wasmachine_waskeuken_611_power')}}
RikBast commented 6 months ago

What do you wan't to add?

Paste this in your developer tools

{{states('sensor.inverter_werkelijk_vermogen') | float(default=0) - 
    states('sensor.power_meter_vermogen') | float(default=0) - 
    states('sensor.waskeuken_wasdroger_waskeuken_618_power') | float(default=0) - 
    states('sensor.waskeuken_wasmachine_waskeuken_611_power') | float(default=0)}}
{% if (states('sensor.inverter_werkelijk_vermogen') | float(default=0) - 
        states('sensor.power_meter_vermogen') | float(default=0) - 
        states('sensor.waskeuken_wasdroger_waskeuken_618_power') | float(default=0) - 
        states('sensor.waskeuken_wasmachine_waskeuken_611_power') | float(default=0)) > 0 %}
        {{states('sensor.inverter_werkelijk_vermogen') | float(default=0) - 
          states('sensor.power_meter_vermogen') | float(default=0) - 
          states('sensor.waskeuken_wasdroger_waskeuken_618_power') | float(default=0) - 
          states('sensor.waskeuken_wasmachine_waskeuken_611_power') | float(default=0)}}
{% else %}
  0
{% endif %}
{{states('sensor.inverter_werkelijk_vermogen')}}
{{states('sensor.power_meter_vermogen')}}
{{states('sensor.waskeuken_wasdroger_waskeuken_618_power')}}
{{states('sensor.waskeuken_wasmachine_waskeuken_611_power')}}

In developers tools --> Templates it nicely calculates the power_no_var_loads:


247.0

        247.0

244
-5
0.7
1.3
RikBast commented 6 months ago

What do you wan't to add?

Paste this in your developer tools

{{states('sensor.inverter_werkelijk_vermogen') | float(default=0) - 
    states('sensor.power_meter_vermogen') | float(default=0) - 
    states('sensor.waskeuken_wasdroger_waskeuken_618_power') | float(default=0) - 
    states('sensor.waskeuken_wasmachine_waskeuken_611_power') | float(default=0)}}
{% if (states('sensor.inverter_werkelijk_vermogen') | float(default=0) - 
        states('sensor.power_meter_vermogen') | float(default=0) - 
        states('sensor.waskeuken_wasdroger_waskeuken_618_power') | float(default=0) - 
        states('sensor.waskeuken_wasmachine_waskeuken_611_power') | float(default=0)) > 0 %}
        {{states('sensor.inverter_werkelijk_vermogen') | float(default=0) - 
          states('sensor.power_meter_vermogen') | float(default=0) - 
          states('sensor.waskeuken_wasdroger_waskeuken_618_power') | float(default=0) - 
          states('sensor.waskeuken_wasmachine_waskeuken_611_power') | float(default=0)}}
{% else %}
  0
{% endif %}
{{states('sensor.inverter_werkelijk_vermogen')}}
{{states('sensor.power_meter_vermogen')}}
{{states('sensor.waskeuken_wasdroger_waskeuken_618_power')}}
{{states('sensor.waskeuken_wasmachine_waskeuken_611_power')}}

Sorry for asking, but how do I implement this constraint? I am new to HA so trying to find my way around the system. Thank you

gieljnssns commented 6 months ago

Where have you defined your sensor.power_no_var_loads? And what is sensor.inverter_werkelijk_vermogen? Is this the sensor that holds your household power consumption? sensor.power_meter_vermogen is this one of your deferrable loads?

Your sensor.power_load_no_var_loads should be, the household power consumption sensor in Watts from Home Assistant. The deferrable loads that we will want to include in the optimization problem should be substracted from this sensor in HASS.

RikBast commented 6 months ago

Where have you defined your sensor.power_no_var_loads? And what is sensor.inverter_werkelijk_vermogen? Is this the sensor that holds your household power consumption? sensor.power_meter_vermogen is this one of your deferrable loads?

Your sensor.power_load_no_var_loads should be, the household power consumption sensor in Watts from Home Assistant. The deferrable loads that we will want to include in the optimization problem should be substracted from this sensor in HASS.

I defined sensor.power_no_var_loads as a template helper:

Scherm­afbeelding 2024-05-11 om 13 16 52 Scherm­afbeelding 2024-05-11 om 13 17 03

State Template:

{{(states('sensor.inverter_werkelijk_vermogen') | float(default=0) - states('sensor.power_meter_vermogen') | float(default=0)) - states('sensor.waskeuken_wasdroger_waskeuken_618_power') | float(default=0) - states('sensor.waskeuken_wasmachine_waskeuken_611_power') | float(default=0)}}

sensor.inverter_werkelijk_vermogen comes from the Huawei inverter, sensor.power_meter_vermogen comes for the Huawei power meter. I use the Huawei integration available in HA.

gieljnssns commented 6 months ago

But sensor.inverter_werkelijk_vermogen is your PV generation? And what is sensor.power_meter_vermogen exactly measuring?

RikBast commented 6 months ago

But sensor.inverter_werkelijk_vermogen is your PV generation? And what is sensor.power_meter_vermogen exactly measuring?

They both measure the active power.

sensor.inverter_werkelijk_vermogen
Scherm­afbeelding 2024-05-11 om 14 08 13
sensor.power_meter_vermogen
Scherm­afbeelding 2024-05-11 om 14 09 03

The difference between the two = house hold power

2600 - 64 = 2536W

gieljnssns commented 6 months ago

Then I would try to change the state template to

{% if (states('sensor.inverter_werkelijk_vermogen') | float(default=0) - 
        states('sensor.power_meter_vermogen') | float(default=0) - 
        states('sensor.waskeuken_wasdroger_waskeuken_618_power') | float(default=0) - 
        states('sensor.waskeuken_wasmachine_waskeuken_611_power') | float(default=0)) > 0 %}
        {{states('sensor.inverter_werkelijk_vermogen') | float(default=0) - 
          states('sensor.power_meter_vermogen') | float(default=0) - 
          states('sensor.waskeuken_wasdroger_waskeuken_618_power') | float(default=0) - 
          states('sensor.waskeuken_wasmachine_waskeuken_611_power') | float(default=0)}}
{% else %}
  0
{% endif %}
RikBast commented 6 months ago

{% if (states('sensor.inverter_werkelijk_vermogen') | float(default=0) - states('sensor.power_meter_vermogen') | float(default=0) - states('sensor.waskeuken_wasdroger_waskeuken_618_power') | float(default=0) - states('sensor.waskeuken_wasmachine_waskeuken_611_power') | float(default=0)) > 0 %} {{states('sensor.inverter_werkelijk_vermogen') | float(default=0) - states('sensor.power_meter_vermogen') | float(default=0) - states('sensor.waskeuken_wasdroger_waskeuken_618_power') | float(default=0) - states('sensor.waskeuken_wasmachine_waskeuken_611_power') | float(default=0)}} {% else %} 0 {% endif %}

OK, I changed it, works it seems. Thank you for the support

RikBast commented 6 months ago

I sometime still get an error:

2024-05-12 09:30:00,354 - web_server - INFO - Passed runtime parameters: {'load_cost_forecast': [10.7575, 1.6267, 0.6949, -1.3085, -0.8982, 4.3307, 10.324, 13.3217, 15.7766, 18.8019, 21.7794, 19.8057, 18.4478, 17.4514], 'prod_price_forecast': [-3.398, -12.012, -12.891, -14.781, -14.394, -9.461, -3.807, -0.979, 1.337, 4.191, 7.0, 5.138, 3.857, 2.917], 'load_power_forecast': [297, 200, 400, 200, 800, 2200, 300, 200, 1500, 200, 2800, -2100, 0, 200, 200, 300, 300, 400, 200, 200, 1500, 200, 200, 400, 500, 500, 400, 500, 300, 300, 500, 400, 400, 500, 300, 200, 200, 300, 200, 200, 300, 500, 400, 100, 300, 400, 300, 300], 'prediction_horizon': 14, 'alpha': 1, 'beta': 0, 'soc_init': 0.22, 'soc_final': 0.12}
2024-05-12 09:30:00,354 - web_server - INFO -  >> Setting input data dict
2024-05-12 09:30:00,354 - web_server - INFO - Setting up needed data
2024-05-12 09:30:00,363 - web_server - INFO - Retrieve hass get data method initiated...
2024-05-12 09:30:00,676 - web_server - INFO - Retrieving weather forecast data using method = scrapper
2024-05-12 09:30:01,742 - web_server - ERROR - Exception on /action/naive-mpc-optim [POST]
Traceback (most recent call last):
  File "/usr/local/lib/python3.11/dist-packages/flask/app.py", line 1463, in wsgi_app
    response = self.full_dispatch_request()
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/flask/app.py", line 872, in full_dispatch_request
    rv = self.handle_user_exception(e)
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/flask/app.py", line 870, in full_dispatch_request
    rv = self.dispatch_request()
         ^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/flask/app.py", line 855, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)  # type: ignore[no-any-return]
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/emhass/web_server.py", line 108, in action_call
    input_data_dict = set_input_data_dict(config_path, str(data_path), costfun,
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/emhass/command_line.py", line 128, in set_input_data_dict
    df_input_data_dayahead = pd.concat([P_PV_forecast, P_load_forecast], axis=1)
                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/pandas/core/reshape/concat.py", line 385, in concat
    return op.get_result()
           ^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/pandas/core/reshape/concat.py", line 592, in get_result
    df = cons(data, index=index, copy=self.copy)
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/pandas/core/frame.py", line 709, in __init__
    mgr = dict_to_mgr(data, index, columns, dtype=dtype, copy=copy, typ=manager)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/pandas/core/internals/construction.py", line 481, in dict_to_mgr
    return arrays_to_mgr(arrays, columns, index, dtype=dtype, typ=typ, consolidate=copy)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/pandas/core/internals/construction.py", line 120, in arrays_to_mgr
    arrays, refs = _homogenize(arrays, index, dtype)
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/pandas/core/internals/construction.py", line 589, in _homogenize
    val = val.reindex(index, copy=False)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/pandas/core/series.py", line 4918, in reindex
    return super().reindex(
           ^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/pandas/core/generic.py", line 5360, in reindex
    return self._reindex_axes(
           ^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/pandas/core/generic.py", line 5375, in _reindex_axes
    new_index, indexer = ax.reindex(
                         ^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/pandas/core/indexes/base.py", line 4275, in reindex
    raise ValueError("cannot reindex on an axis with duplicate labels")
ValueError: cannot reindex on an axis with duplicate labels
2024-05-12 09:30:01,749 - web_server - INFO - Passed runtime parameters: {}
2024-05-12 09:30:01,750 - web_server - INFO -  >> Setting input data dict
2024-05-12 09:30:01,750 - web_server - INFO - Setting up needed data
2024-05-12 09:30:01,750 - web_server - INFO -  >> Publishing data...
2024-05-12 09:30:01,750 - web_server - INFO - Publishing data to HASS instance
2024-05-12 09:30:01,756 - web_server - INFO - Successfully posted to sensor.p_pv_forecast = 2667.34
2024-05-12 09:30:01,759 - web_server - INFO - Successfully posted to sensor.p_load_forecast = 300
2024-05-12 09:30:01,763 - web_server - INFO - Successfully posted to sensor.p_deferrable0 = 0.0
2024-05-12 09:30:01,766 - web_server - INFO - Successfully posted to sensor.p_deferrable1 = 2500.0
2024-05-12 09:30:01,768 - web_server - INFO - Successfully posted to sensor.p_batt_forecast = 132.66
2024-05-12 09:30:01,773 - web_server - INFO - Successfully posted to sensor.soc_batt_forecast = 16.29
2024-05-12 09:30:01,776 - web_server - INFO - Successfully posted to sensor.p_grid_forecast = 0.0
2024-05-12 09:30:01,779 - web_server - INFO - Successfully posted to sensor.total_cost_fun_value = 79.19
2024-05-12 09:30:01,781 - web_server - INFO - Successfully posted to sensor.optim_status = Optimal
2024-05-12 09:30:01,784 - web_server - INFO - Successfully posted to sensor.unit_load_cost = 1.6267
2024-05-12 09:30:01,787 - web_server - INFO - Successfully posted to sensor.unit_prod_price = -12.012

Maybe because there is still one negative number for the load_power_forecast?

EDIT: No, that's not the cause, here below the logging with all positive values.

2024-05-12 10:30:00,354 - web_server - INFO - Passed runtime parameters: {'load_cost_forecast': [1.6267, 0.6949, -1.3085, -0.8982, 4.3307, 10.324, 13.3217, 15.7766, 18.8019, 21.7794, 19.8057, 18.4478, 17.4514], 'prod_price_forecast': [-12.012, -12.891, -14.781, -14.394, -9.461, -3.807, -0.979, 1.337, 4.191, 7.0, 5.138, 3.857, 2.917], 'load_power_forecast': [225, 200, 800, 2200, 300, 200, 1500, 200, 2800, 2100, 0, 200, 200, 300, 300, 400, 200, 200, 1500, 200, 200, 400, 500, 500, 400, 500, 300, 300, 500, 400, 400, 500, 300, 200, 200, 300, 200, 200, 300, 500, 400, 100, 300, 400, 300, 300, 400, 200], 'prediction_horizon': 13, 'alpha': 1, 'beta': 0, 'soc_init': 0.24, 'soc_final': 0.12}
2024-05-12 10:30:00,355 - web_server - INFO -  >> Setting input data dict
2024-05-12 10:30:00,355 - web_server - INFO - Setting up needed data
2024-05-12 10:30:00,360 - web_server - INFO - Retrieve hass get data method initiated...
2024-05-12 10:30:00,812 - web_server - INFO - Retrieving weather forecast data using method = scrapper
2024-05-12 10:30:02,142 - web_server - ERROR - Exception on /action/naive-mpc-optim [POST]
Traceback (most recent call last):
  File "/usr/local/lib/python3.11/dist-packages/flask/app.py", line 1463, in wsgi_app
    response = self.full_dispatch_request()
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/flask/app.py", line 872, in full_dispatch_request
    rv = self.handle_user_exception(e)
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/flask/app.py", line 870, in full_dispatch_request
    rv = self.dispatch_request()
         ^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/flask/app.py", line 855, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)  # type: ignore[no-any-return]
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/emhass/web_server.py", line 108, in action_call
    input_data_dict = set_input_data_dict(config_path, str(data_path), costfun,
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/emhass/command_line.py", line 128, in set_input_data_dict
    df_input_data_dayahead = pd.concat([P_PV_forecast, P_load_forecast], axis=1)
                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/pandas/core/reshape/concat.py", line 385, in concat
    return op.get_result()
           ^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/pandas/core/reshape/concat.py", line 592, in get_result
    df = cons(data, index=index, copy=self.copy)
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/pandas/core/frame.py", line 709, in __init__
    mgr = dict_to_mgr(data, index, columns, dtype=dtype, copy=copy, typ=manager)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/pandas/core/internals/construction.py", line 481, in dict_to_mgr
    return arrays_to_mgr(arrays, columns, index, dtype=dtype, typ=typ, consolidate=copy)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/pandas/core/internals/construction.py", line 120, in arrays_to_mgr
    arrays, refs = _homogenize(arrays, index, dtype)
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/pandas/core/internals/construction.py", line 589, in _homogenize
    val = val.reindex(index, copy=False)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/pandas/core/series.py", line 4918, in reindex
    return super().reindex(
           ^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/pandas/core/generic.py", line 5360, in reindex
    return self._reindex_axes(
           ^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/pandas/core/generic.py", line 5375, in _reindex_axes
    new_index, indexer = ax.reindex(
                         ^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/pandas/core/indexes/base.py", line 4275, in reindex
    raise ValueError("cannot reindex on an axis with duplicate labels")
ValueError: cannot reindex on an axis with duplicate labels
2024-05-12 10:30:02,150 - web_server - INFO - Passed runtime parameters: {}
2024-05-12 10:30:02,151 - web_server - INFO -  >> Setting input data dict
2024-05-12 10:30:02,151 - web_server - INFO - Setting up needed data
2024-05-12 10:30:02,151 - web_server - INFO -  >> Publishing data...
2024-05-12 10:30:02,151 - web_server - INFO - Publishing data to HASS instance
2024-05-12 10:30:02,158 - web_server - INFO - Successfully posted to sensor.p_pv_forecast = 2940.27
2024-05-12 10:30:02,160 - web_server - INFO - Successfully posted to sensor.p_load_forecast = 400
2024-05-12 10:30:02,164 - web_server - INFO - Successfully posted to sensor.p_deferrable0 = 0.0
2024-05-12 10:30:02,166 - web_server - INFO - Successfully posted to sensor.p_deferrable1 = 2500.0
2024-05-12 10:30:02,169 - web_server - INFO - Successfully posted to sensor.p_batt_forecast = -4015.34
2024-05-12 10:30:02,174 - web_server - INFO - Successfully posted to sensor.soc_batt_forecast = 47.02
2024-05-12 10:30:02,177 - web_server - INFO - Successfully posted to sensor.p_grid_forecast = 3975.08
2024-05-12 10:30:02,179 - web_server - INFO - Successfully posted to sensor.total_cost_fun_value = 60.21
2024-05-12 10:30:02,181 - web_server - INFO - Successfully posted to sensor.optim_status = Optimal
2024-05-12 10:30:02,185 - web_server - INFO - Successfully posted to sensor.unit_load_cost = 0.6949
2024-05-12 10:30:02,188 - web_server - INFO - Successfully posted to sensor.unit_prod_price = -12.891