Skip to content

Commit

Permalink
error handling internal chargepoint
Browse files Browse the repository at this point in the history
  • Loading branch information
LKuemmel committed Jan 3, 2024
1 parent 5246ae4 commit d5e7993
Show file tree
Hide file tree
Showing 9 changed files with 54 additions and 62 deletions.
2 changes: 1 addition & 1 deletion packages/helpermodules/exceptions/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class ExceptionRegistry:
def translate_exception(self, exception: Exception) -> [str, FaultStateLevel]:
entry = self.find_registry_entry(exception)
if entry is None:
return "{} {}".format(type(exception), exception.args[-1]), FaultStateLevel.ERROR
return "{} {}".format(type(exception), exception.args), FaultStateLevel.ERROR
if isinstance(entry.handler, str):
return entry.handler, FaultStateLevel.ERROR
result = entry.handler(exception)
Expand Down
2 changes: 1 addition & 1 deletion packages/helpermodules/exceptions/registry_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class ErrorF(ErrorD):


@pytest.mark.parametrize("exception,expected_message", [
[ErrorRoot, "<class 'helpermodules.exceptions.registry_test.ErrorRoot'> ErrorRoot"],
[ErrorRoot, "<class 'helpermodules.exceptions.registry_test.ErrorRoot'> ('ErrorRoot',)"],
[ErrorB, "B"],
[ErrorC, "A"],
[ErrorD, "B"],
Expand Down
2 changes: 1 addition & 1 deletion packages/modules/common/component_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ def __init__(self, soc: float, range: Optional[float] = None, soc_timestamp: flo
@auto_str
class ChargepointState:
def __init__(self,
phases_in_use: int,
phases_in_use: int = 0,
imported: float = 0,
exported: float = 0,
power: float = 0,
Expand Down
3 changes: 2 additions & 1 deletion packages/modules/common/hardware_check.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@

EVSE_MIN_FIRMWARE = 7

OPEN_TICKET = " Bitte nehme über die Support-Funktion in den Einstellungen Kontakt mit uns auf."
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}")
USB_ADAPTER_BROKEN = RS485_ADPATER_BROKEN.format('der USB-Adapter')
Expand Down
17 changes: 7 additions & 10 deletions packages/modules/common/store/_broker.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
from typing import Union

from helpermodules.pub import Pub
from modules.common.store._util import get_rounding_function_by_digits, process_error
from modules.common.store._util import get_rounding_function_by_digits


def pub_to_broker(topic: str, value, digits: Union[int, None] = None) -> None:
rounding = get_rounding_function_by_digits(digits)
try:
if value is None:
Pub().pub(topic, rounding(value))
elif isinstance(value, list):
Pub().pub(topic, [rounding(v) for v in value])
else:
Pub().pub(topic, rounding(value))
except Exception as e:
process_error(e)
if value is None:
Pub().pub(topic, value)
elif isinstance(value, list):
Pub().pub(topic, [rounding(v) for v in value])
else:
Pub().pub(topic, rounding(value))
6 changes: 0 additions & 6 deletions packages/modules/common/store/_util.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
from typing import Callable, Union

from modules.common.fault_state import FaultState


def get_rounding_function_by_digits(digits: Union[int, None]) -> Callable:
if digits is None:
Expand All @@ -10,7 +8,3 @@ def get_rounding_function_by_digits(digits: Union[int, None]) -> Callable:
return int
else:
return lambda value: round(value, digits)


def process_error(e):
raise FaultState.error(__name__+" "+str(type(e))+" "+str(e)) from e
7 changes: 2 additions & 5 deletions packages/modules/common/store/ramdisk/io.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from pathlib import Path
from typing import Iterable, Optional, TypeVar, Callable

from modules.common.store._util import get_rounding_function_by_digits, process_error
from modules.common.store._util import get_rounding_function_by_digits

RAMDISK_PATH = Path(__file__).resolve().parents[5] / "ramdisk"

Expand All @@ -19,10 +19,7 @@ def ramdisk_write_to_files(prefix: str, values: Iterable, digits: int = None):


def ramdisk_write(file: str, value, digits: Optional[int] = None) -> None:
try:
(RAMDISK_PATH / file).write_text(str(get_rounding_function_by_digits(digits)(value)))
except Exception as e:
process_error(e)
(RAMDISK_PATH / file).write_text(str(get_rounding_function_by_digits(digits)(value)))


def ramdisk_read(file: str) -> str:
Expand Down
75 changes: 39 additions & 36 deletions packages/modules/internal_chargepoint_handler/chargepoint_module.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
from modules.common.component_context import SingleComponentUpdateContext
from modules.common.component_state import ChargepointState
from modules.common.fault_state import ComponentInfo, FaultState
from modules.common.hardware_check_context import SeriesHardwareCheckContext
from modules.common.store import get_internal_chargepoint_value_store, get_chargepoint_value_store
from modules.internal_chargepoint_handler.clients import ClientHandler

Expand Down Expand Up @@ -39,22 +38,23 @@ def __init__(self, local_charge_point_num: int,
self.store = get_chargepoint_value_store(hierarchy_id)
self.old_plug_state = False
self.old_phases_in_use = 0
self.__client = client_handler
version = self.__client.evse_client.get_firmware_version()
self.old_chargepoint_state = ChargepointState()
self._client = client_handler
version = self._client.evse_client.get_firmware_version()
with ModifyLoglevelContext(log, logging.DEBUG):
log.debug(f"Firmware-Version der EVSE: {version}")
if version < 17:
self._precise_current = False
else:
if self.__client.evse_client.is_precise_current_active() is False:
self.__client.evse_client.activate_precise_current()
self._precise_current = self.__client.evse_client.is_precise_current_active()
if self._client.evse_client.is_precise_current_active() is False:
self._client.evse_client.activate_precise_current()
self._precise_current = self._client.evse_client.is_precise_current_active()

def set_current(self, current: float) -> None:
with SingleComponentUpdateContext(self.fault_state):
with SingleComponentUpdateContext(self.fault_state, update_always=False):
formatted_current = int(current*100) if self._precise_current else int(current)
if self.set_current_evse != formatted_current:
self.__client.evse_client.set_current(formatted_current)
self._client.evse_client.set_current(formatted_current)

def get_values(self, phase_switch_cp_active: bool, last_tag: str) -> Tuple[ChargepointState, float]:
def store_state(chargepoint_state: ChargepointState) -> None:
Expand All @@ -63,24 +63,24 @@ def store_state(chargepoint_state: ChargepointState) -> None:
self.store_internal.set(chargepoint_state)
self.store_internal.update()
try:
with SeriesHardwareCheckContext(self.__client):
powers, power = self.__client.meter_client.get_power()
if power < self.PLUG_STANDBY_POWER_THRESHOLD:
power = 0
voltages = self.__client.meter_client.get_voltages()
currents = self.__client.meter_client.get_currents()
imported = self.__client.meter_client.get_imported()
power_factors = self.__client.meter_client.get_power_factors()
frequency = self.__client.meter_client.get_frequency()
phases_in_use = sum(1 for current in currents if current > 3)
if phases_in_use == 0:
phases_in_use = self.old_phases_in_use
else:
self.old_phases_in_use = phases_in_use

time.sleep(0.1)
plug_state, charge_state, self.set_current_evse = self.__client.evse_client.get_plug_charge_state()
self.__client.read_error = 0
self._client.check_hardware()
powers, power = self._client.meter_client.get_power()
if power < self.PLUG_STANDBY_POWER_THRESHOLD:
power = 0
voltages = self._client.meter_client.get_voltages()
currents = self._client.meter_client.get_currents()
imported = self._client.meter_client.get_imported()
power_factors = self._client.meter_client.get_power_factors()
frequency = self._client.meter_client.get_frequency()
phases_in_use = sum(1 for current in currents if current > 3)
if phases_in_use == 0:
phases_in_use = self.old_phases_in_use
else:
self.old_phases_in_use = phases_in_use

time.sleep(0.1)
plug_state, charge_state, self.set_current_evse = self._client.evse_client.get_plug_charge_state()
self._client.read_error = 0

if phase_switch_cp_active:
# Während des Threads wird die CP-Leitung unterbrochen, das EV soll aber als angesteckt betrachtet
Expand Down Expand Up @@ -108,11 +108,10 @@ def store_state(chargepoint_state: ChargepointState) -> None:
evse_current=self.set_current_evse
)
except Exception as e:
self.__client.read_error += 1
if self.__client.read_error > 5:
self._client.read_error += 1
if self._client.read_error > 5:
msg = ("Anhaltender Fehler beim Auslesen von EVSE und/oder Zähler. " +
"Lade- und Stecker-Status werden zurückgesetzt.")
log.exception(msg)
plug_state = False
charge_state = False
chargepoint_state = ChargepointState(
Expand All @@ -124,15 +123,19 @@ def store_state(chargepoint_state: ChargepointState) -> None:
e.args += (msg,)
raise e
else:
raise e
chargepoint_state = self.old_chargepoint_state
self.set_current_evse = chargepoint_state.evse_current
# don't log as exception due to sporadic read errors
log.debug(__name__ + " " + str(type(e)) + " " + str(e))

store_state(chargepoint_state)
self.old_chargepoint_state = chargepoint_state
return chargepoint_state, self.set_current_evse

def perform_phase_switch(self, phases_to_use: int, duration: int) -> None:
gpio_cp, gpio_relay = self.__client.get_pins_phase_switch(phases_to_use)
with SingleComponentUpdateContext(self.fault_state):
self.__client.evse_client.set_current(0)
gpio_cp, gpio_relay = self._client.get_pins_phase_switch(phases_to_use)
with SingleComponentUpdateContext(self.fault_state, update_always=False):
self._client.evse_client.set_current(0)
time.sleep(1)
GPIO.output(gpio_cp, GPIO.HIGH) # CP off
GPIO.output(gpio_relay, GPIO.HIGH) # 3 on/off
Expand All @@ -143,9 +146,9 @@ def perform_phase_switch(self, phases_to_use: int, duration: int) -> None:
time.sleep(1)

def perform_cp_interruption(self, duration: int) -> None:
gpio_cp = self.__client.get_pins_cp_interruption()
with SingleComponentUpdateContext(self.fault_state):
self.__client.evse_client.set_current(0)
gpio_cp = self._client.get_pins_cp_interruption()
with SingleComponentUpdateContext(self.fault_state, update_always=False):
self._client.evse_client.set_current(0)
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(gpio_cp, GPIO.OUT)
Expand Down
2 changes: 1 addition & 1 deletion packages/modules/internal_chargepoint_handler/socket.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ def __init__(self,
super().__init__(local_charge_point_num, client_handler, parent_hostname, parent_cp, hierarchy_id)

def set_current(self, current: float) -> None:
with SingleComponentUpdateContext(self.fault_state):
with SingleComponentUpdateContext(self.fault_state, update_always=False):
try:
actor = ActorState(GPIO.input(19))
except Exception:
Expand Down

0 comments on commit d5e7993

Please sign in to comment.