Skip to content
Empty file.
Empty file.
52 changes: 52 additions & 0 deletions packages/modules/devices/marstek/marstek/bat.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#!/usr/bin/env python3
from typing import Any, TypedDict

from modules.common import modbus
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
from modules.common.simcount import SimCounter
from modules.common.store import get_bat_value_store
from modules.devices.marstek.marstek.config import MarstekBatSetup # Adjust path if needed


class KwargsDict(TypedDict):
device_id: int
client: modbus.ModbusTcpClient_
modbus_id: int


class MarstekBat(AbstractBat):
def __init__(self, component_config: MarstekBatSetup, **kwargs: Any) -> None:
self.component_config = component_config
self.kwargs: KwargsDict = kwargs

def initialize(self) -> None:
self.__device_id: int = self.kwargs['device_id']
self.__tcp_client: modbus.ModbusTcpClient_ = self.kwargs['client']
self.__modbus_id: int = self.kwargs['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) -> None:
unit = self.__modbus_id

power = self.__tcp_client.read_holding_registers(32202,
ModbusDataType.INT_32, unit=unit) * -1
soc = self.__tcp_client.read_holding_registers(32104,
ModbusDataType.UINT_16, unit=unit) * 0.1

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=MarstekBatSetup)
38 changes: 38 additions & 0 deletions packages/modules/devices/marstek/marstek/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
from typing import Optional

from modules.common.component_setup import ComponentSetup
from ..vendor import vendor_descriptor


class MarstekConfiguration:
def __init__(self, modbus_id: int = 1, ip_address: Optional[str] = None, port: int = 3600):
self.modbus_id = modbus_id
self.ip_address = ip_address
self.port = port


class Marstek:
def __init__(self,
name: str = "marstek",
type: str = "marstek",
id: int = 0,
configuration: MarstekConfiguration = None) -> None:
self.name = name
self.type = type
self.vendor = vendor_descriptor.configuration_factory().type
self.id = id
self.configuration = configuration or MarstekConfiguration()


class MarstekBatConfiguration:
def __init__(self):
pass


class MarstekBatSetup(ComponentSetup[MarstekBatConfiguration]):
def __init__(self,
name: str = "Marstek Speicher",
type: str = "bat",
id: int = 0,
configuration: MarstekBatConfiguration = None) -> None:
super().__init__(name, type, id, configuration or MarstekBatConfiguration())
48 changes: 48 additions & 0 deletions packages/modules/devices/marstek/marstek/device.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#!/usr/bin/env python3
import logging
from typing import Iterable

from modules.common import modbus
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.devices.marstek.marstek.bat import MarstekBat
from modules.devices.marstek.marstek.config import Marstek, MarstekBatSetup

log = logging.getLogger(__name__)


def create_device(device_config: Marstek):
client = None

def create_bat_component(component_config: MarstekBatSetup):
nonlocal client
return MarstekBat(
component_config,
device_id=device_config.id,
client=client,
modbus_id=device_config.configuration.modbus_id,
)

def update_components(components: Iterable[MarstekBat]):
nonlocal client
with client:
for component in components:
with SingleComponentUpdateContext(component.fault_state):
component.update()

def initializer():
nonlocal client
client = modbus.ModbusTcpClient_(device_config.configuration.ip_address, device_config.configuration.port)

return ConfigurableDevice(
device_config=device_config,
initializer=initializer,
component_factory=ComponentFactoryByType(
bat=create_bat_component,
),
component_updater=MultiComponentUpdater(update_components)
)


device_descriptor = DeviceDescriptor(configuration_factory=Marstek)
14 changes: 14 additions & 0 deletions packages/modules/devices/marstek/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 = "Marstek"
self.group = VendorGroup.VENDORS.value


vendor_descriptor = DeviceDescriptor(configuration_factory=Vendor)