Skip to content

Commit 589e651

Browse files
committed
create device error handler
1 parent 07fdba6 commit 589e651

92 files changed

Lines changed: 854 additions & 498 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

docs/samples/sample_modbus/device.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,18 @@
1717

1818

1919
def create_device(device_config: Sample):
20+
client = None
21+
2022
def create_bat_component(component_config: SampleBatSetup):
23+
nonlocal client
2124
return SampleBat(device_config.id, component_config, device_config.configuration.ip_address, client)
2225

2326
def create_counter_component(component_config: SampleCounterSetup):
27+
nonlocal client
2428
return SampleCounter(device_config.id, component_config, device_config.configuration.ip_address, client)
2529

2630
def create_inverter_component(component_config: SampleInverterSetup):
31+
nonlocal client
2732
return SampleInverter(device_config.id, component_config, device_config.configuration.ip_address, client)
2833

2934
def update_components(components: Iterable[Union[SampleBat, SampleCounter, SampleInverter]]):
@@ -32,12 +37,13 @@ def update_components(components: Iterable[Union[SampleBat, SampleCounter, Sampl
3237
with SingleComponentUpdateContext(component.fault_state):
3338
component.update()
3439

35-
try:
40+
def initializer():
41+
nonlocal client
3642
client = ModbusTcpClient_(device_config.configuration.ip_address, device_config.configuration.port)
37-
except Exception:
38-
log.exception("Fehler in create_device")
43+
3944
return ConfigurableDevice(
4045
device_config=device_config,
46+
initializer=initializer,
4147
component_factory=ComponentFactoryByType(
4248
bat=create_bat_component,
4349
counter=create_counter_component,

docs/samples/sample_request_by_component/device.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515

1616

1717
def create_device(device_config: Sample):
18+
session = None
19+
1820
def create_bat_component(component_config: SampleBatSetup):
1921
return SampleBat(device_config.id, component_config, device_config.configuration.ip_address)
2022

@@ -24,14 +26,19 @@ def create_counter_component(component_config: SampleCounterSetup):
2426
def create_inverter_component(component_config: SampleInverterSetup):
2527
return SampleInverter(device_config.id, component_config, device_config.configuration.ip_address)
2628

29+
def initializer():
30+
nonlocal session
31+
session = req.get_http_session()
32+
2733
return ConfigurableDevice(
2834
device_config=device_config,
35+
initializer=initializer,
2936
component_factory=ComponentFactoryByType(
3037
bat=create_bat_component,
3138
counter=create_counter_component,
3239
inverter=create_inverter_component,
3340
),
34-
component_updater=IndependentComponentUpdater(lambda component: component.update())
41+
component_updater=IndependentComponentUpdater(lambda component: component.update(session))
3542
)
3643

3744

packages/modules/common/component_context.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import logging
22
import threading
3-
from typing import Optional, List, Union, Any, Dict
3+
from typing import Callable, Optional, List, Union, Any, Dict
44
from helpermodules.constants import NO_ERROR
55

66
from modules.common.fault_state import ComponentInfo, FaultState, FaultStateLevel
@@ -17,10 +17,15 @@ class SingleComponentUpdateContext:
1717
component.update()
1818
"""
1919

20-
def __init__(self, fault_state: FaultState, update_always: bool = True, reraise: bool = False):
20+
def __init__(self,
21+
fault_state: FaultState,
22+
error_handler: Callable = None,
23+
update_always: bool = True,
24+
reraise: bool = False):
2125
self.__fault_state = fault_state
2226
self.update_always = update_always
2327
self.reraise = reraise
28+
self.error_handler = error_handler
2429

2530
def __enter__(self):
2631
log.debug("Update Komponente ['"+self.__fault_state.component_info.name+"']")
@@ -30,6 +35,8 @@ def __enter__(self):
3035

3136
def __exit__(self, exception_type, exception, exception_traceback) -> bool:
3237
MultiComponentUpdateContext.override_subcomponent_state(self.__fault_state, exception, self.update_always)
38+
if isinstance(exception, Exception) and self.error_handler is not None:
39+
self.error_handler()
3340
if self.reraise is False:
3441
return True
3542
else:
@@ -46,10 +53,11 @@ class MultiComponentUpdateContext:
4653
"""
4754
__thread_local = threading.local()
4855

49-
def __init__(self, device_components: Union[Dict[Any, Any], List[Any]]):
56+
def __init__(self, device_components: Union[Dict[Any, Any], List[Any]], error_handler: Optional[callable] = None):
5057
self.__device_components = \
5158
device_components.values() if isinstance(device_components, dict) else device_components
5259
self.__ignored_components = [] # type: List[ComponentInfo]
60+
self.error_handler = error_handler
5361

5462
def __enter__(self):
5563
if hasattr(self.__thread_local, "active_context"):
@@ -69,6 +77,8 @@ def __exit__(self, exception_type, exception, exception_traceback) -> bool:
6977
fault_state.from_exception(exception)
7078
fault_state.store_error()
7179
delattr(MultiComponentUpdateContext.__thread_local, "active_context")
80+
if isinstance(exception, Exception) and self.error_handler is not None:
81+
self.error_handler()
7282
return True
7383

7484
def ignore_subcomponent_state(self, component: ComponentInfo):

packages/modules/common/configurable_device.py

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import inspect
2+
import logging
23
from typing import TypeVar, Generic, Dict, Any, Callable, Iterable, List
34

45
from dataclass_utils import dataclass_from_dict
56
from modules.common.abstract_device import AbstractDevice
67
from modules.common.component_context import SingleComponentUpdateContext, MultiComponentUpdateContext
7-
from modules.common.fault_state import FaultState
8+
from modules.common.fault_state import ComponentInfo, FaultState
89

910
T_DEVICE_CONFIG = TypeVar("T_DEVICE_CONFIG")
1011
T_COMPONENT = TypeVar("T_COMPONENT")
@@ -13,24 +14,26 @@
1314
ComponentUpdater = Callable[[Iterable[T_COMPONENT]], None]
1415
ComponentFactory = Callable[[T_COMPONENT_CONFIG], T_COMPONENT]
1516

17+
log = logging.getLogger(__name__)
18+
1619

1720
class IndependentComponentUpdater(Generic[T_COMPONENT]):
1821
def __init__(self, updater: Callable[[T_COMPONENT], None]):
1922
self.__updater = updater
2023

21-
def __call__(self, components: Iterable[T_COMPONENT]) -> None:
24+
def __call__(self, components: Iterable[T_COMPONENT], error_handler: Callable) -> None:
2225
for component in components:
23-
with SingleComponentUpdateContext(component.fault_state):
26+
with SingleComponentUpdateContext(component.fault_state, error_handler):
2427
self.__updater(component)
2528

2629

2730
class MultiComponentUpdater:
2831
def __init__(self, updater: Callable[[List[T_COMPONENT]], None]):
2932
self.__updater = updater
3033

31-
def __call__(self, components: Iterable[T_COMPONENT]) -> None:
34+
def __call__(self, components: Iterable[T_COMPONENT], error_handler: Callable) -> None:
3235
components_list = list(components)
33-
with MultiComponentUpdateContext(components_list):
36+
with MultiComponentUpdateContext(components_list, error_handler):
3437
if not components:
3538
raise FaultState.warning("Keine Komponenten konfiguriert")
3639
self.__updater(components_list)
@@ -62,14 +65,23 @@ class ConfigurableDevice(Generic[T_COMPONENT, T_DEVICE_CONFIG, T_COMPONENT_CONFI
6265
def __init__(self,
6366
device_config: T_DEVICE_CONFIG,
6467
component_factory: ComponentFactory[Any, T_COMPONENT],
65-
component_updater: ComponentUpdater[T_COMPONENT]) -> None:
68+
component_updater: ComponentUpdater[T_COMPONENT],
69+
initializer: Callable = lambda: None) -> None:
70+
self.__initializer = initializer
6671
self.__component_factory = component_factory
6772
self.__component_updater = component_updater
6873
self.device_config = device_config
6974
self.components: Dict[str, T_COMPONENT] = {}
7075

76+
try:
77+
self.__initializer()
78+
except Exception:
79+
log.exception(f"Initialisierung von Gerät {self.device_config.name} fehlgeschlagen")
80+
7181
def add_component(self, component_config: T_COMPONENT_CONFIG) -> None:
72-
self.components["component" + str(component_config.id)] = self.__component_factory(component_config)
82+
with SingleComponentUpdateContext(FaultState(ComponentInfo.from_component_config(component_config)),
83+
self.__initializer):
84+
self.components["component" + str(component_config.id)] = self.__component_factory(component_config)
7385

7486
def update(self):
75-
self.__component_updater(self.components.values())
87+
self.__component_updater(self.components.values(), self.__initializer)

packages/modules/devices/alpha_ess/alpha_ess/counter.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,7 @@ def __init__(self,
2929

3030
def update(self):
3131
time.sleep(0.1)
32-
factory_method = self.__get_values_factory()
33-
counter_state = factory_method(self.__modbus_id)
32+
counter_state = self.__get_values_factory()
3433
self.store.set(counter_state)
3534

3635
def __get_values_factory(self) -> Callable[[int], CounterState]:
@@ -39,13 +38,13 @@ def __get_values_factory(self) -> Callable[[int], CounterState]:
3938
else:
4039
return self.__get_values_since_v123
4140

42-
def __get_values_before_v123(self, unit: int) -> CounterState:
41+
def __get_values_before_v123(self) -> CounterState:
4342
power, exported, imported = self.__tcp_client.read_holding_registers(
44-
0x6, [modbus.ModbusDataType.INT_32] * 3, unit=unit)
43+
0x6, [modbus.ModbusDataType.INT_32] * 3, unit=self.__modbus_id)
4544
exported *= 10
4645
imported *= 10
4746
currents = [val / 230 for val in self.__tcp_client.read_holding_registers(
48-
0x0000, [ModbusDataType.INT_32]*3, unit=unit)]
47+
0x0000, [ModbusDataType.INT_32]*3, unit=self.__modbus_id)]
4948

5049
counter_state = CounterState(
5150
currents=currents,
@@ -55,13 +54,14 @@ def __get_values_before_v123(self, unit: int) -> CounterState:
5554
)
5655
return counter_state
5756

58-
def __get_values_since_v123(self, unit: int) -> CounterState:
59-
power = self.__tcp_client.read_holding_registers(0x0021, ModbusDataType.INT_32, unit=unit)
57+
def __get_values_since_v123(self) -> CounterState:
58+
power = self.__tcp_client.read_holding_registers(0x0021, ModbusDataType.INT_32, unit=self.__modbus_id)
6059
exported, imported = [
6160
val * 10 for val in self.__tcp_client.read_holding_registers(
62-
0x0010, [ModbusDataType.INT_32] * 2, unit=unit)]
61+
0x0010, [ModbusDataType.INT_32] * 2, unit=self.__modbus_id
62+
)]
6363
currents = [val / 1000 for val in self.__tcp_client.read_holding_registers(
64-
0x0017, [ModbusDataType.INT_16]*3, unit=unit)]
64+
0x0017, [ModbusDataType.INT_16]*3, unit=self.__modbus_id)]
6565

