odxtools 10.3.0__py3-none-any.whl → 10.4.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/database.py CHANGED
@@ -21,6 +21,7 @@ from .diaglayers.protocol import Protocol
21
21
  from .ecuconfig import EcuConfig
22
22
  from .exceptions import odxraise, odxrequire
23
23
  from .flash import Flash
24
+ from .multipleecujobspec import MultipleEcuJobSpec
24
25
  from .nameditemlist import NamedItemList
25
26
  from .odxdoccontext import OdxDocContext
26
27
  from .odxlink import DocType, OdxDocFragment, OdxLinkDatabase, OdxLinkId
@@ -43,6 +44,7 @@ class Database:
43
44
  self._comparam_specs = NamedItemList[ComparamSpec]()
44
45
  self._ecu_configs = NamedItemList[EcuConfig]()
45
46
  self._flashs = NamedItemList[Flash]()
47
+ self._multiple_ecu_job_specs = NamedItemList[MultipleEcuJobSpec]()
46
48
  self._short_name = "odx_database"
47
49
 
48
50
  def add_pdx_file(self, pdx_file: Union[str, "PathLike[Any]", IO[bytes], ZipFile]) -> None:
@@ -123,6 +125,10 @@ class Database:
123
125
  elif category_tag == "FLASH":
124
126
  context = OdxDocContext(model_version, (OdxDocFragment(category_sn, DocType.FLASH),))
125
127
  self._flashs.append(Flash.from_et(category_et, context))
128
+ elif category_tag == "MULTIPLE-ECU-JOB-SPEC":
129
+ context = OdxDocContext(model_version,
130
+ (OdxDocFragment(category_sn, DocType.MULTIPLE_ECU_JOB_SPEC),))
131
+ self._multiple_ecu_job_specs.append(MultipleEcuJobSpec.from_et(category_et, context))
126
132
 
127
133
  def refresh(self) -> None:
128
134
  # Create wrapper objects
@@ -160,6 +166,9 @@ class Database:
160
166
  for flash in self.flashs:
161
167
  flash._resolve_odxlinks(self._odxlinks)
162
168
 
169
+ for multiple_ecu_job_spec in self.multiple_ecu_job_specs:
170
+ multiple_ecu_job_spec._resolve_odxlinks(self._odxlinks)
171
+
163
172
  # resolve short name references for containers which do not do
164
173
  # inheritance (we can call directly call _resolve_snrefs())
165
174
  context = SnRefContext()
@@ -176,6 +185,8 @@ class Database:
176
185
  ecu_config._finalize_init(self, self._odxlinks)
177
186
  for flash in self.flashs:
178
187
  flash._finalize_init(self, self._odxlinks)
188
+ for multiple_ecu_job_spec in self.multiple_ecu_job_specs:
189
+ multiple_ecu_job_spec._finalize_init(self, self._odxlinks)
179
190
 
180
191
  for subset in self.comparam_subsets:
181
192
  subset._resolve_snrefs(context)
@@ -187,6 +198,8 @@ class Database:
187
198
  ecu_config._resolve_snrefs(context)
188
199
  for flash in self.flashs:
189
200
  flash._resolve_snrefs(context)
201
+ for multiple_ecu_job_spec in self.multiple_ecu_job_specs:
202
+ multiple_ecu_job_spec._resolve_snrefs(context)
190
203
 
191
204
  def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
192
205
  result: dict[OdxLinkId, Any] = {}
@@ -205,6 +218,8 @@ class Database:
205
218
 
206
219
  for flash in self.flashs:
207
220
  result.update(flash._build_odxlinks())
221
+ for multiple_ecu_job_spec in self.multiple_ecu_job_specs:
222
+ result.update(multiple_ecu_job_spec._build_odxlinks())
208
223
 
209
224
  return result
210
225
 
@@ -287,6 +302,10 @@ class Database:
287
302
  def flashs(self) -> NamedItemList[Flash]:
288
303
  return self._flashs
289
304
 
305
+ @property
306
+ def multiple_ecu_job_specs(self) -> NamedItemList[MultipleEcuJobSpec]:
307
+ return self._multiple_ecu_job_specs
308
+
290
309
  def __repr__(self) -> str:
291
310
  return f"Database(model_version={self.model_version}, " \
292
311
  f"protocols={[x.short_name for x in self.protocols]}, " \
@@ -98,14 +98,7 @@ class DiagLayer:
98
98
  if self.import_refs:
99
99
  imported_links: dict[OdxLinkId, Any] = {}
100
100
  for import_ref in self.import_refs:
101
- imported_dl = odxlinks.resolve(import_ref, DiagLayer)
102
-
103
- odxassert(
104
- imported_dl.variant_type == DiagLayerType.ECU_SHARED_DATA,
105
- f"Tried to import references from diagnostic layer "
106
- f"'{imported_dl.short_name}' of type {imported_dl.variant_type.value}. "
107
- f"Only ECU-SHARED-DATA layers may be referenced using the "
108
- f"IMPORT-REF mechanism")
101
+ imported_dl = odxlinks.resolve(import_ref)
109
102
 
110
103
  # TODO: ensure that the imported diagnostic layer has
111
104
  # not been referenced in any PARENT-REF of the current
