Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions apps/predbat/compare.py
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,7 @@ def run_single(self, tariff, rate_import_base, rate_export_base, end_record, deb
my_predbat.manual_all_times = []
my_predbat.octopus_intelligent_charging = False

self.recompute_iboost()
self.recompute_car_charging(car_charging_slots)

self.log("Running scenario for tariff: {}".format(name))
Expand Down Expand Up @@ -448,6 +449,17 @@ def publish_only(self):
self.select_best(compare_list, self.comparisons)
self.publish_data()

def recompute_iboost(self):
"""
Recompute iBoost plan
"""
my_predbat = self.pb

if my_predbat.iboost_enable and (((not my_predbat.iboost_solar) and (not my_predbat.iboost_charging)) or my_predbat.iboost_smart):
my_predbat.iboost_plan = my_predbat.plan_iboost_smart()
else:
my_predbat.iboost_plan = []

def recompute_car_charging(self, car_charging_slots):
"""
Recompute car charging plan
Expand Down Expand Up @@ -506,6 +518,7 @@ def run_all(self, debug=False, fetch_sensor=True):
save_cost_today_sofar = my_predbat.cost_today_sofar
save_carbon_today_sofar = my_predbat.carbon_today_sofar
save_iboost_today = my_predbat.iboost_today
save_iboost_plan = my_predbat.iboost_plan
save_import_today_now = my_predbat.import_today_now
save_export_today_now = my_predbat.export_today_now
save_octopus_intelligent_charging = my_predbat.octopus_intelligent_charging
Expand Down Expand Up @@ -607,6 +620,7 @@ def run_all(self, debug=False, fetch_sensor=True):
my_predbat.cost_today_sofar = save_cost_today_sofar
my_predbat.carbon_today_sofar = save_carbon_today_sofar
my_predbat.iboost_today = save_iboost_today
my_predbat.iboost_plan = save_iboost_plan
my_predbat.import_today_now = save_import_today_now
my_predbat.export_today_now = save_export_today_now
my_predbat.octopus_intelligent_charging = save_octopus_intelligent_charging
Expand Down
93 changes: 93 additions & 0 deletions apps/predbat/tests/test_compare.py
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,99 @@ def _mock_fetch_config_options():
else:
print("PASS T12: run_all() restores config: overrides inside the per-tariff loop, not just once at the end")

# ------------------------------------------------------------------
# T13: run_single() re-plans iBoost against the tariff's own rates
# instead of leaving it stuck with the plan computed for the live
# tariff (the compare-plan iBoost timing bug)
# ------------------------------------------------------------------
cmp, pb = _make_compare()
pb.iboost_enable = True
pb.iboost_solar = False
pb.iboost_charging = False
pb.iboost_smart = True
pb.iboost_today = 3.0
pb.import_today_now = 0
pb.export_today_now = 0
pb.cost_today_sofar = 0
pb.carbon_today_sofar = 0
pb.forecast_plan_hours = 48
pb.manual_charge_times = None
pb.manual_export_times = None
pb.manual_freeze_charge_times = None
pb.manual_freeze_export_times = None
pb.manual_demand_times = None
pb.manual_all_times = None
pb.octopus_intelligent_charging = False
pb.iboost_plan = ["stale_plan_from_live_tariff"]

tariff_plan_calls = []

def _mock_plan_iboost_smart():
tariff_plan_calls.append(1)
return ["fresh_plan_for_this_tariff"]

pb.plan_iboost_smart = _mock_plan_iboost_smart

cmp.fetch_config = lambda tariff: None
cmp.apply_hardware_overrides = lambda tariff, pb: None
cmp.fetch_rates = lambda tariff, base_import, base_export: "existing"
cmp.recompute_car_charging = lambda slots: None
cmp.run_scenario = lambda end_record: {"cost": 0, "metric": 0}

result = cmp.run_single({"name": "test_tariff", "id": "test"}, {}, {}, 48 * 60, fetch_sensor=False)

if not tariff_plan_calls:
print("ERROR T13: plan_iboost_smart() was not called during run_single()")
failed += 1
elif pb.iboost_plan != ["fresh_plan_for_this_tariff"]:
print("ERROR T13: iboost_plan should be replaced with the tariff-specific plan, got {}".format(pb.iboost_plan))
failed += 1
else:
print("PASS T13: run_single() re-plans iBoost using the compared tariff's own rates")

# ------------------------------------------------------------------
# T14: run_single() clears iboost_plan (rather than reusing a stale one)
# when iBoost smart-rate planning isn't applicable for this tariff run
# ------------------------------------------------------------------
cmp, pb = _make_compare()
pb.iboost_enable = True
pb.iboost_solar = True
pb.iboost_charging = True
pb.iboost_smart = False
pb.iboost_today = 0
pb.import_today_now = 0
pb.export_today_now = 0
pb.cost_today_sofar = 0
pb.carbon_today_sofar = 0
pb.forecast_plan_hours = 48
pb.manual_charge_times = None
pb.manual_export_times = None
pb.manual_freeze_charge_times = None
pb.manual_freeze_export_times = None
pb.manual_demand_times = None
pb.manual_all_times = None
pb.octopus_intelligent_charging = False
pb.iboost_plan = ["stale_plan_from_live_tariff"]
pb.plan_iboost_smart = lambda: tariff_plan_calls.append(1) or []

cmp.fetch_config = lambda tariff: None
cmp.apply_hardware_overrides = lambda tariff, pb: None
cmp.fetch_rates = lambda tariff, base_import, base_export: "existing"
cmp.recompute_car_charging = lambda slots: None
cmp.run_scenario = lambda end_record: {"cost": 0, "metric": 0}

tariff_plan_calls.clear()
cmp.run_single({"name": "test_tariff2", "id": "test2"}, {}, {}, 48 * 60, fetch_sensor=False)

if tariff_plan_calls:
print("ERROR T14: plan_iboost_smart() should not be called when iboost_charging/iboost_solar handle boosting and iboost_smart is off")
failed += 1
elif pb.iboost_plan != []:
print("ERROR T14: stale iboost_plan from the live tariff should be cleared, got {}".format(pb.iboost_plan))
failed += 1
else:
print("PASS T14: run_single() clears stale iboost_plan when smart-rate planning isn't applicable")

if failed:
print("**** compare tests FAILED: {} errors ****\n".format(failed))
else:
Expand Down