pyxcp 0.21.9__cp312-cp312-win_amd64.whl → 0.22.23__cp312-cp312-win_amd64.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.

Potentially problematic release.


This version of pyxcp might be problematic. Click here for more details.

Files changed (182) hide show
  1. pyxcp/__init__.py +12 -20
  2. pyxcp/aml/EtasCANMonitoring.a2l +82 -83
  3. pyxcp/aml/XCP_Common.aml +0 -1
  4. pyxcp/aml/XCPonUSB.aml +1 -1
  5. pyxcp/aml/ifdata_CAN.a2l +0 -1
  6. pyxcp/aml/ifdata_Eth.a2l +0 -1
  7. pyxcp/aml/ifdata_Flx.a2l +0 -1
  8. pyxcp/aml/ifdata_SxI.a2l +0 -1
  9. pyxcp/aml/ifdata_USB.a2l +0 -1
  10. pyxcp/asam/types.py +4 -4
  11. pyxcp/asamkeydll.c +0 -1
  12. pyxcp/checksum.py +0 -1
  13. pyxcp/cmdline.py +32 -50
  14. pyxcp/config/__init__.py +1100 -0
  15. pyxcp/config/legacy.py +120 -0
  16. pyxcp/constants.py +12 -13
  17. pyxcp/cpp_ext/__init__.py +0 -0
  18. pyxcp/cpp_ext/bin.hpp +104 -0
  19. pyxcp/cpp_ext/blockmem.hpp +58 -0
  20. pyxcp/cpp_ext/cpp_ext.cp310-win_amd64.pyd +0 -0
  21. pyxcp/cpp_ext/cpp_ext.cp311-win_amd64.pyd +0 -0
  22. pyxcp/cpp_ext/cpp_ext.cp312-win_amd64.pyd +0 -0
  23. pyxcp/cpp_ext/cpp_ext.cp38-win_amd64.pyd +0 -0
  24. pyxcp/cpp_ext/cpp_ext.cp39-win_amd64.pyd +0 -0
  25. pyxcp/cpp_ext/daqlist.hpp +200 -0
  26. pyxcp/cpp_ext/event.hpp +67 -0
  27. pyxcp/cpp_ext/extension_wrapper.cpp +96 -0
  28. pyxcp/cpp_ext/helper.hpp +280 -0
  29. pyxcp/cpp_ext/mcobject.hpp +246 -0
  30. pyxcp/cpp_ext/tsqueue.hpp +46 -0
  31. pyxcp/daq_stim/__init__.py +228 -0
  32. pyxcp/daq_stim/optimize/__init__.py +67 -0
  33. pyxcp/daq_stim/optimize/binpacking.py +41 -0
  34. pyxcp/daq_stim/scheduler.cpp +28 -0
  35. pyxcp/daq_stim/scheduler.hpp +75 -0
  36. pyxcp/daq_stim/stim.cp310-win_amd64.pyd +0 -0
  37. pyxcp/daq_stim/stim.cp311-win_amd64.pyd +0 -0
  38. pyxcp/daq_stim/stim.cp312-win_amd64.pyd +0 -0
  39. pyxcp/daq_stim/stim.cp38-win_amd64.pyd +0 -0
  40. pyxcp/daq_stim/stim.cp39-win_amd64.pyd +0 -0
  41. pyxcp/daq_stim/stim.cpp +13 -0
  42. pyxcp/daq_stim/stim.hpp +604 -0
  43. pyxcp/daq_stim/stim_wrapper.cpp +48 -0
  44. pyxcp/dllif.py +21 -18
  45. pyxcp/errormatrix.py +5 -3
  46. pyxcp/examples/conf_can.toml +4 -2
  47. pyxcp/examples/conf_can_vector.json +9 -9
  48. pyxcp/examples/conf_can_vector.toml +4 -2
  49. pyxcp/examples/conf_eth.toml +5 -2
  50. pyxcp/examples/conf_nixnet.json +18 -18
  51. pyxcp/examples/conf_sxi.json +7 -7
  52. pyxcp/examples/ex_arrow.py +109 -0
  53. pyxcp/examples/ex_csv.py +85 -0
  54. pyxcp/examples/ex_excel.py +95 -0
  55. pyxcp/examples/ex_mdf.py +124 -0
  56. pyxcp/examples/ex_sqlite.py +128 -0
  57. pyxcp/examples/run_daq.py +148 -0
  58. pyxcp/examples/xcp_policy.py +6 -7
  59. pyxcp/examples/xcp_read_benchmark.py +8 -6
  60. pyxcp/examples/xcp_skel.py +0 -2
  61. pyxcp/examples/xcp_unlock.py +1 -1
  62. pyxcp/examples/xcp_user_supplied_driver.py +1 -2
  63. pyxcp/examples/xcphello.py +6 -3
  64. pyxcp/examples/xcphello_recorder.py +4 -4
  65. pyxcp/master/__init__.py +1 -2
  66. pyxcp/master/errorhandler.py +107 -74
  67. pyxcp/master/master.py +196 -114
  68. pyxcp/py.typed +0 -0
  69. pyxcp/recorder/__init__.py +27 -6
  70. pyxcp/recorder/converter/__init__.py +37 -0
  71. pyxcp/recorder/lz4.c +129 -51
  72. pyxcp/recorder/lz4.h +45 -28
  73. pyxcp/recorder/lz4hc.c +560 -156
  74. pyxcp/recorder/lz4hc.h +1 -1
  75. pyxcp/recorder/mio.hpp +721 -767
  76. pyxcp/recorder/reader.hpp +139 -0
  77. pyxcp/recorder/reco.py +5 -8
  78. pyxcp/recorder/rekorder.cp310-win_amd64.pyd +0 -0
  79. pyxcp/recorder/rekorder.cp311-win_amd64.pyd +0 -0
  80. pyxcp/recorder/rekorder.cp312-win_amd64.pyd +0 -0
  81. pyxcp/recorder/rekorder.cp38-win_amd64.pyd +0 -0
  82. pyxcp/recorder/rekorder.cp39-win_amd64.pyd +0 -0
  83. pyxcp/recorder/rekorder.cpp +18 -22
  84. pyxcp/recorder/rekorder.hpp +200 -587
  85. pyxcp/recorder/setup.py +11 -10
  86. pyxcp/recorder/test_reko.py +2 -3
  87. pyxcp/recorder/unfolder.hpp +1332 -0
  88. pyxcp/recorder/wrap.cpp +171 -9
  89. pyxcp/recorder/writer.hpp +302 -0
  90. pyxcp/scripts/pyxcp_probe_can_drivers.py +0 -2
  91. pyxcp/scripts/xcp_examples.py +64 -0
  92. pyxcp/scripts/xcp_fetch_a2l.py +15 -10
  93. pyxcp/scripts/xcp_id_scanner.py +2 -6
  94. pyxcp/scripts/xcp_info.py +101 -63
  95. pyxcp/scripts/xcp_profile.py +27 -0
  96. pyxcp/stim/__init__.py +0 -0
  97. pyxcp/tests/test_asam_types.py +2 -2
  98. pyxcp/tests/test_binpacking.py +186 -0
  99. pyxcp/tests/test_can.py +1132 -38
  100. pyxcp/tests/test_checksum.py +2 -1
  101. pyxcp/tests/test_daq.py +193 -0
  102. pyxcp/tests/test_frame_padding.py +6 -3
  103. pyxcp/tests/test_master.py +42 -31
  104. pyxcp/tests/test_transport.py +12 -12
  105. pyxcp/tests/test_utils.py +2 -5
  106. pyxcp/timing.py +0 -2
  107. pyxcp/transport/__init__.py +9 -9
  108. pyxcp/transport/base.py +149 -127
  109. pyxcp/transport/base_transport.hpp +0 -0
  110. pyxcp/transport/can.py +194 -167
  111. pyxcp/transport/eth.py +80 -82
  112. pyxcp/transport/sxi.py +106 -60
  113. pyxcp/transport/transport_wrapper.cpp +0 -0
  114. pyxcp/transport/usb_transport.py +65 -83
  115. pyxcp/types.py +69 -20
  116. pyxcp/utils.py +47 -16
  117. pyxcp/vector/map.py +1 -3
  118. {pyxcp-0.21.9.dist-info → pyxcp-0.22.23.dist-info}/METADATA +28 -23
  119. pyxcp-0.22.23.dist-info/RECORD +140 -0
  120. {pyxcp-0.21.9.dist-info → pyxcp-0.22.23.dist-info}/WHEEL +1 -1
  121. {pyxcp-0.21.9.dist-info → pyxcp-0.22.23.dist-info}/entry_points.txt +2 -0
  122. pyxcp/config.py +0 -57
  123. pyxcp/cxx/asynchiofactory.hpp +0 -24
  124. pyxcp/cxx/blocking_client.cpp +0 -44
  125. pyxcp/cxx/blocking_socket.cpp +0 -43
  126. pyxcp/cxx/blocking_socket.hpp +0 -558
  127. pyxcp/cxx/concurrent_queue.hpp +0 -60
  128. pyxcp/cxx/eth.hpp +0 -57
  129. pyxcp/cxx/exceptions.hpp +0 -30
  130. pyxcp/cxx/iasyncioservice.hpp +0 -31
  131. pyxcp/cxx/iresource.hpp +0 -17
  132. pyxcp/cxx/isocket.hpp +0 -22
  133. pyxcp/cxx/linux/epoll.cpp +0 -51
  134. pyxcp/cxx/linux/epoll.hpp +0 -87
  135. pyxcp/cxx/linux/lit_tester.cpp +0 -19
  136. pyxcp/cxx/linux/socket.hpp +0 -234
  137. pyxcp/cxx/linux/timeout.hpp +0 -81
  138. pyxcp/cxx/memoryblock.hpp +0 -42
  139. pyxcp/cxx/pool.hpp +0 -81
  140. pyxcp/cxx/poolmgr.cpp +0 -6
  141. pyxcp/cxx/poolmgr.hpp +0 -31
  142. pyxcp/cxx/test_queue.cpp +0 -69
  143. pyxcp/cxx/timestamp.hpp +0 -84
  144. pyxcp/cxx/utils.cpp +0 -38
  145. pyxcp/cxx/utils.hpp +0 -29
  146. pyxcp/cxx/win/iocp.cpp +0 -242
  147. pyxcp/cxx/win/iocp.hpp +0 -42
  148. pyxcp/cxx/win/perhandledata.hpp +0 -24
  149. pyxcp/cxx/win/periodata.hpp +0 -97
  150. pyxcp/cxx/win/socket.hpp +0 -185
  151. pyxcp/cxx/win/timeout.hpp +0 -83
  152. pyxcp/examples/conf_can.json +0 -20
  153. pyxcp/examples/conf_eth.json +0 -8
  154. pyxcp/logger.py +0 -67
  155. pyxcp/tests/test_config.py +0 -62
  156. pyxcp/transport/candriver/__init__.py +0 -2
  157. pyxcp/transport/candriver/pc_canalystii.py +0 -27
  158. pyxcp/transport/candriver/pc_etas.py +0 -25
  159. pyxcp/transport/candriver/pc_gsusb.py +0 -23
  160. pyxcp/transport/candriver/pc_iscan.py +0 -23
  161. pyxcp/transport/candriver/pc_ixxat.py +0 -27
  162. pyxcp/transport/candriver/pc_kvaser.py +0 -39
  163. pyxcp/transport/candriver/pc_neovi.py +0 -31
  164. pyxcp/transport/candriver/pc_nican.py +0 -23
  165. pyxcp/transport/candriver/pc_nixnet.py +0 -23
  166. pyxcp/transport/candriver/pc_pcan.py +0 -25
  167. pyxcp/transport/candriver/pc_seeed.py +0 -28
  168. pyxcp/transport/candriver/pc_serial.py +0 -27
  169. pyxcp/transport/candriver/pc_slcan.py +0 -29
  170. pyxcp/transport/candriver/pc_socketcan.py +0 -23
  171. pyxcp/transport/candriver/pc_systec.py +0 -29
  172. pyxcp/transport/candriver/pc_usb2can.py +0 -30
  173. pyxcp/transport/candriver/pc_vector.py +0 -34
  174. pyxcp/transport/candriver/python_can.py +0 -101
  175. pyxcp/transport/cxx_ext/CMakeLists.txt +0 -51
  176. pyxcp/transport/cxx_ext/setup.py +0 -49
  177. pyxcp/transport/cxx_ext/tests/test_basic_socket.cpp +0 -39
  178. pyxcp/transport/cxx_ext/tests/test_pool.cpp +0 -39
  179. pyxcp/transport/cxx_ext/tests/test_timestamp.cpp +0 -27
  180. pyxcp-0.21.9.dist-info/RECORD +0 -147
  181. rekorder.cp312-win_amd64.pyd +0 -0
  182. {pyxcp-0.21.9.dist-info/licenses → pyxcp-0.22.23.dist-info}/LICENSE +0 -0