@@ -0,0 +1,178 @@
1
+ # SPDX-License-Identifier: MIT
2
+ from dataclasses import dataclass, field
3
+ from typing import Any
4
+ from xml.etree import ElementTree
5
+
6
+ from .admindata import AdminData
7
+ from .audience import Audience
8
+ from .diaglayers.diaglayer import DiagLayer
9
+ from .element import IdentifiableElement
10
+ from .exceptions import odxrequire
11
+ from .functionalclass import FunctionalClass
12
+ from .inputparam import InputParam
13
+ from .nameditemlist import NamedItemList
14
+ from .negoutputparam import NegOutputParam
15
+ from .odxdoccontext import OdxDocContext
16
+ from .odxlink import OdxLinkDatabase, OdxLinkId, OdxLinkRef
17
+ from .odxtypes import odxstr_to_bool
18
+ from .outputparam import OutputParam
19
+ from .progcode import ProgCode
20
+ from .snrefcontext import SnRefContext
21
+ from .specialdatagroup import SpecialDataGroup
22
+ from .utils import dataclass_fields_asdict
23
+
24
+
25
+ @dataclass(kw_only=True)
26
+ class MultipleEcuJob(IdentifiableElement):
27
+ """A multiple ECU job is a diagnostic communication primitive.
28
+
29
+ A multiple ECU job is more complex than a diagnostic service and is
30
+ not provided natively by the ECU. In particular, the job is
31
+ defined in external programs which are referenced by the attribute
32
+ `.prog_codes`.
33
+
34
+ In contrast to "single ECU jobs", a multiple ECU job only involves
35
+ calls to services provided by more than one ECU.
36
+
37
+ Multiple ECU jobs are defined in section 7.3.11 of the ASAM MCD-2
38
+ standard.
39
+ """
40
+
41
+ admin_data: AdminData | None = None
42
+ sdgs: list[SpecialDataGroup] = field(default_factory=list)
43
+ functional_class_refs: list[OdxLinkRef] = field(default_factory=list)
44
+ prog_codes: list[ProgCode] = field(default_factory=list)
45
+ input_params: NamedItemList[InputParam] = field(default_factory=NamedItemList)
46
+ output_params: NamedItemList[OutputParam] = field(default_factory=NamedItemList)
47
+ neg_output_params: NamedItemList[NegOutputParam] = field(default_factory=NamedItemList)
48
+ diag_layer_refs: list[OdxLinkRef] = field(default_factory=list)
49
+ audience: Audience | None = None
50
+ semantic: str | None = None
51
+ is_executable_raw: bool | None = None
52
+
53
+ @property
54
+ def functional_classes(self) -> NamedItemList[FunctionalClass]:
55
+ return self._functional_classes
56
+
57
+ @property
58
+ def diag_layers(self) -> NamedItemList[DiagLayer]:
59
+ return self._diag_layers
60
+
61
+ @property
62
+ def is_executable(self) -> bool:
63
+ return self.is_executable_raw in (True, None)
64
+
65
+ @staticmethod
66
+ def from_et(et_element: ElementTree.Element, context: OdxDocContext) -> "MultipleEcuJob":
67
+ kwargs = dataclass_fields_asdict(IdentifiableElement.from_et(et_element, context))
68
+
69
+ admin_data = None
70
+ if (admin_data_elem := et_element.find("ADMIN-DATA")) is not None:
71
+ admin_data = AdminData.from_et(admin_data_elem, context)
72
+ sdgs = [SpecialDataGroup.from_et(sdge, context) for sdge in et_element.iterfind("SDGS/SDG")]
73
+ functional_class_refs = [
74
+ odxrequire(OdxLinkRef.from_et(el, context))
75
+ for el in et_element.iterfind("FUNCT-CLASS-REFS/FUNCT-CLASS-REF")
76
+ ]
77
+ prog_codes = [
78
+ ProgCode.from_et(pc_elem, context)
79
+ for pc_elem in et_element.iterfind("PROG-CODES/PROG-CODE")
80
+ ]
81
+
82
+ input_params = NamedItemList([
83
+ InputParam.from_et(el, context)
84
+ for el in et_element.iterfind("INPUT-PARAMS/INPUT-PARAM")
85
+ ])
86
+ output_params = NamedItemList([
87
+ OutputParam.from_et(el, context)
88
+ for el in et_element.iterfind("OUTPUT-PARAMS/OUTPUT-PARAM")
89
+ ])
90
+ neg_output_params = NamedItemList([
91
+ NegOutputParam.from_et(el, context)
92
+ for el in et_element.iterfind("NEG-OUTPUT-PARAMS/NEG-OUTPUT-PARAM")
93
+ ])
94
+ diag_layer_refs = [
95
+ odxrequire(OdxLinkRef.from_et(el, context))
96
+ for el in et_element.iterfind("DIAG-LAYER-REFS/DIAG-LAYER-REF")
97
+ ]
98
+ audience = None
99
+ if (aud_elem := et_element.find("AUDIENCE")) is not None:
100
+ audience = Audience.from_et(aud_elem, context)
101
+
102
+ semantic = et_element.attrib.get("SEMANTIC")
103
+ is_executable_raw = odxstr_to_bool(et_element.attrib.get("IS-EXECUTABLE"))
104
+
105
+ return MultipleEcuJob(
106
+ admin_data=admin_data,
107
+ sdgs=sdgs,
108
+ functional_class_refs=functional_class_refs,
109
+ prog_codes=prog_codes,
110
+ input_params=input_params,
111
+ output_params=output_params,
112
+ neg_output_params=neg_output_params,
113
+ diag_layer_refs=diag_layer_refs,
114
+ audience=audience,
115
+ semantic=semantic,
116
+ is_executable_raw=is_executable_raw,
117
+ **kwargs)
118
+
119
+ def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
120
+ result = {self.odx_id: self}
121
+
122
+ if self.admin_data is not None:
123
+ result.update(self.admin_data._build_odxlinks())
124
+ for sdg in self.sdgs:
125
+ result.update(sdg._build_odxlinks())
126
+ for prog_code in self.prog_codes:
127
+ result.update(prog_code._build_odxlinks())
128
+ for input_param in self.input_params:
129
+ result.update(input_param._build_odxlinks())
130
+ for output_param in self.output_params:
131
+ result.update(output_param._build_odxlinks())
132
+ for neg_output_param in self.neg_output_params:
133
+ result.update(neg_output_param._build_odxlinks())
134
+ if self.audience is not None:
135
+ result.update(self.audience._build_odxlinks())
136
+
137
+ return result
138
+
139
+ def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
140
+ if self.admin_data is not None:
141
+ self.admin_data._resolve_odxlinks(odxlinks)
142
+ for sdg in self.sdgs:
143
+ sdg._resolve_odxlinks(odxlinks)
144
+ for prog_code in self.prog_codes:
145
+ prog_code._resolve_odxlinks(odxlinks)
146
+ for input_param in self.input_params:
147
+ input_param._resolve_odxlinks(odxlinks)
148
+ for output_param in self.output_params:
149
+ output_param._resolve_odxlinks(odxlinks)
150
+ for neg_output_param in self.neg_output_params:
151
+ neg_output_param._resolve_odxlinks(odxlinks)
152
+ if self.audience is not None:
153
+ self.audience._resolve_odxlinks(odxlinks)
154
+
155
+ self._functional_classes = NamedItemList(
156
+ [odxlinks.resolve(fc_ref, FunctionalClass) for fc_ref in self.functional_class_refs])
157
+ self._diag_layers = NamedItemList(
158
+ [odxlinks.resolve(dl_ref, DiagLayer) for dl_ref in self.diag_layer_refs])
159
+
160
+ def _resolve_snrefs(self, context: SnRefContext) -> None:
161
+ context.multiple_ecu_job = self
162
+
163
+ if self.admin_data is not None:
164
+ self.admin_data._resolve_snrefs(context)
165
+ for sdg in self.sdgs:
166
+ sdg._resolve_snrefs(context)
167
+ for prog_code in self.prog_codes:
168
+ prog_code._resolve_snrefs(context)
169
+ for input_param in self.input_params:
170
+ input_param._resolve_snrefs(context)
171
+ for output_param in self.output_params:
172
+ output_param._resolve_snrefs(context)
173
+ for neg_output_param in self.neg_output_params:
174
+ neg_output_param._resolve_snrefs(context)
175
+ if self.audience is not None:
176
+ self.audience._resolve_snrefs(context)
177
+
178
+ context.multiple_ecu_job = None
@@ -0,0 +1,142 @@
1
+ # SPDX-License-Identifier: MIT
2
+ from copy import copy
3
+ from dataclasses import dataclass, field
4
+ from typing import TYPE_CHECKING, Any
5
+ from xml.etree import ElementTree
6
+
7
+ from .additionalaudience import AdditionalAudience
8
+ from .diagdatadictionaryspec import DiagDataDictionarySpec
9
+ from .diaglayers.ecushareddata import EcuSharedData
10
+ from .functionalclass import FunctionalClass
11
+ from .multipleecujob import MultipleEcuJob
12
+ from .nameditemlist import NamedItemList
13
+ from .odxcategory import OdxCategory
14
+ from .odxdoccontext import OdxDocContext
15
+ from .odxlink import OdxLinkDatabase, OdxLinkId, OdxLinkRef
16
+ from .snrefcontext import SnRefContext
17
+ from .utils import dataclass_fields_asdict
18
+
19
+ if TYPE_CHECKING:
20
+ from .database import Database
21
+
22
+
23
+ @dataclass(kw_only=True)
24
+ class MultipleEcuJobSpec(OdxCategory):
25
+ multiple_ecu_jobs: NamedItemList[MultipleEcuJob] = field(default_factory=NamedItemList)
26
+ diag_data_dictionary_spec: DiagDataDictionarySpec | None = None
27
+ functional_classes: NamedItemList[FunctionalClass] = field(default_factory=NamedItemList)
28
+ additional_audiences: NamedItemList[AdditionalAudience] = field(default_factory=NamedItemList)
29
+ import_refs: list[OdxLinkRef] = field(default_factory=list)
30
+
31
+ @property
32
+ def imported_layers(self) -> NamedItemList[EcuSharedData]:
33
+ """The resolved IMPORT-REFs
34
+
35
+ ODXLINK defined by ECU-SHARED-DATA layers referenced via
36
+ IMPORT-REF ought to be treated as if they where defined
37
+ locally.
38
+ """
39
+ return self._imported_layers
40
+
41
+ @staticmethod
42
+ def from_et(et_element: ElementTree.Element, context: OdxDocContext) -> "MultipleEcuJobSpec":
43
+
44
+ base_obj = OdxCategory.from_et(et_element, context)
45
+ kwargs = dataclass_fields_asdict(base_obj)
46
+
47
+ multiple_ecu_jobs = NamedItemList([
48
+ MultipleEcuJob.from_et(el, context)
49
+ for el in et_element.iterfind("MULTIPLE-ECU-JOBS/MULTIPLE-ECU-JOB")
50
+ ])
51
+ diag_data_dictionary_spec = None
52
+ if (ddds_elem := et_element.find("DIAG-DATA-DICTIONARY-SPEC")) is not None:
53
+ diag_data_dictionary_spec = DiagDataDictionarySpec.from_et(ddds_elem, context)
54
+ functional_classes = NamedItemList([
55
+ FunctionalClass.from_et(el, context)
56
+ for el in et_element.iterfind("FUNCT-CLASSS/FUNCT-CLASS")
57
+ ])
58
+ additional_audiences = NamedItemList([
59
+ AdditionalAudience.from_et(el, context)
60
+ for el in et_element.iterfind("ADDITIONAL-AUDIENCES/ADDITIONAL-AUDIENCE")
61
+ ])
62
+ import_refs = [
63
+ OdxLinkRef.from_et(el, context) for el in et_element.iterfind("IMPORT-REFS/IMPORT-REF")
64
+ ]
65
+
66
+ return MultipleEcuJobSpec(
67
+ multiple_ecu_jobs=multiple_ecu_jobs,
68
+ diag_data_dictionary_spec=diag_data_dictionary_spec,
69
+ functional_classes=functional_classes,
70
+ additional_audiences=additional_audiences,
71
+ import_refs=import_refs,
72
+ **kwargs)
73
+
74
+ def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
75
+ odxlinks = super()._build_odxlinks()
76
+
77
+ for multiple_ecu_job in self.multiple_ecu_jobs:
78
+ odxlinks.update(multiple_ecu_job._build_odxlinks())
79
+
80
+ if self.diag_data_dictionary_spec is not None:
81
+ odxlinks.update(self.diag_data_dictionary_spec._build_odxlinks())
82
+
83
+ for functional_class in self.functional_classes:
84
+ odxlinks.update(functional_class._build_odxlinks())
85
+
86
+ for additional_audience in self.additional_audiences:
87
+ odxlinks.update(additional_audience._build_odxlinks())
88
+
89
+ return odxlinks
90
+
91
+ def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
92
+ # deal with the import refs: IDs defined therein are to be
93
+ # handled like they were local.
94
+ self._imported_layers: NamedItemList[EcuSharedData] = NamedItemList()
95
+ if self.import_refs:
96
+ extended_odxlinks = copy(odxlinks)
97
+ imported_links: dict[OdxLinkId, Any] = {}
98
+ for import_ref in self.import_refs:
99
+ imported_dl = odxlinks.resolve(import_ref, EcuSharedData)
100
+ self._imported_layers.append(imported_dl)
101
+
102
+ # replace the document fragments of the ODX id with
103
+ # the those of the muliple-ecu-spec. (be aware that
104
+ # the "original" locations are still available.)
105
+ imported_dl_links = imported_dl._build_odxlinks()
106
+ for link_id, obj in imported_dl_links.items():
107
+ link_id = OdxLinkId(link_id.local_id, self.odx_id.doc_fragments)
108
+ imported_links[link_id] = obj
109
+
110
+ extended_odxlinks.update(imported_links, overwrite=False)
111
+ else:
112
+ extended_odxlinks = odxlinks
113
+
114
+ for multiple_ecu_job in self.multiple_ecu_jobs:
115
+ multiple_ecu_job._resolve_odxlinks(extended_odxlinks)
116
+
117
+ if self.diag_data_dictionary_spec is not None:
118
+ self.diag_data_dictionary_spec._resolve_odxlinks(extended_odxlinks)
119
+
120
+ for functional_class in self.functional_classes:
121
+ functional_class._resolve_odxlinks(extended_odxlinks)
122
+
123
+ for additional_audiences in self.additional_audiences:
124
+ additional_audiences._resolve_odxlinks(extended_odxlinks)
125
+
126
+ def _finalize_init(self, database: "Database", odxlinks: OdxLinkDatabase) -> None:
127
+ super()._finalize_init(database, odxlinks)
128
+
129
+ def _resolve_snrefs(self, context: SnRefContext) -> None:
130
+ super()._resolve_snrefs(context)
131
+
132
+ for multiple_ecu_job in self.multiple_ecu_jobs:
133
+ multiple_ecu_job._resolve_snrefs(context)
134
+
135
+ if self.diag_data_dictionary_spec is not None:
136
+ self.diag_data_dictionary_spec._resolve_snrefs(context)
137
+
138
+ for functional_class in self.functional_classes:
139
+ functional_class._resolve_snrefs(context)
140
+
141
+ for additional_audiences in self.additional_audiences:
142
+ additional_audiences._resolve_snrefs(context)
odxtools/outputparam.py CHANGED
@@ -38,7 +38,7 @@ class OutputParam(IdentifiableElement):
38
38
  return OutputParam(dop_base_ref=dop_base_ref, semantic=semantic, **kwargs)
