odxtools 7.3.0__py3-none-any.whl → 7.4.1__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.
Files changed (34) hide show
  1. odxtools/cli/_print_utils.py +3 -3
  2. odxtools/cli/browse.py +4 -2
  3. odxtools/cli/list.py +3 -3
  4. odxtools/commrelation.py +122 -0
  5. odxtools/comparaminstance.py +1 -1
  6. odxtools/comparamspec.py +1 -2
  7. odxtools/diaglayer.py +13 -8
  8. odxtools/diaglayerraw.py +116 -23
  9. odxtools/diagvariable.py +104 -0
  10. odxtools/dyndefinedspec.py +179 -0
  11. odxtools/environmentdatadescription.py +3 -2
  12. odxtools/odxlink.py +7 -21
  13. odxtools/parameterinfo.py +10 -1
  14. odxtools/parameters/tablekeyparameter.py +11 -4
  15. odxtools/servicebinner.py +1 -1
  16. odxtools/specialdatagroup.py +1 -1
  17. odxtools/swvariable.py +21 -0
  18. odxtools/templates/macros/printComparam.xml.jinja2 +4 -2
  19. odxtools/templates/macros/printCompuMethod.xml.jinja2 +1 -8
  20. odxtools/templates/macros/printDiagVariable.xml.jinja2 +66 -0
  21. odxtools/templates/macros/printDynDefinedSpec.xml.jinja2 +48 -0
  22. odxtools/templates/macros/printEcuVariantPattern.xml.jinja2 +1 -1
  23. odxtools/templates/macros/printParam.xml.jinja2 +7 -8
  24. odxtools/templates/macros/printService.xml.jinja2 +3 -2
  25. odxtools/templates/macros/printSingleEcuJob.xml.jinja2 +2 -2
  26. odxtools/templates/macros/printVariant.xml.jinja2 +30 -13
  27. odxtools/variablegroup.py +22 -0
  28. odxtools/version.py +2 -2
  29. {odxtools-7.3.0.dist-info → odxtools-7.4.1.dist-info}/METADATA +18 -18
  30. {odxtools-7.3.0.dist-info → odxtools-7.4.1.dist-info}/RECORD +34 -27
  31. {odxtools-7.3.0.dist-info → odxtools-7.4.1.dist-info}/WHEEL +1 -1
  32. {odxtools-7.3.0.dist-info → odxtools-7.4.1.dist-info}/LICENSE +0 -0
  33. {odxtools-7.3.0.dist-info → odxtools-7.4.1.dist-info}/entry_points.txt +0 -0
  34. {odxtools-7.3.0.dist-info → odxtools-7.4.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,179 @@
1
+ # SPDX-License-Identifier: MIT
2
+ from dataclasses import dataclass
3
+ from typing import Any, Dict, List, Optional, Union
4
+ from xml.etree import ElementTree
5
+
6
+ from .diagcomm import DiagClassType, DiagComm
7
+ from .exceptions import odxraise, odxrequire
8
+ from .nameditemlist import NamedItemList
9
+ from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId, OdxLinkRef, resolve_snref
10
+ from .snrefcontext import SnRefContext
11
+ from .table import Table
12
+
13
+
14
+ @dataclass
15
+ class DynIdDefModeInfo:
16
+ def_mode: str
17
+
18
+ clear_dyn_def_message_ref: Optional[OdxLinkRef]
19
+ clear_dyn_def_message_snref: Optional[str]
20
+
21
+ read_dyn_def_message_ref: Optional[OdxLinkRef]
22
+ read_dyn_def_message_snref: Optional[str]
23
+
24
+ dyn_def_message_ref: Optional[OdxLinkRef]
25
+ dyn_def_message_snref: Optional[str]
26
+
27
+ supported_dyn_ids: List[bytes]
28
+ selection_table_refs: List[Union[OdxLinkRef, str]]
29
+
30
+ @property
31
+ def clear_dyn_def_message(self) -> DiagComm:
32
+ return self._clear_dyn_def_message
33
+
34
+ @property
35
+ def read_dyn_def_message(self) -> DiagComm:
36
+ return self._read_dyn_def_message
37
+
38
+ @property
39
+ def dyn_def_message(self) -> DiagComm:
40
+ return self._dyn_def_message
41
+
42
+ @property
43
+ def selection_tables(self) -> NamedItemList[Table]:
44
+ return self._selection_tables
45
+
46
+ @staticmethod
47
+ def from_et(et_element: ElementTree.Element,
48
+ doc_frags: List[OdxDocFragment]) -> "DynIdDefModeInfo":
49
+ def_mode = odxrequire(et_element.findtext("DEF-MODE"))
50
+
51
+ clear_dyn_def_message_ref = OdxLinkRef.from_et(
52
+ et_element.find("CLEAR-DYN-DEF-MESSAGE-REF"), doc_frags)
53
+ if (snref_elem := et_element.find("CLEAR-DYN-DEF-MESSAGE-SNREF")) is not None:
54
+ clear_dyn_def_message_snref = snref_elem.attrib["SHORT-NAME"]
55
+
56
+ read_dyn_def_message_ref = OdxLinkRef.from_et(
57
+ et_element.find("READ-DYN-DEF-MESSAGE-REF"), doc_frags)
58
+ if (snref_elem := et_element.find("READ-DYN-DEF-MESSAGE-SNREF")) is not None:
59
+ read_dyn_def_message_snref = snref_elem.attrib["SHORT-NAME"]
60
+
61
+ dyn_def_message_ref = OdxLinkRef.from_et(et_element.find("DYN-DEF-MESSAGE-REF"), doc_frags)
62
+ if (snref_elem := et_element.find("DYN-DEF-MESSAGE-SNREF")) is not None:
63
+ dyn_def_message_snref = snref_elem.attrib["SHORT-NAME"]
64
+
65
+ supported_dyn_ids = [
66
+ bytes.fromhex(odxrequire(x.text))
67
+ for x in et_element.iterfind("SUPPORTED-DYN-IDS/SUPPORTED-DYN-ID")
68
+ ]
69
+
70
+ selection_table_refs: List[Union[OdxLinkRef, str]] = []
71
+ if (st_elems := et_element.find("SELECTION-TABLE-REFS")) is not None:
72
+ for st_elem in st_elems:
73
+ if st_elem.tag == "SELECTION-TABLE-REF":
74
+ selection_table_refs.append(OdxLinkRef.from_et(st_elem, doc_frags))
75
+ elif st_elem.tag == "SELECTION-TABLE-SNREF":
76
+ selection_table_refs.append(odxrequire(st_elem.get("SHORT-NAME")))
77
+ else:
78
+ odxraise()
79
+
80
+ return DynIdDefModeInfo(
81
+ def_mode=def_mode,
82
+ clear_dyn_def_message_ref=clear_dyn_def_message_ref,
83
+ clear_dyn_def_message_snref=clear_dyn_def_message_snref,
84
+ read_dyn_def_message_ref=read_dyn_def_message_ref,
85
+ read_dyn_def_message_snref=read_dyn_def_message_snref,
86
+ dyn_def_message_ref=dyn_def_message_ref,
87
+ dyn_def_message_snref=dyn_def_message_snref,
88
+ supported_dyn_ids=supported_dyn_ids,
89
+ selection_table_refs=selection_table_refs,
90
+ )
91
+
92
+ def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
93
+ result: Dict[OdxLinkId, Any] = {}
94
+
95
+ return result
96
+
97
+ def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
98
+ self._selection_tables = NamedItemList[Table]()
99
+
100
+ if self.clear_dyn_def_message_ref is not None:
101
+ self._clear_dyn_def_message = odxlinks.resolve(self.clear_dyn_def_message_ref, DiagComm)
102
+
103
+ if self.read_dyn_def_message_ref is not None:
104
+ self._read_dyn_def_message = odxlinks.resolve(self.read_dyn_def_message_ref, DiagComm)
105
+
106
+ if self.dyn_def_message_ref is not None:
107
+ self._dyn_def_message = odxlinks.resolve(self.dyn_def_message_ref, DiagComm)
108
+
109
+ # resolve the selection tables referenced using ODXLINK
110
+ for x in self.selection_table_refs:
111
+ if isinstance(x, OdxLinkRef):
112
+ self._selection_tables.append(odxlinks.resolve(x, Table))
113
+
114
+ def _resolve_snrefs(self, context: SnRefContext) -> None:
115
+ diag_layer = odxrequire(context.diag_layer)
116
+
117
+ if self.clear_dyn_def_message_snref is not None:
118
+ self._clear_dyn_def_message = resolve_snref(self.clear_dyn_def_message_snref,
119
+ diag_layer.diag_comms, DiagComm)
120
+
121
+ if self.read_dyn_def_message_snref is not None:
122
+ self._read_dyn_def_message = resolve_snref(self.read_dyn_def_message_snref,
123
+ diag_layer.diag_comms, DiagComm)
124
+
125
+ if self.dyn_def_message_snref is not None:
126
+ self._dyn_def_message = resolve_snref(self.dyn_def_message_snref, diag_layer.diag_comms,
127
+ DiagComm)
128
+
129
+ if self._clear_dyn_def_message.diagnostic_class != DiagClassType.CLEAR_DYN_DEF_MESSAGE:
130
+ odxraise(
131
+ f"Diagnostic communication object of wrong type referenced: "
132
+ f"({odxrequire(self._clear_dyn_def_message.diagnostic_class).value} instead of "
133
+ f"CLEAR-DYN-DEF-MESSAGE)")
134
+ if self._read_dyn_def_message.diagnostic_class != DiagClassType.READ_DYN_DEFINED_MESSAGE:
135
+ odxraise(f"Diagnostic communication object of wrong type referenced: "
136
+ f"({odxrequire(self._read_dyn_def_message.diagnostic_class).value} instead of "
137
+ f"READ-DYN-DEFINED-MESSAGE)")
138
+ if self._dyn_def_message.diagnostic_class != DiagClassType.DYN_DEF_MESSAGE:
139
+ odxraise(f"Diagnostic communication object of wrong type referenced: "
140
+ f"({odxrequire(self._dyn_def_message.diagnostic_class).value} instead of "
141
+ f"DYN-DEF-MESSAGE)")
142
+
143
+ # resolve the remaining selection tables that are referenced via SNREF
144
+ for i, x in enumerate(self.selection_table_refs):
145
+ if isinstance(x, str):
146
+ ddd_spec = odxrequire(diag_layer.diag_data_dictionary_spec)
147
+ self._selection_tables.insert(i, resolve_snref(x, ddd_spec.tables, Table))
148
+
149
+
150
+ @dataclass
151
+ class DynDefinedSpec:
152
+ dyn_id_def_mode_infos: List[DynIdDefModeInfo]
153
+
154
+ @staticmethod
155
+ def from_et(et_element: ElementTree.Element,
156
+ doc_frags: List[OdxDocFragment]) -> "DynDefinedSpec":
157
+ dyn_id_def_mode_infos = [
158
+ DynIdDefModeInfo.from_et(x, doc_frags)
159
+ for x in et_element.iterfind("DYN-ID-DEF-MODE-INFOS/DYN-ID-DEF-MODE-INFO")
160
+ ]
161
+ return DynDefinedSpec(dyn_id_def_mode_infos=dyn_id_def_mode_infos)
162
+
163
+ def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
164
+ result: Dict[OdxLinkId, Any] = {}
165
+
166
+ result.update(self._build_odxlinks())
167
+
168
+ for didmi in self.dyn_id_def_mode_infos:
169
+ result.update(didmi._build_odxlinks())
170
+
171
+ return result
172
+
173
+ def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
174
+ for didmi in self.dyn_id_def_mode_infos:
175
+ didmi._resolve_odxlinks(odxlinks)
176
+
177
+ def _resolve_snrefs(self, context: SnRefContext) -> None:
178
+ for didmi in self.dyn_id_def_mode_infos:
179
+ didmi._resolve_snrefs(context)
@@ -83,8 +83,9 @@ class EnvironmentDataDescription(ComplexDop):
83
83
  def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
84
84
  odxlinks = {self.odx_id: self}
85
85
 
86
- for ed in self.env_datas:
87
- odxlinks.update(ed._build_odxlinks())
86
+ if not self.env_data_refs:
87
+ for ed in self.env_datas:
88
+ odxlinks.update(ed._build_odxlinks())
88
89
 
89
90
  return odxlinks
90
91
 
odxtools/odxlink.py CHANGED
@@ -4,29 +4,14 @@ from dataclasses import dataclass
4
4
  from typing import Any, Dict, Iterable, List, Optional, Type, TypeVar, overload
5
5
  from xml.etree import ElementTree
6
6
 
7
- from .exceptions import OdxWarning, odxassert, odxraise
7
+ from .exceptions import OdxWarning, odxassert, odxraise, odxrequire
8
8
  from .nameditemlist import OdxNamed, TNamed
9
9
 
10
10
 
11
11
  @dataclass(frozen=True)
12
12
  class OdxDocFragment:
13
13
  doc_name: str
14
- doc_type: Optional[str]
15
-
16
- def __eq__(self, other: Any) -> bool:
17
- if other is None:
18
- # if the other document fragment is not specified, we
19
- # treat it as a wildcard...
20
- return True
21
-
22
- if not isinstance(other, OdxDocFragment):
23
- return False
24
-
25
- # the ODX spec says that the doctype can be ignored...
26
- return self.doc_name == other.doc_name
27
-
28
- def __hash__(self) -> int:
29
- return hash(self.doc_name) + hash(self.doc_type)
14
+ doc_type: str
30
15
 
31
16
 
32
17
  @dataclass(frozen=True)
@@ -121,6 +106,7 @@ class OdxLinkRef:
121
106
 
122
107
  id_ref = et.attrib.get("ID-REF")
123
108
  if id_ref is None:
109
+ odxraise(f"Tag {et.tag} is not a ODXLINK reference")
124
110
  return None
125
111
 
126
112
  doc_ref = et.attrib.get("DOCREF")
@@ -134,7 +120,7 @@ class OdxLinkRef:
134
120
  # reference, use it, else use the document fragment containing
135
121
  # the reference.
136
122
  if doc_ref is not None:
137
- doc_frags = [OdxDocFragment(doc_ref, doc_type)]
123
+ doc_frags = [OdxDocFragment(doc_ref, odxrequire(doc_type))]
138
124
  else:
139
125
  doc_frags = source_doc_frags
140
126
 
@@ -154,9 +140,9 @@ T = TypeVar("T")
154
140
 
155
141
  class OdxLinkDatabase:
156
142
  """
157
- A database holding all objects which ehibit OdxLinkIds
143
+ A database holding all objects which exhibit OdxLinkIds
158
144
 
159
- This can resolve references to such.
145
+ This can resolve ODXLINK references.
160
146
  """
161
147
 
162
148
  def __init__(self) -> None:
@@ -182,7 +168,7 @@ class OdxLinkDatabase:
182
168
  if doc_frag_db is None:
183
169
  # No object featured by the database uses the document
184
170
  # fragment mentioned by the reference. This should not
185
- # happen for correct databases...
171
+ # happen for correct ODX databases...
186
172
  warnings.warn(
187
173
  f"Warning: Unknown document fragment {ref_frag} "
188
174
  f"when resolving reference {ref}",
odxtools/parameterinfo.py CHANGED
@@ -132,7 +132,16 @@ def parameter_info(param_list: Iterable[Parameter], quoted_names: bool = False)
132
132
  val_str = ""
133
133
  if scale.lower_limit is not None:
134
134
  val_str = f"({repr(scale.lower_limit.value)})"
135
- of.write(f" {repr(scale.compu_const)}{val_str}\n")
135
+
136
+ if scale.compu_const is None:
137
+ of.write(f" <ERROR in ODX data: no value specified>\n")
138
+ else:
139
+ vt = scale.compu_const.vt
140
+ v = scale.compu_const.v
141
+ if vt is not None:
142
+ of.write(f" \"{vt}\" {val_str}\n")
143
+ else:
144
+ of.write(f" {v}\n")
136
145
 
137
146
  elif isinstance(cm, IdenticalCompuMethod):
138
147
  bdt = dop.physical_type.base_data_type
@@ -99,13 +99,20 @@ class TableKeyParameter(Parameter):
99
99
 
100
100
  if self.table_snref is not None:
101
101
  tables = odxrequire(context.diag_layer).diag_data_dictionary_spec.tables
102
- self._table = resolve_snref(self.table_snref, tables, Table)
102
+ if TYPE_CHECKING:
103
+ self._table = resolve_snref(self.table_snref, tables, Table)
104
+ else:
105
+ self._table = resolve_snref(self.table_snref, tables)
103
106
  if self.table_row_snref is not None:
104
107
  # make sure that we know the table to which the table row
105
108
  # SNREF is relative to.
106
- table = odxrequire(self._table,
107
- "If a table-row is referenced, a table must also be referenced.")
108
- self._table_row = resolve_snref(self.table_row_snref, table.table_rows, TableRow)
109
+ table = odxrequire(
110
+ self._table, "If a table row is referenced via short name, a table must "
111
+ "be referenced as well")
112
+ if TYPE_CHECKING:
113
+ self._table_row = resolve_snref(self.table_row_snref, table.table_rows, TableRow)
114
+ else:
115
+ self._table_row = resolve_snref(self.table_row_snref, table.table_rows)
109
116
 
110
117
  @property
111
118
  def table(self) -> "Table":
odxtools/servicebinner.py CHANGED
@@ -91,7 +91,7 @@ class ServiceBinner:
91
91
  """
92
92
  result = StringIO()
93
93
  result.write("[ ")
94
- result.write(", ".join([f"0x{x}" for x in self._service_groups if x is not None]))
94
+ result.write(", ".join([f"0x{x:x}" for x in self._service_groups if x is not None]))
95
95
  result.write(" ]")
96
96
 
97
97
  return result.getvalue()
@@ -51,7 +51,7 @@ class SpecialDataGroup:
51
51
  def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
52
52
  result = {}
53
53
 
54
- if self.sdg_caption is not None:
54
+ if self.sdg_caption_ref is None and self.sdg_caption is not None:
55
55
  result.update(self.sdg_caption._build_odxlinks())
56
56
 
57
57
  for val in self.values:
odxtools/swvariable.py ADDED
@@ -0,0 +1,21 @@
1
+ # SPDX-License-Identifier: MIT
2
+ from dataclasses import dataclass
3
+ from typing import List, Optional
4
+ from xml.etree import ElementTree
5
+
6
+ from .element import NamedElement
7
+ from .odxlink import OdxDocFragment
8
+ from .utils import dataclass_fields_asdict
9
+
10
+
11
+ @dataclass
12
+ class SwVariable(NamedElement):
13
+ origin: Optional[str]
14
+
15
+ @staticmethod
16
+ def from_et(et_element: ElementTree.Element, doc_frags: List[OdxDocFragment]) -> "SwVariable":
17
+ kwargs = dataclass_fields_asdict(NamedElement.from_et(et_element, doc_frags))
18
+
19
+ origin = et_element.findtext("ORIGIN")
20
+
21
+ return SwVariable(origin=origin, **kwargs)
@@ -44,7 +44,9 @@
44
44
  {{make_xml_attrib("DISPLAY-LEVEL", cp.display_level)}}{#- #}
45
45
  CPUSAGE="{{cp.cpusage.value}}">
46
46
  {{ peid.printElementIdSubtags(cp)|indent(1) }}
47
- <PHYSICAL-DEFAULT-VALUE>{{cp.physical_default_value}}</PHYSICAL-DEFAULT-VALUE>
47
+ {%- if cp.physical_default_value is not none %}
48
+ <PHYSICAL-DEFAULT-VALUE>{{cp.physical_default_value | e}}</PHYSICAL-DEFAULT-VALUE>
49
+ {%- endif %}
48
50
  <DATA-OBJECT-PROP-REF ID-REF="{{cp.dop_ref.ref_id}}" />
49
51
  </COMPARAM>
50
52
  {%- endmacro %}
@@ -61,7 +63,7 @@
61
63
  {%- for sub_cp in cp.subparams %}
62
64
  {{- printAnyComparam(sub_cp) | indent(1, first=True) }}
63
65
  {%- endfor %}
64
- {%- if cp.physical_default_value is not none %}
66
+ {%- if cp.physical_default_value is not none %}
65
67
  {{ printComplexValue(cp.physical_default_value, "COMPLEX-PHYSICAL-DEFAULT-VALUE") | indent(1) }}
66
68
  {%- endif %}
67
69
  </COMPLEX-COMPARAM>
@@ -18,14 +18,7 @@
18
18
  {%- if limit_obj.value_raw is none %}
19
19
  {#- #}/>
20
20
  {%- else %}
21
- {#- #}>
22
- {%- if hasattr(limit_obj._value, 'hex') -%}
23
- {#- bytes or bytarray limit #}
24
- {{- limit_obj._value.hex().upper() }}
25
- {%- else -%}
26
- {{- limit_obj._value }}
27
- {%- endif -%}
28
- </{{tag_name}}>
21
+ {#- #}>{{- limit_obj.value_raw | e }}</{{tag_name}}>
29
22
  {%- endif -%}
30
23
  {%- endif -%}
31
24
  {%- endmacro -%}
@@ -0,0 +1,66 @@
1
+ {#- -*- mode: sgml; tab-width: 2; indent-tabs-mode: nil -*-
2
+ #
3
+ # SPDX-License-Identifier: MIT
4
+ -#}
5
+ {%- import('macros/printElementId.xml.jinja2') as peid %}
6
+ {%- import('macros/printAdminData.xml.jinja2') as pad %}
7
+ {%- import('macros/printDescription.xml.jinja2') as pd %}
8
+
9
+ {%- macro printDiagVariable(diag_var) -%}
10
+ <DIAG-VARIABLE>
11
+ {{ peid.printElementIdSubtags(diag_variable)|indent(2) }}
12
+ {%- if diag_variable.admin_data is not none %}
13
+ {{ pad.printAdminData(diag_variable.admin_data)|indent(2) }}
14
+ {%- endif %}
15
+ <VARIABLE-GROUP-REF ID-REF="{{ diag_var.ref_id }}" />
16
+ {%- if diag_variable.sw_variables %}
17
+ <SW-VARIABLES>
18
+ {%- for sw_var in diag_variable.sw_variables %}
19
+ <SW-VARIABLE>
20
+ {{ peid.printElementIdSubtags(sw_var)|indent(6) }}
21
+ {%- if sw_var.origin is not none %}
22
+ <ORIGIN>{{ sw_var.origin }}</ORIGIN>
23
+ {%- endif %}
24
+ </SW-VARIABLE>
25
+ {%- endfor %}
26
+ </SW-VARIABLES>
27
+ {%- endif %}
28
+ {%- if diag_variable.comm_relations %}
29
+ <COMM-RELATIONS>
30
+ {%- for comm_relation in diag_variable.comm_relations %}
31
+ <COMM-RELATION>
32
+ {{ pd.printDescription(comm_relation.description) }}
33
+ <RELATION-TYPE>{{comm_relation.relation_type}}</RELATION-TYPE>
34
+ {%- if comm_relation.diag_comm_ref is not none %}
35
+ <DIAG-COMM-REF ID-REF="{{comm_relation.diag_comm_ref.ref_id}}" />
36
+ {%- endif %}
37
+ {%- if comm_relation.diag_comm_snref is not none %}
38
+ <DIAG-COMM-SNREF SHORT-NAME="{{comm_relation.diag_comm_snref}}" />
39
+ {%- endif %}
40
+ {%- if comm_relation.in_param_if_ref is not none %}
41
+ <IN-PARAM-IF-REF ID-REF="{{comm_relation.in_param_if_ref.ref_id}}" />
42
+ {%- endif %}
43
+ {%- if comm_relation.in_param_if_snref is not none %}
44
+ <IN-PARAM-IF-SNREF SHORT-NAME="{{comm_relation.in_param_if_snref}}" />
45
+ {%- endif %}
46
+ {%- if comm_relation.out_param_if_ref is not none %}
47
+ <OUT-PARAM-IF-REF ID-REF="{{comm_relation.out_param_if_ref.ref_id}}" />
48
+ {%- endif %}
49
+ {%- if comm_relation.out_param_if_snref is not none %}
50
+ <OUT-PARAM-IF-SNREF SHORT-NAME="{{comm_relation.out_param_if_snref}}" />
51
+ {%- endif %}
52
+ {%- if comm_relation.value_type_raw is not none %}
53
+ <VALUE-TYPE>{{comm_relation.value_type_raw.value}}</VALUE-TYPE>
54
+ {%- endif %}
55
+ <COMM-RELATION>
56
+ {%- endfor %}
57
+ </COMM-RELATIONS>
58
+ {%- endif %}
59
+ </DIAG-VARIABLE>
60
+ {%- endmacro -%}
61
+
62
+ {%- macro printVariableGroup(var_group) -%}
63
+ <VARIABLE-GROUP>
64
+ {{ peid.printElementIdSubtags(diag_variable)|indent(2) }}
65
+ </VARIABLE-GROUP>
66
+ {%- endmacro -%}
@@ -0,0 +1,48 @@
1
+ {#- -*- mode: sgml; tab-width: 2; indent-tabs-mode: nil -*-
2
+ #
3
+ # SPDX-License-Identifier: MIT
4
+ -#}
5
+
6
+ {%- macro printDynDefinedSpec(dd_spec) -%}
7
+ <DYN-DEFINED-SPEC>
8
+ {%- if dd_spec.dyn_id_def_mode_infos %}
9
+ <DYN-ID-DEF-MODE-INFOS>
10
+ {%- for diddmi in dd_spec.dyn_id_def_mode_infos %}
11
+ <DYN-ID-DEF-MODE-INFO>
12
+ <DEF-MODE>{{ diddmi.def_mode }}</DEF-MODE>
13
+ {%- if diddmi.clear_dyn_def_message_ref is not none %}
14
+ <CLEAR-DYN-DEF-MESSAGE-REF ID-REF="{{diddmi.clear_dyn_def_message_ref.ref_id}}" />
15
+ {%- endif %}
16
+ {%- if diddmi.clear_dyn_def_message_snref is not none %}
17
+ <CLEAR-DYN-DEF-MESSAGE-SNREF SHORT-NAME="{{diddmi.clear_dyn_def_message_snref}}" />
18
+ {%- endif %}
19
+ {%- if diddmi.read_dyn_def_message_ref is not none %}
20
+ <READ-DYN-DEF-MESSAGE-REF ID-REF="{{diddmi.read_dyn_def_message_ref.ref_id}}" />
21
+ {%- endif %}
22
+ {%- if diddmi.read_dyn_def_message_snref is not none %}
23
+ <READ-DYN-DEF-MESSAGE-SNREF SHORT-NAME="{{diddmi.read_dyn_def_message_snref}}" />
24
+ {%- endif %}
25
+ {%- if diddmi.supported_dyn_ids %}
26
+ <SUPPORTED-DYN-IDS>
27
+ {%- for dynid in diddmi.supported_dyn_ids %}
28
+ <SUPPORTED-DYN-ID>{{ dynid.hex() }}</SUPPORTED-DYN-ID>
29
+ {%- endfor %}
30
+ </SUPPORTED-DYN-IDS>
31
+ {%- endif %}
32
+ {%- if diddmi.selection_table_refs %}
33
+ <SELECTION-TABLE-REFS>
34
+ {%- for seltref in diddmi.selection_table_refs %}
35
+ {%- if hasattr(seltref, "ref_id") %}
36
+ <SELECTION-TABLE-REF ID-REF="{{ seltref.ref_id }}" />
37
+ {%- else %}
38
+ <SELECTION-TABLE-SNREF SHORT-NAME="{{ seltref }}" />
39
+ {%- endif %}
40
+ {%- endfor %}
41
+ </SELECTION-TABLE-REFS>
42
+ {%- endif %}
43
+ </DYN-ID-DEF-MODE-INFO>
44
+ {%- endfor %}
45
+ </DYN-ID-DEF-MODE-INFOS>
46
+ {%- endif %}
47
+ </DYN-DEFINED-SPEC>
48
+ {%- endmacro -%}
@@ -9,7 +9,7 @@
9
9
 
10
10
  {%- macro printMatchingParameter(mp) -%}
11
11
  <MATCHING-PARAMETER>
12
- <EXPECTED-VALUE>{{mp.expected_value}}</EXPECTED-VALUE>
12
+ <EXPECTED-VALUE>{{mp.expected_value | e}}</EXPECTED-VALUE>
13
13
  <DIAG-COMM-SNREF SHORT-NAME="{{mp.diag_comm_snref}}" />
14
14
  {#- TODO: OUT-PARAM-IF-SNPATHREF #}
15
15
  <OUT-PARAM-IF-SNREF SHORT-NAME="{{mp.out_param_if}}" />
@@ -35,8 +35,6 @@
35
35
  {%- endif %}
36
36
  {%- if param.coded_value is defined %}
37
37
  <CODED-VALUE>{{param.coded_value}}</CODED-VALUE>
38
- {%- elif param.physical_constant_value_raw is defined %}
39
- <PHYS-CONSTANT-VALUE>{{param.physical_constant_value_raw}}</PHYS-CONSTANT-VALUE>
40
38
  {%- elif param.coded_values is defined %}
41
39
  <CODED-VALUES>
42
40
  {%- for coded_value in param.coded_values %}
@@ -44,8 +42,11 @@
44
42
  {%- endfor %}
45
43
  </CODED-VALUES>
46
44
  {%- endif %}
47
- {%- if param.physical_default_value_raw %}
48
- <PHYSICAL-DEFAULT-VALUE>{{param.physical_default_value_raw}}</PHYSICAL-DEFAULT-VALUE>
45
+ {%- if param.physical_constant_value_raw is defined %}
46
+ <PHYS-CONSTANT-VALUE>{{param.physical_constant_value_raw}}</PHYS-CONSTANT-VALUE>
47
+ {%- endif %}
48
+ {%- if param.physical_default_value_raw is defined and param.physical_default_value_raw is not none %}
49
+ <PHYSICAL-DEFAULT-VALUE>{{param.physical_default_value_raw | e}}</PHYSICAL-DEFAULT-VALUE>
49
50
  {%- endif %}
50
51
  {%- if param.dop_ref %}
51
52
  <DOP-REF ID-REF="{{param.dop_ref.ref_id}}"/>
@@ -53,10 +54,8 @@
53
54
  <DOP-SNREF SN="{{param.dop_snref}}"/>
54
55
  {%- elif param.diag_coded_type is defined %}
55
56
  {{pdop.printDiagCodedType(param.diag_coded_type)|indent(2)}}
56
- {%- elif param.parameter_type != "MATCHING-REQUEST-PARAM" %}
57
- {%- if param.bit_length is defined and param.bit_length is not none %}
58
- <BIT-LENGTH>{{param.bit_length}}</BIT-LENGTH>
59
- {%- endif %}
57
+ {%- elif param.bit_length is defined and param.bit_length is not none %}
58
+ <BIT-LENGTH>{{param.bit_length}}</BIT-LENGTH>
60
59
  {%- endif %}
61
60
  {%- if param.parameter_type == "TABLE-KEY" %}
62
61
  {%- if param.table_ref %}
@@ -4,6 +4,7 @@
4
4
  -#}
5
5
 
6
6
  {%- import('macros/printDiagComm.xml.jinja2') as pdc %}
7
+ {%- import('macros/printComparamRef.xml.jinja2') as pcom %}
7
8
 
8
9
  {%- macro printService(service) -%}
9
10
  <DIAG-SERVICE {{pdc.printDiagCommAttribs(service) | indent(1) }}
@@ -18,8 +19,8 @@
18
19
  {{pdc.printDiagCommSubtags(service) | indent(1, first=True) }}
19
20
  {%- if service.comparam_refs %}
20
21
  <COMPARAM-REFS>
21
- {%- for ref in service.comparam_refs %}
22
- <COMPARAM-REF ID-REF="{{ref.ref_id}}" />
22
+ {%- for cpref in service.comparam_refs %}
23
+ {{ pcom.printComparamRef(cpref)|indent(4) }}
23
24
  {%- endfor %}
24
25
  </COMPARAM-REFS>
25
26
  {%- endif%}
@@ -65,8 +65,8 @@
65
65
  <INPUT-PARAM {{-make_xml_attrib("OID", param.oid)}}
66
66
  {{-make_xml_attrib("SEMANTIC", param.semantic)}}>
67
67
  {{ peid.printElementIdSubtags(param)|indent(1) }}
68
- {%- if param.physical_default_value %}
69
- <PHYSICAL-DEFAULT-VALUE>{{param.physical_default_value}}</PHYSICAL-DEFAULT-VALUE>
68
+ {%- if param.physical_default_value is not none %}
69
+ <PHYSICAL-DEFAULT-VALUE>{{param.physical_default_value | e}}</PHYSICAL-DEFAULT-VALUE>
70
70
  {%- endif %}
71
71
  <DOP-BASE-REF ID-REF="{{param.dop_base_ref.ref_id}}" />
72
72
  </INPUT-PARAM>
@@ -26,6 +26,8 @@
26
26
  {%- import('macros/printAudience.xml.jinja2') as paud %}
27
27
  {%- import('macros/printSpecialData.xml.jinja2') as psd %}
28
28
  {%- import('macros/printEcuVariantPattern.xml.jinja2') as pvpat %}
29
+ {%- import('macros/printDynDefinedSpec.xml.jinja2') as pdynspec %}
30
+ {%- import('macros/printDiagVariable.xml.jinja2') as pdv %}
29
31
 
30
32
  {%- macro printVariant(dl) -%}
31
33
  {%- set dlr = dl.diag_layer_raw %}
@@ -124,9 +126,9 @@
124
126
  {%- endif %}
125
127
  </DIAG-DATA-DICTIONARY-SPEC>
126
128
  {%- endif %}
127
- {%- if dlr.diag_comms %}
129
+ {%- if dlr.diag_comms_raw %}
128
130
  <DIAG-COMMS>
129
- {%- for dc in dlr.diag_comms %}
131
+ {%- for dc in dlr.diag_comms_raw %}
130
132
 
131
133
  {#- use some serious duck typing to determine the kind of diag-comm
132
134
  #- object. this would not be necessary if something like
@@ -191,28 +193,43 @@
191
193
  </ADDITIONAL-AUDIENCES>
192
194
  {%- endif %}
193
195
  {{- psd.printSpecialDataGroups(dlr.sdgs)|indent(1, first=True) }}
194
- {%- if dlr.comparams %}
196
+ {%- if dlr.comparam_refs %}
195
197
  <COMPARAM-REFS>
196
- {%- for cp in dlr.comparams -%}
198
+ {%- for cp in dlr.comparam_refs -%}
197
199
  {{ pcom.printComparamRef(cp)|indent(2) }}
198
200
  {%- endfor %}
199
201
  </COMPARAM-REFS>
200
202
  {%- endif %}
201
- {%- if dlr.variant_type.value == "ECU-VARIANT" %}
202
- {%- if dlr.ecu_variant_patterns %}
203
- <ECU-VARIANT-PATTERNS>
204
- {%- for vp in dlr.ecu_variant_patterns -%}
205
- {{ pvpat.printEcuVariantPattern(vp)|indent(2) }}
206
- {%- endfor -%}
207
- </ECU-VARIANT-PATTERNS>
208
- {%- endif %}
209
- {%- endif %}
210
203
  {%- if dlr.variant_type.value == "PROTOCOL" %}
211
204
  <COMPARAM-SPEC-REF ID-REF="{{dlr.comparam_spec_ref.ref_id}}" DOCREF="{{dlr.comparam_spec_ref.ref_docs[0].doc_name}}" DOCTYPE="COMPARAM-SPEC"/>
212
205
  {%- if dlr.prot_stack_snref is not none %}
213
206
  <PROT-STACK-SNREF SHORT-NAME="{{dlr.prot_stack_snref}}"/>
214
207
  {%- endif %}
215
208
  {%- endif %}
209
+ {%- if dlr.diag_variables %}
210
+ <DIAG-VARIABLES>
211
+ {%- for dv in dlr.diag_variables -%}
212
+ {{ pdv.printDiagVariable(dv)|indent(4) }}
213
+ {%- endfor -%}
214
+ </DIAG-VARIABLES>
215
+ {%- endif %}
216
+ {%- if dlr.variable_groups %}
217
+ <VARIABLE-GROUPS>
218
+ {%- for vg in dlr.variable_groups -%}
219
+ {{ pdv.printVariableGroup(vg)|indent(4) }}
220
+ {%- endfor -%}
221
+ </VARIABLE-GROUPS>
222
+ {%- endif %}
223
+ {%- if dlr.dyn_defined_spec %}
224
+ {{ pdynspec.printPrintDefinedSpec(dlr.dyn_defined_spec)|indent(4) }}
225
+ {%- endif %}
226
+ {%- if dlr.ecu_variant_patterns %}
227
+ <ECU-VARIANT-PATTERNS>
228
+ {%- for vp in dlr.ecu_variant_patterns -%}
229
+ {{ pvpat.printEcuVariantPattern(vp)|indent(4) }}
230
+ {%- endfor -%}
231
+ </ECU-VARIANT-PATTERNS>
232
+ {%- endif %}
216
233
  {%- if dlr.parent_refs %}
217
234
  <PARENT-REFS>
218
235
  {%- for parent in dlr.parent_refs -%}