Skip to content

Commit

Permalink
Use create device 2: sma webbox, solax, sonnen, studer, sungrow (#1775)
Browse files Browse the repository at this point in the history
* sma webbox

* solax

* sonnenbatterie

* studer

* sungrow
  • Loading branch information
LKuemmel authored Sep 25, 2024
1 parent 2172d7a commit 33eeb69
Show file tree
Hide file tree
Showing 5 changed files with 160 additions and 424 deletions.
61 changes: 14 additions & 47 deletions packages/modules/devices/sma/sma_webbox/device.py
Original file line number Diff line number Diff line change
@@ -1,59 +1,26 @@
#!/usr/bin/env python3
import logging
from typing import Dict, Union

from dataclass_utils import dataclass_from_dict
from modules.common.configurable_device import ComponentFactoryByType, ConfigurableDevice, IndependentComponentUpdater
from modules.devices.sma.sma_webbox.config import SmaWebbox, SmaWebboxInverterSetup
from modules.devices.sma.sma_webbox import inverter
from modules.common.abstract_device import AbstractDevice, DeviceDescriptor
from modules.common.component_context import SingleComponentUpdateContext
from modules.common.abstract_device import DeviceDescriptor
from modules.devices.sma.sma_webbox.inverter import SmaWebboxInverter


log = logging.getLogger(__name__)


class Device(AbstractDevice):
COMPONENT_TYPE_TO_CLASS = {
"inverter": inverter.SmaWebboxInverter
}

def __init__(self, device_config: Union[Dict, SmaWebbox]) -> None:
self.components = {} # type: Dict[str, inverter.SmaWebboxInverter]
try:
self.device_config = dataclass_from_dict(SmaWebbox, device_config)
except Exception:
log.exception("Fehler im Modul "+self.device_config.name)

def add_component(self, component_config: Union[Dict, SmaWebboxInverterSetup]) -> None:
if isinstance(component_config, Dict):
component_type = component_config["type"]
else:
component_type = component_config.type
component_config = dataclass_from_dict(SmaWebboxInverterSetup, component_config)
if component_type in self.COMPONENT_TYPE_TO_CLASS:
self.components["component"+str(component_config.id)] = (self.COMPONENT_TYPE_TO_CLASS[component_type](
self.device_config.configuration.ip_address,
component_config))
else:
raise Exception(
"illegal component type " + component_type + ". Allowed values: " +
','.join(self.COMPONENT_TYPE_TO_CLASS.keys())
)

def update(self) -> None:
log.debug("Start device reading " + str(self.components))
if self.components:
for component in self.components.values():
# Auch wenn bei einer Komponente ein Fehler auftritt, sollen alle anderen noch ausgelesen werden.
with SingleComponentUpdateContext(component.fault_state):
component.update()
else:
log.warning(
self.device_config.name +
": Es konnten keine Werte gelesen werden, da noch keine Komponenten konfiguriert wurden."
)

# read_legacy in sma_modbus
def create_device(device_config: SmaWebbox):
def create_inverter_component(component_config: SmaWebboxInverterSetup):
return SmaWebboxInverter(device_config.configuration.ip_address, component_config)

return ConfigurableDevice(
device_config=device_config,
component_factory=ComponentFactoryByType(
inverter=create_inverter_component,
),
component_updater=IndependentComponentUpdater(lambda component: component.update())
)


device_descriptor = DeviceDescriptor(configuration_factory=SmaWebbox)
123 changes: 36 additions & 87 deletions packages/modules/devices/solax/solax/device.py
Original file line number Diff line number Diff line change
@@ -1,99 +1,48 @@
#!/usr/bin/env python3
import logging
from typing import Dict, Optional, List, Union
from typing import Iterable, Union

from dataclass_utils import dataclass_from_dict
from helpermodules.cli import run_using_positional_cli_args
from modules.common import modbus
from modules.common.abstract_device import AbstractDevice, DeviceDescriptor
from modules.common.abstract_device import DeviceDescriptor
from modules.common.component_context import SingleComponentUpdateContext
from modules.devices.solax.solax import bat
from modules.devices.solax.solax import counter
from modules.devices.solax.solax import inverter
from modules.common.configurable_device import ComponentFactoryByType, ConfigurableDevice, MultiComponentUpdater
from modules.common.modbus import ModbusTcpClient_
from modules.devices.solax.solax.bat import SolaxBat
from modules.devices.solax.solax.config import Solax, SolaxBatSetup, SolaxCounterSetup, SolaxInverterSetup
from modules.devices.solax.solax.counter import SolaxCounter
from modules.devices.solax.solax.inverter import SolaxInverter

log = logging.getLogger(__name__)


class Device(AbstractDevice):
COMPONENT_TYPE_TO_CLASS = {
"bat": bat.SolaxBat,
"counter": counter.SolaxCounter,
"inverter": inverter.SolaxInverter
}

def __init__(self, device_config: Union[Dict, Solax]) -> None:
self.components = {} # type: Dict[str, counter.SolaxCounter]
try:
self.device_config = dataclass_from_dict(Solax, device_config)
self.client = modbus.ModbusTcpClient_(
self.device_config.configuration.ip_address, self.device_config.configuration.port)
except Exception:
log.exception("Fehler im Modul "+self.device_config.name)

def add_component(self, component_config: Union[Dict,
SolaxBatSetup,
SolaxCounterSetup,
SolaxInverterSetup]) -> None:
if isinstance(component_config, Dict):
component_type = component_config["type"]
else:
component_type = component_config.type
component_config = dataclass_from_dict(COMPONENT_TYPE_TO_MODULE[
component_type].component_descriptor.configuration_factory, component_config)
if component_type in self.COMPONENT_TYPE_TO_CLASS:
self.components["component"+str(component_config.id)] = (self.COMPONENT_TYPE_TO_CLASS[component_type](
self.device_config.id, component_config, self.client,
self.device_config.configuration.modbus_id))
else:
raise Exception(
"illegal component type " + component_type + ". Allowed values: " +
','.join(self.COMPONENT_TYPE_TO_CLASS.keys())
)

def update(self) -> None:
log.debug("Start device reading " + str(self.components))
if self.components:
for component in self.components:
# Auch wenn bei einer Komponente ein Fehler auftritt, sollen alle anderen noch ausgelesen werden.
with SingleComponentUpdateContext(self.components[component].fault_state):
self.components[component].update()
else:
log.warning(
self.device_config.name +
": Es konnten keine Werte gelesen werden, da noch keine Komponenten konfiguriert wurden.")


COMPONENT_TYPE_TO_MODULE = {
"bat": bat,
"counter": counter,
"inverter": inverter
}


def read_legacy(component_type: str, ip_address: str, modbus_id: int, num: Optional[int] = None) -> None:
device_config = Solax()
device_config.configuration.ip_address = ip_address
device_config.configuration.modbus_id = modbus_id
dev = Device(device_config)
if component_type in COMPONENT_TYPE_TO_MODULE:
component_config = COMPONENT_TYPE_TO_MODULE[component_type].component_descriptor.configuration_factory()
else:
raise Exception(
"illegal component type " + component_type + ". Allowed values: " +
','.join(COMPONENT_TYPE_TO_MODULE.keys())
)
component_config.id = num
dev.add_component(component_config)

log.debug('Solax IP-Adresse: ' + ip_address)
log.debug('Solax ID: ' + str(modbus_id))

dev.update()


def main(argv: List[str]):
run_using_positional_cli_args(read_legacy, argv)
def create_device(device_config: Solax):
def create_bat_component(component_config: SolaxBatSetup):
return SolaxBat(device_config.id, component_config, client, device_config.configuration.modbus_id)

def create_counter_component(component_config: SolaxCounterSetup):
return SolaxCounter(device_config.id, component_config, client, device_config.configuration.modbus_id)

def create_inverter_component(component_config: SolaxInverterSetup):
return SolaxInverter(device_config.id, component_config, client, device_config.configuration.modbus_id)

def update_components(components: Iterable[Union[SolaxBat, SolaxCounter, SolaxInverter]]):
with client:
for component in components:
with SingleComponentUpdateContext(component.fault_state):
component.update()

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,
component_factory=ComponentFactoryByType(
bat=create_bat_component,
counter=create_counter_component,
inverter=create_inverter_component,
),
component_updater=MultiComponentUpdater(update_components)
)


