pyxcp 0.23.1__cp314-cp314-win_amd64.whl → 0.23.3__cp314-cp314-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.
- pyxcp/__init__.py +1 -1
- pyxcp/cmdline.py +41 -9
- pyxcp/config/__init__.py +96 -5
- pyxcp/cpp_ext/cpp_ext.cp310-win_amd64.pyd +0 -0
- pyxcp/cpp_ext/cpp_ext.cp311-win_amd64.pyd +0 -0
- pyxcp/cpp_ext/cpp_ext.cp312-win_amd64.pyd +0 -0
- pyxcp/cpp_ext/cpp_ext.cp313-win_amd64.pyd +0 -0
- pyxcp/cpp_ext/cpp_ext.cp314-win_amd64.pyd +0 -0
- pyxcp/daq_stim/stim.cp310-win_amd64.pyd +0 -0
- pyxcp/daq_stim/stim.cp311-win_amd64.pyd +0 -0
- pyxcp/daq_stim/stim.cp312-win_amd64.pyd +0 -0
- pyxcp/daq_stim/stim.cp313-win_amd64.pyd +0 -0
- pyxcp/daq_stim/stim.cp314-win_amd64.pyd +0 -0
- pyxcp/examples/xcphello.py +8 -8
- pyxcp/recorder/rekorder.cp310-win_amd64.pyd +0 -0
- pyxcp/recorder/rekorder.cp311-win_amd64.pyd +0 -0
- pyxcp/recorder/rekorder.cp312-win_amd64.pyd +0 -0
- pyxcp/recorder/rekorder.cp313-win_amd64.pyd +0 -0
- pyxcp/recorder/rekorder.cp314-win_amd64.pyd +0 -0
- pyxcp-0.23.3.dist-info/METADATA +219 -0
- {pyxcp-0.23.1.dist-info → pyxcp-0.23.3.dist-info}/RECORD +24 -24
- pyxcp-0.23.1.dist-info/METADATA +0 -107
- {pyxcp-0.23.1.dist-info → pyxcp-0.23.3.dist-info}/LICENSE +0 -0
- {pyxcp-0.23.1.dist-info → pyxcp-0.23.3.dist-info}/WHEEL +0 -0
- {pyxcp-0.23.1.dist-info → pyxcp-0.23.3.dist-info}/entry_points.txt +0 -0
pyxcp/__init__.py
CHANGED
pyxcp/cmdline.py
CHANGED
|
@@ -8,7 +8,11 @@ import warnings
|
|
|
8
8
|
from dataclasses import dataclass
|
|
9
9
|
from typing import List
|
|
10
10
|
|
|
11
|
-
from pyxcp.config import
|
|
11
|
+
from pyxcp.config import ( # noqa: F401
|
|
12
|
+
create_application,
|
|
13
|
+
get_application,
|
|
14
|
+
reset_application,
|
|
15
|
+
)
|
|
12
16
|
from pyxcp.master import Master
|
|
13
17
|
|
|
14
18
|
|
|
@@ -23,28 +27,56 @@ class Option:
|
|
|
23
27
|
help: str = ""
|
|
24
28
|
type: str = ""
|
|
25
29
|
default: str = ""
|
|
30
|
+
action: str = ""
|
|
26
31
|
|
|
27
32
|
|
|
28
33
|
class FakeParser:
|
|
34
|
+
"""Parser that collects arguments for later processing."""
|
|
29
35
|
|
|
30
|
-
|
|
36
|
+
def __init__(self):
|
|
37
|
+
self.options = []
|
|
31
38
|
|
|
32
|
-
def add_argument(self, short_opt
|
|
33
|
-
|
|
34
|
-
self.options.append(Option(short_opt, long_opt, dest, help, type, default))
|
|
39
|
+
def add_argument(self, short_opt, long_opt="", dest="", help="", type=None, default=None, action=None):
|
|
40
|
+
"""Collect argument definitions without issuing warnings."""
|
|
41
|
+
self.options.append(Option(short_opt, long_opt, dest, help, type, default, action))
|
|
35
42
|
|
|
36
43
|
|
|
37
44
|
class ArgumentParser:
|
|
38
|
-
|
|
45
|
+
"""Argument parser for pyXCP applications.
|
|
46
|
+
|
|
47
|
+
This class provides a way to add custom command-line arguments to pyXCP applications.
|
|
48
|
+
It also supports a callout function that will be called with the master instance and
|
|
49
|
+
the parsed arguments.
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
def __init__(self, callout=None, description=None, *args, **kws):
|
|
39
53
|
self._parser = FakeParser()
|
|
40
|
-
|
|
41
|
-
|
|
54
|
+
self._callout = callout
|
|
55
|
+
self._description = description
|
|
42
56
|
|
|
43
57
|
def run(self, policy=None, transport_layer_interface=None):
|
|
44
|
-
|
|
58
|
+
"""Create and configure a master instance.
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
policy: Optional policy to use for the master
|
|
62
|
+
transport_layer_interface: Optional transport layer interface to use
|
|
63
|
+
|
|
64
|
+
Returns:
|
|
65
|
+
A configured master instance
|
|
66
|
+
"""
|
|
67
|
+
# Create the application with custom arguments and callout
|
|
68
|
+
application = get_application(self.parser.options, self._callout)
|
|
69
|
+
|
|
70
|
+
# Create the master instance
|
|
45
71
|
master = Master(
|
|
46
72
|
application.transport.layer, config=application, policy=policy, transport_layer_interface=transport_layer_interface
|
|
47
73
|
)
|
|
74
|
+
|
|
75
|
+
# If there's a callout function, call it with the master and args
|
|
76
|
+
if application.callout is not None and hasattr(application, "custom_args"):
|
|
77
|
+
args = application.custom_args.get_args()
|
|
78
|
+
application.callout(master, args)
|
|
79
|
+
|
|
48
80
|
return master
|
|
49
81
|
|
|
50
82
|
@property
|
pyxcp/config/__init__.py
CHANGED
|
@@ -17,6 +17,7 @@ from traitlets import (
|
|
|
17
17
|
Dict,
|
|
18
18
|
Enum,
|
|
19
19
|
Float,
|
|
20
|
+
HasTraits,
|
|
20
21
|
Integer,
|
|
21
22
|
List,
|
|
22
23
|
TraitError,
|
|
@@ -24,6 +25,7 @@ from traitlets import (
|
|
|
24
25
|
Union,
|
|
25
26
|
)
|
|
26
27
|
from traitlets.config import Application, Configurable, Instance, default
|
|
28
|
+
from traitlets.config.loader import Config
|
|
27
29
|
|
|
28
30
|
from pyxcp.config import legacy
|
|
29
31
|
|
|
@@ -491,10 +493,22 @@ If set, the `app_name` does not have to be previously defined in
|
|
|
491
493
|
|
|
492
494
|
|
|
493
495
|
class CanCustom(Configurable, CanBase):
|
|
494
|
-
"""
|
|
496
|
+
"""Generic custom CAN interface.
|
|
497
|
+
|
|
498
|
+
Enable basic CanBase options so user-provided python-can backends can
|
|
499
|
+
consume common parameters like bitrate, fd, data_bitrate, poll_interval,
|
|
500
|
+
receive_own_messages, and optional timing.
|
|
501
|
+
"""
|
|
495
502
|
|
|
496
503
|
interface_name = "custom"
|
|
497
504
|
|
|
505
|
+
# Allow usage of the basic options from CanBase for custom backends
|
|
506
|
+
has_fd = True
|
|
507
|
+
has_data_bitrate = True
|
|
508
|
+
has_poll_interval = True
|
|
509
|
+
has_receive_own_messages = True
|
|
510
|
+
has_timing = True
|
|
511
|
+
|
|
498
512
|
|
|
499
513
|
class Virtual(Configurable, CanBase):
|
|
500
514
|
""" """
|
|
@@ -829,6 +843,68 @@ if there is no response to a command.""",
|
|
|
829
843
|
self.usb = Usb(config=self.config, parent=self)
|
|
830
844
|
|
|
831
845
|
|
|
846
|
+
class CustomArgs(Configurable):
|
|
847
|
+
"""Class to handle custom command-line arguments."""
|
|
848
|
+
|
|
849
|
+
def __init__(self, **kwargs):
|
|
850
|
+
super().__init__(**kwargs)
|
|
851
|
+
self._custom_args = {}
|
|
852
|
+
|
|
853
|
+
def add_argument(self, short_opt, long_opt="", dest="", help="", type=None, default=None, action=None):
|
|
854
|
+
"""Add a custom argument dynamically.
|
|
855
|
+
|
|
856
|
+
This mimics the argparse.ArgumentParser.add_argument method.
|
|
857
|
+
"""
|
|
858
|
+
if not dest and long_opt:
|
|
859
|
+
dest = long_opt.lstrip("-").replace("-", "_")
|
|
860
|
+
|
|
861
|
+
# Store the argument definition
|
|
862
|
+
self._custom_args[dest] = {
|
|
863
|
+
"short_opt": short_opt,
|
|
864
|
+
"long_opt": long_opt,
|
|
865
|
+
"help": help,
|
|
866
|
+
"type": type,
|
|
867
|
+
"default": default,
|
|
868
|
+
"action": action,
|
|
869
|
+
"value": default,
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
# Dynamically add a trait for this argument
|
|
873
|
+
trait_type = Any()
|
|
874
|
+
if type == bool or action == "store_true" or action == "store_false":
|
|
875
|
+
trait_type = Bool(default)
|
|
876
|
+
elif type == int:
|
|
877
|
+
trait_type = Integer(default)
|
|
878
|
+
elif type == float:
|
|
879
|
+
trait_type = Float(default)
|
|
880
|
+
elif type == str:
|
|
881
|
+
trait_type = Unicode(default)
|
|
882
|
+
|
|
883
|
+
# Add the trait to this instance
|
|
884
|
+
self.add_trait(dest, trait_type)
|
|
885
|
+
setattr(self, dest, default)
|
|
886
|
+
|
|
887
|
+
def update_from_options(self, options):
|
|
888
|
+
"""Update trait values from parsed options."""
|
|
889
|
+
for option in options:
|
|
890
|
+
if option.dest and option.dest in self._custom_args:
|
|
891
|
+
if option.default is not None:
|
|
892
|
+
setattr(self, option.dest, option.default)
|
|
893
|
+
self._custom_args[option.dest]["value"] = option.default
|
|
894
|
+
|
|
895
|
+
def get_args(self):
|
|
896
|
+
"""Return an object with all custom arguments as attributes."""
|
|
897
|
+
|
|
898
|
+
class Args:
|
|
899
|
+
pass
|
|
900
|
+
|
|
901
|
+
args = Args()
|
|
902
|
+
for name, arg_def in self._custom_args.items():
|
|
903
|
+
setattr(args, name, arg_def["value"])
|
|
904
|
+
|
|
905
|
+
return args
|
|
906
|
+
|
|
907
|
+
|
|
832
908
|
class General(Configurable):
|
|
833
909
|
""" """
|
|
834
910
|
|
|
@@ -929,7 +1005,12 @@ class PyXCP(Application):
|
|
|
929
1005
|
description = "pyXCP application"
|
|
930
1006
|
config_file = Unicode(default_value="pyxcp_conf.py", help="base name of config file").tag(config=True)
|
|
931
1007
|
|
|
932
|
-
|
|
1008
|
+
# Add callout function support
|
|
1009
|
+
callout = Callable(default_value=None, allow_none=True, help="Callback function to be called with master and args").tag(
|
|
1010
|
+
config=True
|
|
1011
|
+
)
|
|
1012
|
+
|
|
1013
|
+
classes = List([General, Transport, CustomArgs])
|
|
933
1014
|
|
|
934
1015
|
subcommands = dict(
|
|
935
1016
|
profile=(
|
|
@@ -985,6 +1066,7 @@ class PyXCP(Application):
|
|
|
985
1066
|
self.read_configuration_file(file_name, emit_warning)
|
|
986
1067
|
self.general = General(config=self.config, parent=self)
|
|
987
1068
|
self.transport = Transport(parent=self)
|
|
1069
|
+
self.custom_args = CustomArgs(config=self.config, parent=self)
|
|
988
1070
|
|
|
989
1071
|
def read_configuration_file(self, file_name: str, emit_warning: bool = True):
|
|
990
1072
|
self.legacy_config: bool = False
|
|
@@ -1086,7 +1168,7 @@ class PyXCP(Application):
|
|
|
1086
1168
|
application: typing.Optional[PyXCP] = None
|
|
1087
1169
|
|
|
1088
1170
|
|
|
1089
|
-
def create_application(options: typing.Optional[typing.List[typing.Any]] = None) -> PyXCP:
|
|
1171
|
+
def create_application(options: typing.Optional[typing.List[typing.Any]] = None, callout=None) -> PyXCP:
|
|
1090
1172
|
global application
|
|
1091
1173
|
if options is None:
|
|
1092
1174
|
options = []
|
|
@@ -1095,15 +1177,24 @@ def create_application(options: typing.Optional[typing.List[typing.Any]] = None)
|
|
|
1095
1177
|
application = PyXCP()
|
|
1096
1178
|
application.initialize(sys.argv)
|
|
1097
1179
|
application.start()
|
|
1180
|
+
|
|
1181
|
+
# Set callout function if provided
|
|
1182
|
+
if callout is not None:
|
|
1183
|
+
application.callout = callout
|
|
1184
|
+
|
|
1185
|
+
# Process custom arguments if provided
|
|
1186
|
+
if options and hasattr(application, "custom_args"):
|
|
1187
|
+
application.custom_args.update_from_options(options)
|
|
1188
|
+
|
|
1098
1189
|
return application
|
|
1099
1190
|
|
|
1100
1191
|
|
|
1101
|
-
def get_application(options: typing.Optional[typing.List[typing.Any]] = None) -> PyXCP:
|
|
1192
|
+
def get_application(options: typing.Optional[typing.List[typing.Any]] = None, callout=None) -> PyXCP:
|
|
1102
1193
|
if options is None:
|
|
1103
1194
|
options = []
|
|
1104
1195
|
global application
|
|
1105
1196
|
if application is None:
|
|
1106
|
-
application = create_application(options)
|
|
1197
|
+
application = create_application(options, callout)
|
|
1107
1198
|
return application
|
|
1108
1199
|
|
|
1109
1200
|
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
pyxcp/examples/xcphello.py
CHANGED
|
@@ -16,14 +16,14 @@ def callout(master, args):
|
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
ap = ArgumentParser(description="pyXCP hello world.", callout=callout)
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
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
27
|
|
|
28
28
|
with ap.run() as x:
|
|
29
29
|
x.connect()
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: pyxcp
|
|
3
|
+
Version: 0.23.3
|
|
4
|
+
Summary: Universal Calibration Protocol for Python
|
|
5
|
+
License: LGPLv3
|
|
6
|
+
Keywords: automotive,ecu,xcp,asam,autosar
|
|
7
|
+
Author: Christoph Schueler
|
|
8
|
+
Author-email: cpu.gems@googlemail.com
|
|
9
|
+
Requires-Python: >=3.10,<4.0
|
|
10
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
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.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering
|
|
21
|
+
Classifier: Topic :: Software Development
|
|
22
|
+
Requires-Dist: bandit (>=1.7.8,<2.0.0)
|
|
23
|
+
Requires-Dist: chardet (>=5.2.0,<6.0.0)
|
|
24
|
+
Requires-Dist: construct (>=2.10.68,<3.0.0)
|
|
25
|
+
Requires-Dist: line-profiler-pycharm (>=1.1.0,<2.0.0)
|
|
26
|
+
Requires-Dist: mako (>=1.2.4,<2.0.0)
|
|
27
|
+
Requires-Dist: pyserial (>=3.5,<4.0)
|
|
28
|
+
Requires-Dist: python-can (>=4.2.2,<5.0.0)
|
|
29
|
+
Requires-Dist: pytz (>=2025.2,<2026.0)
|
|
30
|
+
Requires-Dist: pyusb (>=1.2.1,<2.0.0)
|
|
31
|
+
Requires-Dist: rich (>=14.0.0,<15.0.0)
|
|
32
|
+
Requires-Dist: toml (>=0.10.2,<0.11.0)
|
|
33
|
+
Requires-Dist: tomlkit (>=0.13.3,<0.14.0)
|
|
34
|
+
Requires-Dist: traitlets (<=5.11.2)
|
|
35
|
+
Requires-Dist: uptime (>=3.0.1,<4.0.0)
|
|
36
|
+
Project-URL: Homepage, https://github.com/christoph2/pyxcp
|
|
37
|
+
Description-Content-Type: text/markdown
|
|
38
|
+
|
|
39
|
+
# pyXCP
|
|
40
|
+
|
|
41
|
+
Reliable Python tooling for the ASAM MCD‑1 XCP protocol (measurement, calibration, flashing) with multiple transports (CAN, Ethernet, USB, Serial) and handy CLI utilities.
|
|
42
|
+
|
|
43
|
+
[](https://github.com/christoph2/pyxcp/actions)
|
|
44
|
+
[](https://pypi.org/project/pyxcp/)
|
|
45
|
+
[](https://pypi.org/project/pyxcp/)
|
|
46
|
+
[](https://www.gnu.org/licenses/lgpl-3.0)
|
|
47
|
+
[](https://github.com/psf/black)
|
|
48
|
+
|
|
49
|
+
pyXCP is a production-ready Python library for communicating with XCP-enabled devices, most commonly automotive ECUs. Use it to take measurements, adjust parameters (calibration), stream DAQ/STIM, and program devices during development.
|
|
50
|
+
|
|
51
|
+
Highlights:
|
|
52
|
+
- Transports: Ethernet (TCP/IP), CAN, USB, Serial (SxI)
|
|
53
|
+
- Cross‑platform: Windows, Linux, macOS
|
|
54
|
+
- Rich CLI tools for common XCP tasks
|
|
55
|
+
- Extensible architecture and layered design
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## Installation
|
|
60
|
+
|
|
61
|
+
The easiest way is from PyPI:
|
|
62
|
+
|
|
63
|
+
```shell
|
|
64
|
+
pip install pyxcp
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
To install from the main branch:
|
|
68
|
+
|
|
69
|
+
```shell
|
|
70
|
+
pip install git+https://github.com/christoph2/pyxcp.git
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
### Requirements
|
|
75
|
+
- Python >= 3.10
|
|
76
|
+
- Building from source requires a working C/C++ toolchain (native extensions are used for performance). Wheels are provided for common platforms and Python versions; if a wheel is not available, pip will build from source.
|
|
77
|
+
- An XCP slave device (or simulator)
|
|
78
|
+
|
|
79
|
+
## Quick start
|
|
80
|
+
|
|
81
|
+
The tutorial walks you through typical tasks end‑to‑end: see docs/tutorial.md.
|
|
82
|
+
|
|
83
|
+
Minimal example using the built‑in argument parser and context manager:
|
|
84
|
+
|
|
85
|
+
```python
|
|
86
|
+
from pyxcp.cmdline import ArgumentParser
|
|
87
|
+
|
|
88
|
+
ap = ArgumentParser(description="pyXCP hello world")
|
|
89
|
+
|
|
90
|
+
with ap.run() as x:
|
|
91
|
+
x.connect()
|
|
92
|
+
identifier = x.identifier(0x01)
|
|
93
|
+
print(f"ID: {identifier!r}")
|
|
94
|
+
print(x.slaveProperties)
|
|
95
|
+
x.disconnect()
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Configuration
|
|
99
|
+
pyXCP supports a [traitlets](https://github.com/ipython/traitlets)‑based configuration system.
|
|
100
|
+
- Recommended Python config example and generator: docs/tutorial.md and docs/configuration.md
|
|
101
|
+
- Legacy TOML examples remain available for compatibility.
|
|
102
|
+
|
|
103
|
+
### Command‑line tools
|
|
104
|
+
Installed entry points (see pyproject.toml):
|
|
105
|
+
- xcp-info — print capabilities and properties
|
|
106
|
+
- xcp-id-scanner — scan for slave identifiers
|
|
107
|
+
- xcp-fetch-a2l — retrieve A2L from target (if supported)
|
|
108
|
+
- xcp-profile — generate/convert config files
|
|
109
|
+
- xcp-examples — launch assorted demos/examples
|
|
110
|
+
- xmraw-converter — convert recorder .xmraw data
|
|
111
|
+
- pyxcp-probe-can-drivers — list available CAN interfaces
|
|
112
|
+
|
|
113
|
+
Run any tool with -h for options.
|
|
114
|
+
|
|
115
|
+
## Features
|
|
116
|
+
- Multiple transport layers: Ethernet (TCP), CAN, USB, SxI (serial/UART)
|
|
117
|
+
- Data Acquisition (DAQ) and Stimulation (STIM)
|
|
118
|
+
- Calibration (read/write parameters)
|
|
119
|
+
- Flashing/programming workflows
|
|
120
|
+
- A2L (ASAM MCD‑2 MC) support
|
|
121
|
+
- Recorder utilities and converters (see docs/recorder.md)
|
|
122
|
+
- Extensible architecture for custom transports
|
|
123
|
+
|
|
124
|
+
## Documentation
|
|
125
|
+
- Getting started tutorial: docs/tutorial.md
|
|
126
|
+
- Configuration: docs/configuration.md
|
|
127
|
+
- CAN driver setup and troubleshooting: docs/howto_can_driver.md
|
|
128
|
+
- Recorder: docs/recorder.md
|
|
129
|
+
|
|
130
|
+
To build the Sphinx documentation locally:
|
|
131
|
+
1. Install doc requirements: `pip install -r docs/requirements.txt`
|
|
132
|
+
2. Build: `sphinx-build -b html docs docs/_build/html`
|
|
133
|
+
3. Open `docs/_build/html/index.html`
|
|
134
|
+
|
|
135
|
+
## Compatibility
|
|
136
|
+
- Operating systems: Windows, Linux, macOS
|
|
137
|
+
- Python: 3.10 - 3.14, CPython wheels where available
|
|
138
|
+
- CAN backends: python-can compatible drivers (see docs/howto_can_driver.md)
|
|
139
|
+
|
|
140
|
+
## Contributing
|
|
141
|
+
Contributions are welcome! Please:
|
|
142
|
+
- Read CODE_OF_CONDUCT.md
|
|
143
|
+
- Open an issue or discussion before large changes
|
|
144
|
+
- Use [pre-commit](https://github.com/pre-commit/pre-commit) to run linters and tests locally
|
|
145
|
+
|
|
146
|
+
## License
|
|
147
|
+
GNU Lesser General Public License v3 or later (LGPLv3+). See LICENSE for details.
|
|
148
|
+
|
|
149
|
+
## References
|
|
150
|
+
- ASAM MCD‑1 XCP standard: https://www.asam.net/standards/detail/mcd-1-xcp/
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
## About ASAM MCD‑1 XCP
|
|
154
|
+
XCP (Universal Measurement and Calibration Protocol) is an ASAM standard defining a vendor‑neutral protocol to access internal data of electronic control units (ECUs) for measurement, calibration (parameter tuning), and programming. XCP decouples the protocol from the physical transport, so the same command set can be carried over different buses such as CAN, FlexRay, Ethernet, USB, or Serial.
|
|
155
|
+
|
|
156
|
+
- Roles: An XCP Master (this library) communicates with an XCP Slave (your device/ECU or simulator).
|
|
157
|
+
- Layered concept: XCP defines an application layer and transport layers. pyXCP implements the application layer and multiple transport bindings.
|
|
158
|
+
- Use cases:
|
|
159
|
+
- Measurement: Read variables from the ECU in real‑time, including high‑rate DAQ streaming.
|
|
160
|
+
- Calibration: Read/write parameters (calibration data) in RAM/flash.
|
|
161
|
+
- Programming: Download new program/data to flash (where the slave supports it).
|
|
162
|
+
|
|
163
|
+
For the authoritative description, see the ASAM page: https://www.asam.net/standards/detail/mcd-1-xcp/
|
|
164
|
+
|
|
165
|
+
## XCP in a nutshell
|
|
166
|
+
- Connect/Session: The master establishes a connection, negotiates capabilities/features, and optionally unlocks protected functions via seed & key.
|
|
167
|
+
- Addressing: Memory is accessed via absolute or segment‑relative addresses. Addressing modes are described in the associated A2L file (ASAM MCD‑2 MC), which maps symbolic names to addresses, data types, and conversion rules.
|
|
168
|
+
- Events: The slave exposes events (e.g., “1 ms task”, “Combustion cycle”), which trigger DAQ sampling. The master assigns signals (ODTs) to these events for time‑aligned acquisition.
|
|
169
|
+
- DAQ/STIM: DAQ = Data Acquisition (slave → master), STIM = Stimulation (master → slave). Both use event‑driven lists for deterministic timing.
|
|
170
|
+
- Timestamps: DAQ may carry timestamps from the slave for precise time correlation.
|
|
171
|
+
- Security: Access to sensitive commands (e.g., programming, calibration) can be protected by a seed & key algorithm negotiated at runtime.
|
|
172
|
+
- Checksums: XCP defines checksum services useful for verifying memory regions (e.g., after flashing).
|
|
173
|
+
|
|
174
|
+
## Relation to A2L (ASAM MCD‑2 MC)
|
|
175
|
+
While XCP defines the protocol, the A2L file describes the measurement and calibration objects (characteristics, measurements), data types, conversion rules, and memory layout. In practice, you use pyXCP together with an A2L to:
|
|
176
|
+
- Resolve symbolic names to addresses and data types.
|
|
177
|
+
- Configure DAQ lists from human‑readable signal names.
|
|
178
|
+
- Interpret raw values using the appropriate conversion methods.
|
|
179
|
+
|
|
180
|
+
pyXCP provides utilities to fetch A2L data when supported by the slave and to work with A2L‑described objects.
|
|
181
|
+
See also [pya2ldb](https://github.com/christoph2/pya2l)!
|
|
182
|
+
|
|
183
|
+
## Transports and addressing
|
|
184
|
+
XCP is transport‑agnostic. pyXCP supports multiple transports and addressing schemes:
|
|
185
|
+
- CAN (XCP on CAN): Robust and ubiquitous in vehicles; limited payload and bandwidth; suited for many calibration tasks and moderate DAQ rates.
|
|
186
|
+
- Ethernet (XCP on TCP/UDP): High bandwidth with low latency; well suited for rich DAQ and programming workflows.
|
|
187
|
+
- USB: High throughput for lab setups; requires device support.
|
|
188
|
+
- Serial/SxI: Simple point‑to‑point links for embedded targets and simulators.
|
|
189
|
+
|
|
190
|
+
The exact capabilities (e.g., max CTO/DTO, checksum types, timestamping) are negotiated at connect time and depend on the slave and transport.
|
|
191
|
+
|
|
192
|
+
## Supported features (overview)
|
|
193
|
+
The scope of features depends on the connected slave. At the library level, pyXCP provides:
|
|
194
|
+
- Session management: CONNECT/DISCONNECT, GET_STATUS/SLAVE_PROPERTIES, communication mode setup, error handling.
|
|
195
|
+
- Memory access: Upload/short upload, Download/Download Next, verifications, optional paged memory where supported.
|
|
196
|
+
- DAQ/STIM: Configuration of DAQ lists/ODTs, event assignment, data streaming, timestamp handling when available.
|
|
197
|
+
- Programming helpers: Building blocks for program/erase/write flows (exact sequence per slave’s flash algorithm and A2L description).
|
|
198
|
+
- Security/Seed & Key: Pluggable seed‑to‑key resolution including 32↔64‑bit bridge on Windows.
|
|
199
|
+
- Utilities: Identifier scanning, A2L helpers, recorder and converters.
|
|
200
|
+
|
|
201
|
+
Refer to docs/tutorial.md and docs/configuration.md for feature usage, and xcp-info for a capability dump of your target.
|
|
202
|
+
|
|
203
|
+
## Compliance and versions
|
|
204
|
+
pyXCP aims to be compatible with commonly used parts of ASAM MCD‑1 XCP. Specific optional features are enabled when a slave advertises them during CONNECT. Because implementations vary across vendors and ECU projects, always consult your A2L and use xcp-info to confirm negotiated options (e.g., checksum type, timestamp unit, max DTO size, address granularity).
|
|
205
|
+
|
|
206
|
+
If you rely on a particular XCP feature/profile not mentioned here, please open an issue with details about your slave and A2L so we can clarify support and—if feasible—add coverage.
|
|
207
|
+
|
|
208
|
+
## Safety, performance, and limitations
|
|
209
|
+
- Safety‑critical systems: XCP is a development and testing protocol. Do not enable measurement/calibration on safety‑critical systems in the field unless your system‑level safety case covers it.
|
|
210
|
+
- Performance: Achievable DAQ rates depend on transport bandwidth, ECU event rates, DTO sizes, and host processing. Ethernet typically yields the highest throughput.
|
|
211
|
+
- Latency/jitter: Event scheduling in the slave and OS scheduling on the host can affect determinism. Use timestamps to correlate data precisely.
|
|
212
|
+
- Access control: Seed & key protects sensitive functions; your organization’s policy should govern algorithm distribution and access.
|
|
213
|
+
|
|
214
|
+
## Further resources
|
|
215
|
+
- ASAM MCD‑1 XCP standard (overview and membership): https://www.asam.net/standards/detail/mcd-1-xcp/
|
|
216
|
+
- ASAM MCD‑2 MC (A2L) for object descriptions: https://www.asam.net/standards/detail/mcd-2-mc/
|
|
217
|
+
- Introduction to DAQ/STIM concepts (ASAM publications and vendor docs)
|
|
218
|
+
- Related: CCP (legacy predecessor to XCP), ASAM MDF for measurement data storage
|
|
219
|
+
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
pyxcp/__init__.py,sha256=
|
|
1
|
+
pyxcp/__init__.py,sha256=fVDaHDWZ31NkogpcyWKgMLiQBK356XczUnYPRUcrLAo,547
|
|
2
2
|
pyxcp/aml/EtasCANMonitoring.a2l,sha256=EJYwe3Z3H24vyWAa6lUgcdKnQY8pwFxjyCN6ZU1ST8w,1509
|
|
3
3
|
pyxcp/aml/EtasCANMonitoring.aml,sha256=xl0DdyeiIaLW0mmmJNAyJS0CQdOLSxt9dxfgrdSlU8Y,2405
|
|
4
4
|
pyxcp/aml/ifdata_CAN.a2l,sha256=NCUnCUEEgRbZYSLGtUGwL2e7zJ8hrp0SbmLHGv8uY58,612
|
|
@@ -17,18 +17,18 @@ pyxcp/asam/types.py,sha256=_gKcpBF5mon_SDWZBUW0PGBMcb37yrvhhEuk1wslg-s,2441
|
|
|
17
17
|
pyxcp/asamkeydll.c,sha256=dVEvU0S1kgIo62S0La-T8xHSw668LM_DYc_fiQ0No6g,2952
|
|
18
18
|
pyxcp/asamkeydll.sh,sha256=DC2NKUMwvi39OQgJ6514Chr4wc1LYbTmQHmMq9jAHHs,59
|
|
19
19
|
pyxcp/checksum.py,sha256=hO2JW_eiO9I0A4eiqovMV9d_y5oidq_w8jKdAE4FeOo,11899
|
|
20
|
-
pyxcp/cmdline.py,sha256=
|
|
21
|
-
pyxcp/config/__init__.py,sha256=
|
|
20
|
+
pyxcp/cmdline.py,sha256=4kNHOjbA0HeVfRicnFDeX1J9EBkTlA7KWL5SDfwbbaM,2525
|
|
21
|
+
pyxcp/config/__init__.py,sha256=z9bXNb2Hp-h2ZtASCyGk3JWP3OGoOL5Hmvazl-L_ANE,45258
|
|
22
22
|
pyxcp/config/legacy.py,sha256=4QdDheX8DbBKv5JVT72_C_cjCgKvZmhN3tJ6hsvBEtI,5220
|
|
23
23
|
pyxcp/constants.py,sha256=9yGfujC0ImTYQWfn41wyw8pluJTSrhMGWIVeIZTgsLg,1160
|
|
24
24
|
pyxcp/cpp_ext/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
25
25
|
pyxcp/cpp_ext/bin.hpp,sha256=PwJloZek21la-RBSda2Hc0u_6gID0sfTduPeplaAyR4,2561
|
|
26
26
|
pyxcp/cpp_ext/blockmem.hpp,sha256=ysaJwmTWGTfE54Outk3gJYOfAVFd_QaonBMtXLcXwCc,1242
|
|
27
|
-
pyxcp/cpp_ext/cpp_ext.cp310-win_amd64.pyd,sha256=
|
|
28
|
-
pyxcp/cpp_ext/cpp_ext.cp311-win_amd64.pyd,sha256=
|
|
29
|
-
pyxcp/cpp_ext/cpp_ext.cp312-win_amd64.pyd,sha256=
|
|
30
|
-
pyxcp/cpp_ext/cpp_ext.cp313-win_amd64.pyd,sha256=
|
|
31
|
-
pyxcp/cpp_ext/cpp_ext.cp314-win_amd64.pyd,sha256=
|
|
27
|
+
pyxcp/cpp_ext/cpp_ext.cp310-win_amd64.pyd,sha256=DnSJWDFdj1sm90iV3sEQx8nbkUIKDVRXw8ds113cKKw,288768
|
|
28
|
+
pyxcp/cpp_ext/cpp_ext.cp311-win_amd64.pyd,sha256=nZzaLOhg6Q3vj2xlETL-oQ1ujBeLMlxcapRUK4EKB-8,290816
|
|
29
|
+
pyxcp/cpp_ext/cpp_ext.cp312-win_amd64.pyd,sha256=nXFMOQ0eISY57I-D6hQHeUfxgDMsaf2-Cpy0xBw4eII,295424
|
|
30
|
+
pyxcp/cpp_ext/cpp_ext.cp313-win_amd64.pyd,sha256=ydJGO_zJtB3bDdc9uqAHW2OJp5k62bsS8piscFywAbI,295424
|
|
31
|
+
pyxcp/cpp_ext/cpp_ext.cp314-win_amd64.pyd,sha256=IUj44MCjuVhv3pAPoenwhFnSWks_9eYJHaQjPKKvW9c,297984
|
|
32
32
|
pyxcp/cpp_ext/daqlist.hpp,sha256=g2hlxgoQorAGKHedZFZ0c2FQh1APMIA9sVB6M6hD_n8,7277
|
|
33
33
|
pyxcp/cpp_ext/event.hpp,sha256=Z-1yxsEKsr81NnLVEWJ2ANA8FV7YsM7EbNxaw-elheE,1200
|
|
34
34
|
pyxcp/cpp_ext/extension_wrapper.cpp,sha256=xFs3IcrvHPHA82-n11WPzt8HATGqcks02p84SjQ2BKM,4855
|
|
@@ -40,11 +40,11 @@ pyxcp/daq_stim/optimize/__init__.py,sha256=FUWK0GkNpNT-sUlhibp7xa2aSYpm6Flh5yA2w
|
|
|
40
40
|
pyxcp/daq_stim/optimize/binpacking.py,sha256=Iltho5diKlJG-ltbmx053U2vOFRlCISolXK61T14l_I,1257
|
|
41
41
|
pyxcp/daq_stim/scheduler.cpp,sha256=NuNkAz3Dv849f51_T36YPck2dl-YsdDdG-cozc7XN9U,1504
|
|
42
42
|
pyxcp/daq_stim/scheduler.hpp,sha256=U_6tUbebmzX5vVZS0EFSgTaPsyxMg6yRXHG_aPWA0x4,1884
|
|
43
|
-
pyxcp/daq_stim/stim.cp310-win_amd64.pyd,sha256=
|
|
44
|
-
pyxcp/daq_stim/stim.cp311-win_amd64.pyd,sha256=
|
|
45
|
-
pyxcp/daq_stim/stim.cp312-win_amd64.pyd,sha256=
|
|
46
|
-
pyxcp/daq_stim/stim.cp313-win_amd64.pyd,sha256=
|
|
47
|
-
pyxcp/daq_stim/stim.cp314-win_amd64.pyd,sha256=
|
|
43
|
+
pyxcp/daq_stim/stim.cp310-win_amd64.pyd,sha256=jzG2SA5yhxvEOe_Rztm5s3_1giPtEl8WAMxdDu-65pk,208896
|
|
44
|
+
pyxcp/daq_stim/stim.cp311-win_amd64.pyd,sha256=BlIYDELUmxBFneVVrOP9d0DCaGaVidX1mnnp2M-Zu7M,210432
|
|
45
|
+
pyxcp/daq_stim/stim.cp312-win_amd64.pyd,sha256=oYTn7_qL1-RCquj6PwEnHI-jeH_38PiScnp6HZniSgE,214528
|
|
46
|
+
pyxcp/daq_stim/stim.cp313-win_amd64.pyd,sha256=8nzCcn8oqzdoyOxKHqRQxWsv8BQl7hAlxW579FrqEu4,214528
|
|
47
|
+
pyxcp/daq_stim/stim.cp314-win_amd64.pyd,sha256=WT53aHDOj_q825FkAAVF-DTN_FpsChScZSy_9mviClI,215552
|
|
48
48
|
pyxcp/daq_stim/stim.cpp,sha256=F2OG67W4KKwTTiUCxm-9egIv3TLFdOkRunX6xf7YOtc,177
|
|
49
49
|
pyxcp/daq_stim/stim.hpp,sha256=U-uInRrA6OCdMl1l1SWbQ_KEPpnNYrWut924IvbW6R0,18508
|
|
50
50
|
pyxcp/daq_stim/stim_wrapper.cpp,sha256=iT2yxJ3LRG7HoYC1bwhM3tCAxF9X_HHierBNsLRmTJg,1995
|
|
@@ -65,7 +65,7 @@ pyxcp/examples/xcp_read_benchmark.py,sha256=zOG0Yrji10vA0vhHa27KK7zgc3JDpzXzXsFn
|
|
|
65
65
|
pyxcp/examples/xcp_skel.py,sha256=YXLQC8nn8aAwYSVuBGhr1dvmdMBjmO1Ee1w3e5sy16s,1159
|
|
66
66
|
pyxcp/examples/xcp_unlock.py,sha256=5F7oW17MboxKO3REYrGyhYX4Oc0Dg1oD3EQ3fQXB2Is,690
|
|
67
67
|
pyxcp/examples/xcp_user_supplied_driver.py,sha256=9fFiud6sbjkBjxmcdGwIO6yBc83sUykY388gvI5EcXU,1148
|
|
68
|
-
pyxcp/examples/xcphello.py,sha256=
|
|
68
|
+
pyxcp/examples/xcphello.py,sha256=TAFCRf9Cg5uc-WGaxdHHUS_hKYkWqt77-3j9gGG6GW8,2628
|
|
69
69
|
pyxcp/examples/xcphello_recorder.py,sha256=QHWJsq5h5CI9t5qEmMSorZyzirTpoXz4nzuKTMzbZCA,3409
|
|
70
70
|
pyxcp/master/__init__.py,sha256=QQbkUJM1WQ-5p2MiNFYxLAmHhNsCQLzDp-S4aoOFxoA,318
|
|
71
71
|
pyxcp/master/errorhandler.py,sha256=ulL6WiraZbVZnM2pfR8S9vlWAAP5UXwXqmbjjxH9rgc,15359
|
|
@@ -86,11 +86,11 @@ pyxcp/recorder/mio.hpp,sha256=5ASJLKSEykH0deAQD5uak-_yAgd5p2n8t06315GSGrg,63346
|
|
|
86
86
|
pyxcp/recorder/reader.hpp,sha256=rr9XZ_ciL6eF2_xEqyt9XYNqTIze9ytAsnf8uYukO9U,5201
|
|
87
87
|
pyxcp/recorder/reco.py,sha256=6N6FIwfCEVMpi5dr3eUOQa1lowcg2LCnS_sy_-b-UiQ,8725
|
|
88
88
|
pyxcp/recorder/recorder.rst,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
89
|
-
pyxcp/recorder/rekorder.cp310-win_amd64.pyd,sha256=
|
|
90
|
-
pyxcp/recorder/rekorder.cp311-win_amd64.pyd,sha256=
|
|
91
|
-
pyxcp/recorder/rekorder.cp312-win_amd64.pyd,sha256=
|
|
92
|
-
pyxcp/recorder/rekorder.cp313-win_amd64.pyd,sha256=
|
|
93
|
-
pyxcp/recorder/rekorder.cp314-win_amd64.pyd,sha256=
|
|
89
|
+
pyxcp/recorder/rekorder.cp310-win_amd64.pyd,sha256=53jF5N8lV5iLn8XHgYtrZZoK9i94kSwaB5uZwr93h3A,389632
|
|
90
|
+
pyxcp/recorder/rekorder.cp311-win_amd64.pyd,sha256=MIeTpsRbjzLTbIBGHBinirn9jvrz_r4ao7JPVMqY6Yw,391168
|
|
91
|
+
pyxcp/recorder/rekorder.cp312-win_amd64.pyd,sha256=pWoFwxF3pU80eHFI9k-vxDRJa5CI0p4mHidvEBYHznQ,396800
|
|
92
|
+
pyxcp/recorder/rekorder.cp313-win_amd64.pyd,sha256=M-Rwojpjafj5Gcj5E50EAHfzqx2EmZcKXtvOJ43o-UM,396800
|
|
93
|
+
pyxcp/recorder/rekorder.cp314-win_amd64.pyd,sha256=5TrY17qawo3iSuBP-oZR_JDS0dm84m6f1RAi0VKFmDc,398848
|
|
94
94
|
pyxcp/recorder/rekorder.cpp,sha256=U0LMyk8pZXx9emgS_WPVthvn_9IpgE7JGrh4kg-8CX4,1900
|
|
95
95
|
pyxcp/recorder/rekorder.hpp,sha256=sWvRch9bVt6mmgrFHp5mwWhap7HoFG4geeb7UqEIzio,7638
|
|
96
96
|
pyxcp/recorder/setup.py,sha256=_99XFPQAd5V4LcJaSGJwdnbxgxJ7kl8DEXfHsnKO1Yg,998
|
|
@@ -130,8 +130,8 @@ pyxcp/types.py,sha256=mjp3FhsTTbS3D5VuC-dfdbMql0lJwEfbZjf8a2pHi1o,26158
|
|
|
130
130
|
pyxcp/utils.py,sha256=_ag2QMt0IxVhiCLG5BIO8JzIGt-rdqYrY7DRAPQ4AtA,3530
|
|
131
131
|
pyxcp/vector/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
132
132
|
pyxcp/vector/map.py,sha256=7Gnhvr79geMeqqGVIJPxODXGwABdNDinnqzhpooN5TE,2306
|
|
133
|
-
pyxcp-0.23.
|
|
134
|
-
pyxcp-0.23.
|
|
135
|
-
pyxcp-0.23.
|
|
136
|
-
pyxcp-0.23.
|
|
137
|
-
pyxcp-0.23.
|
|
133
|
+
pyxcp-0.23.3.dist-info/entry_points.txt,sha256=LkHsEwubm30s4oiyCy0cKj6k97ALvQ6KjAVdyEcqu7g,358
|
|
134
|
+
pyxcp-0.23.3.dist-info/LICENSE,sha256=fTqV5eBpeAZO0_jit8j4Ref9ikBSlHJ8xwj5TLg7gFk,7817
|
|
135
|
+
pyxcp-0.23.3.dist-info/METADATA,sha256=wQmqlFOaiVIYsJGLg5m2M0aHyit3Ofwl7T1FEjWiWNg,11688
|
|
136
|
+
pyxcp-0.23.3.dist-info/WHEEL,sha256=kwfqy3xKRHEZfXFvb9ph-wqPOS4inj_OLrOJzUuVYBY,98
|
|
137
|
+
pyxcp-0.23.3.dist-info/RECORD,,
|
pyxcp-0.23.1.dist-info/METADATA
DELETED
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.3
|
|
2
|
-
Name: pyxcp
|
|
3
|
-
Version: 0.23.1
|
|
4
|
-
Summary: Universal Calibration Protocol for Python
|
|
5
|
-
License: LGPLv3
|
|
6
|
-
Keywords: automotive,ecu,xcp,asam,autosar
|
|
7
|
-
Author: Christoph Schueler
|
|
8
|
-
Author-email: cpu.gems@googlemail.com
|
|
9
|
-
Requires-Python: >=3.10,<4.0
|
|
10
|
-
Classifier: Development Status :: 5 - Production/Stable
|
|
11
|
-
Classifier: Intended Audience :: Developers
|
|
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.10
|
|
16
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
-
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
20
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
21
|
-
Classifier: Topic :: Scientific/Engineering
|
|
22
|
-
Classifier: Topic :: Software Development
|
|
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 (>=2025.2,<2026.0)
|
|
31
|
-
Requires-Dist: pyusb (>=1.2.1,<2.0.0)
|
|
32
|
-
Requires-Dist: rich (>=14.0.0,<15.0.0)
|
|
33
|
-
Requires-Dist: toml (>=0.10.2,<0.11.0)
|
|
34
|
-
Requires-Dist: tomlkit (>=0.13.3,<0.14.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
|
|
38
|
-
Description-Content-Type: text/markdown
|
|
39
|
-
|
|
40
|
-
# pyXCP
|
|
41
|
-
|
|
42
|
-
[](https://app.codacy.com/app/christoph2/pyxcp?utm_source=github.com&utm_medium=referral&utm_content=christoph2/pyxcp&utm_campaign=Badge_Grade_Settings)
|
|
43
|
-
[](https://codeclimate.com/github/christoph2/pyxcp/maintainability)
|
|
44
|
-
[](https://github.com/christoph2/pyxcp/actions)
|
|
45
|
-
[](https://ci.appveyor.com/project/christoph2/pyxcp)
|
|
46
|
-
[](https://coveralls.io/github/christoph2/pyxcp?branch=master)
|
|
47
|
-
[](https://github.com/psf/black)
|
|
48
|
-
[](http://opensource.org/licenses/GPL-2.0)
|
|
49
|
-
|
|
50
|
-
pyXCP is a lightweight Python library which talks to ASAM MCD-1 XCP enabled devices.
|
|
51
|
-
These are mainly, but not only, automotive ECUs (Electronic Control Units).
|
|
52
|
-
|
|
53
|
-
XCP is used to take measurements, to adjust parameters, and to flash during the development process.
|
|
54
|
-
|
|
55
|
-
XCP also replaces the older CCP (CAN Calibration Protocol).
|
|
56
|
-
|
|
57
|
-
---
|
|
58
|
-
|
|
59
|
-
## Installation
|
|
60
|
-
|
|
61
|
-
pyXCP is hosted on Github, get the latest release: [https://github.com/christoph2/pyxcp](https://github.com/christoph2/pyxcp)
|
|
62
|
-
|
|
63
|
-
You can install pyxcp from source:
|
|
64
|
-
|
|
65
|
-
```
|
|
66
|
-
pip install -r requirements.txt
|
|
67
|
-
python setup.py install
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
Alternatively, you can install pyxcp from source with pip:
|
|
71
|
-
|
|
72
|
-
```
|
|
73
|
-
pip install git+https://github.com/christoph2/pyxcp.git
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
Alternatively, get pyxcp from [PyPI](https://pypi.org/project/pyxcp/):
|
|
77
|
-
|
|
78
|
-
```
|
|
79
|
-
pip install pyxcp
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
### Requirements
|
|
83
|
-
|
|
84
|
-
- Python >= 3.7
|
|
85
|
-
- A running XCP slave (of course).
|
|
86
|
-
- If you are using a 64bit Windows version and want to use seed-and-key .dlls (to unlock resources), a GCC compiler capable of creating 32bit
|
|
87
|
-
executables is required:
|
|
88
|
-
|
|
89
|
-
These .dlls almost always ship as 32bit versions, but you can't load a 32bit .dll into a 64bit process, so a small bridging program (asamkeydll.exe) is
|
|
90
|
-
required.
|
|
91
|
-
|
|
92
|
-
## First steps
|
|
93
|
-
|
|
94
|
-
T.B.D.
|
|
95
|
-
|
|
96
|
-
## Features
|
|
97
|
-
|
|
98
|
-
T.B.D.
|
|
99
|
-
|
|
100
|
-
## References
|
|
101
|
-
|
|
102
|
-
- [Offical home of XCP](https://www.asam.net/standards/detail/mcd-1-xcp/)
|
|
103
|
-
|
|
104
|
-
## License
|
|
105
|
-
|
|
106
|
-
GNU Lesser General Public License v3 or later (LGPLv3+)
|
|
107
|
-
|
|
File without changes
|
|
File without changes
|
|
File without changes
|