From 0a76c941e62a9cc9e49b583d70641de862646540 Mon Sep 17 00:00:00 2001 From: ndrsnhs Date: Wed, 18 Dec 2024 11:21:25 +0100 Subject: [PATCH 1/4] add high and low volt deye inverter --- packages/modules/devices/deye/deye/bat.py | 25 +++++++++------- packages/modules/devices/deye/deye/config.py | 4 +-- packages/modules/devices/deye/deye/counter.py | 29 ++++++++++--------- .../modules/devices/deye/deye/device_type.py | 8 +++-- .../modules/devices/deye/deye/inverter.py | 13 +++++---- 5 files changed, 44 insertions(+), 35 deletions(-) diff --git a/packages/modules/devices/deye/deye/bat.py b/packages/modules/devices/deye/deye/bat.py index c3d98ca1ca..94216adbc4 100644 --- a/packages/modules/devices/deye/deye/bat.py +++ b/packages/modules/devices/deye/deye/bat.py @@ -25,25 +25,30 @@ def __init__(self, device_id: int, component_config: DeyeBatSetup) -> None: def update(self, client: ModbusTcpClient_, device_type: DeviceType) -> None: unit = self.component_config.configuration.modbus_id - if device_type == DeviceType.THREE_PHASE: - power = client.read_holding_registers(590, ModbusDataType.INT_16, unit=unit) * -1 - soc = client.read_holding_registers(588, ModbusDataType.INT_16, unit=unit) - # 516: Geladen in kWh * 0,1 - imported = client.read_holding_registers(516, ModbusDataType.UINT_16, unit=unit) * 100 - # 518: Entladen in kWh * 0,1 - exported = client.read_holding_registers(518, ModbusDataType.UINT_16, unit=unit) * 100 - elif device_type == DeviceType.SINGLE_PHASE_STRING or device_type == DeviceType.SINGLE_PHASE_HYBRID: + if self.device_type == DeviceType.SINGLE_PHASE_STRING or self.device_type == DeviceType.SINGLE_PHASE_HYBRID: power = client.read_holding_registers(190, ModbusDataType.INT_16, unit=unit) * -1 soc = client.read_holding_registers(184, ModbusDataType.INT_16, unit=unit) - if device_type == DeviceType.SINGLE_PHASE_HYBRID: + if self.device_type == DeviceType.SINGLE_PHASE_HYBRID: # 516: Geladen in kWh * 0,1 imported = client.read_holding_registers(72, ModbusDataType.UINT_16, unit=unit) * 100 # 518: Entladen in kWh * 0,1 exported = client.read_holding_registers(74, ModbusDataType.UINT_16, unit=unit) * 100 - elif device_type == DeviceType.SINGLE_PHASE_STRING: + + elif self.device_type == DeviceType.SINGLE_PHASE_STRING: imported, exported = self.sim_counter.sim_count(power) + else: # THREE_PHASE_LV (0x0500, 0x0005), THREE_PHASE_HV (0x0006) + power = client.read_holding_registers(590, ModbusDataType.INT_16, unit=unit) * -1 + + if self.device_type == DeviceType.THREE_PHASE_HV: + power = power * 10 + soc = client.read_holding_registers(588, ModbusDataType.INT_16, unit=unit) + # 516: Geladen in kWh * 0,1 + imported = client.read_holding_registers(516, ModbusDataType.UINT_16, unit=unit) * 100 + # 518: Entladen in kWh * 0,1 + exported = client.read_holding_registers(518, ModbusDataType.UINT_16, unit=unit) * 100 + bat_state = BatState( power=power, soc=soc, diff --git a/packages/modules/devices/deye/deye/config.py b/packages/modules/devices/deye/deye/config.py index a14b8fe1c1..991aa26486 100644 --- a/packages/modules/devices/deye/deye/config.py +++ b/packages/modules/devices/deye/deye/config.py @@ -8,11 +8,9 @@ class DeyeConfiguration: def __init__(self, ip_address: Optional[str] = None, - port: int = 8899, - device_type: str = "three_phase"): + port: int = 8899): self.ip_address = ip_address self.port = port - self.device_type = device_type class Deye: diff --git a/packages/modules/devices/deye/deye/counter.py b/packages/modules/devices/deye/deye/counter.py index e92b355b97..806dbbc968 100644 --- a/packages/modules/devices/deye/deye/counter.py +++ b/packages/modules/devices/deye/deye/counter.py @@ -22,34 +22,35 @@ def __init__(self, device_id: int, component_config: DeyeCounterSetup) -> None: def update(self, client: ModbusTcpClient_, device_type: DeviceType): unit = self.component_config.configuration.modbus_id - if device_type == DeviceType.THREE_PHASE: - currents = [c / 100 for c in client.read_holding_registers(613, [ModbusDataType.INT_16]*3, unit=unit)] - voltages = [v / 10 for v in client.read_holding_registers(644, [ModbusDataType.INT_16]*3, unit=unit)] - powers = client.read_holding_registers(616, [ModbusDataType.INT_16]*3, unit=unit) - power = sum(powers) - frequency = client.read_holding_registers(187, ModbusDataType.INT_32, unit=unit) * 100 - - # Wenn der Import/export Netz in wh gerechnet wird => *100 !! kommt in kw/h *0.1 - imported = client.read_holding_registers(522, ModbusDataType.INT_16, unit=unit) * 100 - exported = client.read_holding_registers(524, ModbusDataType.INT_16, unit=unit) * 100 - - elif device_type == DeviceType.SINGLE_PHASE_STRING or device_type == DeviceType.SINGLE_PHASE_HYBRID: + if self.device_type == DeviceType.SINGLE_PHASE_STRING or self.device_type == DeviceType.SINGLE_PHASE_HYBRID: frequency = client.read_holding_registers(79, ModbusDataType.INT_16, unit=unit) * 100 - if device_type == DeviceType.SINGLE_PHASE_HYBRID: + if self.device_type == DeviceType.SINGLE_PHASE_HYBRID: powers = [0]*3 currents = [0]*3 voltages = [0]*3 power = [0] # High und low word vom import sind nicht in aufeinanderfolgenden Registern imported, exported = self.sim_counter.sim_count(power) - elif device_type == DeviceType.SINGLE_PHASE_STRING: + + elif self.device_type == DeviceType.SINGLE_PHASE_STRING: currents = [c / 100 for c in client.read_holding_registers(76, [ModbusDataType.INT_16]*3, unit=unit)] voltages = [v / 10 for v in client.read_holding_registers(70, [ModbusDataType.INT_16]*3, unit=unit)] powers = [currents[i] * voltages[i] for i in range(0, 3)] power = sum(powers) imported, exported = self.sim_counter.sim_count(power) + else: # THREE_PHASE_LV (0x0500, 0x0005), THREE_PHASE_HV (0x0006) + currents = [c / 100 for c in client.read_holding_registers(613, [ModbusDataType.INT_16]*3, unit=unit)] + voltages = [v / 10 for v in client.read_holding_registers(644, [ModbusDataType.INT_16]*3, unit=unit)] + powers = client.read_holding_registers(616, [ModbusDataType.INT_16]*3, unit=unit) + power = client.read_holding_registers(625, ModbusDataType.INT_16, unit=unit) + frequency = client.read_holding_registers(609, ModbusDataType.INT_16, unit=unit) / 100 + + # Wenn der Import/export Netz in wh gerechnet wird => *100 !! kommt in kw/h *0.1 + imported = client.read_holding_registers(522, ModbusDataType.INT_16, unit=unit) * 100 + exported = client.read_holding_registers(524, ModbusDataType.INT_16, unit=unit) * 100 + counter_state = CounterState( currents=currents, imported=imported, diff --git a/packages/modules/devices/deye/deye/device_type.py b/packages/modules/devices/deye/deye/device_type.py index 3baef0a7ba..6e38c65bab 100644 --- a/packages/modules/devices/deye/deye/device_type.py +++ b/packages/modules/devices/deye/deye/device_type.py @@ -2,6 +2,8 @@ class DeviceType(Enum): - SINGLE_PHASE_HYBRID = "single_phase_hybrid" - SINGLE_PHASE_STRING = "single_phase_string" - THREE_PHASE = "three_phase" + SINGLE_PHASE_STRING = 0x0200 + SINGLE_PHASE_HYBRID = 0x0300 + THREE_PHASE_LV_0 = 0x0500 + THREE_PHASE_LV_1 = 0x0005 + THREE_PHASE_HV = 0x0006 diff --git a/packages/modules/devices/deye/deye/inverter.py b/packages/modules/devices/deye/deye/inverter.py index aa90166dbd..7256cc1632 100644 --- a/packages/modules/devices/deye/deye/inverter.py +++ b/packages/modules/devices/deye/deye/inverter.py @@ -24,14 +24,17 @@ def __init__(self, device_id: int, component_config: Union[Dict, DeyeInverterSet def update(self, client: ModbusTcpClient_, device_type: DeviceType) -> None: unit = self.component_config.configuration.modbus_id - if device_type == DeviceType.THREE_PHASE: - # Wechselrichter hat 2 mppt Tracker + if self.device_type == DeviceType.SINGLE_PHASE_STRING or self.device_type == DeviceType.SINGLE_PHASE_HYBRID: + power = sum(client.read_holding_registers(186, [ModbusDataType.INT_16]*4, unit=unit)) * -1 + exported = self.sim_counter.sim_count(power)[1] + + else: # THREE_PHASE_LV (0x0500, 0x0005), THREE_PHASE_HV (0x0006) power = sum(client.read_holding_registers(672, [ModbusDataType.INT_16]*2, unit=unit)) * -1 + + if self.device_type == DeviceType.THREE_PHASE_HV: + power = power * 10 # 534: Gesamt Produktion Wechselrichter unsigned integer in kWh * 0,1 exported = client.read_holding_registers(534, ModbusDataType.UINT_16, unit=unit) * 100 - elif device_type == DeviceType.SINGLE_PHASE_STRING or device_type == DeviceType.SINGLE_PHASE_HYBRID: - power = sum(client.read_holding_registers(186, [ModbusDataType.INT_16]*4, unit=unit)) * -1 - exported = self.sim_counter.sim_count(power)[1] inverter_state = InverterState( power=power, From ecc8b2d009eac76af93cc2a2fc34701f1108764f Mon Sep 17 00:00:00 2001 From: ndrsnhs Date: Wed, 18 Dec 2024 11:30:30 +0100 Subject: [PATCH 2/4] read deye inverter type --- packages/modules/devices/deye/deye/device.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/packages/modules/devices/deye/deye/device.py b/packages/modules/devices/deye/deye/device.py index 29722531f6..5389dbdcf7 100644 --- a/packages/modules/devices/deye/deye/device.py +++ b/packages/modules/devices/deye/deye/device.py @@ -6,7 +6,7 @@ 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.common.modbus import ModbusDataType, ModbusTcpClient_ from modules.devices.deye.deye.bat import DeyeBat from modules.devices.deye.deye.counter import DeyeCounter from modules.devices.deye.deye.device_type import DeviceType @@ -19,13 +19,19 @@ def create_device(device_config: Deye): def create_bat_component(component_config: DeyeBatSetup): - return DeyeBat(device_config.id, component_config) + device_type = client.read_holding_registers( + 0, ModbusDataType.INT_16, unit=component_config.configuration.modbus_id) + return DeyeBat(device_config.id, component_config, device_type) def create_counter_component(component_config: DeyeCounterSetup): - return DeyeCounter(device_config.id, component_config) + device_type = client.read_holding_registers( + 0, ModbusDataType.INT_16, unit=component_config.configuration.modbus_id) + return DeyeCounter(device_config.id, component_config, device_type) def create_inverter_component(component_config: DeyeInverterSetup): - return DeyeInverter(device_config.id, component_config) + device_type = client.read_holding_registers( + 0, ModbusDataType.INT_16, unit=component_config.configuration.modbus_id) + return DeyeInverter(device_config.id, component_config, device_type) def update_components(components: Iterable[Union[DeyeBat, DeyeCounter, DeyeInverter]]): with client as c: From d0e6f2cdd895323ccbad15530315bfc236e6c4c2 Mon Sep 17 00:00:00 2001 From: ndrsnhs Date: Wed, 18 Dec 2024 12:14:53 +0100 Subject: [PATCH 3/4] add type detection to devices --- packages/modules/devices/deye/deye/bat.py | 5 ++++- packages/modules/devices/deye/deye/counter.py | 5 ++++- packages/modules/devices/deye/deye/device_type.py | 4 ++-- packages/modules/devices/deye/deye/inverter.py | 5 ++++- 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/packages/modules/devices/deye/deye/bat.py b/packages/modules/devices/deye/deye/bat.py index 94216adbc4..f94b9bfdcf 100644 --- a/packages/modules/devices/deye/deye/bat.py +++ b/packages/modules/devices/deye/deye/bat.py @@ -15,12 +15,15 @@ class DeyeBat(AbstractBat): - def __init__(self, device_id: int, component_config: DeyeBatSetup) -> None: + def __init__(self, device_id: int, + component_config: DeyeBatSetup, + device_type: DeviceType) -> None: self.component_config = dataclass_from_dict(DeyeBatSetup, component_config) self.store = get_bat_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) self.__device_id = device_id self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="speicher") + self.device_type = device_type def update(self, client: ModbusTcpClient_, device_type: DeviceType) -> None: unit = self.component_config.configuration.modbus_id diff --git a/packages/modules/devices/deye/deye/counter.py b/packages/modules/devices/deye/deye/counter.py index 806dbbc968..74b4215e17 100644 --- a/packages/modules/devices/deye/deye/counter.py +++ b/packages/modules/devices/deye/deye/counter.py @@ -12,12 +12,15 @@ class DeyeCounter(AbstractCounter): - def __init__(self, device_id: int, component_config: DeyeCounterSetup) -> None: + def __init__(self, device_id: int, + component_config: DeyeCounterSetup, + device_type: DeviceType) -> None: self.component_config = dataclass_from_dict(DeyeCounterSetup, component_config) self.store = get_counter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) self.__device_id = device_id self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="bezug") + self.device_type = device_type def update(self, client: ModbusTcpClient_, device_type: DeviceType): unit = self.component_config.configuration.modbus_id diff --git a/packages/modules/devices/deye/deye/device_type.py b/packages/modules/devices/deye/deye/device_type.py index 6e38c65bab..c5241c1a63 100644 --- a/packages/modules/devices/deye/deye/device_type.py +++ b/packages/modules/devices/deye/deye/device_type.py @@ -1,7 +1,7 @@ -from enum import Enum +from enum import IntEnum -class DeviceType(Enum): +class DeviceType(IntEnum): SINGLE_PHASE_STRING = 0x0200 SINGLE_PHASE_HYBRID = 0x0300 THREE_PHASE_LV_0 = 0x0500 diff --git a/packages/modules/devices/deye/deye/inverter.py b/packages/modules/devices/deye/deye/inverter.py index 7256cc1632..e836ef112b 100644 --- a/packages/modules/devices/deye/deye/inverter.py +++ b/packages/modules/devices/deye/deye/inverter.py @@ -14,12 +14,15 @@ class DeyeInverter(AbstractInverter): - def __init__(self, device_id: int, component_config: Union[Dict, DeyeInverterSetup]) -> None: + def __init__(self, device_id: int, + component_config: Union[Dict, DeyeInverterSetup], + device_type: DeviceType) -> None: self.component_config = dataclass_from_dict(DeyeInverterSetup, component_config) self.store = get_inverter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) self.__device_id = device_id self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="pv") + self.device_type = device_type def update(self, client: ModbusTcpClient_, device_type: DeviceType) -> None: unit = self.component_config.configuration.modbus_id From b1e24297a7f891a4a9c40deebd42bf45157c6152 Mon Sep 17 00:00:00 2001 From: ndrsnhs Date: Wed, 18 Dec 2024 12:16:29 +0100 Subject: [PATCH 4/4] adjust frequency factor --- packages/modules/devices/deye/deye/counter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/modules/devices/deye/deye/counter.py b/packages/modules/devices/deye/deye/counter.py index 74b4215e17..7926503034 100644 --- a/packages/modules/devices/deye/deye/counter.py +++ b/packages/modules/devices/deye/deye/counter.py @@ -26,7 +26,7 @@ def update(self, client: ModbusTcpClient_, device_type: DeviceType): unit = self.component_config.configuration.modbus_id if self.device_type == DeviceType.SINGLE_PHASE_STRING or self.device_type == DeviceType.SINGLE_PHASE_HYBRID: - frequency = client.read_holding_registers(79, ModbusDataType.INT_16, unit=unit) * 100 + frequency = client.read_holding_registers(79, ModbusDataType.INT_16, unit=unit) / 100 if self.device_type == DeviceType.SINGLE_PHASE_HYBRID: powers = [0]*3