battery swap method wip

This commit is contained in:
Lucas Tan 2025-07-28 18:18:09 +01:00
parent 7c5d3f5b1d
commit 089078a9ea
3 changed files with 55 additions and 11 deletions

View File

@ -95,12 +95,50 @@ def update_cycle_SoC(bess_data, bess_soc_for_cycle, timestamp):
return bess_soc_for_cycle return bess_soc_for_cycle
def arrange_swap(bess_data, c): def arrange_swap(c, bess_data, bess_soc_for_cycle):
for unit in bess_data["units"]: # identify BESS units that need swapping
if unit["SoC"] < c["bess"]["buffer"]: units_needing_swap = [
# find for unassigned BESS unit with SOC at 100% unit for unit in bess_data["units"] if unit["SoC"] < bess_data["buffer"]["min"]
for candidate in bess_data["units"]: ]
if candidate["SoC"] == 1 and candidate["site"] == "Unassigned":
# assign the candidate to the site if not units_needing_swap:
candidate["site"] = unit["site"] return bess_data, bess_soc_for_cycle
break
# identify BESS units that are unassigned and fully charged
unassigned_fully_charged = [
unit
for unit in bess_data["units"]
if unit["SoC"] == 1 and unit["site"] == "Unassigned"
]
if not unassigned_fully_charged:
return bess_data, bess_soc_for_cycle
# assign unassigned fully charged units to units needing swap
for unit in units_needing_swap:
# take the first unassigned fully charged unit
new_unit = unassigned_fully_charged.pop(0)
# assign it to the site of the unit needing swap
new_unit["site"] = unit["site"]
# reset SoC to 1 (fully charged)
new_unit["SoC"] = 1
# set current load to existing load
new_unit["current_load_kW"] = unit["current_load_kW"]
# reset old unit
unit["site"] = "Unassigned" # mark the old unit as unassigned
unit["current_load_kW"] = 0 # reset current load
# update the BESS data
# search for the index of the unit needing swap and replace it with the new unit
index = next(
i for i, d in enumerate(bess_data["units"]) if d["name"] == unit["name"]
)
bess_data["units"][index] = new_unit
# search for index of new unit, and replace with old unit
new_index = next(
i for i, d in enumerate(bess_data["units"]) if d["name"] == new_unit["name"]
)
bess_data["units"][new_index] = unit
return bess_data, bess_soc_for_cycle

View File

@ -104,7 +104,7 @@ if st.session_state.running:
) )
# display BESS data, SoC, Load Consumption # display BESS data, SoC, Load Consumption
show_table() show_table()
time.sleep(3) time.sleep(1)
st.rerun() st.rerun()
else: else:
show_table() show_table()

View File

@ -3,6 +3,7 @@ import yaml
from Utilities.Time import get_start_time from Utilities.Time import get_start_time
from Utilities.LoadProfile import get_load_profiles from Utilities.LoadProfile import get_load_profiles
from Utilities.BESS import ( from Utilities.BESS import (
arrange_swap,
initialise_SoC, initialise_SoC,
initial_site_assignment, initial_site_assignment,
discharge_bess, discharge_bess,
@ -46,7 +47,7 @@ sim_lock = threading.Lock()
# initialise BESS # initialise BESS
def _init_state(): def _init_state():
global bess_data, bess_soc_since_start, bess_soc_for_cycle, cumulative_load_profiles, load_profiles_since_start global bess_data, bess_soc_since_start, bess_soc_for_cycle, cumulative_load_profiles, load_profiles_since_start, init_df
bd = initialise_SoC(bess_data.copy()) bd = initialise_SoC(bess_data.copy())
bd = initial_site_assignment(c, bd) bd = initial_site_assignment(c, bd)
@ -109,6 +110,11 @@ def simulation_loop():
) )
swap_times = predict_swap_time(bess_soc_for_cycle) swap_times = predict_swap_time(bess_soc_for_cycle)
# trigger swap if needed
bess_data, bess_soc_for_cycle = arrange_swap(
c, bess_data, bess_soc_for_cycle
)
# integrate newly fetched profiles # integrate newly fetched profiles
if is_running_in_async and future.done(): if is_running_in_async and future.done():
load_profiles = future.result() load_profiles = future.result()