From 3024b17a2acfad215da72a274639f6b09739696f Mon Sep 17 00:00:00 2001 From: Guzz-T Date: Wed, 4 Mar 2026 19:00:04 +0100 Subject: [PATCH] Add a successor field to the definitions to inform the user about deprecated fields The warning is only logged during the first field query. --- luxtronik/definitions/__init__.py | 19 +++++++++++++++++- luxtronik/definitions/calculations.py | 10 ++++++++++ luxtronik/definitions/parameters.py | 28 +++++++++++++++++++++++++++ tests/test_definition_list.py | 7 +++++++ tests/test_definitions.py | 3 +++ 5 files changed, 66 insertions(+), 1 deletion(-) diff --git a/luxtronik/definitions/__init__.py b/luxtronik/definitions/__init__.py index 9afa9318..9ab06adf 100644 --- a/luxtronik/definitions/__init__.py +++ b/luxtronik/definitions/__init__.py @@ -36,6 +36,7 @@ class LuxtronikDefinition: "type": Unknown, "writeable": False, "names": [], + "successor": None, "since": "", "until": "", "datatype": "", @@ -79,6 +80,7 @@ def __init__(self, data_dict, type_name, offset): if not names: names = ["_invalid_"] self._names = names + self._successor = data_dict["successor"] self._aliases = [] since = str(data_dict["since"]) self._since = parse_version(since) @@ -183,6 +185,14 @@ def num_bits(self): def names(self): return self._names + @property + def successor(self): + # Clear the successor after first use, + # not to generate a lot of warnings + s = self._successor + self._successor = None + return s + @property def aliases(self): return self._aliases @@ -328,7 +338,14 @@ def get(self, name_or_idx, default=None): """ d = self._get(name_or_idx) if d is None: - LOGGER.debug(f"Definition for '{name_or_idx}' not found", ) + LOGGER.debug(f"Definition for '{name_or_idx}' not found") + else: + # The successor is returned only once for each definition, + # not to generate a lot of warnings + successor = d.successor + if successor is not None: + LOGGER.warning(f"Definition for '{name_or_idx}' is outdated and will " \ + + f"be removed soon! Please use '{successor}' instead.") return d if d is not None else default def _is_hashable(self, x): diff --git a/luxtronik/definitions/calculations.py b/luxtronik/definitions/calculations.py index 141c2b44..c609387e 100644 --- a/luxtronik/definitions/calculations.py +++ b/luxtronik/definitions/calculations.py @@ -2388,6 +2388,7 @@ "index": 232, "names": ['Unknown_Calculation_232'], "type": Unknown, + "successor": 'Vapourisation_Temperature', }, { "index": 232, @@ -2403,6 +2404,7 @@ "index": 233, "names": ['Unknown_Calculation_233'], "type": Unknown, + "successor": 'Liquefaction_Temperature', }, { "index": 233, @@ -2438,6 +2440,7 @@ "index": 236, "names": ['Unknown_Calculation_236'], "type": Unknown, + "successor": 'ID_WEB_Freq_VD_Soll', }, { "index": 236, @@ -2453,6 +2456,7 @@ "index": 237, "names": ['Unknown_Calculation_237'], "type": Unknown, + "successor": 'ID_WEB_Freq_VD_Min', }, { "index": 237, @@ -2468,6 +2472,7 @@ "index": 238, "names": ['Unknown_Calculation_238'], "type": Unknown, + "successor": 'ID_WEB_Freq_VD_Max', }, { "index": 238, @@ -2483,6 +2488,7 @@ "index": 239, "names": ['Unknown_Calculation_239'], "type": Unknown, + "successor": 'VBO_Temp_Spread_Soll', }, { "index": 239, @@ -2498,6 +2504,7 @@ "index": 240, "names": ['Unknown_Calculation_240'], "type": Unknown, + "successor": 'VBO_Temp_Spread_Ist', }, { "index": 240, @@ -2523,6 +2530,7 @@ "index": 242, "names": ['Unknown_Calculation_242'], "type": Unknown, + "successor": 'HUP_Temp_Spread_Soll', }, { "index": 242, @@ -2538,6 +2546,7 @@ "index": 243, "names": ['Unknown_Calculation_243'], "type": Unknown, + "successor": 'HUP_Temp_Spread_Ist', }, { "index": 243, @@ -2693,6 +2702,7 @@ "index": 258, "names": ['Unknown_Calculation_258'], "type": Unknown, + "successor": 'RBE_Version', }, { "index": 258, diff --git a/luxtronik/definitions/parameters.py b/luxtronik/definitions/parameters.py index f004a8a1..2b55a2c3 100644 --- a/luxtronik/definitions/parameters.py +++ b/luxtronik/definitions/parameters.py @@ -10921,6 +10921,7 @@ "index": 1087, "names": ['Unknown_Parameter_1087'], "type": Unknown, + "successor": 'SILENT_MODE', }, { "index": 1087, @@ -10976,6 +10977,7 @@ "index": 1092, "names": ['Unknown_Parameter_1092'], "type": Unknown, + "successor": 'ID_Einst_SuSilence', }, { "index": 1092, @@ -10991,6 +10993,7 @@ "index": 1093, "names": ['Unknown_Parameter_1093'], "type": Unknown, + "successor": 'ID_Einst_SilenceTimer_0', }, { "index": 1093, @@ -11006,6 +11009,7 @@ "index": 1094, "names": ['Unknown_Parameter_1094'], "type": Unknown, + "successor": 'ID_Einst_SilenceTimer_1', }, { "index": 1094, @@ -11021,6 +11025,7 @@ "index": 1095, "names": ['Unknown_Parameter_1095'], "type": Unknown, + "successor": 'ID_Einst_SilenceTimer_2', }, { "index": 1095, @@ -11036,6 +11041,7 @@ "index": 1096, "names": ['Unknown_Parameter_1096'], "type": Unknown, + "successor": 'ID_Einst_SilenceTimer_3', }, { "index": 1096, @@ -11051,6 +11057,7 @@ "index": 1097, "names": ['Unknown_Parameter_1097'], "type": Unknown, + "successor": 'ID_Einst_SilenceTimer_4', }, { "index": 1097, @@ -11066,6 +11073,7 @@ "index": 1098, "names": ['Unknown_Parameter_1098'], "type": Unknown, + "successor": 'ID_Einst_SilenceTimer_5', }, { "index": 1098, @@ -11081,6 +11089,7 @@ "index": 1099, "names": ['Unknown_Parameter_1099'], "type": Unknown, + "successor": 'ID_Einst_SilenceTimer_6', }, { "index": 1099, @@ -11096,6 +11105,7 @@ "index": 1100, "names": ['Unknown_Parameter_1100'], "type": Unknown, + "successor": 'ID_Einst_SilenceTimer_7', }, { "index": 1100, @@ -11111,6 +11121,7 @@ "index": 1101, "names": ['Unknown_Parameter_1101'], "type": Unknown, + "successor": 'ID_Einst_SilenceTimer_8', }, { "index": 1101, @@ -11126,6 +11137,7 @@ "index": 1102, "names": ['Unknown_Parameter_1102'], "type": Unknown, + "successor": 'ID_Einst_SilenceTimer_9', }, { "index": 1102, @@ -11141,6 +11153,7 @@ "index": 1103, "names": ['Unknown_Parameter_1103'], "type": Unknown, + "successor": 'ID_Einst_SilenceTimer_10', }, { "index": 1103, @@ -11156,6 +11169,7 @@ "index": 1104, "names": ['Unknown_Parameter_1104'], "type": Unknown, + "successor": 'ID_Einst_SilenceTimer_11', }, { "index": 1104, @@ -11171,6 +11185,7 @@ "index": 1105, "names": ['Unknown_Parameter_1105'], "type": Unknown, + "successor": 'ID_Einst_SilenceTimer_12', }, { "index": 1105, @@ -11186,6 +11201,7 @@ "index": 1106, "names": ['Unknown_Parameter_1106'], "type": Unknown, + "successor": 'ID_Einst_SilenceTimer_13', }, { "index": 1106, @@ -11201,6 +11217,7 @@ "index": 1107, "names": ['Unknown_Parameter_1107'], "type": Unknown, + "successor": 'ID_Einst_SilenceTimer_14', }, { "index": 1107, @@ -11216,6 +11233,7 @@ "index": 1108, "names": ['Unknown_Parameter_1108'], "type": Unknown, + "successor": 'ID_Einst_SilenceTimer_15', }, { "index": 1108, @@ -11231,6 +11249,7 @@ "index": 1109, "names": ['Unknown_Parameter_1109'], "type": Unknown, + "successor": 'ID_Einst_SilenceTimer_16', }, { "index": 1109, @@ -11246,6 +11265,7 @@ "index": 1110, "names": ['Unknown_Parameter_1110'], "type": Unknown, + "successor": 'ID_Einst_SilenceTimer_17', }, { "index": 1110, @@ -11261,6 +11281,7 @@ "index": 1111, "names": ['Unknown_Parameter_1111'], "type": Unknown, + "successor": 'ID_Einst_SilenceTimer_18', }, { "index": 1111, @@ -11276,6 +11297,7 @@ "index": 1112, "names": ['Unknown_Parameter_1112'], "type": Unknown, + "successor": 'ID_Einst_SilenceTimer_19', }, { "index": 1112, @@ -11291,6 +11313,7 @@ "index": 1113, "names": ['Unknown_Parameter_1113'], "type": Unknown, + "successor": 'ID_Einst_SilenceTimer_20', }, { "index": 1113, @@ -11356,6 +11379,7 @@ "index": 1119, "names": ['Unknown_Parameter_1119'], "type": Unknown, + "successor": 'LAST_DEFROST_TIMESTAMP', }, { "index": 1119, @@ -11531,6 +11555,7 @@ "index": 1136, "names": ['Unknown_Parameter_1136'], "type": Unknown, + "successor": 'HEAT_ENERGY_INPUT', }, { "index": 1136, @@ -11546,6 +11571,7 @@ "index": 1137, "names": ['Unknown_Parameter_1137'], "type": Unknown, + "successor": 'DHW_ENERGY_INPUT', }, { "index": 1137, @@ -11571,6 +11597,7 @@ "index": 1139, "names": ['Unknown_Parameter_1139'], "type": Unknown, + "successor": 'COOLING_ENERGY_INPUT', }, { "index": 1139, @@ -11666,6 +11693,7 @@ "index": 1148, "names": ['Unknown_Parameter_1148'], "type": Unknown, + "successor": 'HEATING_TARGET_TEMP_ROOM_THERMOSTAT', }, { "index": 1148, diff --git a/tests/test_definition_list.py b/tests/test_definition_list.py index a84c7f06..d98e3029 100644 --- a/tests/test_definition_list.py +++ b/tests/test_definition_list.py @@ -13,6 +13,7 @@ KEY_IDX = "index" KEY_COUNT = "count" KEY_NAMES = "names" +KEY_SUCCESSOR = "successor" KEY_TYPE = "type" KEY_WRT = "writeable" KEY_DATATYPE = "datatype" @@ -64,6 +65,12 @@ def test_structure(self): assert isinstance(name, str), f"Entry of {KEY_NAMES} " \ f"must be of type 'int': {definition}" + # successor + if KEY_SUCCESSOR in definition: + if definition[KEY_SUCCESSOR] is not None: + assert isinstance(definition[KEY_SUCCESSOR], str), \ + f"{KEY_SUCCESSOR} must be of type 'str': {definition}" + # field_type if KEY_TYPE in definition: assert issubclass(definition[KEY_TYPE], Base), \ diff --git a/tests/test_definitions.py b/tests/test_definitions.py index 43a16f22..321a021e 100644 --- a/tests/test_definitions.py +++ b/tests/test_definitions.py @@ -17,6 +17,7 @@ class TestDefinition: 'type': Base, 'writeable': True, 'names': ['test1', 'test2'], + 'successor': 'abcd', 'datatype': 'INT16', 'since': '1.1', 'until': '3.16.7', @@ -36,6 +37,8 @@ def test_init(self): assert definition.writeable == self.TEST_DATA['writeable'] assert definition.names == names assert definition.name == names[0] + assert definition.successor == 'abcd' + assert definition.successor is None assert definition.data_type == 'INT16' assert definition.valid assert definition