pyxcp 0.21.10__cp312-cp312-win32.whl → 0.21.11__cp312-cp312-win32.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.
pyxcp/__init__.py CHANGED
@@ -25,4 +25,4 @@ from .transport import SxI
25
25
  from .transport import Usb
26
26
 
27
27
  # if you update this manually, do not forget to update .bumpversion.cfg and pyproject.toml
28
- __version__ = "0.21.10"
28
+ __version__ = "0.21.11"
pyxcp/cmdline.py CHANGED
@@ -5,12 +5,14 @@ Parse (transport-layer specific) command line parameters
5
5
  and create a XCP master instance.
6
6
  """
7
7
  import argparse
8
+ import logging
8
9
 
9
10
  from pyxcp.config import readConfiguration
10
11
  from pyxcp.master import Master
11
12
  from pyxcp.transport.can import registered_drivers
12
13
  from pyxcp.transport.can import try_to_install_system_supplied_drivers
13
14
 
15
+
14
16
  try_to_install_system_supplied_drivers()
15
17
 
16
18
  CAN_DRIVERS = registered_drivers()
@@ -51,6 +53,9 @@ class ArgumentParser:
51
53
 
52
54
  def run(self, policy=None):
53
55
  """"""
56
+ # Create a default logging context if run as command line
57
+ logging.basicConfig()
58
+
54
59
  self._args = self.parser.parse_args()
55
60
  args = self.args
56
61
  if args.conf is None:
pyxcp/logger.py CHANGED
@@ -2,9 +2,6 @@
2
2
  # -*- coding: utf-8 -*-
3
3
  import logging
4
4
 
5
- logging.basicConfig()
6
-
7
-
8
5
  class Logger(object):
9
6
 
10
7
  LOGGER_BASE_NAME = "pyxcp"
pyxcp/master/master.py CHANGED
@@ -8,17 +8,17 @@
8
8
  .. [1] XCP Specification, Part 2 - Protocol Layer Specification
9
9
  """
10
10
  import functools
11
- import logging
12
11
  import struct
13
12
  import traceback
14
13
  import warnings
15
14
  from time import sleep
15
+ from typing import Any
16
16
  from typing import Callable
17
17
  from typing import Collection
18
18
  from typing import Dict
19
19
  from typing import List
20
20
  from typing import Optional
21
- from typing import Union
21
+ from typing import Tuple
22
22
 
23
23
  from pyxcp import checksum
24
24
  from pyxcp import types
@@ -33,6 +33,7 @@ from pyxcp.constants import makeWordPacker
33
33
  from pyxcp.constants import makeWordUnpacker
34
34
  from pyxcp.constants import PackerType
35
35
  from pyxcp.constants import UnpackerType
36
+ from pyxcp.logger import Logger
36
37
  from pyxcp.master.errorhandler import disable_error_handling
37
38
  from pyxcp.master.errorhandler import wrapped
38
39
  from pyxcp.transport.base import createTransport
@@ -92,8 +93,7 @@ class Master:
92
93
  self.ctr = 0
93
94
  self.succeeded = True
94
95
  self.config = Configuration(self.PARAMETER_MAP or {}, config or {})
95
- self.logger = logging.getLogger("pyXCP")
96
- self.logger.setLevel(self.config.get("LOGLEVEL"))
96
+ self.logger = Logger("master.Master", level=self.config.get("LOGLEVEL"))
97
97
  disable_error_handling(self.config.get("DISABLE_ERROR_HANDLING"))
98
98
 
99
99
  self.transport = createTransport(transportName, config, policy)
@@ -124,6 +124,7 @@ class Master:
124
124
  self.disconnect_response_optional = self.config.get("DISCONNECT_RESPONSE_OPTIONAL")
125
125
  self.slaveProperties = SlaveProperties()
126
126
  self.slaveProperties.pgmProcessor = SlaveProperties()
127
+ self.slaveProperties.transport_layer = self.transport_name.upper()
127
128
 
128
129
  def __enter__(self):
129
130
  """Context manager entry part."""
