batpred
batpred copied to clipboard
Adaptions for better Huawei support
Hi, i have been looking to resolve the clipping issue for Huawei inverters as they seem to operate different to most others.
when you force charge or more importantly discharge the battery using the huawei_solar/forcible_discharge_soc service it take priority over the PV production so i dont want to use that in the case where clipping is the potental.
before predbat what i did was change the battery mode between max_self_consumption and fully_fed_to_grid. the latter sends as much power as possabel to the gird starting with PV and topping up with battery.
i tried to trace how predbat worked and i came up with this that im trying to test on my end. i did have the select.select_option incorrect ly defined so i just fixed that now but i cant find a way to force this to try the code out..
in apps.yaml i added this, "battery_option_service: " to the template.
`# Services to charge/discharge charge_start_service: service: huawei_solar/forcible_charge_soc charge_stop_service: service: huawei_solar/stop_forcible_charge discharge_start_service: service: huawei_solar/forcible_discharge_soc discharge_stop_service: service: huawei_solar/stop_forcible_charge
battery_option_service: service: select.select_option target: entity_id: select.batteries_working_mode data: max_self_consumption: "maximise_self_consumption" fftg: "fully_fed_to_grid"`
and in the inverter.py file i added /amended this from line 2145
"""
Adjust from exporting or not exporting based on passed target soc
"""
max_self_consumption = self.base.get_arg('battery_option_service', 'data', 'max_self_consumption', index=self.id)
fftg = self.base.get_arg('battery_option_service', 'data', 'fftg', index=self.id)
service_data_stop = {"device_id": self.base.get_arg("device_id", index=self.id, default="")}
extra_data = {"discharge_start_time": self.base.get_arg("discharge_start_time", index=self.id, default="00:00:00"), "discharge_end_time": self.base.get_arg("discharge_end_time", index=self.id, default="00:00:00")}
if target_soc > 0 and target_soc < 100:
service_data = {
"device_id": self.base.get_arg("device_id", index=self.id, default=""),
"target_soc": target_soc,
"power": int(self.battery_rate_max_discharge * MINUTE_WATT),
}
# Stop charge
self.call_service_template("charge_stop_service", service_data_stop, domain="charge"):
self.call_service_template("battery_option_service", {"option": max_self_consumption}, domain="select")
# Start discharge or discharge freeze
if freeze:
if not self.call_service_template("discharge_freeze_service", service_data, domain="discharge", extra_data=extra_data):
if not self.call_service_template("battery_option_service", {"option": fftg}, domain="select"):
self.call_service_template("discharge_start_service", service_data, domain="discharge", extra_data=extra_data)
else:
if not self.call_service_template("battery_option_service", {"option": fftg}, domain="select"):
self.call_service_template("discharge_start_service", service_data, domain="discharge", extra_data=extra_data)
else:
self.call_service_template("battery_option_service", {"option": max_self_consumption}, domain="select")
if not self.call_service_template("discharge_stop_service", service_data_stop, domain="discharge"):
self.call_service_template("charge_stop_service", service_data_stop, domain="discharge")```
do you have any input on this? can you help me refine this? once i have the matter mode working correctly i can address the freeze service as that is also something we can utalise
@springfall2008 i would appreciate your input on this one
i have tried hard coding the options but i still get this error ... Warn: Service call select/select_option data {'target': {'entity_id': 'select.batteries_working_mode'}, 'data': {'max_self_consumption': 'maximise_self_consumption', 'fftg': 'fully_fed_to_grid'}} failed with response None
i have tried hard coding the options but i still get this error
What happens if you call the service to set the inverter mode from developer tools rather than via predbat?
i have tried hard coding the options but i still get this error
What happens if you call the service to set the inverter mode from developer tools rather than via predbat?
this works action: select.select_option target: entity_id: select.batteries_working_mode data: option: maximise_self_consumption
latest code.. does seem to remove the error but does not work
` def adjust_export_immediate(self, target_soc, freeze=False): """ Adjust from exporting or not exporting based on passed target soc """ # Retrieve battery options and settings from the app config (battery_option_service) battery_options = self.base.get_arg("battery_option_service", index=self.id, default={}) mode_map = battery_options.get("data", {}) max_self_consumption = mode_map.get("max_self_consumption") fftg = mode_map.get("fftg")
# Prepare basic service data for stopping services
service_data_stop = {"device_id": self.base.get_arg("device_id", index=self.id, default="")}
extra_data = {
"discharge_start_time": self.base.get_arg("discharge_start_time", index=self.id, default="00:00:00"),
"discharge_end_time": self.base.get_arg("discharge_end_time", index=self.id, default="00:00:00")
}
if target_soc > 0 and target_soc < 100:
service_data = {
"device_id": self.base.get_arg("device_id", index=self.id, default=""),
"target_soc": target_soc,
"power": int(self.battery_rate_max_discharge * MINUTE_WATT),
}
# Stop charge
self.call_service_template("charge_stop_service", service_data_stop, domain="charge")
# Set battery mode to 'maximise_self_consumption'
self.call_service_template(
"select.select_option",
{
"target": {"entity_id": "select.batteries_working_mode"},
"data": {"option": "maximise_self_consumption"}
},
domain="select"
)
# Start discharge or discharge freeze
if freeze:
# Attempt to call discharge_freeze_service
if not self.call_service_template("discharge_freeze_service", service_data, domain="discharge", extra_data=extra_data):
# If discharge_freeze_service fails, try selecting 'fully_fed_to_grid' mode
if not self.call_service_template(
"select.select_option",
{
"target": {"entity_id": "select.batteries_working_mode"},
"data": {"option": "fully_fed_to_grid"}
},
domain="select"
):
# If both fail, start discharge
self.call_service_template("discharge_start_service", service_data, domain="discharge", extra_data=extra_data)
else:
# If not in freeze mode, attempt to select 'fully_fed_to_grid'
service_called = self.call_service_template(
"select.select_option",
{
"target": {"entity_id": "select.batteries_working_mode"},
"data": {"option": "fully_fed_to_grid"}
},
domain="select"
)
# If selecting 'fully_fed_to_grid' fails, start the discharge service
if not service_called:
self.call_service_template("discharge_start_service", service_data, domain="discharge", extra_data=extra_data)
else:
# When target_soc is 0 or 100, we stop the discharge or charge process
self.call_service_template("select.select_option", {
"target": {"entity_id": "select.batteries_working_mode"},
"data": {"option": "maximise_self_consumption"}
}, domain="select")
# Stop discharge or charge if needed
if not self.call_service_template("discharge_stop_service", service_data_stop, domain="discharge"):
self.call_service_template("charge_stop_service", service_data_stop, domain="discharge")`
I don't really understand what you are doing here, without changing the predbat code why don't just call the select option server direct from discharge_start/freeze options e.g:
discharge_start_service:
service: select.select_option
entity_id: select.batteries_working_mode
option: "maximise_self_consumption"