From f4e20ce2f5b3e07842175d809b16d1857fda4647 Mon Sep 17 00:00:00 2001 From: AlexHuebi Date: Wed, 11 Jun 2025 19:40:08 +0200 Subject: [PATCH 1/3] testpatch for Victron 3P75CT --- packages/modules/common/modbus.py | 17 +++++++++++++++-- .../modules/devices/victron/victron/counter.py | 18 +++++++++--------- .../modules/devices/victron/victron/device.py | 4 ++-- 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/packages/modules/common/modbus.py b/packages/modules/common/modbus.py index f81f28b41e..9efead7f43 100644 --- a/packages/modules/common/modbus.py +++ b/packages/modules/common/modbus.py @@ -11,7 +11,7 @@ from typing import Any, Callable, Iterable, Optional, Union, overload, List import pymodbus -from pymodbus.client.sync import ModbusTcpClient, ModbusSerialClient +from pymodbus.client.sync import ModbusTcpClient, ModbusUdpClient, ModbusSerialClient from pymodbus.constants import Endian from pymodbus.payload import BinaryPayloadDecoder from urllib3.util import parse_url @@ -48,7 +48,7 @@ def __init__(self, bits: int, decoding_method: str): class ModbusClient: def __init__(self, - delegate: Union[ModbusSerialClient, ModbusTcpClient], + delegate: Union[ModbusSerialClient, ModbusTcpClient, ModbusUdpClient], address: str, port: int = 502, sleep_after_connect: Optional[int] = 0): self._delegate = delegate @@ -202,6 +202,19 @@ def __init__(self, super().__init__(ModbusTcpClient(host, port, **kwargs), address, port, sleep_after_connect) +class ModbusUdpClient_(ModbusClient): + def __init__(self, + address: str, + port: int = 502, + sleep_after_connect: Optional[int] = 0, + **kwargs): + parsed_url = parse_url(address) + host = parsed_url.host + if parsed_url.port is not None: + port = parsed_url.port + super().__init__(ModbusUdpClient(host, port, **kwargs), address, port, sleep_after_connect) + + class ModbusSerialClient_(ModbusClient): def __init__(self, port: int, diff --git a/packages/modules/devices/victron/victron/counter.py b/packages/modules/devices/victron/victron/counter.py index 00a992cfd7..2781792368 100644 --- a/packages/modules/devices/victron/victron/counter.py +++ b/packages/modules/devices/victron/victron/counter.py @@ -17,10 +17,10 @@ class VictronCounter(AbstractCounter): def __init__(self, device_id: int, component_config: Union[Dict, VictronCounterSetup], - tcp_client: modbus.ModbusTcpClient_) -> None: + udp_client: modbus.ModbusUdpClient_) -> None: self.__device_id = device_id self.component_config = dataclass_from_dict(VictronCounterSetup, component_config) - self.__tcp_client = tcp_client + self.__udp_client = udp_client 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)) @@ -28,18 +28,18 @@ def __init__(self, def update(self): unit = self.component_config.configuration.modbus_id energy_meter = self.component_config.configuration.energy_meter - with self.__tcp_client: + with self.__udp_client: if energy_meter: - powers = self.__tcp_client.read_holding_registers(2600, [ModbusDataType.INT_16]*3, unit=unit) + powers = self.__udp_client.read_holding_registers(0x3082, [ModbusDataType.INT_32]*3, unit=unit) currents = [ - self.__tcp_client.read_holding_registers(reg, ModbusDataType.INT_16, unit=unit) / 10 - for reg in [2617, 2619, 2621]] + self.__udp_client.read_holding_registers(reg, ModbusDataType.INT_16, unit=unit) / 100 + for reg in [0x3041, 0x3049, 0x3051]] voltages = [ - self.__tcp_client.read_holding_registers(reg, ModbusDataType.UINT_16, unit=unit) / 10 - for reg in [2616, 2618, 2620]] + self.__udp_client.read_holding_registers(reg, ModbusDataType.INT_16, unit=unit) / 100 + for reg in [0x3040, 0x3048, 0x3050]] power = sum(powers) else: - powers = self.__tcp_client.read_holding_registers(820, [ModbusDataType.INT_16]*3, unit=unit) + powers = self.__udp_client.read_holding_registers(820, [ModbusDataType.INT_16]*3, unit=unit) power = sum(powers) imported, exported = self.sim_counter.sim_count(power) diff --git a/packages/modules/devices/victron/victron/device.py b/packages/modules/devices/victron/victron/device.py index c74fdda0f8..87f01151ce 100644 --- a/packages/modules/devices/victron/victron/device.py +++ b/packages/modules/devices/victron/victron/device.py @@ -6,7 +6,7 @@ from modules.common.component_context import SingleComponentUpdateContext from modules.common.configurable_device import ComponentFactoryByType, ConfigurableDevice, MultiComponentUpdater -from modules.common.modbus import ModbusTcpClient_ +from modules.common.modbus import ModbusUdpClient_ from modules.devices.victron.victron.bat import VictronBat from modules.devices.victron.victron.config import Victron, VictronBatSetup, VictronCounterSetup, VictronInverterSetup from modules.devices.victron.victron.counter import VictronCounter @@ -32,7 +32,7 @@ def update_components(components: Iterable[Union[VictronBat, VictronCounter, Vic component.update() try: - client = ModbusTcpClient_(device_config.configuration.ip_address, device_config.configuration.port) + client = ModbusUdpClient_(device_config.configuration.ip_address, device_config.configuration.port) except Exception: log.exception("Fehler in create_device") return ConfigurableDevice( From 349d15089258965538cc08333382b9c8093649e4 Mon Sep 17 00:00:00 2001 From: AlexHuebi Date: Wed, 11 Jun 2025 19:56:22 +0200 Subject: [PATCH 2/3] fix for unrealistic phase values --- packages/modules/devices/victron/victron/counter.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/modules/devices/victron/victron/counter.py b/packages/modules/devices/victron/victron/counter.py index 2781792368..84a3b52e0f 100644 --- a/packages/modules/devices/victron/victron/counter.py +++ b/packages/modules/devices/victron/victron/counter.py @@ -30,7 +30,9 @@ def update(self): energy_meter = self.component_config.configuration.energy_meter with self.__udp_client: if energy_meter: - powers = self.__udp_client.read_holding_registers(0x3082, [ModbusDataType.INT_32]*3, unit=unit) + powers = [ + self.__udp_client.read_holding_registers(reg, ModbusDataType.INT_32, unit=unit) / 1 + for reg in [0x3082, 0x3086, 0x308A]] currents = [ self.__udp_client.read_holding_registers(reg, ModbusDataType.INT_16, unit=unit) / 100 for reg in [0x3041, 0x3049, 0x3051]] From f0f2049e69118ab2eb1e556240e5b0399cb15b8f Mon Sep 17 00:00:00 2001 From: AlexHuebi Date: Wed, 11 Jun 2025 20:07:13 +0200 Subject: [PATCH 3/3] fix power/current directions --- packages/modules/devices/victron/victron/counter.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/modules/devices/victron/victron/counter.py b/packages/modules/devices/victron/victron/counter.py index 84a3b52e0f..7da2834cd9 100644 --- a/packages/modules/devices/victron/victron/counter.py +++ b/packages/modules/devices/victron/victron/counter.py @@ -31,10 +31,10 @@ def update(self): with self.__udp_client: if energy_meter: powers = [ - self.__udp_client.read_holding_registers(reg, ModbusDataType.INT_32, unit=unit) / 1 + self.__udp_client.read_holding_registers(reg, ModbusDataType.INT_32, unit=unit) / -1 for reg in [0x3082, 0x3086, 0x308A]] currents = [ - self.__udp_client.read_holding_registers(reg, ModbusDataType.INT_16, unit=unit) / 100 + self.__udp_client.read_holding_registers(reg, ModbusDataType.INT_16, unit=unit) / -100 for reg in [0x3041, 0x3049, 0x3051]] voltages = [ self.__udp_client.read_holding_registers(reg, ModbusDataType.INT_16, unit=unit) / 100