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
25 changes: 12 additions & 13 deletions packages/modules/chargepoints/openwb_pro/chargepoint_module.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,18 @@ def set_current(self, current: float) -> None:

def get_values(self) -> None:
with SingleComponentUpdateContext(self.fault_state):
chargepoint_state = self.request_values()
if chargepoint_state is not None:
# bei Fehler, aber Fehlezähler noch nicht abgelaufen, keine Werte mehr publishen.
self.store.set(chargepoint_state)
try:
chargepoint_state = self.request_values()
if chargepoint_state is not None:
# bei Fehler, aber Fehlezähler noch nicht abgelaufen, keine Werte mehr publishen.
self.store.set(chargepoint_state)
except Exception as e:
if self.client_error_context.error_counter_exceeded():
chargepoint_state = ChargepointState(plug_state=False, charge_state=False, imported=None,
# bei im-/exported None werden keine Werte gepublished
exported=None, phases_in_use=0, power=0, currents=[0]*3)
self.store.set(chargepoint_state)
raise e

def request_values(self) -> ChargepointState:
with self.client_error_context:
Expand Down Expand Up @@ -113,15 +121,6 @@ def request_values(self) -> ChargepointState:
self.validate_values(chargepoint_state)
self.client_error_context.reset_error_counter()
return chargepoint_state
if self.client_error_context.error_counter_exceeded():
chargepoint_state = ChargepointState()
chargepoint_state.plug_state = False
chargepoint_state.charge_state = False
chargepoint_state.imported = None # bei None werden keine Werte gepublished
chargepoint_state.exported = None
return chargepoint_state
else:
return None

def validate_values(self, chargepoint_state: ChargepointState) -> None:
if chargepoint_state.charge_state is False and max(chargepoint_state.currents) > 1:
Expand Down
40 changes: 27 additions & 13 deletions packages/modules/internal_chargepoint_handler/pro_plus.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@


class ProPlus(ChargepointModule):
NO_DATA_SINCE_BOOT = "Es konnten seit dem Start keine Daten abgefangen werden."
NO_CONNECTION_TO_INTERNAL_CP = "Interner Ladepunkt ist nicht erreichbar."

