odxtools 4.0.5__tar.gz → 4.1.0__tar.gz

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 (126) hide show
  1. {odxtools-4.0.5 → odxtools-4.1.0}/PKG-INFO +1 -1
  2. {odxtools-4.0.5 → odxtools-4.1.0}/examples/somersaultecu.py +146 -36
  3. {odxtools-4.0.5 → odxtools-4.1.0}/examples/somersaultlazy.py +18 -35
  4. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/compumethods/compuscale.py +2 -1
  5. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/compumethods/limit.py +1 -1
  6. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/dataobjectproperty.py +26 -8
  7. odxtools-4.1.0/odxtools/decodestate.py +24 -0
  8. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/diagcodedtypes.py +49 -29
  9. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/diagdatadictionaryspec.py +2 -2
  10. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/diaglayer.py +8 -12
  11. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/ecu_variant_matcher.py +13 -12
  12. odxtools-4.1.0/odxtools/encodestate.py +37 -0
  13. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/endofpdufield.py +6 -5
  14. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/message.py +2 -3
  15. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/multiplexer.py +2 -2
  16. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/nameditemlist.py +10 -1
  17. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/odxlink.py +14 -2
  18. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/odxtypes.py +33 -11
  19. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/parameter_info.py +1 -0
  20. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/parameters/codedconstparameter.py +22 -8
  21. odxtools-4.1.0/odxtools/parameters/lengthkeyparameter.py +59 -0
  22. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/parameters/nrcconstparameter.py +21 -6
  23. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/parameters/parameterbase.py +35 -29
  24. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/parameters/parameterwithdop.py +5 -3
  25. odxtools-4.1.0/odxtools/parameters/tablekeyparameter.py +160 -0
  26. odxtools-4.1.0/odxtools/parameters/tablestructparameter.py +156 -0
  27. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/service.py +1 -1
  28. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/singleecujob.py +1 -1
  29. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/structures.py +61 -84
  30. odxtools-4.1.0/odxtools/table.py +119 -0
  31. odxtools-4.1.0/odxtools/tablerow.py +153 -0
  32. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/uds.py +2 -2
  33. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/version.py +1 -1
  34. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools.egg-info/PKG-INFO +1 -1
  35. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools.egg-info/SOURCES.txt +1 -0
  36. {odxtools-4.0.5 → odxtools-4.1.0}/tests/test_diag_coded_types.py +40 -27
  37. {odxtools-4.0.5 → odxtools-4.1.0}/tests/test_diag_data_dictionary_spec.py +52 -14
  38. {odxtools-4.0.5 → odxtools-4.1.0}/tests/test_ecu_variant_matching.py +1 -1
  39. {odxtools-4.0.5 → odxtools-4.1.0}/tests/test_somersault.py +69 -0
  40. odxtools-4.0.5/odxtools/decodestate.py +0 -22
  41. odxtools-4.0.5/odxtools/encodestate.py +0 -31
  42. odxtools-4.0.5/odxtools/parameters/lengthkeyparameter.py +0 -37
  43. odxtools-4.0.5/odxtools/parameters/tablekeyparameter.py +0 -71
  44. odxtools-4.0.5/odxtools/parameters/tablestructparameter.py +0 -30
  45. odxtools-4.0.5/odxtools/table.py +0 -247
  46. {odxtools-4.0.5 → odxtools-4.1.0}/LICENSE +0 -0
  47. {odxtools-4.0.5 → odxtools-4.1.0}/README.md +0 -0
  48. {odxtools-4.0.5 → odxtools-4.1.0}/examples/__init__.py +0 -0
  49. {odxtools-4.0.5 → odxtools-4.1.0}/examples/isotp_send.py +0 -0
  50. {odxtools-4.0.5 → odxtools-4.1.0}/examples/mksomersaultpdx.py +0 -0
  51. {odxtools-4.0.5 → odxtools-4.1.0}/examples/pdxcopy.py +0 -0
  52. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/__init__.py +0 -0
  53. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/__main__.py +0 -0
  54. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/admindata.py +0 -0
  55. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/audience.py +0 -0
  56. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/cli/__init__.py +0 -0
  57. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/cli/_parser_utils.py +0 -0
  58. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/cli/_print_utils.py +0 -0
  59. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/cli/browse.py +0 -0
  60. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/cli/dummy_sub_parser.py +0 -0
  61. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/cli/find.py +0 -0
  62. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/cli/list.py +0 -0
  63. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/cli/main.py +0 -0
  64. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/cli/snoop.py +0 -0
  65. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/communicationparameter.py +0 -0
  66. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/companydata.py +0 -0
  67. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/comparam_subset.py +0 -0
  68. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/compumethods/__init__.py +0 -0
  69. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/compumethods/compumethodbase.py +0 -0
  70. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/compumethods/compurationalcoeffs.py +0 -0
  71. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/compumethods/createanycompumethod.py +0 -0
  72. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/compumethods/identicalcompumethod.py +0 -0
  73. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/compumethods/linearcompumethod.py +0 -0
  74. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/compumethods/scalelinearcompumethod.py +0 -0
  75. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/compumethods/tabintpcompumethod.py +0 -0
  76. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/compumethods/texttablecompumethod.py +0 -0
  77. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/database.py +0 -0
  78. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/diaglayercontainer.py +0 -0
  79. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/diaglayerraw.py +0 -0
  80. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/diaglayertype.py +0 -0
  81. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/ecu_variant_patterns.py +0 -0
  82. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/envdata.py +0 -0
  83. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/envdatadesc.py +0 -0
  84. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/exceptions.py +0 -0
  85. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/functionalclass.py +0 -0
  86. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/globals.py +0 -0
  87. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/isotp_state_machine.py +0 -0
  88. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/load_file.py +0 -0
  89. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/load_odx_d_file.py +0 -0
  90. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/load_pdx_file.py +0 -0
  91. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/obd.py +0 -0
  92. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/parameters/__init__.py +0 -0
  93. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/parameters/createanyparameter.py +0 -0
  94. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/parameters/dynamicparameter.py +0 -0
  95. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/parameters/matchingrequestparameter.py +0 -0
  96. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/parameters/physicalconstantparameter.py +0 -0
  97. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/parameters/reservedparameter.py +0 -0
  98. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/parameters/systemparameter.py +0 -0
  99. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/parameters/tableentryparameter.py +0 -0
  100. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/parameters/valueparameter.py +0 -0
  101. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/parentref.py +0 -0
  102. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/physicaltype.py +0 -0
  103. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/specialdata.py +0 -0
  104. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/state.py +0 -0
  105. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/statechart.py +0 -0
  106. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/statetransition.py +0 -0
  107. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/units.py +0 -0
  108. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/utils.py +0 -0
  109. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools/write_pdx_file.py +0 -0
  110. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools.egg-info/dependency_links.txt +0 -0
  111. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools.egg-info/entry_points.txt +0 -0
  112. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools.egg-info/requires.txt +0 -0
  113. {odxtools-4.0.5 → odxtools-4.1.0}/odxtools.egg-info/top_level.txt +0 -0
  114. {odxtools-4.0.5 → odxtools-4.1.0}/pyproject.toml +0 -0
  115. {odxtools-4.0.5 → odxtools-4.1.0}/setup.cfg +0 -0
  116. {odxtools-4.0.5 → odxtools-4.1.0}/setup.py +0 -0
  117. {odxtools-4.0.5 → odxtools-4.1.0}/tests/test_compu_methods.py +0 -0
  118. {odxtools-4.0.5 → odxtools-4.1.0}/tests/test_decoding.py +0 -0
  119. {odxtools-4.0.5 → odxtools-4.1.0}/tests/test_ecu_variant_patterns.py +0 -0
  120. {odxtools-4.0.5 → odxtools-4.1.0}/tests/test_encoding.py +0 -0
  121. {odxtools-4.0.5 → odxtools-4.1.0}/tests/test_odxtools.py +0 -0
  122. {odxtools-4.0.5 → odxtools-4.1.0}/tests/test_odxtypes.py +0 -0
  123. {odxtools-4.0.5 → odxtools-4.1.0}/tests/test_readparameters.py +0 -0
  124. {odxtools-4.0.5 → odxtools-4.1.0}/tests/test_singleecujob.py +0 -0
  125. {odxtools-4.0.5 → odxtools-4.1.0}/tests/test_unit_spec.py +0 -0
  126. {odxtools-4.0.5 → odxtools-4.1.0}/tests/test_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: odxtools