@@ -1,55 +1,57 @@
1
1
  #!/usr/bin/env python
2
- # -*- coding: utf-8 -*-
3
2
  import struct
4
3
  import threading
5
4
  from array import array
6
5
  from collections import deque
7
- from time import perf_counter
8
- from time import sleep
9
- from time import time
6
+ from typing import Optional
10
7
 
11
- import usb.backend.libusb1 as libusb1
12
8
  import usb.backend.libusb0 as libusb0
9
+ import usb.backend.libusb1 as libusb1
13
10
  import usb.backend.openusb as openusb
14
11
  import usb.core
15
12
  import usb.util
13
+ from usb.core import USBError, USBTimeoutError
16
14
 
17
15
  from pyxcp.transport.base import BaseTransport
18
- from pyxcp.utils import SHORT_SLEEP
16
+ from pyxcp.utils import short_sleep
17
+
19
18
 
20
19
  RECV_SIZE = 16384
20
+ FIVE_MS = 5_000_000 # Five milliseconds in nanoseconds.
21
21
 
22
22
 
23
23
  class Usb(BaseTransport):
24
24
  """"""
25
25
 
26
- PARAMETER_MAP = {
27
- # Type Req'd Default
28
- "serial_number": (str, True, ""),
29
- "configuration_number": (int, True, 1),
30
- "interface_number": (int, True, 2),
31
- "command_endpoint_number": (int, True, 0),
32
- "reply_endpoint_number": (int, True, 1),
33
- "vendor_id": (int, False, 0),
34
- "product_id": (int, False, 0),
35
- "library": (str, False, "") # absolute path to USB shared library
36
- }
37
26
  HEADER = struct.Struct("<2H")