@@ -1795,7 +1796,7 @@ class Master:
1795
1796
  result = self.getSeed(types.XcpGetSeedMode.REMAINING, resource_value)
1796
1797
  seed.extend(list(result.seed))
1797
1798
 
1798
- seed = seed[: length] # maybe there are some padding bytes
1799
+ seed = seed[:length] # maybe there are some padding bytes
1799
1800
 
1800
1801
  result, key = getKey(
1801
1802
  self.logger,
@@ -1810,7 +1811,7 @@ class Master:
1810
1811
  offset = 0
1811
1812
  while offset < total_length:
1812
1813
  data = key[offset : offset + MAX_PAYLOAD]
1813
- self.unlock(total_length-offset, data)
1814
+ self.unlock(total_length - offset, data)
1814
1815
  offset += len(data)
1815
1816
  else:
1816
1817
  raise SeedNKeyError("SeedAndKey DLL returned: {}".format(SeedNKeyResult(result).name))
@@ -1903,6 +1904,47 @@ class Master:
1903
1904
  result[name] = response
1904
1905
  return result
1905
1906
 
1907
+ def try_command(self, cmd: Callable, *args, **kws) -> Tuple[types.TryCommandResult, Any]:
1908
+ """Call master functions and handle XCP errors more gracefuly.
1909
+
1910
+ Parameter
1911
+ ---------
1912
+ cmd: Callable
1913
+ args: list
1914
+ variable length arguments to `cmd`.
1915
+ kws: dict
1916
+ keyword arguments to `cmd`.
1917
+
1918
+ `extra_msg`: str
1919
+ Additional info to log message (not passed to `cmd`).
1920
+
1921
+ Returns
1922
+ -------
1923
+
1924
+ Note
1925
+ ----
1926
+ Mainly used for plug-and-play applications, e.g. `id_scanner` may confronted with `ERR_OUT_OF_RANGE` errors, which
1927
+ is normal for this kind of applications -- or to test for optional commands.
1928
+ Use carefuly not to hide serious error causes.
1929
+ """
1930
+ try:
1931
+ extra_msg: Optional[str] = kws.get("extra_msg")
1932
+ if extra_msg:
1933
+ kws.pop("extra_msg")
1934
+ res = cmd(*args, **kws)
1935
+ except SystemExit as e:
1936
+ if e.error_code == types.XcpError.ERR_CMD_UNKNOWN:
1937
+ # This is a rather common use-case, so let the user know that there is some functionality missing.
1938
+ if extra_msg:
1939
+ self.logger.warning(f"Optional command {cmd.__name__!r} not implemented -- {extra_msg!r}")
1940
+ else:
1941
+ self.logger.warning(f"Optional command {cmd.__name__!r} not implemented.")
1942
+ return (types.TryCommandResult.XCP_ERROR, e)
1943
+ except Exception as e:
1944
+ return (types.TryCommandResult.OTHER_ERROR, e)
1945
+ else:
1946
+ return (types.TryCommandResult.OK, res)
1947
+
1906
1948
 
1907
1949
  def ticks_to_seconds(ticks, resolution):
1908
1950
  """Convert DAQ timestamp/tick value to seconds.
pyxcp/scripts/xcp_info.py CHANGED
@@ -1,74 +1,89 @@
1
1
  #!/usr/bin/env python
2
- # -*- coding: utf-8 -*-
3
- """Very basic hello-world example.
2
+ """XCP info/exploration tool.
4
3
  """
5
4
  from pprint import pprint
6
5
 
7
6
  from pyxcp.cmdline import ArgumentParser
7
+ from pyxcp.types import TryCommandResult
8
8
 
9
- daq_info = False
10
9
 
10
+ ap = ArgumentParser(description="XCP info/exploration tool.")
11
11
 
12
- def callout(master, args):
13
- global daq_info
14
- if args.daq_info:
15
- daq_info = True
16
-
17
-
18
- ap = ArgumentParser(description="pyXCP hello world.", callout=callout)
19
- ap.parser.add_argument(
20
- "-d",
21
- "--daq-info",
22
- dest="daq_info",
23
- help="Display DAQ-info",
24
- default=False,
25
- action="store_true",
26
- )
27
12
  with ap.run() as x:
28
13
  x.connect()
29
14
  if x.slaveProperties.optionalCommMode:
30
- x.getCommModeInfo()
31
- identifier = x.identifier(0x01)
15
+ x.try_command(x.getCommModeInfo, extra_msg="availability signaled by CONNECT, this may be a slave configuration error.")
32
16
  print("\nSlave Properties:")
33
17
  print("=================")
34
- print(f"ID: '{identifier}'")
35
18
  pprint(x.slaveProperties)
19
+
20
+ # result = x.id_scanner()
21
+ # print("\n")
22
+ # print("Implemented IDs:")
23
+ # print("================")
24
+ # for key, value in result.items():
25
+ # print(f"{key}: {value}", end="\n\n")
36
26
  cps = x.getCurrentProtectionStatus()
37
27
  print("\nProtection Status")
38
28
  print("=================")
39
29
  for k, v in cps.items():
40
30
  print(f" {k:6s}: {v}")
41
- if daq_info:
42
- dqp = x.getDaqProcessorInfo()
43
- print("\nDAQ Processor Info:")
44
- print("===================")
45
- print(dqp)
46
- print("\nDAQ Events:")
47
- print("===========")
48
- for idx in range(dqp.maxEventChannel):
49
- evt = x.getDaqEventInfo(idx)
50
- length = evt.eventChannelNameLength
51
- name = x.pull(length).decode("utf-8")
52
- dq = "DAQ" if evt.daqEventProperties.daq else ""
53
- st = "STIM" if evt.daqEventProperties.stim else ""
54
- dq_st = dq + " " + st
55
- print(f' [{idx:04}] "{name:s}"')
56
- print(f" dir: {dq_st}")
57
- print(f" packed: {evt.daqEventProperties.packed}")
58
- PFX_CONS = "CONSISTENCY_"
59
- print(f" consistency: {evt.daqEventProperties.consistency.strip(PFX_CONS)}")
60
- print(f" max. DAQ lists: {evt.maxDaqList}")
61
- PFX_TU = "EVENT_CHANNEL_TIME_UNIT_"
62
- print(f" unit: {evt.eventChannelTimeUnit.strip(PFX_TU)}")
63
- print(f" cycle: {evt.eventChannelTimeCycle or 'SPORADIC'}")
64
- print(f" priority {evt.eventChannelPriority}")
31
+ x.cond_unlock()
32
+ print("\nDAQ Info:")
33
+ print("=========")
34
+ daq_info = x.getDaqInfo()
35
+ pprint(daq_info)
65
36
 
66
- dqr = x.getDaqResolutionInfo()
67
- print("\nDAQ Resolution Info:")
68
- print("====================")
69
- print(dqr)
70
- for idx in range(dqp.maxDaq):
71
- print(f"\nDAQ List Info #{idx}")
72
- print("=================")
73
- print(f"{x.getDaqListInfo(idx)}")
37
+ daq_pro = daq_info["processor"]
38
+ daq_properties = daq_pro["properties"]
39
+ if x.slaveProperties.transport_layer == "CAN":
40
+ print("")
41
+ if daq_properties["pidOffSupported"]:
42
+ print("*** pidOffSupported -- i.e. one CAN-ID per DAQ-list.")
43
+ else:
44
+ print("*** NO support for PID_OFF")
45
+ num_predefined = daq_pro["minDaq"]
46
+ print("\nPredefined DAQ-Lists")
47
+ print("====================")
48
+ if num_predefined > 0:
49
+ print(f"There are {num_predefined} predefined DAQ-lists")
50
+ for idx in range(num_predefined):
51
+ print(f"DAQ-List #{idx}\n____________\n")
52
+ status, dm = x.try_command(x.getDaqListMode, idx)
53
+ if status == TryCommandResult.OK:
54
+ print(dm)
55
+ status, di = x.try_command(x.getDaqListInfo, idx)
56
+ if status == TryCommandResult.OK:
57
+ print(di)
58
+ else:
59
+ print("*** NO Predefined DAQ-Lists")
60
+ print("\nPAG Info:")
61
+ print("=========")
62
+ if x.slaveProperties.supportsCalpag:
63
+ status, pag = x.try_command(x.getPagProcessorInfo)
64
+ if status == TryCommandResult.OK:
65
+ print(pag)
66
+ # for idx in range(pag.maxSegments):
67
+ # x.getSegmentInfo(0x01, idx, 0, 0)
68
+ else:
69
+ print("*** PAGING IS NOT SUPPORTED.")
70
+
71
+ print("\nPGM Info:")
72
+ print("=========")
73
+ if x.slaveProperties.supportsPgm:
74
+ status, pgm = x.try_command(x.getPgmProcessorInfo)
75
+ if status == TryCommandResult.OK:
76
+ print(pgm)
77
+ else:
78
+ print("*** FLASH PROGRAMMING IS NOT SUPPORTED.")
79
+
80
+ if x.slaveProperties.transport_layer == "CAN":
81
+ # print("OK, CAN!!!")
82
+ for idx in range(num_predefined):
83
+ status, daq_id = x.try_command(x.getDaqId, idx)
84
+ if status != TryCommandResult.OK:
85
+ break
86
+ print(f"DAQ-ID #{idx}", daq_id)
74
87
  x.disconnect()
88
+
89
+ print("\nDone.")
pyxcp/types.py CHANGED
@@ -942,3 +942,11 @@ class FrameCategory(enum.IntEnum):
942
942
  SERV = 5
943
943
  DAQ = 6
944
944
  STIM = 7
945
+
946
+
947
+ class TryCommandResult(enum.IntEnum):
948
+ """ """
949
+
950
+ OK = 0
951
+ XCP_ERROR = 1
952
+ OTHER_ERROR = 2
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pyxcp
3
- Version: 0.21.10
3
+ Version: 0.21.11
4
4
  Summary: Universal Calibration Protocol for Python
5
5
  Keywords: automotive,ecu,xcp,asam,autosar
6
6
  Author: Christoph Schueler
@@ -1,4 +1,4 @@
1
- pyxcp/__init__.py,sha256=YidEMFV2A-qJiIqpKabLnA_QQP2V2gm0W4LIkFEj49s,747
1
+ pyxcp/__init__.py,sha256=9gfgRYGNG-J_wgs9znuex29MD65S7FZgiY1xlm9Rfvc,747
2
2
  pyxcp/aml/EtasCANMonitoring.a2l,sha256=hEHpb3GpuFDvU6GpAiuV028mu7MUXtfE7wslPA0GlZg,1640
3
3
  pyxcp/aml/EtasCANMonitoring.aml,sha256=xl0DdyeiIaLW0mmmJNAyJS0CQdOLSxt9dxfgrdSlU8Y,2405
4
4
  pyxcp/aml/ifdata_CAN.a2l,sha256=mQFDM6y9qyxUORYR1L0m8fMJ7S1oGheuD8ouEeYxEnI,614
@@ -17,7 +17,7 @@ pyxcp/asam/types.py,sha256=3BhMH4jH-MNYNpN7W92fW1h4xONXG2tMsHMVzlHAzN0,2492
17
17
  pyxcp/asamkeydll.c,sha256=9G10yK-8NbF6DFvXZuCgdwHfmO8Hk54J_08RMLdDL3o,2979
18
18
  pyxcp/asamkeydll.sh,sha256=DC2NKUMwvi39OQgJ6514Chr4wc1LYbTmQHmMq9jAHHs,59
19
19
  pyxcp/checksum.py,sha256=FzUe4Aa7dgJhpL7P5SbxKke8o-ogsqTFWg8AxVNYba8,11560
20
- pyxcp/cmdline.py,sha256=fdp2aL80UIkAhiq3gkapTiMFUz3-4-UJGAZFM87tklw,2187
20
+ pyxcp/cmdline.py,sha256=Zd6RlCvmXMhVhtAk0gh_sfhg-extva97EvIK2TFHXZw,2305
21
21
  pyxcp/config.py,sha256=G9d14Od9Ra9lmnWRqEfLpRszXivTPHD4kIG_a5tos1U,1480
22
22
  pyxcp/constants.py,sha256=sg3Rg0U_6VHM-ybCcuh0KG1NW4qmE1IihlnHZlLxcEY,1306
23
23
  pyxcp/cxx/asynchiofactory.hpp,sha256=ivnWJ_Qyzh20K7aj0EbVsrgLUKoJ8YmO1mYXX4h1rcg,434
@@ -69,10 +69,10 @@ pyxcp/examples/xcp_unlock.py,sha256=Hn83vubRbaZhJPzlMoH_u-OH7b46zVx2COriqZDzbj4,
69
69
  pyxcp/examples/xcp_user_supplied_driver.py,sha256=psU9rwGRcGI1IuLVb5sw2LVJc2QHSjjeEgbKwSU2R5Y,1101
70
70
  pyxcp/examples/xcphello.py,sha256=vRpY7uMEdV8CbIFmCjV_V56dRdbF2qH-tR5BHkaCu4g,2591
71
71
  pyxcp/examples/xcphello_recorder.py,sha256=RbnuMzk67zszp3t0PAEcpXzuZELHYq-3VovZlPgs_IQ,3407
72
- pyxcp/logger.py,sha256=-g6VIWsu7uyPilZHz41qWUTha1B1a0ZTGJwckMxaTjI,1991
72
+ pyxcp/logger.py,sha256=5UIkx0vfztA9s5LSAR2nox6rDcxzkRxS_4Zq0_Yx_p4,1964
73
73
  pyxcp/master/__init__.py,sha256=sZOjpI4cZS_kuTXYGQ3R6FL96w0bNbWTtNzSZAtngUw,329
74
74
  pyxcp/master/errorhandler.py,sha256=eCO3RWqfv5CTV84HBw6i26NSmU0L6LGZzq5EsmgSu_s,13622
75
- pyxcp/master/master.py,sha256=AHuhU1uF3UnY_Trx-COakdMpScjpSx_u8LshVHt4xrE,72583
75
+ pyxcp/master/master.py,sha256=rKXGhRfgomD3P34q16c2mQ-BoOU2t0gFmBRPVeQQZVA,74353
76
76
  pyxcp/recorder/__init__.py,sha256=hdIkTKrGePj8-7A5UpvNIaZnY44ayh4fP-0gfzm14a8,2260
77
77
  pyxcp/recorder/build_clang.cmd,sha256=JvFngSnb28XcBGXxC6MGrcOCGYfahOIvHpgRpqbA6HQ,175
78
78
  pyxcp/recorder/build_clang.sh,sha256=zmU3nZxaNH1pxGWMyQ-S541TuVqxS00p3iPR9NUP4Ec,181
@@ -95,7 +95,7 @@ pyxcp/scripts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
95
95
  pyxcp/scripts/pyxcp_probe_can_drivers.py,sha256=kh_Nnap3xo8bmPtY_rP6cf1GMXBGPE81lGzpO0uLISo,619
96
96
  pyxcp/scripts/xcp_fetch_a2l.py,sha256=EvFnmJoXyonKvMd9a8ydWCUUeybCDXaiuN0MmyJbXyw,932
97
97
  pyxcp/scripts/xcp_id_scanner.py,sha256=E_IlOC_6D6UFZcS0jcSJ1fYfRXPjD9OvCveanAy9IuE,495
98
- pyxcp/scripts/xcp_info.py,sha256=zktv7shrhKBNd3PuRjPGWe6m_wLnuLkRaygCRxqcnRU,2553
98
+ pyxcp/scripts/xcp_info.py,sha256=3vnWfhiTaymHBI3qwATsjZgg8yXBn-OmkjHImjte420,3045
99
99
  pyxcp/tests/test_asam_types.py,sha256=XfEUZHV0h2PBzedF86GAQOILgH_CyUExZeIZog1r2ZE,587
100
100
  pyxcp/tests/test_can.py,sha256=svkmwHlnJB0VWoFkrV3qE8-v9UvajJ-Syy7AJq-epbU,5133
101
101
  pyxcp/tests/test_checksum.py,sha256=7Z3V_cfWuyL43Aq4ivkU3Df7UcD1ACxdVqXt7FOe01k,1806
@@ -135,13 +135,13 @@ pyxcp/transport/cxx_ext/tests/test_timestamp.cpp,sha256=6V_rZJR9rtQgIO-CFdFIWSx7
135
135
  pyxcp/transport/eth.py,sha256=PoCafj5BF1Ir0SLEvscZivXTEihGJPo7EAgYq5WHvok,7923
136
136
  pyxcp/transport/sxi.py,sha256=VVqiXD800GociBryMtXma9l2QspQpwECE1eNy4Cq4us,2583
137
137
  pyxcp/transport/usb_transport.py,sha256=hK4FTl1DM7xDoNjcBXoMeb-YZfk2SP3BihlbJM6mL2w,7888
138
- pyxcp/types.py,sha256=uV-f4XlG1IjqeIT8PGUnb5CwEBcX10JQ7aDt3gWJrwk,24950
138
+ pyxcp/types.py,sha256=TVXsAs-Js1pp4JJME2pDojRNIq96wfG9tJ357RVBn7w,25060
139
139
  pyxcp/utils.py,sha256=b7zNSMLOYhgKBHXQSDbSfGYzhgXlje_xsJK0LztdNTk,1960
140
140
  pyxcp/vector/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
141
141
  pyxcp/vector/map.py,sha256=5FPdKgvP5CKuas2R5PIsxUvip-bVp7kwrEcQAZjZcAw,2369
142
- rekorder.cp312-win32.pyd,sha256=K4Ldj2rjt3ydg5NG4NCcbZLrGTzLhodnU8Abf_myjns,141312
143
- pyxcp-0.21.10.dist-info/entry_points.txt,sha256=wL4Cgx0wIAbuEr93nPewLCL-6DCSunxxTkui-bibme8,219
144
- pyxcp-0.21.10.dist-info/WHEEL,sha256=4b0mtI0-qo1BufjhFYXXEqC6LZSbmC3VzWKotlxOTkM,93
145
- pyxcp-0.21.10.dist-info/METADATA,sha256=uK6eR-eJ54LMAbV0K5m0LVgj_jt6xAm3VQotEdsbG8c,3862
146
- pyxcp-0.21.10.dist-info/licenses/LICENSE,sha256=fTqV5eBpeAZO0_jit8j4Ref9ikBSlHJ8xwj5TLg7gFk,7817
147
- pyxcp-0.21.10.dist-info/RECORD,,
142
+ rekorder.cp312-win32.pyd,sha256=Rqrrc4WGkLdCjzOBAvCtvJATU7mY8ID9A93XYq0eVQY,141312
143
+ pyxcp-0.21.11.dist-info/entry_points.txt,sha256=wL4Cgx0wIAbuEr93nPewLCL-6DCSunxxTkui-bibme8,219
144
+ pyxcp-0.21.11.dist-info/WHEEL,sha256=4b0mtI0-qo1BufjhFYXXEqC6LZSbmC3VzWKotlxOTkM,93
145
+ pyxcp-0.21.11.dist-info/METADATA,sha256=GK1NxADBF_DgZU5tvGlwV6fW6LlbTiNn4g_89RjxONc,3862
146
+ pyxcp-0.21.11.dist-info/licenses/LICENSE,sha256=fTqV5eBpeAZO0_jit8j4Ref9ikBSlHJ8xwj5TLg7gFk,7817
147
+ pyxcp-0.21.11.dist-info/RECORD,,
rekorder.cp312-win32.pyd CHANGED
Binary file