device_descriptor = DeviceDescriptor(configuration_factory=Solax)
124 changes: 34 additions & 90 deletions packages/modules/devices/sonnen/sonnenbatterie/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,104 +2,48 @@
""" Modul zum Auslesen von sonnenBatterie Speichern.
"""
import logging
from typing import Dict, Union, Optional, List

from dataclass_utils import dataclass_from_dict
from helpermodules.cli import run_using_positional_cli_args
from modules.common.abstract_device import AbstractDevice, DeviceDescriptor
from modules.common.component_context import SingleComponentUpdateContext
from modules.devices.sonnen.sonnenbatterie import bat, counter, inverter
from modules.common.abstract_device import DeviceDescriptor
from modules.common.configurable_device import ComponentFactoryByType, ConfigurableDevice, IndependentComponentUpdater
from modules.devices.sonnen.sonnenbatterie.bat import SonnenbatterieBat
from modules.devices.sonnen.sonnenbatterie.config import (SonnenBatterie, SonnenbatterieBatSetup,
SonnenbatterieCounterSetup,
SonnenbatterieInverterSetup)
log = logging.getLogger(__name__)


sonnenbatterie_component_classes = Union[
bat.SonnenbatterieBat,
counter.SonnenbatterieCounter,
inverter.SonnenbatterieInverter
]