39
39
 
40
40
  def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
41
- return {}
41
+ return {self.odx_id: self}
42
42
 
43
43
  def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
44
44
  self._dop = odxlinks.resolve(self.dop_base_ref, DopBase)
odxtools/snrefcontext.py CHANGED
@@ -6,6 +6,7 @@ if TYPE_CHECKING:
6
6
  from .database import Database
7
7
  from .diaglayers.diaglayer import DiagLayer
8
8
  from .diagservice import DiagService
9
+ from .multipleecujob import MultipleEcuJob
9
10
  from .parameters.parameter import Parameter
10
11
  from .request import Request
11
12
  from .response import Response
@@ -23,6 +24,7 @@ class SnRefContext:
23
24
  diag_layer: Optional["DiagLayer"] = None
24
25
  diag_service: Optional["DiagService"] = None
25
26
  single_ecu_job: Optional["SingleEcuJob"] = None
27
+ multiple_ecu_job: Optional["MultipleEcuJob"] = None
26
28
  request: Optional["Request"] = None
27
29
  response: Optional["Response"] = None
28
30
  parameters: list["Parameter"] | None = None
@@ -26,7 +26,7 @@
26
26
  {%- endfor %}
27
27
  </COMPANY-DOC-INFOS>
28
28
  {%- endif %}
29
- {%- if admin_data.doc_revisions is not none %}
29
+ {%- if admin_data.doc_revisions %}
30
30
  <DOC-REVISIONS>
31
31
  {%- for doc_revision in admin_data.doc_revisions %}
32
32
  <DOC-REVISION>
