EMHASS: An Energy Management for Home Assistant

For the moment I use solaredge-modbus-multi to communicate with my inverter. Its also trough Modbus TCP.

And this is the flow I’m using:

[{"id":"cb29cf709eb1ce07","type":"api-call-service","z":"0af73310326caf4c","name":"solaredge storage control: remote control","server":"1f859cbc.9f25a3","version":5,"debugenabled":false,"domain":"select","service":"select_option","areaId":[],"deviceId":[],"entityId":["select.solaredge_i1_storage_control_mode"],"data":"{\"option\":\"Remote Control\"}","dataType":"jsonata","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":740,"y":260,"wires":[["c0cb45f866fa6d67"]]},{"id":"1f859cbc.9f25a3","type":"server","name":"Home Assistant","version":5,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":true,"heartbeat":false,"heartbeatInterval":"30","areaSelector":"friendlyName","deviceSelector":"friendlyName","entitySelector":"friendlyName","statusSeparator":"at: ","statusYear":"hidden","statusMonth":"short","statusDay":"numeric","statusHourCycle":"h23","statusTimeFormat":"h:m","enableGlobalContextStore":true}]

But I can try the way you explain, maybe that should work better.

Node red doesnt expose the calls correctly,

I have 3 solaredge inverters that do not accept the calls, i use automations with a trigger, then use the beautiful flow of node red to still achieve what i want the call to be but then its activated over automation.

Has anyone worked out how to prioritise battery charge so the curtailment isnt so rough,

I find the system turning on and off through the day when it shouldnt need too,

I would expect the batteries to be full charge then curtail if its negative feed in

There should be a way to control solaredge inverter directry from node-red without passing control back into HA.

If the modbus contrib doesn’t do it what does node-red-contrib-solaredge do and these other contribs:

Here’s what chatGPT says about it:
Yes, there are known issues when using node-red-contrib-modbus with SolarEdge inverters. Some users have reported challenges, such as timeouts, communication errors, or incompatibilities, when trying to control or read data from SolarEdge inverters via Modbus TCP using Node-RED. Below are common issues and potential solutions or workarounds:

Common Issues:

  1. Connection Timeouts: The Modbus connection may time out if SolarEdge inverters are busy processing data or if the polling rate is too fast.

  2. Unit ID Confusion: SolarEdge inverters use Unit ID 1 by default for Modbus communication. Setting the wrong Unit ID can prevent the commands from reaching the inverter.

  3. Modbus Register Address Offsets: Some Modbus clients add an offset to register addresses, so a register like 62852 might need to be referenced as 62851 or 62853, depending on the implementation.

  4. Poll Rate Issues: Polling too frequently can overwhelm the inverter’s Modbus communication stack, leading to dropped connections.

Working Configuration for Node-RED:

To avoid issues with node-red-contrib-modbus and SolarEdge inverters, follow these guidelines when controlling the battery’s charge and discharge power registers (62852 for charging and 62853 for discharging):

1. Modbus Timeout and Retries:

  • Client Timeout: Set a relatively high timeout in the Modbus client (e.g., 5000 ms) to give the SolarEdge inverter enough time to respond.
  • Reconnect Timeout: Set the reconnect timeout to around 2000 ms if a connection is dropped.
  • Retries: Set retries to 3 or 5 to ensure commands are sent even when there’s transient communication failure.

2. Modbus Write Configuration:

  • Data Type: Use the Holding Register type, as SolarEdge expects this for control commands.
  • Register Addressing: Directly target registers 62852 and 62853. Make sure your Modbus client does not add an offset. If it does, adjust the addresses accordingly (e.g., try 62851 or 62853 if you encounter errors).

3. Modbus Polling Frequency:

  • For reading data, ensure that the polling frequency is set to something moderate, like every 5 or 10 seconds, rather than continuous fast polling. For writing (charge/discharge commands), ensure that you don’t send commands too frequently to avoid overwhelming the inverter.

4. Avoid Overwriting Control Registers:

  • Some SolarEdge models may have conflicts when you attempt to write to both charge and discharge power registers simultaneously. Ensure you’re only writing to one register at a time (e.g., either to charge or discharge, but not both).

Example Node-RED Flow for Charge/Discharge Control:

[
    {
        "id": "modbus_write_charge",
        "type": "modbus-write",
        "z": "flow1",
        "name": "Charge Power",
        "topic": "",
        "showStatusActivities": false,
        "showErrors": false,
        "unitid": "1",
        "dataType": "HoldingRegister",
        "adr": "62852",
        "quantity": "1",
        "server": "solaredge_modbus_server",
        "payload": "[1000]",  // Charge at 1kW (1000W)
        "payloadType": "array",
        "x": 560,
        "y": 260,
        "wires": [
            [],
            []
        ]
    },
    {
        "id": "modbus_write_discharge",
        "type": "modbus-write",
        "z": "flow1",
        "name": "Discharge Power",
        "topic": "",
        "showStatusActivities": false,
        "showErrors": false,
        "unitid": "1",
        "dataType": "HoldingRegister",
        "adr": "62853",
        "quantity": "1",
        "server": "solaredge_modbus_server",
        "payload": "[500]",  // Discharge at 0.5kW (500W)
        "payloadType": "array",
        "x": 560,
        "y": 360,
        "wires": [
            [],
            []
        ]
    },
    {
        "id": "inject_charge",
        "type": "inject",
        "z": "flow1",
        "name": "Set Charge Power",
        "props": [
            {
                "p": "payload",
                "v": "2000",  // Example charge rate: 2kW (2000W)
                "vt": "num"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "x": 200,
        "y": 260,
        "wires": [
            [
                "function_charge_power"
            ]
        ]
    },
    {
        "id": "inject_discharge",
        "type": "inject",
        "z": "flow1",
        "name": "Set Discharge Power",
        "props": [
            {
                "p": "payload",
                "v": "1000",  // Example discharge rate: 1kW (1000W)
                "vt": "num"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "x": 200,
        "y": 360,
        "wires": [
            [
                "function_discharge_power"
            ]
        ]
    },
    {
        "id": "function_charge_power",
        "type": "function",
        "z": "flow1",
        "name": "Convert kW to Modbus (Charge)",
        "func": "let charge_kW = msg.payload;\nlet charge_W = charge_kW * 1000;\nmsg.payload = [charge_W];\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 380,
        "y": 260,
        "wires": [
            [
                "modbus_write_charge"
            ]
        ]
    },
    {
        "id": "function_discharge_power",
        "type": "function",
        "z": "flow1",
        "name": "Convert kW to Modbus (Discharge)",
        "func": "let discharge_kW = msg.payload;\nlet discharge_W = discharge_kW * 1000;\nmsg.payload = [discharge_W];\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 380,
        "y": 360,
        "wires": [
            [
                "modbus_write_discharge"
            ]
        ]
    },
    {
        "id": "solaredge_modbus_server",
        "type": "modbus-client",
        "name": "SolarEdge Modbus",
        "clienttype": "tcp",
        "bufferCommands": true,
        "stateLogEnabled": false,
        "tcpHost": "192.168.1.100",
        "tcpPort": "1502",
        "unit_id": 1,
        "clientTimeout": 5000,
        "reconnectTimeout": 2000
    }
]

Configuration Notes:

  1. Modbus Register Addresses:

    • 62852 for charging power (in watts).
    • 62853 for discharging power (in watts).
  2. Payload: The payload is sent in an array format where the power is expressed in watts. For example, a charge rate of 2 kW will be sent as [2000].

Further Considerations:

  • Make sure to validate the behavior of your inverter and battery system when writing to these registers. SolarEdge firmware updates or changes to battery management may impact the functionality of these registers.
  • Test carefully to avoid setting conflicting values (e.g., trying to charge and discharge at the same time).

By following these configuration tips and best practices, you should be able to control the charging and discharging of your BYD battery via the SolarEdge inverter with minimal issues using Node-RED.

Which sensors should have long statistics on besides sensor.power_load_novar_loads to make EMHASS work best

Actually the one you mention doesn’t require any stats, rather the ones you use to create it need stats.
It depends if you use machine learning (as much as possible but you have to check effectiveness yourself) or day ahead, BTW 24h minimum.

Hello,
I am currently trying to get the mlforecaster working. The normal MPC optimisation works fine but when I try to run the model fit function one of two things happens:

  1. when setting days to retrieve to 3:
2024-10-04 18:26:55,003 - web_server - INFO - Passed runtime parameters: {'days_to_retrieve': 3, 'var_model': 'sensor.power_load_no_var_loads', 'num_lags': 48}
2024-10-04 18:26:55,003 - web_server - INFO -  >> Setting input data dict
2024-10-04 18:26:55,003 - web_server - INFO - Setting up needed data
2024-10-04 18:26:55,007 - web_server - INFO - Retrieve hass get data method initiated...
2024-10-04 18:26:56,854 - web_server - INFO -  >> Performing a machine learning forecast model fit...
2024-10-04 18:26:56,855 - web_server - INFO - Performing a forecast model fit for load_forecast
2024-10-04 18:26:56,859 - web_server - INFO - Training a KNeighborsRegressor model
2024-10-04 18:26:56,866 - web_server - ERROR - Exception on /action/forecast-model-fit [POST]
Traceback (most recent call last):
  File "/usr/local/lib/python3.11/dist-packages/flask/app.py", line 1473, in wsgi_app
    response = self.full_dispatch_request()
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/flask/app.py", line 882, in full_dispatch_request
    rv = self.handle_user_exception(e)
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/flask/app.py", line 880, in full_dispatch_request
    rv = self.dispatch_request()
         ^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/flask/app.py", line 865, 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 179, in action_call
    df_fit_pred, _, mlf = forecast_model_fit(input_data_dict, app.logger)
                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/emhass/command_line.py", line 498, in forecast_model_fit
    df_pred, df_pred_backtest = mlf.fit(
                                ^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/emhass/machine_learning_forecaster.py", line 153, in fit
    self.forecaster.fit(y=self.data_train[self.var_model],
  File "/usr/local/lib/python3.11/dist-packages/skforecast/ForecasterAutoreg/ForecasterAutoreg.py", line 606, in fit
    data  = self.regressor.predict(X_train),
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/sklearn/neighbors/_regression.py", line 242, in predict
    neigh_ind = self.kneighbors(X, return_distance=False)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/sklearn/neighbors/_base.py", line 835, in kneighbors
    raise ValueError(
ValueError: Expected n_neighbors <= n_samples_fit, but n_neighbors = 5, n_samples_fit = 1, n_samples = 1
  1. when setting the days to 30:
2024-10-04 18:27:34,930 - web_server - INFO - Passed runtime parameters: {'days_to_retrieve': 30, 'var_model': 'sensor.power_load_no_var_loads', 'num_lags': 48}
2024-10-04 18:27:34,930 - web_server - INFO -  >> Setting input data dict
2024-10-04 18:27:34,930 - web_server - INFO - Setting up needed data
2024-10-04 18:27:34,932 - web_server - INFO - Retrieve hass get data method initiated...
2024-10-04 18:27:34,940 - web_server - ERROR - The retrieved JSON is empty, A sensor:sensor.power_load_no_var_loads may have 0 days of history, passed sensor may not be correct, or days to retrieve is set too heigh

the sensor sensor.power_load_no_var_loads has data going back ~300 days so there must be enough data there. Maybe there are some very small gaps in the data because of reboots during updates.

The sensor also works great when doing MPC optimisations. I pass the data into the runtime like @rcruikshank is suggesting in node Red.

Does anyone know what I am missing? Thanks in advance :slight_smile:

What happens when you try to retrieve 1 or 2 days only? Same error?

If your recorder is correctly set then this may be similar to some issues some us faced from time to time with β€œnot available” data.
Missing data because of reboot should not be a problem, if I correctly remember David implemented some interpolation.

To start with I suggest you to set 1 day and in one day try again, so you already have a partial answer to the possible cause of the problem.

Thank you for the fast reply :slight_smile:

when I set the days to one or 2 I get the following error:

2024-10-04 18:44:16,978 - web_server - INFO - Passed runtime parameters: {'days_to_retrieve': 2, 'var_model': 'sensor.power_load_no_var_loads', 'num_lags': 48}
2024-10-04 18:44:16,979 - web_server - INFO -  >> Setting input data dict
2024-10-04 18:44:16,979 - web_server - INFO - Setting up needed data
2024-10-04 18:44:16,983 - web_server - INFO - Retrieve hass get data method initiated...
2024-10-04 18:44:18,286 - web_server - INFO -  >> Performing a machine learning forecast model fit...
2024-10-04 18:44:18,286 - web_server - INFO - Performing a forecast model fit for load_forecast
2024-10-04 18:44:18,292 - web_server - INFO - Training a KNeighborsRegressor model
2024-10-04 18:44:18,294 - web_server - ERROR - Exception on /action/forecast-model-fit [POST]
Traceback (most recent call last):
  File "/usr/local/lib/python3.11/dist-packages/flask/app.py", line 1473, in wsgi_app
    response = self.full_dispatch_request()
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/flask/app.py", line 882, in full_dispatch_request
    rv = self.handle_user_exception(e)
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/flask/app.py", line 880, in full_dispatch_request
    rv = self.dispatch_request()
         ^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/flask/app.py", line 865, 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 179, in action_call
    df_fit_pred, _, mlf = forecast_model_fit(input_data_dict, app.logger)
                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/emhass/command_line.py", line 498, in forecast_model_fit
    df_pred, df_pred_backtest = mlf.fit(
                                ^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/emhass/machine_learning_forecaster.py", line 153, in fit
    self.forecaster.fit(y=self.data_train[self.var_model],
  File "/usr/local/lib/python3.11/dist-packages/skforecast/ForecasterAutoreg/ForecasterAutoreg.py", line 578, in fit
    X_train, y_train = self.create_train_X_y(y=y, exog=exog)
                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/skforecast/ForecasterAutoreg/ForecasterAutoreg.py", line 457, in create_train_X_y
    X_train, y_train = self._create_lags(y=y_values)
                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/skforecast/ForecasterAutoreg/ForecasterAutoreg.py", line 364, in _create_lags
    raise ValueError(
ValueError: The maximum lag (48) must be less than the length of the series (2).

The data is working for MPC optimisation. But that one would probably only need the last day (?)

:wink:
Any elaboration approach (MPC or day ahead) need future load data (let’s say 24h for simplicity).
Naive approach uses past 24h and assumes the same will occur tomorrow, ML uses past X days to train a model and then simulate the load for the next 24h.

I assume you set this so MPC knows which data to use (naive vs. ML).

In general these errors are quite tricky to identify, my suggestion is to set model fit to 1 day and check again in one day. We may bump hour head on the wall now and still not be able to fix the problem. If in one day the issue is still there it’s something else, maybe on the data you pass or in the command.

In particular this makes me think there is no data enough at this moment:

The maximum lag (48) must be less than the length of the series (2).

ok. I’ll wait and look at this line tomorrow maybe something changes. Its just a bit sad to loose the 300 days of data. But if that one day works, maybe it is possible to continously fine tune to get a result quicker (?)
Thanks for the help again :slight_smile:

just one additional discovery when setting days to 1 and lags to 20. Then the data is 0? That is strange:

2024-10-04 19:08:26,801 - web_server - INFO - Passed runtime parameters: {'days_to_retrieve': 1, 'var_model': 'sensor.power_load_no_var_loads', 'num_lags': 20}
2024-10-04 19:08:26,801 - web_server - INFO -  >> Setting input data dict
2024-10-04 19:08:26,801 - web_server - INFO - Setting up needed data
2024-10-04 19:08:26,806 - web_server - INFO - Retrieve hass get data method initiated...
2024-10-04 19:08:27,449 - web_server - INFO -  >> Performing a machine learning forecast model fit...
2024-10-04 19:08:27,449 - web_server - INFO - Performing a forecast model fit for load_forecast
2024-10-04 19:08:27,454 - web_server - INFO - Training a KNeighborsRegressor model
2024-10-04 19:08:27,456 - web_server - ERROR - Exception on /action/forecast-model-fit [POST]
Traceback (most recent call last):
  File "/usr/local/lib/python3.11/dist-packages/flask/app.py", line 1473, in wsgi_app
    response = self.full_dispatch_request()
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/flask/app.py", line 882, in full_dispatch_request
    rv = self.handle_user_exception(e)
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/flask/app.py", line 880, in full_dispatch_request
    rv = self.dispatch_request()
         ^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/flask/app.py", line 865, 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 179, in action_call
    df_fit_pred, _, mlf = forecast_model_fit(input_data_dict, app.logger)
                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/emhass/command_line.py", line 498, in forecast_model_fit
    df_pred, df_pred_backtest = mlf.fit(
                                ^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/emhass/machine_learning_forecaster.py", line 153, in fit
    self.forecaster.fit(y=self.data_train[self.var_model],
  File "/usr/local/lib/python3.11/dist-packages/skforecast/ForecasterAutoreg/ForecasterAutoreg.py", line 578, in fit
    X_train, y_train = self.create_train_X_y(y=y, exog=exog)
                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/skforecast/ForecasterAutoreg/ForecasterAutoreg.py", line 457, in create_train_X_y
    X_train, y_train = self._create_lags(y=y_values)
                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/skforecast/ForecasterAutoreg/ForecasterAutoreg.py", line 364, in _create_lags
    raise ValueError(
ValueError: The maximum lag (20) must be less than the length of the series (0).

I know. Let’s see. But don’t think that with that 300 days you will get a perfect prediction. For example I tried with 4 weeks and I can’t get anything good enough, most probably it’s related to the predictability of the load signal, so I preferred to go back to naive. Some of us use ML others naive, it depends on the outcome.

Yes, you can continuously improve the model, but every day you will have to increase the number of days that are retrieved.
Anyway in my experience naive is good enough to start.

ok thats good to know. I’ll look tomorrow and if nothing helps just continue using naive mode :+1:

Good.

For example this is the results I get with 28 days using fit+tune. You see R2 value is quite poor

2024-10-04 19:15:05,593 - web_server - INFO - Passed runtime parameters: {'days_to_retrieve': 28, 'model_type': 'KNN', 'var_model': 'sensor.consumption_filtered_w', 'sklearn_model': 'KNeighborsRegressor', 'num_lags': 48, 'split_date_delta': '24h', 'perform_backtest': 'False'}
2024-10-04 19:15:05,593 - web_server - INFO -  >> Setting input data dict
2024-10-04 19:15:05,593 - web_server - INFO - Setting up needed data
2024-10-04 19:15:05,597 - web_server - INFO - Retrieve hass get data method initiated...
2024-10-04 19:15:48,880 - web_server - INFO -  >> Performing a machine learning forecast model fit...
2024-10-04 19:15:48,881 - web_server - INFO - Performing a forecast model fit for KNN
2024-10-04 19:15:48,889 - web_server - INFO - Training a KNeighborsRegressor model
2024-10-04 19:15:48,935 - web_server - INFO - Elapsed time for model fit: 0.04668474197387695
2024-10-04 19:15:48,955 - web_server - INFO - Prediction R2 score of fitted model on test data: 0.29507151281871546
2024-10-04 19:17:32,816 - web_server - INFO - Passed runtime parameters: {'days_to_retrieve': 28, 'model_type': 'KNN', 'var_model': 'sensor.consumption_filtered_w', 'sklearn_model': 'KNeighborsRegressor', 'num_lags': 48, 'split_date_delta': '24h', 'perform_backtest': 'False'}
2024-10-04 19:17:32,816 - web_server - INFO -  >> Setting input data dict
2024-10-04 19:17:32,816 - web_server - INFO - Setting up needed data
2024-10-04 19:17:32,821 - web_server - INFO - Retrieve hass get data method initiated...
2024-10-04 19:18:15,118 - web_server - INFO -  >> Performing a machine learning forecast model tune...
2024-10-04 19:18:15,120 - web_server - INFO - Bayesian hyperparameter optimization with backtesting

  0%|          | 0/10 [00:00<?, ?it/s]
Best trial: 0. Best value: -0.126449:   0%|          | 0/10 [00:01<?, ?it/s]
Best trial: 0. Best value: -0.126449:  10%|β–ˆ         | 1/10 [00:01<00:09,  1.06s/it]
Best trial: 0. Best value: -0.126449:  10%|β–ˆ         | 1/10 [00:01<00:09,  1.06s/it]
Best trial: 0. Best value: -0.126449:  20%|β–ˆβ–ˆ        | 2/10 [00:01<00:08,  1.06s/it]
Best trial: 0. Best value: -0.126449:  30%|β–ˆβ–ˆβ–ˆ       | 3/10 [00:01<00:02,  3.02it/s]
Best trial: 0. Best value: -0.126449:  30%|β–ˆβ–ˆβ–ˆ       | 3/10 [00:01<00:02,  3.02it/s]
Best trial: 0. Best value: -0.126449:  40%|β–ˆβ–ˆβ–ˆβ–ˆ      | 4/10 [00:01<00:01,  3.02it/s]
Best trial: 0. Best value: -0.126449:  50%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆ     | 5/10 [00:01<00:00,  5.08it/s]
Best trial: 0. Best value: -0.126449:  50%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆ     | 5/10 [00:01<00:00,  5.08it/s]
Best trial: 0. Best value: -0.126449:  60%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ    | 6/10 [00:01<00:00,  5.08it/s]
Best trial: 0. Best value: -0.126449:  70%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ   | 7/10 [00:01<00:00,  6.89it/s]
Best trial: 0. Best value: -0.126449:  70%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ   | 7/10 [00:01<00:00,  6.89it/s]
Best trial: 0. Best value: -0.126449:  80%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ  | 8/10 [00:01<00:00,  6.89it/s]
Best trial: 0. Best value: -0.126449:  90%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ | 9/10 [00:01<00:00,  8.69it/s]
Best trial: 0. Best value: -0.126449:  90%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ | 9/10 [00:01<00:00,  8.69it/s]
Best trial: 0. Best value: -0.126449: 100%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 10/10 [00:01<00:00,  5.87it/s]
2024-10-04 19:18:16,881 - web_server - INFO - Elapsed time: 1.7611944675445557
2024-10-04 19:18:16,931 - web_server - INFO - R2 score for optimized prediction in train period: 0.12644879974022627
2024-10-04 19:18:16,932 - web_server - INFO - R2 score for optimized prediction in test period: 0.1037983522440129
2024-10-04 19:18:16,932 - web_server - INFO - Number of optimal lags obtained: 24
1 Like

Im struggling to find why the system wouldnt prioritise a full charge in the batteries prior to export limiting.

Surely this can be adjusted? I think its very silly as the weather can change and it should be prioritised as most days the batteries can miss a full charge with a storm rolling in and solcast not picking up on it.

Im currently on self consumption too.

It’s a bit related to the way EMHASS works, with a final target SOC, I think.
One possibility is to work with a 24h rolling window, so basically you are always postponing the battery target SOC and focus on the short-mid term.
Another option is to take control only when EMHASS suggests to charge from the grid (when PV is zero) and for the rest of the time let the battery work autonomously. But in such case the impact on how deferrable loads work should be assessed.
A third option I didn’t check is to have a longer forecast, in such case the target soc would occur in 48h and so - maybe - the batteries are pushed to higher charge values for the next 24h.

Hi torstein, I am trying your addons without success.

In the log I get following from deye-solarmanpy:
730 - main - ERROR - HTTP request error: 404 Client Error: Not Found for url: http://supervisor/core/api/states/input_text.emhass_deye_set_soc

Is this add working, and should I install and run both pysolarmanv5-proxy and deye-solarmanpy?

Very happy if you see this.

Does anyone use their in emhass for electric underfloor heating in a bathroom. I will work on that around the clock but maybe fluctuate with the temperature up and down depending on your price
If so, how would one proceed?

How many hours a day do you want the floor switched on for? Does this charge with other factors; internal or external temp?

What controls do you have available? On/off or setpoint?

Do you have specific times you want the floor heated?

A simple deferrable load in EMHASS would switch it on for a cheapest number of hours a day, would be my starting point to prove it is functional.

There is a thermal model in EMHASS, which can be complex to setup so once you have the simple system setup you could try to adapt the thermal model.