Skip to content

Commit

Permalink
refactor DiagLayer into a class hierarchy
Browse files Browse the repository at this point in the history
Instead of a single class for all types of diagnostic layers, ODX
specifies a hierarchy of types: ECU shared datas, protocols,
functional groups, base variants and ECU variants whereas all but ECU
shared data layers derive from a "hierarchy element" to indicate that
these may be a member of a inheritance hierarchy defined using
`PARENT-REF`s. This patch implements this approach.

Signed-off-by: Andreas Lauser <andreas.lauser@mbition.io>
Signed-off-by: Florian Jost <florian.jost@mbition.io>
  • Loading branch information
andlaus committed Jul 31, 2024
1 parent abf7fad commit 5e33bbb
Show file tree
Hide file tree
Showing 57 changed files with 2,617 additions and 1,278 deletions.
15 changes: 8 additions & 7 deletions examples/mksomersaultmodifiedpdx.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
import odxtools.uds as uds
from examples import somersaultecu
from odxtools.description import Description
from odxtools.diaglayer import DiagLayer
from odxtools.diaglayers.diaglayer import DiagLayer
from odxtools.diaglayers.ecuvariant import EcuVariant
from odxtools.diagservice import DiagService
from odxtools.nameditemlist import NamedItemList
from odxtools.odxlink import OdxLinkId, OdxLinkRef
Expand Down Expand Up @@ -75,7 +76,7 @@ def find_named_object(item_list: List[T], name: str) -> T:
# add a new "somersault_young" variant which can do flic-flacs and
# does not take any instructions
somersault_lazy = dlc.ecu_variants.somersault_lazy
somersault_young_dlr = deepcopy(somersault_lazy.diag_layer_raw)
somersault_young_dlr = deepcopy(somersault_lazy.ecu_variant_raw)
somersault_young_dlr.short_name = "somersault_young"
somersault_young_dlr.odx_id = OdxLinkId("ECU.somersault_young",
somersault_young_dlr.odx_id.doc_fragments)
Expand Down Expand Up @@ -193,18 +194,18 @@ def find_named_object(item_list: List[T], name: str) -> T:

# create a new list of diagnostic communications that does not include
# the "set_operation_params" and "compulsory_program" services
ss_young_diag_comms = [
x for x in somersault_young_dlr.diag_comms
ss_young_diag_comms_raw = [
x for x in somersault_young_dlr.diag_comms_raw
if getattr(x, "short_name", None) not in ("set_operation_params", "compulsory_program")
]

# append the flic-flac service
ss_young_diag_comms.append(flic_flac_service)
ss_young_diag_comms_raw.append(flic_flac_service)

# change the list of the ECU's diag comms
somersault_young_dlr.diag_comms = ss_young_diag_comms
somersault_young_dlr.diag_comms_raw = ss_young_diag_comms_raw

dlc.ecu_variants.append(DiagLayer(diag_layer_raw=somersault_young_dlr))
dlc.ecu_variants.append(EcuVariant(diag_layer_raw=somersault_young_dlr))

# make the database consistent. Note: For just writing to disk this is
# not necessary (but it is useful if the database is going to be used
Expand Down
Binary file modified examples/somersault.pdx
Binary file not shown.
Binary file modified examples/somersault_modified.pdx
Binary file not shown.
134 changes: 90 additions & 44 deletions examples/somersaultecu.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from odxtools.companydocinfo import CompanyDocInfo
from odxtools.companyspecificinfo import CompanySpecificInfo
from odxtools.comparaminstance import ComparamInstance
from odxtools.comparamspec import ComparamSpec
from odxtools.comparamsubset import ComparamSubset
from odxtools.compumethods.compuconst import CompuConst
from odxtools.compumethods.compuinternaltophys import CompuInternalToPhys
Expand All @@ -28,10 +29,14 @@
from odxtools.dataobjectproperty import DataObjectProperty
from odxtools.description import Description
from odxtools.diagdatadictionaryspec import DiagDataDictionarySpec
from odxtools.diaglayer import DiagLayer
from odxtools.diaglayercontainer import DiagLayerContainer
from odxtools.diaglayerraw import DiagLayerRaw
from odxtools.diaglayertype import DiagLayerType
from odxtools.diaglayers.basevariant import BaseVariant
from odxtools.diaglayers.basevariantraw import BaseVariantRaw
from odxtools.diaglayers.diaglayertype import DiagLayerType
from odxtools.diaglayers.ecuvariant import EcuVariant
from odxtools.diaglayers.ecuvariantraw import EcuVariantRaw
from odxtools.diaglayers.protocol import Protocol
from odxtools.diaglayers.protocolraw import ProtocolRaw
from odxtools.diagservice import DiagService
from odxtools.docrevision import DocRevision
from odxtools.exceptions import odxrequire
Expand Down Expand Up @@ -1868,15 +1873,15 @@ 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_comparams = [
somersault_comparam_refs = [
###
# basic parameters
###
# bus speed
ComparamInstance(
spec_ref=OdxLinkRef("ISO_11898_2_DWCAN.CP_Baudrate", cp_dwcan_doc_frags),
value="500000",
protocol_snref="MyProtocol",
protocol_snref="somersault_protocol",
prot_stack_snref=None,
description=None,
),
Expand Down Expand Up @@ -1905,15 +1910,15 @@ class SomersaultSID(IntEnum):
# CP_ECULayerShortName
"Somersault",
],
protocol_snref="MyProtocol",
protocol_snref="somersault_protocol",
prot_stack_snref=None,
description=None,
),
# timeout for responses [us]
ComparamInstance(
spec_ref=OdxLinkRef("ISO_15765_3.CP_RC21CompletionTimeout", cp_iso15765_3_doc_frags),
value="1000000",
protocol_snref="MyProtocol",
protocol_snref="somersault_protocol",
prot_stack_snref=None,
description=None,
),
Expand All @@ -1924,39 +1929,39 @@ class SomersaultSID(IntEnum):
ComparamInstance(
spec_ref=OdxLinkRef("ISO_15765_3.CP_TesterPresentMessage", cp_iso15765_3_doc_frags),
value=f"{tester_present_value.hex()}",
protocol_snref="MyProtocol",
protocol_snref="somersault_protocol",
prot_stack_snref=None,
description=None,
),
# a response is mandatory
ComparamInstance(
spec_ref=OdxLinkRef("ISO_15765_3.CP_TesterPresentReqRsp", cp_iso15765_3_doc_frags),
value="Response expected",
protocol_snref="MyProtocol",
protocol_snref="somersault_protocol",
prot_stack_snref=None,
description=None,
),
# positive response to "tester present"
ComparamInstance(
spec_ref=OdxLinkRef("ISO_15765_3.CP_TesterPresentExpPosResp", cp_iso15765_3_doc_frags),
value=f"{tester_pr_value.hex()}",
protocol_snref="MyProtocol",
protocol_snref="somersault_protocol",
prot_stack_snref=None,
description=None,
),
# negative response to "tester present"
ComparamInstance(
spec_ref=OdxLinkRef("ISO_15765_3.CP_TesterPresentExpNegResp", cp_iso15765_3_doc_frags),
value=f"{tester_nr_value.hex()}",
protocol_snref="MyProtocol",
protocol_snref="somersault_protocol",
prot_stack_snref=None,
description=None,
),
# when a tester present message must be send
ComparamInstance(
spec_ref=OdxLinkRef("ISO_15765_3.CP_TesterPresentSendType", cp_iso15765_3_doc_frags),
value="On idle",
protocol_snref="MyProtocol",
protocol_snref="somersault_protocol",
prot_stack_snref=None,
description=None,
),
Expand All @@ -1965,15 +1970,15 @@ class SomersaultSID(IntEnum):
ComparamInstance(
spec_ref=OdxLinkRef("ISO_15765_3.CP_TesterPresentAddrMode", cp_iso15765_3_doc_frags),
value="Physical",
protocol_snref="MyProtocol",
protocol_snref="somersault_protocol",
prot_stack_snref=None,
description=None,
),
# is a response from the ECU to "tester present" messages expected
ComparamInstance(
spec_ref=OdxLinkRef("ISO_15765_3.CP_TesterPresentReqRsp", cp_iso15765_3_doc_frags),
value="Response expected",
protocol_snref="MyProtocol",
protocol_snref="somersault_protocol",
prot_stack_snref=None,
description=None,
),
Expand All @@ -1984,7 +1989,7 @@ class SomersaultSID(IntEnum):
ComparamInstance(
spec_ref=OdxLinkRef("ISO_15765_2.CP_BlockSize", cp_iso15765_2_doc_frags),
value="4",
protocol_snref="MyProtocol",
protocol_snref="somersault_protocol",
prot_stack_snref=None,
description=None,
),
Expand Down Expand Up @@ -2012,8 +2017,37 @@ class SomersaultSID(IntEnum):
sdgs=[],
)