@@ -0,0 +1,107 @@
1
+ {#- -*- mode: sgml; tab-width: 1; indent-tabs-mode: nil -*-
2
+ #
3
+ # SPDX-License-Identifier: MIT
4
+ -#}
5
+
6
+ {%- import('macros/printAdminData.xml.jinja2') as pad %}
7
+ {%- import('macros/printDOP.xml.jinja2') as pdop %}
8
+ {%- import('macros/printTable.xml.jinja2') as pt %}
9
+ {%- import('macros/printStructure.xml.jinja2') as pst %}
10
+ {%- import('macros/printEndOfPdu.xml.jinja2') as peopdu %}
11
+ {%- import('macros/printStaticField.xml.jinja2') as psf %}
12
+ {%- import('macros/printDynamicLengthField.xml.jinja2') as pdlf %}
13
+ {%- import('macros/printDynamicEndmarkerField.xml.jinja2') as pdemf %}
14
+ {%- import('macros/printMux.xml.jinja2') as pm %}
15
+ {%- import('macros/printEnvData.xml.jinja2') as ped %}
16
+ {%- import('macros/printEnvDataDesc.xml.jinja2') as pedd %}
17
+ {%- import('macros/printUnitSpec.xml.jinja2') as punit %}
18
+ {%- import('macros/printSpecialData.xml.jinja2') as psd %}
19
+
20
+ {%- macro printDiagDataDictionarySpec(ddds) -%}
21
+ <DIAG-DATA-DICTIONARY-SPEC>
22
+ {%- if ddds.admin_data is not none %}
23
+ {{- pad.printAdminData(ddds.admin_data)|indent(2) }}
24
+ {%- endif %}
25
+ {%- if ddds.dtc_dops %}
26
+ <DTC-DOPS>
27
+ {%- for dop in ddds.dtc_dops -%}
28
+ {{ pdop.printDtcDop(dop)|indent(4) }}
29
+ {%- endfor %}
30
+ </DTC-DOPS>
31
+ {%- endif %}
32
+ {%- if ddds.env_data_descs %}
33
+ <ENV-DATA-DESCS>
34
+ {%- for env_data_desc in ddds.env_data_descs -%}
35
+ {{ pedd.printEnvDataDesc(env_data_desc)|indent(4) }}
36
+ {%- endfor %}
37
+ </ENV-DATA-DESCS>
38
+ {%- endif %}
39
+ {%- if ddds.data_object_props %}
40
+ <DATA-OBJECT-PROPS>
41
+ {%- for dop in ddds.data_object_props %}
42
+ {{- pdop.printDataObjectProp(dop)|indent(4) }}
43
+ {%- endfor %}
44
+ </DATA-OBJECT-PROPS>
45
+ {%- endif %}
46
+ {%- if ddds.structures %}
47
+ <STRUCTURES>
48
+ {%- for st in ddds.structures %}
49
+ {{ pst.printStructure(st)|indent(4) }}
50
+ {%- endfor %}
51
+ </STRUCTURES>
52
+ {%- endif %}
53
+ {%- if ddds.static_fields %}
54
+ <STATIC-FIELDS>
55
+ {%- for sf in ddds.static_fields %}
56
+ {{ psf.printStaticField(sf)|indent(4) }}
57
+ {%- endfor %}
58
+ </STATIC-FIELDS>
59
+ {%- endif %}
60
+ {%- if ddds.dynamic_length_fields %}
61
+ <DYNAMIC-LENGTH-FIELDS>
62
+ {%- for dlf in ddds.dynamic_length_fields %}
63
+ {{ pdlf.printDynamicLengthField(dlf)|indent(4) }}
64
+ {%- endfor %}
65
+ </DYNAMIC-LENGTH-FIELDS>
66
+ {%- endif %}
67
+ {%- if ddds.dynamic_endmarker_fields %}
68
+ <DYNAMIC-ENDMARKER-FIELDS>
69
+ {%- for demf in ddds.dynamic_endmarker_fields %}
70
+ {{ pdemf.printDynamicEndmarkerField(demf)|indent(4) }}
71
+ {%- endfor %}
72
+ </DYNAMIC-ENDMARKER-FIELDS>
73
+ {%- endif %}
74
+ {%- if ddds.end_of_pdu_fields %}
75
+ <END-OF-PDU-FIELDS>
76
+ {%- for eopdu in ddds.end_of_pdu_fields %}
77
+ {{ peopdu.printEndOfPdu(eopdu)|indent(4) }}
78
+ {%- endfor %}
79
+ </END-OF-PDU-FIELDS>
80
+ {%- endif %}
81
+ {%- if ddds.muxs %}
82
+ <MUXS>
83
+ {%- for mux in ddds.muxs %}
84
+ {{ pm.printMux(mux)|indent(4) }}
85
+ {%- endfor %}
86
+ </MUXS>
87
+ {%- endif %}
88
+ {%- if ddds.env_datas %}
89
+ <ENV-DATAS>
90
+ {%- for env_data in ddds.env_datas %}
91
+ {{ ped.printEnvData(env_data)|indent(4) }}
92
+ {%- endfor %}
93
+ </ENV-DATAS>
94
+ {%- endif %}
95
+ {%- if ddds.unit_spec %}
96
+ {{ punit.printUnitSpec(ddds.unit_spec)|indent(2) }}
97
+ {%- endif %}
98
+ {%- if ddds.tables %}
99
+ <TABLES>
100
+ {%- for table in ddds.tables -%}
101
+ {{ pt.printTable(table)|indent(4) }}
102
+ {%- endfor %}
103
+ </TABLES>
104
+ {%- endif %}
105
+ {{- psd.printSpecialDataGroups(ddds.sdgs)|indent(2, first=True) }}
106
+ </DIAG-DATA-DICTIONARY-SPEC>
107
+ {%- endmacro -%}
@@ -4,18 +4,10 @@
4
4
  -#}
5
5
 
6
6
  {%- import('macros/printElementId.xml.jinja2') as peid %}
7
- {%- import('macros/printDOP.xml.jinja2') as pdop %}
8
- {%- import('macros/printTable.xml.jinja2') as pt %}
7
+ {%- import('macros/printAdminData.xml.jinja2') as pad %}
8
+ {%- import('macros/printCompanyData.xml.jinja2') as pcd %}
9
9
  {%- import('macros/printFunctionalClass.xml.jinja2') as pfc %}
10
- {%- import('macros/printStructure.xml.jinja2') as pst %}
11
- {%- import('macros/printEndOfPdu.xml.jinja2') as peopdu %}
12
- {%- import('macros/printStaticField.xml.jinja2') as psf %}
13
- {%- import('macros/printDynamicLengthField.xml.jinja2') as pdlf %}
14
- {%- import('macros/printDynamicEndmarkerField.xml.jinja2') as pdemf %}
15
- {%- import('macros/printMux.xml.jinja2') as pm %}
16
- {%- import('macros/printEnvData.xml.jinja2') as ped %}
17
- {%- import('macros/printEnvDataDesc.xml.jinja2') as pedd %}
18
- {%- import('macros/printUnitSpec.xml.jinja2') as punit %}
10
+ {%- import('macros/printDiagDataDictionarySpec.xml.jinja2') as pddds %}
19
11
  {%- import('macros/printService.xml.jinja2') as ps %}
20
12
  {%- import('macros/printSingleEcuJob.xml.jinja2') as psej %}
21
13
  {%- import('macros/printRequest.xml.jinja2') as prq %}
@@ -25,8 +17,6 @@
25
17
  {%- import('macros/printSubComponent.xml.jinja2') as psubcomp %}
26
18
  {%- import('macros/printLibrary.xml.jinja2') as plib %}
27
19
  {%- import('macros/printSpecialData.xml.jinja2') as psd %}
28
- {%- import('macros/printEcuVariantPattern.xml.jinja2') as pvpat %}
29
- {%- import('macros/printAdminData.xml.jinja2') as pad %}
30
20
 
31
21
  {%- macro printDiagLayerAttribs(dl) -%}
32
22
  {#- #} {{-peid.printElementIdAttribs(dl)}}{# -#}
@@ -54,90 +44,7 @@
54
44
  </FUNCT-CLASSS>
55
45
  {%- endif %}
56
46
  {%- if dlr.diag_data_dictionary_spec is not none %}
57
- {%- set ddds = dlr.diag_data_dictionary_spec %}
58
- <DIAG-DATA-DICTIONARY-SPEC>
59
- {%- if ddds.dtc_dops %}
60
- <DTC-DOPS>
61
- {%- for dop in ddds.dtc_dops -%}
62
- {{ pdop.printDtcDop(dop)|indent(3) }}
63
- {%- endfor %}
64
- </DTC-DOPS>
65
- {%- endif %}
66
- {%- if ddds.env_data_descs %}
67
- <ENV-DATA-DESCS>
68
- {%- for env_data_desc in ddds.env_data_descs -%}
69
- {{ pedd.printEnvDataDesc(env_data_desc)|indent(3) }}
70
- {%- endfor %}
71
- </ENV-DATA-DESCS>
72
- {%- endif %}
73
- {%- if ddds.data_object_props %}
74
- <DATA-OBJECT-PROPS>
75
- {%- for dop in ddds.data_object_props %}
76
- {{- pdop.printDataObjectProp(dop)|indent(3) }}
77
- {%- endfor %}
78
- </DATA-OBJECT-PROPS>
79
- {%- endif %}
80
- {%- if ddds.structures %}
81
- <STRUCTURES>
82
- {%- for st in ddds.structures %}
83
- {{ pst.printStructure(st)|indent(3) }}
84
- {%- endfor %}
85
- </STRUCTURES>
86
- {%- endif %}
87
- {%- if ddds.static_fields %}
88
- <STATIC-FIELDS>
89
- {%- for sf in ddds.static_fields %}
90
- {{ psf.printStaticField(sf)|indent(3) }}
91
- {%- endfor %}
92
- </STATIC-FIELDS>
93
- {%- endif %}
94
- {%- if ddds.dynamic_length_fields %}
95
- <DYNAMIC-LENGTH-FIELDS>
96
- {%- for dlf in ddds.dynamic_length_fields %}
97
- {{ pdlf.printDynamicLengthField(dlf)|indent(3) }}
98
- {%- endfor %}
99
- </DYNAMIC-LENGTH-FIELDS>
100
- {%- endif %}
101
- {%- if ddds.dynamic_endmarker_fields %}
102
- <DYNAMIC-ENDMARKER-FIELDS>
103
- {%- for demf in ddds.dynamic_endmarker_fields %}
104
- {{ pdemf.printDynamicEndmarkerField(demf)|indent(3) }}
105
- {%- endfor %}
106
- </DYNAMIC-ENDMARKER-FIELDS>
107
- {%- endif %}
108
- {%- if ddds.end_of_pdu_fields %}
109
- <END-OF-PDU-FIELDS>
110
- {%- for eopdu in ddds.end_of_pdu_fields %}
111
- {{ peopdu.printEndOfPdu(eopdu)|indent(3) }}
112
- {%- endfor %}
113
- </END-OF-PDU-FIELDS>
114
- {%- endif %}
115
- {%- if ddds.muxs %}
116
- <MUXS>
117
- {%- for mux in ddds.muxs %}
118
- {{ pm.printMux(mux)|indent(3) }}
119
- {%- endfor %}
120
- </MUXS>
121
- {%- endif %}
122
- {%- if ddds.env_datas %}
123
- <ENV-DATAS>
124
- {%- for env_data in ddds.env_datas %}
125
- {{ ped.printEnvData(env_data)|indent(3) }}
126
- {%- endfor %}
127
- </ENV-DATAS>
128
- {%- endif %}
129
- {%- if ddds.unit_spec %}
130
- {{ punit.printUnitSpec(ddds.unit_spec)|indent(2) }}
131
- {%- endif %}
132
- {%- if ddds.tables %}
133
- <TABLES>
134
- {%- for table in ddds.tables -%}
135
- {{ pt.printTable(table)|indent(3) }}
136
- {%- endfor %}
137
- </TABLES>
138
- {%- endif %}
139
- {{- psd.printSpecialDataGroups(ddds.sdgs)|indent(2, first=True) }}
140
- </DIAG-DATA-DICTIONARY-SPEC>
47
+ {{ pddds.printDiagDataDictionarySpec(dlr.diag_data_dictionary_spec) }}
141
48
  {%- endif %}
142
49
  {%- if dlr.diag_comms_raw %}
143
50
  <DIAG-COMMS>
@@ -191,6 +98,13 @@
191
98
  {%- endfor %}
192
99
  </GLOBAL-NEG-RESPONSES>
193
100
  {%- endif %}
101
+ {%- if dlr.import_refs %}
102
+ <IMPORT-REFS>
103
+ {%- for ir in dlr.import_refs %}
104
+ <IMPORT-REF {{make_ref_attribs(ir)}} />
105
+ {%- endfor %}
106
+ </IMPORT-REFS>
107
+ {%- endif %}
194
108
  {%- if dlr.state_charts %}
195
109
  <STATE-CHARTS>
196
110
  {%- for sc in dlr.state_charts %}
@@ -6,7 +6,9 @@
6
6
  {%- import('macros/printDescription.xml.jinja2') as pd %}
7
7
 
8
8
  {%- macro printElementIdAttribs(obj) -%}
9
+ {%- if obj.odx_id is defined %}
9
10
  {#- #} {{- make_xml_attrib("ID", obj.odx_id.local_id) }}
11
+ {%- endif %}
10
12
  {#- #} {{- make_xml_attrib("OID", getattr(obj, "oid", none)) -}}
11
13
  {%- endmacro -%}
12
14
 
@@ -9,9 +9,9 @@
9
9
 
10
10
  {%- macro printFunctionalClass(fc) -%}
11
11
  <FUNCT-CLASS {{-peid.printElementIdAttribs(fc)}}>
12
- {{ peid.printElementIdSubtags(fc)|indent(1) }}
13
- {%- if fc.admin_data is not none -%}
14
- {{ pad.printAdminData(fc.admin_data)|indent(1) }}
15
- {%- endif -%}
12
+ {{ peid.printElementIdSubtags(fc)|indent(2) }}
13
+ {%- if fc.admin_data is not none %}
14
+ {{ pad.printAdminData(fc.admin_data)|indent(2) }}
15
+ {%- endif %}
16
16
  </FUNCT-CLASS>
17
17
  {%- endmacro -%}
@@ -0,0 +1,77 @@
1
+ 1{#- -*- mode: sgml; tab-width: 1; indent-tabs-mode: nil -*-
2
+ #
3
+ # SPDX-License-Identifier: MIT
4
+ -#}
5
+
6
+ {%- import('macros/printElementId.xml.jinja2') as peid %}
7
+ {%- import('macros/printAdminData.xml.jinja2') as pad %}
8
+ {%- import('macros/printSpecialData.xml.jinja2') as psd %}
9
+ {%- import('macros/printCompuMethod.xml.jinja2') as pcm %}
10
+ {%- import('macros/printAudience.xml.jinja2') as paud %}
11
+
12
+ {%- macro printMultipleEcuJob(multiple_ecu_job) -%}
13
+ <MULTIPLE-ECU-JOB {{peid.printElementIdAttribs(multiple_ecu_job)}}
14
+ {{-make_xml_attrib("SEMANTIC", multiple_ecu_job.semantic)}}
15
+ {{-make_bool_xml_attrib("IS-EXECUTABLE", multiple_ecu_job.is_executable_raw)}}>
16
+ {{peid.printElementIdSubtags(multiple_ecu_job)|indent(2) }}
17
+ {%- if multiple_ecu_job.admin_data is not none %}
18
+ {{- pad.printAdminData(multiple_ecu_job.admin_data)|indent(2) }}
19
+ {%- endif %}
20
+ {{- psd.printSpecialDataGroups(multiple_ecu_job.sdgs)|indent(2, first=True) }}{#- #}
21
+ {%- if multiple_ecu_job.functional_class_refs %}
22
+ <FUNCT-CLASS-REFS>
23
+ {%- for fc_ref in multiple_ecu_job.functional_class_refs %}
24
+ <FUNCT-CLASS-REF {{make_ref_attribs(fc_ref)}} />
25
+ {%- endfor %}
26
+ </FUNCT-CLASS-REFS>
27
+ {%- endif %}
28
+ <PROG-CODES>
29
+ {%- for pc in multiple_ecu_job.prog_codes %}
30
+ {{pcm.printProgCode(pc)|indent(4)}}
31
+ {%- endfor %}
32
+ </PROG-CODES>
33
+ {%- if multiple_ecu_job.input_params %}
34
+ <INPUT-PARAMS>
35
+ {%- for ip in multiple_ecu_job.input_params %}
36
+ <INPUT-PARAM {{ peid.printElementIdAttribs(ip) }} {{make_xml_attrib("SEMANTIC", ip.semantic)}}>
37
+ {{peid.printElementIdSubtags(ip)|indent(4)}}
38
+ {%- if ip.physical_default_value is not none %}
39
+ <PHYSICAL-DEFAULT-VALUE>{{ip.physical_default_value | e}}</PHYSICAL-DEFAULT-VALUE>
40
+ {%- endif %}
41
+ <DOP-BASE-REF {{make_ref_attribs(ip.dop_base_ref)}} />
42
+ </INPUT-PARAM>
43
+ {%- endfor %}
44
+ </INPUT-PARAMS>
45
+ {%- endif %}
46
+ {%- if multiple_ecu_job.output_params %}
47
+ <OUTPUT-PARAMS>
48
+ {%- for op in multiple_ecu_job.output_params %}
49
+ <OUTPUT-PARAM {{ peid.printElementIdAttribs(op) }} {{make_xml_attrib("SEMANTIC", op.semantic)}}>
50
+ {{peid.printElementIdSubtags(op)|indent(4)}}
51
+ <DOP-BASE-REF {{make_ref_attribs(op.dop_base_ref)}} />
52
+ </OUTPUT-PARAM>
53
+ {%- endfor %}
54
+ </OUTPUT-PARAMS>
55
+ {%- endif %}
56
+ {%- if multiple_ecu_job.neg_output_params %}
57
+ <NEG-OUTPUT-PARAMS>
58
+ {%- for nop in multiple_ecu_job.neg_output_params %}
59
+ <NEG-OUTPUT-PARAM {{ peid.printElementIdAttribs(nop) }}>
60
+ {{peid.printElementIdSubtags(nop)|indent(4)}}
61
+ <DOP-BASE-REF {{make_ref_attribs(nop.dop_base_ref)}} />
62
+ </NEG-OUTPUT-PARAM>
63
+ {%- endfor %}
64
+ </NEG-OUTPUT-PARAMS>
65
+ {%- endif %}
66
+ {%- if multiple_ecu_job.diag_layer_refs %}
67
+ <DIAG-LAYER-REFS>
68
+ {%- for dl_ref in multiple_ecu_job.diag_layer_refs %}
69
+ <DIAG-LAYER-REF {{make_ref_attribs(dl_ref)}} />
70
+ {%- endfor %}
71
+ </DIAG-LAYER-REFS>
72
+ {%- endif %}
73
+ {%- if multiple_ecu_job.audience is not none %}
74
+ {{ paud.printAudience(multiple_ecu_job.audience) | indent(2) }}
75
+ {%- endif %}
76
+ </MULTIPLE-ECU-JOB>
77
+ {%- endmacro -%}
@@ -0,0 +1,51 @@
1
+ {#- -*- mode: sgml; tab-width: 1; indent-tabs-mode: nil -*-
2
+ #
3
+ # SPDX-License-Identifier: MIT
4
+ #
5
+ # This template writes an .odx-f file containing descriptions of firmware
6
+ # blobs that can be flashed to ECUs.
7
+ -#}
8
+ {%- import('macros/printOdxCategory.xml.jinja2') as poc %}
9
+ {%- import('macros/printMultipleEcuJob.xml.jinja2') as pmecuj %}
10
+ {%- import('macros/printDiagDataDictionarySpec.xml.jinja2') as pddds %}
11
+ {%- import('macros/printFunctionalClass.xml.jinja2') as pfc %}
12
+ {%- import('macros/printAudience.xml.jinja2') as paud %}
13
+ {#- -#}
14
+
15
+ <?xml version="1.0" encoding="UTF-8" standalone="no" ?>
16
+ <!-- Written using odxtools {{odxtools_version}} -->
17
+ <ODX MODEL-VERSION="2.2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="odx.xsd">
18
+ {{- set_category_docfrag(multiple_ecu_job_spec.short_name, "MULTIPLE-ECU-JOB-SPEC") }}
19
+ <MULTIPLE-ECU-JOB-SPEC {{- poc.printOdxCategoryAttribs(multiple_ecu_job_spec) }}>
20
+ {{- poc.printOdxCategorySubtags(multiple_ecu_job_spec)|indent(4) }}
21
+ <MULTIPLE-ECU-JOBS>
22
+ {%- for mecuj in multiple_ecu_job_spec.multiple_ecu_jobs %}
23
+ {{ pmecuj.printMultipleEcuJob(mecuj) | indent(6) }}
24
+ {%- endfor %}
25
+ </MULTIPLE-ECU-JOBS>
26
+ {%- if multiple_ecu_job_spec.diag_data_dictionary_spec is not none %}
27
+ {{ pddds.printDiagDataDictionarySpec(multiple_ecu_job_spec.diag_data_dictionary_spec) }}
28
+ {%- endif %}
29
+ {%- if multiple_ecu_job_spec.functional_classes %}
30
+ <FUNCT-CLASSS>
31
+ {%- for fc in multiple_ecu_job_spec.functional_classes %}
32
+ {{ pfc.printFunctionalClass(fc)|indent(6) }}
33
+ {%- endfor%}
34
+ </FUNCT-CLASSS>
35
+ {%- endif %}
36
+ {%- if multiple_ecu_job_spec.additional_audiences %}
37
+ <ADDITIONAL-AUDIENCES>
38
+ {%- for audience in multiple_ecu_job_spec.additional_audiences %}
39
+ {{ paud.printAdditionalAudience(audience) | indent(6) }}
40
+ {%- endfor %}
41
+ </ADDITIONAL-AUDIENCES>
42
+ {%- endif %}
43
+ {%- if multiple_ecu_job_spec.import_refs %}
44
+ <IMPORT-REFS>
45
+ {%- for ir in multiple_ecu_job_spec.import_refs %}
46
+ <IMPORT-REF {{make_ref_attribs(ir)}} />
47
+ {%- endfor %}
48
+ </IMPORT-REFS>
49
+ {%- endif %}
50
+ </MULTIPLE-ECU-JOB-SPEC>
51
+ </ODX>
odxtools/version.py CHANGED
@@ -17,5 +17,5 @@ __version__: str
17
17
  __version_tuple__: VERSION_TUPLE
18
18
  version_tuple: VERSION_TUPLE
19
19
 
20
- __version__ = version = '10.3.0'
21
- __version_tuple__ = version_tuple = (10, 3, 0)
20
+ __version__ = version = '10.4.0'
21
+ __version_tuple__ = version_tuple = (10, 4, 0)
odxtools/writepdxfile.py CHANGED
@@ -166,20 +166,50 @@ def write_pdx_file(
166
166
  jinja_env.globals["set_layer_docfrag"] = lambda lname: set_layer_docfrag(jinja_vars, lname)
167
167
  jinja_env.globals["make_ref_attribs"] = lambda ref: make_ref_attribs(jinja_vars, ref)
168
168
 
169
- # write the communication parameter subsets
170
- comparam_subset_tpl = jinja_env.get_template("comparam-subset.odx-cs.xml.jinja2")
171
- for comparam_subset in database.comparam_subsets:
172
- zf_file_name = f"{comparam_subset.short_name}.odx-cs"
169
+ # write the flash description objects
170
+ flash_tpl = jinja_env.get_template("flash.odx-f.xml.jinja2")
171
+ for flash in database.flashs:
172
+ zf_file_name = f"{flash.short_name}.odx-f"
173
173
  zf_file_cdate = datetime.datetime.now().strftime("%Y-%m-%dT%H:%M:%S")
174
- zf_mime_type = "application/x-asam.odx.odx-cs"
174
+ zf_mime_type = "application/x-asam.odx.odx-f"
175
175
 
176
- jinja_vars["comparam_subset"] = comparam_subset
176
+ jinja_vars["flash"] = flash
177
177
 
178
178
  file_index.append((zf_file_name, zf_file_cdate, zf_mime_type))
179
179
 
180
- zf.writestr(zf_file_name, comparam_subset_tpl.render(**jinja_vars))
180
+ zf.writestr(zf_file_name, flash_tpl.render(**jinja_vars))
181
181
 
182
- del jinja_vars["comparam_subset"]
182
+ del jinja_vars["flash"]
183
+
184
+ # write the actual diagnostic data.
185
+ dlc_tpl = jinja_env.get_template("diag_layer_container.odx-d.xml.jinja2")
186
+ for dlc in database.diag_layer_containers:
187
+ jinja_vars["dlc"] = dlc
188
+
189
+ file_name = f"{dlc.short_name}.odx-d"
190
+ file_cdate = datetime.datetime.now()
191
+ creation_date = file_cdate.strftime("%Y-%m-%dT%H:%M:%S")
192
+ mime_type = "application/x-asam.odx.odx-d"
193
+
194
+ file_index.append((file_name, creation_date, mime_type))
195
+ zf.writestr(file_name, dlc_tpl.render(**jinja_vars))
196
+ del jinja_vars["dlc"]
197
+
198
+ # write the multiple ECU jobs specs
199
+ multiple_ecu_jobs_spec_tpl = jinja_env.get_template(
200
+ "multiple-ecu-job-spec.odx-m.xml.jinja2")
201
+ for multiple_ecu_jobs_spec in database.multiple_ecu_job_specs:
202
+ zf_file_name = f"{multiple_ecu_jobs_spec.short_name}.odx-m"
203
+ zf_file_cdate = datetime.datetime.now().strftime("%Y-%m-%dT%H:%M:%S")
204
+ zf_mime_type = "application/x-asam.odx.odx-m"
205
+
206
+ jinja_vars["multiple_ecu_jobs_spec"] = multiple_ecu_jobs_spec
207
+
208
+ file_index.append((zf_file_name, zf_file_cdate, zf_mime_type))
209
+
210
+ zf.writestr(zf_file_name, multiple_ecu_jobs_spec_tpl.render(**jinja_vars))
211
+
212
+ del jinja_vars["multiple_ecu_jobs_spec"]
183
213
 
184
214
  # write the communication parameter specs
185
215
  comparam_spec_tpl = jinja_env.get_template("comparam-spec.odx-c.xml.jinja2")
@@ -196,34 +226,20 @@ def write_pdx_file(
196
226
 
197
227
  del jinja_vars["comparam_spec"]
198
228
 
199
- # write the actual diagnostic data.
200
- dlc_tpl = jinja_env.get_template("diag_layer_container.odx-d.xml.jinja2")
201
- for dlc in database.diag_layer_containers:
202
- jinja_vars["dlc"] = dlc
203
-
204
- file_name = f"{dlc.short_name}.odx-d"
205
- file_cdate = datetime.datetime.now()
206
- creation_date = file_cdate.strftime("%Y-%m-%dT%H:%M:%S")
207
- mime_type = "application/x-asam.odx.odx-d"
208
-
209
- file_index.append((file_name, creation_date, mime_type))
210
- zf.writestr(file_name, dlc_tpl.render(**jinja_vars))
211
- del jinja_vars["dlc"]
212
-
213
- # write the flash description objects
214
- flash_tpl = jinja_env.get_template("flash.odx-f.xml.jinja2")
215
- for flash in database.flashs:
216
- zf_file_name = f"{flash.short_name}.odx-f"
229
+ # write the communication parameter subsets
230
+ comparam_subset_tpl = jinja_env.get_template("comparam-subset.odx-cs.xml.jinja2")
231
+ for comparam_subset in database.comparam_subsets:
232
+ zf_file_name = f"{comparam_subset.short_name}.odx-cs"
217
233
  zf_file_cdate = datetime.datetime.now().strftime("%Y-%m-%dT%H:%M:%S")
218
- zf_mime_type = "application/x-asam.odx.odx-f"
234
+ zf_mime_type = "application/x-asam.odx.odx-cs"
219
235
 
220
- jinja_vars["flash"] = flash
236
+ jinja_vars["comparam_subset"] = comparam_subset
221
237
 
222
238
  file_index.append((zf_file_name, zf_file_cdate, zf_mime_type))
223
239
 
224
- zf.writestr(zf_file_name, flash_tpl.render(**jinja_vars))
240
+ zf.writestr(zf_file_name, comparam_subset_tpl.render(**jinja_vars))
225
241
 
226
- del jinja_vars["flash"]
242
+ del jinja_vars["comparam_subset"]
227
243
 
228
244
  # write the ECU-config objects
229
245
  ecu_config_tpl = jinja_env.get_template("ecu_config.odx-e.xml.jinja2")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: odxtools
3
- Version: 10.3.0
3
+ Version: 10.4.0
4
4
  Summary: Utilities to work with the ODX standard for automotive diagnostics
5
5
  Author-email: Katrin Bauer <katrin.bauer@mbition.io>, Andreas Lauser <andreas.lauser@mbition.io>, Ayoub Kaanich <kayoub5@live.com>
6
6
  Maintainer-email: Andreas Lauser <andreas.lauser@mbition.io>, Ayoub Kaanich <kayoub5@live.com>
@@ -32,7 +32,7 @@ odxtools/configitem.py,sha256=yXlFyuaRMYLa2HmUoWdq_TOabEYf3Vpz6SCXuMO2828,3237
32
32
  odxtools/configrecord.py,sha256=f0GLG_PIj0MBFhHPT59_0PhvzYwDLKCw8XLLIKWpoVw,6567
33
33
  odxtools/createanycomparam.py,sha256=KHsN027D7AoDx6kKjQ_0f84Us_UQD54Ps0fR1-p09n8,587
34
34
  odxtools/createanydiagcodedtype.py,sha256=eLyqOminWq7yI8WGIPsUHbm7_J4IkaJP0rsoDQDpUUM,1178
35
- odxtools/database.py,sha256=Rc79c--TACKmqgIoufUYv2iFI_gzmG_U8ulSRLuKRTY,12056
35
+ odxtools/database.py,sha256=vioK3yLowla35rX-c6RHIK6SKCa--CNBwvIqKy1wE08,13148
36
36
  odxtools/datablock.py,sha256=ILjjna50PyLFApnLM4cduxQ77P9I-Sr7kzrMZ_ebX6M,6306
37
37
  odxtools/datafile.py,sha256=k_SatFNGhf7x1P-Iiyh7iphDufNkql6OZGA0HJFJXnk,658
38
38
  odxtools/dataformat.py,sha256=1yiZj0gmEmqJikpKHP-IW7xSFsuHI40TVcuOfJ1JWLA,1320
@@ -107,6 +107,8 @@ odxtools/mem.py,sha256=M0M7G7vAmoYV1njP6PpSe-N_KjmRCEZKMMmytSuC79k,2976
107
107
  odxtools/message.py,sha256=7FZV5iVy1KTN-h7CO6OSKjdp89Yuci3_2h-Alj19Q_4,869
108
108
  odxtools/minmaxlengthtype.py,sha256=MfmH_D4o-JDOHIgUSyC-jW2xwvHCsGm57tnBYlYGndI,9621
109
109
  odxtools/modification.py,sha256=BNm3MgYa8TNccG1t76IyDCMzbz4xJpFgdgCqPKqDDSA,947
110
+ odxtools/multipleecujob.py,sha256=oRGY2B2hN-TXmMwICUZEippSCTWuWmKBnodcdoBYYT4,7293
111
+ odxtools/multipleecujobspec.py,sha256=VBj16TFuEU3N6bi_55j3CznrBU5GOgBdzQYqsHaW4Uc,5996
110
112
  odxtools/multiplexer.py,sha256=qay6yE_Wxne86CH9HQuZ2VrwL7_bLh3dPqeI6AfqQG8,11634
111
113
  odxtools/multiplexercase.py,sha256=bs-mAnkd7MY_hOaQtoYT-pEMGKPfUOFpt1YJuIECL8w,3082
112
114
  odxtools/multiplexerdefaultcase.py,sha256=RI3SrEwfE8WiPr-TBoafzNwAO9vF57nMKZnYwD8iZXA,2030
@@ -120,7 +122,7 @@ odxtools/odxdoccontext.py,sha256=QjdOp7jwtJVgyGwzPBH_a35xqdS24WJmlF6uNqLrp9U,460
120
122
  odxtools/odxlink.py,sha256=me0Y5yoXv6HsFGPQjo99hSt1GxpzllJlwIy0nhgpcdQ,10807
121
123
  odxtools/odxtypes.py,sha256=uhlKergX9Mutax_gf-bsyf_LJwF-t18HoYt2OXcimf0,8208
122
124
  odxtools/optionitem.py,sha256=kihbKVgPSNNqIT6aL2Ac5gNhluXUbTaXenYvn4hgmho,2914
123
- odxtools/outputparam.py,sha256=oijoIXChUY7Jwds4x7OeIiyp5VTEivi61Sj5oVPjQMY,1477
125
+ odxtools/outputparam.py,sha256=q974Fa-fre1NcwK8RMRUD50D7GXBYq4gvEHOopZOe6s,1494
124
126
  odxtools/ownident.py,sha256=beX1glfBfG-s9hMD6qT_cGMZLln7LYt2X8uY4R_-_Zo,1146
125
127
  odxtools/parameterinfo.py,sha256=OeHQK1Ockq-CZgEXl1XWPH9UZ7vEW2_OSRnF1BZPRnY,11198
126
128
  odxtools/paramlengthinfotype.py,sha256=tBVKJHmC2jyeUiY4fRuq8FGx3UQoHJOjVzozMAEyTbM,4931
@@ -153,7 +155,7 @@ odxtools/sessionsubelemtype.py,sha256=k3dL5TT6AYIJQ_U7W78ad6pNz4SH1pge4m62epRtT7
153
155
  odxtools/singleecujob.py,sha256=181jUAefl5LPdkdV4jOB_x_6LlVmw8YyuI3fAfxqXd8,4116
154
156
  odxtools/sizedeffilter.py,sha256=CYLo4293-dJMw5pNYzUIIr6d6sb_zHZSxM6ZYcpHFKM,1084
155
157
  odxtools/sizedefphyssegment.py,sha256=6Ykna8Fq-0Yu1puAOU_qbhFPauqD1ueylxDXkybgQBY,1084
156
- odxtools/snrefcontext.py,sha256=zuY3SU16YvgDKvKF7vocCA6f92iXQUKR6sFrLm7U2YU,958
158
+ odxtools/snrefcontext.py,sha256=mb1-07gaGpncDFzpNINGwzJFJf2S-GnmqqKT2zq5rv0,1061
157
159
  odxtools/specialdata.py,sha256=6AvvLiP8TC37wlBVFzFuwtBx2z3q7gIQZgy0RD5qB3s,1140
158
160
  odxtools/specialdatagroup.py,sha256=GnlaePVPNbcQ6MyLEIb5N567BPKMwW7qhwalD43p680,3134
159
161
  odxtools/specialdatagroupcaption.py,sha256=xYiwSQyxbzRnWGzd5bj-CPcBudEvxtxZ4mPCpizJN1M,1003
@@ -193,9 +195,9 @@ odxtools/validtype.py,sha256=exe5OIqoIWgsgEm1t54pyk-U2m61DgBWI0Gew8rNYFc,194
193
195
  odxtools/variablegroup.py,sha256=o2hHupTvYSAJgOK8YOG9-VjXZpOMQ9vp9Sssu6RvN6E,834
194
196
  odxtools/variantmatcher.py,sha256=9qCg0ln3B1_zdNw-imFZ1DCECGdH4oa8_oGhC2gyl_g,8331
195
197
  odxtools/variantpattern.py,sha256=Mt2iXrlHvdo2EZtWq_tTqOqD-MxsaMUumQLcOpTkFR8,1406
196
- odxtools/version.py,sha256=l3ET6ASSL16dZtet-ppmR_MsErP2kLj0yDnEBXEt-is,513
198
+ odxtools/version.py,sha256=19M94hjIavZZJFdX2XJTnMIikXzunL4QfRwNieuLnp8,513
197
199
  odxtools/writediagcommconnector.py,sha256=pkpIX8msn82L3S9mAL_ebXdoqZ8f-SK9eeFX8FXqgaA,3256
198
- odxtools/writepdxfile.py,sha256=nXrOTF3WypCDtirCuXj59TzDYaU9ZxTNBMdehlHwktM,9753
200
+ odxtools/writepdxfile.py,sha256=_pestzsUMngFLWeOsG3t70vk2L36TgnFcEhbPONdTnY,10489
199
201
  odxtools/xdoc.py,sha256=Ymir_UH5dz8h-T4_kVCm2M_zyip7lDSnQ_wJvu-BCAA,1463
200
202
  odxtools/cli/__init__.py,sha256=T7ano_FIyzBASxYpmcA5VJXU5bQLIy_Qk0HE_SDKelY,106
201
203
  odxtools/cli/_parser_utils.py,sha256=p0L9NYYnml5ydfD22oC04EMhz8PKHgU40GPOPkybZwg,1116
@@ -232,7 +234,7 @@ odxtools/compumethods/tabintpcompumethod.py,sha256=Jb57a3xKtFreZmwDdvKbmPQ4Dg0fR
232
234
  odxtools/compumethods/texttablecompumethod.py,sha256=0aLSPsOsb3XgP1aj13CkpDfSi4PIZID6ErnAXiQgtZo,5957
233
235
  odxtools/diaglayers/basevariant.py,sha256=urQiHezdLQ2TM6X8LfPTQHIMELxAP_CKFiHxZI3JKzQ,4660
234
236
  odxtools/diaglayers/basevariantraw.py,sha256=y7yujzGooVuPuX0bAtCNcvSCSrKQObgmyNABI5Pypyc,4994
235
- odxtools/diaglayers/diaglayer.py,sha256=3IlRq6Z0WkTYMOn8KUay8dPJm0FqnJWkphgyEdT23C8,17106
237
+ odxtools/diaglayers/diaglayer.py,sha256=oR-oxtv2QZxxHMirY2q7ns2inFKx25Qq60hq9WCeRrA,16697
236
238
  odxtools/diaglayers/diaglayerraw.py,sha256=cS3w4FcjuTPZ06wyfXPRrI99X_zsx9vjbaDwFCyGzn4,13059
237
239
  odxtools/diaglayers/diaglayertype.py,sha256=o1Vz6ycSqkDGNxNErcqpXUs0SAk9c4NSmxPDGWlufOE,1316
238
240
  odxtools/diaglayers/ecushareddata.py,sha256=2mg6bS50oSJlpqYDgRfXqPbkZHSvY4fFF3b_VwBhPwE,3336
@@ -267,7 +269,8 @@ odxtools/templates/diag_layer_container.odx-d.xml.jinja2,sha256=WL__gfOYnta-cHDG
267
269
  odxtools/templates/ecu_config.odx-e.xml.jinja2,sha256=pc7tBjJIkDXqaH8l09efZ2NnAl4v2zszLWLpT3Cp5xI,1581
268
270
  odxtools/templates/flash.odx-f.xml.jinja2,sha256=kgToXyDbAfS2qJ2nNamF8Wh1cCX0Wl9Rt5L5EKc0Wuw,1572
269
271
  odxtools/templates/index.xml.jinja2,sha256=Z1bcntvvky7NoH0Q0CRJgUORwf3g96PFPGeOpi7VATw,647
270
- odxtools/templates/macros/printAdminData.xml.jinja2,sha256=uG5BzloGpnW3FrmlqyMHGlaEtA1X3lZ-iJsOtWtDGPY,2598
272
+ odxtools/templates/multiple-ecu-job-spec.odx-m.xml.jinja2,sha256=IbNchTHNQyKFzmpIKr1qxhfZaZAlk8NjoXGJiFbXMsU,2181
273
+ odxtools/templates/macros/printAdminData.xml.jinja2,sha256=_faltyDPBghsk_AKb-WAiun9MXIMpvTvxATgA9UYQHE,2586
271
274
  odxtools/templates/macros/printAudience.xml.jinja2,sha256=IkEKH5sPcoaLhS2aqTUBmwoh3GxtSpOp8-g_niktU5c,1320
272
275
  odxtools/templates/macros/printBaseVariant.xml.jinja2,sha256=Ovf7NvO5jzy_9w1-iXi_q2dedoEfsQOYCK_WASkcITQ,1451
273
276
  odxtools/templates/macros/printBaseVariantPattern.xml.jinja2,sha256=foL_DmH4mWFzPObZ3VjPixdzbomAA5jK7GLpAhJsKVE,1192
@@ -287,7 +290,8 @@ odxtools/templates/macros/printDatablock.xml.jinja2,sha256=Eyvvtig2TknUXS4svdYly
287
290
  odxtools/templates/macros/printDescription.xml.jinja2,sha256=95Zamh5YtS5d-R3RVdOZV5xqb9syho_L0-CFq0PPJdI,589
288
291
  odxtools/templates/macros/printDiagComm.xml.jinja2,sha256=pw0cB-eHWL9sG_iTPRSR9D4z_vdw3oasQ76NWRL1pUY,2378
289
292
  odxtools/templates/macros/printDiagCommDataConnector.xml.jinja2,sha256=jWnhlpsM-IvjYDbY19xG5vLy6DDUdfhP-vDDgNfIUWk,2917
290
- odxtools/templates/macros/printDiagLayer.xml.jinja2,sha256=ZbeKP0UtJfV-yCL-fZ4GzCCj-ndlLk9iIHhPOr0clmw,6943
293
+ odxtools/templates/macros/printDiagDataDictionarySpec.xml.jinja2,sha256=7mtgWV9VWFQv8ZPE6VbONna-MWufsdfSwmXID-hFYHg,3364
294
+ odxtools/templates/macros/printDiagLayer.xml.jinja2,sha256=eoHepbwCRpKc7E-H43C3oL07qAl1qm25rYtv7x5BxKo,4218
291
295
  odxtools/templates/macros/printDiagVariable.xml.jinja2,sha256=SuJKQvlfaUEJo7kvNnKQeKyRBL_agxzZ7Hek16OdpoE,3178
292
296
  odxtools/templates/macros/printDynDefinedSpec.xml.jinja2,sha256=AuvP0Rvfd29o4xkBSxpIcS6g7OBMyfBTf1pMlS11Sus,1746
293
297
  odxtools/templates/macros/printDynamicEndmarkerField.xml.jinja2,sha256=xO_FxjCecLwE1FU16AlT_NDKb261w5z3oE8I-kxux74,591
@@ -297,19 +301,20 @@ odxtools/templates/macros/printEcuMemConnector.xml.jinja2,sha256=eS_m0zyXxJK0lYW
297
301
  odxtools/templates/macros/printEcuSharedData.xml.jinja2,sha256=WK08eoDFEjj9o3eOuy__H0r9ioo688rTuQp6uXE6Tdo,820
298
302
  odxtools/templates/macros/printEcuVariant.xml.jinja2,sha256=Nsgj2VUWZvSDFPQsn6wv75M9TaryOB-tlQYCVq9hDEM,1594
299
303
  odxtools/templates/macros/printEcuVariantPattern.xml.jinja2,sha256=YoYyzmxerJLJzUNoQ8H-JBnOqiwpVdODqk2KNRdWKWo,844
300
- odxtools/templates/macros/printElementId.xml.jinja2,sha256=Oe4sgtBB_VhTz6uJzaiTCpQki2ulKKfpBq56FVgBC-I,570
304
+ odxtools/templates/macros/printElementId.xml.jinja2,sha256=1Ykzcq2hF5qAFE5Q8Wb9j8_fSEuNmwxkZcbBaHE78yA,615
301
305
  odxtools/templates/macros/printEndOfPdu.xml.jinja2,sha256=ezcZpkRnOGXKkExVXceI9EKudoZAx2ch7qMOsfDVzoU,681
302
306
  odxtools/templates/macros/printEnvData.xml.jinja2,sha256=2Goatqb66d-pCf9wqJDXn1EZWNhkQ8FJANKQMOnxuJs,609
303
307
  odxtools/templates/macros/printEnvDataDesc.xml.jinja2,sha256=RSICw9XQzIhkGbbI9rvdKCmM50DHuVpPjnsXxVGe2bY,590
304
308
  odxtools/templates/macros/printExpectedIdent.xml.jinja2,sha256=YdAjL8GEfs3jv8vAIDxZbMc2KSDGlun5NVsb7VhQWug,665
305
309
  odxtools/templates/macros/printFlashdata.xml.jinja2,sha256=9hvB93SW_0xSxrBXgiRgAcqPWa4vR3C_8yMTxjq8Cvk,1815
306
- odxtools/templates/macros/printFunctionalClass.xml.jinja2,sha256=o6_YZhmULzsC2WJZEpV8Z8iEW6myztY9FwNli9t42LM,490
310
+ odxtools/templates/macros/printFunctionalClass.xml.jinja2,sha256=OajJ-DvcWu5Hk9HHBWF5IpgopYJEkW9kC9Ip_dM8LFI,492
307
311
  odxtools/templates/macros/printFunctionalGroup.xml.jinja2,sha256=zIeZbhf8haXhgJJUPiOnMe3lvqvfye4-zmwWDQJxFtQ,1159
308
312
  odxtools/templates/macros/printHierarchyElement.xml.jinja2,sha256=GD6iNIE0Wu0QsJ8uLtwEV8N9t6mIhI00_KpCVzOVQBM,651
309
313
  odxtools/templates/macros/printIdentDesc.xml.jinja2,sha256=r4FX9zurKH0gBi_lTUJBHL8aurF7wVmE0jLpleJK7Ak,614
310
314
  odxtools/templates/macros/printItemValue.xml.jinja2,sha256=z7mxGVuLGMCvD8QA4JuxDuQt7v0c2TSDf6VcX9PZxZE,1199
311
315
  odxtools/templates/macros/printLibrary.xml.jinja2,sha256=wp8vZzHPLZayWZh6BOQ56kGyHSeyrlNacdlxBw9d0N0,683
312
316
  odxtools/templates/macros/printMem.xml.jinja2,sha256=aZ3bYZ5LMDzsBQGDa5SCiVCkaHOI4OBgvWJ1w8jSQPU,935
317
+ odxtools/templates/macros/printMultipleEcuJob.xml.jinja2,sha256=amlu1l4D6wRi2cnTiFa9vQeKHjTig0r4hsls2jhGBAs,3082
313
318
  odxtools/templates/macros/printMux.xml.jinja2,sha256=lSJEOac8paS57A_pA0vzNNiDUMvizTvLrY7Poau5LR4,1875
314
319
  odxtools/templates/macros/printOdxCategory.xml.jinja2,sha256=82uLhYpQfi9eE_3d8_JUk_LFh3uiwfC2o34l14DI0II,829
315
320
  odxtools/templates/macros/printOwnIdent.xml.jinja2,sha256=NuEUrmFiyNE-f95EKMuk4Pn_SCSn5iEkbqr02s0sV2Y,544
@@ -338,9 +343,9 @@ odxtools/templates/macros/printStructure.xml.jinja2,sha256=M8p82SlgKaDk6nJA-0wr6
338
343
  odxtools/templates/macros/printSubComponent.xml.jinja2,sha256=R3DxnK6NysUQL84uf2kGYMoF_VVym2l7H-J0JZ1uLKc,3416
339
344
  odxtools/templates/macros/printTable.xml.jinja2,sha256=iMmq4tSFl_nc44HNdFqzk4XLYjrbQ73cKm7kMVdRLmc,3336
340
345
  odxtools/templates/macros/printUnitSpec.xml.jinja2,sha256=pgZdrPdWi3OGtDIFNpEDz_TQs103uuRQoDdmGkNffOM,2878
341
- odxtools-10.3.0.dist-info/licenses/LICENSE,sha256=NeGPFQdTa6EKeON3aShVlPAIquJnbbiOfj0suz6rzyQ,1074
342
- odxtools-10.3.0.dist-info/METADATA,sha256=_CHHDpFXH3dskoC9eXGLocoSszuinHrzhmDb49x9w2Y,44054
343
- odxtools-10.3.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
344
- odxtools-10.3.0.dist-info/entry_points.txt,sha256=_sBDzuNoT8LbbCjfc-OJiUt5WPrtOq_x-rr9txhrPjY,53
345
- odxtools-10.3.0.dist-info/top_level.txt,sha256=pdS02kE5ZdgsaBRZDpX3NBFlaSx3zotsqX4E4V6tXEI,9
346
- odxtools-10.3.0.dist-info/RECORD,,
346
+ odxtools-10.4.0.dist-info/licenses/LICENSE,sha256=NeGPFQdTa6EKeON3aShVlPAIquJnbbiOfj0suz6rzyQ,1074
347
+ odxtools-10.4.0.dist-info/METADATA,sha256=4ECV1XPqKUcNCxO-fjRG5tDsf_g0sYNS-ywa3yCMFEs,44054
348
+ odxtools-10.4.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
349
+ odxtools-10.4.0.dist-info/entry_points.txt,sha256=_sBDzuNoT8LbbCjfc-OJiUt5WPrtOq_x-rr9txhrPjY,53
350
+ odxtools-10.4.0.dist-info/top_level.txt,sha256=pdS02kE5ZdgsaBRZDpX3NBFlaSx3zotsqX4E4V6tXEI,9
351
+ odxtools-10.4.0.dist-info/RECORD,,