-
Notifications
You must be signed in to change notification settings - Fork 75
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add ampere_pro inverter module (#2028)
- Loading branch information
Showing
8 changed files
with
253 additions
and
0 deletions.
There are no files selected for viewing
Empty file.
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,41 @@ | ||
#!/usr/bin/env python3 | ||
from typing import Dict, Union | ||
|
||
from dataclass_utils import dataclass_from_dict | ||
from modules.common.abstract_device import AbstractBat | ||
from modules.common.component_state import BatState | ||
from modules.common.component_type import ComponentDescriptor | ||
from modules.common.fault_state import ComponentInfo, FaultState | ||
from modules.common.modbus import ModbusDataType, ModbusTcpClient_ | ||
from modules.common.simcount import SimCounter | ||
from modules.common.store import get_bat_value_store | ||
from modules.devices.ampere.ampere.config import AmpereBatSetup | ||
|
||
|
||
class AmpereBat(AbstractBat): | ||
def __init__(self, | ||
device_id: int, | ||
component_config: Union[Dict, AmpereBatSetup], | ||
modbus_id: int) -> 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)) | ||
|
||
def update(self, client: ModbusTcpClient_) -> None: | ||
power = client.read_input_registers(535, ModbusDataType.INT_16, unit=self.modbus_id) | ||
soc = client.read_input_registers(1339, ModbusDataType.UINT_16, unit=self.modbus_id) | ||
|
||
imported, exported = self.sim_counter.sim_count(power) | ||
bat_state = BatState( | ||
power=power, | ||
soc=soc, | ||
imported=imported, | ||
exported=exported | ||
) | ||
self.store.set(bat_state) | ||
|
||
|
||
component_descriptor = ComponentDescriptor(configuration_factory=AmpereBatSetup) |
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,66 @@ | ||
from typing import Optional | ||
|
||
from modules.common.component_setup import ComponentSetup | ||
from ..vendor import vendor_descriptor | ||
|
||
|
||
class AmpereConfiguration: | ||
def __init__(self, modbus_id: int = 1, ip_address: Optional[str] = None, port: int = 502): | ||
self.modbus_id = modbus_id | ||
self.ip_address = ip_address | ||
self.port = port | ||
|
||
|
||
class Ampere: | ||
def __init__(self, | ||
name: str = "Ampere Pro", | ||
type: str = "ampere", | ||
id: int = 0, | ||
configuration: AmpereConfiguration = None) -> None: | ||
self.name = name | ||
self.type = type | ||
self.vendor = vendor_descriptor.configuration_factory().type | ||
self.id = id | ||
self.configuration = configuration or AmpereConfiguration() | ||
|
||
|
||
class AmpereBatConfiguration: | ||
def __init__(self): | ||
pass | ||
|
||
|
||
class AmpereBatSetup(ComponentSetup[AmpereBatConfiguration]): | ||
def __init__(self, | ||
name: str = "Ampere Speicher", | ||
type: str = "bat", | ||
id: int = 0, | ||
configuration: AmpereBatConfiguration = None) -> None: | ||
super().__init__(name, type, id, configuration or AmpereBatConfiguration()) | ||
|
||
|
||
class AmpereCounterConfiguration: | ||
def __init__(self): | ||
pass | ||
|
||
|
||
class AmpereCounterSetup(ComponentSetup[AmpereCounterConfiguration]): | ||
def __init__(self, | ||
name: str = "Ampere Pro Zähler", | ||
type: str = "counter", | ||
id: int = 0, | ||
configuration: AmpereCounterConfiguration = None) -> None: | ||
super().__init__(name, type, id, configuration or AmpereCounterConfiguration()) | ||
|
||
|
||
class AmpereInverterConfiguration: | ||
def __init__(self): | ||
pass | ||
|
||
|
||
class AmpereInverterSetup(ComponentSetup[AmpereInverterConfiguration]): | ||
def __init__(self, | ||
name: str = "Ampere Pro Wechselrichter", | ||
type: str = "inverter", | ||
id: int = 0, | ||
configuration: AmpereInverterConfiguration = None) -> None: | ||
super().__init__(name, type, id, configuration or AmpereInverterConfiguration()) |
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,42 @@ | ||
#!/usr/bin/env python3 | ||
from typing import Dict, Union | ||
|
||
from dataclass_utils import dataclass_from_dict | ||
from modules.common.abstract_device import AbstractCounter | ||
from modules.common.component_state import CounterState | ||
from modules.common.component_type import ComponentDescriptor | ||
from modules.common.fault_state import ComponentInfo, FaultState | ||
from modules.common.modbus import ModbusDataType, ModbusTcpClient_ | ||
from modules.common.simcount import SimCounter | ||
from modules.common.store import get_counter_value_store | ||
from modules.devices.ampere.ampere.config import AmpereCounterSetup | ||
|
||
|
||
class AmpereCounter(AbstractCounter): | ||
def __init__(self, | ||
device_id: int, | ||
component_config: Union[Dict, AmpereCounterSetup], | ||
modbus_id: int) -> 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)) | ||
|
||
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) * -1 | ||
|
||
imported, exported = self.sim_counter.sim_count(power) | ||
|
||
counter_state = CounterState( | ||
currents=powers, | ||
imported=imported, | ||
exported=exported, | ||
power=power | ||
) | ||
self.store.set(counter_state) | ||
|
||
|
||
component_descriptor = ComponentDescriptor(configuration_factory=AmpereCounterSetup) |
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,49 @@ | ||
#!/usr/bin/env python3 | ||
import logging | ||
from typing import Iterable, Union | ||
|
||
from modules.common.abstract_device import DeviceDescriptor | ||
from modules.common.component_context import SingleComponentUpdateContext | ||
from modules.common.configurable_device import ComponentFactoryByType, ConfigurableDevice, MultiComponentUpdater | ||
from modules.common.modbus import ModbusTcpClient_ | ||
from modules.devices.ampere.ampere.bat import AmpereBat | ||
from modules.devices.ampere.ampere.config import Ampere, AmpereBatSetup, AmpereCounterSetup, AmpereInverterSetup | ||
from modules.devices.ampere.ampere.counter import AmpereCounter | ||
from modules.devices.ampere.ampere.inverter import AmpereInverter | ||
|
||
log = logging.getLogger(__name__) | ||
|
||
|
||
def create_device(device_config: Ampere): | ||
def create_bat_component(component_config: AmpereBatSetup): | ||
return AmpereBat(device_config.id, component_config, device_config.configuration.modbus_id) | ||
|
||
def create_counter_component(component_config: AmpereCounterSetup): | ||
return AmpereCounter(device_config.id, component_config, device_config.configuration.modbus_id) | ||
|
||
def create_inverter_component(component_config: AmpereInverterSetup): | ||
return AmpereInverter(device_config.id, component_config, device_config.configuration.modbus_id) | ||
|
||
def update_components(components: Iterable[Union[AmpereBat, AmpereCounter, AmpereInverter]]): | ||
with client: | ||
for component in components: | ||
with SingleComponentUpdateContext(component.fault_state): | ||
component.update(client) | ||
|
||
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=Ampere) |
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,41 @@ | ||
#!/usr/bin/env python3 | ||
from typing import Dict, Union | ||
|
||
from dataclass_utils import dataclass_from_dict | ||
from modules.common.abstract_device import AbstractInverter | ||
from modules.common.component_state import InverterState | ||
from modules.common.component_type import ComponentDescriptor | ||
from modules.common.fault_state import ComponentInfo, FaultState | ||
from modules.common.modbus import ModbusDataType, ModbusTcpClient_ | ||
from modules.common.simcount import SimCounter | ||
from modules.common.store import get_inverter_value_store | ||
from modules.devices.ampere.ampere.config import AmpereInverterSetup | ||
|
||
|
||
class AmpereInverter(AbstractInverter): | ||
def __init__(self, | ||
device_id: int, | ||
component_config: Union[Dict, AmpereInverterSetup], | ||
modbus_id: int) -> None: | ||
self.__device_id = device_id | ||
self.component_config = dataclass_from_dict(AmpereInverterSetup, component_config) | ||
self.modbus_id = modbus_id | ||
self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="pv") | ||
self.store = get_inverter_value_store(self.component_config.id) | ||
self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) | ||
|
||
def update(self, client: ModbusTcpClient_) -> None: | ||
pv1_power = client.read_holding_registers(519, ModbusDataType.INT_16, unit=self.modbus_id) * -1 | ||
pv2_power = client.read_holding_registers(522, ModbusDataType.INT_16, unit=self.modbus_id) * -1 | ||
|
||
power = pv1_power + pv2_power | ||
|
||
_, exported = self.sim_counter.sim_count(power) | ||
inverter_state = InverterState( | ||
power=power, | ||
exported=exported | ||
) | ||
self.store.set(inverter_state) | ||
|
||
|
||
component_descriptor = ComponentDescriptor(configuration_factory=AmpereInverterSetup) |
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,14 @@ | ||
from pathlib import Path | ||
|
||
from modules.common.abstract_device import DeviceDescriptor | ||
from modules.devices.vendors import VendorGroup | ||
|
||
|
||
class Vendor: | ||
def __init__(self): | ||
self.type = Path(__file__).parent.name | ||
self.vendor = "Ampere" | ||
self.group = VendorGroup.VENDORS.value | ||
|
||
|
||
vendor_descriptor = DeviceDescriptor(configuration_factory=Vendor) |