From 05957b99daa0cd86879c3e34586dba97fba45671 Mon Sep 17 00:00:00 2001 From: Andreas Lauser Date: Tue, 20 Feb 2024 10:39:43 +0100 Subject: [PATCH] fix encoding of DTCs also, add a unit test to prevent this from regressing in the future. Signed-off-by: Andreas Lauser Signed-off-by: Michael Hahn --- odxtools/dtcdop.py | 10 +++++++--- odxtools/parameters/physicalconstantparameter.py | 8 ++------ odxtools/parameters/valueparameter.py | 4 +++- tests/test_decoding.py | 15 ++++++++++----- 4 files changed, 22 insertions(+), 15 deletions(-) diff --git a/odxtools/dtcdop.py b/odxtools/dtcdop.py index 39bca96a..979be3aa 100644 --- a/odxtools/dtcdop.py +++ b/odxtools/dtcdop.py @@ -137,13 +137,17 @@ def convert_physical_to_bytes(self, physical_value: ParameterValue, encode_state trouble_code = physical_value elif isinstance(physical_value, str): # assume that physical value is the short_name - dtc = next(filter(lambda dtc: dtc.short_name == physical_value, self.dtcs)) - trouble_code = dtc.trouble_code + dtcs = [dtc for dtc in self.dtcs if dtc.short_name == physical_value] + odxassert(len(dtcs) == 1) + trouble_code = dtcs[0].trouble_code else: raise EncodeError(f"The DTC-DOP {self.short_name} expected a" f" DiagnosticTroubleCode but got {physical_value!r}.") - return super().convert_physical_to_bytes(trouble_code, encode_state, bit_position) + internal_trouble_code = self.compu_method.convert_physical_to_internal(trouble_code) + + return self.diag_coded_type.convert_internal_to_bytes( + internal_trouble_code, encode_state=encode_state, bit_position=bit_position) def _build_odxlinks(self) -> Dict[OdxLinkId, Any]: odxlinks = super()._build_odxlinks() diff --git a/odxtools/parameters/physicalconstantparameter.py b/odxtools/parameters/physicalconstantparameter.py index e54184ad..6a5387b3 100644 --- a/odxtools/parameters/physicalconstantparameter.py +++ b/odxtools/parameters/physicalconstantparameter.py @@ -1,5 +1,4 @@ # SPDX-License-Identifier: MIT -import warnings from dataclasses import dataclass from typing import TYPE_CHECKING, Any, Dict @@ -70,13 +69,10 @@ def decode_from_pdu(self, decode_state: DecodeState) -> ParameterValue: # Check if decoded value matches expected value if phys_val != self.physical_constant_value: - warnings.warn( + odxraise( f"Physical constant parameter does not match! " f"The parameter {self.short_name} expected physical value " f"{self.physical_constant_value!r} but got {phys_val!r} " f"at byte position {decode_state.cursor_byte_position} " - f"in coded message {decode_state.coded_message.hex()}.", - DecodeError, - stacklevel=1, - ) + f"in coded message {decode_state.coded_message.hex()}.", DecodeError) return phys_val diff --git a/odxtools/parameters/valueparameter.py b/odxtools/parameters/valueparameter.py index 8c0fad88..ecfb7196 100644 --- a/odxtools/parameters/valueparameter.py +++ b/odxtools/parameters/valueparameter.py @@ -18,6 +18,9 @@ class ValueParameter(ParameterWithDOP): physical_default_value_raw: Optional[str] + def __post_init__(self) -> None: + self._physical_default_value: Optional[AtomicOdxType] = None + @property def parameter_type(self) -> ParameterType: return "VALUE" @@ -31,7 +34,6 @@ def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None: def _resolve_snrefs(self, diag_layer: "DiagLayer") -> None: super()._resolve_snrefs(diag_layer) - self._physical_default_value: Optional[AtomicOdxType] = None if self.physical_default_value_raw is not None: dop = odxrequire(self.dop) if not isinstance(dop, DataObjectProperty): diff --git a/tests/test_decoding.py b/tests/test_decoding.py index f3783905..62df2ace 100644 --- a/tests/test_decoding.py +++ b/tests/test_decoding.py @@ -21,7 +21,7 @@ from odxtools.minmaxlengthtype import MinMaxLengthType from odxtools.nameditemlist import NamedItemList from odxtools.odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId, OdxLinkRef -from odxtools.odxtypes import DataType +from odxtools.odxtypes import DataType, ParameterValueDict from odxtools.parameters.codedconstparameter import CodedConstParameter from odxtools.parameters.matchingrequestparameter import MatchingRequestParameter from odxtools.parameters.physicalconstantparameter import PhysicalConstantParameter @@ -1478,7 +1478,7 @@ def test_decode_response(self) -> None: self.assertEqual(expected_message.coding_object, decoded_message.coding_object) self.assertEqual(expected_message.param_dict, decoded_message.param_dict) - def test_decode_dtc(self) -> None: + def test_code_dtc(self) -> None: odxlinks = OdxLinkDatabase() diag_coded_type = StandardLengthType( base_data_type=DataType.A_UINT32, @@ -1570,9 +1570,14 @@ def test_decode_dtc(self) -> None: dop._resolve_odxlinks(odxlinks) pos_response._resolve_odxlinks(odxlinks) - coded_message = bytes([0x12, 0x34]) - decoded_param_dict = pos_response.decode(coded_message) - self.assertEqual(decoded_param_dict["DTC_Param"], dtc1) + expected_coded_message = bytes([0x12, 0x34]) + expected_param_dict: ParameterValueDict = {"SID": 0x12, "DTC_Param": dtc1} + + actual_param_dict = pos_response.decode(expected_coded_message) + self.assertEqual(actual_param_dict, expected_param_dict) + + actual_coded_message = pos_response.encode(coded_request=None, **expected_param_dict) + self.assertEqual(actual_coded_message, expected_coded_message) class TestDecodingAndEncoding(unittest.TestCase):