diff --git a/packages/helpermodules/update_config.py b/packages/helpermodules/update_config.py index 07ed97fc2a..eb122d6521 100644 --- a/packages/helpermodules/update_config.py +++ b/packages/helpermodules/update_config.py @@ -28,6 +28,8 @@ from control import ev from control.general import Prices from modules.common.abstract_vehicle import GeneralVehicleConfig +from modules.common.component_type import ComponentType +from modules.devices.sungrow.version import Version from modules.display_themes.cards.config import CardsDisplayTheme from modules.ripple_control_receivers.gpio.config import GpioRcr from modules.web_themes.standard_legacy.config import StandardLegacyWebTheme @@ -38,7 +40,7 @@ class UpdateConfig: - DATASTORE_VERSION = 43 + DATASTORE_VERSION = 44 valid_topic = [ "^openWB/bat/config/configured$", "^openWB/bat/set/charging_power_left$", @@ -191,9 +193,7 @@ class UpdateConfig: "^openWB/general/chargemode_config/pv_charging/phases_to_use$", "^openWB/general/chargemode_config/pv_charging/min_bat_soc$", "^openWB/general/chargemode_config/pv_charging/bat_power_discharge$", - "^openWB/general/chargemode_config/pv_charging/bat_power_discharge_active$", "^openWB/general/chargemode_config/pv_charging/bat_power_reserve$", - "^openWB/general/chargemode_config/pv_charging/bat_power_reserve_active$", "^openWB/general/chargemode_config/retry_failed_phase_switches$", "^openWB/general/chargemode_config/scheduled_charging/phases_to_use$", "^openWB/general/chargemode_config/instant_charging/phases_to_use$", @@ -419,10 +419,8 @@ class UpdateConfig: ("openWB/general/chargemode_config/instant_charging/phases_to_use", 3), ("openWB/general/chargemode_config/pv_charging/bat_mode", BatConsiderationMode.EV_MODE.value), ("openWB/general/chargemode_config/pv_charging/bat_power_discharge", 1000), - ("openWB/general/chargemode_config/pv_charging/bat_power_discharge_active", False), ("openWB/general/chargemode_config/pv_charging/min_bat_soc", 50), ("openWB/general/chargemode_config/pv_charging/bat_power_reserve", 200), - ("openWB/general/chargemode_config/pv_charging/bat_power_reserve_active", False), ("openWB/general/chargemode_config/pv_charging/control_range", [0, 230]), ("openWB/general/chargemode_config/pv_charging/switch_off_threshold", 50), ("openWB/general/chargemode_config/pv_charging/switch_off_delay", 60), @@ -1439,3 +1437,53 @@ def upgrade(topic: str, payload) -> Optional[dict]: payload) > 0} self._loop_all_received_topics(upgrade) self.__update_topic("openWB/system/datastore_version", 43) + + def upgrade_datastore_43(self) -> None: + def upgrade(topic: str, payload) -> None: + if re.search("openWB/system/device/[0-9]+", topic) is not None: + device = decode_payload(payload) + if device.get("type") == "sungrow" and "version" not in device["configuration"]: + device_id = get_index(topic) + device_name = device.get("name") + version = None + inverter_id = None + battery_id = None + hierarchy = None + for other_topic, other_payload in self.all_received_topics.items(): + if re.search(f"openWB/system/device/{device_id}/component/[0-9]+", other_topic) is not None: + component = decode_payload(other_payload) + component_id = int(get_second_index(other_topic)) + if component.get("type") == ComponentType.COUNTER.value \ + and "version" in component["configuration"]: + version = component['configuration']['version'] + log.debug(f"Version {version} found for device {device_id} '{device_name}'") + elif component.get("type") == ComponentType.BAT.value: + battery_id = component_id + elif component.get("type") == ComponentType.INVERTER.value: + inverter_id = component_id + elif re.search("openWB/counter/get/hierarchy", other_topic) is not None: + hierarchy = decode_payload(other_payload) + + if battery_id or version == Version.SH: + # Assume an SH_WiNet if hybrid inverter, this is compatible to SH_LAN (but not vice versa) + version = Version.SH_winet_dongle + elif not version: + # Assume an SG_WiNet version as default if no battery or version from counter found + version = Version.SG_winet_dongle + log.debug(f"Setting version {version} for device {device_id} '{device_name}'") + device["configuration"].update({"version": version}) + Pub().pub(topic, device) + pub_system_message(device, f"Die Konfiguration von '{device_name}' wurde aktualisiert. " + f"Bitte in den Geräteeinstellungen sicherstellen, dass Version " + f"'{Version(version).name}' korrekt ist", MessageType.INFO) + + if battery_id and inverter_id and hierarchy: + _counter_all = counter_all.CounterAll() + _counter_all.data.get.hierarchy = hierarchy + _counter_all.hierarchy_remove_item(battery_id) + _counter_all.hierarchy_add_item_below(battery_id, ComponentType.BAT, inverter_id) + log.debug(f"Moved battery {battery_id} below inverter {inverter_id} in hierarchy") + Pub().pub("openWB/counter/get/hierarchy", _counter_all.data.get.hierarchy) + + self._loop_all_received_topics(upgrade) + Pub().pub("openWB/system/datastore_version", 44) diff --git a/packages/modules/devices/sungrow/bat.py b/packages/modules/devices/sungrow/bat.py index 86e7316a9d..dc579b7ebb 100644 --- a/packages/modules/devices/sungrow/bat.py +++ b/packages/modules/devices/sungrow/bat.py @@ -9,25 +9,23 @@ from modules.common.modbus import ModbusDataType from modules.common.simcount import SimCounter from modules.common.store import get_bat_value_store -from modules.devices.sungrow.config import SungrowBatSetup +from modules.devices.sungrow.config import SungrowBatSetup, Sungrow class SungrowBat: def __init__(self, - device_id: int, - device_modbus_id: int, + device_config: Union[Dict, Sungrow], component_config: Union[Dict, SungrowBatSetup], tcp_client: modbus.ModbusTcpClient_) -> None: - self.__device_id = device_id - self.__device_modbus_id = device_modbus_id + self.device_config = device_config self.component_config = dataclass_from_dict(SungrowBatSetup, component_config) self.__tcp_client = tcp_client - self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="speicher") + self.sim_counter = SimCounter(self.device_config.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.__device_modbus_id + unit = self.device_config.configuration.modbus_id soc = int(self.__tcp_client.read_input_registers(13022, ModbusDataType.INT_16, unit=unit) / 10) resp = self.__tcp_client._delegate.read_input_registers(13000, 1, unit=unit) binary = bin(resp.registers[0])[2:].zfill(8) diff --git a/packages/modules/devices/sungrow/config.py b/packages/modules/devices/sungrow/config.py index 2fb6a668cd..2d9adfab4b 100644 --- a/packages/modules/devices/sungrow/config.py +++ b/packages/modules/devices/sungrow/config.py @@ -1,13 +1,19 @@ from typing import Optional from modules.common.component_setup import ComponentSetup +from modules.devices.sungrow.version import Version class SungrowConfiguration: - def __init__(self, ip_address: Optional[str] = None, port: int = 502, modbus_id: int = 1): + def __init__(self, + ip_address: Optional[str] = None, + port: int = 502, + modbus_id: int = 1, + version: Version = Version.SG): self.ip_address = ip_address self.port = port self.modbus_id = modbus_id + self.version = version class Sungrow: @@ -37,8 +43,8 @@ def __init__(self, class SungrowCounterConfiguration: - def __init__(self, version=1): - self.version = version + def __init__(self): + pass class SungrowCounterSetup(ComponentSetup[SungrowCounterConfiguration]): diff --git a/packages/modules/devices/sungrow/counter.py b/packages/modules/devices/sungrow/counter.py index 6d1c58f428..04d20a10ae 100644 --- a/packages/modules/devices/sungrow/counter.py +++ b/packages/modules/devices/sungrow/counter.py @@ -9,34 +9,29 @@ from modules.common.modbus import ModbusDataType, Endian from modules.common.simcount import SimCounter from modules.common.store import get_counter_value_store -from modules.devices.sungrow.config import SungrowCounterSetup +from modules.devices.sungrow.config import SungrowCounterSetup, Sungrow from modules.devices.sungrow.version import Version class SungrowCounter: def __init__(self, - device_id: int, - device_modbus_id: int, + device_config: Union[Dict, Sungrow], component_config: Union[Dict, SungrowCounterSetup], tcp_client: modbus.ModbusTcpClient_) -> None: - self.__device_id = device_id - self.__device_modbus_id = device_modbus_id + self.device_config = device_config self.component_config = dataclass_from_dict(SungrowCounterSetup, component_config) self.__tcp_client = tcp_client - self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="bezug") + self.sim_counter = SimCounter(self.device_config.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, pv_power: float): - unit = self.__device_modbus_id - if self.component_config.configuration.version == Version.SH: + unit = self.device_config.configuration.modbus_id + if self.device_config.configuration.version in (Version.SH, Version.SH_winet_dongle): power = self.__tcp_client.read_input_registers(13009, ModbusDataType.INT_32, wordorder=Endian.Little, unit=unit) * -1 - # no valid data for powers per phase - # powers = self.__tcp_client.read_input_registers(5084, [ModbusDataType.INT_16] * 3, - # wordorder=Endian.Little, unit=unit) - # powers = [power / 10 for power in powers] - # log.info("power: " + str(power) + " powers?: " + str(powers)) + powers = self.__tcp_client.read_input_registers(5602, [ModbusDataType.INT_32] * 3, + wordorder=Endian.Little, unit=unit) else: if pv_power != 0: power = self.__tcp_client.read_input_registers(5082, ModbusDataType.INT_32, @@ -44,16 +39,26 @@ def update(self, pv_power: float): else: power = self.__tcp_client.read_input_registers(5090, ModbusDataType.INT_32, wordorder=Endian.Little, unit=unit) + powers = self.__tcp_client.read_input_registers(5084, [ModbusDataType.INT_32] * 3, + wordorder=Endian.Little, unit=unit) - # no valid data for powers per phase - # powers = self.__tcp_client.read_input_registers(5084, [ModbusDataType.UINT_16] * 3, - # wordorder=Endian.Little, unit=unit) - # powers = [power / 10 for power in powers] - # log.info("power: " + str(power) + " powers?: " + str(powers)) frequency = self.__tcp_client.read_input_registers(5035, ModbusDataType.UINT_16, unit=unit) / 10 - voltages = self.__tcp_client.read_input_registers(5018, [ModbusDataType.UINT_16] * 3, - wordorder=Endian.Little, unit=unit) - voltages = [voltage / 10 for voltage in voltages] + if self.device_config.configuration.version == Version.SH_winet_dongle: + # On WiNet-S, the frequency accuracy is higher by one place + frequency /= 10 + + power_factor = self.__tcp_client.read_input_registers(5034, ModbusDataType.INT_16, unit=unit) / 1000 + + if self.device_config.configuration.version == Version.SH: + # SH (LAN) provides accurate values from meter + voltages = self.__tcp_client.read_input_registers(5740, [ModbusDataType.UINT_16] * 3, + wordorder=Endian.Little, unit=unit) + else: + # These are actually output voltages of the inverter: + voltages = self.__tcp_client.read_input_registers(5018, [ModbusDataType.UINT_16] * 3, + wordorder=Endian.Little, unit=unit) + + voltages = [value / 10 for value in voltages] imported, exported = self.sim_counter.sim_count(power) @@ -61,8 +66,10 @@ def update(self, pv_power: float): imported=imported, exported=exported, power=power, + powers=powers, voltages=voltages, - frequency=frequency + frequency=frequency, + power_factors=[power_factor] * 3 ) self.store.set(counter_state) diff --git a/packages/modules/devices/sungrow/device.py b/packages/modules/devices/sungrow/device.py index 86cf56eb31..8b24a09e32 100644 --- a/packages/modules/devices/sungrow/device.py +++ b/packages/modules/devices/sungrow/device.py @@ -46,7 +46,7 @@ def add_component(self, COMPONENT_TYPE_TO_MODULE[component_type].component_descriptor.configuration_factory, component_config) if component_type in self.COMPONENT_TYPE_TO_CLASS: self.components["component" + str(component_config.id)] = (self.COMPONENT_TYPE_TO_CLASS[component_type]( - self.device_config.id, self.device_config.configuration.modbus_id, component_config, self.client)) + self.device_config, component_config, self.client)) else: raise Exception( "illegal component type " + component_type + ". Allowed values: " + @@ -84,23 +84,25 @@ def update(self) -> None: def read_legacy(ip_address: str, port: int, modbus_id: int, + version: int, component_config: dict): device_config = Sungrow() device_config.configuration.ip_address = ip_address device_config.configuration.port = port device_config.configuration.modbus_id = modbus_id + device_config.configuration.version = Version(version) dev = Device(device_config) dev.add_component(component_config) dev.update() -def read_legacy_bat(ip_address: str, port: int, modbus_id: int): - read_legacy(ip_address, port, modbus_id, bat.component_descriptor.configuration_factory(id=None)) +def read_legacy_bat(ip_address: str, port: int, modbus_id: int, version: int): + read_legacy(ip_address, port, modbus_id, version, bat.component_descriptor.configuration_factory(id=None)) def read_legacy_counter(ip_address: str, port: int, modbus_id: int, version: int): - read_legacy(ip_address, port, modbus_id, counter.component_descriptor.configuration_factory( - id=None, configuration=SungrowCounterConfiguration(version=Version(version)))) + read_legacy(ip_address, port, modbus_id, version, counter.component_descriptor.configuration_factory( + id=None, configuration=SungrowCounterConfiguration())) def read_legacy_inverter(ip_address: str, @@ -113,11 +115,12 @@ def read_legacy_inverter(ip_address: str, device_config.configuration.ip_address = ip_address device_config.configuration.port = port device_config.configuration.modbus_id = modbus_id + device_config.configuration.version = Version(version) dev = Device(device_config) dev.add_component(inverter.component_descriptor.configuration_factory(id=num)) if read_counter == 1: dev.add_component(counter.component_descriptor.configuration_factory( - id=None, configuration=SungrowCounterConfiguration(version=Version(version)))) + id=None, configuration=SungrowCounterConfiguration())) dev.update() diff --git a/packages/modules/devices/sungrow/inverter.py b/packages/modules/devices/sungrow/inverter.py index 40908325de..23199f9cf4 100644 --- a/packages/modules/devices/sungrow/inverter.py +++ b/packages/modules/devices/sungrow/inverter.py @@ -9,29 +9,31 @@ from modules.common.modbus import ModbusDataType, Endian from modules.common.simcount import SimCounter from modules.common.store import get_inverter_value_store -from modules.devices.sungrow.config import SungrowInverterSetup +from modules.devices.sungrow.config import SungrowInverterSetup, Sungrow +from modules.devices.sungrow.version import Version class SungrowInverter: def __init__(self, - device_id: int, - device_modbus_id: int, + device_config: Union[Dict, Sungrow], component_config: Union[Dict, SungrowInverterSetup], tcp_client: modbus.ModbusTcpClient_) -> None: - self.__device_id = device_id - self.__device_modbus_id = device_modbus_id + self.device_config = device_config self.component_config = dataclass_from_dict(SungrowInverterSetup, component_config) self.__tcp_client = tcp_client - self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="pv") + self.sim_counter = SimCounter(self.device_config.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) -> float: - unit = self.__device_modbus_id - power = self.__tcp_client.read_input_registers(5016, - ModbusDataType.UINT_32, - wordorder=Endian.Little, - unit=unit) * -1 + unit = self.device_config.configuration.modbus_id + + if self.device_config.configuration.version in (Version.SH, Version.SH_winet_dongle): + power = self.__tcp_client.read_input_registers(13033, ModbusDataType.INT_32, + wordorder=Endian.Little, unit=unit) * -1 + else: + power = self.__tcp_client.read_input_registers(5030, ModbusDataType.INT_32, + wordorder=Endian.Little, unit=unit) * -1 _, exported = self.sim_counter.sim_count(power) diff --git a/packages/modules/devices/sungrow/modbus.md b/packages/modules/devices/sungrow/modbus.md new file mode 100644 index 0000000000..35a07e588b --- /dev/null +++ b/packages/modules/devices/sungrow/modbus.md @@ -0,0 +1,42 @@ +# Modbus Adressen für Sungrow SH* und SG* Wechselrichter + +## Datengrundlage: +* TI_20230918_Communication Protocol of Residential and Commerical PV Grid-connected Inverter_V1.1.58_EN.pdf +* TI_20231019_Communication Protocol of Residential Hybrid Inverter_V1.1.2_EN.pdf +* modbus_finder.py an SH10RT-V112 (LAN) Firmware SAPPHIRE-H_B001.V000.P005-20231027 +* modbus_finder.py an SH10RT-V112 (WiNet-S) Firmware WINET-SV200.001.00.P023 +* modbus_finder.py an SG10RT (WiNet-S) Firmware BERYL-S_B000.V000.P039-20230626 / WINET-SV200.001.00.P023 + +## Werte +| Wert | SH_LAN | SH_WiNet | SG_WiNet | Einheit | Typ | Bemerkung | +|-------------------------------------|--------|----------|---------------|---------|----------------|------------------------------------------------------------------| +| WR: Zähler inkl. Batterieentladung | 5003 | 5003 | -- | 0.1 kWh | UINT_32 mixed | Delta zu 'WR: Zähler Gesamtertrag' ist entladene **Netz**energie | +| WR: Zähler Gesamtertrag | 5660 | -- | 5143 | 0.1 kWh | UINT_32 mixed | Wirkleistungszähler, abweichend zu Gesamt-PV-Stromerzeugung | +| WR: AC Ausgangsspannung Phase A | 5018 | 5018 | 5018 | 0.1 V | UINT_16 little | Unterscheidet sich pro WR (nicht vom Meter gemessen) | +| WR: AC Ausgangsspannung Phase B | 5019 | 5019 | 5019 | 0.1 V | UINT_16 little | Unterscheidet sich pro WR (nicht vom Meter gemessen) | +| WR: AC Ausgangsspannung Phase C | 5020 | 5020 | 5020 | 0.1 V | UINT_16 little | Unterscheidet sich pro WR (nicht vom Meter gemessen) | +| WR: Akt. DC Bruttoleistung | 5016 | 5016 | 5016 | 1 W | INT_32 mixed | | +| WR: Akt. AC Wirkleistung | 13033 | 13033 | -- | 1 W | INT_32 mixed | ggf. Speicherladung addieren für effektive PV-Leistung | +| WR: Akt. AC Wirkleistung | 5030 | -- | 5030 | 1 W | INT_32 mixed | 5030 "altes" Register, 13033 bevorzugt für SH Versionen | +| WR: Akt. Leistungsfluss | 13000 | 13000 | -- | ja/nein | 8-bit bitmask | (v.r.) Bit0: PV-Erzeugung, Bit1: Batt. lädt, Bit2: Batt. entlädt | +| BAT: Akt. Leistung (ein-/ausgehend) | 13021 | 13021 | -- | 1 W | UINT16 little | Immer positiv, bei Be- und Entladung. WR Leistungsfluss beachten | +| BAT: SoC | 13022 | 13022 | -- | 0.1 % | UINT16 little | | +| BAT: Zähler Ladung von PV | 13012 | 13012 | -- | 0.1 kWh | UINT32 mixed | | +| BAT: Zähler Gesamtladung | 13026 | 13026 | -- | 0.1 kWh | UINT32 mixed | | +| BAT: Zähler Gesamtentladung | 13040 | 13040 | -- | 0.1 kWh | UINT32 mixed | | +| Netz: Akt. Wirkleistung | 13009 | 13009 | -- | -1 W | INT_32 mixed | | +| Netz: Akt. Wirkleistung | -- | -- | ? 5090 ? 5082 | 1 W | INT_32 mixed | | +| Netz: Akt. Frequenz | 5035 | -- | 5035 | 0.1 Hz | UINT_16 little | | +| Netz: Akt. Frequenz | -- | 5035 | -- | 0.01 Hz | UINT_16 little | | +| Netz: Akt. Leistungsfaktor | 5034 | 5034 | 5034 | 0.001 | INT_16 little | Nur über alle Phasen vorhanden | +| Netz: Zähler Netzentnahme | 13036 | 13036 | -- | 0.1 kWh | UINT_32 mixed | | +| Netz: Zähler Einspeisung | 13045 | 13045 | -- | 0.1 kWh | UINT_32 mixed | | +| Meter: AC Wirkleistung Phase A | 5602 | 5602 | 5084 | 1 W | INT_32 mixed | Im Unterschied zu 13009 Vorzeichen korrekt | +| Meter: AC Wirkleistung Phase B | 5604 | 5604 | 5086 | 1 W | INT_32 mixed | Im Unterschied zu 13009 Vorzeichen korrekt | +| Meter: AC Wirkleistung Phase C | 5606 | 5606 | 5088 | 1 W | INT_32 mixed | Im Unterschied zu 13009 Vorzeichen korrekt | +| Meter: AC Spannung Phase A | 5740 | -- | -- | 0.1 V | UINT_16 little | | +| Meter: AC Spannung Phase B | 5741 | -- | -- | 0.1 V | UINT_16 little | | +| Meter: AC Spannung Phase C | 5742 | -- | -- | 0.1 V | UINT_16 little | | +| Meter: AC Strom Phase A | 5743 | -- | -- | 0.01 A | UINT_16 little | Immer positiv, auch bei Einspeisung | +| Meter: AC Strom Phase B | 5744 | -- | -- | 0.01 A | UINT_16 little | Immer positiv, auch bei Einspeisung | +| Meter: AC Strom Phase C | 5745 | -- | -- | 0.01 A | UINT_16 little | Immer positiv, auch bei Einspeisung | diff --git a/packages/modules/devices/sungrow/version.py b/packages/modules/devices/sungrow/version.py index 6e3607756b..539705095e 100644 --- a/packages/modules/devices/sungrow/version.py +++ b/packages/modules/devices/sungrow/version.py @@ -5,3 +5,4 @@ class Version(IntEnum): SH = 0 SG = 1 SG_winet_dongle = 2 + SH_winet_dongle = 3 diff --git a/packages/tools/modbus_finder.py b/packages/tools/modbus_finder.py new file mode 100644 index 0000000000..2b575a8b3a --- /dev/null +++ b/packages/tools/modbus_finder.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python3 +import sys +import time +from typing import Callable + +import pymodbus +from pymodbus.constants import Endian + +from modules.common import modbus + + +def try_read(function: Callable, **kwargs) -> str: + result = "--" + try: + result = str(function(**kwargs)) + except pymodbus.exceptions.ConnectionException: + # Can happen on concurrent access, retry once + result = str(function(**kwargs)) + finally: + return result + + +host = sys.argv[1] +port = int(sys.argv[2]) +slave_id = int(sys.argv[3]) +start = int(sys.argv[4]) +end = int(sys.argv[5]) +func = int(sys.argv[6]) + +print(time.strftime("%Y-%m-%d %H:%M:%S modbus-finder")) +print("Parameter:") +print("Host: " + host) +print("Port: " + str(port)) +print("Modbus ID: " + str(slave_id)) +print("Startadresse: " + str(start)) +print("Endadresse: " + str(end)) +print("Funktion: " + str(func) + "\n") +try: + client = modbus.ModbusTcpClient_(host, port=port) + function: Callable + if func == 4: + function = client.read_input_registers + elif func == 3: + function = client.read_holding_registers + else: + print("unsupported function code: " + str(func)) + exit(1) + + print("Address;INT_16;UINT_16;INT_32;UINT_32") + for address in range(start, end): + resp_INT_16 = try_read(function, address=address, types=modbus.ModbusDataType.INT_16, unit=slave_id) + resp_UINT_16 = try_read(function, address=address, types=modbus.ModbusDataType.UINT_16, unit=slave_id) + resp_INT_32 = try_read(function, address=address, types=modbus.ModbusDataType.INT_32, wordorder=Endian.Little, + unit=slave_id) + resp_UINT_32 = try_read(function, address=address, types=modbus.ModbusDataType.UINT_32, wordorder=Endian.Little, + unit=slave_id) + print(f"{address};{resp_INT_16};{resp_UINT_16};{resp_INT_32};{resp_UINT_32}") +except Exception as e: + print("Exception " + str(e))