odxtools 6.6.1__py3-none-any.whl → 9.3.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- odxtools/__init__.py +7 -5
- odxtools/additionalaudience.py +3 -5
- odxtools/admindata.py +5 -7
- odxtools/audience.py +10 -13
- odxtools/basecomparam.py +3 -5
- odxtools/basicstructure.py +55 -241
- odxtools/cli/_parser_utils.py +16 -1
- odxtools/cli/_print_utils.py +169 -134
- odxtools/cli/browse.py +127 -103
- odxtools/cli/compare.py +114 -87
- odxtools/cli/decode.py +2 -1
- odxtools/cli/dummy_sub_parser.py +3 -1
- odxtools/cli/find.py +2 -1
- odxtools/cli/list.py +26 -16
- odxtools/cli/main.py +1 -0
- odxtools/cli/snoop.py +32 -6
- odxtools/codec.py +211 -0
- odxtools/commrelation.py +122 -0
- odxtools/companydata.py +5 -7
- odxtools/companydocinfo.py +7 -8
- odxtools/companyrevisioninfo.py +3 -5
- odxtools/companyspecificinfo.py +8 -9
- odxtools/comparam.py +4 -6
- odxtools/comparaminstance.py +14 -14
- odxtools/comparamspec.py +16 -54
- odxtools/comparamsubset.py +22 -62
- odxtools/complexcomparam.py +5 -7
- odxtools/compumethods/compucodecompumethod.py +63 -0
- odxtools/compumethods/compuconst.py +31 -0
- odxtools/compumethods/compudefaultvalue.py +27 -0
- odxtools/compumethods/compuinternaltophys.py +56 -0
- odxtools/compumethods/compuinversevalue.py +7 -0
- odxtools/compumethods/compumethod.py +94 -15
- odxtools/compumethods/compuphystointernal.py +56 -0
- odxtools/compumethods/compurationalcoeffs.py +20 -9
- odxtools/compumethods/compuscale.py +67 -32
- odxtools/compumethods/createanycompumethod.py +31 -172
- odxtools/compumethods/identicalcompumethod.py +31 -6
- odxtools/compumethods/limit.py +70 -36
- odxtools/compumethods/linearcompumethod.py +70 -181
- odxtools/compumethods/linearsegment.py +190 -0
- odxtools/compumethods/ratfunccompumethod.py +106 -0
- odxtools/compumethods/ratfuncsegment.py +87 -0
- odxtools/compumethods/scalelinearcompumethod.py +132 -26
- odxtools/compumethods/scaleratfunccompumethod.py +113 -0
- odxtools/compumethods/tabintpcompumethod.py +123 -92
- odxtools/compumethods/texttablecompumethod.py +117 -57
- odxtools/createanydiagcodedtype.py +10 -67
- odxtools/database.py +167 -87
- odxtools/dataobjectproperty.py +25 -32
- odxtools/decodestate.py +14 -17
- odxtools/description.py +47 -0
- odxtools/determinenumberofitems.py +4 -5
- odxtools/diagcodedtype.py +37 -106
- odxtools/diagcomm.py +24 -12
- odxtools/diagdatadictionaryspec.py +120 -96
- odxtools/diaglayercontainer.py +46 -54
- odxtools/diaglayers/basevariant.py +128 -0
- odxtools/diaglayers/basevariantraw.py +123 -0
- odxtools/diaglayers/diaglayer.py +432 -0
- odxtools/{diaglayerraw.py → diaglayers/diaglayerraw.py} +105 -120
- odxtools/diaglayers/diaglayertype.py +42 -0
- odxtools/diaglayers/ecushareddata.py +96 -0
- odxtools/diaglayers/ecushareddataraw.py +87 -0
- odxtools/diaglayers/ecuvariant.py +124 -0
- odxtools/diaglayers/ecuvariantraw.py +129 -0
- odxtools/diaglayers/functionalgroup.py +110 -0
- odxtools/diaglayers/functionalgroupraw.py +106 -0
- odxtools/{diaglayer.py → diaglayers/hierarchyelement.py} +273 -472
- odxtools/diaglayers/hierarchyelementraw.py +58 -0
- odxtools/diaglayers/protocol.py +64 -0
- odxtools/diaglayers/protocolraw.py +91 -0
- odxtools/diagnostictroublecode.py +8 -9
- odxtools/diagservice.py +57 -44
- odxtools/diagvariable.py +113 -0
- odxtools/docrevision.py +5 -7
- odxtools/dopbase.py +15 -15
- odxtools/dtcdop.py +170 -50
- odxtools/dynamicendmarkerfield.py +134 -0
- odxtools/dynamiclengthfield.py +47 -42
- odxtools/dyndefinedspec.py +177 -0
- odxtools/dynenddopref.py +38 -0
- odxtools/ecuvariantmatcher.py +6 -7
- odxtools/element.py +13 -15
- odxtools/encodestate.py +199 -22
- odxtools/endofpdufield.py +31 -18
- odxtools/environmentdata.py +8 -1
- odxtools/environmentdatadescription.py +198 -36
- odxtools/exceptions.py +11 -2
- odxtools/field.py +10 -10
- odxtools/functionalclass.py +3 -5
- odxtools/inputparam.py +3 -12
- odxtools/internalconstr.py +14 -5
- odxtools/isotp_state_machine.py +14 -6
- odxtools/leadinglengthinfotype.py +37 -18
- odxtools/library.py +66 -0
- odxtools/loadfile.py +64 -0
- odxtools/matchingparameter.py +3 -3
- odxtools/message.py +0 -7
- odxtools/minmaxlengthtype.py +61 -33
- odxtools/modification.py +3 -5
- odxtools/multiplexer.py +135 -75
- odxtools/multiplexercase.py +39 -18
- odxtools/multiplexerdefaultcase.py +15 -12
- odxtools/multiplexerswitchkey.py +4 -5
- odxtools/nameditemlist.py +33 -8
- odxtools/negoutputparam.py +3 -5
- odxtools/odxcategory.py +83 -0
- odxtools/odxlink.py +62 -53
- odxtools/odxtypes.py +93 -8
- odxtools/outputparam.py +5 -16
- odxtools/parameterinfo.py +219 -61
- odxtools/parameters/codedconstparameter.py +45 -32
- odxtools/parameters/createanyparameter.py +19 -193
- odxtools/parameters/dynamicparameter.py +25 -4
- odxtools/parameters/lengthkeyparameter.py +83 -25
- odxtools/parameters/matchingrequestparameter.py +48 -18
- odxtools/parameters/nrcconstparameter.py +76 -54
- odxtools/parameters/parameter.py +97 -73
- odxtools/parameters/parameterwithdop.py +41 -38
- odxtools/parameters/physicalconstantparameter.py +41 -20
- odxtools/parameters/reservedparameter.py +36 -18
- odxtools/parameters/systemparameter.py +74 -7
- odxtools/parameters/tableentryparameter.py +47 -7
- odxtools/parameters/tablekeyparameter.py +142 -55
- odxtools/parameters/tablestructparameter.py +79 -58
- odxtools/parameters/valueparameter.py +39 -21
- odxtools/paramlengthinfotype.py +56 -33
- odxtools/parentref.py +20 -3
- odxtools/physicaldimension.py +3 -8
- odxtools/progcode.py +26 -11
- odxtools/protstack.py +3 -5
- odxtools/py.typed +0 -0
- odxtools/relateddoc.py +7 -9
- odxtools/request.py +120 -10
- odxtools/response.py +123 -23
- odxtools/scaleconstr.py +14 -8
- odxtools/servicebinner.py +1 -1
- odxtools/singleecujob.py +12 -10
- odxtools/snrefcontext.py +29 -0
- odxtools/specialdata.py +3 -5
- odxtools/specialdatagroup.py +7 -9
- odxtools/specialdatagroupcaption.py +3 -6
- odxtools/standardlengthtype.py +80 -14
- odxtools/state.py +3 -5
- odxtools/statechart.py +13 -19
- odxtools/statetransition.py +8 -18
- odxtools/staticfield.py +107 -0
- odxtools/subcomponent.py +288 -0
- odxtools/swvariable.py +21 -0
- odxtools/table.py +9 -9
- odxtools/tablerow.py +30 -15
- odxtools/teammember.py +3 -5
- odxtools/templates/comparam-spec.odx-c.xml.jinja2 +4 -24
- odxtools/templates/comparam-subset.odx-cs.xml.jinja2 +5 -26
- odxtools/templates/diag_layer_container.odx-d.xml.jinja2 +15 -31
- odxtools/templates/{index.xml.xml.jinja2 → index.xml.jinja2} +1 -1
- odxtools/templates/macros/printAudience.xml.jinja2 +1 -1
- odxtools/templates/macros/printBaseVariant.xml.jinja2 +53 -0
- odxtools/templates/macros/printCompanyData.xml.jinja2 +4 -7
- odxtools/templates/macros/printComparam.xml.jinja2 +6 -4
- odxtools/templates/macros/printComparamRef.xml.jinja2 +5 -12
- odxtools/templates/macros/printCompuMethod.xml.jinja2 +147 -0
- odxtools/templates/macros/printDOP.xml.jinja2 +27 -137
- odxtools/templates/macros/printDescription.xml.jinja2 +18 -0
- odxtools/templates/macros/printDiagComm.xml.jinja2 +1 -1
- odxtools/templates/macros/printDiagLayer.xml.jinja2 +222 -0
- odxtools/templates/macros/printDiagVariable.xml.jinja2 +66 -0
- odxtools/templates/macros/printDynDefinedSpec.xml.jinja2 +48 -0
- odxtools/templates/macros/printDynamicEndmarkerField.xml.jinja2 +16 -0
- odxtools/templates/macros/printDynamicLengthField.xml.jinja2 +1 -1
- odxtools/templates/macros/printEcuSharedData.xml.jinja2 +30 -0
- odxtools/templates/macros/printEcuVariant.xml.jinja2 +53 -0
- odxtools/templates/macros/printEcuVariantPattern.xml.jinja2 +1 -1
- odxtools/templates/macros/printElementId.xml.jinja2 +8 -3
- odxtools/templates/macros/printEndOfPdu.xml.jinja2 +1 -1
- odxtools/templates/macros/printEnvDataDesc.xml.jinja2 +1 -1
- odxtools/templates/macros/printFunctionalClass.xml.jinja2 +1 -1
- odxtools/templates/macros/printFunctionalGroup.xml.jinja2 +40 -0
- odxtools/templates/macros/printHierarchyElement.xml.jinja2 +24 -0
- odxtools/templates/macros/printLibrary.xml.jinja2 +21 -0
- odxtools/templates/macros/printMux.xml.jinja2 +5 -3
- odxtools/templates/macros/printOdxCategory.xml.jinja2 +28 -0
- odxtools/templates/macros/printParam.xml.jinja2 +18 -19
- odxtools/templates/macros/printProtStack.xml.jinja2 +1 -1
- odxtools/templates/macros/printProtocol.xml.jinja2 +30 -0
- odxtools/templates/macros/printRequest.xml.jinja2 +1 -1
- odxtools/templates/macros/printResponse.xml.jinja2 +1 -1
- odxtools/templates/macros/printService.xml.jinja2 +3 -2
- odxtools/templates/macros/printSingleEcuJob.xml.jinja2 +5 -26
- odxtools/templates/macros/printSpecialData.xml.jinja2 +1 -1
- odxtools/templates/macros/printState.xml.jinja2 +1 -1
- odxtools/templates/macros/printStateChart.xml.jinja2 +1 -1
- odxtools/templates/macros/printStateTransition.xml.jinja2 +1 -1
- odxtools/templates/macros/printStaticField.xml.jinja2 +15 -0
- odxtools/templates/macros/printStructure.xml.jinja2 +1 -1
- odxtools/templates/macros/printSubComponent.xml.jinja2 +104 -0
- odxtools/templates/macros/printTable.xml.jinja2 +4 -5
- odxtools/templates/macros/printUnitSpec.xml.jinja2 +3 -5
- odxtools/uds.py +2 -10
- odxtools/unit.py +4 -8
- odxtools/unitgroup.py +3 -5
- odxtools/unitspec.py +17 -17
- odxtools/utils.py +38 -20
- odxtools/variablegroup.py +32 -0
- odxtools/version.py +2 -2
- odxtools/{write_pdx_file.py → writepdxfile.py} +22 -12
- odxtools/xdoc.py +3 -5
- {odxtools-6.6.1.dist-info → odxtools-9.3.0.dist-info}/METADATA +44 -33
- odxtools-9.3.0.dist-info/RECORD +228 -0
- {odxtools-6.6.1.dist-info → odxtools-9.3.0.dist-info}/WHEEL +1 -1
- odxtools/createcompanydatas.py +0 -17
- odxtools/createsdgs.py +0 -19
- odxtools/diaglayertype.py +0 -30
- odxtools/load_file.py +0 -13
- odxtools/load_odx_d_file.py +0 -6
- odxtools/load_pdx_file.py +0 -8
- odxtools/templates/macros/printVariant.xml.jinja2 +0 -208
- odxtools-6.6.1.dist-info/RECORD +0 -180
- {odxtools-6.6.1.dist-info → odxtools-9.3.0.dist-info}/LICENSE +0 -0
- {odxtools-6.6.1.dist-info → odxtools-9.3.0.dist-info}/entry_points.txt +0 -0
- {odxtools-6.6.1.dist-info → odxtools-9.3.0.dist-info}/top_level.txt +0 -0
odxtools/cli/compare.py
CHANGED
@@ -3,15 +3,16 @@
|
|
3
3
|
|
4
4
|
import argparse
|
5
5
|
import os
|
6
|
-
from typing import Any, Dict, List, Optional, Set, Union
|
6
|
+
from typing import Any, Dict, List, Optional, Set, Union, cast
|
7
7
|
|
8
|
-
from rich import print
|
9
|
-
from
|
8
|
+
from rich import print as rich_print
|
9
|
+
from rich.padding import Padding as RichPadding
|
10
|
+
from rich.table import Table as RichTable
|
10
11
|
|
11
12
|
from ..database import Database
|
12
|
-
from ..diaglayer import DiagLayer
|
13
|
+
from ..diaglayers.diaglayer import DiagLayer
|
13
14
|
from ..diagservice import DiagService
|
14
|
-
from ..
|
15
|
+
from ..loadfile import load_file
|
15
16
|
from ..odxtypes import AtomicOdxType
|
16
17
|
from ..parameters.codedconstparameter import CodedConstParameter
|
17
18
|
from ..parameters.nrcconstparameter import NrcConstParameter
|
@@ -19,6 +20,7 @@ from ..parameters.parameter import Parameter
|
|
19
20
|
from ..parameters.physicalconstantparameter import PhysicalConstantParameter
|
20
21
|
from ..parameters.valueparameter import ValueParameter
|
21
22
|
from . import _parser_utils
|
23
|
+
from ._parser_utils import SubparsersList
|
22
24
|
from ._print_utils import (extract_service_tabulation_data, print_dl_metrics,
|
23
25
|
print_service_parameters)
|
24
26
|
|
@@ -45,11 +47,14 @@ class Display:
|
|
45
47
|
# class with variables and functions to display the result of the comparison
|
46
48
|
|
47
49
|
# TODO
|
48
|
-
# Idea: results as json export
|
49
|
-
#
|
50
|
-
#
|
51
|
-
|
52
|
-
#
|
50
|
+
# - Idea: results as json export
|
51
|
+
# - write results of comparison in json structure
|
52
|
+
# - use odxlinks to refer to dignostic services / objects if
|
53
|
+
# changes have already been detected (e.g. in another ecu
|
54
|
+
# variant / diagnostic layer)
|
55
|
+
# - print all information about parameter properties (request,
|
56
|
+
# pos. response & neg. response parameters) for changed diagnostic
|
57
|
+
# services
|
53
58
|
param_detailed: bool
|
54
59
|
obj_detailed: bool
|
55
60
|
|
@@ -61,56 +66,69 @@ class Display:
|
|
61
66
|
if service_dict["new_services"] or service_dict["deleted_services"] or service_dict[
|
62
67
|
"changed_name_of_service"][0] or service_dict["changed_parameters_of_service"][0]:
|
63
68
|
assert isinstance(service_dict["diag_layer"], str)
|
64
|
-
|
65
|
-
|
69
|
+
rich_print()
|
70
|
+
rich_print(
|
66
71
|
f"Changed diagnostic services for diagnostic layer '{service_dict['diag_layer']}' ({service_dict['diag_layer_type']}):"
|
67
72
|
)
|
68
73
|
if service_dict["new_services"]:
|
69
74
|
assert isinstance(service_dict["new_services"], List)
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
service_dict["new_services"]) # type: ignore[arg-type]
|
74
|
-
print(tabulate(table, headers="keys", tablefmt="presto"))
|
75
|
+
rich_print()
|
76
|
+
rich_print(" [blue]New services[/blue]")
|
77
|
+
rich_print(extract_service_tabulation_data(
|
78
|
+
service_dict["new_services"])) # type: ignore[arg-type]
|
75
79
|
if service_dict["deleted_services"]:
|
76
80
|
assert isinstance(service_dict["deleted_services"], List)
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
service_dict["deleted_services"]) # type: ignore[arg-type]
|
81
|
-
print(tabulate(table, headers="keys", tablefmt="presto"))
|
81
|
+
rich_print()
|
82
|
+
rich_print(" [blue]Deleted services[/blue]")
|
83
|
+
rich_print(extract_service_tabulation_data(
|
84
|
+
service_dict["deleted_services"])) # type: ignore[arg-type]
|
82
85
|
if service_dict["changed_name_of_service"][0]:
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
service_dict["changed_name_of_service"][0]) # type: ignore[arg-type]
|
87
|
-
table["Old service name"] = service_dict["changed_name_of_service"][1]
|
88
|
-
print(tabulate(table, headers="keys", tablefmt="presto"))
|
86
|
+
rich_print()
|
87
|
+
rich_print(" [blue]Renamed services[/blue]")
|
88
|
+
rich_print(extract_service_tabulation_data(
|
89
|
+
service_dict["changed_name_of_service"][0])) # type: ignore[arg-type]
|
89
90
|
if service_dict["changed_parameters_of_service"][0]:
|
90
|
-
|
91
|
-
|
91
|
+
rich_print()
|
92
|
+
rich_print(" [blue]Services with parameter changes[/blue]")
|
92
93
|
# create table with information about services with parameter changes
|
94
|
+
changed_param_column = [
|
95
|
+
str(x) for x in service_dict["changed_parameters_of_service"][
|
96
|
+
1] # type: ignore[union-attr]
|
97
|
+
]
|
93
98
|
table = extract_service_tabulation_data(
|
94
|
-
service_dict["changed_parameters_of_service"][0]
|
95
|
-
|
96
|
-
table
|
97
|
-
print(tabulate(table, headers="keys", tablefmt="presto"))
|
99
|
+
service_dict["changed_parameters_of_service"][0], # type: ignore[arg-type]
|
100
|
+
additional_columns=[("Changed Parameters", changed_param_column)])
|
101
|
+
rich_print(table)
|
98
102
|
|
99
103
|
for service_idx, service in enumerate(
|
100
104
|
service_dict["changed_parameters_of_service"][0]): # type: ignore[arg-type]
|
101
105
|
assert isinstance(service, DiagService)
|
102
|
-
|
103
|
-
|
106
|
+
rich_print()
|
107
|
+
rich_print(
|
104
108
|
f" Detailed changes of diagnostic service [u cyan]{service.short_name}[/u cyan]"
|
105
109
|
)
|
106
110
|
# detailed_info in [infotext1, dict1, infotext2, dict2, ...]
|
107
|
-
|
108
|
-
|
111
|
+
info_list = cast(
|
112
|
+
list, # type: ignore[type-arg]
|
113
|
+
service_dict["changed_parameters_of_service"])[2][service_idx]
|
114
|
+
for detailed_info in info_list:
|
109
115
|
if isinstance(detailed_info, str):
|
110
|
-
|
111
|
-
|
116
|
+
rich_print()
|
117
|
+
rich_print(detailed_info)
|
112
118
|
elif isinstance(detailed_info, dict):
|
113
|
-
|
119
|
+
table = RichTable(
|
120
|
+
show_header=True,
|
121
|
+
header_style="bold cyan",
|
122
|
+
border_style="blue",
|
123
|
+
show_lines=True)
|
124
|
+
for header in detailed_info:
|
125
|
+
table.add_column(header)
|
126
|
+
rows = zip(*detailed_info.values())
|
127
|
+
for row in rows:
|
128
|
+
table.add_row(*map(str, row))
|
129
|
+
|
130
|
+
rich_print(RichPadding(table, pad=(0, 0, 0, 4)))
|
131
|
+
rich_print()
|
114
132
|
if self.param_detailed:
|
115
133
|
# print all parameter details of diagnostic service
|
116
134
|
print_service_parameters(service, allow_unknown_bit_lengths=True)
|
@@ -121,16 +139,18 @@ class Display:
|
|
121
139
|
# diagnostic layers
|
122
140
|
if changes_variants["new_diagnostic_layers"] or changes_variants[
|
123
141
|
"deleted_diagnostic_layers"]:
|
124
|
-
|
125
|
-
|
126
|
-
|
142
|
+
rich_print()
|
143
|
+
rich_print("[bright_blue]Changed diagnostic layers[/bright_blue]: ")
|
144
|
+
rich_print(" New diagnostic layers: ")
|
127
145
|
for variant in changes_variants["new_diagnostic_layers"]:
|
128
146
|
assert isinstance(variant, DiagLayer)
|
129
|
-
|
130
|
-
|
147
|
+
rich_print(
|
148
|
+
f" [magenta]{variant.short_name}[/magenta] ({variant.variant_type.value})")
|
149
|
+
rich_print(" Deleted diagnostic layers: ")
|
131
150
|
for variant in changes_variants["deleted_diagnostic_layers"]:
|
132
151
|
assert isinstance(variant, DiagLayer)
|
133
|
-
|
152
|
+
rich_print(
|
153
|
+
f" [magenta]{variant.short_name}[/magenta] ({variant.variant_type.value})")
|
134
154
|
|
135
155
|
# diagnostic services
|
136
156
|
for _, value in changes_variants.items():
|
@@ -256,7 +276,8 @@ class Comparison(Display):
|
|
256
276
|
|
257
277
|
return {"Property": property, "Old Value": old, "New Value": new}
|
258
278
|
|
259
|
-
def compare_services(self, service1: DiagService,
|
279
|
+
def compare_services(self, service1: DiagService,
|
280
|
+
service2: DiagService) -> List[SpecsServiceDict]:
|
260
281
|
# compares request, positive response and negative response parameters of two diagnostic services
|
261
282
|
|
262
283
|
information: List[Union[str, Dict[str, Any]]] = [
|
@@ -271,8 +292,8 @@ class Comparison(Display):
|
|
271
292
|
if res1_idx == res2_idx:
|
272
293
|
# find changed request parameter properties
|
273
294
|
table = self.compare_parameters(param1, param2)
|
274
|
-
infotext = (f" Properties of request parameter '{param2.short_name}'"
|
275
|
-
f" have changed
|
295
|
+
infotext = (f" Properties of request parameter '{param2.short_name}' "
|
296
|
+
f"that have changed:\n")
|
276
297
|
# array index starts with 0 -> param[0] is 1. service parameter
|
277
298
|
|
278
299
|
if table["Property"]:
|
@@ -307,8 +328,8 @@ class Comparison(Display):
|
|
307
328
|
# find changed positive response parameter properties
|
308
329
|
table = self.compare_parameters(param1, param2)
|
309
330
|
infotext = (
|
310
|
-
f" Properties of positive response parameter '{param2.short_name}'"
|
311
|
-
f"have changed
|
331
|
+
f" Properties of positive response parameter '{param2.short_name}' that "
|
332
|
+
f"have changed:\n")
|
312
333
|
# array index starts with 0 -> param[0] is first service parameter
|
313
334
|
|
314
335
|
if table["Property"]:
|
@@ -350,7 +371,7 @@ class Comparison(Display):
|
|
350
371
|
if param1_idx == param2_idx:
|
351
372
|
# find changed negative response parameter properties
|
352
373
|
table = self.compare_parameters(param1, param2)
|
353
|
-
infotext = f" Properties of response parameter '{param2.short_name}' have changed
|
374
|
+
infotext = f" Properties of response parameter '{param2.short_name}' that have changed:\n"
|
354
375
|
# array index starts with 0 -> param[0] is 1. service parameter
|
355
376
|
|
356
377
|
if table["Property"]:
|
@@ -382,9 +403,10 @@ class Comparison(Display):
|
|
382
403
|
str(service2.negative_responses)]
|
383
404
|
})
|
384
405
|
|
385
|
-
return [information, changed_params]
|
406
|
+
return [information, changed_params] # type: ignore[list-item]
|
386
407
|
|
387
|
-
def compare_diagnostic_layers(self, dl1: DiagLayer,
|
408
|
+
def compare_diagnostic_layers(self, dl1: DiagLayer,
|
409
|
+
dl2: DiagLayer) -> dict: # type: ignore[type-arg]
|
388
410
|
# compares diagnostic services of two diagnostic layers with each other
|
389
411
|
# save changes in dictionary (service_dict)
|
390
412
|
# TODO: add comparison of SingleECUJobs
|
@@ -467,21 +489,23 @@ class Comparison(Display):
|
|
467
489
|
# add parameters which have been changed (type: String)
|
468
490
|
service_dict["changed_parameters_of_service"][
|
469
491
|
1].append( # type: ignore[union-attr]
|
470
|
-
detailed_information[1])
|
492
|
+
detailed_information[1]) # type: ignore[arg-type]
|
471
493
|
# add detailed information about changed service parameters (type: list) [infotext1, table1, infotext2, table2, ...]
|
472
494
|
service_dict["changed_parameters_of_service"][
|
473
495
|
2].append( # type: ignore[union-attr]
|
474
|
-
detailed_information[0])
|
496
|
+
detailed_information[0]) # type: ignore[arg-type]
|
475
497
|
|
476
498
|
for service2_idx, service2 in enumerate(dl2.services):
|
477
499
|
|
478
500
|
# check for deleted diagnostic services
|
479
501
|
if service2.short_name not in dl1_service_names and dl2_request_prefixes[
|
480
|
-
service2_idx] not in dl1_request_prefixes
|
481
|
-
"deleted_services"]:
|
502
|
+
service2_idx] not in dl1_request_prefixes:
|
482
503
|
|
483
|
-
service_dict["deleted_services"]
|
484
|
-
|
504
|
+
deleted_list = service_dict["deleted_services"]
|
505
|
+
assert isinstance(deleted_list, list)
|
506
|
+
if service2 not in deleted_list:
|
507
|
+
service_dict["deleted_services"].append( # type: ignore[union-attr]
|
508
|
+
service2) # type: ignore[arg-type]
|
485
509
|
|
486
510
|
if service1.short_name == service2.short_name:
|
487
511
|
# compare request, pos. response and neg. response parameters of both diagnostic services
|
@@ -496,13 +520,14 @@ class Comparison(Display):
|
|
496
520
|
service1)
|
497
521
|
# add parameters which have been changed (type: String)
|
498
522
|
service_dict["changed_parameters_of_service"][ # type: ignore[union-attr]
|
499
|
-
1].append(detailed_information[1])
|
523
|
+
1].append(detailed_information[1]) # type: ignore[arg-type]
|
500
524
|
# add detailed information about changed service parameters (type: list) [infotext1, table1, infotext2, table2, ...]
|
501
525
|
service_dict["changed_parameters_of_service"][ # type: ignore[union-attr]
|
502
|
-
2].append(detailed_information[0])
|
526
|
+
2].append(detailed_information[0]) # type: ignore[arg-type]
|
503
527
|
return service_dict
|
504
528
|
|
505
|
-
def compare_databases(self, database_new: Database,
|
529
|
+
def compare_databases(self, database_new: Database,
|
530
|
+
database_old: Database) -> dict: # type: ignore[type-arg]
|
506
531
|
# compares two PDX-files with each other
|
507
532
|
|
508
533
|
new_variants: NewVariants = []
|
@@ -539,7 +564,7 @@ class Comparison(Display):
|
|
539
564
|
return changes_variants
|
540
565
|
|
541
566
|
|
542
|
-
def add_subparser(subparsers:
|
567
|
+
def add_subparser(subparsers: SubparsersList) -> None:
|
543
568
|
parser = subparsers.add_parser(
|
544
569
|
"compare",
|
545
570
|
description="\n".join([
|
@@ -614,7 +639,7 @@ def run(args: argparse.Namespace) -> None:
|
|
614
639
|
|
615
640
|
for name in args.variants:
|
616
641
|
if name not in task.diagnostic_layer_names:
|
617
|
-
|
642
|
+
rich_print(f"The variant '{name}' could not be found!")
|
618
643
|
return
|
619
644
|
|
620
645
|
task.db_indicator_1 = 0
|
@@ -624,19 +649,20 @@ def run(args: argparse.Namespace) -> None:
|
|
624
649
|
break
|
625
650
|
task.db_indicator_2 = db_idx + 1
|
626
651
|
|
627
|
-
|
628
|
-
|
629
|
-
|
652
|
+
rich_print()
|
653
|
+
rich_print(f"Changes in file '{os.path.basename(db_names[0])}'")
|
654
|
+
rich_print(f" (compared to '{os.path.basename(db_names[db_idx + 1])}')")
|
630
655
|
|
631
|
-
|
632
|
-
|
656
|
+
rich_print()
|
657
|
+
rich_print(f"Overview of diagnostic layers (for {os.path.basename(db_names[0])})")
|
633
658
|
print_dl_metrics([
|
634
659
|
variant for variant in task.databases[0].diag_layers
|
635
660
|
if variant.short_name in task.diagnostic_layer_names
|
636
661
|
])
|
637
662
|
|
638
|
-
|
639
|
-
|
663
|
+
rich_print()
|
664
|
+
rich_print(
|
665
|
+
f"Overview of diagnostic layers (for {os.path.basename(db_names[db_idx+1])})")
|
640
666
|
print_dl_metrics([
|
641
667
|
variant for variant in task.databases[db_idx + 1].diag_layers
|
642
668
|
if variant.short_name in task.diagnostic_layer_names
|
@@ -665,16 +691,17 @@ def run(args: argparse.Namespace) -> None:
|
|
665
691
|
break
|
666
692
|
task.db_indicator_2 = db_idx + 1
|
667
693
|
|
668
|
-
|
669
|
-
|
670
|
-
|
694
|
+
rich_print()
|
695
|
+
rich_print(f"Changes in file '{os.path.basename(db_names[0])}")
|
696
|
+
rich_print(f" (compared to '{os.path.basename(db_names[db_idx + 1])}')")
|
671
697
|
|
672
|
-
|
673
|
-
|
698
|
+
rich_print()
|
699
|
+
rich_print(f"Overview of diagnostic layers (for {os.path.basename(db_names[0])})")
|
674
700
|
print_dl_metrics(list(task.databases[0].diag_layers))
|
675
701
|
|
676
|
-
|
677
|
-
|
702
|
+
rich_print()
|
703
|
+
rich_print(
|
704
|
+
f"Overview of diagnostic layers (for {os.path.basename(db_names[db_idx+1])})")
|
678
705
|
print_dl_metrics(list(task.databases[db_idx + 1].diag_layers))
|
679
706
|
|
680
707
|
task.print_database_changes(
|
@@ -696,20 +723,20 @@ def run(args: argparse.Namespace) -> None:
|
|
696
723
|
|
697
724
|
for name in args.variants:
|
698
725
|
if name not in task.diagnostic_layer_names:
|
699
|
-
|
726
|
+
rich_print(f"The variant '{name}' could not be found!")
|
700
727
|
return
|
701
728
|
|
702
|
-
|
703
|
-
|
729
|
+
rich_print()
|
730
|
+
rich_print(f"Overview of diagnostic layers: ")
|
704
731
|
print_dl_metrics(task.diagnostic_layers)
|
705
732
|
|
706
733
|
for db_idx, dl in enumerate(task.diagnostic_layers):
|
707
734
|
if db_idx + 1 >= len(task.diagnostic_layers):
|
708
735
|
break
|
709
736
|
|
710
|
-
|
711
|
-
|
712
|
-
|
737
|
+
rich_print()
|
738
|
+
rich_print(f"Changes in diagnostic layer '{dl.short_name}' ({dl.variant_type.value})")
|
739
|
+
rich_print(
|
713
740
|
f" (compared to '{task.diagnostic_layers[db_idx + 1].short_name}' ({task.diagnostic_layers[db_idx + 1].variant_type.value}))"
|
714
741
|
)
|
715
742
|
task.print_dl_changes(
|
@@ -717,4 +744,4 @@ def run(args: argparse.Namespace) -> None:
|
|
717
744
|
|
718
745
|
else:
|
719
746
|
# no databases & no variants specified
|
720
|
-
|
747
|
+
rich_print("Please specify either a database or variant for a comparison")
|
odxtools/cli/decode.py
CHANGED
@@ -9,6 +9,7 @@ from ..exceptions import odxraise
|
|
9
9
|
from ..odxtypes import ParameterValue
|
10
10
|
from ..singleecujob import SingleEcuJob
|
11
11
|
from . import _parser_utils
|
12
|
+
from ._parser_utils import SubparsersList
|
12
13
|
|
13
14
|
# name of the tool
|
14
15
|
_odxtools_tool_name_ = "decode"
|
@@ -70,7 +71,7 @@ def print_summary(
|
|
70
71
|
print(f" {param_name}={get_display_value(param_value)}")
|
71
72
|
|
72
73
|
|
73
|
-
def add_subparser(subparsers:
|
74
|
+
def add_subparser(subparsers: SubparsersList) -> None:
|
74
75
|
parser = subparsers.add_parser(
|
75
76
|
"decode",
|
76
77
|
description="\n".join([
|
odxtools/cli/dummy_sub_parser.py
CHANGED
@@ -4,6 +4,8 @@ import sys
|
|
4
4
|
import traceback
|
5
5
|
from io import StringIO
|
6
6
|
|
7
|
+
from ._parser_utils import SubparsersList
|
8
|
+
|
7
9
|
|
8
10
|
class DummyTool:
|
9
11
|
"""A tool which acts as a placeholder for a "real" tool that
|
@@ -20,7 +22,7 @@ class DummyTool:
|
|
20
22
|
self._odxtools_tool_name_ = tool_name
|
21
23
|
self._error = error
|
22
24
|
|
23
|
-
def add_subparser(self, subparser_list:
|
25
|
+
def add_subparser(self, subparser_list: SubparsersList) -> None:
|
24
26
|
desc = StringIO()
|
25
27
|
|
26
28
|
print(f"Tool '{self._odxtools_tool_name_}' is unavailable: {self._error}", file=desc)
|
odxtools/cli/find.py
CHANGED
@@ -7,6 +7,7 @@ from ..diagservice import DiagService
|
|
7
7
|
from ..odxtypes import ParameterValue
|
8
8
|
from ..singleecujob import SingleEcuJob
|
9
9
|
from . import _parser_utils
|
10
|
+
from ._parser_utils import SubparsersList
|
10
11
|
from ._print_utils import print_diagnostic_service
|
11
12
|
|
12
13
|
# name of the tool
|
@@ -66,7 +67,7 @@ def print_summary(odxdb: Database,
|
|
66
67
|
print(f"Unknown service: {service}")
|
67
68
|
|
68
69
|
|
69
|
-
def add_subparser(subparsers:
|
70
|
+
def add_subparser(subparsers: SubparsersList) -> None:
|
70
71
|
parser = subparsers.add_parser(
|
71
72
|
"find",
|
72
73
|
description="\n".join([
|
odxtools/cli/list.py
CHANGED
@@ -4,12 +4,18 @@ from typing import Callable, List, Optional
|
|
4
4
|
|
5
5
|
import rich
|
6
6
|
|
7
|
+
from ..comparaminstance import ComparamInstance
|
7
8
|
from ..database import Database
|
9
|
+
from ..dataobjectproperty import DataObjectProperty
|
8
10
|
from ..diagcomm import DiagComm
|
9
|
-
from ..
|
11
|
+
from ..diaglayers.basevariant import BaseVariant
|
12
|
+
from ..diaglayers.diaglayer import DiagLayer
|
13
|
+
from ..diaglayers.ecuvariant import EcuVariant
|
14
|
+
from ..diaglayers.hierarchyelement import HierarchyElement
|
10
15
|
from ..diagservice import DiagService
|
11
16
|
from ..singleecujob import SingleEcuJob
|
12
17
|
from . import _parser_utils
|
18
|
+
from ._parser_utils import SubparsersList
|
13
19
|
from ._print_utils import format_desc, print_diagnostic_service, print_dl_metrics
|
14
20
|
|
15
21
|
# name of the tool
|
@@ -46,7 +52,7 @@ def print_summary(odxdb: Database,
|
|
46
52
|
if diag_layers:
|
47
53
|
rich.print("\n")
|
48
54
|
rich.print(f"Overview of diagnostic layers: ")
|
49
|
-
print_dl_metrics(diag_layers
|
55
|
+
print_dl_metrics(diag_layers)
|
50
56
|
|
51
57
|
for dl in diag_layers:
|
52
58
|
rich.print("\n")
|
@@ -55,15 +61,14 @@ def print_summary(odxdb: Database,
|
|
55
61
|
|
56
62
|
all_services: List[DiagComm] = sorted(dl.services, key=lambda x: x.short_name)
|
57
63
|
|
58
|
-
|
59
|
-
|
64
|
+
if isinstance(dl, (BaseVariant, EcuVariant)):
|
65
|
+
for proto in dl.protocols:
|
66
|
+
if (can_rx_id := dl.get_can_receive_id(proto.short_name)) is not None:
|
67
|
+
rich.print(
|
68
|
+
f" CAN receive ID for protocol '{proto.short_name}': 0x{can_rx_id:x}")
|
60
69
|
|
61
|
-
|
62
|
-
|
63
|
-
rich.print(f" CAN receive ID for protocol '{proto.short_name}': 0x{can_rx_id:x}")
|
64
|
-
|
65
|
-
if (can_tx_id := dl.get_can_send_id(proto.short_name)) is not None:
|
66
|
-
rich.print(f" CAN send ID for protocol '{proto.short_name}': 0x{can_tx_id:x}")
|
70
|
+
if (can_tx_id := dl.get_can_send_id(proto.short_name)) is not None:
|
71
|
+
rich.print(f" CAN send ID for protocol '{proto.short_name}': 0x{can_tx_id:x}")
|
67
72
|
|
68
73
|
if dl.description:
|
69
74
|
desc = format_desc(dl.description, indent=2)
|
@@ -88,13 +93,14 @@ def print_summary(odxdb: Database,
|
|
88
93
|
print_pre_condition_states=print_pre_condition_states,
|
89
94
|
print_state_transitions=print_state_transitions,
|
90
95
|
print_audiences=print_audiences,
|
91
|
-
allow_unknown_bit_lengths=allow_unknown_bit_lengths
|
92
|
-
print_fn=rich.print)
|
96
|
+
allow_unknown_bit_lengths=allow_unknown_bit_lengths)
|
93
97
|
elif isinstance(service, SingleEcuJob):
|
94
98
|
rich.print(f" Single ECU job: {service.odx_id}")
|
95
99
|
else:
|
96
100
|
rich.print(f" Unidentifiable service: {service}")
|
97
|
-
|
101
|
+
ddd_spec = dl.diag_data_dictionary_spec
|
102
|
+
data_object_properties: List[
|
103
|
+
DataObjectProperty] = [] if ddd_spec is None else ddd_spec.data_object_props
|
98
104
|
if print_dops and len(data_object_properties) > 0:
|
99
105
|
rich.print("\n")
|
100
106
|
rich.print(f"The DOPs of the {dl.variant_type.value} '{dl.short_name}' are: ")
|
@@ -102,16 +108,20 @@ def print_summary(odxdb: Database,
|
|
102
108
|
data_object_properties, key=lambda x: (type(x).__name__, x.short_name)):
|
103
109
|
rich.print(" " + str(dop.short_name).replace("\n", "\n "))
|
104
110
|
|
105
|
-
|
111
|
+
comparam_refs: List[ComparamInstance] = []
|
112
|
+
if isinstance(dl, HierarchyElement):
|
113
|
+
comparam_refs = dl.comparam_refs
|
114
|
+
|
115
|
+
if print_comparams and len(comparam_refs) > 0:
|
106
116
|
rich.print("\n")
|
107
117
|
rich.print(
|
108
118
|
f"The communication parameters of the {dl.variant_type.value} '{dl.short_name}' are: "
|
109
119
|
)
|
110
|
-
for com_param in
|
120
|
+
for com_param in comparam_refs:
|
111
121
|
rich.print(f" {com_param.short_name}: {com_param.value}")
|
112
122
|
|
113
123
|
|
114
|
-
def add_subparser(subparsers:
|
124
|
+
def add_subparser(subparsers: SubparsersList) -> None:
|
115
125
|
parser = subparsers.add_parser(
|
116
126
|
"list",
|
117
127
|
description="\n".join([
|
odxtools/cli/main.py
CHANGED
odxtools/cli/snoop.py
CHANGED
@@ -4,17 +4,19 @@
|
|
4
4
|
import argparse
|
5
5
|
import asyncio
|
6
6
|
import sys
|
7
|
-
from typing import Any, Type
|
7
|
+
from typing import Any, List, Optional, Type
|
8
8
|
|
9
9
|
import can
|
10
10
|
|
11
11
|
import odxtools.isotp_state_machine as ism
|
12
12
|
import odxtools.uds as uds
|
13
|
+
from odxtools.diaglayers.protocol import Protocol
|
13
14
|
from odxtools.exceptions import DecodeError
|
14
15
|
from odxtools.isotp_state_machine import IsoTpStateMachine
|
15
16
|
from odxtools.response import Response, ResponseType
|
16
17
|
|
17
18
|
from . import _parser_utils
|
19
|
+
from ._parser_utils import SubparsersList
|
18
20
|
|
19
21
|
# name of the tool
|
20
22
|
_odxtools_tool_name_ = "snoop"
|
@@ -30,6 +32,8 @@ def handle_telegram(telegram_id: int, payload: bytes) -> None:
|
|
30
32
|
global odx_diag_layer
|
31
33
|
global last_request
|
32
34
|
|
35
|
+
assert odx_diag_layer is not None
|
36
|
+
|
33
37
|
if telegram_id == ecu_tx_id:
|
34
38
|
if uds.is_response_pending(payload):
|
35
39
|
print(f" ... (response pending)")
|
@@ -209,7 +213,7 @@ def add_cli_arguments(parser: argparse.ArgumentParser) -> None:
|
|
209
213
|
_parser_utils.add_pdx_argument(parser)
|
210
214
|
|
211
215
|
|
212
|
-
def add_subparser(subparsers:
|
216
|
+
def add_subparser(subparsers: SubparsersList) -> None:
|
213
217
|
parser = subparsers.add_parser(
|
214
218
|
"snoop",
|
215
219
|
description="Live decoding of a diagnostic session.",
|
@@ -242,21 +246,43 @@ def run(args: argparse.Namespace) -> None:
|
|
242
246
|
|
243
247
|
protocol_name = args.protocol
|
244
248
|
if odx_diag_layer is not None and protocol_name is not None:
|
245
|
-
|
249
|
+
protocols: Optional[List[Protocol]] = getattr(odx_diag_layer, "protocols", None)
|
250
|
+
|
251
|
+
if protocols is None:
|
252
|
+
print(f"ECU variant {odx_diag_layer.short_name} is of type "
|
253
|
+
f"{odx_diag_layer.variant_type.value} and thus does not "
|
254
|
+
f"feature any protocols")
|
255
|
+
sys.exit(1)
|
256
|
+
|
257
|
+
protocol_names = [x.short_name for x in protocols]
|
246
258
|
if protocol_name not in protocol_names:
|
247
259
|
print(f"ECU variant {odx_diag_layer.short_name} does not support "
|
248
260
|
f"a protocol named '{protocol_name}'. Supported protocols are:")
|
249
|
-
for x in
|
261
|
+
for x in protocols:
|
250
262
|
desc = "" if x.description is None else f": {x.description}"
|
251
263
|
print(f" {x.short_name}{desc}")
|
252
264
|
sys.exit(1)
|
253
265
|
|
254
266
|
# if no can IDs have been explicitly specified, take them from the DL
|
255
267
|
if args.rx is None and odx_diag_layer:
|
256
|
-
|
268
|
+
get_can_rx_id = getattr(odx_diag_layer, "get_can_receive_id", None)
|
269
|
+
if get_can_rx_id is None:
|
270
|
+
print(f"ECU variant {odx_diag_layer.short_name} is of type "
|
271
|
+
f"{odx_diag_layer.variant_type.value} and thus does not "
|
272
|
+
f"provide any communication parameters")
|
273
|
+
sys.exit(1)
|
274
|
+
|
275
|
+
args.rx = str(get_can_rx_id(protocol=protocol_name))
|
257
276
|
|
258
277
|
if args.tx is None and odx_diag_layer:
|
259
|
-
|
278
|
+
get_can_tx_id = getattr(odx_diag_layer, "get_can_send_id", None)
|
279
|
+
if get_can_tx_id is None:
|
280
|
+
print(f"ECU variant {odx_diag_layer.short_name} is of type "
|
281
|
+
f"{odx_diag_layer.variant_type.value} and thus does not "
|
282
|
+
f"provide any communication parameters")
|
283
|
+
sys.exit(1)
|
284
|
+
|
285
|
+
args.tx = str(get_can_tx_id(protocol=protocol_name))
|
260
286
|
|
261
287
|
if args.rx is None:
|
262
288
|
print(f"Could not determine a CAN receive ID.")
|