def __init__(self, local_charge_point_num: int,
internal_cp: InternalChargepoint,
hierarchy_id: int) -> None:
Expand All @@ -17,30 +20,41 @@ def __init__(self, local_charge_point_num: int,
self.old_chargepoint_state = None

super().__init__(OpenWBPro(configuration=OpenWBProConfiguration(ip_address="192.168.192.50")))
super().set_internal_context_handlers(hierarchy_id, internal_cp)
self.set_internal_context_handlers(hierarchy_id, internal_cp)

def get_values(self, phase_switch_cp_active: bool, last_tag: str) -> ChargepointState:
def store_state(chargepoint_state: ChargepointState) -> None:
self.store.set(chargepoint_state)
self.store.update()
self.store_internal.set(chargepoint_state)
self.store_internal.update()
self.old_chargepoint_state = chargepoint_state

try:
chargepoint_state = super().request_values()
chargepoint_state = self.request_values()
if chargepoint_state is not None and last_tag is not None and last_tag != "":
chargepoint_state.rfid = last_tag
except (requests.exceptions.ConnectTimeout, requests.exceptions.ConnectionError):
raise Exception("Interner Ladepunkt ist nicht erreichbar.")

if chargepoint_state is None:
if self.old_chargepoint_state is None:
raise Exception("Keine erfolgreiche Auslesung der Daten seit dem Start möglich.")
# bei Fehler, aber Fehlerzähler noch nicht abgelaufen
chargepoint_state = self.old_chargepoint_state
store_state(chargepoint_state)
self.old_chargepoint_state = chargepoint_state
return chargepoint_state
if chargepoint_state is not None:
store_state(chargepoint_state)
return chargepoint_state
else:
store_state(self.old_chargepoint_state)
return self.old_chargepoint_state
except Exception as e:
if self.client_error_context.error_counter_exceeded():
chargepoint_state = ChargepointState(plug_state=False, charge_state=False, imported=None,
# bei im-/exported None werden keine Werte gepublished
exported=None, phases_in_use=0, power=0, currents=[0]*3)
store_state(chargepoint_state)
if isinstance(e, (requests.exceptions.ConnectTimeout, requests.exceptions.ConnectionError)):
raise Exception(self.NO_CONNECTION_TO_INTERNAL_CP)
else:
raise e
elif self.old_chargepoint_state is not None:
store_state(self.old_chargepoint_state)
return self.old_chargepoint_state
else:
raise Exception(self.NO_DATA_SINCE_BOOT)

def perform_phase_switch(self, phases_to_use: int, duration: int) -> None:
super().switch_phases(phases_to_use, duration)
Expand Down
75 changes: 75 additions & 0 deletions packages/modules/internal_chargepoint_handler/pro_plus_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import re
from typing import Callable, Tuple
from unittest.mock import Mock

import pytest
from modules.common.component_state import ChargepointState
from modules.internal_chargepoint_handler.internal_chargepoint_handler_config import InternalChargepoint
from modules.internal_chargepoint_handler.pro_plus import ProPlus


@pytest.fixture(autouse=True)
def setup_pro_plus(monkeypatch) -> Tuple[ProPlus, Mock]:
pro_plus = ProPlus(0, InternalChargepoint(), 1)
mock_store_set = Mock()
monkeypatch.setattr(pro_plus.store, "set", mock_store_set)
monkeypatch.setattr(pro_plus.store, "update", lambda: None)
monkeypatch.setattr(pro_plus.store_internal, "set", lambda x: None)
monkeypatch.setattr(pro_plus.store_internal, "update", lambda: None)
return pro_plus, mock_store_set


@pytest.fixture()
def chargepoint_state() -> ChargepointState:
return ChargepointState(currents=[0, 0, 0], powers=[0, 0, 0], voltages=[
229.4, 229.4, 229.4], imported=0, exported=0, power=0, phases_in_use=2, charge_state=False, plug_state=True)


@pytest.mark.parametrize(
"request_values_return, expected_chargepoint_state",
[pytest.param(lambda: chargepoint_state, chargepoint_state, id="Normalfall"),
pytest.param(Mock(side_effect=Exception(ProPlus.NO_CONNECTION_TO_INTERNAL_CP)),
chargepoint_state, id="Fehler, aber Timer noch nicht abgelaufen")])
def test_get_values(request_values_return: ChargepointState,
expected_chargepoint_state: ChargepointState,
setup_pro_plus: Callable[[], Tuple[ProPlus, Mock]],
monkeypatch):
# setup
pro_plus, mock_store_set = setup_pro_plus
pro_plus.old_chargepoint_state = expected_chargepoint_state
monkeypatch.setattr(pro_plus, "request_values", request_values_return)
monkeypatch.setattr(pro_plus.client_error_context, "error_counter_exceeded", lambda: False)

# execution
chargepoint_state = pro_plus.get_values(False, None)

# evalutation
assert chargepoint_state == expected_chargepoint_state
assert mock_store_set.call_args.args[0].__dict__ == expected_chargepoint_state.__dict__


def test_get_values_no_data_since_boot(setup_pro_plus: Callable[[], Tuple[ProPlus, Mock]], monkeypatch):
# setup
pro_plus = setup_pro_plus[0]
monkeypatch.setattr(pro_plus, "request_values", Mock(side_effect=Exception(ProPlus.NO_CONNECTION_TO_INTERNAL_CP)))
monkeypatch.setattr(pro_plus.client_error_context, "error_counter_exceeded", lambda: False)

# execution
with pytest.raises(Exception, match=re.escape(ProPlus.NO_DATA_SINCE_BOOT)):
pro_plus.get_values(False, None)


def test_get_values_error_timer_exceed(setup_pro_plus: Callable[[], Tuple[ProPlus, Mock]], monkeypatch):
# Exception werfen und Ladepunkt-Status zurücksetzen
# setup
pro_plus, mock_store_set = setup_pro_plus
monkeypatch.setattr(pro_plus, "request_values", Mock(side_effect=Exception(ProPlus.NO_CONNECTION_TO_INTERNAL_CP)))
monkeypatch.setattr(pro_plus.client_error_context, "error_counter_exceeded", lambda: True)

# execution
with pytest.raises(Exception, match=re.escape(ProPlus.NO_CONNECTION_TO_INTERNAL_CP)):
pro_plus.get_values(False, None)

assert mock_store_set.call_args.args[0].__dict__ == ChargepointState(
plug_state=False, charge_state=False, imported=None, exported=None,
phases_in_use=0, power=0, currents=[0]*3).__dict__