Skip to content
Merged
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
8 changes: 7 additions & 1 deletion packages/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,13 @@
from control.counter_all import CounterAll
from control.pv import Pv, PvData
from control.pv import Get as PvGet
from helpermodules import pub, timecheck
from helpermodules import hardware_configuration, pub, timecheck


@pytest.fixture(autouse=True)
def mock_open_file(monkeypatch) -> None:
mock_config = Mock(return_value={"dc_charging": False, "openwb-version": 1, "max_c_socket": 32})
monkeypatch.setattr(hardware_configuration, "_read_configuration", mock_config)


@pytest.fixture(autouse=True)
Expand Down
11 changes: 8 additions & 3 deletions packages/control/algorithm/additional_current.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,15 @@ def set_additional_current(self) -> None:
cp = preferenced_chargepoints[0]
missing_currents, counts = common.get_missing_currents_left(preferenced_chargepoints)
available_currents, limit = Loadmanagement().get_available_currents(missing_currents, counter)
log.debug(f"cp {cp.num} available currents {available_currents} missing currents "
f"{missing_currents} limit {limit}")
cp.data.control_parameter.limit = limit
available_for_cp = common.available_current_for_cp(cp, counts, available_currents, missing_currents)
current = common.get_current_to_set(
cp.data.set.current, available_for_cp, cp.data.set.target_current)
self._set_loadmangement_message(current, limit, cp, counter)
common.set_current_counterdiff(
current - cp.data.set.charging_ev_data.ev_template.data.min_current,
cp.data.control_parameter.min_current,
current,
cp)
preferenced_chargepoints.pop(0)
Expand All @@ -50,9 +52,12 @@ def _set_loadmangement_message(self,
chargepoint: Chargepoint,
counter: Counter) -> None:
# Strom muss an diesem Zähler geändert werden
log.debug(
f"current {current} target {chargepoint.data.set.target_current} set current {chargepoint.data.set.current}"
f" required currents {chargepoint.data.control_parameter.required_currents}")
if (current != max(chargepoint.data.set.target_current, chargepoint.data.set.current or 0) and
# Strom erreicht nicht die vorgegebene Stromstärke
current != max(
chargepoint.data.control_parameter.required_currents)):
round(current, 2) != round(max(
chargepoint.data.control_parameter.required_currents), 2)):
chargepoint.set_state_and_log(f"Es kann nicht mit der vorgegebenen Stromstärke geladen werden"
f"{limit.value.format(get_component_name_by_id(counter.num))}")
48 changes: 31 additions & 17 deletions packages/control/algorithm/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from control.chargemode import Chargemode
from control.chargepoint.chargepoint import Chargepoint
from control.counter import Counter
from helpermodules.timecheck import check_timestamp
from modules.common.component_type import ComponentType

log = logging.getLogger(__name__)
Expand All @@ -29,6 +30,8 @@
(None, Chargemode.STOP, True),
(None, Chargemode.STOP, False))

LESS_CHARGING_TIMEOUT = 60

# tested


