odxtools 10.2.0__py3-none-any.whl → 10.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.
Files changed (68) hide show
  1. odxtools/cli/browse.py +4 -2
  2. odxtools/cli/compare.py +3 -3
  3. odxtools/compositecodec.py +1 -1
  4. odxtools/configdata.py +70 -0
  5. odxtools/configdatadictionaryspec.py +57 -0
  6. odxtools/configiditem.py +18 -0
  7. odxtools/configitem.py +85 -0
  8. odxtools/configrecord.py +146 -0
  9. odxtools/database.py +21 -0
  10. odxtools/dataiditem.py +18 -0
  11. odxtools/datarecord.py +132 -0
  12. odxtools/decodestate.py +1 -1
  13. odxtools/diagcommdataconnector.py +61 -0
  14. odxtools/diaglayers/diaglayer.py +39 -17
  15. odxtools/diaglayers/ecuvariant.py +12 -19
  16. odxtools/diaglayers/hierarchyelement.py +5 -5
  17. odxtools/diaglayers/protocol.py +14 -0
  18. odxtools/diagservice.py +10 -10
  19. odxtools/ecuconfig.py +89 -0
  20. odxtools/encryptcompressmethod.py +16 -3
  21. odxtools/externflashdata.py +21 -2
  22. odxtools/flashdata.py +40 -2
  23. odxtools/identvalue.py +16 -3
  24. odxtools/internflashdata.py +4 -0
  25. odxtools/isotp_state_machine.py +11 -11
  26. odxtools/itemvalue.py +77 -0
  27. odxtools/nameditemlist.py +2 -2
  28. odxtools/odxlink.py +4 -2
  29. odxtools/optionitem.py +79 -0
  30. odxtools/parameters/codedconstparameter.py +2 -3
  31. odxtools/readdiagcommconnector.py +79 -0
  32. odxtools/readparamvalue.py +52 -0
  33. odxtools/request.py +3 -3
  34. odxtools/response.py +8 -4
  35. odxtools/statemachine.py +3 -2
  36. odxtools/subcomponentparamconnector.py +1 -1
  37. odxtools/systemitem.py +23 -0
  38. odxtools/templates/diag_layer_container.odx-d.xml.jinja2 +4 -0
  39. odxtools/templates/ecu_config.odx-e.xml.jinja2 +38 -0
  40. odxtools/templates/flash.odx-f.xml.jinja2 +2 -2
  41. odxtools/templates/macros/printAudience.xml.jinja2 +3 -3
  42. odxtools/templates/macros/printChecksum.xml.jinja2 +1 -1
  43. odxtools/templates/macros/printCompuMethod.xml.jinja2 +2 -2
  44. odxtools/templates/macros/printConfigData.xml.jinja2 +39 -0
  45. odxtools/templates/macros/printConfigDataDictionarySpec.xml.jinja2 +22 -0
  46. odxtools/templates/macros/printConfigItems.xml.jinja2 +66 -0
  47. odxtools/templates/macros/printConfigRecord.xml.jinja2 +73 -0
  48. odxtools/templates/macros/printDOP.xml.jinja2 +5 -6
  49. odxtools/templates/macros/printDataRecord.xml.jinja2 +35 -0
  50. odxtools/templates/macros/printDiagCommDataConnector.xml.jinja2 +66 -0
  51. odxtools/templates/macros/printExpectedIdent.xml.jinja2 +1 -1
  52. odxtools/templates/macros/printFlashdata.xml.jinja2 +2 -2
  53. odxtools/templates/macros/printItemValue.xml.jinja2 +31 -0
  54. odxtools/templates/macros/printOwnIdent.xml.jinja2 +1 -1
  55. odxtools/templates/macros/printSecurity.xml.jinja2 +4 -4
  56. odxtools/templates/macros/printSegment.xml.jinja2 +1 -1
  57. odxtools/validbasevariant.py +62 -0
  58. odxtools/validityfor.py +16 -3
  59. odxtools/variantmatcher.py +4 -4
  60. odxtools/version.py +2 -2
  61. odxtools/writediagcommconnector.py +77 -0
  62. odxtools/writepdxfile.py +15 -0
  63. {odxtools-10.2.0.dist-info → odxtools-10.3.0.dist-info}/METADATA +2 -1
  64. {odxtools-10.2.0.dist-info → odxtools-10.3.0.dist-info}/RECORD +68 -44
  65. {odxtools-10.2.0.dist-info → odxtools-10.3.0.dist-info}/WHEEL +1 -1
  66. {odxtools-10.2.0.dist-info → odxtools-10.3.0.dist-info}/entry_points.txt +0 -0
  67. {odxtools-10.2.0.dist-info → odxtools-10.3.0.dist-info}/licenses/LICENSE +0 -0
  68. {odxtools-10.2.0.dist-info → odxtools-10.3.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,39 @@
1
+ 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/printConfigRecord.xml.jinja2') as pcr %}
8
+ {%- import('macros/printElementId.xml.jinja2') as peid %}
9
+ {%- import('macros/printSpecialData.xml.jinja2') as psd %}
10
+
11
+ {%- macro printConfigData(config_data) -%}
12
+ <CONFIG-DATA>
13
+ {{peid.printElementIdSubtags(config_data)|indent(2) }}
14
+ {%- if config_data.valid_base_variants %}
15
+ <VALID-BASE-VARIANTS>
16
+ {%- for valid_base_variant in config_data.valid_base_variants %}
17
+ <VALID-BASE-VARIANT>
18
+ {%- if valid_base_variant.ecu_variant_snrefs %}
19
+ <ECU-VARIANT-SNREFS>
20
+ {%- for ecu_variant_snref in valid_base_variant.ecu_variant_snrefs %}
21
+ <ECU-VARIANT-SNREF SHORT-NAME="{{ecu_variant_snref}}" />
22
+ {%- endfor %}
23
+ </ECU-VARIANT-SNREFS>
24
+ {%- endif %}
25
+ <BASE-VARIANT-SNREF SHORT-NAME="{{valid_base_variant.base_variant_snref}}" />
26
+ </VALID-BASE-VARIANT>
27
+ {%- endfor %}
28
+ </VALID-BASE-VARIANTS>
29
+ {%- endif %}
30
+ {%- if config_data.config_records %}
31
+ <CONFIG-RECORDS>
32
+ {%- for config_record in config_data.config_records %}
33
+ {{ pcr.printConfigRecord(config_record) | indent(4) }}
34
+ {%- endfor %}
35
+ </CONFIG-RECORDS>
36
+ {%- endif %}
37
+ {{- psd.printSpecialDataGroups(config_data.sdgs)|indent(2, first=True) }}{#- #}
38
+ </CONFIG-DATA>
39
+ {%- endmacro -%}
@@ -0,0 +1,22 @@
1
+ {#- -*- mode: sgml; tab-width: 1; indent-tabs-mode: nil -*-
2
+ #
3
+ # SPDX-License-Identifier: MIT
4
+ -#}
5
+
6
+ {%- import('macros/printDOP.xml.jinja2') as pdop %}
7
+ {%- import('macros/printUnitSpec.xml.jinja2') as punit %}
8
+
9
+ {%- macro printConfigDataDictionarySpec(cdds) -%}
10
+ <CONFIG-DATA-DICTIONARY-SPEC>
11
+ {%- if cdds.data_object_props %}
12
+ <DATA-OBJECT-PROPS>
13
+ {%- for dop in cdds.data_object_props %}
14
+ {{- pdop.printDataObjectProp(dop)|indent(3) }}
15
+ {%- endfor %}
16
+ </DATA-OBJECT-PROPS>
17
+ {%- endif %}
18
+ {%- if cdds.unit_spec %}
19
+ {{ punit.printUnitSpec(cdds.unit_spec)|indent(2) }}
20
+ {%- endif %}
21
+ </CONFIG-DATA-DICTIONARY-SPEC>
22
+ {%- endmacro -%}
@@ -0,0 +1,66 @@
1
+ 1{#- -*- mode: sgml; tab-width: 1; indent-tabs-mode: nil -*-
2
+ #
3
+ # SPDX-License-Identifier: MIT
4
+ -#}
5
+
6
+ {%- import('macros/printAudience.xml.jinja2') as paud %}
7
+ {%- import('macros/printElementId.xml.jinja2') as peid %}
8
+ {%- import('macros/printItemValue.xml.jinja2') as piv %}
9
+ {%- import('macros/printSpecialData.xml.jinja2') as psd %}
10
+
11
+ {%- macro printConfigItemSubtags(config_item) %}
12
+ {#-#}{{ peid.printElementIdSubtags(config_item) }}
13
+ {%- if config_item.byte_position is not none %}
14
+ <BYTE-POSITION>{{config_item.byte_position}}</BYTE-POSITION>
15
+ {%- endif %}
16
+ {%- if config_item.bit_position is not none %}
17
+ <BIT-POSITION>{{config_item.bit_position}}</BIT-POSITION>
18
+ {%- endif %}
19
+ {%- if config_item.data_object_prop_ref is not none %}
20
+ <DATA-OBJECT-PROP-REF {{ make_ref_attribs(config_item.data_object_prop_ref) }} />
21
+ {%- endif %}
22
+ {%- if config_item.data_object_prop_snref is not none %}
23
+ <DATA-OBJECT-PROP-SNREF SHORT-NAME="{{ config_item.data_object_prop_snref }}" />
24
+ {%- endif %}
25
+ {{- psd.printSpecialDataGroups(config_item.sdgs) }}
26
+ {%- endmacro %}
27
+
28
+ {%- macro printConfigIdItem(config_id_item) %}
29
+ <CONFIG-ID-ITEM>
30
+ {{ printConfigItemSubtags(config_id_item)|indent(2) }}
31
+ </CONFIG-ID-ITEM>
32
+ {%- endmacro %}
33
+
34
+ {%- macro printDataIdItem(data_id_item) %}
35
+ <DATA-ID-ITEM>
36
+ {{ printConfigItemSubtags(data_id_item)|indent(2) }}
37
+ </DATA-ID-ITEM>
38
+ {%- endmacro %}
39
+
40
+ {%- macro printOptionItem(option_item) %}
41
+ <OPTION-ITEM>
42
+ {{ printConfigItemSubtags(option_item)|indent(2) }}
43
+ {%- if option_item.physical_default_value is not none %}
44
+ <PHYSICAL-DEFAULT-VALUE>{{ option_item.physical_default_value|e }}</PHYSICAL-DEFAULT-VALUE>
45
+ {%- endif %}
46
+ {%- if option_item.item_values %}
47
+ <ITEM-VALUES>
48
+ {%- for item_value in option_item.item_values %}
49
+ {{ piv.printItemValue(item_value) }}
50
+ {%- endfor %}
51
+ </ITEM-VALUES>
52
+ {%- endif %}
53
+ {%- if option_item.write_audience is not none %}
54
+ {{ paud.printAudience(option_item.write_audience, "WRITE-AUDIENCE")}}
55
+ {%- endif %}
56
+ {%- if option_item.read_audience is not none %}
57
+ {{ paud.printAudience(option_item.read_audience, "READ-AUDIENCE")}}
58
+ {%- endif %}
59
+ </OPTION-ITEM>
60
+ {%- endmacro %}
61
+
62
+ {%- macro printSystemItem(system_item) %}
63
+ <SYSTEM-ITEM {{ make_xml_attrib("SYSPARAM", system_item.sysparam) }}>
64
+ {{ printConfigItemSubtags(system_item)|indent(2) }}
65
+ </SYSTEM-ITEM>
66
+ {%- endmacro %}
@@ -0,0 +1,73 @@
1
+ 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/printAudience.xml.jinja2') as paud %}
8
+ {%- import('macros/printDataRecord.xml.jinja2') as pdr %}
9
+ {%- import('macros/printDiagCommDataConnector.xml.jinja2') as pdcdc %}
10
+ {%- import('macros/printElementId.xml.jinja2') as peid %}
11
+ {%- import('macros/printConfigItems.xml.jinja2') as pcits %}
12
+ {%- import('macros/printSpecialData.xml.jinja2') as psd %}
13
+
14
+ {%- macro printConfigRecord(config_record) -%}
15
+ <CONFIG-RECORD>
16
+ {{peid.printElementIdSubtags(config_record)|indent(2) }}
17
+ {%- if config_record.config_id_item is not none %}
18
+ {{- pcits.printConfigIdItem(config_record.config_id_item)|indent(2)}}
19
+ {%- endif %}
20
+ {%- if config_record.data_items %}
21
+ <DATA-ITEMS>
22
+ {%- for data_item in config_record.data_items %}
23
+ {{ pcits.printDataItem(data_item) | indent(4) }}
24
+ {%- endfor %}
25
+ </DATA-ITEMS>
26
+ {%- endif %}
27
+ {%- if config_record.diag_comm_data_connectors %}
28
+ <DIAG-COMM-DATA-CONNECTORS>
29
+ {%- for connector in config_record.diag_comm_data_connectors %}
30
+ {{ pdcdc.printDiagCommDataConnector(connector) | indent(4) }}
31
+ {%- endfor %}
32
+ </DIAG-COMM-DATA-CONNECTORS>
33
+ {%- endif %}
34
+ {%- if config_record.config_id is not none %}
35
+ <CONFIG-ID
36
+ {%- if config_record.config_id.value_type is not none %}
37
+ {#- #} TYPE="{{ config_record.config_id.value_type.value }}"
38
+ {%- endif %}
39
+ {#- #}>{{config_record.config_id.value}}</CONFIG-ID>
40
+ {%- endif %}
41
+ {%- if config_record.data_records %}
42
+ <DATA-RECORDS>
43
+ {%- for data_record in config_record.data_records %}
44
+ {{ pdr.printDataRecord(data_record) | indent(4) }}
45
+ {%- endfor %}
46
+ </DATA-RECORDS>
47
+ {%- endif %}
48
+ {%- if config_record.audience is not none %}
49
+ {{ paud.printAudience(config_record.audience) | indent(2) }}
50
+ {%- endif %}
51
+ {%- if config_record.system_items %}
52
+ <SYSTEM-ITEMS>
53
+ {%- for system_item in config_record.system_items %}
54
+ {{- pcits.printSystemItem(system_item) | indent(4) }}
55
+ {%- endfor %}
56
+ </SYSTEM-ITEMS>
57
+ {%- endif %}
58
+ {%- if config_record.data_id_item is not none %}
59
+ {{- pcits.printDataIdItem(config_record.data_id_item)|indent(2)}}
60
+ {%- endif %}
61
+ {%- if config_record.option_items %}
62
+ <OPTION-ITEMS>
63
+ {%- for option_item in config_record.option_items %}
64
+ {{- pcits.printOptionItem(option_item) | indent(4) }}
65
+ {%- endfor %}
66
+ </OPTION-ITEMS>
67
+ {%- endif %}
68
+ {%- if config_record.default_data_record_snref is not none %}
69
+ <DEFAULT-DATA-RECORD-SNREF SHORT-NAME="{{config_record.default_data_record_snref}}" />
70
+ {%- endif %}
71
+ {{- psd.printSpecialDataGroups(config_record.sdgs)|indent(2, first=True) }}{#- #}
72
+ </CONFIG-RECORD>
73
+ {%- endmacro -%}
@@ -10,7 +10,7 @@
10
10
  {%- import('macros/printDescription.xml.jinja2') as pd %}
11
11
 
12
12
 
13
- {%- macro printDiagCodedType(dct) -%}
13
+ {%- macro printDiagCodedType(dct) %}
14
14
  <DIAG-CODED-TYPE {{-make_xml_attrib("BASE-DATA-TYPE", dct.base_data_type.value)}}
15
15
  {{-make_xml_attrib("BASE-TYPE-ENCODING", dct.base_type_encoding and dct.base_type_encoding.value)}}
16
16
  {{-make_bool_xml_attrib("IS-HIGHLOW-BYTE-ORDER", dct.is_highlow_byte_order_raw)}}
@@ -34,7 +34,7 @@
34
34
  <MIN-LENGTH>{{dct.min_length}}</MIN-LENGTH>
35
35
  {%- endif %}
36
36
  </DIAG-CODED-TYPE>
37
- {%- endmacro -%}
37
+ {%- endmacro %}
38
38
 
39
39
  {%- macro printPhysicalType(physical_type) %}
40
40
  {%- if physical_type.display_radix is not none %}
@@ -84,7 +84,6 @@
84
84
  {%- macro printDopBaseAttribs(dop) %}
85
85
  {{- make_xml_attrib("ID", dop.odx_id.local_id) }}
86
86
  {{- make_xml_attrib("OID", dop.oid) }}
87
- {#- -#}
88
87
  {%- endmacro %}
89
88
 
90
89
  {%- macro printDopBaseSubtags(dop) %}
@@ -92,8 +91,8 @@
92
91
  {%- if dop.admin_data %}
93
92
  {{ pad.printAdminData(dop.admin_data)|indent(1) }}
94
93
  {%- endif %}
95
- {{ psd.printSpecialDataGroups(dop.sdgs)|indent(1) }}
96
- {%- endmacro -%}
94
+ {{- psd.printSpecialDataGroups(dop.sdgs)|indent(1) }}
95
+ {%- endmacro %}
97
96
 
98
97
  {%- macro printComplexDopAttribs(st) %}
99
98
  {{- printDopBaseAttribs(st) }}
@@ -101,7 +100,7 @@
101
100
 
102
101
  {%- macro printComplexDopSubtags(st) %}
103
102
  {{- printDopBaseSubtags(st) }}
104
- {%- endmacro -%}
103
+ {%- endmacro %}
105
104
 
106
105
  {%- macro printDataObjectProp(dop) %}
107
106
  <DATA-OBJECT-PROP {{- printDopBaseAttribs(dop) }}>
@@ -0,0 +1,35 @@
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/printSpecialData.xml.jinja2') as psd %}
8
+
9
+ {%- macro printDataRecord(data_record) -%}
10
+ <DATA-RECORD {{ make_xml_attrib("DATAFORMAT", data_record.dataformat.value) }}>
11
+ {{peid.printElementIdSubtags(data_record)|indent(2) }}
12
+ {%- if data_record.rule is not none %}
13
+ <RULE>{{data_record.rule | e}}</RULE>
14
+ {%- endif %}
15
+ {%- if data_record.key is not none %}
16
+ <KEY>{{data_record.key | e}}</KEY>
17
+ {%- endif %}
18
+ {%- if data_record.data_id is not none %}
19
+ <DATA-ID
20
+ {%- if data_record.data_id.value_type is not none %}
21
+ {#- #} TYPE="{{ data_record.data_id.value_type.value }}"
22
+ {%- endif %}
23
+ {#- #}>{{data_record.data_id.value_raw | e}}</DATA-ID>
24
+ {%- endif %}
25
+ {{- psd.printSpecialDataGroups(data_record.sdgs)|indent(2, first=True) }}{#- #}
26
+ {%- if data_record.datafile is not none %}
27
+ <DATAFILE {{ make_bool_xml_attrib("LATEBOUND-DATAFILE", data_record.datafile.latebound_datafile) }}>
28
+ {#- #}{{data_record.datafile.value | e}}
29
+ {#- #}</DATAFILE>
30
+ {%- endif %}
31
+ {%- if data_record.data is defined %}
32
+ <DATA>{{data_record.data | e}}</DATA>
33
+ {%- endif %}
34
+ </DATA-RECORD>
35
+ {%- endmacro -%}
@@ -0,0 +1,66 @@
1
+ 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/printElementId.xml.jinja2') as peid %}
8
+ {%- import('macros/printConfigItems.xml.jinja2') as pcits %}
9
+ {%- import('macros/printSpecialData.xml.jinja2') as psd %}
10
+
11
+ {%- macro printDiagCommDataConnector(connector) -%}
12
+ <DIAG-COMM-DATA-CONNECTOR>
13
+ <UNCOMPRESSED-SIZE>{{connector.uncompressed_size}}</UNCOMPRESSED-SIZE>
14
+ {%- set num_nibbles = (connector.source_start_address.bit_length() + 7) // 8 * 2 %}
15
+ <SOURCE-START-ADDRESS>{{ ("%%0%dX" | format(num_nibbles | int)) | format(connector.source_start_address | int) }}</SOURCE-START-ADDRESS>
16
+ {%- if connector.read_diag_comm_connector is not none %}
17
+ {%- set rdcc = connector.read_diag_comm_connector %}
18
+ <READ-DIAG-COMM-CONNECTOR>
19
+ {%- if rdcc.read_param_values %}
20
+ <READ-PARAM-VALUES>
21
+ {%- for rpv in rdcc.read_param_values %}
22
+ <READ-PARAM-VALUE {{ make_xml_attrib("SEMANTIC", rpv.semantic) }}>
23
+ <PHYS-CONSTANT-VALUE>{{ rpv.phys_constant_value | e }}</PHYS-CONSTANT-VALUE>
24
+ {%- if rpv.in_param_if_snref is not none %}
25
+ <IN-PARAM-IF-SNREF SHORT-NAME="{{rpv.in_param_if_snref}}" />
26
+ {%- endif %}
27
+ {%- if rpv.in_param_if_snpathref is not none %}
28
+ <IN-PARAM-IF-SNPATHREF SHORT-NAME-PATH="{{rpv.in_param_if_snpathref}}" />
29
+ {%- endif %}
30
+ </READ-PARAM-VALUE>
31
+ {%- endfor %}
32
+ </READ-PARAM-VALUES>
33
+ {%- endif %}
34
+ {%- if rdcc.read_diag_comm_ref is not none %}
35
+ <READ-DIAG-COMM-REF {{make_ref_attribs(rdcc.read_diag_comm_ref)}} />
36
+ {%- endif %}
37
+ {%- if rdcc.read_diag_comm_snref is not none %}
38
+ <READ-DIAG-COMM-SNREF SHORT-NAME="{{rdcc.read_diag_comm_snref}}" />
39
+ {%- endif %}
40
+ {%- if rdcc.read_data_snref is not none %}
41
+ <READ-DATA-SNREF SHORT-NAME="{{rdcc.read_data_snref}}" />
42
+ {%- endif %}
43
+ {%- if rdcc.read_data_snpathref is not none %}
44
+ <READ-DATA-SNPATHREF SHORT-NAME-PATH="{{rdcc.read_data_snpathref}}" />
45
+ {%- endif %}
46
+ </READ-DIAG-COMM-CONNECTOR>
47
+ {%- endif %}
48
+ {%- if connector.write_diag_comm_connector is not none %}
49
+ {%- set wdcc = connector.write_diag_comm_connector %}
50
+ <WRITE-DIAG-COMM-CONNECTOR>
51
+ {%- if wdcc.write_diag_comm_ref is not none %}
52
+ <WRITE-DIAG-COMM-REF {{make_ref_attribs(wdcc.write_diag_comm_ref)}} />
53
+ {%- endif %}
54
+ {%- if wdcc.write_diag_comm_snref is not none %}
55
+ <WRITE-DIAG-COMM-SNREF SHORT-NAME="{{wdcc.write_diag_comm_snref}}" />
56
+ {%- endif %}
57
+ {%- if wdcc.write_data_snref is not none %}
58
+ <WRITE-DATA-SNREF SHORT-NAME="{{wdcc.write_data_snref}}" />
59
+ {%- endif %}
60
+ {%- if wdcc.write_data_snpathref is not none %}
61
+ <WRITE-DATA-SNPATHREF SHORT-NAME-PATH="{{wdcc.write_data_snpathref}}" />
62
+ {%- endif %}
63
+ </WRITE-DIAG-COMM-CONNECTOR>
64
+ {%- endif %}
65
+ </DIAG-COMM-DATA-CONNECTOR>
66
+ {%- endmacro -%}
@@ -14,7 +14,7 @@
14
14
  {%- if ident_value.value_type is not none %}
15
15
  {#- #} TYPE="{{ ident_value.value_type.value }}"
16
16
  {%- endif %}
17
- {#- #}>{{ident_value.value}}</IDENT-VALUE>
17
+ {#- #}>{{ident_value.value_raw}}</IDENT-VALUE>
18
18
  {%- endfor %}
19
19
  </IDENT-VALUES>
20
20
  </EXPECTED-IDENT>
@@ -30,10 +30,10 @@
30
30
  {%- if flashdata.encrypt_compress_method.value_type is not none %}
31
31
  {#- #} TYPE="{{ flashdata.encrypt_compress_method.value_type.value }}"
32
32
  {%- endif %}
33
- {#- #}>{{flashdata.encrypt_compress_method.value}}</ENCRYPT-COMPRESS-METHOD>
33
+ {#- #}>{{flashdata.encrypt_compress_method.value_raw}}</ENCRYPT-COMPRESS-METHOD>
34
34
  {%- endif %}
35
35
  {%- if flashdata.datafile is defined %}
36
- <DATAFILE {{ make_bool_xml_attrib("LATEBOUND-DATAFILE", flashdata.latebound_datafile) }}>
36
+ <DATAFILE {{ make_bool_xml_attrib("LATEBOUND-DATAFILE", flashdata.datafile.latebound_datafile) }}>
37
37
  {#- #}{{flashdata.datafile.value}}
38
38
  {#- #}</DATAFILE>
39
39
  {%- elif flashdata.data is defined %}
@@ -0,0 +1,31 @@
1
+ 1{#- -*- mode: sgml; tab-width: 1; indent-tabs-mode: nil -*-
2
+ #
3
+ # SPDX-License-Identifier: MIT
4
+ -#}
5
+
6
+ {%- import('macros/printAudience.xml.jinja2') as paud %}
7
+ {%- import('macros/printSpecialData.xml.jinja2') as psd %}
8
+
9
+ {%- macro printItemValue(item_value) -%}
10
+ <ITEM-VALUE>
11
+ {%- if item_value.phys_constant_value is not none %}
12
+ <PHYS-CONSTANT-VALUE>{{item_value.phys_constant_value | e}}</PHYS-CONSTANT-VALUE>
13
+ {%- endif %}
14
+ {%- if item_value.meaning is not none %}
15
+ <MEANING {{- make_xml_attrib("TI", item_value.meaning.text_identifier) }}>{{item_value.meaning|e}}</MEANING>
16
+ {%- endif %}
17
+ {%- if item_value.key is not none %}
18
+ <KEY>{{item_value.key | e}}</KEY>
19
+ {%- endif %}
20
+ {%- if item_value.rule is not none %}
21
+ <RULE>{{item_value.rule | e}}</RULE>
22
+ {%- endif %}
23
+ {%- if item_value.description is not none %}
24
+ <DESCRIPTION {{- make_xml_attrib("TI", item_value.description.text_identifier) }}>{{item_value.description|e}}</DESCRIPTION>
25
+ {%- endif %}
26
+ {{- psd.printSpecialDataGroups(item_value.sdgs)|indent(2, first=True) }}{#- #}
27
+ {%- if item_value.audience is not none %}
28
+ {{ paud.printAudience(item_value.audience) | indent(2) }}
29
+ {%- endif %}
30
+ </ITEM-VALUE>
31
+ {%- endmacro -%}
@@ -12,6 +12,6 @@
12
12
  {%- if own_ident.ident_value.value_type is not none %}
13
13
  {#- #} TYPE="{{ own_ident.ident_value.value_type.value }}"
14
14
  {%- endif %}
15
- {#- #}>{{own_ident.ident_value.value}}</IDENT-VALUE>
15
+ {#- #}>{{own_ident.ident_value.value_raw}}</IDENT-VALUE>
16
16
  </OWN-IDENT>
17
17
  {%- endmacro -%}
@@ -10,28 +10,28 @@
10
10
  {%- if security.security_method.value_type is not none %}
11
11
  {#- #} TYPE="{{ security.security_method.value_type.value }}"
12
12
  {%- endif %}
13
- {#- #}>{{security.security_method.value}}</SECURITY-METHOD>
13
+ {#- #}>{{security.security_method.value_raw}}</SECURITY-METHOD>
14
14
  {%- endif %}
15
15
  {%- if security.fw_signature is not none %}
16
16
  <FW-SIGNATURE
17
17
  {%- if security.fw_signature.value_type is not none %}
18
18
  {#- #} TYPE="{{ security.fw_signature.value_type.value }}"
19
19
  {%- endif %}
20
- {#- #}>{{security.fw_signature.value}}</FW-SIGNATURE>
20
+ {#- #}>{{security.fw_signature.value_raw}}</FW-SIGNATURE>
21
21
  {%- endif %}
22
22
  {%- if security.fw_checksum is not none %}
23
23
  <FW-CHECKSUM
24
24
  {%- if security.fw_checksum.value_type is not none %}
25
25
  {#- #} TYPE="{{ security.fw_checksum.value_type.value }}"
26
26
  {%- endif %}
27
- {#- #}>{{security.fw_checksum.value}}</FW-CHECKSUM>
27
+ {#- #}>{{security.fw_checksum.value_raw}}</FW-CHECKSUM>
28
28
  {%- endif %}
29
29
  {%- if security.validity_for is not none %}
30
30
  <VALIDITY-FOR
31
31
  {%- if security.validity_for.value_type is not none %}
32
32
  {#- #} TYPE="{{ security.validity_for.value_type.value }}"
33
33
  {%- endif %}
34
- {#- #}>{{security.validity_for.value}}</VALIDITY-FOR>
34
+ {#- #}>{{security.validity_for.value_raw}}</VALIDITY-FOR>
35
35
  {%- endif %}
36
36
  </SECURITY>
37
37
  {%- endmacro -%}
@@ -25,7 +25,7 @@
25
25
  {%- if segment.encrypt_compress_method.value_type is not none %}
26
26
  {#- #} TYPE="{{ segment.encrypt_compress_method.value_type.value }}"
27
27
  {%- endif %}
28
- {#- #}>{{segment.encrypt_compress_method.value}}</ENCRYPT-COMPRESS-METHOD>
28
+ {#- #}>{{segment.encrypt_compress_method.value_raw | e}}</ENCRYPT-COMPRESS-METHOD>
29
29
  {%- endif %}
30
30
  </SEGMENT>
31
31
  {%- endmacro -%}
@@ -0,0 +1,62 @@
1
+ # SPDX-License-Identifier: MIT
2
+ from dataclasses import dataclass
3
+ from itertools import chain
4
+ from typing import Any
5
+ from xml.etree import ElementTree
6
+
7
+ from .diaglayers.basevariant import BaseVariant
8
+ from .diaglayers.ecuvariant import EcuVariant
9
+ from .exceptions import odxrequire
10
+ from .nameditemlist import NamedItemList
11
+ from .odxdoccontext import OdxDocContext
12
+ from .odxlink import OdxLinkDatabase, OdxLinkId, resolve_snref
13
+ from .snrefcontext import SnRefContext
14
+
15
+
16
+ @dataclass(kw_only=True)
17
+ class ValidBaseVariant:
18
+ ecu_variant_snrefs: list[str]
19
+ base_variant_snref: str
20
+
21
+ @property
22
+ def ecu_variants(self) -> NamedItemList[EcuVariant]:
23
+ return self._ecu_variants
24
+
25
+ @property
26
+ def base_variant(self) -> BaseVariant:
27
+ return self._base_variant
28
+
29
+ @staticmethod
30
+ def from_et(et_element: ElementTree.Element, context: OdxDocContext) -> "ValidBaseVariant":
31
+ ecu_variant_snrefs = []
32
+ for ecuv_snref_elem in et_element.iterfind("ECU-VARIANT-SNREFS/ECU-VARIANT-SNREF"):
33
+ ecu_variant_snrefs.append(odxrequire(ecuv_snref_elem.attrib["SHORT-NAME"]))
34
+
35
+ basev_snref_elem = odxrequire(et_element.find("BASE-VARIANT-SNREF"))
36
+ base_variant_snref = odxrequire(basev_snref_elem.attrib["SHORT-NAME"])
37
+
38
+ return ValidBaseVariant(
39
+ ecu_variant_snrefs=ecu_variant_snrefs, base_variant_snref=base_variant_snref)
40
+
41
+ def __post_init__(self) -> None:
42
+ self._ecu_variants: NamedItemList[EcuVariant]
43
+ self._base_variant: BaseVariant
44
+
45
+ def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
46
+ result: dict[OdxLinkId, Any] = {}
47
+ return result
48
+
49
+ def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
50
+ pass
51
+
52
+ def _resolve_snrefs(self, context: SnRefContext) -> None:
53
+ db = odxrequire(context.database)
54
+
55
+ ecu_variants = chain(*[dlc.ecu_variants for dlc in db.diag_layer_containers])
56
+ base_variants = chain(*[dlc.base_variants for dlc in db.diag_layer_containers])
57
+
58
+ self._ecu_variants = NamedItemList[EcuVariant]()
59
+ for ev_snref in self.ecu_variant_snrefs:
60
+ self._ecu_variants.append(resolve_snref(ev_snref, ecu_variants, EcuVariant))
61
+
62
+ self._base_variant = resolve_snref(self.base_variant_snref, base_variants, BaseVariant)
odxtools/validityfor.py CHANGED
@@ -5,17 +5,26 @@ from xml.etree import ElementTree
5
5
 
6
6
  from .exceptions import odxraise, odxrequire
7
7
  from .odxdoccontext import OdxDocContext
8
+ from .odxtypes import AtomicOdxType, DataType
8
9
  from .sessionsubelemtype import SessionSubElemType
9
10
 
10
11
 
11
12
  @dataclass(kw_only=True)
12
13
  class ValidityFor:
13
- value: str
14
+ value_raw: str
14
15
  value_type: SessionSubElemType
15
16
 
17
+ @property
18
+ def value(self) -> AtomicOdxType:
19
+ return self._value
20
+
21
+ @property
22
+ def data_type(self) -> DataType:
23
+ return self._data_type
24
+
16
25
  @staticmethod
17
26
  def from_et(et_element: ElementTree.Element, context: OdxDocContext) -> "ValidityFor":
18
- value = et_element.text or ""
27
+ value_raw = et_element.text or ""
19
28
 
20
29
  value_type_str = odxrequire(et_element.get("TYPE"))
21
30
  try:
@@ -25,6 +34,10 @@ class ValidityFor:
25
34
  odxraise(f"Encountered unknown SESSION-SUB-ELEM-TYPE type '{value_type_str}'")
26
35
 
27
36
  return ValidityFor(
28
- value=value,
37
+ value_raw=value_raw,
29
38
  value_type=value_type,
30
39
  )
40
+
41
+ def __post_init__(self) -> None:
42
+ self._data_type = DataType(self.value_type.value)
43
+ self._value = self._data_type.from_string(self.value_raw.strip())
@@ -107,14 +107,14 @@ class VariantMatcher:
107
107
  req_bytes = matching_param.get_ident_service(variant).encode_request()
108
108
 
109
109
  if self.use_cache and req_bytes in self.req_resp_cache:
110
- resp_values = copy(self.req_resp_cache[req_bytes])
110
+ resp_values = copy(bytes(self.req_resp_cache[bytes(req_bytes)]))
111
111
  else:
112
112
  if isinstance(matching_param, MatchingBaseVariantParameter):
113
- yield matching_param.use_physical_addressing, req_bytes
113
+ yield matching_param.use_physical_addressing, bytes(req_bytes)
114
114
  else:
115
- yield True, req_bytes
115
+ yield True, bytes(req_bytes)
116
116
  resp_values = self._get_ident_response()
117
- self._update_cache(req_bytes, copy(resp_values))
117
+ self._update_cache(bytes(req_bytes), copy(bytes(resp_values)))
118
118
 
119
119
  cur_response_matches = self._ident_response_matches(
120
120
  variant, matching_param, resp_values)
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.2.0'
21
- __version_tuple__ = version_tuple = (10, 2, 0)
20
+ __version__ = version = '10.3.0'
21
+ __version_tuple__ = version_tuple = (10, 3, 0)
@@ -0,0 +1,77 @@
1
+ # SPDX-License-Identifier: MIT
2
+ from dataclasses import dataclass
3
+ from typing import Any
4
+ from xml.etree import ElementTree
5
+
6
+ from .diagcomm import DiagComm
7
+ from .exceptions import odxrequire
8
+ from .odxdoccontext import OdxDocContext
9
+ from .odxlink import OdxLinkDatabase, OdxLinkId, OdxLinkRef, resolve_snref
10
+ from .parameters.valueparameter import ValueParameter
11
+ from .request import Request
12
+ from .snrefcontext import SnRefContext
13
+
14
+
15
+ @dataclass(kw_only=True)
16
+ class WriteDiagCommConnector:
17
+ # exactly one of the following attributes must be non-None
18
+ write_diag_comm_ref: OdxLinkRef | None = None
19
+ write_diag_comm_snref: str | None = None
20
+
21
+ # exactly one of the following attributes must be non-None
22
+ write_data_snref: str | None = None
23
+ write_data_snpathref: str | None = None
24
+
25
+ @property
26
+ def write_diag_comm(self) -> DiagComm | None:
27
+ return self._write_diag_comm
28
+
29
+ @property
30
+ def write_data(self) -> ValueParameter | None:
31
+ return self._write_data
32
+
33
+ @staticmethod
34
+ def from_et(et_element: ElementTree.Element,
35
+ context: OdxDocContext) -> "WriteDiagCommConnector":
36
+ write_diag_comm_ref = OdxLinkRef.from_et(et_element.find("WRITE-DIAG-COMM-REF"), context)
37
+ write_diag_comm_snref = None
38
+ if (write_diag_comm_snref_elem := et_element.find("WRITE-DIAG-COMM-SNREF")) is not None:
39
+ write_diag_comm_snref = odxrequire(write_diag_comm_snref_elem.attrib.get("SHORT-NAME"))
40
+
41
+ write_data_snref = None
42
+ if (write_data_snref_elem := et_element.find("WRITE-DATA-SNREF")) is not None:
43
+ write_data_snref = odxrequire(write_data_snref_elem.attrib.get("SHORT-NAME"))
44
+
45
+ write_data_snpathref = None
46
+ if (write_data_snpathref_elem := et_element.find("WRITE-DATA-SNPATHREF")) is not None:
47
+ write_data_snpathref = odxrequire(
48
+ write_data_snpathref_elem.attrib.get("SHORT-NAME-PATH"))
49
+
50
+ return WriteDiagCommConnector(
51
+ write_diag_comm_ref=write_diag_comm_ref,
52
+ write_diag_comm_snref=write_diag_comm_snref,
53
+ write_data_snref=write_data_snref,
54
+ write_data_snpathref=write_data_snpathref,
55
+ )
56
+
57
+ def _build_odxlinks(self) -> dict[OdxLinkId, Any]:
58
+ odxlinks: dict[OdxLinkId, Any] = {}
59
+
60
+ return odxlinks
61
+
62
+ def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
63
+ self._write_diag_comm = None
64
+ if self.write_diag_comm_ref is not None:
65
+ self._write_diag_comm = odxlinks.resolve(self.write_diag_comm_ref, DiagComm)
66
+
67
+ def _resolve_snrefs(self, context: SnRefContext) -> None:
68
+ # write_diag_comm_snref can only be uniquely resolved ahead of
69
+ # time if the diag comm is referenced via ODXLINK, the write
70
+ # data parameter is referenced via SNREF. If the diag comm is
71
+ # referenced via SNREF, it depends on the applicable diag layer
72
+ self._write_data = None
73
+ if self.write_data_snref is not None and \
74
+ self._write_diag_comm is not None and \
75
+ (req := getattr(self._write_diag_comm, "request", None)) is not None:
76
+ assert isinstance(req, Request)
77
+ self._write_data = resolve_snref(self.write_data_snref, req.parameters, ValueParameter)