38
27
  HEADER_SIZE = HEADER.size
39
28
 
40
- def __init__(self, config=None, policy=None):
41
- super(Usb, self).__init__(config, policy)
42
- self.loadConfig(config)
43
- self.serial_number = self.config.get("serial_number").strip()
44
- self.vendor_id = self.config.get("vendor_id")
45
- self.product_id = self.config.get("product_id")
46
- self.configuration_number = self.config.get("configuration_number")
47
- self.interface_number = self.config.get("interface_number")
48
- self.command_endpoint_number = self.config.get("command_endpoint_number")
49
- self.reply_endpoint_number = self.config.get("reply_endpoint_number")
29
+ def __init__(self, config=None, policy=None, transport_layer_interface: Optional[usb.core.Device] = None):
30
+ super().__init__(config, policy, transport_layer_interface)
31
+ self.load_config(config)
32
+ self.serial_number: str = self.config.serial_number
33
+ self.vendor_id: int = self.config.vendor_id
34
+ self.product_id: int = self.config.product_id
35
+ self.configuration_number: int = self.config.configuration_number
36
+ self.interface_number: int = self.config.interface_number
37
+ self.library: str = self.config.library
38
+ self.header_format: str = self.config.header_format
50
39
  self.library = self.config.get("library")
51
40
  self.device = None