6666
counter_state = CounterState(
6767
currents=currents,

packages/modules/devices/alpha_ess/alpha_ess/device.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,43 +19,50 @@
1919

2020

2121
def create_device(device_config: AlphaEss):
22+
client = None
23+
2224
def create_bat_component(component_config: AlphaEssBatSetup):
25+
nonlocal client
2326
return bat.AlphaEssBat(device_config.id,
2427
component_config,
2528
client,
2629
device_config.configuration,
2730
device_config.configuration.modbus_id)
2831

2932
def create_counter_component(component_config: AlphaEssCounterSetup):
33+
nonlocal client
3034
return counter.AlphaEssCounter(device_config.id,
3135
component_config,
3236
client,
3337
device_config.configuration,
3438
device_config.configuration.modbus_id)
3539

3640
def create_inverter_component(component_config: AlphaEssInverterSetup):
41+
nonlocal client
3742
return inverter.AlphaEssInverter(device_config.id,
3843
component_config,
3944
client,
4045
device_config.configuration,
4146
device_config.configuration.modbus_id)
4247

4348
def update_components(components: Iterable[Union[alpha_ess_component_classes]]):
49+
nonlocal client
4450
with client:
4551
for component in components:
4652
with SingleComponentUpdateContext(component.fault_state):
4753
component.update()
4854

49-
try:
55+
def initializer():
56+
nonlocal client
5057
if device_config.configuration.source == 0:
5158
client = modbus.ModbusTcpClient_("192.168.193.125", 8899)
5259
else:
5360
client = modbus.ModbusTcpClient_(
5461
device_config.configuration.ip_address, device_config.configuration.port)
55-
except Exception:
56-
log.exception("Fehler in create_device")
62+
5763
return ConfigurableDevice(
5864
device_config=device_config,
65+
initializer=initializer,
5966
component_factory=ComponentFactoryByType(
6067
bat=create_bat_component,
6168
counter=create_counter_component,

packages/modules/devices/ampere/ampere/bat.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,19 @@ class AmpereBat(AbstractBat):
1616
def __init__(self,
1717
device_id: int,
1818
component_config: Union[Dict, AmpereBatSetup],
19-
modbus_id: int) -> None:
19+
modbus_id: int,
20+
client: ModbusTcpClient_) -> None:
2021
self.__device_id = device_id
2122
self.component_config = dataclass_from_dict(AmpereBatSetup, component_config)
2223
self.modbus_id = modbus_id
2324
self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="speicher")
2425
self.store = get_bat_value_store(self.component_config.id)
2526
self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config))
27+
self.client = client
2628

