pyxcp 0.21.10__cp311-cp311-macosx_10_9_x86_64.whl → 0.21.11__cp311-cp311-macosx_10_9_x86_64.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.

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,19 +1,19 @@
1
1
  rekorder.cpython-311-darwin.so,sha256=a3gjMYuwCetqmLwvGrQXEYbhxZxY-jVt-7FBm8u7DGQ,319360
2
- pyxcp-0.21.10.dist-info/RECORD,,
3
- pyxcp-0.21.10.dist-info/WHEEL,sha256=1LO1kSN6mor21iujzR1Z_Aa0UwxX6-6CmfsIBq_uQlM,106
4
- pyxcp-0.21.10.dist-info/entry_points.txt,sha256=wL4Cgx0wIAbuEr93nPewLCL-6DCSunxxTkui-bibme8,219
5
- pyxcp-0.21.10.dist-info/METADATA,sha256=uK6eR-eJ54LMAbV0K5m0LVgj_jt6xAm3VQotEdsbG8c,3862
6
- pyxcp-0.21.10.dist-info/licenses/LICENSE,sha256=46mU2C5kSwOnkqkw9XQAJlhBL2JAf1_uCD8lVcXyMRg,7652
2
+ pyxcp-0.21.11.dist-info/RECORD,,
3
+ pyxcp-0.21.11.dist-info/WHEEL,sha256=1LO1kSN6mor21iujzR1Z_Aa0UwxX6-6CmfsIBq_uQlM,106
4
+ pyxcp-0.21.11.dist-info/entry_points.txt,sha256=wL4Cgx0wIAbuEr93nPewLCL-6DCSunxxTkui-bibme8,219
5
+ pyxcp-0.21.11.dist-info/METADATA,sha256=GK1NxADBF_DgZU5tvGlwV6fW6LlbTiNn4g_89RjxONc,3862
6
+ pyxcp-0.21.11.dist-info/licenses/LICENSE,sha256=46mU2C5kSwOnkqkw9XQAJlhBL2JAf1_uCD8lVcXyMRg,7652
7
7
  pyxcp/dllif.py,sha256=o7t_M_n6XwE63ng97DV8t8BJkGmFHtj7Esdhi7qH4DQ,3023
8
8
  pyxcp/checksum.py,sha256=nsEosSKtU1b8L14sm9HyxvUNUMc07hnCR6oK_bH6-Ew,10837
9
9
  pyxcp/asamkeydll.sh,sha256=iema12sub6qNE0xAuzwGtx0FmkdaaOKoXalhrtWVaa8,57
10
10
  pyxcp/config.py,sha256=dJ5WfX4Stlz2bvUA-mO-ez6jruFi27C9r7TDj1Vkc4g,1423
11
11
  pyxcp/asamkeydll.c,sha256=PnfD6UbMWz3cszGpJDHBrSPizjlg8RrV_nrCqC9xPOw,2862
12
12
  pyxcp/constants.py,sha256=Ifs1cxpRoctEU0BKAo5yDXqBtTWpTNIKzcV8YbrgNCA,1258
13
- pyxcp/cmdline.py,sha256=IvI946DR7CoCDutAaIrFTdTlCBSQ-ib_qlxBLWIK4dc,2117
14
- pyxcp/__init__.py,sha256=lQ5Ezf6-a5DuagwXCgG3ewVEz-3i8DH1jhRNlxlTEgM,719
15
- pyxcp/types.py,sha256=fwAH5XAOPAiHo4EW2JgR9P1GdNTTPGzDrPLGeNeWhjI,24006
16
- pyxcp/logger.py,sha256=Zl9TolTcbvUjpRs8Chx8rK8TGHiHAq9-TC3fWQRnxgY,1924
13
+ pyxcp/cmdline.py,sha256=XgxKYidBwhLHrliT-MuYbiIzSKYaPI755DBRIJgkGv4,2230
14
+ pyxcp/__init__.py,sha256=THlUNKH747uy5DigkJkNSetYXMNCrJIy9n0g7MkWlSk,719
15
+ pyxcp/types.py,sha256=Ac5tTo5j6-Tv3y17BXQFEqk8rSyjaGQj8ENfaFZ8OcA,24108
16
+ pyxcp/logger.py,sha256=oSqczYMO9G38D0ZglOGJuZ-HbCaISDciX7M6Ip3aT8Q,1900
17
17
  pyxcp/timing.py,sha256=dK89nGWV1sUVCd5FVkNCTDjoyuP8qK4Ggo9GgFGe_s0,1670
