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
2 changes: 1 addition & 1 deletion packages/control/algorithm/algorithm.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def _check_auto_phase_switch_delay(self) -> None:
"""
for cp in data.data.cp_data.values():
try:
if cp.data.set.charging_ev != -1:
if cp.data.control_parameter.required_current != 0:
charging_ev = cp.data.set.charging_ev_data
control_parameter = cp.data.control_parameter
if cp.cp_state_hw_support_phase_switch() and control_parameter.template_phases == 0:
Expand Down
2 changes: 1 addition & 1 deletion packages/control/algorithm/filter_chargepoints.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def get_chargepoints_by_mode(mode_tuple: Tuple[Optional[str], str, bool]) -> Lis
# enthält alle LP, auf die das Tupel zutrifft
valid_chargepoints = []
for cp in data.data.cp_data.values():
if cp.data.set.charging_ev != -1:
if cp.data.control_parameter.required_current != 0:
if ((cp.data.control_parameter.prio == prio) and
(cp.data.control_parameter.chargemode == mode or
mode is None) and
Expand Down
29 changes: 14 additions & 15 deletions packages/control/algorithm/filter_chargepoints_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,42 +96,41 @@ def mock_cp(cp: Chargepoint, num: int):


@pytest.mark.parametrize(
"set_mode_tuple, charging_ev_1, mode_tuple_1, charging_ev_2, mode_tuple_2, expected_valid_chargepoints",
"set_mode_tuple, required_current_1, mode_tuple_1, mode_tuple_2, expected_valid_chargepoints",
[
pytest.param((Chargemode.SCHEDULED_CHARGING, Chargemode.INSTANT_CHARGING, False),
1, (Chargemode.SCHEDULED_CHARGING,
6, (Chargemode.SCHEDULED_CHARGING,
Chargemode.INSTANT_CHARGING, False),
1, (Chargemode.SCHEDULED_CHARGING,
(Chargemode.SCHEDULED_CHARGING,
Chargemode.INSTANT_CHARGING, False),
[mock_cp1, mock_cp2], id="fits mode"),
pytest.param((Chargemode.SCHEDULED_CHARGING, Chargemode.INSTANT_CHARGING, False),
-1, (Chargemode.SCHEDULED_CHARGING,
Chargemode.INSTANT_CHARGING, False),
1, (Chargemode.SCHEDULED_CHARGING,
0, (Chargemode.SCHEDULED_CHARGING,
Chargemode.INSTANT_CHARGING, False),
[mock_cp2], id="cp1 has no charging car"),
(Chargemode.SCHEDULED_CHARGING,
Chargemode.INSTANT_CHARGING, False),
[mock_cp2], id="cp1 should not charge"),
pytest.param((Chargemode.SCHEDULED_CHARGING, Chargemode.INSTANT_CHARGING, False),
1, (Chargemode.SCHEDULED_CHARGING,
6, (Chargemode.SCHEDULED_CHARGING,
Chargemode.INSTANT_CHARGING, False),
1, (Chargemode.SCHEDULED_CHARGING,
(Chargemode.SCHEDULED_CHARGING,
Chargemode.INSTANT_CHARGING, True),
[mock_cp1], id="cp2 is prioritized")
])
def test_get_chargepoints_by_mode(set_mode_tuple: Tuple[Optional[str], str, bool],
charging_ev_1: int,
required_current_1: int,
mode_tuple_1: Tuple[str, str, bool],
charging_ev_2: int,
mode_tuple_2: Tuple[str, str, bool],
expected_valid_chargepoints):
# setup
def setup_cp(cp: Chargepoint, charging_ev: int, mode_tuple: Tuple[str, str, bool]) -> Chargepoint:
cp.data.set.charging_ev = charging_ev
def setup_cp(cp: Chargepoint, required_current: float, mode_tuple: Tuple[str, str, bool]) -> Chargepoint:
cp.data.control_parameter.required_current = required_current
cp.data.control_parameter.prio = mode_tuple[2]
cp.data.control_parameter.chargemode = mode_tuple[0]
cp.data.control_parameter.submode = mode_tuple[1]
return cp
data.data.cp_data = {"cp1": setup_cp(mock_cp1, charging_ev_1, mode_tuple_1),
"cp2": setup_cp(mock_cp2, charging_ev_2, mode_tuple_2)}
data.data.cp_data = {"cp1": setup_cp(mock_cp1, required_current_1, mode_tuple_1),
"cp2": setup_cp(mock_cp2, 6, mode_tuple_2)}

# evaluation
valid_chargepoints = filter_chargepoints.get_chargepoints_by_mode(set_mode_tuple)
Expand Down
1 change: 0 additions & 1 deletion packages/control/algorithm/integration_test/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ def data_() -> None:
for i in range(3, 6):
data.data.cp_data[f"cp{i}"].template = CpTemplate()
data.data.cp_data[f"cp{i}"].data.config.phase_1 = i-2
data.data.cp_data[f"cp{i}"].data.set.charging_ev = i
data.data.cp_data[f"cp{i}"].data.set.charging_ev_data = Ev(i)
data.data.cp_data[f"cp{i}"].data.set.charging_ev_data.ev_template.data.max_current_single_phase = 32
data.data.cp_data[f"cp{i}"].data.get.plug_state = True
Expand Down
3 changes: 2 additions & 1 deletion packages/control/algorithm/surplus_controlled_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,9 +140,10 @@ def test_get_chargepoints_submode_pv_charging(submode_1: Chargemode,
expected_chargepoints: List[Chargepoint]):
# setup
def setup_cp(cp: Chargepoint, submode: str) -> Chargepoint:
cp.data.set.charging_ev = Ev(0)
cp.data.set.charging_ev_data = Ev(0)
cp.data.control_parameter.chargemode = Chargemode.PV_CHARGING
cp.data.control_parameter.submode = submode
cp.data.control_parameter.required_current = 6
return cp
data.data.cp_data = {"cp1": setup_cp(mock_cp1, submode_1),
"cp2": setup_cp(mock_cp2, submode_2)}
Expand Down
19 changes: 5 additions & 14 deletions packages/control/chargelog/chargelog.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,16 +125,14 @@ def save_interim_data(chargepoint, charging_ev, immediately: bool = True):
try:
log_data = chargepoint.data.set.log
# Es wurde noch nie ein Auto zugeordnet
if charging_ev == -1:
return
if log_data.imported_since_mode_switch == 0:
# Die Daten wurden schon erfasst.
return
if not immediately:
if chargepoint.data.get.power != 0:
# Das Fahrzeug hat die Ladung noch nicht beendet. Der Logeintrag wird später erstellt.
return
save_data(chargepoint, charging_ev, immediately)
save_data(chargepoint, charging_ev)
chargepoint.reset_log_data_chargemode_switch()
except Exception:
log.exception("Fehler im Ladelog-Modul")
Expand All @@ -154,16 +152,13 @@ def save_and_reset_data(chargepoint, charging_ev, immediately: bool = True):
Soll sofort ein Eintrag erstellt werden oder gewartet werden, bis die Ladung beendet ist.
"""
try:
if charging_ev == -1:
# Es wurde noch nie ein Auto zugeordnet.
return
if not immediately:
if chargepoint.data.get.power != 0:
# Das Fahrzeug hat die Ladung noch nicht beendet. Der Logeintrag wird später erstellt.
return
if chargepoint.data.set.log.imported_since_mode_switch > 0:
# Die Daten wurden noch nicht erfasst.
save_data(chargepoint, charging_ev, immediately)
save_data(chargepoint, charging_ev)
chargepoint.reset_log_data()
except Exception:
log.exception("Fehler im Ladelog-Modul")
Expand All @@ -187,7 +182,7 @@ def _get_range_charged(log_data, charging_ev) -> float:
charging_ev.ev_template.data.average_consump), 2))


