Skip to content

Commit

Permalink
Merge pull request #326 from andlaus/diag_layer_hierarchy
Browse files Browse the repository at this point in the history
refactor `DiagLayer` into a class hierarchy
  • Loading branch information
andlaus authored Aug 12, 2024
2 parents 9af7857 + bbd05fd commit 61943f0
Show file tree
Hide file tree
Showing 51 changed files with 2,505 additions and 1,196 deletions.
7 changes: 4 additions & 3 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 @@ -204,7 +205,7 @@ def find_named_object(item_list: List[T], name: str) -> T:
# change the list of the ECU's 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.
46 changes: 21 additions & 25 deletions examples/somersaultecu.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,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 @@ -2014,7 +2018,7 @@ class SomersaultSID(IntEnum):
)

# diagnostics layer for the protocol
somersault_protocol_raw = DiagLayerRaw(
somersault_protocol_raw = ProtocolRaw(
variant_type=DiagLayerType.PROTOCOL,
odx_id=OdxLinkId("somersault.protocol", doc_frags),
short_name="somersault_protocol",
Expand All @@ -2039,14 +2043,11 @@ class SomersaultSID(IntEnum):
[OdxDocFragment("ISO_15765_3_on_ISO_15765_2", "COMPARAM-SPEC")]),
comparam_refs=somersault_comparam_refs,
prot_stack_snref=None,
ecu_variant_patterns=[],
diag_variables_raw=[],
variable_groups=NamedItemList(),
dyn_defined_spec=None)
somersault_protocol = DiagLayer(diag_layer_raw=somersault_protocol_raw)
)
somersault_protocol = Protocol(diag_layer_raw=somersault_protocol_raw)

# diagnostics layer for the base variant
somersault_base_variant_raw = DiagLayerRaw(
somersault_base_variant_raw = BaseVariantRaw(
variant_type=DiagLayerType.BASE_VARIANT,
odx_id=OdxLinkId("somersault", doc_frags),
short_name="somersault",
Expand Down Expand Up @@ -2076,19 +2077,16 @@ class SomersaultSID(IntEnum):
)
],
comparam_refs=[],
ecu_variant_patterns=[],
comparam_spec_ref=None,
prot_stack_snref=None,
diag_variables_raw=[],
variable_groups=NamedItemList(),
dyn_defined_spec=None)
somersault_base_variant = DiagLayer(diag_layer_raw=somersault_base_variant_raw)
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 @@ -2111,7 +2109,8 @@ class SomersaultSID(IntEnum):
parent_refs=[
ParentRef(
layer_ref=OdxLinkRef.from_id(somersault_base_variant.odx_id),
# this variant does not do backflips
# 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 @@ -2122,15 +2121,13 @@ class SomersaultSID(IntEnum):
not_inherited_global_neg_responses=[],
)
],
comparam_refs=somersault_comparam_refs,
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 @@ -2303,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 Down Expand Up @@ -2342,6 +2339,7 @@ class SomersaultSID(IntEnum):
ParentRef(
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=[],
Expand All @@ -2351,13 +2349,11 @@ class SomersaultSID(IntEnum):
],
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 @@ -2376,7 +2372,7 @@ class SomersaultSID(IntEnum):
somersault_company_datas["acme"],
]),
base_variants=NamedItemList([somersault_base_variant]),
ecu_variants=NamedItemList([somersault_lazy_diaglayer, somersault_assiduous_diaglayer]),
ecu_variants=NamedItemList([somersault_lazy_ecu, somersault_assiduous_ecu]),
ecu_shared_datas=NamedItemList(),
protocols=NamedItemList([somersault_protocol]),
functional_groups=NamedItemList(),
Expand Down
7 changes: 4 additions & 3 deletions odxtools/cli/_print_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from tabulate import tabulate # TODO: switch to rich tables