3
- Version: 4.0.5
3
+ Version: 4.1.0
4
4
  Summary: Utilities to work with the automotive diagnostics standard ODX.
5
5
  Home-page: https://github.com/Daimler/odxtools
6
6
  Author: Katrin Bauer, Andreas Lauser
@@ -34,7 +34,7 @@ from odxtools.nameditemlist import NamedItemList
34
34
  from odxtools.odxlink import OdxDocFragment, OdxLinkId, OdxLinkRef
35
35
  from odxtools.odxtypes import DataType
36
36
  from odxtools.parameters import (CodedConstParameter, MatchingRequestParameter, NrcConstParameter,
37
- ValueParameter)
37
+ TableKeyParameter, TableStructParameter, ValueParameter)
38
38
  from odxtools.parentref import ParentRef
39
39
  from odxtools.physicaltype import PhysicalType
40
40
  from odxtools.service import DiagService
@@ -292,6 +292,15 @@ somersault_diagcodedtypes = {
292
292
  is_condensed_raw=None,
293
293
  is_highlow_byte_order_raw=None,
294
294
  ),
295
+ "float32":
296
+ StandardLengthType(
297
+ base_data_type="A_FLOAT32",
298
+ bit_length=32,
299
+ bit_mask=None,
300
+ is_condensed_raw=None,
301
+ is_highlow_byte_order_raw=None,
302
+ base_type_encoding=None,
303
+ ),
295
304
  }