# diagnostics layer
somersault_diaglayer_raw = DiagLayerRaw(
# diagnostics layer for the protocol
somersault_protocol_raw = ProtocolRaw(
variant_type=DiagLayerType.PROTOCOL,
odx_id=OdxLinkId("somersault.protocol", doc_frags),
short_name="somersault_protocol",
long_name="Somersault protocol info",
description=Description.from_string(
"<p>Protocol information of the somersault ECUs &amp; cetera</p>"),
admin_data=None,
company_datas=NamedItemList(),
functional_classes=NamedItemList(),
diag_data_dictionary_spec=None,
diag_comms_raw=[],
requests=NamedItemList(),
positive_responses=NamedItemList(),
negative_responses=NamedItemList(),
global_negative_responses=NamedItemList(),
import_refs=[],
state_charts=NamedItemList(),
additional_audiences=NamedItemList(),
sdgs=[],
parent_refs=[],
comparam_spec_ref=OdxLinkRef("CPS_ISO_15765_3_on_ISO_15765_2",
[OdxDocFragment("ISO_15765_3_on_ISO_15765_2", "COMPARAM-SPEC")]),
comparam_refs=somersault_comparam_refs,
prot_stack_snref=None,
)
somersault_protocol = Protocol(diag_layer_raw=somersault_protocol_raw)

# diagnostics layer for the base variant
somersault_base_variant_raw = BaseVariantRaw(
variant_type=DiagLayerType.BASE_VARIANT,
odx_id=OdxLinkId("somersault", doc_frags),
short_name="somersault",
Expand All @@ -2023,7 +2057,7 @@ class SomersaultSID(IntEnum):
company_datas=NamedItemList(),
functional_classes=NamedItemList(somersault_functional_classes.values()),
diag_data_dictionary_spec=somersault_diag_data_dictionary_spec,
diag_comms=[*somersault_services.values(), *somersault_single_ecu_jobs.values()],
diag_comms_raw=[*somersault_services.values(), *somersault_single_ecu_jobs.values()],
requests=NamedItemList(somersault_requests.values()),
positive_responses=NamedItemList(somersault_positive_responses.values()),
negative_responses=NamedItemList(somersault_negative_responses.values()),
Expand All @@ -2032,22 +2066,27 @@ class SomersaultSID(IntEnum):
state_charts=NamedItemList(),
additional_audiences=NamedItemList(somersault_additional_audiences.values()),
sdgs=[],
parent_refs=[],
comparams=somersault_comparams,
ecu_variant_patterns=[],
comparam_spec_ref=None,
prot_stack_snref=None,
parent_refs=[
ParentRef(
layer_ref=OdxLinkRef.from_id(somersault_protocol.odx_id),
not_inherited_diag_comms=[],
not_inherited_dops=[],
not_inherited_variables=[],
not_inherited_tables=[],
not_inherited_global_neg_responses=[],
)
],
comparam_refs=[],
diag_variables_raw=[],
variable_groups=NamedItemList(),
dyn_defined_spec=None,
)
somersault_diaglayer = DiagLayer(diag_layer_raw=somersault_diaglayer_raw)
dyn_defined_spec=None)
somersault_base_variant = BaseVariant(diag_layer_raw=somersault_base_variant_raw)

##################
# Lazy variant of Somersault ECU: this one is lazy and cuts corners
##################

somersault_lazy_diaglayer_raw = DiagLayerRaw(
somersault_lazy_ecu_raw = EcuVariantRaw(
variant_type=DiagLayerType.ECU_VARIANT,
odx_id=OdxLinkId("somersault_lazy", doc_frags),
short_name="somersault_lazy",
Expand All @@ -2058,7 +2097,7 @@ class SomersaultSID(IntEnum):
company_datas=NamedItemList(),
functional_classes=NamedItemList(),
diag_data_dictionary_spec=None,
diag_comms=[],
diag_comms_raw=[],
requests=NamedItemList(),
positive_responses=NamedItemList(),
negative_responses=NamedItemList(),
Expand All @@ -2069,8 +2108,9 @@ class SomersaultSID(IntEnum):
sdgs=[],
parent_refs=[
ParentRef(
layer_ref=OdxLinkRef.from_id(somersault_diaglayer.odx_id),
# this variant does not do backflips
layer_ref=OdxLinkRef.from_id(somersault_base_variant.odx_id),
# this variant does not do backflips and does not like
# being told under which conditions it operates.
not_inherited_diag_comms=[
somersault_requests["backward_flips"].short_name,
somersault_requests["set_operation_params"].short_name,
Expand All @@ -2081,15 +2121,13 @@ class SomersaultSID(IntEnum):
not_inherited_global_neg_responses=[],
)
],
comparams=somersault_comparams,
comparam_refs=[],
ecu_variant_patterns=[],
comparam_spec_ref=None,
prot_stack_snref=None,
diag_variables_raw=[],
variable_groups=NamedItemList(),
dyn_defined_spec=None,
)
somersault_lazy_diaglayer = DiagLayer(diag_layer_raw=somersault_lazy_diaglayer_raw)
somersault_lazy_ecu = EcuVariant(diag_layer_raw=somersault_lazy_ecu_raw)

##################
# Assiduous production variant of Somersault ECU: This one works
Expand Down Expand Up @@ -2262,7 +2300,7 @@ class SomersaultSID(IntEnum):
),
}

