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/browse.py
CHANGED
@@ -4,14 +4,17 @@ import logging
|
|
4
4
|
import sys
|
5
5
|
from typing import List, Optional, Union, cast
|
6
6
|
|
7
|
-
|
8
|
-
from tabulate import tabulate # TODO: switch to rich tables
|
7
|
+
import InquirerPy.prompt as IP_prompt
|
9
8
|
|
9
|
+
from ..complexdop import ComplexDop
|
10
10
|
from ..database import Database
|
11
11
|
from ..dataobjectproperty import DataObjectProperty
|
12
12
|
from ..diaglayer import DiagLayer
|
13
13
|
from ..diagservice import DiagService
|
14
|
+
from ..dopbase import DopBase
|
14
15
|
from ..exceptions import odxraise, odxrequire
|
16
|
+
from ..hierarchyelement import HierarchyElement
|
17
|
+
from ..odxlink import resolve_snref
|
15
18
|
from ..odxtypes import AtomicOdxType, DataType, ParameterValueDict
|
16
19
|
from ..parameters.matchingrequestparameter import MatchingRequestParameter
|
17
20
|
from ..parameters.parameter import Parameter
|
@@ -20,6 +23,7 @@ from ..parameters.valueparameter import ValueParameter
|
|
20
23
|
from ..request import Request
|
21
24
|
from ..response import Response
|
22
25
|
from . import _parser_utils
|
26
|
+
from ._parser_utils import SubparsersList
|
23
27
|
from ._print_utils import extract_parameter_tabulation_data
|
24
28
|
|
25
29
|
# name of the tool
|
@@ -88,13 +92,15 @@ def prompt_single_parameter_value(parameter: Parameter) -> Optional[AtomicOdxTyp
|
|
88
92
|
# else _convert_string_to_odx_type(x, p.physical_type.base_data_type, param=p) # This does not work because the next parameter to be promted is used (for some reason?)
|
89
93
|
}]
|
90
94
|
|
91
|
-
if
|
92
|
-
|
93
|
-
scales =
|
95
|
+
if (dop := getattr(parameter, "dop", None)) and \
|
96
|
+
(compu_method := getattr(dop, "compu_method", None)):
|
97
|
+
scales = compu_method.internal_to_phys
|
94
98
|
choices = [scale.compu_const for scale in scales if scale is not None]
|
99
|
+
if (cdv := compu_method.compu_default_value) is not None:
|
100
|
+
choices.append(cdv.compu_const)
|
95
101
|
param_prompt[0]["choices"] = choices
|
96
102
|
|
97
|
-
answer =
|
103
|
+
answer = IP_prompt(param_prompt)
|
98
104
|
if answer.get(parameter.short_name) == "" and not parameter.is_required:
|
99
105
|
return None
|
100
106
|
elif parameter.physical_type.base_data_type is not None:
|
@@ -104,26 +110,47 @@ def prompt_single_parameter_value(parameter: Parameter) -> Optional[AtomicOdxTyp
|
|
104
110
|
logging.warning(
|
105
111
|
f"Parameter {parameter.short_name} does not have a physical data type. Param details: {parameter}"
|
106
112
|
)
|
107
|
-
return answer.get(parameter.short_name)
|
113
|
+
return cast(str, answer.get(parameter.short_name))
|
108
114
|
|
109
115
|
|
110
|
-
def encode_message_interactively(
|
116
|
+
def encode_message_interactively(codec: Union[Request, Response],
|
111
117
|
ask_user_confirmation: bool = False) -> None:
|
112
|
-
if
|
118
|
+
if sys.__stdin__ is None or sys.__stdout__ is None or not sys.__stdin__.isatty(
|
119
|
+
) or not sys.__stdout__.isatty():
|
113
120
|
raise SystemError("This command can only be used in an interactive shell!")
|
114
|
-
param_dict = sub_service.parameter_dict()
|
115
121
|
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
122
|
+
answered_request = b''
|
123
|
+
if isinstance(codec, Response):
|
124
|
+
answered_request_prompt = [{
|
125
|
+
"type":
|
126
|
+
"input",
|
127
|
+
"name":
|
128
|
+
"request",
|
129
|
+
"message":
|
130
|
+
f"What is the request you want to answer? (Enter the coded request as integer in hexadecimal format (e.g. 12 3B 5)",
|
131
|
+
"filter":
|
132
|
+
lambda input: _convert_string_to_bytes(input),
|
133
|
+
}]
|
134
|
+
answer = IP_prompt(answered_request_prompt)
|
135
|
+
answered_request = cast(bytes, answer.get("request"))
|
136
|
+
print(f"Input interpretation as list: {list(answered_request)}")
|
137
|
+
|
138
|
+
has_settable_param = False
|
139
|
+
for param in codec.parameters:
|
140
|
+
if not param.is_settable:
|
141
|
+
continue
|
142
|
+
|
143
|
+
# TODO: Specifying complex parameters with nesting depth > 1
|
144
|
+
# is not possible yet
|
145
|
+
if (inner_params := getattr(getattr(param, "dop", None), "parameters", None)) is not None:
|
146
|
+
for inner_param in inner_params:
|
147
|
+
if inner_param.is_settable:
|
148
|
+
has_settable_param = True
|
149
|
+
elif param.is_settable:
|
150
|
+
has_settable_param = True
|
124
151
|
|
125
152
|
param_values: ParameterValueDict = {}
|
126
|
-
if
|
153
|
+
if has_settable_param:
|
127
154
|
# Ask whether user wants to encode a message
|
128
155
|
if ask_user_confirmation:
|
129
156
|
encode_message_prompt = [{
|
@@ -132,51 +159,44 @@ def encode_message_interactively(sub_service: Union[Request, Response],
|
|
132
159
|
"message": f"Do you want to encode a message? [y/n]",
|
133
160
|
"choices": ["yes", "no"],
|
134
161
|
}]
|
135
|
-
answer =
|
162
|
+
answer = IP_prompt(encode_message_prompt)
|
136
163
|
if answer.get("yes_no_prompt") == "no":
|
137
164
|
return
|
138
165
|
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
"filter":
|
148
|
-
lambda input: _convert_string_to_bytes(input),
|
149
|
-
}]
|
150
|
-
answer = PI_prompt(answered_request_prompt)
|
151
|
-
answered_request = cast(bytes, answer.get("request"))
|
152
|
-
print(f"Input interpretation as list: {list(answered_request)}")
|
153
|
-
|
154
|
-
# Request values for parameters
|
155
|
-
for key, param_or_structure in param_dict.items():
|
156
|
-
if isinstance(param_or_structure, dict):
|
157
|
-
# param_or_structure refers to a structure (represented as dict of params)
|
166
|
+
# Query user for the values of all settable parameters
|
167
|
+
for param in codec.parameters:
|
168
|
+
if (inner_params := getattr(dop := getattr(param, "dop", None), "parameters",
|
169
|
+
None)) is not None:
|
170
|
+
assert isinstance(dop, DopBase)
|
171
|
+
inner_params = cast(List[Parameter], inner_params)
|
172
|
+
# param refers to a complex DOP, i.e., the required
|
173
|
+
# value is a key-value dict
|
158
174
|
print(
|
159
|
-
f"The next {len(
|
175
|
+
f"The next {len(inner_params)} parameters belong to the structure '{dop.short_name}'"
|
160
176
|
)
|
161
177
|
structure_param_values: ParameterValueDict = {}
|
162
|
-
for
|
163
|
-
if
|
164
|
-
val = prompt_single_parameter_value(
|
178
|
+
for inner_param in inner_params:
|
179
|
+
if inner_param.is_settable:
|
180
|
+
val = prompt_single_parameter_value(inner_param)
|
165
181
|
if val is not None:
|
166
|
-
structure_param_values[
|
167
|
-
param_values[
|
168
|
-
elif
|
169
|
-
|
170
|
-
val = prompt_single_parameter_value(param_or_structure)
|
182
|
+
structure_param_values[inner_param.short_name] = val
|
183
|
+
param_values[param.short_name] = structure_param_values
|
184
|
+
elif param.is_settable:
|
185
|
+
val = prompt_single_parameter_value(param)
|
171
186
|
if val is not None:
|
172
|
-
param_values[
|
173
|
-
|
174
|
-
|
187
|
+
param_values[param.short_name] = val
|
188
|
+
|
189
|
+
if isinstance(codec, Response):
|
190
|
+
payload = codec.encode(coded_request=answered_request, **param_values)
|
175
191
|
else:
|
176
|
-
payload =
|
192
|
+
payload = codec.encode(coded_request=b'', **param_values)
|
177
193
|
else:
|
178
|
-
# There are no
|
179
|
-
|
194
|
+
# There are no settable parameters -> Just print message
|
195
|
+
if isinstance(codec, Response):
|
196
|
+
payload = codec.encode(coded_request=answered_request)
|
197
|
+
else:
|
198
|
+
payload = codec.encode()
|
199
|
+
|
180
200
|
print(f"Message payload: 0x{bytes(payload).hex()}")
|
181
201
|
|
182
202
|
|
@@ -187,56 +207,58 @@ def encode_message_from_string_values(
|
|
187
207
|
if parameter_values is None:
|
188
208
|
parameter_values = {}
|
189
209
|
parameter_values = parameter_values.copy()
|
190
|
-
param_dict = sub_service.parameter_dict()
|
191
210
|
|
192
|
-
# Check if all needed parameters
|
211
|
+
# Check if all needed parameters have been specified
|
193
212
|
missing_parameter_names = []
|
194
|
-
for
|
195
|
-
if
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
213
|
+
for param in sub_service.parameters:
|
214
|
+
if (inner_params := getattr(dop := getattr(param, "dop", None), "parameters",
|
215
|
+
None)) is not None:
|
216
|
+
inner_param_values = parameter_values.get(param.short_name, {})
|
217
|
+
if not isinstance(inner_param_values, dict):
|
218
|
+
print(f"Value for composite parameter {param.short_name} must be "
|
219
|
+
f"a dictionary, got {type(inner_param_values).__name__}")
|
220
|
+
continue
|
221
|
+
for inner_param in inner_params:
|
222
|
+
if inner_param.is_required and inner_param.short_name not in inner_param_values:
|
223
|
+
missing_parameter_names.append(f"{param.short_name}.{inner_param.short_name}")
|
204
224
|
else:
|
205
|
-
if param.is_required and parameter_values.get(
|
206
|
-
missing_parameter_names.append(
|
225
|
+
if param.is_required and parameter_values.get(param.short_name) is None:
|
226
|
+
missing_parameter_names.append(param.short_name)
|
207
227
|
|
208
228
|
if len(missing_parameter_names) > 0:
|
209
|
-
print("The following parameters are required but missing
|
210
|
-
print(" - " + "\n - ".join(missing_parameter_names))
|
229
|
+
print("The following parameters are required but missing:")
|
230
|
+
print(" - " + "\n - ".join(sorted(missing_parameter_names)))
|
211
231
|
return
|
212
232
|
|
213
233
|
# Request values for parameters
|
214
234
|
for parameter_sn, parameter_value in parameter_values.items():
|
215
|
-
parameter =
|
235
|
+
parameter = resolve_snref(parameter_sn, sub_service.parameters, Parameter)
|
216
236
|
if parameter is None:
|
217
237
|
print(f"I don't know the parameter {parameter_sn}")
|
218
238
|
continue
|
219
239
|
|
220
240
|
if isinstance(parameter_value, dict):
|
221
241
|
# parameter_value refers to a structure (represented as dict of params)
|
242
|
+
dop = getattr(parameter, "dop", None)
|
243
|
+
inner_params = getattr(dop, "parameters", None)
|
244
|
+
assert isinstance(dop, ComplexDop)
|
245
|
+
assert isinstance(inner_params, list)
|
246
|
+
inner_params = cast(List[Parameter], inner_params)
|
247
|
+
|
222
248
|
typed_dict = parameter_value.copy()
|
223
|
-
for
|
224
|
-
|
225
|
-
if
|
226
|
-
print(f"Unknown sub-parameter {
|
249
|
+
for inner_param_sn, inner_param_value in parameter_value.items():
|
250
|
+
inner_param = resolve_snref(inner_param_sn, inner_params, Parameter)
|
251
|
+
if inner_param is None:
|
252
|
+
print(f"Unknown sub-parameter {inner_param_sn}")
|
227
253
|
continue
|
228
|
-
if not isinstance(
|
229
|
-
print(f"The value specified for parameter {
|
254
|
+
if not isinstance(inner_param_value, str):
|
255
|
+
print(f"The value specified for parameter {inner_param_sn} is not a string")
|
230
256
|
continue
|
231
257
|
|
232
|
-
typed_dict[
|
233
|
-
|
234
|
-
|
235
|
-
)
|
236
|
-
parameter_values[parameter_sn] = typed_dict
|
258
|
+
typed_dict[inner_param_sn] = _convert_string_to_odx_type(
|
259
|
+
inner_param_value, inner_param.physical_type.base_data_type)
|
260
|
+
parameter_values[parameter.short_name] = typed_dict
|
237
261
|
else:
|
238
|
-
assert isinstance(parameter, Parameter)
|
239
|
-
|
240
262
|
if not isinstance(parameter_value, str):
|
241
263
|
print(f"Value for parameter {parameter_sn} is not a string")
|
242
264
|
continue
|
@@ -250,12 +272,14 @@ def encode_message_from_string_values(
|
|
250
272
|
parameter_values[parameter_sn] = _convert_string_to_odx_type(
|
251
273
|
parameter_value, DataType.A_BYTEFIELD)
|
252
274
|
|
253
|
-
payload = sub_service.encode(**parameter_values)
|
275
|
+
payload = sub_service.encode(coded_request=b'\xff' * 100, **parameter_values)
|
276
|
+
|
254
277
|
print(f"Message payload: 0x{bytes(payload).hex()}")
|
255
278
|
|
256
279
|
|
257
280
|
def browse(odxdb: Database) -> None:
|
258
|
-
if
|
281
|
+
if sys.__stdin__ is None or sys.__stdout__ is None or not sys.__stdin__.isatty(
|
282
|
+
) or not sys.__stdout__.isatty():
|
259
283
|
raise SystemError("This command can only be used in an interactive shell!")
|
260
284
|
dl_names = [dl.short_name for dl in odxdb.diag_layers]
|
261
285
|
while True:
|
@@ -266,7 +290,7 @@ def browse(odxdb: Database) -> None:
|
|
266
290
|
"message": "Select a Variant.",
|
267
291
|
"choices": list(dl_names) + ["[exit]"],
|
268
292
|
}]
|
269
|
-
answer =
|
293
|
+
answer = IP_prompt(selection)
|
270
294
|
if answer.get("variant") == "[exit]":
|
271
295
|
return
|
272
296
|
|
@@ -276,19 +300,20 @@ def browse(odxdb: Database) -> None:
|
|
276
300
|
print(f"{type(answer.get('variant'))=}")
|
277
301
|
assert isinstance(variant, DiagLayer)
|
278
302
|
|
279
|
-
if (
|
280
|
-
|
281
|
-
|
282
|
-
|
303
|
+
if isinstance(variant, HierarchyElement):
|
304
|
+
if (rx_id := variant.get_receive_id()) is not None:
|
305
|
+
recv_id = hex(rx_id)
|
306
|
+
else:
|
307
|
+
recv_id = "None"
|
283
308
|
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
309
|
+
if (tx_id := variant.get_send_id()) is not None:
|
310
|
+
send_id = hex(tx_id)
|
311
|
+
else:
|
312
|
+
send_id = "None"
|
288
313
|
|
289
|
-
|
290
|
-
|
291
|
-
|
314
|
+
print(
|
315
|
+
f"{variant.variant_type.value} '{variant.short_name}' (Receive ID: {recv_id}, Send ID: {send_id})"
|
316
|
+
)
|
292
317
|
|
293
318
|
while True:
|
294
319
|
services: List[DiagService] = [
|
@@ -304,7 +329,7 @@ def browse(odxdb: Database) -> None:
|
|
304
329
|
f"The variant {variant.short_name} offers the following services. Select one!",
|
305
330
|
"choices": [s.short_name for s in services] + ["[back]"],
|
306
331
|
}]
|
307
|
-
answer =
|
332
|
+
answer = IP_prompt(selection)
|
308
333
|
if answer.get("service") == "[back]":
|
309
334
|
break
|
310
335
|
|
@@ -339,7 +364,7 @@ def browse(odxdb: Database) -> None:
|
|
339
364
|
"short": f"Negative response: {nr.short_name}",
|
340
365
|
} for nr in service.negative_responses] + ["[back]"], # type: ignore
|
341
366
|
}]
|
342
|
-
answer =
|
367
|
+
answer = IP_prompt(selection)
|
343
368
|
if answer.get("message_type") == "[back]":
|
344
369
|
continue
|
345
370
|
|
@@ -347,13 +372,12 @@ def browse(odxdb: Database) -> None:
|
|
347
372
|
if codec is not None:
|
348
373
|
assert isinstance(codec, (Request, Response))
|
349
374
|
table = extract_parameter_tabulation_data(codec.parameters)
|
350
|
-
|
351
|
-
print(table_str)
|
375
|
+
print(table)
|
352
376
|
|
353
377
|
encode_message_interactively(codec, ask_user_confirmation=True)
|
354
378
|
|
355
379
|
|
356
|
-
def add_subparser(subparsers:
|
380
|
+
def add_subparser(subparsers: SubparsersList) -> None:
|
357
381
|
# Browse interactively to avoid spamming the console.
|
358
382
|
parser = subparsers.add_parser(
|
359
383
|
"browse",
|