From 211af6d0138c71e075d49bb4b1ee1b319bc8a484 Mon Sep 17 00:00:00 2001 From: Guzz-T Date: Tue, 3 Mar 2026 19:30:35 +0100 Subject: [PATCH] Add some fields as they existed in v0.3.14 In version v0.3.14, there were several unknown_fields of the `unknown` data type. These were changed later, both in name and data type. This is now divided into two different fields: the old one as `unknown` and the new one with the current data type. --- luxtronik/cfi/calculations.py | 11 -- luxtronik/datatypes.py | 14 ++ luxtronik/definitions/calculations.py | 82 +++++++++-- luxtronik/definitions/parameters.py | 196 ++++++++++++++++++++++---- tests/test_LuxtronikData.py | 7 +- tests/test_compatibility.py | 2 +- tests/test_datatypes.py | 19 +++ 7 files changed, 277 insertions(+), 54 deletions(-) diff --git a/luxtronik/cfi/calculations.py b/luxtronik/cfi/calculations.py index 62416ee9..752fa29c 100644 --- a/luxtronik/cfi/calculations.py +++ b/luxtronik/cfi/calculations.py @@ -13,7 +13,6 @@ from luxtronik.cfi.constants import CALCULATIONS_FIELD_NAME from luxtronik.cfi.vector import DataVectorConfig -from luxtronik.datatypes import Base LOGGER = logging.getLogger(__name__) @@ -39,13 +38,3 @@ def get_firmware_version(self): def _get_firmware_version(self): """Get the firmware version as string like in previous versions.""" return self.get_firmware_version().strip("\x00") - - def get(self, target): - """Treats certain names specially. For all others, the function of the base class is called.""" - if target == "ID_WEB_SoftStand": - LOGGER.debug("The name 'ID_WEB_SoftStand' is obsolete! Use 'get_firmware_version()' instead.") - entry = Base("ID_WEB_SoftStand") - entry.raw = self._get_firmware_version() - return entry - else: - return super().get(target) diff --git a/luxtronik/datatypes.py b/luxtronik/datatypes.py index 9f66aee6..16c06bc4 100755 --- a/luxtronik/datatypes.py +++ b/luxtronik/datatypes.py @@ -607,6 +607,20 @@ class Count(Base): datatype_class = "count" +class Version(Base): + """Version datatype, converts from and to a Heatpump Version.""" + + datatype_class = "version" + + concatenate_multiple_data_chunks = False + + @classmethod + def from_heatpump(self, value): + if not isinstance(value, list): + return None + return "".join([chr(c) for c in value]).strip("\x00") + + class Character(Base): """Character datatype, converts from and to a Character.""" diff --git a/luxtronik/definitions/calculations.py b/luxtronik/definitions/calculations.py index 4c21e8d0..141c2b44 100644 --- a/luxtronik/definitions/calculations.py +++ b/luxtronik/definitions/calculations.py @@ -41,6 +41,7 @@ Timestamp, Unknown, MajorMinorVersion, + Version, Voltage, ) @@ -50,7 +51,6 @@ CALCULATIONS_DEFAULT_DATA_TYPE: Final = 'INT32' CALCULATIONS_OUTDATED = { - "ID_WEB_SoftStand": "get_firmware_version()" } CALCULATIONS_DEFINITIONS_LIST: Final = [ @@ -864,6 +864,16 @@ "unit": 'enum', "description": '', }, + { + "index": 81, + "count": 10, + "names": ['ID_WEB_SoftStand'], + "type": Version, + "writeable": False, + "datatype": 'UINT32', + "unit": '', + "description": '', + }, { "index": 81, "count": 1, @@ -2374,20 +2384,30 @@ "unit": 'Hz', "description": '', }, + { + "index": 232, + "names": ['Unknown_Calculation_232'], + "type": Unknown, + }, { "index": 232, "count": 1, - "names": ['Vapourisation_Temperature', 'Unknown_Calculation_232'], + "names": ['Vapourisation_Temperature'], "type": Celsius, "writeable": False, "datatype": 'INT32', "unit": '°C/10', "description": '', }, + { + "index": 233, + "names": ['Unknown_Calculation_233'], + "type": Unknown, + }, { "index": 233, "count": 1, - "names": ['Liquefaction_Temperature', 'Unknown_Calculation_233'], + "names": ['Liquefaction_Temperature'], "type": Celsius, "writeable": False, "datatype": 'INT32', @@ -2414,50 +2434,75 @@ "unit": '', "description": '', }, + { + "index": 236, + "names": ['Unknown_Calculation_236'], + "type": Unknown, + }, { "index": 236, "count": 1, - "names": ['ID_WEB_Freq_VD_Soll', 'Unknown_Calculation_236'], + "names": ['ID_WEB_Freq_VD_Soll'], "type": Frequency, "writeable": False, "datatype": 'UINT32', "unit": 'Hz', "description": '', }, + { + "index": 237, + "names": ['Unknown_Calculation_237'], + "type": Unknown, + }, { "index": 237, "count": 1, - "names": ['ID_WEB_Freq_VD_Min', 'Unknown_Calculation_237'], + "names": ['ID_WEB_Freq_VD_Min'], "type": Frequency, "writeable": False, "datatype": 'UINT32', "unit": 'Hz', "description": '', }, + { + "index": 238, + "names": ['Unknown_Calculation_238'], + "type": Unknown, + }, { "index": 238, "count": 1, - "names": ['ID_WEB_Freq_VD_Max', 'Unknown_Calculation_238'], + "names": ['ID_WEB_Freq_VD_Max'], "type": Frequency, "writeable": False, "datatype": 'UINT32', "unit": 'Hz', "description": '', }, + { + "index": 239, + "names": ['Unknown_Calculation_239'], + "type": Unknown, + }, { "index": 239, "count": 1, - "names": ['VBO_Temp_Spread_Soll', 'Unknown_Calculation_239'], + "names": ['VBO_Temp_Spread_Soll'], "type": Kelvin, "writeable": False, "datatype": 'INT32', "unit": 'K/10', "description": '', }, + { + "index": 240, + "names": ['Unknown_Calculation_240'], + "type": Unknown, + }, { "index": 240, "count": 1, - "names": ['VBO_Temp_Spread_Ist', 'Unknown_Calculation_240'], + "names": ['VBO_Temp_Spread_Ist'], "type": Kelvin, "writeable": False, "datatype": 'INT32', @@ -2474,20 +2519,30 @@ "unit": '%', "description": '', }, + { + "index": 242, + "names": ['Unknown_Calculation_242'], + "type": Unknown, + }, { "index": 242, "count": 1, - "names": ['HUP_Temp_Spread_Soll', 'Unknown_Calculation_242'], + "names": ['HUP_Temp_Spread_Soll'], "type": Kelvin, "writeable": False, "datatype": 'INT32', "unit": 'K/10', "description": '', }, + { + "index": 243, + "names": ['Unknown_Calculation_243'], + "type": Unknown, + }, { "index": 243, "count": 1, - "names": ['HUP_Temp_Spread_Ist', 'Unknown_Calculation_243'], + "names": ['HUP_Temp_Spread_Ist'], "type": Kelvin, "writeable": False, "datatype": 'INT32', @@ -2634,10 +2689,15 @@ "unit": 'W', "description": '', }, + { + "index": 258, + "names": ['Unknown_Calculation_258'], + "type": Unknown, + }, { "index": 258, "count": 1, - "names": ['RBE_Version', 'Unknown_Calculation_258'], + "names": ['RBE_Version'], "type": MajorMinorVersion, "writeable": False, "datatype": 'UINT32', diff --git a/luxtronik/definitions/parameters.py b/luxtronik/definitions/parameters.py index 809040a7..f004a8a1 100644 --- a/luxtronik/definitions/parameters.py +++ b/luxtronik/definitions/parameters.py @@ -10917,10 +10917,15 @@ "unit": '', "description": '', }, + { + "index": 1087, + "names": ['Unknown_Parameter_1087'], + "type": Unknown, + }, { "index": 1087, "count": 1, - "names": ['SILENT_MODE', 'Unknown_Parameter_1087'], + "names": ['SILENT_MODE'], "type": OnOffMode, "writeable": False, "datatype": 'UINT32', @@ -10967,220 +10972,330 @@ "unit": '', "description": '', }, + { + "index": 1092, + "names": ['Unknown_Parameter_1092'], + "type": Unknown, + }, { "index": 1092, "count": 1, - "names": ['ID_Einst_SuSilence', 'Unknown_Parameter_1092'], + "names": ['ID_Einst_SuSilence'], "type": TimerProgram, "writeable": False, "datatype": 'UINT32', "unit": 'enum', "description": '', }, + { + "index": 1093, + "names": ['Unknown_Parameter_1093'], + "type": Unknown, + }, { "index": 1093, "count": 1, - "names": ['ID_Einst_SilenceTimer_0', 'Unknown_Parameter_1093'], + "names": ['ID_Einst_SilenceTimer_0'], "type": TimeOfDay2, "writeable": False, "datatype": 'UINT32', "unit": '', "description": '', }, + { + "index": 1094, + "names": ['Unknown_Parameter_1094'], + "type": Unknown, + }, { "index": 1094, "count": 1, - "names": ['ID_Einst_SilenceTimer_1', 'Unknown_Parameter_1094'], + "names": ['ID_Einst_SilenceTimer_1'], "type": TimeOfDay2, "writeable": False, "datatype": 'UINT32', "unit": '', "description": '', }, + { + "index": 1095, + "names": ['Unknown_Parameter_1095'], + "type": Unknown, + }, { "index": 1095, "count": 1, - "names": ['ID_Einst_SilenceTimer_2', 'Unknown_Parameter_1095'], + "names": ['ID_Einst_SilenceTimer_2'], "type": TimeOfDay2, "writeable": False, "datatype": 'UINT32', "unit": '', "description": '', }, + { + "index": 1096, + "names": ['Unknown_Parameter_1096'], + "type": Unknown, + }, { "index": 1096, "count": 1, - "names": ['ID_Einst_SilenceTimer_3', 'Unknown_Parameter_1096'], + "names": ['ID_Einst_SilenceTimer_3'], "type": TimeOfDay2, "writeable": False, "datatype": 'UINT32', "unit": '', "description": '', }, + { + "index": 1097, + "names": ['Unknown_Parameter_1097'], + "type": Unknown, + }, { "index": 1097, "count": 1, - "names": ['ID_Einst_SilenceTimer_4', 'Unknown_Parameter_1097'], + "names": ['ID_Einst_SilenceTimer_4'], "type": TimeOfDay2, "writeable": False, "datatype": 'UINT32', "unit": '', "description": '', }, + { + "index": 1098, + "names": ['Unknown_Parameter_1098'], + "type": Unknown, + }, { "index": 1098, "count": 1, - "names": ['ID_Einst_SilenceTimer_5', 'Unknown_Parameter_1098'], + "names": ['ID_Einst_SilenceTimer_5'], "type": TimeOfDay2, "writeable": False, "datatype": 'UINT32', "unit": '', "description": '', }, + { + "index": 1099, + "names": ['Unknown_Parameter_1099'], + "type": Unknown, + }, { "index": 1099, "count": 1, - "names": ['ID_Einst_SilenceTimer_6', 'Unknown_Parameter_1099'], + "names": ['ID_Einst_SilenceTimer_6'], "type": TimeOfDay2, "writeable": False, "datatype": 'UINT32', "unit": '', "description": '', }, + { + "index": 1100, + "names": ['Unknown_Parameter_1100'], + "type": Unknown, + }, { "index": 1100, "count": 1, - "names": ['ID_Einst_SilenceTimer_7', 'Unknown_Parameter_1100'], + "names": ['ID_Einst_SilenceTimer_7'], "type": TimeOfDay2, "writeable": False, "datatype": 'UINT32', "unit": '', "description": '', }, + { + "index": 1101, + "names": ['Unknown_Parameter_1101'], + "type": Unknown, + }, { "index": 1101, "count": 1, - "names": ['ID_Einst_SilenceTimer_8', 'Unknown_Parameter_1101'], + "names": ['ID_Einst_SilenceTimer_8'], "type": TimeOfDay2, "writeable": False, "datatype": 'UINT32', "unit": '', "description": '', }, + { + "index": 1102, + "names": ['Unknown_Parameter_1102'], + "type": Unknown, + }, { "index": 1102, "count": 1, - "names": ['ID_Einst_SilenceTimer_9', 'Unknown_Parameter_1102'], + "names": ['ID_Einst_SilenceTimer_9'], "type": TimeOfDay2, "writeable": False, "datatype": 'UINT32', "unit": '', "description": '', }, + { + "index": 1103, + "names": ['Unknown_Parameter_1103'], + "type": Unknown, + }, { "index": 1103, "count": 1, - "names": ['ID_Einst_SilenceTimer_10', 'Unknown_Parameter_1103'], + "names": ['ID_Einst_SilenceTimer_10'], "type": TimeOfDay2, "writeable": False, "datatype": 'UINT32', "unit": '', "description": '', }, + { + "index": 1104, + "names": ['Unknown_Parameter_1104'], + "type": Unknown, + }, { "index": 1104, "count": 1, - "names": ['ID_Einst_SilenceTimer_11', 'Unknown_Parameter_1104'], + "names": ['ID_Einst_SilenceTimer_11'], "type": TimeOfDay2, "writeable": False, "datatype": 'UINT32', "unit": '', "description": '', }, + { + "index": 1105, + "names": ['Unknown_Parameter_1105'], + "type": Unknown, + }, { "index": 1105, "count": 1, - "names": ['ID_Einst_SilenceTimer_12', 'Unknown_Parameter_1105'], + "names": ['ID_Einst_SilenceTimer_12'], "type": TimeOfDay2, "writeable": False, "datatype": 'UINT32', "unit": '', "description": '', }, + { + "index": 1106, + "names": ['Unknown_Parameter_1106'], + "type": Unknown, + }, { "index": 1106, "count": 1, - "names": ['ID_Einst_SilenceTimer_13', 'Unknown_Parameter_1106'], + "names": ['ID_Einst_SilenceTimer_13'], "type": TimeOfDay2, "writeable": False, "datatype": 'UINT32', "unit": '', "description": '', }, + { + "index": 1107, + "names": ['Unknown_Parameter_1107'], + "type": Unknown, + }, { "index": 1107, "count": 1, - "names": ['ID_Einst_SilenceTimer_14', 'Unknown_Parameter_1107'], + "names": ['ID_Einst_SilenceTimer_14'], "type": TimeOfDay2, "writeable": False, "datatype": 'UINT32', "unit": '', "description": '', }, + { + "index": 1108, + "names": ['Unknown_Parameter_1108'], + "type": Unknown, + }, { "index": 1108, "count": 1, - "names": ['ID_Einst_SilenceTimer_15', 'Unknown_Parameter_1108'], + "names": ['ID_Einst_SilenceTimer_15'], "type": TimeOfDay2, "writeable": False, "datatype": 'UINT32', "unit": '', "description": '', }, + { + "index": 1109, + "names": ['Unknown_Parameter_1109'], + "type": Unknown, + }, { "index": 1109, "count": 1, - "names": ['ID_Einst_SilenceTimer_16', 'Unknown_Parameter_1109'], + "names": ['ID_Einst_SilenceTimer_16'], "type": TimeOfDay2, "writeable": False, "datatype": 'UINT32', "unit": '', "description": '', }, + { + "index": 1110, + "names": ['Unknown_Parameter_1110'], + "type": Unknown, + }, { "index": 1110, "count": 1, - "names": ['ID_Einst_SilenceTimer_17', 'Unknown_Parameter_1110'], + "names": ['ID_Einst_SilenceTimer_17'], "type": TimeOfDay2, "writeable": False, "datatype": 'UINT32', "unit": '', "description": '', }, + { + "index": 1111, + "names": ['Unknown_Parameter_1111'], + "type": Unknown, + }, { "index": 1111, "count": 1, - "names": ['ID_Einst_SilenceTimer_18', 'Unknown_Parameter_1111'], + "names": ['ID_Einst_SilenceTimer_18'], "type": TimeOfDay2, "writeable": False, "datatype": 'UINT32', "unit": '', "description": '', }, + { + "index": 1112, + "names": ['Unknown_Parameter_1112'], + "type": Unknown, + }, { "index": 1112, "count": 1, - "names": ['ID_Einst_SilenceTimer_19', 'Unknown_Parameter_1112'], + "names": ['ID_Einst_SilenceTimer_19'], "type": TimeOfDay2, "writeable": False, "datatype": 'UINT32', "unit": '', "description": '', }, + { + "index": 1113, + "names": ['Unknown_Parameter_1113'], + "type": Unknown, + }, { "index": 1113, "count": 1, - "names": ['ID_Einst_SilenceTimer_20', 'Unknown_Parameter_1113'], + "names": ['ID_Einst_SilenceTimer_20'], "type": TimeOfDay2, "writeable": False, "datatype": 'UINT32', @@ -11237,10 +11352,15 @@ "unit": '', "description": '', }, + { + "index": 1119, + "names": ['Unknown_Parameter_1119'], + "type": Unknown, + }, { "index": 1119, "count": 1, - "names": ['LAST_DEFROST_TIMESTAMP', 'Unknown_Parameter_1119'], + "names": ['LAST_DEFROST_TIMESTAMP'], "type": Timestamp, "writeable": False, "datatype": 'UINT32', @@ -11407,20 +11527,30 @@ "unit": '', "description": '', }, + { + "index": 1136, + "names": ['Unknown_Parameter_1136'], + "type": Unknown, + }, { "index": 1136, "count": 1, - "names": ['HEAT_ENERGY_INPUT', 'Unknown_Parameter_1136'], + "names": ['HEAT_ENERGY_INPUT'], "type": Energy, "writeable": False, "datatype": 'UINT32', "unit": 'kWh/10', "description": '', }, + { + "index": 1137, + "names": ['Unknown_Parameter_1137'], + "type": Unknown, + }, { "index": 1137, "count": 1, - "names": ['DHW_ENERGY_INPUT', 'Unknown_Parameter_1137'], + "names": ['DHW_ENERGY_INPUT'], "type": Energy, "writeable": False, "datatype": 'UINT32', @@ -11437,10 +11567,15 @@ "unit": '', "description": '', }, + { + "index": 1139, + "names": ['Unknown_Parameter_1139'], + "type": Unknown, + }, { "index": 1139, "count": 1, - "names": ['COOLING_ENERGY_INPUT', 'Unknown_Parameter_1139'], + "names": ['COOLING_ENERGY_INPUT'], "type": Energy, "writeable": False, "datatype": 'UINT32', @@ -11527,10 +11662,15 @@ "unit": '', "description": '', }, + { + "index": 1148, + "names": ['Unknown_Parameter_1148'], + "type": Unknown, + }, { "index": 1148, "count": 1, - "names": ['HEATING_TARGET_TEMP_ROOM_THERMOSTAT', 'Unknown_Parameter_1148'], + "names": ['HEATING_TARGET_TEMP_ROOM_THERMOSTAT'], "type": Celsius, "writeable": True, "datatype": 'INT32', diff --git a/tests/test_LuxtronikData.py b/tests/test_LuxtronikData.py index 39ca2e52..5a1722c9 100644 --- a/tests/test_LuxtronikData.py +++ b/tests/test_LuxtronikData.py @@ -61,13 +61,14 @@ def test_get_firmware_version(self): assert a.get_firmware_version() == "V3.1" # Test of downward compatibility with outdated entry name + a.calculations.get("ID_WEB_SoftStand").raw = [ord("V"), ord("3"), ord("."), ord("1"), 0x00] assert a.calculations.get("ID_WEB_SoftStand").value == "V3.1" @pytest.mark.parametrize("vector, index, names", [ - ("para", 1106, ["ID_Einst_SilenceTimer_13", "Unknown_Parameter_1106"]), - ("para", 1109, ["ID_Einst_SilenceTimer_16", "Unknown_Parameter_1109"]), - ("calc", 232, ["Vapourisation_Temperature", "Unknown_Calculation_232"]), + ("para", 1106, ["ID_Einst_SilenceTimer_13"]), + ("para", 1109, ["ID_Einst_SilenceTimer_16"]), + ("calc", 232, ["Vapourisation_Temperature"]), ("calc", 241, ["HUP_PWM", "Circulation_Pump"]), ("visi", 182, ["ID_Visi_Heizung_Zeitschaltprogramm", "ID_Visi_Heizung_Zeitschlaltprogramm"]), ("visi", 326, ["Unknown_Visibility_326"]), diff --git a/tests/test_compatibility.py b/tests/test_compatibility.py index 2b831523..aa881812 100644 --- a/tests/test_compatibility.py +++ b/tests/test_compatibility.py @@ -1293,6 +1293,7 @@ def test_compatibilities(self): "ID_WEB_Code_WP_akt": 78, "ID_WEB_BIV_Stufe_akt": 79, "ID_WEB_WP_BZ_akt": 80, + "ID_WEB_SoftStand": 81, "ID_WEB_AdresseIP_akt": 91, "ID_WEB_SubNetMask_akt": 92, "ID_WEB_Add_Broadcast": 93, @@ -1494,7 +1495,6 @@ def test_compatibilities(self): "Desired_Room_Temperature": 267, "AC_Power_Input": 268, } - # Note: "ID_WEB_SoftStand" tested in "test_get_firmware_version()" visis = { # Status of 0.3.14: diff --git a/tests/test_datatypes.py b/tests/test_datatypes.py index 81038f7d..ac536c87 100644 --- a/tests/test_datatypes.py +++ b/tests/test_datatypes.py @@ -54,6 +54,7 @@ TimerProgram, TimeOfDay, TimeOfDay2, + Version, ) @@ -936,6 +937,24 @@ def test_init(self): assert a.datatype_unit is None +class TestVersion: + """Test suite for Version datatype""" + + def test_init(self): + """Test cases for initialization""" + + a = Version("ver") + assert a.name == "ver" + assert a.datatype_class == "version" + assert a.datatype_unit is None + + def test_from_heatpump(self): + + assert Version.from_heatpump([3, 1, 4]) == '\x03\x01\x04' + assert Version.from_heatpump(None) is None + assert Version.from_heatpump("a") is None + + class TestCharacter: """Test suite for Character datatype"""