somersault_assiduous_diaglayer_raw = DiagLayerRaw(
somersault_assiduous_ecu_raw = EcuVariantRaw(
variant_type=DiagLayerType.ECU_VARIANT,
odx_id=OdxLinkId("somersault_assiduous", doc_frags),
short_name="somersault_assiduous",
Expand All @@ -2288,7 +2326,7 @@ class SomersaultSID(IntEnum):
unit_spec=None,
sdgs=[],
),
diag_comms=list(somersault_assiduous_services.values()),
diag_comms_raw=list(somersault_assiduous_services.values()),
requests=NamedItemList(somersault_assiduous_requests.values()),
positive_responses=NamedItemList(somersault_assiduous_positive_responses.values()),
negative_responses=NamedItemList(somersault_assiduous_negative_responses.values()),
Expand All @@ -2299,24 +2337,23 @@ class SomersaultSID(IntEnum):
sdgs=[],
parent_refs=[
ParentRef(
layer_ref=OdxLinkRef.from_id(somersault_diaglayer.odx_id),
layer_ref=OdxLinkRef.from_id(somersault_base_variant.odx_id),
# this variant does everything which the base variant does
# and more
not_inherited_diag_comms=[],
not_inherited_dops=[],
not_inherited_variables=[],
not_inherited_tables=[],
not_inherited_global_neg_responses=[],
)
],
comparams=somersault_comparams,
comparam_refs=somersault_comparam_refs,
ecu_variant_patterns=[],
comparam_spec_ref=None,
prot_stack_snref=None,
diag_variables_raw=[],
variable_groups=NamedItemList(),
dyn_defined_spec=None,
)
somersault_assiduous_diaglayer = DiagLayer(diag_layer_raw=somersault_assiduous_diaglayer_raw)
somersault_assiduous_ecu = EcuVariant(diag_layer_raw=somersault_assiduous_ecu_raw)

##################
# Container with all ECUs
Expand All @@ -2334,10 +2371,10 @@ class SomersaultSID(IntEnum):
somersault_company_datas["suncus"],
somersault_company_datas["acme"],
]),
base_variants=NamedItemList([somersault_diaglayer]),
ecu_variants=NamedItemList([somersault_lazy_diaglayer, somersault_assiduous_diaglayer]),
base_variants=NamedItemList([somersault_base_variant]),
ecu_variants=NamedItemList([somersault_lazy_ecu, somersault_assiduous_ecu]),
ecu_shared_datas=NamedItemList(),
protocols=NamedItemList(),
protocols=NamedItemList([somersault_protocol]),
functional_groups=NamedItemList(),
sdgs=[],
)
Expand All @@ -2350,16 +2387,25 @@ class SomersaultSID(IntEnum):
"ISO_11898_3_DWFTCAN.odx-cs",
"ISO_15765_2.odx-cs",
"ISO_15765_3_CPSS.odx-cs",
"SAE_J2411_SWCAN_CPSS.odx-cs",
):
odx_cs_root = ElementTree.parse(odx_cs_dir / odx_cs_filename).getroot()
subset = odx_cs_root.find("COMPARAM-SUBSET")
if subset is not None:
comparam_subsets.append(ComparamSubset.from_et(subset, []))

comparam_specs = []
for odx_c_filename in ("UDSOnCAN_CPS.odx-c",):
odx_c_root = ElementTree.parse(odx_cs_dir / odx_c_filename).getroot()
subset = odx_c_root.find("COMPARAM-SPEC")
if subset is not None:
comparam_specs.append(ComparamSpec.from_et(subset, []))

# create a database object
database = Database()
database._diag_layer_containers = NamedItemList([somersault_dlc])
database._comparam_subsets = NamedItemList(comparam_subsets)
database._comparam_specs = NamedItemList(comparam_specs)
database.add_auxiliary_file("jobs.py",
BytesIO(b"""
def compulsory_program():
Expand Down
Loading

0 comments on commit 5e33bbb

Please sign in to comment.