Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions packages/modules/devices/fox_ess/fox_ess/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def __init__(self,

class FoxEss:
def __init__(self,
name: str = "FoxESS",
name: str = "FoxESS H3",
type: str = "fox_ess",
id: int = 0,
configuration: FoxEssConfiguration = None) -> None:
Expand All @@ -35,7 +35,7 @@ def __init__(self, modbus_id: int = 1):
@auto_str
class FoxEssBatSetup(ComponentSetup[FoxEssBatConfiguration]):
def __init__(self,
name: str = "FoxESS Speicher",
name: str = "FoxESS H3 Speicher",
type: str = "bat",
id: int = 0,
configuration: FoxEssBatConfiguration = None,
Expand All @@ -52,7 +52,7 @@ def __init__(self, modbus_id: int = 1):
@auto_str
class FoxEssCounterSetup(ComponentSetup[FoxEssCounterConfiguration]):
def __init__(self,
name: str = "FoxESS Zähler",
name: str = "FoxESS H3 Zähler",
type: str = "counter",
id: int = 0,
configuration: FoxEssCounterConfiguration = None,
Expand All @@ -69,7 +69,7 @@ def __init__(self, modbus_id: int = 1):
@auto_str
class FoxEssInverterSetup(ComponentSetup[FoxEssInverterConfiguration]):
def __init__(self,
name: str = "FoxESS Wechselrichter",
name: str = "FoxESS H3 Wechselrichter",
type: str = "inverter",
id: int = 0,
configuration: FoxEssInverterConfiguration = None,
Expand Down
54 changes: 54 additions & 0 deletions packages/modules/devices/fox_ess/fox_ess_h3_smart/bat.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#!/usr/bin/env python3
import logging
from typing import TypedDict, Any

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_component_value_store
from modules.devices.fox_ess.fox_ess_h3_smart.config import FoxEssH3SmartBatSetup
from modules.common.utils.peak_filter import PeakFilter
from modules.common.component_type import ComponentType

log = logging.getLogger(__name__)


class KwargsDict(TypedDict):
device_id: int
client: ModbusTcpClient_


class FoxEssH3SmartBat(AbstractBat):
def __init__(self, component_config: FoxEssH3SmartBatSetup, **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.client: ModbusTcpClient_ = self.kwargs['client']
self.store = get_component_value_store(self.component_config.type, self.component_config.id)
self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config))
self.peak_filter = PeakFilter(ComponentType.BAT, self.component_config.id, self.fault_state)
self.sim_counter = SimCounter(self.__device_id, self.component_config.id, self.component_config.type)

def update(self) -> None:
unit = self.component_config.configuration.modbus_id

power = self.client.read_holding_registers(39237, ModbusDataType.INT_32, unit=unit)
soc = self.client.read_holding_registers(37612, ModbusDataType.INT_16, unit=unit) / 100

self.peak_filter.check_values(power)
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=FoxEssH3SmartBatSetup)
77 changes: 77 additions & 0 deletions packages/modules/devices/fox_ess/fox_ess_h3_smart/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
from typing import Optional

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


class FoxEssH3SmartConfiguration:
def __init__(self,
ip_address: Optional[str] = None,
port: int = 502):
self.ip_address = ip_address
self.port = port


class FoxEssH3Smart:
def __init__(self,
name: str = "FoxEss H3 Smart",
type: str = "fox_ess_h3_smart",
id: int = 0,
configuration: FoxEssH3SmartConfiguration = None) -> None:
self.name = name
self.type = type
self.vendor = vendor_descriptor.configuration_factory().type
self.id = id
self.configuration = configuration or FoxEssH3SmartConfiguration()


@auto_str
class FoxEssH3SmartBatConfiguration:
def __init__(self, modbus_id: int = 247):
self.modbus_id = modbus_id


@auto_str
class FoxEssH3SmartBatSetup(ComponentSetup[FoxEssH3SmartBatConfiguration]):
def __init__(self,
name: str = "FoxEss H3 Smart Speicher",
type: str = "bat",
id: int = 0,
configuration: FoxEssH3SmartBatConfiguration = None,
**kwargs) -> None:
super().__init__(name, type, id, configuration or FoxEssH3SmartBatConfiguration(), **kwargs)


@auto_str
class FoxEssH3SmartCounterConfiguration:
def __init__(self, modbus_id: int = 247):
self.modbus_id = modbus_id


@auto_str
class FoxEssH3SmartCounterSetup(ComponentSetup[FoxEssH3SmartCounterConfiguration]):
def __init__(self,
name: str = "FoxEss H3 Smart Zähler",
type: str = "counter",
id: int = 0,
configuration: FoxEssH3SmartCounterConfiguration = None,
**kwargs) -> None:
super().__init__(name, type, id, configuration or FoxEssH3SmartCounterConfiguration(), **kwargs)


@auto_str
class FoxEssH3SmartInverterConfiguration:
def __init__(self, modbus_id: int = 247):
self.modbus_id = modbus_id


@auto_str
class FoxEssH3SmartInverterSetup(ComponentSetup[FoxEssH3SmartInverterConfiguration]):
def __init__(self,
name: str = "FoxEss H3 Smart Wechselrichter",
type: str = "inverter",
id: int = 0,
configuration: FoxEssH3SmartInverterConfiguration = None,
**kwargs) -> None:
super().__init__(name, type, id, configuration or FoxEssH3SmartInverterConfiguration(), **kwargs)
52 changes: 52 additions & 0 deletions packages/modules/devices/fox_ess/fox_ess_h3_smart/counter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#!/usr/bin/env python3
from typing import TypedDict, Any

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_component_value_store
from modules.devices.fox_ess.fox_ess_h3_smart.config import FoxEssH3SmartCounterSetup
from modules.common.utils.peak_filter import PeakFilter
from modules.common.component_type import ComponentType


class KwargsDict(TypedDict):
device_id: int
client: ModbusTcpClient_


class FoxEssH3SmartCounter(AbstractCounter):
def __init__(self, component_config: FoxEssH3SmartCounterSetup, **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.client: ModbusTcpClient_ = self.kwargs['client']
self.store = get_component_value_store(self.component_config.type, self.component_config.id)
self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config))
self.peak_filter = PeakFilter(ComponentType.COUNTER, self.component_config.id, self.fault_state)
self.sim_counter = SimCounter(self.__device_id, self.component_config.id, self.component_config.type)

def update(self) -> None:
unit = self.component_config.configuration.modbus_id

power = self.client.read_holding_registers(38814, ModbusDataType.INT_32, unit=unit) * -0.1
powers = self.client.read_holding_registers(38816, [ModbusDataType.INT_32]*3, unit=unit)
powers = [value * -0.1 for value in powers]

self.peak_filter.check_values(power)
imported, exported = self.sim_counter.sim_count(power)
counter_state = CounterState(
imported=imported,
exported=exported,
power=power,
powers=powers
)
self.store.set(counter_state)


component_descriptor = ComponentDescriptor(configuration_factory=FoxEssH3SmartCounterSetup)
52 changes: 52 additions & 0 deletions packages/modules/devices/fox_ess/fox_ess_h3_smart/device.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#!/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 ConfigurableDevice, ComponentFactoryByType, MultiComponentUpdater
from modules.common.modbus import ModbusTcpClient_
from modules.devices.fox_ess.fox_ess_h3_smart.bat import FoxEssH3SmartBat
from modules.devices.fox_ess.fox_ess_h3_smart.counter import FoxEssH3SmartCounter
from modules.devices.fox_ess.fox_ess_h3_smart.inverter import FoxEssH3SmartInverter
from modules.devices.fox_ess.fox_ess_h3_smart.config import FoxEssH3Smart, FoxEssH3SmartBatSetup
from modules.devices.fox_ess.fox_ess_h3_smart.config import FoxEssH3SmartCounterSetup, FoxEssH3SmartInverterSetup

log = logging.getLogger(__name__)


def create_device(device_config: FoxEssH3Smart):
client = None

def create_bat_component(component_config: FoxEssH3SmartBatSetup):
return FoxEssH3SmartBat(component_config, device_id=device_config.id, client=client)

def create_counter_component(component_config: FoxEssH3SmartCounterSetup):
return FoxEssH3SmartCounter(component_config, device_id=device_config.id, client=client)

def create_inverter_component(component_config: FoxEssH3SmartInverterSetup):
return FoxEssH3SmartInverter(component_config, device_id=device_config.id, client=client)

def update_components(components: Iterable[Union[FoxEssH3SmartBat, FoxEssH3SmartCounter, FoxEssH3SmartInverter]]):
with client:
for component in components:
with SingleComponentUpdateContext(component.fault_state):
component.update()

def initializer():
nonlocal client
client = 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,
counter=create_counter_component,
inverter=create_inverter_component,
),
component_updater=MultiComponentUpdater(update_components)
)