Expand Down Expand Up @@ -62,21 +65,27 @@ def mode_and_counter_generator(chargemodes: List) -> Iterable[Tuple[Tuple[Option
def get_min_current(chargepoint: Chargepoint) -> Tuple[List[float], List[int]]:
min_currents = [0.0]*3
counts = [0]*3
charging_ev_data = chargepoint.data.set.charging_ev_data
required_currents = chargepoint.data.control_parameter.required_currents
for i in range(3):
if required_currents[i] != 0:
counts[i] += 1
min_currents[i] = charging_ev_data.ev_template.data.min_current
min_currents[i] = chargepoint.data.control_parameter.min_current
else:
min_currents[i] = 0
return min_currents, counts

# tested


def set_current_counterdiff(diff: float, current: float, chargepoint: Chargepoint, surplus: bool = False) -> None:
def set_current_counterdiff(diff_curent: float,
current: float,
chargepoint: Chargepoint,
surplus: bool = False) -> None:
required_currents = chargepoint.data.control_parameter.required_currents
considered_current = consider_less_charging_chargepoint_in_loadmanagement(
chargepoint, current)
# gar nicht ladende Autos?
diff = max(considered_current - diff_curent, 0)
diffs = [diff if required_currents[i] != 0 else 0 for i in range(3)]
if max(diffs) > 0:
counters = data.data.counter_all_data.get_counters_to_check(chargepoint.num)
Expand Down Expand Up @@ -129,21 +138,20 @@ def update_raw_data(preferenced_chargepoints: List[Chargepoint],
"""alle CP, die schon einen Sollstrom haben, wieder rausrechnen, da dieser neu gesetzt wird
und die neue Differenz bei den Zählern eingetragen wird."""
for chargepoint in preferenced_chargepoints:
if consider_not_charging_chargepoint_in_loadmanagement(chargepoint):
continue
charging_ev_data = chargepoint.data.set.charging_ev_data
required_currents = chargepoint.data.control_parameter.required_currents
max_target_set_current = max(chargepoint.data.set.target_current, chargepoint.data.set.current or 0)
max_target_set_current = consider_less_charging_chargepoint_in_loadmanagement(
chargepoint, max_target_set_current)

if diff_to_zero is False:
if charging_ev_data.ev_template.data.min_current < max_target_set_current:
diffs = [charging_ev_data.ev_template.data.min_current -
if chargepoint.data.control_parameter.min_current < max_target_set_current:
diffs = [chargepoint.data.control_parameter.min_current -
max_target_set_current if required_currents[i] != 0 else 0 for i in range(3)]
else:
continue
else:
if charging_ev_data.ev_template.data.min_current <= max_target_set_current:
diffs = [-charging_ev_data.ev_template.data.min_current if required_currents[i]
if chargepoint.data.control_parameter.min_current <= max_target_set_current:
diffs = [-chargepoint.data.control_parameter.min_current if required_currents[i]
!= 0 else 0 for i in range(3)]
else:
continue
Expand All @@ -155,26 +163,32 @@ def update_raw_data(preferenced_chargepoints: List[Chargepoint],
data.data.counter_data[counter].update_values_left(diffs)


def consider_not_charging_chargepoint_in_loadmanagement(cp: Chargepoint) -> bool:
# tested
return data.data.counter_all_data.data.config.reserve_for_not_charging is False and max(cp.data.get.currents) == 0

def consider_less_charging_chargepoint_in_loadmanagement(cp: Chargepoint, set_current: float) -> bool:
if (data.data.counter_all_data.data.config.consider_less_charging and
((set_current -
cp.data.set.charging_ev_data.ev_template.data.nominal_difference) > max(cp.data.get.currents) and
cp.data.control_parameter.timestamp_charge_start is not None and
check_timestamp(cp.data.control_parameter.timestamp_charge_start, LESS_CHARGING_TIMEOUT) is False)):
log.debug(
f"LP {cp.num} lädt deutlich unter dem Sollstrom und wird nur mit {cp.data.get.currents}A berücksichtigt.")
return max(cp.data.get.currents)
else:
return set_current
# tested


def get_missing_currents_left(preferenced_chargepoints: List[Chargepoint]) -> Tuple[List[float], List[int]]:
missing_currents = [0.0]*3
counts = [0]*3
for chargepoint in preferenced_chargepoints:
charging_ev_data = chargepoint.data.set.charging_ev_data
required_currents = chargepoint.data.control_parameter.required_currents
for i in range(0, 3):
if required_currents[i] != 0:
counts[i] += 1
try:
missing_currents[i] += required_currents[i] - charging_ev_data.ev_template.data.min_current
missing_currents[i] += required_currents[i] - chargepoint.data.control_parameter.min_current
except KeyError:
missing_currents[i] += max(required_currents) - charging_ev_data.ev_template.data.min_current
missing_currents[i] += max(required_currents) - chargepoint.data.control_parameter.min_current
else:
missing_currents[i] += 0
return missing_currents, counts
Expand Down
32 changes: 16 additions & 16 deletions packages/control/algorithm/common_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,9 @@ def test_reset_current(set_current: int, expected_current: int):
@pytest.mark.parametrize(
"diff, required_currents, expected_set_current, expected_diffs",
[
pytest.param(2, [10, 0, 0], 8, [2, 0, 0], id="set diff one phase"),
pytest.param(2, [12]*3, 8, [2]*3, id="set diff three phases"),
pytest.param(8, [8]*3, 8, [8]*3, id="set min current three phases"),
pytest.param(0, [8]*3, 8, [0]*3, id="min current is already set, three phases"),
pytest.param(10, [10, 0, 0], 10, [2, 0, 0], id="set diff one phase"),
pytest.param(10, [12]*3, 10, [2]*3, id="set diff three phases"),
pytest.param(8, [8]*3, 8, [0]*3, id="min current is already set, three phases"),
])
def test_set_current_counterdiff(diff: float,
required_currents: List[float],
Expand All @@ -55,11 +54,11 @@ def test_set_current_counterdiff(diff: float,
data.data.counter_data = {"cp0": Mock(spec=Counter), "cp6": Mock(spec=Counter)}

# evaluation
common.set_current_counterdiff(diff, 8, cp)
common.set_current_counterdiff(8, diff, cp)

# assertion
assert cp.data.set.current == expected_set_current
if diff != 0:
if max(expected_diffs) != 0:
assert data.data._counter_data['cp0'].update_values_left.call_args_list[0][0][0] == expected_diffs
assert data.data._counter_data['cp6'].update_values_left.call_args_list[0][0][0] == expected_diffs

Expand Down Expand Up @@ -152,23 +151,24 @@ def setup_cp(num: int, required_currents) -> Chargepoint:


@pytest.mark.parametrize(
"reserve_for_not_charging, get_currents, expected_considered",
"consider_less_charging, get_currents, expected_considered",
[
pytest.param(True, [0]*3, False, id="reserve_for_not_charging active"),
pytest.param(True, [6]*3, False, id="reserve_for_not_charging active"),
pytest.param(False, [0]*3, True, id="not charging"),
pytest.param(False, [6]*3, False, id="charging"),
pytest.param(True, [6]*3, 6, id="consider_less_charging active, charging less"),
pytest.param(True, [10]*3, 10, id="consider_less_charging active, charging with set current"),
pytest.param(False, [0]*3, 10, id="consider_less_charging inactive"),
])
def test_consider_not_charging_chargepoint_in_loadmanagement(reserve_for_not_charging: bool,
get_currents: List[float],
expected_considered: bool):
def test_consider_less_charging_chargepoint_in_loadmanagement(consider_less_charging: bool,
get_currents: List[float],
expected_considered: bool):
# setup
cp = Chargepoint(4, None)
cp.data.get.currents = get_currents
data.data.counter_all_data.data.config.reserve_for_not_charging = reserve_for_not_charging
cp.data.set.current = 10
cp.data.control_parameter.timestamp_charge_start = 1652683152
data.data.counter_all_data.data.config.consider_less_charging = consider_less_charging

# evaluation
considered = common.consider_not_charging_chargepoint_in_loadmanagement(cp)
considered = common.consider_less_charging_chargepoint_in_loadmanagement(cp, 10)

# assertion
assert considered == expected_considered
3 changes: 2 additions & 1 deletion packages/control/algorithm/integration_test/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ def data_() -> None:
data.data.cp_data[f"cp{i}"].data.set.plug_time = f"12/01/2022, 15:0{i}:11"
data.data.cp_data[f"cp{i}"].data.set.charging_ev_data.ev_template.data.nominal_difference = 2
data.data.cp_data["cp3"].data.set.charging_ev_data.ev_template.data.min_current = 10
data.data.cp_data["cp3"].data.control_parameter.min_current = 10
data.data.bat_data.update({"bat2": Bat(2), "all": BatAll()})
data.data.pv_data.update({"pv1": Pv(1)})
data.data.counter_data.update({
Expand All @@ -46,7 +47,7 @@ def data_() -> None:
data.data.counter_data["counter6"].data.config.max_total_power = 11000
data.data.counter_all_data = CounterAll()
data.data.counter_all_data.data.get.hierarchy = NESTED_HIERARCHY
data.data.counter_all_data.data.config.reserve_for_not_charging = True
data.data.counter_all_data.data.config.consider_less_charging = True


@dataclass
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
def all_cp_instant_charging_1p():
for i in range(3, 6):
control_parameter = data.data.cp_data[f"cp{i}"].data.control_parameter
control_parameter.min_current = data.data.cp_data[
f"cp{i}"].data.set.charging_ev_data.ev_template.data.min_current
control_parameter.required_currents = [0]*3
control_parameter.required_currents[i-3] = 16
control_parameter.required_current = 16
Expand All @@ -34,6 +36,8 @@ def all_cp_charging_1p():
def all_cp_instant_charging_3p():
for i in range(3, 6):
control_parameter = data.data.cp_data[f"cp{i}"].data.control_parameter
control_parameter.min_current = data.data.cp_data[
f"cp{i}"].data.set.charging_ev_data.ev_template.data.min_current
control_parameter.required_currents = [16]*3
control_parameter.required_current = 16
control_parameter.chargemode = Chargemode.INSTANT_CHARGING
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ def all_cp_pv_charging_3p():
f"cp{i}"].data.set.charging_ev_data.ev_template.data.min_current
control_parameter.required_currents = [
data.data.cp_data[f"cp{i}"].data.set.charging_ev_data.ev_template.data.min_current]*3
control_parameter.min_current = data.data.cp_data[
f"cp{i}"].data.set.charging_ev_data.ev_template.data.min_current
control_parameter.chargemode = Chargemode.PV_CHARGING
control_parameter.submode = Chargemode.PV_CHARGING
control_parameter.phases = 3
Expand Down Expand Up @@ -52,6 +54,8 @@ def all_cp_pv_charging_1p():
for i in range(3, 6):
control_parameter = data.data.cp_data[f"cp{i}"].data.control_parameter
charging_ev_data = data.data.cp_data[f"cp{i}"].data.set.charging_ev_data
control_parameter.min_current = data.data.cp_data[
f"cp{i}"].data.set.charging_ev_data.ev_template.data.min_current
control_parameter.required_current = data.data.cp_data[
f"cp{i}"].data.set.charging_ev_data.ev_template.data.min_current
control_parameter.required_currents = [0]*3
Expand Down
26 changes: 9 additions & 17 deletions packages/control/algorithm/min_current.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,24 +29,16 @@ def set_min_current(self) -> None:
cp, counts, available_currents, missing_currents)
current = common.get_current_to_set(
cp.data.set.current, available_for_cp, cp.data.set.target_current)
if common.consider_not_charging_chargepoint_in_loadmanagement(cp):
cp.data.set.current = cp.data.set.charging_ev_data.ev_template.data.min_current
log.debug(
f"LP{cp.num}: Stromstärke {cp.data.set.charging_ev_data.ev_template.data.min_current}"
"A. Zuteilung ohne Berücksichtigung im Lastmanagement, da kein Ladestart zu erwarten "
"ist und Reserve für nicht-ladende inaktiv.")
if current < cp.data.control_parameter.min_current:
common.set_current_counterdiff(-(cp.data.set.current or 0), 0, cp)
if limit:
cp.set_state_and_log(
f"Ladung kann nicht gestartet werden{limit.value.format(counter.num)}")
else:
if current < cp.data.set.charging_ev_data.ev_template.data.min_current:
common.set_current_counterdiff(-(cp.data.set.current or 0), 0, cp)
if limit:
cp.set_state_and_log(
f"Ladung kann nicht gestartet werden{limit.value.format(counter.num)}")
else:
common.set_current_counterdiff(
(cp.data.set.charging_ev_data.ev_template.data.min_current
- cp.data.set.target_current),
cp.data.set.charging_ev_data.ev_template.data.min_current,
cp)
common.set_current_counterdiff(
cp.data.set.target_current,
cp.data.control_parameter.min_current,
cp)
else:
cp.data.set.current = 0
preferenced_chargepoints.pop(0)
4 changes: 2 additions & 2 deletions packages/control/algorithm/surplus_controlled.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def _set(self,
limited_current = self._limit_adjust_current(cp, current)
limited_current = self._add_unused_evse_current(limited_current, cp)
common.set_current_counterdiff(
limited_current - cp.data.set.charging_ev_data.ev_template.data.min_current,
cp.data.control_parameter.min_current,
limited_current,
cp,
surplus=True)
Expand Down Expand Up @@ -107,7 +107,7 @@ def _limit_adjust_current(self, chargepoint: Chargepoint, new_current: float) ->
current = max(chargepoint.data.get.currents) + MAX_CURRENT
msg = "Es darf um max 5A über den aktuell genutzten Strom geregelt werden."
chargepoint.set_state_and_log(msg)
return max(current, chargepoint.data.set.charging_ev_data.ev_template.data.min_current)
return max(current, chargepoint.data.control_parameter.min_current)

def _add_unused_evse_current(self, limited_current, chargepoint: Chargepoint) -> float:
"""Wenn Autos nicht die volle Ladeleistung nutzen, wird unnötig eingespeist. Dann kann um den noch nicht
Expand Down
Loading