Skip to content

Commit

Permalink
Merge pull request mercedes-benz#233 from andlaus/refactor_comparam_c…
Browse files Browse the repository at this point in the history
…lasses

refactor the comparam classes
  • Loading branch information
andlaus authored Nov 2, 2023
2 parents 13d8fde + 968665c commit aafcc89
Show file tree
Hide file tree
Showing 19 changed files with 240 additions and 236 deletions.
70 changes: 35 additions & 35 deletions examples/somersaultecu.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@
from odxtools.additionalaudience import AdditionalAudience
from odxtools.admindata import AdminData
from odxtools.audience import Audience
from odxtools.communicationparameterref import CommunicationParameterRef
from odxtools.companydata import CompanyData
from odxtools.companydocinfo import CompanyDocInfo
from odxtools.companyspecificinfo import CompanySpecificInfo
from odxtools.comparaminstance import ComparamInstance
from odxtools.comparamsubset import ComparamSubset
from odxtools.compumethods.compumethod import CompuMethod
from odxtools.compumethods.compuscale import CompuScale
Expand Down Expand Up @@ -1580,7 +1580,7 @@ class SomersaultSID(IntEnum):
is_mandatory_raw=None,
is_executable_raw=None,
is_final_raw=None,
comparam_refs=NamedItemList[CommunicationParameterRef](),
comparam_refs=NamedItemList[ComparamInstance](),
is_cyclic_raw=None,
is_multiple_raw=None,
addressing_raw=None,
Expand Down Expand Up @@ -1614,7 +1614,7 @@ class SomersaultSID(IntEnum):
is_mandatory_raw=None,
is_executable_raw=None,
is_final_raw=None,
comparam_refs=NamedItemList[CommunicationParameterRef](),
comparam_refs=NamedItemList[ComparamInstance](),
is_cyclic_raw=None,
is_multiple_raw=None,
addressing_raw=None,
Expand Down Expand Up @@ -1648,7 +1648,7 @@ class SomersaultSID(IntEnum):
is_mandatory_raw=None,
is_executable_raw=None,
is_final_raw=None,
comparam_refs=NamedItemList[CommunicationParameterRef](),
comparam_refs=NamedItemList[ComparamInstance](),
is_cyclic_raw=None,
is_multiple_raw=None,
addressing_raw=None,
Expand Down Expand Up @@ -1691,7 +1691,7 @@ class SomersaultSID(IntEnum):
is_mandatory_raw=None,
is_executable_raw=None,
is_final_raw=None,
comparam_refs=NamedItemList[CommunicationParameterRef](),
comparam_refs=NamedItemList[ComparamInstance](),
is_cyclic_raw=None,
is_multiple_raw=None,
addressing_raw=None,
Expand Down Expand Up @@ -1723,7 +1723,7 @@ class SomersaultSID(IntEnum):
is_mandatory_raw=None,
is_executable_raw=None,
is_final_raw=None,
comparam_refs=NamedItemList[CommunicationParameterRef](),
comparam_refs=NamedItemList[ComparamInstance](),
is_cyclic_raw=None,
is_multiple_raw=None,
addressing_raw=None,
Expand Down Expand Up @@ -1774,7 +1774,7 @@ class SomersaultSID(IntEnum):
is_mandatory_raw=None,
is_executable_raw=None,
is_final_raw=None,
comparam_refs=NamedItemList[CommunicationParameterRef](),
comparam_refs=NamedItemList[ComparamInstance](),
is_cyclic_raw=None,
is_multiple_raw=None,
addressing_raw=None,
Expand Down Expand Up @@ -1819,7 +1819,7 @@ class SomersaultSID(IntEnum):
is_mandatory_raw=None,
is_executable_raw=None,
is_final_raw=None,
comparam_refs=NamedItemList[CommunicationParameterRef](),
comparam_refs=NamedItemList[ComparamInstance](),
is_cyclic_raw=None,
is_multiple_raw=None,
addressing_raw=None,
Expand Down Expand Up @@ -1890,21 +1890,21 @@ class SomersaultSID(IntEnum):
tester_present_value = somersault_requests["tester_present"].encode()
tester_pr_value = somersault_positive_responses["tester_ok"].encode()
tester_nr_value = somersault_negative_responses["tester_nok"].encode()
somersault_communication_parameters = [
somersault_comparams = [
###
# basic parameters
###
# bus speed
CommunicationParameterRef(
id_ref=OdxLinkRef("ISO_11898_2_DWCAN.CP_Baudrate", cp_dwcan_doc_frags),
ComparamInstance(
spec_ref=OdxLinkRef("ISO_11898_2_DWCAN.CP_Baudrate", cp_dwcan_doc_frags),
value="500000",
protocol_snref="MyProtocol",
prot_stack_snref=None,
description=None,
),
# parameters of the CAN diagnostics frames
CommunicationParameterRef(
id_ref=OdxLinkRef("ISO_15765_2.CP_UniqueRespIdTable", cp_iso15765_2_doc_frags),
ComparamInstance(
spec_ref=OdxLinkRef("ISO_15765_2.CP_UniqueRespIdTable", cp_iso15765_2_doc_frags),
value=[
# CP_CanPhysReqFormat
"normal segmented 11-bit transmit with FC",
Expand Down Expand Up @@ -1932,8 +1932,8 @@ class SomersaultSID(IntEnum):
description=None,
),
# timeout for responses [us]
CommunicationParameterRef(
id_ref=OdxLinkRef("ISO_15765_3.CP_RC21CompletionTimeout", cp_iso15765_3_doc_frags),
ComparamInstance(
spec_ref=OdxLinkRef("ISO_15765_3.CP_RC21CompletionTimeout", cp_iso15765_3_doc_frags),
value="1000000",
protocol_snref="MyProtocol",
prot_stack_snref=None,
Expand All @@ -1943,57 +1943,57 @@ class SomersaultSID(IntEnum):
# "tester present" message handling
###
# expected "tester present" message
CommunicationParameterRef(
id_ref=OdxLinkRef("ISO_15765_3.CP_TesterPresentMessage", cp_iso15765_3_doc_frags),
ComparamInstance(
spec_ref=OdxLinkRef("ISO_15765_3.CP_TesterPresentMessage", cp_iso15765_3_doc_frags),
value=f"{tester_present_value.hex()}",
protocol_snref="MyProtocol",
prot_stack_snref=None,
description=None,
),
# a response is mandatory
CommunicationParameterRef(
id_ref=OdxLinkRef("ISO_15765_3.CP_TesterPresentReqRsp", cp_iso15765_3_doc_frags),
ComparamInstance(
spec_ref=OdxLinkRef("ISO_15765_3.CP_TesterPresentReqRsp", cp_iso15765_3_doc_frags),
value="Response expected",
protocol_snref="MyProtocol",
prot_stack_snref=None,
description=None,
),
# positive response to "tester present"
CommunicationParameterRef(
id_ref=OdxLinkRef("ISO_15765_3.CP_TesterPresentExpPosResp", cp_iso15765_3_doc_frags),
ComparamInstance(
spec_ref=OdxLinkRef("ISO_15765_3.CP_TesterPresentExpPosResp", cp_iso15765_3_doc_frags),
value=f"{tester_pr_value.hex()}",
protocol_snref="MyProtocol",
prot_stack_snref=None,
description=None,
),
# negative response to "tester present"
CommunicationParameterRef(
id_ref=OdxLinkRef("ISO_15765_3.CP_TesterPresentExpNegResp", cp_iso15765_3_doc_frags),
ComparamInstance(
spec_ref=OdxLinkRef("ISO_15765_3.CP_TesterPresentExpNegResp", cp_iso15765_3_doc_frags),
value=f"{tester_nr_value.hex()}",
protocol_snref="MyProtocol",
prot_stack_snref=None,
description=None,
),
# when a tester present message must be send
CommunicationParameterRef(
id_ref=OdxLinkRef("ISO_15765_3.CP_TesterPresentSendType", cp_iso15765_3_doc_frags),
ComparamInstance(
spec_ref=OdxLinkRef("ISO_15765_3.CP_TesterPresentSendType", cp_iso15765_3_doc_frags),
value="On idle",
protocol_snref="MyProtocol",
prot_stack_snref=None,
description=None,
),
# "tester present" messages are send directly to the CAN IDs
# (i.e., they are not embedded in the ISO-TP telegram?)
CommunicationParameterRef(
id_ref=OdxLinkRef("ISO_15765_3.CP_TesterPresentAddrMode", cp_iso15765_3_doc_frags),
ComparamInstance(
spec_ref=OdxLinkRef("ISO_15765_3.CP_TesterPresentAddrMode", cp_iso15765_3_doc_frags),
value="Physical",
protocol_snref="MyProtocol",
prot_stack_snref=None,
description=None,
),
# is a response from the ECU to "tester present" messages expected
CommunicationParameterRef(
id_ref=OdxLinkRef("ISO_15765_3.CP_TesterPresentReqRsp", cp_iso15765_3_doc_frags),
ComparamInstance(
spec_ref=OdxLinkRef("ISO_15765_3.CP_TesterPresentReqRsp", cp_iso15765_3_doc_frags),
value="Response expected",
protocol_snref="MyProtocol",
prot_stack_snref=None,
Expand All @@ -2003,8 +2003,8 @@ class SomersaultSID(IntEnum):
# ISO-TP parameters:
###
# maximum number of frames between flow control ACKs
CommunicationParameterRef(
id_ref=OdxLinkRef("ISO_15765_2.CP_BlockSize", cp_iso15765_2_doc_frags),
ComparamInstance(
spec_ref=OdxLinkRef("ISO_15765_2.CP_BlockSize", cp_iso15765_2_doc_frags),
value="4",
protocol_snref="MyProtocol",
prot_stack_snref=None,
Expand Down Expand Up @@ -2052,7 +2052,7 @@ class SomersaultSID(IntEnum):
additional_audiences=NamedItemList(somersault_additional_audiences.values()),
sdgs=[],
parent_refs=[],
communication_parameters=somersault_communication_parameters,
comparams=somersault_comparams,
ecu_variant_patterns=[],
)
somersault_diaglayer = DiagLayer(diag_layer_raw=somersault_diaglayer_raw)
Expand Down Expand Up @@ -2094,7 +2094,7 @@ class SomersaultSID(IntEnum):
not_inherited_global_neg_responses=[],
)
],
communication_parameters=somersault_communication_parameters,
comparams=somersault_comparams,
ecu_variant_patterns=[],
)
somersault_lazy_diaglayer = DiagLayer(diag_layer_raw=somersault_lazy_diaglayer_raw)
Expand Down Expand Up @@ -2250,7 +2250,7 @@ class SomersaultSID(IntEnum):
neg_response_refs=[
OdxLinkRef.from_id(somersault_assiduous_negative_responses["fell_over"].odx_id),
],
comparam_refs=NamedItemList[CommunicationParameterRef](),
comparam_refs=NamedItemList[ComparamInstance](),
is_cyclic_raw=None,
is_multiple_raw=None,
addressing_raw=None,
Expand Down Expand Up @@ -2312,7 +2312,7 @@ class SomersaultSID(IntEnum):
not_inherited_global_neg_responses=[],
)
],
communication_parameters=somersault_communication_parameters,
comparams=somersault_comparams,
ecu_variant_patterns=[],
)
somersault_assiduous_diaglayer = DiagLayer(diag_layer_raw=somersault_assiduous_diaglayer_raw)
Expand Down
33 changes: 19 additions & 14 deletions odxtools/basecomparam.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from .element import IdentifiableElement
from .exceptions import odxraise, odxrequire
from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId
from .utils import create_description_from_et
from .utils import dataclass_fields_asdict

if TYPE_CHECKING:
from .diaglayer import DiagLayer
Expand Down Expand Up @@ -35,32 +35,37 @@ class BaseComparam(IdentifiableElement):
cpusage: Optional[Usage]
display_level: Optional[int]

def __init_from_et__(self, et_element: ElementTree.Element,
doc_frags: List[OdxDocFragment]) -> None:
self.odx_id = odxrequire(OdxLinkId.from_et(et_element, doc_frags))
self.short_name = odxrequire(et_element.findtext("SHORT-NAME"))
self.long_name = et_element.findtext("LONG-NAME")
self.description = create_description_from_et(et_element.find("DESC"))
self.param_class = odxrequire(et_element.attrib.get("PARAM-CLASS"))
@staticmethod
def from_et(et_element: ElementTree.Element, doc_frags: List[OdxDocFragment]) -> "BaseComparam":
kwargs = dataclass_fields_asdict(IdentifiableElement.from_et(et_element, doc_frags))

param_class = odxrequire(et_element.attrib.get("PARAM-CLASS"))

cptype_str = odxrequire(et_element.attrib.get("CPTYPE"))
try:
self.cptype = StandardizationLevel(cptype_str)
cptype = StandardizationLevel(cptype_str)
except ValueError:
self.cptype = cast(StandardizationLevel, None)
cptype = cast(StandardizationLevel, None)
odxraise(f"Encountered unknown CPTYPE '{cptype_str}'")

dl = et_element.attrib.get("DISPLAY_LEVEL")
display_level = None if dl is None else int(dl)

# Required in ODX 2.2, missing in ODX 2.0
cpusage_str = et_element.attrib.get("CPUSAGE")
if cpusage_str is not None:
try:
self.cpusage = Usage(cpusage_str)
cpusage = Usage(cpusage_str)
except ValueError:
self.cpusage = None
cpusage = None
odxraise(f"Encountered unknown CPUSAGE '{cpusage_str}'")

dl = et_element.attrib.get("DISPLAY_LEVEL")
self.display_level = None if dl is None else int(dl)
return BaseComparam(
param_class=param_class,
cptype=cptype,
display_level=display_level,
cpusage=cpusage,
**kwargs)

def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
return {self.odx_id: self}
Expand Down
12 changes: 6 additions & 6 deletions odxtools/cli/list.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def print_summary(
print_services: bool = False,
print_dops: bool = False,
print_params: bool = False,
print_com_params: bool = False,
print_comparams: bool = False,
print_pre_condition_states: bool = False,
print_state_transitions: bool = False,
print_audiences: bool = False,
Expand All @@ -41,11 +41,11 @@ def print_summary(
all_services: List[DiagComm] = sorted(dl.services, key=lambda x: x.short_name)

data_object_properties = dl.diag_data_dictionary_spec.data_object_props
com_params = dl.communication_parameters
comparams = dl.comparams

print(f"{dl.variant_type} '{dl.short_name}'")
print(
f" num services: {len(all_services)}, num DOPs: {len(data_object_properties)}, num communication parameters: {len(com_params)}."
f" num services: {len(all_services)}, num DOPs: {len(data_object_properties)}, num communication parameters: {len(comparams)}."
)

for proto in dl.protocols:
Expand Down Expand Up @@ -89,11 +89,11 @@ def print_summary(
data_object_properties, key=lambda x: (type(x).__name__, x.short_name)):
print(" " + str(dop).replace("\n", "\n "))

if print_com_params and len(com_params) > 0:
if print_comparams and len(comparams) > 0:
print(
f"The communication parameters of the {dl.variant_type.value} '{dl.short_name}' are: "
)
for com_param in com_params:
for com_param in comparams:
print(f" {com_param.short_name}: {com_param.value}")


Expand Down Expand Up @@ -196,7 +196,7 @@ def service_filter(s: DiagComm) -> bool:
print_dops=args.all or args.dops,
variants=None if variants == "all" else variants,
print_params=args.all or args.params,
print_com_params=args.all,
print_comparams=args.all,
print_pre_condition_states=args.all,
print_state_transitions=args.all,
print_audiences=args.all,
Expand Down
31 changes: 8 additions & 23 deletions odxtools/comparam.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
# SPDX-License-Identifier: MIT
from dataclasses import dataclass
from typing import TYPE_CHECKING, Any, Dict, List, Optional
from typing import TYPE_CHECKING, Any, Dict, List
from xml.etree import ElementTree

from .basecomparam import BaseComparam
from .dataobjectproperty import DataObjectProperty
from .exceptions import odxraise, odxrequire
from .exceptions import odxrequire
from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId, OdxLinkRef
from .utils import dataclass_fields_asdict

if TYPE_CHECKING:
from .diaglayer import DiagLayer
Expand All @@ -15,30 +16,16 @@
@dataclass
class Comparam(BaseComparam):
dop_ref: OdxLinkRef
physical_default_value: Optional[str]
physical_default_value: str

@staticmethod
def from_et(et_element: ElementTree.Element, doc_frags: List[OdxDocFragment]) -> "Comparam":
# create an "empty" Comparam object without calling the
# "official" constructor. We need to do this because we need
# all data attributes of the class to call the constructor,
# including those which are supposed to be handled by the base
# class (i.e., ComparamBase)
result = Comparam.__new__(Comparam)

# initialize the new "empty" object from the ElementTree
result.__init_from_et__(et_element, doc_frags)

return result

def __init_from_et__(self, et_element: ElementTree.Element,
doc_frags: List[OdxDocFragment]) -> None:
super().__init_from_et__(et_element, doc_frags)
kwargs = dataclass_fields_asdict(BaseComparam.from_et(et_element, doc_frags))

dop_ref = odxrequire(OdxLinkRef.from_et(et_element.find("DATA-OBJECT-PROP-REF"), doc_frags))
physical_default_value = odxrequire(et_element.findtext("PHYSICAL-DEFAULT-VALUE"))

self.dop_ref = dop_ref
self.physical_default_value = et_element.findtext("PHYSICAL-DEFAULT-VALUE")
return Comparam(dop_ref=dop_ref, physical_default_value=physical_default_value, **kwargs)

@property
def dop(self) -> DataObjectProperty:
Expand All @@ -52,9 +39,7 @@ def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
"""Resolves the reference to the dop"""
super()._resolve_odxlinks(odxlinks)

self._dop = odxlinks.resolve(self.dop_ref)
if not isinstance(self._dop, DataObjectProperty):
odxraise()
self._dop = odxlinks.resolve(self.dop_ref, DataObjectProperty)

def _resolve_snrefs(self, diag_layer: "DiagLayer") -> None:
super()._resolve_snrefs(diag_layer)
Loading

0 comments on commit aafcc89

Please sign in to comment.