-
Notifications
You must be signed in to change notification settings - Fork 70
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
16 additions
and
122 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,136 +1,30 @@ | ||
#!/usr/bin/env python3 | ||
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.devices.byd.config import BYD, BYDBatSetup, BYDConfiguration | ||
from modules.devices.byd.device import Device as BYDDevice | ||
from modules.common.abstract_device import AbstractDevice, DeviceDescriptor | ||
from modules.common.component_context import SingleComponentUpdateContext | ||
from modules.common.component_state import CounterState | ||
from modules.common.simcount import sim_count | ||
from modules.common.store import get_counter_value_store | ||
from modules.common.configurable_device import ComponentFactoryByType, ConfigurableDevice, IndependentComponentUpdater | ||
from modules.common.abstract_device import DeviceDescriptor | ||
from modules.devices.kostal_piko import counter | ||
from modules.devices.kostal_piko import inverter | ||
from modules.devices.kostal_piko.config import (KostalPiko, | ||
KostalPikoConfiguration, | ||
KostalPikoCounterSetup, KostalPikoInverterConfiguration, | ||
KostalPikoInverterSetup) | ||
from modules.devices.kostal_piko.config import KostalPiko, KostalPikoCounterSetup, KostalPikoInverterSetup | ||
|
||
log = logging.getLogger(__name__) | ||
|
||
|
||
kostal_piko_component_classes = Union[counter.KostalPikoCounter, inverter.KostalPikoInverter] | ||
def create_device(device_config: KostalPiko): | ||
def create_counter_component(component_config: KostalPikoCounterSetup): | ||
return counter.KostalPikoCounter(device_config.id, component_config, device_config.configuration.ip_address) | ||
|
||
def create_inverter_component(component_config: KostalPikoInverterSetup): | ||
return inverter.KostalPikoInverter(device_config.id, component_config, device_config.configuration.ip_address) | ||
|
||
class Device(AbstractDevice): | ||
COMPONENT_TYPE_TO_CLASS = { | ||
"counter": counter.KostalPikoCounter, | ||
"inverter": inverter.KostalPikoInverter | ||
} | ||
|
||
def __init__(self, device_config: Union[Dict, KostalPiko]) -> None: | ||
self.components = {} # type: Dict[str, kostal_piko_component_classes] | ||
try: | ||
self.device_config = dataclass_from_dict(KostalPiko, device_config) | ||
except Exception: | ||
log.exception("Fehler im Modul "+self.device_config.name) | ||
|
||
def add_component(self, component_config: Union[Dict, KostalPikoCounterSetup, KostalPikoInverterSetup]) -> 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.device_config.configuration.ip_address)) | ||
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 = { | ||
"counter": counter, | ||
"inverter": inverter | ||
} | ||
|
||
|
||
def read_legacy(component_type: str, | ||
address: str, | ||
bat_module: str, | ||
bat_ip: str, | ||
bat_username: str, | ||
bat_password: str, | ||
num: Optional[int] = None) -> None: | ||
dev = Device(KostalPiko(configuration=KostalPikoConfiguration(ip_address=address))) | ||
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 | ||
if isinstance(component_config, KostalPikoInverterSetup) and bat_module != "none": | ||
component_config.configuration.bat_configured = True | ||
dev.add_component(component_config) | ||
|
||
log.debug('KostalPiko IP-Adresse: ' + address) | ||
log.debug('KostalPiko Speicher: ' + bat_module) | ||
|
||
if isinstance(component_config, KostalPikoInverterSetup): | ||
dev.update() | ||
elif isinstance(component_config, KostalPikoCounterSetup): | ||
with SingleComponentUpdateContext(dev.components["componentNone"].component_info): | ||
home_consumption, powers = dev.components["componentNone"].get_values() | ||
if bat_module == "speicher_bydhv": | ||
bat_power = _get_byd_bat_power(bat_ip, bat_username, bat_password, 1) | ||
home_consumption += bat_power | ||
|
||
dev.add_component(KostalPikoInverterSetup( | ||
id=1, configuration=KostalPikoInverterConfiguration(bat_configured=True))) | ||
inverter_power, _ = dev.components["component"+str(1)].update() | ||
|
||
power = home_consumption + inverter_power | ||
imported, exported = sim_count(power, prefix="bezug") | ||
counter_state = CounterState( | ||
imported=imported, | ||
exported=exported, | ||
power=power, | ||
powers=powers | ||
) | ||
get_counter_value_store(None).set(counter_state) | ||
|
||
|
||
def _get_byd_bat_power(bat_ip: str, bat_username: str, bat_password: str, num: int) -> float: | ||
bat_dev = BYDDevice(BYD(configuration=BYDConfiguration(user=bat_username, | ||
password=bat_password, | ||
ip_address=bat_ip))) | ||
bat_dev.add_component(BYDBatSetup(id=num)) | ||
bat_power, _ = bat_dev.components["component"+str(num)].get_values() | ||
return bat_power | ||
|
||
|
||
def main(argv: List[str]): | ||
run_using_positional_cli_args(read_legacy, argv) | ||
return ConfigurableDevice( | ||
device_config=device_config, | ||
component_factory=ComponentFactoryByType( | ||
counter=create_counter_component, | ||
inverter=create_inverter_component, | ||
), | ||
component_updater=IndependentComponentUpdater(lambda component: component.update()) | ||
) | ||
|
||
|
||
device_descriptor = DeviceDescriptor(configuration_factory=KostalPiko) |