from ..description import Description
from ..diaglayer import DiagLayer
from ..diaglayers.diaglayer import DiagLayer
from ..diagservice import DiagService
from ..parameters.codedconstparameter import CodedConstParameter
from ..parameters.nrcconstparameter import NrcConstParameter
Expand Down Expand Up @@ -243,8 +243,9 @@ def print_dl_metrics(variants: List[DiagLayer], print_fn: Callable[..., Any] = p
name.append(variant.short_name)
type.append(variant.variant_type.value)
num_services.append(len(all_services))
num_dops.append(len(variant.diag_data_dictionary_spec.data_object_props))
num_comparam_refs.append(len(variant.comparam_refs))
ddds = variant.diag_data_dictionary_spec
num_dops.append(len(ddds.data_object_props))
num_comparam_refs.append(len(getattr(variant, "comparams_refs", [])))

table = {
'Name': name,
Expand Down
24 changes: 13 additions & 11 deletions odxtools/cli/browse.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from ..diaglayer import DiagLayer
from ..diagservice import DiagService
from ..exceptions import odxraise, odxrequire
from ..hierarchyelement import HierarchyElement
from ..odxtypes import AtomicOdxType, DataType, ParameterValueDict
from ..parameters.matchingrequestparameter import MatchingRequestParameter
from ..parameters.parameter import Parameter
Expand Down Expand Up @@ -283,19 +284,20 @@ def browse(odxdb: Database) -> None:
print(f"{type(answer.get('variant'))=}")
assert isinstance(variant, DiagLayer)

if (rx_id := variant.get_receive_id()) is not None:
recv_id = hex(rx_id)
else:
recv_id = "None"
if isinstance(variant, HierarchyElement):
if (rx_id := variant.get_receive_id()) is not None:
recv_id = hex(rx_id)
else:
recv_id = "None"

if (tx_id := variant.get_send_id()) is not None:
send_id = hex(tx_id)
else:
send_id = "None"
if (tx_id := variant.get_send_id()) is not None:
send_id = hex(tx_id)
else:
send_id = "None"

print(
f"{variant.variant_type.value} '{variant.short_name}' (Receive ID: {recv_id}, Send ID: {send_id})"
)
print(
f"{variant.variant_type.value} '{variant.short_name}' (Receive ID: {recv_id}, Send ID: {send_id})"
)

while True:
services: List[DiagService] = [
Expand Down
2 changes: 1 addition & 1 deletion odxtools/cli/compare.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from tabulate import tabulate # TODO: switch to rich tables

from ..database import Database
from ..diaglayer import DiagLayer
from ..diaglayers.diaglayer import DiagLayer
from ..diagservice import DiagService
from ..loadfile import load_file
from ..odxtypes import AtomicOdxType
Expand Down
30 changes: 20 additions & 10 deletions odxtools/cli/list.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,14 @@

import rich

from ..comparaminstance import ComparamInstance
from ..database import Database
from ..dataobjectproperty import DataObjectProperty
from ..diagcomm import DiagComm
from ..diaglayer import DiagLayer
from ..diaglayers.basevariant import BaseVariant
from ..diaglayers.diaglayer import DiagLayer
from ..diaglayers.ecuvariant import EcuVariant
from ..diaglayers.hierarchyelement import HierarchyElement
from ..diagservice import DiagService
from ..singleecujob import SingleEcuJob
from . import _parser_utils
Expand Down Expand Up @@ -56,15 +61,14 @@ def print_summary(odxdb: Database,

all_services: List[DiagComm] = sorted(dl.services, key=lambda x: x.short_name)

data_object_properties = dl.diag_data_dictionary_spec.data_object_props
comparam_refs = dl.comparam_refs
if isinstance(dl, (BaseVariant, EcuVariant)):
for proto in dl.protocols:
if (can_rx_id := dl.get_can_receive_id(proto.short_name)) is not None:
rich.print(
f" CAN receive ID for protocol '{proto.short_name}': 0x{can_rx_id:x}")

for proto in dl.protocols:
if (can_rx_id := dl.get_can_receive_id(proto.short_name)) is not None:
rich.print(f" CAN receive ID for protocol '{proto.short_name}': 0x{can_rx_id:x}")

if (can_tx_id := dl.get_can_send_id(proto.short_name)) is not None:
rich.print(f" CAN send ID for protocol '{proto.short_name}': 0x{can_tx_id:x}")
if (can_tx_id := dl.get_can_send_id(proto.short_name)) is not None:
rich.print(f" CAN send ID for protocol '{proto.short_name}': 0x{can_tx_id:x}")

if dl.description:
desc = format_desc(dl.description, indent=2)
Expand Down Expand Up @@ -95,14 +99,20 @@ def print_summary(odxdb: Database,
rich.print(f" Single ECU job: {service.odx_id}")
else:
rich.print(f" Unidentifiable service: {service}")

ddd_spec = dl.diag_data_dictionary_spec
data_object_properties: List[
DataObjectProperty] = [] if ddd_spec is None else ddd_spec.data_object_props
if print_dops and len(data_object_properties) > 0:
rich.print("\n")
rich.print(f"The DOPs of the {dl.variant_type.value} '{dl.short_name}' are: ")
for dop in sorted(
data_object_properties, key=lambda x: (type(x).__name__, x.short_name)):
rich.print(" " + str(dop.short_name).replace("\n", "\n "))

comparam_refs: List[ComparamInstance] = []
if isinstance(dl, HierarchyElement):
comparam_refs = dl.comparam_refs

if print_comparams and len(comparam_refs) > 0:
rich.print("\n")
rich.print(
Expand Down
33 changes: 28 additions & 5 deletions odxtools/cli/snoop.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@
import argparse
import asyncio
import sys
from typing import Any, Type
from typing import Any, List, Optional, Type

import can

import odxtools.isotp_state_machine as ism
import odxtools.uds as uds
from odxtools.diaglayers.protocol import Protocol
from odxtools.exceptions import DecodeError
from odxtools.isotp_state_machine import IsoTpStateMachine
from odxtools.response import Response, ResponseType
Expand Down Expand Up @@ -245,21 +246,43 @@ def run(args: argparse.Namespace) -> None:

protocol_name = args.protocol
if odx_diag_layer is not None and protocol_name is not None:
protocol_names = [x.short_name for x in odx_diag_layer.protocols]
protocols: Optional[List[Protocol]] = getattr(odx_diag_layer, "protocols", None)

if protocols is None:
print(f"ECU variant {odx_diag_layer.short_name} is of type "
f"{odx_diag_layer.variant_type.value} and thus does not "
f"feature any protocols")
sys.exit(1)

protocol_names = [x.short_name for x in protocols]
if protocol_name not in protocol_names:
print(f"ECU variant {odx_diag_layer.short_name} does not support "
f"a protocol named '{protocol_name}'. Supported protocols are:")
for x in odx_diag_layer.protocols:
for x in protocols:
desc = "" if x.description is None else f": {x.description}"
print(f" {x.short_name}{desc}")
sys.exit(1)

# if no can IDs have been explicitly specified, take them from the DL
if args.rx is None and odx_diag_layer:
args.rx = str(odx_diag_layer.get_can_receive_id(protocol=protocol_name))
get_can_rx_id = getattr(odx_diag_layer, "get_can_receive_id", None)
if get_can_rx_id is None:
print(f"ECU variant {odx_diag_layer.short_name} is of type "
f"{odx_diag_layer.variant_type.value} and thus does not "
f"provide any communication parameters")
sys.exit(1)

args.rx = str(get_can_rx_id(protocol=protocol_name))

if args.tx is None and odx_diag_layer:
args.tx = str(odx_diag_layer.get_can_send_id(protocol=protocol_name))
get_can_tx_id = getattr(odx_diag_layer, "get_can_send_id", None)
if get_can_tx_id is None:
print(f"ECU variant {odx_diag_layer.short_name} is of type "
f"{odx_diag_layer.variant_type.value} and thus does not "
f"provide any communication parameters")
sys.exit(1)

args.tx = str(get_can_tx_id(protocol=protocol_name))

if args.rx is None:
print(f"Could not determine a CAN receive ID.")
Expand Down
Loading

0 comments on commit 61943f0

Please sign in to comment.