27-
def update(self, client: ModbusTcpClient_) -> None:
28-
power = client.read_input_registers(535, ModbusDataType.INT_16, unit=self.modbus_id) * -1
29-
soc = client.read_input_registers(1339, ModbusDataType.UINT_16, unit=self.modbus_id)
29+
def update(self) -> None:
30+
power = self.client.read_input_registers(535, ModbusDataType.INT_16, unit=self.modbus_id) * -1
31+
soc = self.client.read_input_registers(1339, ModbusDataType.UINT_16, unit=self.modbus_id)
3032

3133
imported, exported = self.sim_counter.sim_count(power)
3234
bat_state = BatState(

packages/modules/devices/ampere/ampere/counter.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,19 @@ class AmpereCounter(AbstractCounter):
1616
def __init__(self,
1717
device_id: int,
1818
component_config: Union[Dict, AmpereCounterSetup],
19-
modbus_id: int) -> None:
19+
modbus_id: int,
20+
client: ModbusTcpClient_) -> None:
2021
self.__device_id = device_id
2122
self.component_config = dataclass_from_dict(AmpereCounterSetup, component_config)
2223
self.modbus_id = modbus_id
2324
self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="bezug")
2425
self.store = get_counter_value_store(self.component_config.id)
2526
self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config))
27+
self.client = client
2628