def save_data(chargepoint, charging_ev, immediately: bool = True):
def save_data(chargepoint, charging_ev):
""" json-Objekt für den Log-Eintrag erstellen, an die Datei anhängen und die Daten, die sich auf den Ladevorgang
beziehen, löschen.

Expand All @@ -198,17 +193,13 @@ def save_data(chargepoint, charging_ev, immediately: bool = True):
charging_ev: class
EV, das an diesem Ladepunkt lädt. (Wird extra übergeben, da es u.U. noch nicht zugewiesen ist und nur die
Nummer aus dem Broker in der LP-Klasse hinterlegt ist.)
reset: bool
Wenn die Daten komplett zurückgesetzt werden, wird nicht der Zwischenzählerstand für
imported_at_mode_switch notiert. Sonst schon, damit zwischen save_data und dem nächsten collect_data keine
Daten verloren gehen.
"""
if chargepoint.data.set.log.imported_since_mode_switch != 0:
new_entry = _create_entry(chargepoint, charging_ev, immediately)
new_entry = _create_entry(chargepoint, charging_ev)
write_new_entry(new_entry)


def _create_entry(chargepoint, charging_ev, immediately: bool = True):
def _create_entry(chargepoint, charging_ev):
log_data = chargepoint.data.set.log
# Daten vor dem Speichern nochmal aktualisieren, auch wenn nicht mehr geladen wird.
log_data.imported_since_plugged = get_value_or_default(lambda: round(
Expand Down
94 changes: 27 additions & 67 deletions packages/control/chargepoint/chargepoint.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,3 @@
"""Ladepunkt-Logik

charging_ev: EV, das aktuell laden darf
charging_ev_prev: EV, das vorher geladen hat. Dies wird benötigt, da wenn das EV nicht mehr laden darf, z.B. weil
Autolock aktiv ist, gewartet werden muss, bis die Ladeleistung 0 ist und dann erst der Eintrag im Protokoll erstellt
werden kann.
charging_ev = -1 zeigt an, dass der LP im Algorithmus nicht berücksichtigt werden soll. Ist das Ev abgesteckt, wird
auch charging_ev_prev -1 und im nächsten Zyklus kann ein neues Profil geladen werden.

ID-Tag/Code-Eingabe:
Mit einem ID-Tag/Code kann optional der Ladepunkt freigeschaltet werden, es wird gleichzeitig immer ein EV damit
zugeordnet, mit dem nach der Freischaltung geladen werden soll. Wenn max 5 Min nach dem Scannen kein Auto
angesteckt wird, wird der Tag verworfen. Ebenso wenn kein EV gefunden wird.
Tag-Liste: Tags, mit denen der Ladepunkt freigeschaltet werden kann. Ist diese leer, kann mit jedem Tag der Ladepunkt
freigeschaltet werden.
"""
from dataclasses import asdict
import dataclasses
import logging
Expand Down Expand Up @@ -215,41 +199,28 @@ def _process_charge_stop(self) -> None:
self.data.set.ocpp_transaction_id,
self.data.set.rfid)
Pub().pub("openWB/set/chargepoint/"+str(self.num)+"/set/ocpp_transaction_id", None)
if self.data.set.charging_ev_prev != -1:
# Daten zurücksetzen, wenn nicht geladen werden soll.
self.reset_control_parameter_at_charge_stop()
data.data.counter_all_data.get_evu_counter().reset_switch_on_off(
self, data.data.ev_data["ev"+str(self.data.set.charging_ev_prev)])
# Abstecken
if not self.data.get.plug_state:
self.data.control_parameter = control_parameter_factory()
# Standardprofil nach Abstecken laden
if self.data.set.charge_template.data.load_default:
self.data.config.ev = 0
Pub().pub("openWB/set/chargepoint/"+str(self.num)+"/config/ev", 0)
# Ladepunkt nach Abstecken sperren
if self.template.data.disable_after_unplug:
self.data.set.manual_lock = True
Pub().pub("openWB/set/chargepoint/"+str(self.num)+"/set/manual_lock", True)
log.debug("/set/manual_lock True")
# Ev wurde noch nicht aktualisiert.
# Ladeprofil aus den Einstellungen laden.
if data.data.general_data.data.temporary_charge_templates_active:
self.update_charge_template(
data.data.ev_data["ev"+str(self.data.set.charging_ev_prev)].charge_template)
chargelog.save_and_reset_data(self, data.data.ev_data["ev"+str(self.data.set.charging_ev_prev)])
self.data.set.charging_ev_prev = -1
Pub().pub("openWB/set/chargepoint/"+str(self.num)+"/set/charging_ev_prev",
self.data.set.charging_ev_prev)
self.data.set.rfid = None
Pub().pub("openWB/set/chargepoint/"+str(self.num)+"/set/rfid", None)
self.data.set.plug_time = None
Pub().pub("openWB/set/chargepoint/"+str(self.num)+"/set/plug_time", None)
self.data.set.phases_to_use = self.data.get.phases_in_use
Pub().pub("openWB/set/chargepoint/"+str(self.num)+"/set/phases_to_use",
self.data.set.phases_to_use)
self.data.set.charging_ev = -1
Pub().pub("openWB/set/chargepoint/"+str(self.num)+"/set/charging_ev", -1)
self.reset_control_parameter_at_charge_stop()
data.data.counter_all_data.get_evu_counter().reset_switch_on_off(self)
if self.data.get.plug_state is False:
self.data.control_parameter = control_parameter_factory()
if self.data.set.charge_template.data.load_default:
self.data.config.ev = 0
Pub().pub("openWB/set/chargepoint/"+str(self.num)+"/config/ev", 0)
if self.template.data.disable_after_unplug:
self.data.set.manual_lock = True
Pub().pub("openWB/set/chargepoint/"+str(self.num)+"/set/manual_lock", True)
log.debug("/set/manual_lock True")
if data.data.general_data.data.temporary_charge_templates_active:
self.update_charge_template(
data.data.ev_data["ev"+str(self.data.config.ev)].charge_template)
chargelog.save_and_reset_data(self, data.data.ev_data["ev"+str(self.data.config.ev)])
self.data.set.rfid = None
Pub().pub("openWB/set/chargepoint/"+str(self.num)+"/set/rfid", None)
self.data.set.plug_time = None
Pub().pub("openWB/set/chargepoint/"+str(self.num)+"/set/plug_time", None)
self.data.set.phases_to_use = self.data.get.phases_in_use
Pub().pub("openWB/set/chargepoint/"+str(self.num)+"/set/phases_to_use",
self.data.set.phases_to_use)
self.data.set.current = 0
Pub().pub("openWB/set/chargepoint/"+str(self.num)+"/set/current", 0)
self.data.set.energy_to_charge = 0
Expand Down Expand Up @@ -710,8 +681,7 @@ def update(self, ev_list: Dict[str, Ev]) -> None:
self.check_phase_switch_completed()

if self.chargemode_changed or self.submode_changed:
data.data.counter_all_data.get_evu_counter().reset_switch_on_off(
self, charging_ev)
data.data.counter_all_data.get_evu_counter().reset_switch_on_off(self)
charging_ev.reset_phase_switch(self.data.control_parameter)
if self.chargemode_changed:
self.data.control_parameter.failed_phase_switches = 0
Expand All @@ -724,14 +694,6 @@ def update(self, ev_list: Dict[str, Ev]) -> None:
# Wenn die Nachrichten gesendet wurden, EV wieder löschen, wenn das EV im Algorithmus nicht
# berücksichtigt werden soll.
if not state:
if self.data.set.charging_ev != -1:
# Altes EV merken
self.data.set.charging_ev_prev = self.data.set.charging_ev
Pub().pub("openWB/set/chargepoint/"+str(self.num) +
"/set/charging_ev_prev", self.data.set.charging_ev_prev)
self.data.set.charging_ev = -1
Pub().pub("openWB/set/chargepoint/" +
str(self.num)+"/set/charging_ev", -1)
log.debug(f'LP {self.num}, EV: {self.data.set.charging_ev_data.data.name}'
f' (EV-Nr.{vehicle}): Lademodus '
f'{self.data.set.charge_template.data.chargemode.selected}, Submodus: '
Expand Down Expand Up @@ -816,18 +778,16 @@ def _get_charging_ev(self, vehicle: int, ev_list: Dict[str, Ev]) -> Ev:
" verwendet.")
charging_ev = ev_list["ev0"]
vehicle = 0
if self.data.set.charging_ev_prev != vehicle:
if self.data.config.ev != vehicle:
Pub().pub(f"openWB/set/vehicle/{charging_ev.num}/get/force_soc_update", True)
log.debug("SoC nach EV-Wechsel")
# wenn vorher kein anderes Fahrzeug zugeordnet war, Ladeprofil nicht zurücksetzen
if ((self.data.set.charging_ev_prev != vehicle and self.data.set.charging_ev_prev != -1) or
if (self.data.config.ev != vehicle or
(self.data.set.charge_template.data.id != charging_ev.charge_template.data.id)):
self.update_charge_template(charging_ev.charge_template)
self.data.set.charging_ev_data = charging_ev
self.data.set.charging_ev = vehicle
Pub().pub("openWB/set/chargepoint/"+str(self.num)+"/set/charging_ev", vehicle)
self.data.set.charging_ev_prev = vehicle
Pub().pub("openWB/set/chargepoint/"+str(self.num)+"/set/charging_ev_prev", vehicle)
self.data.config.ev = vehicle
Pub().pub(f"openWB/set/chargepoint/{self.num}/config", dataclasses.asdict(self.data.config))
return charging_ev

def update_charge_template(self, charge_template: ChargeTemplate) -> None:
Expand Down
7 changes: 3 additions & 4 deletions packages/control/chargepoint/chargepoint_all.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,12 @@ def no_charge(self):
control_parameter = chargepoint.data.control_parameter
if (not chargepoint.data.get.plug_state or
# Kein EV, das Laden soll
chargepoint.data.set.charging_ev == -1 or
# Kein EV, das auf das Ablaufen der Einschalt- oder Phasenumschaltverzögerung wartet
(chargepoint.data.set.charging_ev != -1 and
control_parameter.state != ChargepointState.PERFORMING_PHASE_SWITCH and
(control_parameter.state != ChargepointState.PERFORMING_PHASE_SWITCH and
control_parameter.state != ChargepointState.PHASE_SWITCH_DELAY and
control_parameter.state != ChargepointState.SWITCH_OFF_DELAY and
control_parameter.state != ChargepointState.SWITCH_ON_DELAY)):
control_parameter.state != ChargepointState.SWITCH_ON_DELAY and
control_parameter.state != ChargepointState.NO_CHARGING_ALLOWED)):
continue
else:
break
Expand Down
2 changes: 0 additions & 2 deletions packages/control/chargepoint/chargepoint_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,6 @@ def log_factory() -> Log:

@dataclass
class Set:
charging_ev: int = -1
charging_ev_prev: int = -1
charge_template: ChargeTemplate = field(default_factory=charge_template_factory)
current: float = 0
energy_to_charge: float = 0
Expand Down
3 changes: 1 addition & 2 deletions packages/control/chargepoint/chargepoint_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,6 @@ def get_ev(self, rfid: str, vehicle_id: str, assigned_ev: int) -> int:
message: str
Status-Text
"""
num = -1
message = None
try:
if data.data.optional_data.data.rfid.active and (rfid is not None or vehicle_id is not None):
Expand All @@ -103,4 +102,4 @@ def get_ev(self, rfid: str, vehicle_id: str, assigned_ev: int) -> int:
except Exception:
log.exception(
"Fehler in der Ladepunkt-Profil Klasse")
return num, "Keine Ladung, da ein interner Fehler aufgetreten ist: " + traceback.format_exc()
return assigned_ev, "Keine Ladung, da ein interner Fehler aufgetreten ist: " + traceback.format_exc()
Loading