Skip to content

Commit c3e270b

Browse files
authored
fix pro error handling (#2708)
* fix pro error handling * fix
1 parent a5d8c11 commit c3e270b

3 files changed

Lines changed: 114 additions & 26 deletions

File tree

packages/modules/chargepoints/openwb_pro/chargepoint_module.py

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,18 @@ def set_current(self, current: float) -> None:
6363

6464
def get_values(self) -> None:
6565
with SingleComponentUpdateContext(self.fault_state):
66-
chargepoint_state = self.request_values()
67-
if chargepoint_state is not None:
68-
# bei Fehler, aber Fehlezähler noch nicht abgelaufen, keine Werte mehr publishen.
69-
self.store.set(chargepoint_state)
66+
try:
67+
chargepoint_state = self.request_values()
68+
if chargepoint_state is not None:
69+
# bei Fehler, aber Fehlezähler noch nicht abgelaufen, keine Werte mehr publishen.
70+
self.store.set(chargepoint_state)
71+
except Exception as e:
72+
if self.client_error_context.error_counter_exceeded():
73+
chargepoint_state = ChargepointState(plug_state=False, charge_state=False, imported=None,
74+
# bei im-/exported None werden keine Werte gepublished
75+
exported=None, phases_in_use=0, power=0, currents=[0]*3)
76+
self.store.set(chargepoint_state)
77+
raise e
7078

7179
def request_values(self) -> ChargepointState:
7280
with self.client_error_context:
@@ -113,15 +121,6 @@ def request_values(self) -> ChargepointState:
113121
self.validate_values(chargepoint_state)
114122
self.client_error_context.reset_error_counter()
115123
return chargepoint_state
116-
if self.client_error_context.error_counter_exceeded():
117-
chargepoint_state = ChargepointState()
118-
chargepoint_state.plug_state = False
119-
chargepoint_state.charge_state = False
120-
chargepoint_state.imported = None # bei None werden keine Werte gepublished
121-
chargepoint_state.exported = None
122-
return chargepoint_state
123-
else:
124-
return None
125124

126125
def validate_values(self, chargepoint_state: ChargepointState) -> None:
127126
if chargepoint_state.charge_state is False and max(chargepoint_state.currents) > 1:

packages/modules/internal_chargepoint_handler/pro_plus.py

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88

99

1010
class ProPlus(ChargepointModule):
11+
NO_DATA_SINCE_BOOT = "Es konnten seit dem Start keine Daten abgefangen werden."
12+
NO_CONNECTION_TO_INTERNAL_CP = "Interner Ladepunkt ist nicht erreichbar."
13+
1114
def __init__(self, local_charge_point_num: int,
1215
internal_cp: InternalChargepoint,
1316
hierarchy_id: int) -> None:
@@ -17,30 +20,41 @@ def __init__(self, local_charge_point_num: int,
1720
self.old_chargepoint_state = None
1821

1922
super().__init__(OpenWBPro(configuration=OpenWBProConfiguration(ip_address="192.168.192.50")))
20-
super().set_internal_context_handlers(hierarchy_id, internal_cp)
23+
self.set_internal_context_handlers(hierarchy_id, internal_cp)
2124

2225
def get_values(self, phase_switch_cp_active: bool, last_tag: str) -> ChargepointState:
2326
def store_state(chargepoint_state: ChargepointState) -> None:
2427
self.store.set(chargepoint_state)
2528
self.store.update()
2629
self.store_internal.set(chargepoint_state)
2730
self.store_internal.update()
31+
self.old_chargepoint_state = chargepoint_state
2832

2933
try:
30-
chargepoint_state = super().request_values()
34+
chargepoint_state = self.request_values()
3135
if chargepoint_state is not None and last_tag is not None and last_tag != "":
3236
chargepoint_state.rfid = last_tag
33-
except (requests.exceptions.ConnectTimeout, requests.exceptions.ConnectionError):
34-
raise Exception("Interner Ladepunkt ist nicht erreichbar.")
35-
36-
if chargepoint_state is None:
37-
if self.old_chargepoint_state is None:
38-
raise Exception("Keine erfolgreiche Auslesung der Daten seit dem Start möglich.")
39-
# bei Fehler, aber Fehlerzähler noch nicht abgelaufen
40-
chargepoint_state = self.old_chargepoint_state
41-
store_state(chargepoint_state)
42-
self.old_chargepoint_state = chargepoint_state
43-
return chargepoint_state
37+
if chargepoint_state is not None:
38+
store_state(chargepoint_state)
39+
return chargepoint_state
40+
else:
41+
store_state(self.old_chargepoint_state)
42+
return self.old_chargepoint_state
43+
except Exception as e:
44+
if self.client_error_context.error_counter_exceeded():
45+
chargepoint_state = ChargepointState(plug_state=False, charge_state=False, imported=None,
46+
# bei im-/exported None werden keine Werte gepublished
47+
exported=None, phases_in_use=0, power=0, currents=[0]*3)
48+
store_state(chargepoint_state)
49+
if isinstance(e, (requests.exceptions.ConnectTimeout, requests.exceptions.ConnectionError)):
50+
raise Exception(self.NO_CONNECTION_TO_INTERNAL_CP)
51+
else:
52+
raise e
53+
elif self.old_chargepoint_state is not None:
54+
store_state(self.old_chargepoint_state)
55+
return self.old_chargepoint_state
56+
else:
57+
raise Exception(self.NO_DATA_SINCE_BOOT)
4458

4559
def perform_phase_switch(self, phases_to_use: int, duration: int) -> None:
4660
super().switch_phases(phases_to_use, duration)
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import re
2+
from typing import Callable, Tuple
3+
from unittest.mock import Mock
4+
5+
import pytest
6+
from modules.common.component_state import ChargepointState
7+
from modules.internal_chargepoint_handler.internal_chargepoint_handler_config import InternalChargepoint
8+
from modules.internal_chargepoint_handler.pro_plus import ProPlus
9+
10+
11+
@pytest.fixture(autouse=True)
12+
def setup_pro_plus(monkeypatch) -> Tuple[ProPlus, Mock]:
13+
pro_plus = ProPlus(0, InternalChargepoint(), 1)
14+
mock_store_set = Mock()
15+
monkeypatch.setattr(pro_plus.store, "set", mock_store_set)
16+
monkeypatch.setattr(pro_plus.store, "update", lambda: None)
17+
monkeypatch.setattr(pro_plus.store_internal, "set", lambda x: None)
18+
monkeypatch.setattr(pro_plus.store_internal, "update", lambda: None)
19+
return pro_plus, mock_store_set
20+
21+
22+
@pytest.fixture()
23+
def chargepoint_state() -> ChargepointState:
24+
return ChargepointState(currents=[0, 0, 0], powers=[0, 0, 0], voltages=[
25+
229.4, 229.4, 229.4], imported=0, exported=0, power=0, phases_in_use=2, charge_state=False, plug_state=True)
26+
27+
28+
@pytest.mark.parametrize(
29+
"request_values_return, expected_chargepoint_state",
30+
[pytest.param(lambda: chargepoint_state, chargepoint_state, id="Normalfall"),
31+
pytest.param(Mock(side_effect=Exception(ProPlus.NO_CONNECTION_TO_INTERNAL_CP)),
32+
chargepoint_state, id="Fehler, aber Timer noch nicht abgelaufen")])
33+
def test_get_values(request_values_return: ChargepointState,
34+
expected_chargepoint_state: ChargepointState,
35+
setup_pro_plus: Callable[[], Tuple[ProPlus, Mock]],
36+
monkeypatch):
37+
# setup
38+
pro_plus, mock_store_set = setup_pro_plus
39+
pro_plus.old_chargepoint_state = expected_chargepoint_state
40+
monkeypatch.setattr(pro_plus, "request_values", request_values_return)
41+
monkeypatch.setattr(pro_plus.client_error_context, "error_counter_exceeded", lambda: False)
42+
43+
# execution
44+
chargepoint_state = pro_plus.get_values(False, None)
45+
46+
# evalutation
47+
assert chargepoint_state == expected_chargepoint_state
48+
assert mock_store_set.call_args.args[0].__dict__ == expected_chargepoint_state.__dict__
49+
50+
51+
def test_get_values_no_data_since_boot(setup_pro_plus: Callable[[], Tuple[ProPlus, Mock]], monkeypatch):
52+
# setup
53+
pro_plus = setup_pro_plus[0]
54+
monkeypatch.setattr(pro_plus, "request_values", Mock(side_effect=Exception(ProPlus.NO_CONNECTION_TO_INTERNAL_CP)))
55+
monkeypatch.setattr(pro_plus.client_error_context, "error_counter_exceeded", lambda: False)
56+
57+
# execution
58+
with pytest.raises(Exception, match=re.escape(ProPlus.NO_DATA_SINCE_BOOT)):
59+
pro_plus.get_values(False, None)
60+
61+
62+
def test_get_values_error_timer_exceed(setup_pro_plus: Callable[[], Tuple[ProPlus, Mock]], monkeypatch):
63+
# Exception werfen und Ladepunkt-Status zurücksetzen
64+
# setup
65+
pro_plus, mock_store_set = setup_pro_plus
66+
monkeypatch.setattr(pro_plus, "request_values", Mock(side_effect=Exception(ProPlus.NO_CONNECTION_TO_INTERNAL_CP)))
67+
monkeypatch.setattr(pro_plus.client_error_context, "error_counter_exceeded", lambda: True)
68+
69+
# execution
70+
with pytest.raises(Exception, match=re.escape(ProPlus.NO_CONNECTION_TO_INTERNAL_CP)):
71+
pro_plus.get_values(False, None)
72+
73+
assert mock_store_set.call_args.args[0].__dict__ == ChargepointState(
74+
plug_state=False, charge_state=False, imported=None, exported=None,
75+
phases_in_use=0, power=0, currents=[0]*3).__dict__

0 commit comments

Comments
 (0)