-
Notifications
You must be signed in to change notification settings - Fork 203
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2585 from LKuemmel/solarworld
solarworld
- Loading branch information
Showing
9 changed files
with
196 additions
and
86 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
This file was deleted.
Oops, something went wrong.
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
This file was deleted.
Oops, something went wrong.
Empty file.
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 |
---|---|---|
@@ -0,0 +1,54 @@ | ||
from typing import Optional | ||
from helpermodules.auto_str import auto_str | ||
from modules.common.component_setup import ComponentSetup | ||
|
||
|
||
@auto_str | ||
class SolarWorldConfiguration: | ||
def __init__(self, ip_address: Optional[str] = None): | ||
self.ip_address = ip_address | ||
|
||
|
||
@auto_str | ||
class SolarWorld: | ||
def __init__(self, | ||
name: str = "SolarWorld", | ||
type: str = "solar_world", | ||
id: int = 0, | ||
configuration: SolarWorldConfiguration = None) -> None: | ||
self.name = name | ||
self.type = type | ||
self.id = id | ||
self.configuration = configuration or SolarWorldConfiguration() | ||
|
||
|
||
@auto_str | ||
class SolarWorldCounterConfiguration: | ||
def __init__(self): | ||
pass | ||
|
||
|
||
@auto_str | ||
class SolarWorldCounterSetup(ComponentSetup[SolarWorldCounterConfiguration]): | ||
def __init__(self, | ||
name: str = "SolarWorld Zähler", | ||
type: str = "counter", | ||
id: int = 0, | ||
configuration: SolarWorldCounterConfiguration = None) -> None: | ||
super().__init__(name, type, id, configuration or SolarWorldCounterConfiguration()) | ||
|
||
|
||
@auto_str | ||
class SolarWorldInverterConfiguration: | ||
def __init__(self): | ||
pass | ||
|
||
|
||
@auto_str | ||
class SolarWorldInverterSetup(ComponentSetup[SolarWorldInverterConfiguration]): | ||
def __init__(self, | ||
name: str = "SolarWorld Wechselrichter", | ||
type: str = "inverter", | ||
id: int = 0, | ||
configuration: SolarWorldInverterConfiguration = None) -> None: | ||
super().__init__(name, type, id, configuration or SolarWorldInverterConfiguration()) |
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 |
---|---|---|
@@ -0,0 +1,33 @@ | ||
#!/usr/bin/env python3 | ||
from typing import Dict, Union | ||
|
||
from dataclass_utils import dataclass_from_dict | ||
from modules.common.component_state import CounterState | ||
from modules.common.component_type import ComponentDescriptor | ||
from modules.common.fault_state import ComponentInfo | ||
from modules.common.simcount import SimCounter | ||
from modules.common.store import get_counter_value_store | ||
from modules.devices.solar_world.config import SolarWorldCounterSetup | ||
|
||
|
||
class SolarWorldCounter: | ||
def __init__(self, device_id: int, component_config: Union[Dict, SolarWorldCounterSetup]) -> None: | ||
self.__device_id = device_id | ||
self.component_config = dataclass_from_dict(SolarWorldCounterSetup, component_config) | ||
self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="bezug") | ||
self.store = get_counter_value_store(self.component_config.id) | ||
self.component_info = ComponentInfo.from_component_config(self.component_config) | ||
|
||
def update(self, response): | ||
power = response["PowerIn"] - response["PowerOut"] | ||
imported, exported = self.sim_counter.sim_count(power) | ||
|
||
counter_state = CounterState( | ||
imported=imported, | ||
exported=exported, | ||
power=power | ||
) | ||
self.store.set(counter_state) | ||
|
||
|
||
component_descriptor = ComponentDescriptor(configuration_factory=SolarWorldCounterSetup) |
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 |
---|---|---|
@@ -0,0 +1,69 @@ | ||
#!/usr/bin/env python3 | ||
import logging | ||
from typing import Iterable, Optional, Union, List | ||
|
||
from helpermodules.cli import run_using_positional_cli_args | ||
from modules.common import req | ||
from modules.common.abstract_device import DeviceDescriptor | ||
from modules.common.configurable_device import ConfigurableDevice, ComponentFactoryByType, MultiComponentUpdater | ||
from modules.devices.solar_world import counter, inverter | ||
from modules.devices.solar_world.config import ( | ||
SolarWorld, SolarWorldConfiguration, SolarWorldCounterSetup, SolarWorldInverterSetup) | ||
from modules.devices.solar_world.counter import SolarWorldCounter | ||
from modules.devices.solar_world.inverter import SolarWorldInverter | ||
|
||
log = logging.getLogger(__name__) | ||
|
||
|
||
def create_device(device_config: SolarWorld): | ||
def create_counter_component(component_config: SolarWorldCounterSetup): | ||
return SolarWorldCounter(device_config.id, component_config) | ||
|
||
def create_inverter_component(component_config: SolarWorldInverterSetup): | ||
return SolarWorldInverter(device_config.id, component_config) | ||
|
||
def update_components(components: Iterable[Union[SolarWorldCounter, SolarWorldInverter]]): | ||
response = req.get_http_session().get("http://"+str(device_config.configuration.ip_address) + | ||
"/rest/solarworld/lpvm/powerAndBatteryData", timeout=5).json() | ||
for component in components: | ||
component.update(response) | ||
|
||
return ConfigurableDevice( | ||
device_config=device_config, | ||
component_factory=ComponentFactoryByType( | ||
counter=create_counter_component, | ||
inverter=create_inverter_component, | ||
), | ||
component_updater=MultiComponentUpdater(update_components) | ||
) | ||
|
||
|
||
COMPONENT_TYPE_TO_MODULE = { | ||
"counter": counter, | ||
"inverter": inverter | ||
} | ||
|
||
|
||
def read_legacy(component_type: str, ip_address: str, num: Optional[int]) -> None: | ||
device_config = SolarWorld(configuration=SolarWorldConfiguration(ip_address=ip_address)) | ||
dev = create_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('SolarWorld IP-Adresse: ' + ip_address) | ||
|
||
dev.update() | ||
|
||
|
||
def main(argv: List[str]): | ||
run_using_positional_cli_args(read_legacy, argv) | ||
|
||
|
||
device_descriptor = DeviceDescriptor(configuration_factory=SolarWorld) |
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 |
---|---|---|
@@ -0,0 +1,36 @@ | ||
#!/usr/bin/env python3 | ||
from typing import Dict, Union | ||
|
||
from dataclass_utils import dataclass_from_dict | ||
from modules.common.component_state import InverterState | ||
from modules.common.component_type import ComponentDescriptor | ||
from modules.common.fault_state import ComponentInfo | ||
from modules.common.simcount import SimCounter | ||
from modules.common.store import get_inverter_value_store | ||
from modules.devices.solar_world.config import SolarWorldInverterSetup | ||
|
||
|
||
class SolarWorldInverter: | ||
def __init__(self, device_id: int, component_config: Union[Dict, SolarWorldInverterSetup]) -> None: | ||
self.__device_id = device_id | ||
self.component_config = dataclass_from_dict(SolarWorldInverterSetup, component_config) | ||
self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="pv") | ||
self.store = get_inverter_value_store(self.component_config.id) | ||
self.component_info = ComponentInfo.from_component_config(self.component_config) | ||
|
||
def update(self, response) -> None: | ||
try: | ||
power = response["PowerTotalPV"] * -1 | ||
except ValueError: | ||
# wenn eManager aus bzw. keine Antwort ersetze leeren Wert durch eine 0 | ||
power = 0 | ||
exported = self.sim_counter.sim_count(power)[1] | ||
|
||
inverter_state = InverterState( | ||
power=power, | ||
exported=exported | ||
) | ||
self.store.set(inverter_state) | ||
|
||
|
||
component_descriptor = ComponentDescriptor(configuration_factory=SolarWorldInverterSetup) |