Skip to content

Commit

Permalink
add ampere_pro inverter module (#2028)
Browse files Browse the repository at this point in the history
  • Loading branch information
ndrsnhs authored Dec 17, 2024
1 parent 4b44550 commit 6ab1be5
Show file tree
Hide file tree
Showing 8 changed files with 253 additions and 0 deletions.
Empty file.
Empty file.
41 changes: 41 additions & 0 deletions packages/modules/devices/ampere/ampere/bat.py
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)
66 changes: 66 additions & 0 deletions packages/modules/devices/ampere/ampere/config.py
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())
42 changes: 42 additions & 0 deletions packages/modules/devices/ampere/ampere/counter.py
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)
49 changes: 49 additions & 0 deletions packages/modules/devices/ampere/ampere/device.py
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)
41 changes: 41 additions & 0 deletions packages/modules/devices/ampere/ampere/inverter.py
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)
14 changes: 14 additions & 0 deletions packages/modules/devices/ampere/vendor.py
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)

0 comments on commit 6ab1be5

Please sign in to comment.