diff --git a/apps/predbat/execute.py b/apps/predbat/execute.py index d91762d0..fbc361e9 100644 --- a/apps/predbat/execute.py +++ b/apps/predbat/execute.py @@ -164,16 +164,12 @@ def execute_plan(self): else: # We can only hold charge if a) we have a way to hold the charge level on the reserve or with a pause feature # and the current charge level is above the target for all inverters - can_hold_charge = True - target_soc = self.charge_limit_percent_best[0] if self.charge_limit_best[0] != self.reserve else self.soc_percent - target_soc = max(target_soc, self.best_soc_min, inverter.reserve) - for check in self.inverters: - if not check.inv_has_timed_pause and (check.reserve_max < check.soc_percent): - can_hold_charge = False - break - if self.set_soc_enable and can_hold_charge and self.soc_percent >= target_soc: + target_soc = calc_percent_limit(max(self.charge_limit_best[0] if self.charge_limit_best[0] != self.reserve else self.soc_kw, self.reserve), self.soc_max) + if self.set_soc_enable and self.soc_percent >= target_soc: status = "Hold charging" - self.log("Inverter {} Hold charging as soc {}% is above target {}% set_discharge_during_charge {}".format(inverter.id, inverter.soc_percent, target_soc, self.charge_limit_percent_best[0], self.set_discharge_during_charge)) + self.log( + "Inverter {} Hold charging as soc {}% is above target {}% set_discharge_during_charge {}".format(inverter.id, inverter.soc_percent, target_soc, self.charge_limit_percent_best[0], self.set_discharge_during_charge) + ) if (target_soc < 100.0) and (abs(inverter.soc_percent - target_soc) <= 1.0): # If we are within 1% of the target but not at 100% then we can hold charge @@ -181,12 +177,14 @@ def execute_plan(self): if self.set_soc_enable and ((self.set_reserve_enable and self.set_reserve_hold and inverter.reserve_max >= inverter.soc_percent) or inverter.inv_has_timed_pause): inverter.disable_charge_window() disabled_charge_window = True + if self.set_reserve_enable and not inverter.inv_has_timed_pause: inverter.adjust_reserve(min(inverter.soc_percent + 1, 100)) resetReserve = False else: inverter.adjust_charge_window(charge_start_time, charge_end_time, self.minutes_now) + # Pause? if inverter.inv_has_timed_pause: inverter.adjust_pause_mode(pause_discharge=True) resetPause = False @@ -432,16 +430,14 @@ def execute_plan(self): self.log("Resetting charging SOC as we are not charging and inverter_soc_reset is enabled") self.adjust_battery_target_multi(inverter, 100.0, isCharging, isExporting) elif isCharging: - target_soc = self.charge_limit_percent_best[0] if self.charge_limit_best[0] != self.reserve else self.soc_percent - target_soc = max(target_soc, self.best_soc_min, inverter.reserve) + target_soc = calc_percent_limit(max(self.charge_limit_best[0] if self.charge_limit_best[0] != self.reserve else self.soc_kw, self.reserve), self.soc_max) self.log("Setting charging SOC to {} as per target".format(target_soc)) self.adjust_battery_target_multi(inverter, target_soc, isCharging, isExporting) elif not inverter.inv_has_target_soc: self.log("Setting charging SOC to 0 as we are not charging and inverter doesn't support target soc") self.adjust_battery_target_multi(inverter, 0, isCharging, isExporting) else: - target_soc = self.charge_limit_percent_best[0] if self.charge_limit_best[0] != self.reserve else self.soc_percent - target_soc = max(target_soc, self.best_soc_min, inverter.reserve) + target_soc = calc_percent_limit(max(self.charge_limit_best[0] if self.charge_limit_best[0] != self.reserve else self.soc_kw, self.reserve), self.soc_max) self.log("Setting charging SOC to {} as per target for when charge window starts".format(target_soc)) self.adjust_battery_target_multi(inverter, target_soc, isCharging, isExporting) else: diff --git a/apps/predbat/unit_test.py b/apps/predbat/unit_test.py index 9af6cab8..dd3133e4 100644 --- a/apps/predbat/unit_test.py +++ b/apps/predbat/unit_test.py @@ -2743,7 +2743,7 @@ def run_execute_tests(my_predbat): assert_charge_time_enable=True, set_charge_window=True, set_export_window=True, - assert_status="Charging", + assert_status="Hold charging", soc_kw=9, assert_charge_start_time_minutes=-1, assert_charge_end_time_minutes=my_predbat.minutes_now + 60, @@ -2761,7 +2761,7 @@ def run_execute_tests(my_predbat): assert_charge_time_enable=True, set_charge_window=True, set_export_window=True, - assert_status="Charging", + assert_status="Hold charging", soc_kw=9, assert_charge_start_time_minutes=-1, assert_charge_end_time_minutes=my_predbat.minutes_now + 60, @@ -3042,7 +3042,7 @@ def run_execute_tests(my_predbat): assert_status="Charging", assert_reserve=0, assert_soc_target=10, - assert_immediate_soc_target=0.5, + assert_immediate_soc_target=10, assert_charge_start_time_minutes=-1, assert_charge_end_time_minutes=my_predbat.minutes_now + 60, ) @@ -3091,6 +3091,7 @@ def run_execute_tests(my_predbat): if failed: return failed + # Target SOC can not be lower than reserve (which is 1) so it will charge to 1 not freeze failed |= run_execute_test( my_predbat, "charge_freeze_imb3", @@ -3101,10 +3102,10 @@ def run_execute_tests(my_predbat): assert_charge_time_enable=True, soc_kw=0.75, assert_pause_discharge=False, - assert_status="Hold charging", + assert_status="Charging", assert_reserve=0, assert_soc_target_array=[10, 10], - assert_immediate_soc_target=8, + assert_immediate_soc_target=10, assert_charge_start_time_minutes=-1, assert_charge_end_time_minutes=my_predbat.minutes_now + 60, soc_kw_array=[0.5, 0.25],