Skip to content

Commit

Permalink
detect broken evse and broken meter (openWB#1759)
Browse files Browse the repository at this point in the history
  • Loading branch information
LKuemmel authored Jul 19, 2024
1 parent fa41cc3 commit a5bc93d
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 20 deletions.
35 changes: 19 additions & 16 deletions packages/modules/common/hardware_check.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,16 @@
OPEN_TICKET = (" Bitte nehme bei anhaltenden Problemen über die Support-Funktion in den Einstellungen Kontakt mit " +
"uns auf.")
RS485_ADPATER_BROKEN = ("Auslesen von Zähler UND Evse nicht möglich. Vermutlich ist {} defekt oder zwei "
f"Busteilnehmer haben die gleiche Modbus-ID. Bitte die Zähler-ID prüfen. {OPEN_TICKET}")
"Busteilnehmer haben die gleiche Modbus-ID. Bitte die Zähler-ID prüfen.")
USB_ADAPTER_BROKEN = RS485_ADPATER_BROKEN.format('der USB-Adapter')
LAN_ADAPTER_BROKEN = (f"{RS485_ADPATER_BROKEN.format('der LAN-Konverter abgestürzt,')} "
"Bitte den openWB series2 satellit stromlos machen.")
METER_PROBLEM = ("Der Zähler konnte nicht ausgelesen werden. "
f"Vermutlich ist der Zähler falsch konfiguriert oder defekt. {OPEN_TICKET}")
METER_BROKEN = ("Die Spannungen des Zählers konnten nicht korrekt ausgelesen werden. "
f"Der Zähler ist defekt. {OPEN_TICKET}")
METER_PROBLEM = "Der Zähler konnte nicht ausgelesen werden. Vermutlich ist der Zähler falsch konfiguriert oder defekt."
METER_BROKEN = "Die Spannungen des Zählers konnten nicht korrekt ausgelesen werden: {}V Der Zähler ist defekt."
METER_NO_SERIAL_NUMBER = ("Die Seriennummer des Zählers für das Ladelog kann nicht ausgelesen werden. Wenn Sie die "
"Seriennummer für Abrechnungszwecke benötigen, wenden Sie sich bitte an unseren Support. Die "
"Funktionalität wird dadurch nicht beeinträchtigt!")
EVSE_BROKEN = ("Auslesen der EVSE nicht möglich. "
f"Vermutlich ist die EVSE defekt oder hat eine unbekannte Modbus-ID. {OPEN_TICKET}")
EVSE_BROKEN = "Auslesen der EVSE nicht möglich. Vermutlich ist die EVSE defekt oder hat eine unbekannte Modbus-ID."


def check_meter_values(voltages: List[float]) -> Optional[str]:
Expand All @@ -33,7 +30,7 @@ def valid_voltage(voltage) -> bool:
(valid_voltage(voltages[0]) and valid_voltage(voltages[1]) and valid_voltage((voltages[2])))):
return None
else:
return METER_BROKEN
return METER_BROKEN.format(voltages)


class ClientHandlerProtocol(Protocol):
Expand Down Expand Up @@ -73,17 +70,23 @@ def check_hardware(self: ClientHandlerProtocol, fault_state: FaultState):
except Exception as e:
evse_check_passed = self.handle_exception(e)
meter_check_passed, meter_error_msg = self.check_meter()
if meter_check_passed is False and evse_check_passed is False:
if isinstance(self.client, ModbusTcpClient_):
raise Exception(LAN_ADAPTER_BROKEN)
else:
raise Exception(USB_ADAPTER_BROKEN)
if meter_check_passed is False:
raise Exception(meter_error_msg)
elif meter_check_passed and meter_error_msg is not None:
if evse_check_passed is False:
if isinstance(self.client, ModbusTcpClient_):
raise Exception(LAN_ADAPTER_BROKEN + OPEN_TICKET)
else:
raise Exception(USB_ADAPTER_BROKEN + OPEN_TICKET)
else:
raise Exception(meter_error_msg + OPEN_TICKET)
elif evse_check_passed and meter_check_passed and meter_error_msg is not None:
if meter_error_msg != METER_NO_SERIAL_NUMBER:
meter_error_msg += OPEN_TICKET
fault_state.warning(meter_error_msg)
if evse_check_passed is False:
raise Exception(EVSE_BROKEN)
if meter_error_msg is not None:
raise Exception(EVSE_BROKEN + " " + meter_error_msg + OPEN_TICKET)
else:
raise Exception(EVSE_BROKEN + OPEN_TICKET)

def check_meter(self: ClientHandlerProtocol) -> Tuple[bool, Optional[str]]:
try:
Expand Down
12 changes: 8 additions & 4 deletions packages/modules/common/hardware_check_test.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import re
from typing import List, Optional, Tuple, Union
from unittest.mock import MagicMock, Mock, patch

import pytest
from modules.common import sdm
from modules.common.evse import Evse
from modules.common.hardware_check import (
EVSE_BROKEN, LAN_ADAPTER_BROKEN, METER_BROKEN, METER_NO_SERIAL_NUMBER, METER_PROBLEM, USB_ADAPTER_BROKEN,
SeriesHardwareCheckMixin, check_meter_values)
EVSE_BROKEN, LAN_ADAPTER_BROKEN, METER_BROKEN, METER_NO_SERIAL_NUMBER, METER_PROBLEM, OPEN_TICKET,
USB_ADAPTER_BROKEN, SeriesHardwareCheckMixin, check_meter_values)
from modules.common.modbus import NO_CONNECTION, ModbusClient, ModbusSerialClient_, ModbusTcpClient_
from modules.conftest import SAMPLE_IP, SAMPLE_PORT
from modules.internal_chargepoint_handler.clients import ClientHandler
Expand All @@ -17,6 +18,9 @@
"handle_exception_return_value, client_spec, expected_error_msg"),
[pytest.param(Exception("Modbus"), None, None, [230]*3, None, False, ModbusSerialClient_, EVSE_BROKEN,
id="EVSE defekt"),
pytest.param(Exception("Modbus"), None, None, [230, 0, 230], None, False, ModbusSerialClient_,
EVSE_BROKEN + " " + METER_BROKEN.format([230, 0, 230]) + OPEN_TICKET,
id="EVSE defekt und Zähler eine Phase defekt"),
pytest.param(None, 18, Exception("Modbus"), None, None, None,
ModbusSerialClient_, METER_PROBLEM, id="Zähler verkonfiguriert"),
pytest.param(Exception("Modbus"), None, Exception("Modbus"), None, None, False, ModbusSerialClient_,
Expand Down Expand Up @@ -55,7 +59,7 @@ def test_hardware_check_fails(evse_side_effect,
mock_modbus_client.__enter__.return_value = mock_modbus_client

# execution and evaluation
with pytest.raises(Exception, match=expected_error_msg):
with pytest.raises(Exception, match=re.escape(expected_error_msg)):
ClientHandler(0, mock_modbus_client, [1], Mock())


Expand Down Expand Up @@ -93,7 +97,7 @@ def test_check_meter_values(voltages, expected_msg, monkeypatch):
msg = check_meter_values(voltages)

# assert
assert msg == expected_msg
assert msg == expected_msg if expected_msg is None else expected_msg.format(voltages)


@patch('modules.common.hardware_check.ClientHandlerProtocol')
Expand Down

0 comments on commit a5bc93d

Please sign in to comment.