device_descriptor = DeviceDescriptor(configuration_factory=FoxEssH3Smart)
49 changes: 49 additions & 0 deletions packages/modules/devices/fox_ess/fox_ess_h3_smart/inverter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#!/usr/bin/env python3
from typing import TypedDict, Any

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.utils.peak_filter import PeakFilter
from modules.common.modbus import ModbusDataType, ModbusTcpClient_
from modules.common.simcount import SimCounter
from modules.common.store import get_component_value_store
from modules.devices.fox_ess.fox_ess_h3_smart.config import FoxEssH3SmartInverterSetup
from modules.common.component_type import ComponentType


class KwargsDict(TypedDict):
device_id: int
client: ModbusTcpClient_


class FoxEssH3SmartInverter(AbstractInverter):
def __init__(self, component_config: FoxEssH3SmartInverterSetup, **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.client: ModbusTcpClient_ = self.kwargs['client']
self.store = get_component_value_store(self.component_config.type, self.component_config.id)
self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config))
self.peak_filter = PeakFilter(ComponentType.INVERTER, self.component_config.id, self.fault_state)
self.sim_counter = SimCounter(self.__device_id, self.component_config.id, self.component_config.type)

def update(self) -> None:
unit = self.component_config.configuration.modbus_id

pv_strings = self.client.read_holding_registers(39279, [ModbusDataType.INT_32]*6, unit=unit)
power = sum(pv_strings) * -1

self.peak_filter.check_values(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=FoxEssH3SmartInverterSetup)