Skip to content

Commit

Permalink
Bug fix min/max selection in optimiser (#1831)
Browse files Browse the repository at this point in the history
* Test case updates

* [pre-commit.ci lite] apply automatic fixes

* Bug fix issue where min/max soc were not selected correctly in some cases

* Similar fix for clipping

* Debug typo

---------

Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
  • Loading branch information
springfall2008 and pre-commit-ci-lite[bot] authored Jan 1, 2025
1 parent de3ee9b commit 167d2e9
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 13 deletions.
27 changes: 17 additions & 10 deletions apps/predbat/plan.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from config import PREDICT_STEP, TIME_FORMAT
from utils import calc_percent_limit, dp0, dp1, dp2, dp3, dp4, remove_intersecting_windows
from prediction import Prediction, wrapped_run_prediction_single, wrapped_run_prediction_charge, wrapped_run_prediction_export
import sys

"""
Used to mimic threads when they are disabled
Expand Down Expand Up @@ -1684,15 +1685,19 @@ def clip_charge_slots(self, minutes_now, predict_soc, charge_window_best, charge
predict_minute_end_m1 = max(predict_minute_end - 5, predict_minute_start)

if (predict_minute_start in predict_soc) and (predict_minute_end in predict_soc):
soc_start = predict_soc[predict_minute_start]
soc_end = predict_soc[predict_minute_end]
# Work out min/max soc
soc_min = self.soc_max
soc_max = 0
for minute in range(predict_minute_start, predict_minute_end + 5, 5):
if minute in predict_soc:
soc_min = min(soc_min, predict_soc[minute])
soc_max = max(soc_max, predict_soc[minute])

soc_m1 = predict_soc[predict_minute_end_m1]
soc_min = min(soc_start, soc_end)
soc_min_percent = calc_percent_limit(soc_min, self.soc_max)
soc_max = max(soc_start, soc_end)

if self.debug_enable:
self.log("Examine charge window {} from {} - {} (minute {}) limit {} - starting soc {} ending soc {} soc_m1 {}".format(window_n, window_start, window_end, predict_minute_start, limit, soc_start, soc_end, soc_m1))
self.log("Examine charge window {} from {} - {} (minute {}) limit {} - min soc {} max soc {} soc_m1 {}".format(window_n, window_start, window_end, predict_minute_start, limit, soc_min, soc_max, soc_m1))

if (soc_min_percent > calc_percent_limit(charge_limit_best[window_n], self.soc_max)) and (charge_limit_best[window_n] != self.reserve):
charge_limit_best[window_n] = 0
Expand Down Expand Up @@ -1737,13 +1742,15 @@ def clip_export_slots(self, minutes_now, predict_soc, export_window_best, export
predict_minute_start = max(int((window_start - minutes_now) / 5) * 5, 0)
predict_minute_end = int((window_end - minutes_now) / 5) * 5
if (predict_minute_start in predict_soc) and (predict_minute_end in predict_soc):
soc_start = predict_soc[predict_minute_start]
soc_end = predict_soc[predict_minute_end]
soc_min = min(soc_start, soc_end)
soc_max = max(soc_start, soc_end)
soc_min = self.soc_max
soc_max = 0
for minute in range(predict_minute_start, predict_minute_end + 5, 5):
if minute in predict_soc:
soc_min = min(soc_min, predict_soc[minute])
soc_max = max(soc_max, predict_soc[minute])

if self.debug_enable:
self.log("Examine window {} from {} - {} (minute {}) limit {} - starting soc {} ending soc {}".format(window_n, window_start, window_end, predict_minute_start, limit, soc_start, soc_end))
self.log("Examine window {} from {} - {} (minute {}) limit {} - starting soc {} ending soc {}".format(window_n, window_start, window_end, predict_minute_start, limit, soc_min, soc_max))

# Export level adjustments for safety
if soc_min > limit_soc:
Expand Down
2 changes: 1 addition & 1 deletion apps/predbat/predbat.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
import asyncio
import json

THIS_VERSION = "v8.9.0"
THIS_VERSION = "v8.9.1"

# fmt: off
PREDBAT_FILES = ["predbat.py", "config.py", "prediction.py", "gecloud.py","utils.py", "inverter.py", "ha.py", "download.py", "unit_test.py", "web.py", "predheat.py", "futurerate.py", "octopus.py", "solcast.py","execute.py", "plan.py", "fetch.py", "output.py", "userinterface.py"]
Expand Down
4 changes: 3 additions & 1 deletion apps/predbat/unit_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -1997,7 +1997,7 @@ def run_single_debug(test_name, my_predbat, debug_file, expected_file=None):
# Force off combine export XXX:
print("Combined export slots {} min_improvement_export {} set_export_freeze_only {}".format(my_predbat.combine_export_slots, my_predbat.metric_min_improvement_export, my_predbat.set_export_freeze_only))
if not expected_file:
my_predbat.plan_debug = True
my_predbat.args["plan_debug"] = True
pass
# my_predbat.combine_export_slots = False
# my_predbat.best_soc_keep = 1.0
Expand Down Expand Up @@ -5853,6 +5853,8 @@ def main():
basename = os.path.basename(filename)
pathname = os.path.dirname(filename)
failed |= run_single_debug(basename, my_predbat, filename, pathname + "/" + basename + ".expected.json")
if failed:
break

if failed:
print("**** ERROR: Some tests failed ****")
Expand Down
2 changes: 1 addition & 1 deletion apps/predbat/userinterface.py
Original file line number Diff line number Diff line change
Expand Up @@ -606,7 +606,7 @@ def read_debug_yaml(self, filename):
current = self.config_index.get(item["name"], None)
if current:
# print("Restore setting: {} = {} (was {})".format(item["name"], item["value"], current["value"]))
if current.get("value", None) != item["value"]:
if current.get("value", None) != item.get("value", None):
current["value"] = item["value"]
self.log("Restored debug settings - minutes now {}".format(self.minutes_now))

Expand Down

0 comments on commit 167d2e9

Please sign in to comment.