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
12 changes: 9 additions & 3 deletions docs/samples/sample_modbus/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,18 @@


def create_device(device_config: Sample):
client = None

def create_bat_component(component_config: SampleBatSetup):
nonlocal client
return SampleBat(device_config.id, component_config, device_config.configuration.ip_address, client)

def create_counter_component(component_config: SampleCounterSetup):
nonlocal client
return SampleCounter(device_config.id, component_config, device_config.configuration.ip_address, client)

def create_inverter_component(component_config: SampleInverterSetup):
nonlocal client
return SampleInverter(device_config.id, component_config, device_config.configuration.ip_address, client)

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

try:
def initializer():
nonlocal client
client = ModbusTcpClient_(device_config.configuration.ip_address, device_config.configuration.port)
except Exception:
log.exception("Fehler in create_device")

return ConfigurableDevice(
device_config=device_config,
initializer=initializer,
component_factory=ComponentFactoryByType(
bat=create_bat_component,
counter=create_counter_component,
Expand Down
9 changes: 8 additions & 1 deletion docs/samples/sample_request_by_component/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@


def create_device(device_config: Sample):
session = None

def create_bat_component(component_config: SampleBatSetup):
return SampleBat(device_config.id, component_config, device_config.configuration.ip_address)

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

def initializer():
nonlocal session
session = req.get_http_session()

return ConfigurableDevice(
device_config=device_config,
initializer=initializer,
component_factory=ComponentFactoryByType(
bat=create_bat_component,
counter=create_counter_component,
inverter=create_inverter_component,
),
component_updater=IndependentComponentUpdater(lambda component: component.update())
component_updater=IndependentComponentUpdater(lambda component: component.update(session))
)


Expand Down
16 changes: 13 additions & 3 deletions packages/modules/common/component_context.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import logging
import threading
from typing import Optional, List, Union, Any, Dict
from typing import Callable, Optional, List, Union, Any, Dict
from helpermodules.constants import NO_ERROR

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

def __init__(self, fault_state: FaultState, update_always: bool = True, reraise: bool = False):
def __init__(self,
fault_state: FaultState,
error_handler: Callable = None,
update_always: bool = True,
reraise: bool = False):
self.__fault_state = fault_state
self.update_always = update_always
self.reraise = reraise
self.error_handler = error_handler

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

def __exit__(self, exception_type, exception, exception_traceback) -> bool:
MultiComponentUpdateContext.override_subcomponent_state(self.__fault_state, exception, self.update_always)
if isinstance(exception, Exception) and self.error_handler is not None:
self.error_handler()
if self.reraise is False:
return True
else:
Expand All @@ -46,10 +53,11 @@ class MultiComponentUpdateContext:
"""
__thread_local = threading.local()

def __init__(self, device_components: Union[Dict[Any, Any], List[Any]]):
def __init__(self, device_components: Union[Dict[Any, Any], List[Any]], error_handler: Optional[callable] = None):
self.__device_components = \
device_components.values() if isinstance(device_components, dict) else device_components
self.__ignored_components = [] # type: List[ComponentInfo]
self.error_handler = error_handler

def __enter__(self):
if hasattr(self.__thread_local, "active_context"):
Expand All @@ -69,6 +77,8 @@ def __exit__(self, exception_type, exception, exception_traceback) -> bool:
fault_state.from_exception(exception)
fault_state.store_error()
delattr(MultiComponentUpdateContext.__thread_local, "active_context")
if isinstance(exception, Exception) and self.error_handler is not None:
self.error_handler()
return True

def ignore_subcomponent_state(self, component: ComponentInfo):
Expand Down
28 changes: 20 additions & 8 deletions packages/modules/common/configurable_device.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import inspect
import logging
from typing import TypeVar, Generic, Dict, Any, Callable, Iterable, List

from dataclass_utils import dataclass_from_dict
from modules.common.abstract_device import AbstractDevice
from modules.common.component_context import SingleComponentUpdateContext, MultiComponentUpdateContext
from modules.common.fault_state import FaultState
from modules.common.fault_state import ComponentInfo, FaultState

T_DEVICE_CONFIG = TypeVar("T_DEVICE_CONFIG")
T_COMPONENT = TypeVar("T_COMPONENT")
Expand All @@ -13,24 +14,26 @@
ComponentUpdater = Callable[[Iterable[T_COMPONENT]], None]
ComponentFactory = Callable[[T_COMPONENT_CONFIG], T_COMPONENT]

log = logging.getLogger(__name__)


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

def __call__(self, components: Iterable[T_COMPONENT]) -> None:
def __call__(self, components: Iterable[T_COMPONENT], error_handler: Callable) -> None:
for component in components:
with SingleComponentUpdateContext(component.fault_state):
with SingleComponentUpdateContext(component.fault_state, error_handler):
self.__updater(component)


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

def __call__(self, components: Iterable[T_COMPONENT]) -> None:
def __call__(self, components: Iterable[T_COMPONENT], error_handler: Callable) -> None:
components_list = list(components)
with MultiComponentUpdateContext(components_list):
with MultiComponentUpdateContext(components_list, error_handler):
if not components:
raise FaultState.warning("Keine Komponenten konfiguriert")
self.__updater(components_list)
Expand Down Expand Up @@ -62,14 +65,23 @@ class ConfigurableDevice(Generic[T_COMPONENT, T_DEVICE_CONFIG, T_COMPONENT_CONFI
def __init__(self,
device_config: T_DEVICE_CONFIG,
component_factory: ComponentFactory[Any, T_COMPONENT],
component_updater: ComponentUpdater[T_COMPONENT]) -> None:
component_updater: ComponentUpdater[T_COMPONENT],
initializer: Callable = lambda: None) -> None:
self.__initializer = initializer
self.__component_factory = component_factory
self.__component_updater = component_updater
self.device_config = device_config
self.components: Dict[str, T_COMPONENT] = {}

try:
self.__initializer()
except Exception:
log.exception(f"Initialisierung von Gerät {self.device_config.name} fehlgeschlagen")

def add_component(self, component_config: T_COMPONENT_CONFIG) -> None:
self.components["component" + str(component_config.id)] = self.__component_factory(component_config)
with SingleComponentUpdateContext(FaultState(ComponentInfo.from_component_config(component_config)),
self.__initializer):
self.components["component" + str(component_config.id)] = self.__component_factory(component_config)

def update(self):
self.__component_updater(self.components.values())
self.__component_updater(self.components.values(), self.__initializer)
18 changes: 9 additions & 9 deletions packages/modules/devices/alpha_ess/alpha_ess/counter.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,7 @@ def __init__(self,

def update(self):
time.sleep(0.1)
factory_method = self.__get_values_factory()
counter_state = factory_method(self.__modbus_id)
counter_state = self.__get_values_factory()
self.store.set(counter_state)

def __get_values_factory(self) -> Callable[[int], CounterState]:
Expand All @@ -39,13 +38,13 @@ def __get_values_factory(self) -> Callable[[int], CounterState]:
else:
return self.__get_values_since_v123

def __get_values_before_v123(self, unit: int) -> CounterState:
def __get_values_before_v123(self) -> CounterState:
power, exported, imported = self.__tcp_client.read_holding_registers(
0x6, [modbus.ModbusDataType.INT_32] * 3, unit=unit)
0x6, [modbus.ModbusDataType.INT_32] * 3, unit=self.__modbus_id)
exported *= 10
imported *= 10
currents = [val / 230 for val in self.__tcp_client.read_holding_registers(
0x0000, [ModbusDataType.INT_32]*3, unit=unit)]
0x0000, [ModbusDataType.INT_32]*3, unit=self.__modbus_id)]

counter_state = CounterState(
currents=currents,
Expand All @@ -55,13 +54,14 @@ def __get_values_before_v123(self, unit: int) -> CounterState:
)
return counter_state

def __get_values_since_v123(self, unit: int) -> CounterState:
power = self.__tcp_client.read_holding_registers(0x0021, ModbusDataType.INT_32, unit=unit)
def __get_values_since_v123(self) -> CounterState:
power = self.__tcp_client.read_holding_registers(0x0021, ModbusDataType.INT_32, unit=self.__modbus_id)
exported, imported = [
val * 10 for val in self.__tcp_client.read_holding_registers(
0x0010, [ModbusDataType.INT_32] * 2, unit=unit)]
0x0010, [ModbusDataType.INT_32] * 2, unit=self.__modbus_id
)]
currents = [val / 1000 for val in self.__tcp_client.read_holding_registers(
0x0017, [ModbusDataType.INT_16]*3, unit=unit)]
0x0017, [ModbusDataType.INT_16]*3, unit=self.__modbus_id)]

counter_state = CounterState(
currents=currents,
Expand Down
13 changes: 10 additions & 3 deletions packages/modules/devices/alpha_ess/alpha_ess/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,43 +19,50 @@


def create_device(device_config: AlphaEss):
client = None

def create_bat_component(component_config: AlphaEssBatSetup):
nonlocal client
return bat.AlphaEssBat(device_config.id,
component_config,
client,
device_config.configuration,
device_config.configuration.modbus_id)

def create_counter_component(component_config: AlphaEssCounterSetup):
nonlocal client
return counter.AlphaEssCounter(device_config.id,
component_config,
client,
device_config.configuration,
device_config.configuration.modbus_id)

def create_inverter_component(component_config: AlphaEssInverterSetup):
nonlocal client
return inverter.AlphaEssInverter(device_config.id,
component_config,
client,
device_config.configuration,
device_config.configuration.modbus_id)

def update_components(components: Iterable[Union[alpha_ess_component_classes]]):
nonlocal client
with client:
for component in components:
with SingleComponentUpdateContext(component.fault_state):
component.update()

try:
def initializer():
nonlocal client
if device_config.configuration.source == 0:
client = modbus.ModbusTcpClient_("192.168.193.125", 8899)
else:
client = modbus.ModbusTcpClient_(
device_config.configuration.ip_address, device_config.configuration.port)
except Exception:
log.exception("Fehler in create_device")

return ConfigurableDevice(
device_config=device_config,
initializer=initializer,
component_factory=ComponentFactoryByType(
bat=create_bat_component,
counter=create_counter_component,
Expand Down
10 changes: 6 additions & 4 deletions packages/modules/devices/ampere/ampere/bat.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,19 @@ class AmpereBat(AbstractBat):
def __init__(self,
device_id: int,
component_config: Union[Dict, AmpereBatSetup],
modbus_id: int) -> None:
modbus_id: int,
client: ModbusTcpClient_) -> None:
self.__device_id = device_id
self.component_config = dataclass_from_dict(AmpereBatSetup, component_config)
self.modbus_id = modbus_id
self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="speicher")
self.store = get_bat_value_store(self.component_config.id)
self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config))
self.client = client

def update(self, client: ModbusTcpClient_) -> None:
power = client.read_input_registers(535, ModbusDataType.INT_16, unit=self.modbus_id) * -1
soc = client.read_input_registers(1339, ModbusDataType.UINT_16, unit=self.modbus_id)
def update(self) -> None:
power = self.client.read_input_registers(535, ModbusDataType.INT_16, unit=self.modbus_id) * -1
soc = self.client.read_input_registers(1339, ModbusDataType.UINT_16, unit=self.modbus_id)

imported, exported = self.sim_counter.sim_count(power)
bat_state = BatState(
Expand Down
10 changes: 6 additions & 4 deletions packages/modules/devices/ampere/ampere/counter.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,19 @@ class AmpereCounter(AbstractCounter):
def __init__(self,
device_id: int,
component_config: Union[Dict, AmpereCounterSetup],
modbus_id: int) -> None:
modbus_id: int,
client: ModbusTcpClient_) -> None:
self.__device_id = device_id
self.component_config = dataclass_from_dict(AmpereCounterSetup, component_config)
self.modbus_id = modbus_id
self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="bezug")
self.store = get_counter_value_store(self.component_config.id)
self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config))
self.client = client

def update(self, client: ModbusTcpClient_):
powers = client.read_input_registers(1349, [ModbusDataType.INT_16]*3, unit=self.modbus_id)
power = client.read_input_registers(1348, ModbusDataType.INT_16, unit=self.modbus_id)
def update(self):
powers = self.client.read_input_registers(1349, [ModbusDataType.INT_16]*3, unit=self.modbus_id)
power = self.client.read_input_registers(1348, ModbusDataType.INT_16, unit=self.modbus_id)

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

Expand Down
23 changes: 14 additions & 9 deletions packages/modules/devices/ampere/ampere/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,28 +15,33 @@


def create_device(device_config: Ampere):
client = None

def create_bat_component(component_config: AmpereBatSetup):
return AmpereBat(device_config.id, component_config, device_config.configuration.modbus_id)
nonlocal client
return AmpereBat(device_config.id, component_config, device_config.configuration.modbus_id, client)

def create_counter_component(component_config: AmpereCounterSetup):
return AmpereCounter(device_config.id, component_config, device_config.configuration.modbus_id)
nonlocal client
return AmpereCounter(device_config.id, component_config, device_config.configuration.modbus_id, client)

def create_inverter_component(component_config: AmpereInverterSetup):
return AmpereInverter(device_config.id, component_config, device_config.configuration.modbus_id)
nonlocal client
return AmpereInverter(device_config.id, component_config, device_config.configuration.modbus_id, client)

def update_components(components: Iterable[Union[AmpereBat, AmpereCounter, AmpereInverter]]):
with client:
for component in components:
with SingleComponentUpdateContext(component.fault_state):
component.update(client)
component.update()

def initializer():
nonlocal client
client = ModbusTcpClient_(device_config.configuration.ip_address, device_config.configuration.port)

try:
client = ModbusTcpClient_(device_config.configuration.ip_address,
device_config.configuration.port)
except Exception:
log.exception("Fehler in create_device")
return ConfigurableDevice(
device_config=device_config,
initializer=initializer,
component_factory=ComponentFactoryByType(
bat=create_bat_component,
counter=create_counter_component,
Expand Down
Loading