-
Notifications
You must be signed in to change notification settings - Fork 104
fix en- and decoding of environment data descriptions #379
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
41494f9
672ff47
e6d1976
a9a791f
ede0fed
c068384
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,15 +6,17 @@ | |
| from typing_extensions import override | ||
|
|
||
| from .complexdop import ComplexDop | ||
| from .dataobjectproperty import DataObjectProperty | ||
| from .decodestate import DecodeState | ||
| from .dtcdop import DtcDop | ||
| from .encodestate import EncodeState | ||
| from .environmentdata import EnvironmentData | ||
| from .exceptions import odxraise, odxrequire | ||
| from .nameditemlist import NamedItemList | ||
| from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId, OdxLinkRef | ||
| from .odxtypes import ParameterValue, ParameterValueDict | ||
| from .odxtypes import DataType, ParameterValue, ParameterValueDict | ||
| from .parameters.parameter import Parameter | ||
| from .parameters.valueparameter import ValueParameter | ||
| from .snrefcontext import SnRefContext | ||
| from .utils import dataclass_fields_asdict | ||
|
|
||
|
|
@@ -116,40 +118,64 @@ def encode_into_pdu(self, physical_value: Optional[ParameterValue], | |
| """Convert a physical value into bytes and emplace them into a PDU. | ||
| """ | ||
|
|
||
| # retrieve the relevant DTC parameter which must be located in | ||
| # front of the environment data description. | ||
| # retrieve the DTC as a numerical value from the referenced | ||
| # parameter (which must be located somewhere before the | ||
| # parameter using the environment data description) | ||
| if self.param_snref is None: | ||
| odxraise("Specifying the DTC parameter for environment data " | ||
| "descriptions via SNPATHREF is not supported yet") | ||
| return None | ||
|
|
||
| dtc_param: Optional[Parameter] = None | ||
| dtc_dop: Optional[DtcDop] = None | ||
| dtc_param_value: Optional[ParameterValue] = None | ||
| numerical_dtc_value: Optional[ParameterValue] = None | ||
| for prev_param, prev_param_value in reversed(encode_state.journal): | ||
| if prev_param.short_name == self.param_snref: | ||
| dtc_param = prev_param | ||
| prev_dop = getattr(prev_param, "dop", None) | ||
| if not isinstance(prev_dop, DtcDop): | ||
| odxraise(f"The DOP of the parameter referenced by environment data " | ||
| f"descriptions must be a DTC-DOP (is '{type(prev_dop).__name__}')") | ||
| if not isinstance(prev_param, ValueParameter): | ||
| odxraise( | ||
| f"The parameter referenced by environment data descriptions " | ||
| f"must use a VALUE-PARAMETER (encountered {type(prev_param).__name__} " | ||
| f"for reference '{self.param_snref}' of ENV-DATA-DESC '{self.short_name}')") | ||
| return | ||
| dtc_dop = prev_dop | ||
| dtc_param_value = prev_param_value | ||
|
|
||
| prev_dop = prev_param.dop | ||
| if isinstance(prev_dop, DtcDop): | ||
| if prev_dop.diag_coded_type.base_data_type != DataType.A_UINT32: | ||
| odxraise(f"The data type used by the DOP of the parameter referenced " | ||
| f"by environment data descriptions must be A_UINT32 " | ||
| f"(encountered '{prev_dop.diag_coded_type.base_data_type.value}')") | ||
| return | ||
|
|
||
| if prev_param_value is None: | ||
| odxraise() | ||
| return | ||
|
|
||
| numerical_dtc_value = prev_dop.convert_to_numerical_trouble_code( | ||
| prev_param_value) | ||
| elif isinstance(prev_dop, DataObjectProperty): | ||
| if prev_dop.diag_coded_type.base_data_type != DataType.A_UINT32: | ||
| odxraise(f"The data type used by the DOP of the parameter referenced " | ||
| f"by environment data descriptions must be A_UINT32 " | ||
| f"(encountered '{prev_dop.diag_coded_type.base_data_type.value}')") | ||
| return | ||
|
|
||
| if not isinstance(prev_param_value, (int, str)): | ||
| odxraise() | ||
kayoub5 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| return | ||
|
|
||
| numerical_dtc_value = prev_dop.compu_method.convert_physical_to_internal( | ||
| prev_param_value) | ||
| else: | ||
| odxraise(f"The DOP of the parameter referenced " | ||
| f"by environment data descriptions must use a simple DOP or a DTC-DOP " | ||
| f"(encountered '{type(prev_dop).__name__}')") | ||
| return | ||
|
|
||
| break | ||
|
|
||
| if dtc_param is None: | ||
| if numerical_dtc_value is None: | ||
| odxraise("Environment data description parameters are only allowed following " | ||
| "the referenced value parameter.") | ||
| return | ||
|
|
||
| if dtc_param_value is None or dtc_dop is None: | ||
| # this should never happen | ||
| odxraise() | ||
| return | ||
|
|
||
| numerical_dtc = dtc_dop.convert_to_numerical_trouble_code(dtc_param_value) | ||
|
|
||
| # deal with the "all value" environment data. This holds | ||
| # parameters that are common to all DTCs. Be aware that the | ||
| # specification mandates that there is at most one such | ||
|
|
@@ -165,7 +191,7 @@ def encode_into_pdu(self, physical_value: Optional[ParameterValue], | |
| # find the environment data corresponding to the given trouble | ||
| # code | ||
| for env_data in self.env_datas: | ||
| if numerical_dtc in env_data.dtc_values: | ||
| if numerical_dtc_value in env_data.dtc_values: | ||
| tmp = encode_state.allow_unknown_parameters | ||
| encode_state.allow_unknown_parameters = True | ||
| env_data.encode_into_pdu(physical_value, encode_state) | ||
|
|
@@ -177,40 +203,64 @@ def decode_from_pdu(self, decode_state: DecodeState) -> ParameterValue: | |
| """Extract the bytes from a PDU and convert them to a physical value. | ||
| """ | ||
|
|
||
| # retrieve the relevant DTC parameter which must be located in | ||
| # front of the environment data description. | ||
| # retrieve the DTC as a numerical value from the referenced | ||
| # parameter (which must be located somewhere before the | ||
| # parameter using the environment data description) | ||
| if self.param_snref is None: | ||
| odxraise("Specifying the DTC parameter for environment data " | ||
| "descriptions via SNPATHREF is not supported yet") | ||
| return None | ||
|
|
||
| dtc_param: Optional[Parameter] = None | ||
| dtc_dop: Optional[DtcDop] = None | ||
| dtc_param_value: Optional[ParameterValue] = None | ||
| numerical_dtc_value: Optional[ParameterValue] = None | ||
| for prev_param, prev_param_value in reversed(decode_state.journal): | ||
| if prev_param.short_name == self.param_snref: | ||
| dtc_param = prev_param | ||
| prev_dop = getattr(prev_param, "dop", None) | ||
| if not isinstance(prev_dop, DtcDop): | ||
| odxraise(f"The DOP of the parameter referenced by environment data " | ||
| f"descriptions must be a DTC-DOP (is '{type(prev_dop).__name__}')") | ||
| if not isinstance(prev_param, ValueParameter): | ||
| odxraise( | ||
| f"The parameter referenced by environment data descriptions " | ||
| f"must use a VALUE-PARAMETER (encountered {type(prev_param).__name__} " | ||
| f"for reference '{self.param_snref}' of ENV-DATA-DESC '{self.short_name}')") | ||
| return | ||
| dtc_dop = prev_dop | ||
| dtc_param_value = prev_param_value | ||
|
|
||
| prev_dop = prev_param.dop | ||
| if isinstance(prev_dop, DtcDop): | ||
| if prev_dop.diag_coded_type.base_data_type != DataType.A_UINT32: | ||
| odxraise(f"The data type used by the DOP of the parameter referenced " | ||
| f"by environment data descriptions must be A_UINT32 " | ||
| f"(encountered '{prev_dop.diag_coded_type.base_data_type.value}')") | ||
| return | ||
|
|
||
| if prev_param_value is None: | ||
| odxraise() | ||
| return | ||
|
|
||
| numerical_dtc_value = prev_dop.convert_to_numerical_trouble_code( | ||
|
||
| prev_param_value) | ||
| elif isinstance(prev_dop, DataObjectProperty): | ||
| if prev_dop.diag_coded_type.base_data_type != DataType.A_UINT32: | ||
| odxraise(f"The data type used by the DOP of the parameter referenced " | ||
| f"by environment data descriptions must be A_UINT32 " | ||
| f"(encountered '{prev_dop.diag_coded_type.base_data_type.value}')") | ||
| return | ||
|
|
||
| if not isinstance(prev_param_value, (int, str)): | ||
| odxraise() | ||
| return | ||
|
|
||
| numerical_dtc_value = prev_dop.compu_method.convert_physical_to_internal( | ||
| prev_param_value) | ||
| else: | ||
| odxraise(f"The DOP of the parameter referenced " | ||
| f"by environment data descriptions must use a simple DOP or a DTC-DOP " | ||
| f"(encountered '{type(prev_dop).__name__}')") | ||
| return | ||
|
|
||
| break | ||
|
|
||
| if dtc_param is None: | ||
| if numerical_dtc_value is None: | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Check could be moved inside
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the check here is only triggered if no parameter with the specified short name has been found ( |
||
| odxraise("Environment data description parameters are only allowed following " | ||
| "the referenced value parameter.") | ||
| return | ||
|
|
||
| if dtc_param_value is None or dtc_dop is None: | ||
| # this should never happen | ||
| odxraise() | ||
| return | ||
|
|
||
| numerical_dtc = dtc_dop.convert_to_numerical_trouble_code(dtc_param_value) | ||
|
|
||
| result: ParameterValueDict = {} | ||
|
|
||
| # deal with the "all value" environment data. This holds | ||
|
|
@@ -228,7 +278,7 @@ def decode_from_pdu(self, decode_state: DecodeState) -> ParameterValue: | |
| # find the environment data corresponding to the given trouble | ||
| # code | ||
| for env_data in self.env_datas: | ||
| if numerical_dtc in env_data.dtc_values: | ||
| if numerical_dtc_value in env_data.dtc_values: | ||
| tmp = env_data.decode_from_pdu(decode_state) | ||
| if not isinstance(tmp, dict): | ||
| odxraise() | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it could be a constant parameter? no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think so: environment data descriptions are a multiplexer mechanism to attach additional information to a DTC depending on the value of the trouble code (basically this data describes the circumstances under which the DTC was encountered). mandating the key of the multiplexer to be a constant defies the purpose? (haven't checked the spec about this, though..
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if the dtc have only one environment data, then it could be in theory a constant.
the main idea, is that the check you are doing either needs to backed by a specification clause, or to prevent an error for something not supported by the rest of the code.
the check here does not seem to fit any of those conditions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, but then you don't need the multiplexer because you can simply put the parameters of the environment data into the parameters for the response. Anyway, since the spec probably does not explicitly forbid such atrocities, I fixed it: 672ff47 (plus, I found a better solution for the copy-and-paste issue...)