Skip to content

Commit

Permalink
[pre-commit.ci lite] apply automatic fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
pre-commit-ci-lite[bot] authored Dec 12, 2024
1 parent cd98c43 commit 26e90b5
Show file tree
Hide file tree
Showing 8 changed files with 59 additions and 54 deletions.
4 changes: 2 additions & 2 deletions apps/predbat/execute.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ def execute_plan(self):
self.log("Charge window will be: {} - {} - current soc {} target {}".format(charge_start_time, charge_end_time, inverter.soc_percent, self.charge_limit_percent_best[0]))
# Are we actually charging?
if self.minutes_now >= minutes_start and self.minutes_now < minutes_end:
new_charge_rate = int(
new_charge_rate = int(
find_charge_rate(
self.minutes_now,
inverter.soc_kw,
Expand Down Expand Up @@ -179,7 +179,7 @@ def execute_plan(self):
resetDischarge = False
else:
inverter.adjust_charge_window(charge_start_time, charge_end_time, self.minutes_now)

inverter.adjust_charge_immediate(self.charge_limit_percent_best[0], freeze=True)
else:
status = "Charging"
Expand Down
4 changes: 2 additions & 2 deletions apps/predbat/output.py
Original file line number Diff line number Diff line change
Expand Up @@ -584,14 +584,14 @@ def publish_html_plan(self, pv_forecast_minute_step, pv_forecast_minute_step10,

for try_minute in range(minute_start, minute_end, PREDICT_STEP):
charge_window_n = self.in_charge_window(self.charge_window_best, try_minute)
if charge_window_n >=0 and self.charge_limit_best[charge_window_n] == 0:
if charge_window_n >= 0 and self.charge_limit_best[charge_window_n] == 0:
charge_window_n = -1
if charge_window_n >= 0:
break

for try_minute in range(minute_start, minute_end, PREDICT_STEP):
export_window_n = self.in_charge_window(self.export_window_best, try_minute)
if export_window_n >=0 and self.export_limits_best[export_window_n] == 100:
if export_window_n >= 0 and self.export_limits_best[export_window_n] == 100:
export_window_n = -1
if export_window_n >= 0:
break
Expand Down
4 changes: 2 additions & 2 deletions apps/predbat/plan.py
Original file line number Diff line number Diff line change
Expand Up @@ -1798,7 +1798,7 @@ def update_target_values(self):
self.export_window_best[window_n]["target"] = self.export_limits_best[window_n]
for window_n in range(len(self.charge_limit_best)):
self.charge_window_best[window_n]["target"] = self.charge_limit_best[window_n]

def tweak_plan(self, end_record, best_metric, metric_keep):
"""
Tweak existing plan only
Expand Down Expand Up @@ -1866,7 +1866,7 @@ def optimise_all_windows(self, best_metric, metric_keep, debug_mode=False):
record_charge_windows = max(self.max_charge_windows(self.end_record + self.minutes_now, self.charge_window_best), 1)
record_export_windows = max(self.max_charge_windows(self.end_record + self.minutes_now, self.export_window_best), 1)
window_sorted, window_index, price_set, price_links = self.sort_window_by_price_combined(self.charge_window_best[:record_charge_windows], self.export_window_best[:record_export_windows])

best_soc = self.soc_max
best_cost = best_metric
best_keep = metric_keep
Expand Down
2 changes: 2 additions & 0 deletions apps/predbat/predbat.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,11 @@
try:
import adbase as ad
import appdaemon.plugins.hass.hassapi as hass

IS_APPDAEMON = True
except:
import hass as hass

IS_APPDAEMON = False

import pytz
Expand Down
24 changes: 12 additions & 12 deletions apps/predbat/prediction.py
Original file line number Diff line number Diff line change
Expand Up @@ -592,7 +592,7 @@ def run_prediction(self, charge_limit, charge_window, export_window, export_limi

if not self.set_export_freeze_only and (export_window_n >= 0) and export_limits[export_window_n] < 100.0 and (soc - step * self.battery_rate_max_discharge_scaled) >= discharge_min:
# Discharge enable
discharge_rate_now = self.battery_rate_max_discharge # Assume discharge becomes enabled here
discharge_rate_now = self.battery_rate_max_discharge # Assume discharge becomes enabled here
discharge_rate_now_curve = get_discharge_rate_curve(soc, discharge_rate_now, self.soc_max, self.battery_rate_max_discharge, self.battery_discharge_power_curve, self.battery_rate_min) * self.battery_rate_max_scaling_discharge

battery_draw = min(discharge_rate_now_curve * step, battery_to_min)
Expand Down Expand Up @@ -649,19 +649,19 @@ def run_prediction(self, charge_limit, charge_window, export_window, export_limi
if save in ["best", "best10", "test"]:
# Only tune charge rate on final plan not every simulation
charge_rate_now = find_charge_rate(
minute_absolute,
soc,
charge_window[charge_window_n],
charge_limit_n,
self.battery_rate_max_charge,
self.soc_max,
self.battery_charge_power_curve,
self.set_charge_low_power,
minute_absolute,
soc,
charge_window[charge_window_n],
charge_limit_n,
self.battery_rate_max_charge,
self.soc_max,
self.battery_charge_power_curve,
self.set_charge_low_power,
self.charge_low_power_margin,
self.battery_rate_min,
self.battery_rate_max_scaling,
self.battery_loss,
None
None,
)
else:
charge_rate_now = self.battery_rate_max_charge # Assume charge becomes enabled here
Expand Down Expand Up @@ -815,8 +815,8 @@ def run_prediction(self, charge_limit, charge_window, export_window, export_limi
if soc < self.best_soc_keep and battery_draw > 0:
# Apply keep as a percentage of the time in the future so it gets stronger over an 4 hour period
# Weight to 50% chance of the scenario
#keep_diff = max(get_diff(0, 0, pv_now, load_yesterday, inverter_loss), battery_draw)
#if keep_diff > 0:
# keep_diff = max(get_diff(0, 0, pv_now, load_yesterday, inverter_loss), battery_draw)
# if keep_diff > 0:
metric_keep += rate_import[minute_absolute] * battery_draw * keep_minute_scaling
if diff > 0:
# Import
Expand Down
48 changes: 23 additions & 25 deletions apps/predbat/unit_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -907,7 +907,7 @@ def run_single_debug(my_predbat, debug_file):

# Force off combine export XXX:
print("Combined export slots {}".format(my_predbat.combine_export_slots))
#my_predbat.combine_export_slots = False
# my_predbat.combine_export_slots = False
my_predbat.best_soc_keep = 1.0

if re_do_rates:
Expand Down Expand Up @@ -952,13 +952,13 @@ def run_single_debug(my_predbat, debug_file):
load_forecast=my_predbat.load_forecast,
load_scaling_dynamic=my_predbat.load_scaling_dynamic,
cloud_factor=min(my_predbat.metric_load_divergence + 0.5, 1.0) if my_predbat.metric_load_divergence else None,
)
)

pv_step = my_predbat.pv_forecast_minute_step
pv10_step = my_predbat.pv_forecast_minute10_step
load_step = my_predbat.load_minutes_step
load10_step = my_predbat.load_minutes_step10

my_predbat.prediction = Prediction(my_predbat, pv_step, pv_step, load_step, load_step)
my_predbat.debug_enable = True

Expand Down Expand Up @@ -1047,7 +1047,6 @@ def run_single_debug(my_predbat, debug_file):
print("Wrote plan to plan_final.html")



def run_execute_tests(my_predbat):
print("**** Running execute tests ****\n")
reset_inverter(my_predbat)
Expand Down Expand Up @@ -1298,22 +1297,22 @@ def run_execute_tests(my_predbat):
return failed

my_predbat.battery_charge_power_curve = {
100 : 0.50,
99 : 0.50,
98 : 0.50,
97 : 0.50,
96 : 0.50,
95 : 0.50,
94 : 1.00,
93 : 1.00,
92 : 1.00,
91 : 1.00,
90 : 1.00,
89 : 1.00,
88 : 1.00,
87 : 1.00,
86 : 1.00,
85 : 1.00,
100: 0.50,
99: 0.50,
98: 0.50,
97: 0.50,
96: 0.50,
95: 0.50,
94: 1.00,
93: 1.00,
92: 1.00,
91: 1.00,
90: 1.00,
89: 1.00,
88: 1.00,
87: 1.00,
86: 1.00,
85: 1.00,
}

# 60 minutes - 10 minute margin = 50 minutes to add 0.75kWh to each battery (x2 inverters)
Expand Down Expand Up @@ -2940,10 +2939,10 @@ def run_model_tests(my_predbat):
failed |= simple_scenario("load_only", my_predbat, 1, 0, assert_final_metric=import_rate * 24, assert_final_soc=0, with_battery=False)
failed |= simple_scenario("load_bat_ac", my_predbat, 4, 0, assert_final_metric=import_rate * 24 * 3.2, assert_final_soc=100 - 24, with_battery=True, battery_soc=100.0, inverter_loss=0.8)
failed |= simple_scenario("load_bat_dc", my_predbat, 4, 0, assert_final_metric=import_rate * 24 * 3.2, assert_final_soc=100 - 24, with_battery=True, battery_soc=100.0, inverter_loss=0.8, hybrid=True)
failed |= simple_scenario("load_bat_ac2", my_predbat, 0.5, 0, assert_final_metric=0, assert_final_soc=100 - 12/0.8, with_battery=True, battery_soc=100.0, inverter_loss=0.8)
failed |= simple_scenario("load_bat_dc2", my_predbat, 0.5, 0, assert_final_metric=0, assert_final_soc=100 - 12/0.8, with_battery=True, battery_soc=100.0, inverter_loss=0.8, hybrid=True)
failed |= simple_scenario("load_bat_ac3", my_predbat, 1.0, 0, assert_final_metric=import_rate * 0.2*24, assert_final_soc=100 - 24, with_battery=True, battery_soc=100.0, inverter_loss=0.8)
failed |= simple_scenario("load_bat_dc3", my_predbat, 1.0, 0, assert_final_metric=import_rate * 0.2*24, assert_final_soc=100 - 24, with_battery=True, battery_soc=100.0, inverter_loss=0.8, hybrid=True)
failed |= simple_scenario("load_bat_ac2", my_predbat, 0.5, 0, assert_final_metric=0, assert_final_soc=100 - 12 / 0.8, with_battery=True, battery_soc=100.0, inverter_loss=0.8)
failed |= simple_scenario("load_bat_dc2", my_predbat, 0.5, 0, assert_final_metric=0, assert_final_soc=100 - 12 / 0.8, with_battery=True, battery_soc=100.0, inverter_loss=0.8, hybrid=True)
failed |= simple_scenario("load_bat_ac3", my_predbat, 1.0, 0, assert_final_metric=import_rate * 0.2 * 24, assert_final_soc=100 - 24, with_battery=True, battery_soc=100.0, inverter_loss=0.8)
failed |= simple_scenario("load_bat_dc3", my_predbat, 1.0, 0, assert_final_metric=import_rate * 0.2 * 24, assert_final_soc=100 - 24, with_battery=True, battery_soc=100.0, inverter_loss=0.8, hybrid=True)

failed |= simple_scenario(
"load_bat_dc_pv",
Expand Down Expand Up @@ -4139,7 +4138,6 @@ def main():
parser = argparse.ArgumentParser(description="Predbat unit tests")
parser.add_argument("--debug_file", action="store", help="Enable debug output")
args = parser.parse_args()


print("**** Starting Predbat tests ****")
my_predbat = PredBat()
Expand Down
12 changes: 6 additions & 6 deletions apps/predbat/userinterface.py
Original file line number Diff line number Diff line change
Expand Up @@ -574,15 +574,15 @@ async def async_save_settings_yaml(self, filename=None):
def read_debug_yaml(self, filename):
"""
Read debug yaml - used for debugging scenarios not for the main code
"""
"""
debug = {}
if os.path.exists(filename):
with open(filename, "r") as file:
debug = yaml.safe_load(file)
else:
self.log("Warn: Debug file {} not found".format(filename))
return

for key in debug:
if key not in ["CONFIG_ITEMS", "inverters"]:
self.__dict__[key] = copy.deepcopy(debug[key])
Expand All @@ -591,7 +591,7 @@ def read_debug_yaml(self, filename):
for key in inverter:
self.inverters[inverter["id"]].__dict__[key] = copy.deepcopy(inverter[key])

for item in debug['CONFIG_ITEMS']:
for item in debug["CONFIG_ITEMS"]:
current = self.config_index.get(item["name"], None)
if current:
if current.get("value", None) != item["value"]:
Expand All @@ -614,7 +614,7 @@ def create_debug_yaml(self):
for key in self.__dict__:
if not key.startswith("__") and not callable(getattr(self, key)):
if (key.startswith("db")) or ("_key" in key) or key in ["pool", "ha_interface", "web_interface", "web_interface_task", "prediction", "logfile", "predheat", "inverters", "run_list", "threads", "EVENT_LISTEN_LIST", "local_tz"]:
pass
pass
else:
debug[key] = self.__dict__[key]
inverters_debug = []
Expand All @@ -627,9 +627,9 @@ def create_debug_yaml(self):
else:
inverter_debug[key] = inverter.__dict__[key]
inverters_debug.append(inverter_debug)
debug['inverters'] = inverters_debug
debug["inverters"] = inverters_debug

debug['CONFIG_ITEMS'] = CONFIG_ITEMS
debug["CONFIG_ITEMS"] = CONFIG_ITEMS
with open(filename, "w") as file:
yaml.dump(debug, file)
self.log("Wrote debug yaml to {}".format(filename_p))
Expand Down
15 changes: 10 additions & 5 deletions apps/predbat/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ def get_charge_rate_curve(soc, charge_rate_setting, soc_max, battery_rate_max_ch
soc_percent = calc_percent_limit(soc, soc_max)
max_charge_rate = battery_rate_max_charge * battery_charge_power_curve.get(soc_percent, 1.0)
if debug:
print("Max charge rate: {} SOC: {} Percent {} Rate in: {} rate out: {}".format(max_charge_rate*MINUTE_WATT, soc, soc_percent, charge_rate_setting*MINUTE_WATT, min(charge_rate_setting, max_charge_rate)*MINUTE_WATT))
print("Max charge rate: {} SOC: {} Percent {} Rate in: {} rate out: {}".format(max_charge_rate * MINUTE_WATT, soc, soc_percent, charge_rate_setting * MINUTE_WATT, min(charge_rate_setting, max_charge_rate) * MINUTE_WATT))
return max(min(charge_rate_setting, max_charge_rate), battery_rate_min)


Expand All @@ -182,6 +182,7 @@ def get_discharge_rate_curve(soc, discharge_rate_setting, soc_max, battery_rate_
max_discharge_rate = battery_rate_max_discharge * battery_discharge_power_curve.get(soc_percent, 1.0)
return max(min(discharge_rate_setting, max_discharge_rate), battery_rate_min)


def find_charge_rate(minutes_now, soc, window, target_soc, max_rate, soc_max, battery_charge_power_curve, set_charge_low_power, charge_low_power_margin, battery_rate_min, battery_rate_max_scaling, battery_loss, log_to):
"""
Find the lowest charge rate that fits the charge slow
Expand Down Expand Up @@ -238,21 +239,25 @@ def find_charge_rate(minutes_now, soc, window, target_soc, max_rate, soc_max, ba
if round(charge_now, 2) >= target_soc:
best_rate = rate
break
#if log_to:
# if log_to:
# log_to("Low Power mode: rate: {} minutes: {} SOC: {} Target SOC: {} Charge left: {} Charge now: {} Rate scale: {} Charge amount: {} Charge now: {} best rate: {} highest achievable_rate {}".format(
# rate * MINUTE_WATT, minute, soc, target_soc, charge_left, charge_now, rate_scale * MINUTE_WATT, charge_amount, charge_now, best_rate*MINUTE_WATT, highest_achievable_rate*MINUTE_WATT))
else:
break
rate_w -= 100.0

# If we tried to select a rate which is actually faster than the highest achievable (due to being close to 100% SOC) then default to max rate
if best_rate < max_rate and best_rate >= highest_achievable_rate:
if log_to:
log_to("Low Power mode: best rate {} >= highest achievable rate {}, default to max rate".format(best_rate*MINUTE_WATT, highest_achievable_rate*MINUTE_WATT))
log_to("Low Power mode: best rate {} >= highest achievable rate {}, default to max rate".format(best_rate * MINUTE_WATT, highest_achievable_rate * MINUTE_WATT))
best_rate = max_rate

if log_to:
log_to("Low Power mode: minutes left: {} absolute: {} SOC: {} Target SOC: {} Charge left: {} Max rate: {} Min rate: {} Best rate: {}".format(minutes_left, abs_minutes_left, soc, target_soc, charge_left, max_rate*MINUTE_WATT, min_rate*MINUTE_WATT, best_rate*MINUTE_WATT))
log_to(
"Low Power mode: minutes left: {} absolute: {} SOC: {} Target SOC: {} Charge left: {} Max rate: {} Min rate: {} Best rate: {}".format(
minutes_left, abs_minutes_left, soc, target_soc, charge_left, max_rate * MINUTE_WATT, min_rate * MINUTE_WATT, best_rate * MINUTE_WATT
)
)
return best_rate
else:
return max_rate

0 comments on commit 26e90b5

Please sign in to comment.