class Device(AbstractDevice):
COMPONENT_TYPE_TO_CLASS = {
"bat": bat.SonnenbatterieBat,
"counter": counter.SonnenbatterieCounter,
"inverter": inverter.SonnenbatterieInverter
}

def __init__(self, device_config: Union[Dict, SonnenBatterie]) -> None:
self.components = {} # type: Dict[str, sonnenbatterie_component_classes]
try:
self.device_config = dataclass_from_dict(SonnenBatterie, device_config)
except Exception:
log.exception("Fehler im Modul "+self.device_config.name)
from modules.devices.sonnen.sonnenbatterie.counter import SonnenbatterieCounter
from modules.devices.sonnen.sonnenbatterie.inverter import SonnenbatterieInverter

def add_component(self, component_config: Union[Dict,
SonnenbatterieBatSetup,
SonnenbatterieCounterSetup,
SonnenbatterieInverterSetup]) -> None:
if isinstance(component_config, Dict):
component_type = component_config["type"]
else:
component_type = component_config.type
component_config = dataclass_from_dict(COMPONENT_TYPE_TO_MODULE[
component_type].component_descriptor.configuration_factory, component_config)
if component_type in self.COMPONENT_TYPE_TO_CLASS:
self.components["component"+str(component_config.id)] = (self.COMPONENT_TYPE_TO_CLASS[component_type](
self.device_config.id,
self.device_config.configuration.ip_address,
self.device_config.configuration.variant,
component_config))
else:
raise Exception(
"illegal component type " + component_type + ". Allowed values: " +
','.join(self.COMPONENT_TYPE_TO_CLASS.keys())
)

def update(self) -> None:
log.debug("Start device reading " + str(self.components))
if self.components:
for component in self.components:
# Auch wenn bei einer Komponente ein Fehler auftritt, sollen alle anderen noch ausgelesen werden.
with SingleComponentUpdateContext(self.components[component].fault_state):
self.components[component].update()
else:
log.warning(
self.device_config.name +
": Es konnten keine Werte gelesen werden, da noch keine Komponenten konfiguriert wurden."
)


COMPONENT_TYPE_TO_MODULE = {
"bat": bat,
"counter": counter,
"inverter": inverter
}


def read_legacy(component_type: str, address: str, variant: int, num: Optional[int] = None) -> None:
device_config = SonnenBatterie()
device_config.configuration.ip_address = address
device_config.configuration.variant = variant
dev = Device(device_config)
if component_type in COMPONENT_TYPE_TO_MODULE:
component_config = COMPONENT_TYPE_TO_MODULE[component_type].component_descriptor.configuration_factory()
else:
raise Exception(
"illegal component type " + component_type + ". Allowed values: " +
','.join(COMPONENT_TYPE_TO_MODULE.keys())
)
component_config.id = num
dev.add_component(component_config)
log.debug('SonnenBatterie address: ' + address)
log.debug('SonnenBatterie variant: ' + str(variant))
dev.update()
log = logging.getLogger(__name__)


def main(argv: List[str]):
run_using_positional_cli_args(read_legacy, argv)
def create_device(device_config: SonnenBatterie):
def create_bat_component(component_config: SonnenbatterieBatSetup):
return SonnenbatterieBat(device_config.id,
device_config.configuration.ip_address,
device_config.configuration.variant,
component_config)

def create_counter_component(component_config: SonnenbatterieCounterSetup):
return SonnenbatterieCounter(device_config.id,
device_config.configuration.ip_address,
device_config.configuration.variant,
component_config)

def create_inverter_component(component_config: SonnenbatterieInverterSetup):
return SonnenbatterieInverter(device_config.id,
device_config.configuration.ip_address,
device_config.configuration.variant,
component_config)

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


device_descriptor = DeviceDescriptor(configuration_factory=SonnenBatterie)
Loading

0 comments on commit 33eeb69

Please sign in to comment.