18
18
  pyxcp/utils.py,sha256=qN2b8fYzLzFhHbG449fuB9wx_BMPXFFFvoKgtrdCMeY,1889
19
19
  pyxcp/errormatrix.py,sha256=A90h09mD_MKoMa7hMELlyGrMUZyQpO9ihbKrlJOoMvg,44479
@@ -100,7 +100,7 @@ pyxcp/aml/XCPonUSB.aml,sha256=1xNuM0fsDQi712hkzhBPveJcx1m318tC28bZEfnKpXU,4846
100
100
  pyxcp/aml/ifdata_SxI.a2l,sha256=ElFw9n43E4wSNVVvOiuq9TDv_zsAwSVSh4SnW8P7pCo,304
101
101
  pyxcp/aml/XCPonFlx.aml,sha256=z58FMu6ZF4hVun8WBCuxvDrq6FZ_gj3tZM15G7E8Uvw,4647
102
102
  pyxcp/master/__init__.py,sha256=14ZrFHp9wc_lizE47yl0Yr-NZ3PT2PEFPWWAaXvna34,319
103
- pyxcp/master/master.py,sha256=MK1_NgSG6Zb3ZLzNiZhYI7N85IXhAGOIERHX4zCzPwE,70635
103
+ pyxcp/master/master.py,sha256=0-9oOgYRWrTAWRbrfpuJoZZ0tqKq1KfyirrEkcvk1AA,72363
104
104
  pyxcp/master/errorhandler.py,sha256=rVtCpvkxWLZtAYpjvs3SygQuLGp4lyIIxzFcYjAhsCo,13219
105
105
  pyxcp/examples/xcp_read_benchmark.py,sha256=8nlFK7ZssAuwp2nyPdI8s5MDVObP4PKRZJ--hRouNDU,839
106
106
  pyxcp/examples/conf_eth.toml,sha256=zONw4kMsNH-uQYd8V3AlNH21sAlJ9wY7RY0DuSGJiiA,109
@@ -123,7 +123,7 @@ pyxcp/examples/xcp_policy.py,sha256=iQ1Pz5UzJHz5jEHaEIG49jSmkvW5BJVW3PiUXbHlLmM,
123
123
  pyxcp/scripts/xcp_id_scanner.py,sha256=-Z7l7uGosaJC1Po4Odml92fX3GAQjPJRW3ASFt81J-Q,472
124
124
  pyxcp/scripts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
125
125
  pyxcp/scripts/xcp_fetch_a2l.py,sha256=rOhT0K5ERsobOeJyo8rlCV6ZGSFtgRJO0WzHrl-y87g,897
126
- pyxcp/scripts/xcp_info.py,sha256=COrBR1Wxncw5qQd05HVpbVUODIdbPZ7-_5ZOyitvg0E,2479
126
+ pyxcp/scripts/xcp_info.py,sha256=GB8sz1bD1FZPO-aKr6q3EK9J1ng_z2T9ZjbB4Jczq9s,2956
127
127
  pyxcp/scripts/pyxcp_probe_can_drivers.py,sha256=r_Mc6VwGNziwyOYCHoXNcmzD8LeNgG17g7lfDS8Mohw,597
128
128
  pyxcp/recorder/build_gcc_arm.sh,sha256=spqHf6D8Jd4NACYG65SNjb-BLMntELwBDO4PpHUiyYc,238
129
129
  pyxcp/recorder/recorder.rst,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0