296
305
 
297
306
  somersault_physical_dimensions = {
@@ -388,6 +397,8 @@ somersault_unit_groups = {
388
397
  somersault_compumethods = {
389
398
  "uint_passthrough":
390
399
  IdenticalCompuMethod(internal_type="A_UINT32", physical_type="A_UINT32"),
400
+ "float_passthrough":
401
+ IdenticalCompuMethod(internal_type="A_FLOAT32", physical_type="A_FLOAT32"),
391
402
  "boolean":
392
403
  TexttableCompuMethod(
393
404
  internal_type="A_UINT32",
@@ -505,8 +516,37 @@ somersault_dops = {
505
516
  is_visible_raw=None,
506
517
  sdgs=[],
507
518
  ),
519
+ "uint8":
520
+ DataObjectProperty(
521
+ odx_id=OdxLinkId("somersault.DOP.uint8", doc_frags),
522
+ short_name="uint8",
523
+ long_name=None,
524
+ description=None,
525
+ diag_coded_type=somersault_diagcodedtypes["uint8"],
526
+ physical_type=PhysicalType(DataType.A_UINT32, display_radix=None, precision=None),
527
+ compu_method=somersault_compumethods["uint_passthrough"],
528
+ unit_ref=None,
529
+ is_visible_raw=None,
530
+ sdgs=[],
531
+ ),
532
+ "float":
533
+ DataObjectProperty(
534
+ odx_id=OdxLinkId("somersault.DOP.float", doc_frags),
535
+ short_name="float",
536
+ long_name=None,
537
+ description=None,
538
+ diag_coded_type=somersault_diagcodedtypes["float32"],
539
+ physical_type=PhysicalType(DataType.A_FLOAT32, display_radix=None, precision=None),
540
+ compu_method=somersault_compumethods["float_passthrough"],
541
+ unit_ref=None,
542
+ is_visible_raw=None,
543
+ sdgs=[],
544
+ ),
508
545
  }
509
546
 
547
+ last_flip_details_table_id = OdxLinkId("somersault.table.last_flip_details", doc_frags)
548
+ last_flip_details_table_ref = OdxLinkRef.from_id(last_flip_details_table_id)
549
+
510
550
  # positive responses
511
551
  somersault_positive_responses = {
512
552
  "session":
@@ -702,15 +742,27 @@ somersault_positive_responses = {
702
742
  bit_position=None,
703
743
  sdgs=[],
704
744
  ),
705
- # TODO (?): non-byte aligned MatchingRequestParameters
706
- MatchingRequestParameter(
745
+ ValueParameter(
707
746
  short_name="num_flips_done",
708
747
  long_name=None,
709
748
  semantic=None,
710
749
  description=None,
711
- request_byte_position=3,
712
- byte_position=1,
713
- byte_length=1,
750
+ physical_default_value_raw=None,
751
+ dop_ref=OdxLinkRef("somersault.DOP.uint8", doc_frags),
752
+ dop_snref=None,
753
+ byte_position=None,
754
+ bit_position=None,
755
+ sdgs=[],
756
+ ),
757
+ ValueParameter(
758
+ short_name="grumpiness_level",
759
+ long_name=None,
760
+ semantic=None,
761
+ description=None,
762
+ physical_default_value_raw=None,
763
+ dop_ref=OdxLinkRef("somersault.DOP.uint8", doc_frags),
764
+ dop_snref=None,
765
+ byte_position=None,
714
766
  bit_position=None,
715
767
  sdgs=[],
716
768
  ),
@@ -767,6 +819,33 @@ somersault_positive_responses = {
767
819
  bit_position=None,
768
820
  sdgs=[],
769
821
  ),
822
+ TableKeyParameter(
823
+ odx_id=OdxLinkId("somersault.PR.report_status.last_pos_response_key",
824
+ doc_frags),
825
+ short_name="last_pos_response_key",
826
+ long_name=None,
827
+ semantic=None,
828
+ description=None,
829
+ table_ref=last_flip_details_table_ref,
830
+ table_snref=None,
831
+ table_row_ref=None,
832
+ table_row_snref=None,
833
+ byte_position=3,
834
+ bit_position=None,
835
+ sdgs=[],
836
+ ),
837
+ TableStructParameter(
838
+ short_name="last_pos_response",
839
+ long_name=None,
840
+ semantic=None,
841
+ description=None,
842
+ table_key_ref=OdxLinkRef(
843
+ "somersault.PR.report_status.last_pos_response_key", doc_frags),
844
+ table_key_snref=None,
845
+ byte_position=None,
846
+ bit_position=None,
847
+ sdgs=[],
848
+ ),
770
849
  ],
771
850
  ),
772
851
  byte_size=None,
@@ -1026,51 +1105,82 @@ somersault_global_negative_responses = {
1026
1105
  }
1027
1106
 
1028
1107
  # tables
1108
+ flip_quality_table_id = OdxLinkId("somersault.table.flip_quality", doc_frags)
1109
+ flip_quality_table_ref = OdxLinkRef.from_id(flip_quality_table_id)
1029
1110
  somersault_tables = {
1030
- "flip_quality":
1111
+ "last_flip_details":
1031
1112
  Table(
1032
- odx_id=OdxLinkId("somersault.table.flip_quality", doc_frags),
1033
- short_name="flip_quality",
1034
- long_name="Flip Quality",
1035
- description="<p>The quality the flip (average, good or best)</p>",
1036
- semantic="QUALITY",
1037
- key_dop_ref=OdxLinkRef.from_id(somersault_dops["num_flips"].odx_id),
1038
- table_rows=[
1113
+ odx_id=last_flip_details_table_id,
1114
+ short_name="last_flip_details",
1115
+ long_name="Flip Details",
1116
+ description="<p>The details the last successfully executed request</p>",
1117
+ semantic="DETAILS",
1118
+ admin_data=None,
1119
+ key_label="key",
1120
+ struct_label="response",
1121
+ key_dop_ref=OdxLinkRef.from_id(somersault_dops["uint8"].odx_id),
1122
+ table_rows_raw=[
1039
1123
  TableRow(
1040
- odx_id=OdxLinkId("somersault.table.flip_quality.average", doc_frags),
1041
- short_name="average",
1042
- long_name="Average",
1043
- key=3,
1044
- structure_ref=OdxLinkRef.from_id(somersault_dops["num_flips"].odx_id),
1045
- description="<p>The quality of the flip is average</p>",
1046
- semantic="QUALITY-KEY",
1124
+ table_ref=last_flip_details_table_ref,
1125
+ odx_id=OdxLinkId("somersault.table.last_flip_details.none", doc_frags),
1126
+ short_name="none",
1127
+ long_name="No Flips Done Yet",
1128
+ key_raw="0",
1129
+ structure_ref=None,
1130
+ structure_snref=None,
1131
+ description="<p>We have not done any flips yet!</p>",
1132
+ semantic="DETAILS-KEY",
1133
+ dop_ref=OdxLinkRef.from_id(somersault_dops["soberness_check"].odx_id),
1134
+ dop_snref=None,
1135
+ sdgs=[],
1136
+ ),
1137
+ TableRow(
1138
+ table_ref=last_flip_details_table_ref,
1139
+ odx_id=OdxLinkId("somersault.table.last_flip_details.forward_grudging",
1140
+ doc_frags),
1141
+ short_name="forward_grudging",
1142
+ long_name="Forward Flips Grudgingly Done",
1143
+ key_raw="3",
1144
+ structure_ref=OdxLinkRef.from_id(
1145
+ somersault_positive_responses["forward_flips_grudgingly_done"].odx_id),
1146
+ structure_snref=None,
1147
+ description="<p>The the last forward flip was grudgingly done</p>",
1148
+ semantic="DETAILS-KEY",
1047
1149
  dop_ref=None,
1150
+ dop_snref=None,
1048
1151
  sdgs=[],
1049
1152
  ),
1050
1153
  TableRow(
1051
- odx_id=OdxLinkId("somersault.table.flip_quality.good", doc_frags),
1052
- short_name="good",
1053
- long_name="Good",
1154
+ table_ref=last_flip_details_table_ref,
1155
+ odx_id=OdxLinkId("somersault.table.last_flip_details.forward_happy", doc_frags),
1156
+ short_name="forward_happily",
1157
+ long_name="Forward Flips Happily Done",
1054
1158
  description=None,
1055
1159
  semantic=None,
1056
- key=5,
1057
- structure_ref=OdxLinkRef.from_id(somersault_dops["num_flips"].odx_id),
1160
+ key_raw="5",
1161
+ structure_ref=OdxLinkRef.from_id(
1162
+ somersault_positive_responses["forward_flips_happily_done"].odx_id),
1163
+ structure_snref=None,
1058
1164
  dop_ref=None,
1165
+ dop_snref=None,
1059
1166
  sdgs=[],
1060
1167
  ),
1061
1168
  TableRow(
1062
- odx_id=OdxLinkId("somersault.table.flip_quality.best", doc_frags),
1063
- short_name="best",
1064
- long_name="Best",
1169
+ table_ref=last_flip_details_table_ref,
1170
+ odx_id=OdxLinkId("somersault.table.last_flip_details.backward", doc_frags),
1171
+ short_name="backward_grudging",
1172
+ long_name="Backward Flips",
1065
1173
  description=None,
1066
1174
  semantic=None,
1067
- key=10,
1068
- structure_ref=OdxLinkRef.from_id(somersault_dops["num_flips"].odx_id),
1175
+ key_raw="10",
1176
+ structure_ref=OdxLinkRef.from_id(
1177
+ somersault_positive_responses["backward_flips_grudgingly_done"].odx_id),
1178
+ structure_snref=None,
1069
1179
  dop_ref=None,
1180
+ dop_snref=None,
1070
1181
  sdgs=[],
1071
1182
  ),
1072
1183
  ],
1073
- table_row_refs=[],
1074
1184
  sdgs=[],
1075
1185
  )
1076
1186
  }
@@ -1196,7 +1306,7 @@ somersault_requests = {
1196
1306
  sdgs=[],
1197
1307
  ),
1198
1308
  CodedConstParameter(
1199
- short_name="odx_id",
1309
+ short_name="id",
1200
1310
  long_name=None,
1201
1311
  semantic=None,
1202
1312
  description=None,
@@ -1230,7 +1340,7 @@ somersault_requests = {
1230
1340
  sdgs=[],
1231
1341
  ),
1232
1342
  CodedConstParameter(
1233
- short_name="odx_id",
1343
+ short_name="id",
1234
1344
  long_name=None,
1235
1345
  semantic=None,
1236
1346
  description=None,
@@ -1264,7 +1374,7 @@ somersault_requests = {
1264
1374
  sdgs=[],
1265
1375
  ),
1266
1376
  CodedConstParameter(
1267
- short_name="odx_id",
1377
+ short_name="id",
1268
1378
  long_name=None,
1269
1379
  semantic=None,
1270
1380
  description=None,
@@ -1430,7 +1540,7 @@ somersault_requests = {
1430
1540
  sdgs=[],
1431
1541
  ),
1432
1542
  CodedConstParameter(
1433
- short_name="odx_id",
1543
+ short_name="id",
1434
1544
  long_name=None,
1435
1545
  semantic=None,
1436
1546
  description=None,
@@ -158,38 +158,24 @@ class SomersaultLazyEcu:
158
158
 
159
159
  self.isotp_socket = create_isotp_socket(
160
160
  can_channel,
161
- rxid=somersault_lazy_diag_layer.get_receive_id(),
162
- txid=somersault_lazy_diag_layer.get_send_id(),
161
+ rxid=somersault_lazy_diag_layer.get_can_receive_id(),
162
+ txid=somersault_lazy_diag_layer.get_can_send_id(),
163
163
  )
164
164
 
165
165
  ##############
166
166
  # extract the tester present parameters from the ECU's
167
167
  # communication parameters.
168
- #
169
- # TODO: move this into the DiagLayer analogous to
170
- # get_receive_id() plus deal with more parameters.
171
168
  ##############
172
169
 
173
- # the timeout on inactivity [s]
174
- cps = [
175
- x for x in somersault_lazy_diag_layer.communication_parameters
176
- if x.id_ref == "ISO_14230_3.CP_TesterPresentTime"
177
- ]
178
-
179
- if len(cps):
180
- assert len(cps) == 1
181
- self._idle_timeout = int(cps[0].value) / 1e6
182
- else:
170
+ # determine the timeout on inactivity [s]
171
+ self._idle_timeout = somersault_lazy_diag_layer.get_tester_present_time()
172
+ if self._idle_timeout is None:
183
173
  self._idle_timeout = 3.0 # default specified by the standard
184
174
 
185
175
  # we send a response to tester present messages. make sure
186
176
  # that this is specified
187
- cps = [
188
- x for x in somersault_lazy_diag_layer.communication_parameters
189
- if x.id_ref == "ISO_15765_3.CP_TesterPresentReqRsp"
190
- ]
191
- assert len(cps) == 1
192
- assert cps[0].value == "Response expected" or cps[0].value == "1"
177
+ cp = somersault_lazy_diag_layer.get_communication_parameter("CP_TesterPresentReqRsp")
178
+ assert cp.value == "Response expected" or cp.value == "1"
193
179
 
194
180
  async def _handle_requests_task(self):
195
181
  loop = asyncio.get_running_loop()
@@ -288,8 +274,7 @@ class SomersaultLazyEcu:
288
274
  num_flips = message.param_dict["num_flips"]
289
275
 
290
276
  if soberness_check != 0x12:
291
- response = [x for x in service.negative_responses if x.short_name == "flips_not_done"
292
- ][0]
277
+ response = service.negative_responses.flips_not_done
293
278
  response_data = response.encode(
294
279
  coded_request=message.coded_message,
295
280
  reason=0, # -> not sober
@@ -301,9 +286,7 @@ class SomersaultLazyEcu:
301
286
  # we cannot do all flips because we are too dizzy
302
287
  if self.dizziness_level + num_flips > self.max_dizziness_level:
303
288
 
304
- response = [
305
- x for x in service.positive_responses if x.short_name == "grudging_forward"
306
- ][0]
289
+ response = service.positive_responses.grudging_forward
307
290
  response_data = response.encode(
308
291
  coded_request=message.coded_message,
309
292
  reason=1, # -> too dizzy
@@ -317,9 +300,7 @@ class SomersaultLazyEcu:
317
300
  # because we stumble
318
301
  for i in range(0, num_flips):
319
302
  if random.randrange(0, 10000) < 100:
320
- response = [
321
- x for x in service.negative_responses if x.short_name == "flips_not_done"
322
- ]
303
+ response = service.negative_responses.flips_not_done
323
304
  response_data = response.encode(
324
305
  coded_request=message.coded_message,
325
306
  reason=2, # -> stumbled
@@ -330,7 +311,7 @@ class SomersaultLazyEcu:
330
311
 
331
312
  self.dizziness_level += 1
332
313
 
333
- response = [x for x in service.positive_responses if x.short_name == "grudging_forward"][0]
314
+ response = service.positive_responses.grudging_forward
334
315
  response_data = response.encode(coded_request=message.coded_message)
335
316
  await ecu_send(self.isotp_socket, response_data)
336
317
 
@@ -428,8 +409,8 @@ async def tester_main():
428
409
  # reversed.
429
410
  isotp_socket = create_isotp_socket(
430
411
  can_channel,
431
- txid=somersault_lazy_diag_layer.get_receive_id(),
432
- rxid=somersault_lazy_diag_layer.get_send_id(),
412
+ txid=somersault_lazy_diag_layer.get_can_receive_id(),
413
+ rxid=somersault_lazy_diag_layer.get_can_send_id(),
433
414
  )
434
415
 
435
416
  # try to to do a single forward flip without having an active session (ought to fail)
@@ -507,9 +488,6 @@ async def main(args):
507
488
  else:
508
489
  assert args.mode == "unittest"
509
490
 
510
- logging.basicConfig(level=logging.DEBUG)
511
- logging.getLogger("odxtools").setLevel(logging.WARNING)
512
-
513
491
  # run both tasks in parallel. Since the server task does not
514
492
  # complete, we need to wait until the first task is completed
515
493
  # and then manually that this was the server task
@@ -550,6 +528,11 @@ parser.add_argument(
550
528
 
551
529
  args = parser.parse_args() # deals with the help message handling
552
530
 
531
+ # set the verbosity of the log output
532
+ logging.basicConfig(level=logging.DEBUG) # log messages from the ECU itself
533
+ logging.getLogger("odxtools").setLevel(
534
+ logging.WARNING) # log messages stemming from the odxtools library
535
+
553
536
  can_channel = args.channel
554
537
 
555
538
  asyncio.run(main(args))
@@ -2,6 +2,7 @@
2
2
  # Copyright (c) 2022 MBition GmbH
3
3
  from typing import NamedTuple, Optional, Union
4
4
 
5
+ from ..odxtypes import AtomicOdxType
5
6
  from .compurationalcoeffs import CompuRationalCoeffs
6
7
  from .limit import Limit
7
8
 
@@ -33,6 +34,6 @@ class CompuScale(NamedTuple):
33
34
  description: Optional[str] = None
34
35
  lower_limit: Optional[Limit] = None
35
36
  upper_limit: Optional[Limit] = None
36
- compu_inverse_value: Optional[Union[float, str, bytearray]] = None
37
+ compu_inverse_value: Optional[AtomicOdxType] = None
37
38
  compu_const: Optional[Union[float, str]] = None
38
39
  compu_rational_coeffs: Optional[CompuRationalCoeffs] = None
@@ -37,7 +37,7 @@ class Limit(NamedTuple):
37
37
  hex_text = et_element.text
38
38
  if len(hex_text) % 2 == 1:
39
39
  hex_text = "0" + hex_text
40
- return Limit(bytearray.fromhex(hex_text), interval_type)
40
+ return Limit(bytes.fromhex(hex_text), interval_type)
41
41
  else:
42
42
  return Limit(internal_type.from_string(et_element.text), interval_type)
43
43
 
@@ -1,7 +1,7 @@
1
1
  # SPDX-License-Identifier: MIT
2
2
  # Copyright (c) 2022 MBition GmbH
3
3
  from dataclasses import dataclass, field
4
- from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union, cast
4
+ from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple, Union, cast
5
5
 
6
6
  from .compumethods import CompuMethod, create_any_compu_method_from_et
7
7
  from .decodestate import DecodeState
@@ -42,8 +42,6 @@ class DopBase:
42
42
  result += hash(self.long_name)
43
43
  result += hash(self.description)
44
44
  result += hash(self.is_visible_raw)
45
- for sdg in self.sdgs:
46
- result += hash(sdg)
47
45
 
48
46
  return result
49
47
 
@@ -166,12 +164,16 @@ class DataObjectProperty(DopBase):
166
164
  return dop
167
165
 
168
166
  def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
169
- return super()._build_odxlinks()
167
+ result = super()._build_odxlinks()
168
+ result.update(self.diag_coded_type._build_odxlinks())
169
+ return result
170
170
 
171
171
  def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase):
172
172
  """Resolves the reference to the unit"""
173
173
  super()._resolve_odxlinks(odxlinks)
174
174
 
175
+ self.diag_coded_type._resolve_odxlinks(odxlinks)
176
+
175
177
  self._unit: Optional[Unit] = None
176
178
  if self.unit_ref:
177
179
  self._unit = odxlinks.resolve(self.unit_ref, Unit)
@@ -179,6 +181,8 @@ class DataObjectProperty(DopBase):
179
181
  def _resolve_snrefs(self, diag_layer: "DiagLayer") -> None:
180
182
  super()._resolve_snrefs(diag_layer)
181
183
 
184
+ self.diag_coded_type._resolve_snrefs(diag_layer)
185
+
182
186
  @property
183
187
  def unit(self) -> Optional[Unit]:
184
188
  return self._unit
@@ -192,14 +196,21 @@ class DataObjectProperty(DopBase):
192
196
  else:
193
197
  return None
194
198
 
195
- def convert_physical_to_internal(self, physical_value):
199
+ def convert_physical_to_internal(self, physical_value: Any) -> Any:
200
+ """
201
+ Convert a physical representation of a parameter to its internal counterpart
202
+ """
196
203
  assert self.physical_type.base_data_type.isinstance(
197
204
  physical_value
198
205
  ), f"Expected {self.physical_type.base_data_type.value}, got {type(physical_value)}"
199
206
 
200
207
  return self.compu_method.convert_physical_to_internal(physical_value)
201
208
 
202
- def convert_physical_to_bytes(self, physical_value, encode_state, bit_position):
209
+ def convert_physical_to_bytes(self, physical_value: Any, encode_state: EncodeState,
210
+ bit_position: int) -> bytes:
211
+ """
212
+ Convert a physical representation of a parameter to a string bytes that can be send over the wire
213
+ """
203
214
  if not self.is_valid_physical_value(physical_value):
204
215
  raise EncodeError(f"The value {repr(physical_value)} of type {type(physical_value)}"
205
216
  f" is not a valid." +
@@ -211,7 +222,14 @@ class DataObjectProperty(DopBase):
211
222
  return self.diag_coded_type.convert_internal_to_bytes(
212
223
  internal_val, encode_state, bit_position=bit_position)
213
224
 
214
- def convert_bytes_to_physical(self, decode_state, bit_position: int = 0):
225
+ def convert_bytes_to_physical(self,
226
+ decode_state: DecodeState,
227
+ bit_position: int = 0) -> Tuple[Any, int]:
228
+ """
229
+ Convert the internal representation of a value into its physical value.
230
+
231
+ Returns a (physical_value, start_position_of_next_parameter) tuple.
232
+ """
215
233
  assert 0 <= bit_position and bit_position < 8
216
234
 
217
235
  internal, next_byte_position = self.diag_coded_type.convert_bytes_to_internal(
@@ -255,7 +273,7 @@ class DiagnosticTroubleCode:
255
273
  short_name: Optional[str]
256
274
  text: Optional[str]
257
275
  display_trouble_code: Optional[str]
258
- level: Union[bytes, bytearray, None]
276
+ level: Union[bytes, None]
259
277
  is_temporary_raw: Optional[bool]
260
278
  sdgs: List[SpecialDataGroup]
261
279
 
@@ -0,0 +1,24 @@
1
+ # SPDX-License-Identifier: MIT
2
+ # Copyright (c) 2022 MBition GmbH
3
+ from dataclasses import dataclass, field
4
+ from typing import TYPE_CHECKING, Any, Dict, List, NamedTuple, Union
5
+
6
+ from .odxtypes import ParameterValueDict
7
+
8
+ if TYPE_CHECKING:
9
+ from .parameters.parameterbase import Parameter
10
+ from .tablerow import TableRow
11
+
12
+
13
+ @dataclass
14
+ class DecodeState:
15
+ """Utility class to be used while decoding a message."""
16
+
17
+ #: bytes to be decoded
18
+ coded_message: bytes
19
+
20
+ #: values of already decoded parameters
21
+ parameter_values: ParameterValueDict
22
+
23
+ #: Position of the next parameter if its position is not specified in ODX
24
+ next_byte_position: int