27-
def update(self, client: ModbusTcpClient_):
28-
powers = client.read_input_registers(1349, [ModbusDataType.INT_16]*3, unit=self.modbus_id)
29-
power = client.read_input_registers(1348, ModbusDataType.INT_16, unit=self.modbus_id)
29+
def update(self):
30+
powers = self.client.read_input_registers(1349, [ModbusDataType.INT_16]*3, unit=self.modbus_id)
31+
power = self.client.read_input_registers(1348, ModbusDataType.INT_16, unit=self.modbus_id)
3032

3133
imported, exported = self.sim_counter.sim_count(power)
3234

packages/modules/devices/ampere/ampere/device.py

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,28 +15,33 @@
1515

1616

1717
def create_device(device_config: Ampere):
18+
client = None
19+
1820
def create_bat_component(component_config: AmpereBatSetup):
19-
return AmpereBat(device_config.id, component_config, device_config.configuration.modbus_id)
21+
nonlocal client
22+
return AmpereBat(device_config.id, component_config, device_config.configuration.modbus_id, client)
2023

2124
def create_counter_component(component_config: AmpereCounterSetup):
22-
return AmpereCounter(device_config.id, component_config, device_config.configuration.modbus_id)
25+
nonlocal client
26+
return AmpereCounter(device_config.id, component_config, device_config.configuration.modbus_id, client)
2327

2428
def create_inverter_component(component_config: AmpereInverterSetup):
25-
return AmpereInverter(device_config.id, component_config, device_config.configuration.modbus_id)
29+
nonlocal client
30+
return AmpereInverter(device_config.id, component_config, device_config.configuration.modbus_id, client)
2631

2732
def update_components(components: Iterable[Union[AmpereBat, AmpereCounter, AmpereInverter]]):
2833
with client:
2934
for component in components:
3035
with SingleComponentUpdateContext(component.fault_state):
31-
component.update(client)
36+
component.update()
37+
38+
def initializer():
39+
nonlocal client
40+
client = ModbusTcpClient_(device_config.configuration.ip_address, device_config.configuration.port)
3241

33-
try:
34-
client = ModbusTcpClient_(device_config.configuration.ip_address,
35-
device_config.configuration.port)
36-
except Exception:
37-
log.exception("Fehler in create_device")
3842
return ConfigurableDevice(
3943
device_config=device_config,
44+
initializer=initializer,
4045
component_factory=ComponentFactoryByType(
4146
bat=create_bat_component,
4247
counter=create_counter_component,

0 commit comments

Comments
 (0)