52
41
 
42
+ ## IN-EP (RES/ERR, DAQ, and EV/SERV) Parameters.
43
+ self.in_ep_number: int = self.config.in_ep_number
44
+ self.in_ep_transfer_type = self.config.in_ep_transfer_type
45
+ self.in_ep_max_packet_size: int = self.config.in_ep_max_packet_size
46
+ self.in_ep_polling_interval: int = self.config.in_ep_polling_interval
47
+ self.in_ep_message_packing = self.config.in_ep_message_packing
48
+ self.in_ep_alignment = self.config.in_ep_alignment
49
+ self.in_ep_recommended_host_bufsize: int = self.config.in_ep_recommended_host_bufsize
50
+
51
+ ## OUT-EP (CMD and STIM) Parameters.
52
+ self.out_ep_number: int = self.config.out_ep_number
53
+
54
+ self.device: Optional[usb.core.Device] = None
53
55
  self.status = 0
54
56
 
55
57
  self._packet_listener = threading.Thread(
@@ -86,10 +88,10 @@ class Usb(BaseTransport):
86
88
  if device.serial_number.strip().strip("\0").lower() == self.serial_number.lower():
87
89
  self.device = device
88
90
  break
89
- except BaseException:
91
+ except (USBError, USBTimeoutError):
90
92
  continue
91
93
  else:
92
- raise Exception("Device with serial {} not found".format(self.serial_number))
94
+ raise Exception(f"XCPonUSB - device with serial {self.serial_number!r} not found")
93
95
 
94
96
  current_configuration = self.device.get_active_configuration()
95
97
  if current_configuration.bConfigurationValue != self.configuration_number:
@@ -98,14 +100,14 @@ class Usb(BaseTransport):
98
100
 
99
101
  interface = cfg[(self.interface_number, 0)]
100
102
 
101
- self.command_endpoint = interface[self.command_endpoint_number]
102
- self.reply_endpoint = interface[self.reply_endpoint_number]
103
+ self.out_ep = interface[self.out_ep_number]
104
+ self.in_ep = interface[self.in_ep_number]
103
105
 
104
- self.startListener()
106
+ self.start_listener()
105
107
  self.status = 1 # connected
106
108
 
107
- def startListener(self):
108
- super().startListener()
109
+ def start_listener(self):
110
+ super().start_listener()
109
111
  if self._packet_listener.is_alive():
110
112
  self._packet_listener.join()
111
113
  self._packet_listener = threading.Thread(target=self._packet_listen)
@@ -113,83 +115,68 @@ class Usb(BaseTransport):
113
115
 
114
116
  def close(self):
115
117
  """Close the transport-layer connection and event-loop."""
116
- self.finishListener()
118
+ self.finish_listener()
117
119
  if self.listener.is_alive():
118
120
  self.listener.join()
119
121
  if self._packet_listener.is_alive():
120
122
  self._packet_listener.join()
121
- self.closeConnection()
123
+ self.close_connection()
122
124
 
123
125
  def _packet_listen(self):
124
-
125
- close_event_set = self.closeEvent.isSet
126
-
126
+ close_event_set = self.closeEvent.is_set
127
127
  _packets = self._packets
128
- read = self.reply_endpoint.read
129
-
128
+ read = self.in_ep.read
130
129
  buffer = array("B", bytes(RECV_SIZE))
131
130
  buffer_view = memoryview(buffer)
132
-
133
131
  while True:
134
132
  try:
135
133
  if close_event_set():
136
134
  return
137
-
138
135
  try:
139
- recv_timestamp = time()
136
+ recv_timestamp = self.timestamp.value
140
137
  read_count = read(buffer, 100) # 100ms timeout
141
138
  if read_count != RECV_SIZE:
142
139
  _packets.append((buffer_view[:read_count].tobytes(), recv_timestamp))
143
140
  else:
144
141
  _packets.append((buffer.tobytes(), recv_timestamp))
145
- except BaseException:
142
+ except (USBError, USBTimeoutError):
146
143
  # print(format_exc())
147
- sleep(SHORT_SLEEP)
144
+ short_sleep()
148
145
  continue
149
-
150
- except BaseException:
146
+ except BaseException: # noqa: B036
147
+ # Note: catch-all only permitted if the intention is re-raising.
151
148
  self.status = 0 # disconnected
152
149
  break
153
150
 
154
151
  def listen(self):
155
152
  HEADER_UNPACK_FROM = self.HEADER.unpack_from
156
153
  HEADER_SIZE = self.HEADER_SIZE
157
-
158
154
  popleft = self._packets.popleft
159
-
160
- processResponse = self.processResponse
161
- close_event_set = self.closeEvent.isSet
162
-
155
+ process_response = self.process_response
156
+ close_event_set = self.closeEvent.is_set
163
157
  _packets = self._packets
164
- length, counter = None, None
165
-
166
- data = bytearray(b"")
167
-
168
- last_sleep = perf_counter()
158
+ length: Optional[int] = None
159
+ counter: int = 0
160
+ data: bytearray = bytearray(b"")
161
+ last_sleep: int = self.timestamp.value
169
162
 
170
163
  while True:
171
164
  if close_event_set():
172
165
  return
173
-
174
- count = len(_packets)
175
-
166
+ count: int = len(_packets)
176
167
  if not count:
177
- sleep(SHORT_SLEEP)
178
- last_sleep = perf_counter()
168
+ short_sleep()
169
+ last_sleep = self.timestamp.value
179
170
  continue
180
-
181
171
  for _ in range(count):
182
172
  bts, timestamp = popleft()
183
-
184
173
  data += bts
185
- current_size = len(data)
186
- current_position = 0
187
-
174
+ current_size: int = len(data)
175
+ current_position: int = 0
188
176
  while True:
189
- if perf_counter() - last_sleep >= 0.005:
190
- sleep(SHORT_SLEEP)
191
- last_sleep = perf_counter()
192
-
177
+ if self.timestamp.value - last_sleep >= FIVE_MS:
178
+ short_sleep()
179
+ last_sleep = self.timestamp.value
193
180
  if length is None:
194
181
  if current_size >= HEADER_SIZE:
195
182
  length, counter = HEADER_UNPACK_FROM(data, current_position)
@@ -201,31 +188,26 @@ class Usb(BaseTransport):
201
188
  else:
202
189
  if current_size >= length:
203
190
  response = data[current_position : current_position + length]
204
- processResponse(response, length, counter, timestamp)
205
-
191
+ process_response(response, length, counter, timestamp)
206
192
  current_size -= length
207
193
  current_position += length
208
-
209
194
  length = None
210
-
211
195
  else:
212
-
213
196
  data = data[current_position:]
214
197
  break
215
198
 
216
199
  def send(self, frame):
217
-
218
- self.pre_send_timestamp = time()
200
+ self.pre_send_timestamp = self.timestamp.value
219
201
  try:
220
- self.command_endpoint.write(frame)
221
- except BaseException:
202
+ self.out_ep.write(frame)
203
+ except (USBError, USBTimeoutError):
222
204
  # sometimes usb.core.USBError: [Errno 5] Input/Output Error is raised
223
205
  # even though the command is send and a reply is received from the device.
224
206
  # Ignore this here since a Timeout error will be raised anyway if
225
207
  # the device does not respond
226
208
  pass
227
- self.post_send_timestamp = time()
209
+ self.post_send_timestamp = self.timestamp.value
228
210
 
229
- def closeConnection(self):
211
+ def close_connection(self):
230
212
  if self.device is not None:
231
213
  usb.util.dispose_resources(self.device)
pyxcp/types.py CHANGED
@@ -1,28 +1,30 @@
1
1
  #!/usr/bin/env python
2
- # -*- coding: utf-8 -*-
3
2
  import enum
4
3
  from collections import namedtuple
5
4
 
6
5
  import construct
7
- from construct import BitsInteger
8
- from construct import BitStruct
9
- from construct import Enum
10
- from construct import Flag
11
- from construct import GreedyBytes
12
- from construct import GreedyRange
13
- from construct import If
14
- from construct import IfThenElse
15
- from construct import Int16ub
16
- from construct import Int16ul
17
- from construct import Int32ub
18
- from construct import Int32ul
19
- from construct import Int64ub
20
- from construct import Int64ul
21
- from construct import Int8ul
22
- from construct import Padding
23
- from construct import Struct
24
- from construct import Switch
25
- from construct import this
6
+ from construct import (
7
+ BitsInteger,
8
+ BitStruct,
9
+ Bytes,
10
+ Enum,
11
+ Flag,
12
+ GreedyBytes,
13
+ GreedyRange,
14
+ If,
15
+ IfThenElse,
16
+ Int8ul,
17
+ Int16ub,
18
+ Int16ul,
19
+ Int32ub,
20
+ Int32ul,
21
+ Int64ub,
22
+ Int64ul,
23
+ Padding,
24
+ Struct,
25
+ Switch,
26
+ this,
27
+ )
26
28
 
27
29
 
28
30
  if construct.version < (2, 8):
@@ -735,6 +737,11 @@ GetEventChannelInfoResponse = Struct(
735
737
  "eventChannelPriority" / Int8ul,
736
738
  )
737
739
 
740
+ GetSlaveIdResponse = Struct(
741
+ "magic" / Bytes(3),
742
+ "identifier" / Int32u,
743
+ )
744
+
738
745
  GetDaqIdResponse = Struct(
739
746
  "canIdFixed"
740
747
  / Enum(
@@ -909,6 +916,7 @@ DbgGetTriDescTblResponse = Struct("mode" / Int8ul, Padding(2), "length" / Int32u
909
916
 
910
917
  DbgLlbtResponse = Struct(Padding(1), "length" / Int16u, "data" / Int8ul[this.length])
911
918
 
919
+ # Convert to seconds.
912
920
  DAQ_TIMESTAMP_UNIT_TO_EXP = {
913
921
  "DAQ_TIMESTAMP_UNIT_1PS": -12,
914
922
  "DAQ_TIMESTAMP_UNIT_10PS": -11,
@@ -925,6 +933,39 @@ DAQ_TIMESTAMP_UNIT_TO_EXP = {
925
933
  "DAQ_TIMESTAMP_UNIT_1S": 0,
926
934
  }
927
935
 
936
+ # Convert to nano-seconds.
937
+ DAQ_TIMESTAMP_UNIT_TO_NS = {
938
+ "DAQ_TIMESTAMP_UNIT_1PS": 0.001,
939
+ "DAQ_TIMESTAMP_UNIT_10PS": 0.01,
940
+ "DAQ_TIMESTAMP_UNIT_100PS": 0.1,
941
+ "DAQ_TIMESTAMP_UNIT_1NS": 1,
942
+ "DAQ_TIMESTAMP_UNIT_10NS": 10,
943
+ "DAQ_TIMESTAMP_UNIT_100NS": 100,
944
+ "DAQ_TIMESTAMP_UNIT_1US": 1000,
945
+ "DAQ_TIMESTAMP_UNIT_10US": 10 * 1000,
946
+ "DAQ_TIMESTAMP_UNIT_100US": 100 * 1000,
947
+ "DAQ_TIMESTAMP_UNIT_1MS": 1000 * 1000,
948
+ "DAQ_TIMESTAMP_UNIT_10MS": 10 * 1000 * 1000,
949
+ "DAQ_TIMESTAMP_UNIT_100MS": 100 * 1000 * 1000,
950
+ "DAQ_TIMESTAMP_UNIT_1S": 1000 * 1000 * 1000,
951
+ }
952
+
953
+ EVENT_CHANNEL_TIME_UNIT_TO_EXP = {
954
+ "EVENT_CHANNEL_TIME_UNIT_1PS": -12,
955
+ "EVENT_CHANNEL_TIME_UNIT_10PS": -11,
956
+ "EVENT_CHANNEL_TIME_UNIT_100PS": -10,
957
+ "EVENT_CHANNEL_TIME_UNIT_1NS": -9,
958
+ "EVENT_CHANNEL_TIME_UNIT_10NS": -8,
959
+ "EVENT_CHANNEL_TIME_UNIT_100NS": -7,
960
+ "EVENT_CHANNEL_TIME_UNIT_1US": -6,
961
+ "EVENT_CHANNEL_TIME_UNIT_10US": -5,
962
+ "EVENT_CHANNEL_TIME_UNIT_100US": -4,
963
+ "EVENT_CHANNEL_TIME_UNIT_1MS": -3,
964
+ "EVENT_CHANNEL_TIME_UNIT_10MS": -2,
965
+ "EVENT_CHANNEL_TIME_UNIT_100MS": -1,
966
+ "EVENT_CHANNEL_TIME_UNIT_1S": 0,
967
+ }
968
+
928
969
 
929
970
  class XcpGetSeedMode(enum.IntEnum):
930
971
  FIRST_PART = 0
@@ -942,3 +983,11 @@ class FrameCategory(enum.IntEnum):
942
983
  SERV = 5
943
984
  DAQ = 6
944
985
  STIM = 7
986
+
987
+
988
+ class TryCommandResult(enum.IntEnum):
989
+ """ """
990
+
991
+ OK = 0
992
+ XCP_ERROR = 1
993
+ OTHER_ERROR = 2
pyxcp/utils.py CHANGED
@@ -1,12 +1,15 @@
1
1
  #!/usr/bin/env python
2
- # -*- coding: utf-8 -*-
2
+ import datetime
3
+ import functools
4
+ import operator
3
5
  import sys
4
6
  from binascii import hexlify
5
- from time import get_clock_info
6
- from time import perf_counter
7
- from time import time
7
+ from time import perf_counter, sleep
8
8
 
9
9
  import chardet
10
+ import pytz
11
+
12
+ from pyxcp.cpp_ext.cpp_ext import TimestampInfo
10
13
 
11
14
 
12
15
  def hexDump(arr):
@@ -14,7 +17,7 @@ def hexDump(arr):
14
17
  size = len(arr)
15
18
  try:
16
19
  arr = arr.hex()
17
- except BaseException:
20
+ except BaseException: # noqa: B036
18
21
  arr = hexlify(arr).decode("ascii")
19
22
  return "[{}]".format(" ".join([arr[i * 2 : (i + 1) * 2] for i in range(size)]))
20
23
  elif isinstance(arr, (list, tuple)):
@@ -22,28 +25,34 @@ def hexDump(arr):
22
25
  size = len(arr)
23
26
  try:
24
27
  arr = arr.hex()
25
- except BaseException:
28
+ except BaseException: # noqa: B036
26
29
  arr = hexlify(arr).decode("ascii")
27
30
  return "[{}]".format(" ".join([arr[i * 2 : (i + 1) * 2] for i in range(size)]))
28
31
  else:
29
- return "[{}]".format(" ".join(["{:02x}".format(x) for x in arr]))
32
+ return "[{}]".format(" ".join([f"{x:02x}" for x in arr]))
33
+
34
+
35
+ def seconds_to_nanoseconds(value: float) -> int:
36
+ return int(value * 1_000_000_000)
30
37
 
31
38
 
32
39
  def slicer(iterable, sliceLength, converter=None):
33
40
  if converter is None:
34
41
  converter = type(iterable)
35
42
  length = len(iterable)
36
- return [converter((iterable[item : item + sliceLength])) for item in range(0, length, sliceLength)]
43
+ return [converter(iterable[item : item + sliceLength]) for item in range(0, length, sliceLength)]
44
+
45
+
46
+ def functools_reduce_iconcat(a):
47
+ return functools.reduce(operator.iconcat, a, [])
37
48
 
38
49
 
39
50
  def flatten(*args):
40
- result = []
41
- for arg in list(args):
42
- if hasattr(arg, "__iter__"):
43
- result.extend(flatten(*arg))
44
- else:
45
- result.append(arg)
46
- return result
51
+ """Flatten a list of lists into a single list.
52
+
53
+ s. https://stackoverflow.com/questions/952914/how-do-i-make-a-flat-list-out-of-a-list-of-lists
54
+ """
55
+ return functools.reduce(operator.iconcat, args, [])
47
56
 
48
57
 
49
58
  def getPythonVersion():
@@ -60,7 +69,10 @@ def decode_bytes(byte_str: bytes) -> str:
60
69
 
61
70
 
62
71
  PYTHON_VERSION = getPythonVersion()
63
- SHORT_SLEEP = 0.0005
72
+
73
+
74
+ def short_sleep():
75
+ sleep(0.0005)
64
76
 
65
77
 
66
78
  def delay(amount: float):
@@ -69,3 +81,22 @@ def delay(amount: float):
69
81
  start = perf_counter()
70
82
  while perf_counter() < start + amount:
71
83
  pass
84
+
85
+
86
+ class CurrentDatetime(TimestampInfo):
87
+
88
+ def __init__(self, timestamp_ns: int):
89
+ TimestampInfo.__init__(self, timestamp_ns)
90
+ timezone = pytz.timezone(self.timezone)
91
+ dt = datetime.datetime.fromtimestamp(timestamp_ns / 1_000_000_000.0)
92
+ self.utc_offset = int(timezone.utcoffset(dt).total_seconds() / 60)
93
+ self.dst_offset = int(timezone.dst(dt).total_seconds() / 60)
94
+
95
+ def __str__(self):
96
+ return f"""CurrentDatetime(
97
+ datetime="{datetime.datetime.fromtimestamp(self.timestamp_ns / 1_000_000_000.0)!s}",
98
+ timezone="{self.timezone}",
99
+ timestamp_ns={self.timestamp_ns},
100
+ utc_offset={self.utc_offset},
101
+ dst_offset={self.dst_offset}
102
+ )"""
pyxcp/vector/map.py CHANGED
@@ -1,6 +1,4 @@
1
1
  #!/usr/bin/env python
2
- # -*- coding: utf-8 -*-
3
- from enum import IntEnum
4
2
 
5
3
  MAP_NAMES = {
6
4
  1: "BorlandC 16 Bit",
@@ -81,4 +79,4 @@ MAP name
81
79
 
82
80
 
83
81
  def mapfile_name(name, counter, fmt):
84
- return "{:2d}{:d}{:s}.map".format(fmt, counter, name)
82
+ return f"{fmt:2d}{counter:d}{name:s}.map"
@@ -1,41 +1,43 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.3
2
2
  Name: pyxcp
3
- Version: 0.21.9
3
+ Version: 0.22.23
4
4
  Summary: Universal Calibration Protocol for Python
5
+ License: LGPLv3
5
6
  Keywords: automotive,ecu,xcp,asam,autosar
6
7
  Author: Christoph Schueler
7
- Author-email: cpu12.gems@googlemail.com
8
- Requires-Python: >=3.7
8
+ Author-email: cpu.gems@googlemail.com
9
+ Requires-Python: >=3.8.1,<4.0.0
9
10
  Classifier: Development Status :: 5 - Production/Stable
10
11
  Classifier: Intended Audience :: Developers
11
12
  Classifier: License :: OSI Approved :: GNU Lesser General Public License v3 or later (LGPLv3+)
13
+ Classifier: License :: Other/Proprietary License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.9
12
16
  Classifier: Programming Language :: Python :: 3.10
13
17
  Classifier: Programming Language :: Python :: 3.11
14
18
  Classifier: Programming Language :: Python :: 3.12
15
- Classifier: Programming Language :: Python :: 3.7
19
+ Classifier: Programming Language :: Python :: 3.13
16
20
  Classifier: Programming Language :: Python :: 3.8
17
- Classifier: Programming Language :: Python :: 3.9
18
21
  Classifier: Topic :: Scientific/Engineering
19
22
  Classifier: Topic :: Software Development
20
- Requires-Dist: Mako<2.0.0,>=1.1.6
21
- Requires-Dist: chardet>=5.2.0
22
- Requires-Dist: construct<3.0.0,>=2.10.67
23
- Requires-Dist: pyserial<4.0,>=3.5
24
- Requires-Dist: python-can>=4.0.0
25
- Requires-Dist: pyusb<2.0.0,>=1.2.1
26
- Requires-Dist: setuptools-cpp<1.0.0,>=0.1.0
27
- Requires-Dist: toml<1.0.0,>=0.10.2
28
- Requires-Dist: traitlets>=5.9.0
29
- Requires-Dist: uptime>=3.0.1
30
- Provides-Extra: doc
31
- Requires-Dist: sphinx; extra == "doc"
32
- Requires-Dist: sphinxcontrib-napoleon; extra == "doc"
33
- Project-URL: homepage, https://github.com/christoph2/pyxcp
23
+ Requires-Dist: bandit (>=1.7.8,<2.0.0)
24
+ Requires-Dist: chardet (>=5.2.0,<6.0.0)
25
+ Requires-Dist: construct (>=2.10.68,<3.0.0)
26
+ Requires-Dist: line-profiler-pycharm (>=1.1.0,<2.0.0)
27
+ Requires-Dist: mako (>=1.2.4,<2.0.0)
28
+ Requires-Dist: pyserial (>=3.5,<4.0)
29
+ Requires-Dist: python-can (>=4.2.2,<5.0.0)
30
+ Requires-Dist: pytz (>=2024.1,<2025.0)
31
+ Requires-Dist: pyusb (>=1.2.1,<2.0.0)
32
+ Requires-Dist: rich (>=13.6.0,<14.0.0)
33
+ Requires-Dist: toml (>=0.10.2,<0.11.0)
34
+ Requires-Dist: tomlkit (>=0.12.5,<0.13.0)
35
+ Requires-Dist: traitlets (<=5.11.2)
36
+ Requires-Dist: uptime (>=3.0.1,<4.0.0)
37
+ Project-URL: Homepage, https://github.com/christoph2/pyxcp
34
38
  Description-Content-Type: text/markdown
35
39
 
36
-
37
- pyXCP
38
- =====
40
+ # pyXCP
39
41
 
40
42
  [![Codacy Badge](https://api.codacy.com/project/badge/Grade/85f774708b2542d98d02df55c743d24a)](https://app.codacy.com/app/christoph2/pyxcp?utm_source=github.com&utm_medium=referral&utm_content=christoph2/pyxcp&utm_campaign=Badge_Grade_Settings)
41
43
  [![Maintainability](https://api.codeclimate.com/v1/badges/4c639f3695f2725e392a/maintainability)](https://codeclimate.com/github/christoph2/pyxcp/maintainability)
@@ -59,17 +61,20 @@ XCP also replaces the older CCP (CAN Calibration Protocol).
59
61
  pyXCP is hosted on Github, get the latest release: [https://github.com/christoph2/pyxcp](https://github.com/christoph2/pyxcp)
60
62
 
61
63
  You can install pyxcp from source:
64
+
62
65
  ```
63
66
  pip install -r requirements.txt
64
67
  python setup.py install
65
68
  ```
66
69
 
67
70
  Alternatively, you can install pyxcp from source with pip:
71
+
68
72
  ```
69
73
  pip install git+https://github.com/christoph2/pyxcp.git
70
74
  ```
71
75
 
72
76
  Alternatively, get pyxcp from [PyPI](https://pypi.org/project/pyxcp/):
77
+
73
78
  ```
74
79
  pip install pyxcp
75
80
  ```