python-can-canpal 0.1.0rc2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. python_can_canpal-0.1.0rc2/LICENSE +25 -0
  2. python_can_canpal-0.1.0rc2/MANIFEST.in +10 -0
  3. python_can_canpal-0.1.0rc2/PKG-INFO +135 -0
  4. python_can_canpal-0.1.0rc2/README.md +114 -0
  5. python_can_canpal-0.1.0rc2/docs/INSTALL.md +105 -0
  6. python_can_canpal-0.1.0rc2/docs/RELEASE.md +61 -0
  7. python_can_canpal-0.1.0rc2/docs/TESTING.md +88 -0
  8. python_can_canpal-0.1.0rc2/docs/hardware-lab.example.json +47 -0
  9. python_can_canpal-0.1.0rc2/native/fake/abi_internal.cpp +113 -0
  10. python_can_canpal-0.1.0rc2/native/fake/abi_probe.cpp +109 -0
  11. python_can_canpal-0.1.0rc2/native/fake/fake.cpp +280 -0
  12. python_can_canpal-0.1.0rc2/native/fake/sdk_smoke.cpp +103 -0
  13. python_can_canpal-0.1.0rc2/native/fake/sdk_smoke.pro +14 -0
  14. python_can_canpal-0.1.0rc2/native/sdk-revision.txt +1 -0
  15. python_can_canpal-0.1.0rc2/pyproject.toml +37 -0
  16. python_can_canpal-0.1.0rc2/setup.cfg +4 -0
  17. python_can_canpal-0.1.0rc2/src/canpal/__init__.py +10 -0
  18. python_can_canpal-0.1.0rc2/src/canpal/bus.py +312 -0
  19. python_can_canpal-0.1.0rc2/src/canpal/codec.py +110 -0
  20. python_can_canpal-0.1.0rc2/src/canpal/discovery.py +66 -0
  21. python_can_canpal-0.1.0rc2/src/canpal/native.py +187 -0
  22. python_can_canpal-0.1.0rc2/src/python_can_canpal.egg-info/PKG-INFO +135 -0
  23. python_can_canpal-0.1.0rc2/src/python_can_canpal.egg-info/SOURCES.txt +37 -0
  24. python_can_canpal-0.1.0rc2/src/python_can_canpal.egg-info/dependency_links.txt +1 -0
  25. python_can_canpal-0.1.0rc2/src/python_can_canpal.egg-info/entry_points.txt +2 -0
  26. python_can_canpal-0.1.0rc2/src/python_can_canpal.egg-info/requires.txt +7 -0
  27. python_can_canpal-0.1.0rc2/src/python_can_canpal.egg-info/top_level.txt +1 -0
  28. python_can_canpal-0.1.0rc2/tests/conftest.py +99 -0
  29. python_can_canpal-0.1.0rc2/tests/test_bus.py +279 -0
  30. python_can_canpal-0.1.0rc2/tests/test_codec.py +91 -0
  31. python_can_canpal-0.1.0rc2/tests/test_ecosystem.py +154 -0
  32. python_can_canpal-0.1.0rc2/tests/test_hardware.py +372 -0
  33. python_can_canpal-0.1.0rc2/tests/test_release_check.py +346 -0
  34. python_can_canpal-0.1.0rc2/tests/test_sdk_source.py +50 -0
  35. python_can_canpal-0.1.0rc2/tools/build_fake.py +51 -0
  36. python_can_canpal-0.1.0rc2/tools/build_sdk.py +96 -0
  37. python_can_canpal-0.1.0rc2/tools/inspect_devices.py +62 -0
  38. python_can_canpal-0.1.0rc2/tools/release_check.py +301 -0
  39. python_can_canpal-0.1.0rc2/tools/sdk_source.py +41 -0
@@ -0,0 +1,25 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Python CANPAL contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
23
+ This license applies to the newly developed PythonCAN plugin, test harness,
24
+ and documentation. The separately supplied CANPAL SDK, its headers, firmware,
25
+ Qt, and other third-party components retain their respective licenses.
@@ -0,0 +1,10 @@
1
+ include LICENSE README.md pyproject.toml
2
+ include docs/INSTALL.md docs/TESTING.md docs/RELEASE.md docs/hardware-lab.example.json
3
+ recursive-include native/fake *.cpp *.pro
4
+ include native/sdk-revision.txt
5
+ include tools/sdk_source.py tools/build_fake.py tools/build_sdk.py tools/inspect_devices.py tools/release_check.py
6
+ recursive-include tests *.py
7
+ prune build
8
+ prune dist
9
+ prune artifacts
10
+ exclude PLAN.zh-CN.md
@@ -0,0 +1,135 @@
1
+ Metadata-Version: 2.4
2
+ Name: python-can-canpal
3
+ Version: 0.1.0rc2
4
+ Summary: CANPAL USB and TCP backend for python-can
5
+ License-Expression: MIT
6
+ Classifier: Development Status :: 4 - Beta
7
+ Classifier: Programming Language :: Python :: 3.12
8
+ Classifier: Operating System :: Microsoft :: Windows
9
+ Classifier: Operating System :: POSIX :: Linux
10
+ Classifier: Topic :: System :: Hardware :: Hardware Drivers
11
+ Requires-Python: <3.13,>=3.12
12
+ Description-Content-Type: text/markdown
13
+ License-File: LICENSE
14
+ Requires-Dist: python-can==4.6.1
15
+ Requires-Dist: pyserial==3.5
16
+ Provides-Extra: test
17
+ Requires-Dist: pytest<10,>=8; extra == "test"
18
+ Requires-Dist: build<2,>=1; extra == "test"
19
+ Requires-Dist: twine<8,>=6; extra == "test"
20
+ Dynamic: license-file
21
+
22
+ # python-can-canpal
23
+
24
+ CANPAL USB and TCP client backend for [python-can](https://python-can.readthedocs.io/).
25
+
26
+ **0.1.0rc2 is an experimental preview. Full hardware release acceptance is incomplete.**
27
+ Use it for evaluation on an isolated test bench. It is not the qualified 0.1.0 release.
28
+
29
+ ## Install
30
+
31
+ Requires Python 3.12, python-can 4.6.1, pySerial 3.5, and a separately supplied
32
+ 64-bit CANPAL native SDK with the fixes described below.
33
+
34
+ ```text
35
+ python -m pip install python-can-canpal==0.1.0rc2
36
+ ```
37
+
38
+ The Python package does **not** include the CANPAL SDK, firmware, device drivers,
39
+ Qt/MinGW runtime, or fake binaries. Obtain compatible native components from your
40
+ CANPAL supplier before attempting hardware access. The MIT license applies to
41
+ the new Python plugin, tests and documentation; native components have separate licenses.
42
+
43
+ ## What has been verified
44
+
45
+ | Environment | Preview evidence |
46
+ | --- | --- |
47
+ | Windows 11 x64 | X5 classic CAN/RTR and X6 classic CAN/RTR/ISO FD over USB and explicit-IP WLAN TCP |
48
+ | Windows, multiple devices | Two USB devices, X5 USB + X6 WLAN, X5 WLAN + X6 USB; five reopen cycles per device/transport |
49
+ | Ubuntu 24.04 x86_64 in Hyper-V | Native Linux SDK with two USB devices through USB/IP; ttyACM number swap with UID selection; TCP checks through temporary SSH forwarding via Windows WLAN |
50
+
51
+ Both devices had CAN1 wired to their own CAN2 on separate physical buses.
52
+ These checks do not use an independent reference CAN interface. Classic checks
53
+ covered standard/extended frames and RTR DLC 0–8 in both directions. X6 FD checks
54
+ covered lengths 0–64 and BRS off/on. The current SDK checks verified 19,680 frames
55
+ and 20 Windows reopen cycles. Of these, 4,384 frames were verified on Linux USB
56
+ using usbipd-win 5.3.0 and Linux CDC ACM. Reversing attachment order swapped
57
+ ttyACM0/ttyACM1 while UID selection still found the correct X5 and X6.
58
+
59
+ SDK software regressions passed 170 assertions on each of Windows x64, Windows
60
+ x86, and Ubuntu x86_64, plus two Linux ThreadSanitizer checks. Windows x86 SDK
61
+ checks do not qualify a 32-bit Python plugin configuration.
62
+
63
+ **Not yet qualified:** independent-reference CAN/CAN FD interoperability, physical
64
+ Linux host USB controllers, direct Linux WLAN, two simultaneous WLAN devices,
65
+ full repeated physical renumbering/disconnection acceptance, rated-load/endurance
66
+ runs, and native resource stability. Formal 0.1.0 retains the complete release
67
+ acceptance requirements.
68
+
69
+ ## Native SDK and firmware requirements
70
+
71
+ Request **CANPAL native SDK build `663eda8`** from your CANPAL supplier through
72
+ the existing supplier channel. Windows x64 and Ubuntu 24.04 x86_64 runtime bundles
73
+ are supplied on request, separately from PyPI. Match the binary SHA256 below and
74
+ the bundle manifest before use; updating this Python package alone does not
75
+ update your installed native SDK.
76
+
77
+ The pinned source revision is `663eda823be0533754123695405033b38e115489`. It adds
78
+ stricter CAN ACK validation, TCP buffered-read handling, immediate OBD write-error
79
+ propagation, UDS source filtering, and synchronized command handoff. It also
80
+ includes cooperative worker shutdown and the Qt serial buffered-read fix.
81
+ The firmware protocol has no transaction sequence, so a delayed ACK for an
82
+ identical earlier request cannot be distinguished by the echoed fields alone.
83
+
84
+ | Runtime file | SHA256 |
85
+ | --- | --- |
86
+ | Windows x64 CANPAL.dll | `c5bf185e71d06171302163d47f9c709b791306ecddf911de464d5b432daa943a` |
87
+ | Ubuntu x86_64 libCANPAL.so | `a7b5d46e50bdb1fa5a580f59f43498fa78a05b959dd2d0c2bd01f9eba242c70d` |
88
+
89
+ Matching exported function names or the SDK version string alone does not identify
90
+ this fixed build. rc2 updates the SDK baseline, validation tooling and documentation;
91
+ its Python runtime behavior is unchanged from rc1.
92
+
93
+ Classic RTR also requires firmware that preserves the received DLC. The original
94
+ X5 firmware reporting `0x0332` and X6 firmware reporting `0x0127` cleared RTR DLC
95
+ to zero. Supplier-signed diagnostic builds fixed this on the two test devices.
96
+ Those builds still report the same version numbers: ask your supplier to identify
97
+ the actual fixed build. The plugin cannot recover DLC that firmware has discarded.
98
+
99
+ Set `CANPAL_LIBRARY` to the absolute DLL/SO path, or pass `library_path`.
100
+ On Windows, `CANPAL_DEPENDENCY_DIRS` may list Qt/MinGW runtime directories,
101
+ separated by semicolons. On Linux, install the matching Qt 5 runtime and grant
102
+ serial-port access through udev or the dialout group.
103
+
104
+ ## Connect by UID or IP
105
+
106
+ ```python
107
+ import can
108
+
109
+ with can.Bus(interface="canpal", ignore_config=True,
110
+ transport="usb", device_id="YOUR_24_HEX_DIGIT_UID",
111
+ channel=0, bitrate=500_000) as bus:
112
+ message = bus.recv(timeout=1)
113
+ ```
114
+
115
+ The device UID remains the selector when a COM/ttyACM number changes. After a
116
+ reconnection, close and recreate the Bus using the same UID; automatic reconnect
117
+ is not implemented. A Linux USB/IP enumeration-order swap has been verified;
118
+ the full repeated physical renumbering acceptance remains pending.
119
+
120
+ Use `transport="wlan", host="192.0.2.10", port=8000` for TCP direct connection.
121
+ The IP and port must match the actual device; no network discovery is attempted.
122
+ Keep `device_id` to verify identity at that endpoint. X6 CAN FD additionally uses
123
+ `fd=True, data_bitrate=2_000_000`.
124
+
125
+ Different physical devices use independent Bus objects. A device can have one
126
+ Bus and one selected CAN channel at a time. Use one Notifier per device for
127
+ independent fault handling. UDP, server mode, transmit echo and concurrent
128
+ channels on one device are not implemented.
129
+
130
+ A successful `send()` means the native queue accepted the frame, not that the
131
+ CAN bus acknowledged it. Use a single receiver per Bus, stop its Notifier before
132
+ shutdown, and handle python-can exceptions. Timestamp alignment is approximate
133
+ per device and does not provide precise synchronization between devices.
134
+
135
+ The source distribution includes Chinese installation, testing and release notes.
@@ -0,0 +1,114 @@
1
+ # python-can-canpal
2
+
3
+ CANPAL USB and TCP client backend for [python-can](https://python-can.readthedocs.io/).
4
+
5
+ **0.1.0rc2 is an experimental preview. Full hardware release acceptance is incomplete.**
6
+ Use it for evaluation on an isolated test bench. It is not the qualified 0.1.0 release.
7
+
8
+ ## Install
9
+
10
+ Requires Python 3.12, python-can 4.6.1, pySerial 3.5, and a separately supplied
11
+ 64-bit CANPAL native SDK with the fixes described below.
12
+
13
+ ```text
14
+ python -m pip install python-can-canpal==0.1.0rc2
15
+ ```
16
+
17
+ The Python package does **not** include the CANPAL SDK, firmware, device drivers,
18
+ Qt/MinGW runtime, or fake binaries. Obtain compatible native components from your
19
+ CANPAL supplier before attempting hardware access. The MIT license applies to
20
+ the new Python plugin, tests and documentation; native components have separate licenses.
21
+
22
+ ## What has been verified
23
+
24
+ | Environment | Preview evidence |
25
+ | --- | --- |
26
+ | Windows 11 x64 | X5 classic CAN/RTR and X6 classic CAN/RTR/ISO FD over USB and explicit-IP WLAN TCP |
27
+ | Windows, multiple devices | Two USB devices, X5 USB + X6 WLAN, X5 WLAN + X6 USB; five reopen cycles per device/transport |
28
+ | Ubuntu 24.04 x86_64 in Hyper-V | Native Linux SDK with two USB devices through USB/IP; ttyACM number swap with UID selection; TCP checks through temporary SSH forwarding via Windows WLAN |
29
+
30
+ Both devices had CAN1 wired to their own CAN2 on separate physical buses.
31
+ These checks do not use an independent reference CAN interface. Classic checks
32
+ covered standard/extended frames and RTR DLC 0–8 in both directions. X6 FD checks
33
+ covered lengths 0–64 and BRS off/on. The current SDK checks verified 19,680 frames
34
+ and 20 Windows reopen cycles. Of these, 4,384 frames were verified on Linux USB
35
+ using usbipd-win 5.3.0 and Linux CDC ACM. Reversing attachment order swapped
36
+ ttyACM0/ttyACM1 while UID selection still found the correct X5 and X6.
37
+
38
+ SDK software regressions passed 170 assertions on each of Windows x64, Windows
39
+ x86, and Ubuntu x86_64, plus two Linux ThreadSanitizer checks. Windows x86 SDK
40
+ checks do not qualify a 32-bit Python plugin configuration.
41
+
42
+ **Not yet qualified:** independent-reference CAN/CAN FD interoperability, physical
43
+ Linux host USB controllers, direct Linux WLAN, two simultaneous WLAN devices,
44
+ full repeated physical renumbering/disconnection acceptance, rated-load/endurance
45
+ runs, and native resource stability. Formal 0.1.0 retains the complete release
46
+ acceptance requirements.
47
+
48
+ ## Native SDK and firmware requirements
49
+
50
+ Request **CANPAL native SDK build `663eda8`** from your CANPAL supplier through
51
+ the existing supplier channel. Windows x64 and Ubuntu 24.04 x86_64 runtime bundles
52
+ are supplied on request, separately from PyPI. Match the binary SHA256 below and
53
+ the bundle manifest before use; updating this Python package alone does not
54
+ update your installed native SDK.
55
+
56
+ The pinned source revision is `663eda823be0533754123695405033b38e115489`. It adds
57
+ stricter CAN ACK validation, TCP buffered-read handling, immediate OBD write-error
58
+ propagation, UDS source filtering, and synchronized command handoff. It also
59
+ includes cooperative worker shutdown and the Qt serial buffered-read fix.
60
+ The firmware protocol has no transaction sequence, so a delayed ACK for an
61
+ identical earlier request cannot be distinguished by the echoed fields alone.
62
+
63
+ | Runtime file | SHA256 |
64
+ | --- | --- |
65
+ | Windows x64 CANPAL.dll | `c5bf185e71d06171302163d47f9c709b791306ecddf911de464d5b432daa943a` |
66
+ | Ubuntu x86_64 libCANPAL.so | `a7b5d46e50bdb1fa5a580f59f43498fa78a05b959dd2d0c2bd01f9eba242c70d` |
67
+
68
+ Matching exported function names or the SDK version string alone does not identify
69
+ this fixed build. rc2 updates the SDK baseline, validation tooling and documentation;
70
+ its Python runtime behavior is unchanged from rc1.
71
+
72
+ Classic RTR also requires firmware that preserves the received DLC. The original
73
+ X5 firmware reporting `0x0332` and X6 firmware reporting `0x0127` cleared RTR DLC
74
+ to zero. Supplier-signed diagnostic builds fixed this on the two test devices.
75
+ Those builds still report the same version numbers: ask your supplier to identify
76
+ the actual fixed build. The plugin cannot recover DLC that firmware has discarded.
77
+
78
+ Set `CANPAL_LIBRARY` to the absolute DLL/SO path, or pass `library_path`.
79
+ On Windows, `CANPAL_DEPENDENCY_DIRS` may list Qt/MinGW runtime directories,
80
+ separated by semicolons. On Linux, install the matching Qt 5 runtime and grant
81
+ serial-port access through udev or the dialout group.
82
+
83
+ ## Connect by UID or IP
84
+
85
+ ```python
86
+ import can
87
+
88
+ with can.Bus(interface="canpal", ignore_config=True,
89
+ transport="usb", device_id="YOUR_24_HEX_DIGIT_UID",
90
+ channel=0, bitrate=500_000) as bus:
91
+ message = bus.recv(timeout=1)
92
+ ```
93
+
94
+ The device UID remains the selector when a COM/ttyACM number changes. After a
95
+ reconnection, close and recreate the Bus using the same UID; automatic reconnect
96
+ is not implemented. A Linux USB/IP enumeration-order swap has been verified;
97
+ the full repeated physical renumbering acceptance remains pending.
98
+
99
+ Use `transport="wlan", host="192.0.2.10", port=8000` for TCP direct connection.
100
+ The IP and port must match the actual device; no network discovery is attempted.
101
+ Keep `device_id` to verify identity at that endpoint. X6 CAN FD additionally uses
102
+ `fd=True, data_bitrate=2_000_000`.
103
+
104
+ Different physical devices use independent Bus objects. A device can have one
105
+ Bus and one selected CAN channel at a time. Use one Notifier per device for
106
+ independent fault handling. UDP, server mode, transmit echo and concurrent
107
+ channels on one device are not implemented.
108
+
109
+ A successful `send()` means the native queue accepted the frame, not that the
110
+ CAN bus acknowledged it. Use a single receiver per Bus, stop its Notifier before
111
+ shutdown, and handle python-can exceptions. Timestamp alignment is approximate
112
+ per device and does not provide precise synchronization between devices.
113
+
114
+ The source distribution includes Chinese installation, testing and release notes.
@@ -0,0 +1,105 @@
1
+ # 安装与连接
2
+
3
+ 当前 0.1.0rc2 为实验性预览版。正式发布资格以 RELEASE.md 和验收报告为准,构建成功不表示硬件验收完成。
4
+
5
+ ## 环境
6
+
7
+ 首版目标是 Python 3.12、Windows 11 x64 和 Ubuntu 24.04 x86_64。
8
+ python-can 固定 4.6.1,pySerial 固定 3.5。WSL 可用于开发,但不能代替原生 Linux 硬件验收。
9
+
10
+ 安装 Python 包后,还需要单独安装兼容的 CANPAL 原生 SDK、设备驱动和 Qt/编译器运行库。
11
+ 已发布 0.1.0rc1 的验收基线为 e222ccf48f29c530fd09617df6e3a83a8095d25f。
12
+ rc2 的 SDK 基线为 SDK 提交 663eda823be0533754123695405033b38e115489,
13
+ 在协作退出及 Qt 串口缓冲修复上,补充 CAN ACK 校验、TCP 缓冲读取、OBD 写失败返回、UDS 来源过滤与跨线程命令同步。
14
+ Windows x64 DLL 和 Ubuntu 24.04 x86_64 SO 通过现有厂商渠道按需提供;请向供应方索取构建 663eda8,并核对 README 与交付包 manifest.json 中的 SHA256。
15
+ 升级 Python 包不会自动更新 SDK,须替换 CANPAL_LIBRARY 指向的原生文件。
16
+ 旧版 SDK 仅凭导出函数相同不能认定兼容;应使用供应方提供并经过本插件验收的修复版本。
17
+ 原生 SDK、固件和第三方库不包含在 PyPI 包内,也不适用本插件的 MIT 许可证。
18
+
19
+ RTR 接收还需要设备固件保留远程帧 DLC 的修复。已发现的原 X5 0x0332、X6 0x0127
20
+ 会把收到的 RTR DLC 清零;插件不能从接收记录中恢复丢失的值。两台测试设备已刷入
21
+ 修复构建,并通过 USB/WLAN 双向 RTR DLC 0–8 检查。诊断构建仍报告原版本号,
22
+ 因此只比较 SWVer 不足以判断已修复;应向设备供应方确认具体固件构建包含该修复。
23
+
24
+
25
+ ```text
26
+ python -m pip install python-can-canpal==0.1.0rc2
27
+ ```
28
+
29
+ 实际支持范围与未验收项见包首页 README。开发时从源码执行:
30
+
31
+ ```text
32
+ python -m pip install -e ".[test]"
33
+ ```
34
+
35
+ Windows 设置 CANPAL_LIBRARY 为 DLL 绝对路径;若依赖不在 DLL 同目录,
36
+ 可设置 CANPAL_DEPENDENCY_DIRS,多个目录使用分号分隔。
37
+ Linux 设置 CANPAL_LIBRARY 为 SO 绝对路径,通过系统链接器安装 Qt 依赖。
38
+ 也可在 can.Bus 中传 library_path。导入模块不会加载库或打开设备。
39
+
40
+ Linux 串口为 /dev/ttyACM数字;通过 udev 或 dialout 组授予当前用户权限,正常运行不要求 root。
41
+ 首版不接受任意 ttyUSB 路径。WSL 下调用 Windows python.exe 仍属于 Windows 测试。
42
+
43
+ ## USB 与 UID
44
+
45
+ ```python
46
+ import can
47
+
48
+ bus = can.Bus(interface="canpal", ignore_config=True,
49
+ transport="usb", device_id="0123456789abcdef01234567",
50
+ channel=0, bitrate=500_000)
51
+ try:
52
+ print(bus.recv(1))
53
+ finally:
54
+ bus.shutdown()
55
+ ```
56
+
57
+ UID 为实际设备的 12 字节标识,用 24 位十六进制表示。不要把 USB 描述符序列号直接当 UID。
58
+ 插件先枚举 CANPAL VID/PID 端口,再读取原生设备身份;不会发送网络广播。
59
+ 端口改号后关闭并重新创建 Bus,仍使用相同 UID。
60
+
61
+ 可以同时提供 usb_port="COM9" 作为优先探测提示。
62
+ 有 UID 时旧端口不匹配会继续寻找其他候选;仅传 usb_port 则不保证拔插后的设备身份。
63
+ COM1000 等完整编号会被解析,不截取末三位。
64
+
65
+ ## WLAN
66
+
67
+ ```python
68
+ bus = can.Bus(interface="canpal", ignore_config=True,
69
+ transport="wlan", host="192.0.2.10", port=8000,
70
+ channel=0, bitrate=500_000,
71
+ device_id="0123456789abcdef01234567")
72
+ ```
73
+
74
+ IP 与端口必须来自设备实际配置。只支持 PC 为 TCP 客户端、设备为 TCP 服务端的模式。
75
+ 可不传 device_id,但仍会读取真实 UID 并检查本进程是否已经占用。
76
+ IP 直连完全不依赖 UDP/广播发现;无自动重连、监听或 UDP 回退。
77
+
78
+ ## 多设备和 CAN FD
79
+
80
+ 为每台不同 UID 设备创建一个 Bus。每台只能选择一个 CAN 通道。
81
+ 不同设备可使用相同 channel=0 和相同 CAN ID;应用应在监听器或日志中带上来源 UID。
82
+ 每台使用独立 Notifier,避免应用自己把多台设备合并成共享故障处理单元。
83
+
84
+ X6 开启 FD 时提供 fd=True、data_bitrate=2_000_000。
85
+ fd=False 时仍使用 X6 的原生 FD API承载经典帧。
86
+ 完整位时序取自 SDK 的 80/100 MHz 表,由型号和固件版本选择;不支持的速率明确拒绝。
87
+ FD 的非标准物理长度(如 9 字节)会补零到下一合法长度(12),不修改调用者的 Message。
88
+
89
+ 同一个 Bus 只使用一个接收者:直接 recv 或一个 Notifier。
90
+ 需要多个消费者时在该 Notifier 上增加监听器,不要并发调用 recv。
91
+
92
+ ## 行为与排错
93
+
94
+ - send 成功表示原生队列接受,不表示线缆 ACK 或对端收到;Python 不自动重发。
95
+ - send 的 timeout 只约束进入原生调用之前的本地等待;不能取消在途 DLL 调用。
96
+ - recv(None) 等待至收到消息、关闭或离线;软件过滤使用 python-can 基类。
97
+ - 收发时的故障转换为标准 python-can 异常。关闭应用前先停止 Notifier。
98
+ - 设备配置会临时关闭硬件过滤、自动发送、桥接和 spy 功能;不调用保存设置,不写非易失存储。
99
+ - termination=None 保留读取到的终端电阻;True/False 显式设置,listen_only=True 禁止发送。
100
+ - 周期发送使用上游实现,停止后睡眠线程可能在当前周期结束时才退出;关闭后不会再次进入原生发送。
101
+ - 时间戳是每设备初始化采样后的相对换算,含连接采样误差,不提供多设备精确时间同步。
102
+ - 配置失败后关闭本次连接;不在不确定的命令流上继续发送配置或回滚命令。
103
+ - “找不到库”检查绝对路径、64 位架构和 Qt/运行库依赖;禁止用 fake 库处理真实设备。
104
+ - “未找到或不可访问”检查 UID、串口权限、其他进程占用和实际 USB 型号。
105
+ - 本进程 UID 去重不能协调其他应用;同一物理设备应由一个应用独占。
@@ -0,0 +1,61 @@
1
+ # PyPI 发布流程
2
+
3
+ 用户已指定公开 PyPI,包名 python-can-canpal,新插件代码使用 MIT。
4
+ 原生 SDK、头文件、固件与 Qt 不纳入 Python 发布包;其许可独立。
5
+
6
+ 用户已批准先公开发布明确限界的 0.1.0rc1 预览版。版本号本身不代表上传成功或正式验收完成。
7
+ 正式 0.1.0 必须完成既定双平台硬件矩阵;没有硬件证据时停止在候选产物阶段。
8
+
9
+ 1. 完成 Windows/Python 3.12 和 Linux/Python 3.12 无硬件回归、三方 ABI、真实 SDK 回归。
10
+ 2. 在 Windows 11 x64 与原生 Ubuntu 24.04 x86_64 运行完整硬件 release profile。
11
+ 3. 核对 26 组验收、资源计数、实际设备能力、失败记录及支持矩阵。未运行、skip、xfail 均未完成。
12
+ 4. 冻结最终代码、SDK 构建哈希、包版本;清洁环境从 sdist 重建 wheel 并安装验证。
13
+ 5. 运行 python -m twine check dist/*,审计包内文件,不包含 fake 二进制、私有端点、凭据或 SDK。
14
+ 6. 用 tools/release_check.py 检查最终产物和全部证据。任何缺项返回非零。
15
+ 7. 通过已有 PyPI 账号的安全凭据或可信发布完成上传;不要把 token 写进源码、日志或聊天。
16
+ 8. 从 PyPI JSON 核对版本和 SHA256,并在干净环境从 PyPI 安装该精确版本验证入口和依赖。
17
+
18
+ 发布授权已经给出,不再额外要求一次重复批准。凭据或硬件信息缺失时需要用户补充;
19
+ 未通过验收不能将候选包上传后称为正式完成。
20
+ 新建公网仓库、上传原生 SDK 或更改 SDK 许可不包含在此发布动作中。
21
+
22
+ 环境及原始报告位于本地 artifacts,默认不随 PyPI 包发布。内部 release-evidence.json
23
+ 必须列出最终产物 SHA256、四份无跳过的测试报告(两平台 unit/hardware)、两平台 SDK 回归,
24
+ 以及 26 项验收的证据文件。模板允许完整保留 pending 状态。
25
+
26
+ ## 0.1.0rc1 预览版例外
27
+
28
+ 本次例外来自用户明确选择“先发布明确限界的预览版 0.1.0rc1”。
29
+ 只允许该预发布版本:README/PyPI 必须列出已验证平台/组合、未验收项目及修复版 SDK/固件要求。
30
+ 两平台软件、ABI、真实 SDK 回归和干净安装必须通过;两台刷写后的 12 组补充实机报告必须通过且哈希匹配。
31
+ 包内禁止分发原生库、固件、凭据和内部验收资料。正式版检查器默认行为保持完整门槛。
32
+
33
+ ```text
34
+ python tools/release_check.py --profile preview --evidence artifacts/release-evidence.json --dist dist
35
+ ```
36
+
37
+ 预览版检查只对本次明确授权的 0.1.0rc1 生效;不将未运行的正式硬件测试标为通过。
38
+ 上传后须核对 PyPI 的两份分发文件哈希,并从公共索引在干净环境安装精确版本。
39
+ 正式版继续使用默认 release profile,仍需完整双平台矩阵、独立参考设备和额定/长时间验收。
40
+
41
+ ## 0.1.0rc2 预览版
42
+
43
+ rc2 已获执行授权,继续保持预览版范围。原生 SDK 构建 663eda8 由用户通过现有厂商渠道按需提供;Python 包说明应明确索取方式及两平台 SDK 文件哈希。
44
+
45
+ rc2 检查器使用独立规则,不扩大 rc1 例外,也不改变正式版门槛。它要求:
46
+
47
+ - 两平台 unit、installed、真实 SDK JUnit 无失败或跳过;
48
+ - SDK 固定提交、实际 DLL/SO、SDK 构建上下文和交付 ZIP 内文件一致;
49
+ - 两平台干净安装上下文绑定最终 wheel 哈希、SDK 哈希、版本和插件入口;
50
+ - Windows x64/x86、Linux 各 170 项回归,以及 Linux TSan 两项检查通过;
51
+ - 12 份指定收发报告使用交付 SDK,其中 Linux 双 USB 报告必须显示同一 UID 的端口确实变化;
52
+ - X5/X6 各 USB/WLAN 五次重新打开报告通过;
53
+ - SDK 获取方式可用,wheel/sdist 的版本、哈希和预览版限制说明正确。
54
+
55
+ 仅版本号、文档和发布工具变化时可复用与交付 SDK 哈希完全一致的实机报告;运行时代码或 SDK 二进制变化则重新验证受影响路径。
56
+
57
+ ```text
58
+ python tools/release_check.py --profile preview --evidence artifacts/rc2-release/release-evidence.json --dist dist/0.1.0rc2
59
+ ```
60
+
61
+ 从最终 sdist 在干净构建环境生成 wheel,再在 Windows 与 Ubuntu 的干净环境安装测试。上传后核对公共 PyPI JSON 中两个文件的 SHA256,分别安装精确版本验证插件入口及短程实机收发。SDK、固件、Qt/MinGW 运行库仍不进入 Python 包,MIT 范围不变。
@@ -0,0 +1,88 @@
1
+ # 自动化测试与真实验收
2
+
3
+ ## 本地回归
4
+
5
+ 从独立安装的、记录提交版本的 CANPALAPI 源码构建 fake:
6
+
7
+ ```text
8
+ python tools/build_fake.py --sdk /path/to/CANPALAPI --compiler /path/to/g++
9
+ python -m pip install -e ".[test]"
10
+ python -m pytest -m "not hardware" --junitxml=artifacts/unit.xml
11
+ ```
12
+
13
+ Windows 的 MinGW 线程运行库目录应加入 CANPAL_DEPENDENCY_DIRS。
14
+ 同一份 C++ fake 导出真实 ABI,模拟四个设备、独立句柄/队列、断线、调用失败及发送阻塞。
15
+ fake 不进入生产 wheel;测试只通过显式路径加载它。
16
+
17
+ 构建脚本生成 abi.json 与 abi-internal.json,分别来自公开头文件与 SDK 实际内部定义;
18
+ 两者必须一致,pytest 再与 ctypes 的所有字段逐一对照。
19
+ SDK 源码不复制进本项目,运行环境和头文件哈希进入内部验收记录。
20
+
21
+ ## 真实 SDK 回归
22
+
23
+ 执行以下命令可复现构建并保存原生 JUnit、二进制哈希及构建日志:
24
+
25
+ ```text
26
+ python tools/build_sdk.py --sdk /path/to/CANPALAPI --qmake /path/to/qmake --make /path/to/make
27
+ ```
28
+
29
+ Windows 使用 MinGW 配套 qmake/mingw32-make,Linux 使用系统 Qt 5 工具。
30
+ 两个构建脚本强制核对 native/sdk-revision.txt 中的 SDK 提交,并拒绝修改过的 SDK 源文件。
31
+ CI 在两平台依次运行上述构建、pytest 和包构建命令,SDK 源码须由其授权渠道提供。
32
+ 再次运行会将旧报告保存到 artifacts/history,保留失败与重跑记录。
33
+ 每次使用独立构建目录,防止 SDK 切换版本后复用旧目标文件;实际 DLL/SO 路径记录在 artifacts/{windows,linux}-sdk-context.json 的 library 字段。
34
+ 版本校验允许生成的二进制、安装器和 IDE 文件变化,仍拒绝修改过的编译输入和新增的根目录源码。
35
+
36
+ native/fake/sdk_smoke.pro 是真实库回归工程,名称所在目录不表示它链接 fake。
37
+ qmake 参数 SDK_ROOT 指向 SDK 源码,SDK_BUILD 指向真实 DLL/SO 和导入库目录。
38
+ 测试包括命令/通道/条目不匹配的 ACK,以及两台设备对象同时存在时 200 次线程协作回收。
39
+ Linux 还使用真实 Qt 串口与伪终端:先缓冲 128 字节,再停止输入,分批读完,防止等待新数据时遗漏已缓冲数据。
40
+ 伪终端没有 DTR 引脚,因此夹具直接打开 Qt 串口,只检查生产 process() 读取路径;真实设备的 DTR 初始化仍须通过 USB 硬件验收。
41
+ 这项测试已验证修复前失败、修复后通过。以上回归不打开真实 CAN 设备,不能替代连接故障和硬件验收。
42
+
43
+ 固定版本 SDK 另提供 tests/regression/run.py:170 项原生断言覆盖 ACK 字段与超时、TCP 缓冲边界、OBD 重试、UDS ExpectedMask 和双设备命令交接;Linux --tsan 检查线程生命周期与命令同步。该套件的源码快照、提交号、编译器、库哈希和 JUnit 应一并保存。
44
+
45
+ ## 硬件配置
46
+
47
+ 复制 hardware-lab.example.json 到不纳入版本管理的内部位置,并填写:
48
+
49
+ - 独立且已隔离的测试总线确认、真实 SDK 路径、至少两台设备 UID 和网络端点;
50
+ - 每台的独立参考 CAN 接口,不能用 canpal 或 virtual 作为参考;
51
+ - 两条隔离物理 CAN 网络及各自终端电阻/位时序;
52
+ - 控制 USB 断开/连接/改号与网络断开的命令数组;
53
+ - 阻断和恢复发现广播的命令数组。
54
+
55
+ 控制脚本由测试台提供,pytest 通过 subprocess 参数数组调用,不使用 shell 展开。
56
+ 命令须同步完成对应动作后返回;不支持的控制不能填写一个空操作来冒充。
57
+ 系统实际 COM/ttyACM 编号必须发生变化,否则不计入改号次数。
58
+
59
+ ```text
60
+ python -m pytest -m hardware --hardware-config /path/to/lab.json --junitxml=artifacts/hardware.xml
61
+ ```
62
+
63
+ profile=smoke 用于短联调,不能放行正式版;profile=release 启用每组合 30 分钟和混合连接两小时运行,
64
+ 以及 10 次改号、每拓扑 5 次断线、USB/TCP 各 20 次重新打开。
65
+ 实际平均发送率至少达到预设 500 fps 的 98%,不在失败后降低目标。
66
+ 硬件套件会验证数据序号、载荷、丢失/重复、跨设备隔离、监听和关闭清理。
67
+ 线缆矩阵逐向校验标准/扩展 ID 的零值和最大值、经典 CAN 的 0–8 字节及 RTR DLC、
68
+ FD 的 0–64 字节和 BRS 开关,并检查完整标志位、DLC、补零和原消息不变。
69
+ 参考接口发送 FD 时使用合法线缆长度;任意长度补零由 CANPAL 发送路径负责验证。
70
+ RTR 没有数据不代表 DLC 必须为零,接收 DLC 与请求不符必须判失败。
71
+ 没有配置时硬件用例明确 skip,完整验收仍未完成。
72
+
73
+ Windows 与原生 Linux 分别执行;WSL 的 release profile 被拒绝。
74
+ Hyper-V 中的 Ubuntu 可运行原生 Linux SDK。USB/IP 透传验收应记录宿主、来宾系统、USB/IP 版本、CDC ACM 端口和设备 UID;它验证 Linux USB 协议栈与真实设备,不能声称已覆盖物理 Linux 主机的 USB 控制器或拔线电气行为。
75
+ 还须保存原生句柄/线程/端口资源计数、广播阻断抓包、型号/固件矩阵及实际重试/时间戳行为记录。
76
+ 这些设备和系统级证据不能由 fake 或 Python 对象数量替代。
77
+
78
+ ## 与方案对应
79
+
80
+ 测试名称中的 T 编号对应 PLAN.zh-CN.md 的 26 组要求。
81
+ 一个用例可能覆盖多组要求,同一组也可能需要 fake、真实库和硬件三种证据。
82
+ 自动化套件成功不是整个需求组自动关闭:尚未实测的型号、固件行为、
83
+ 故障清理和资源观察必须留在发布验收记录中,不允许补填“通过”。
84
+
85
+ 发布前从最终 sdist 构建 wheel,并在干净环境安装、检查 can.interface 入口、运行消息与 fake 回归。
86
+ 最终 SDK 二进制、wheel、sdist、代码提交及报告必须匹配。
87
+
88
+ 0.1.0rc1 和 0.1.0rc2 经用户明确授权采用各自预览版门槛,见 RELEASE.md。预览版补充检查不关闭上述正式硬件验收缺项。
@@ -0,0 +1,47 @@
1
+ {
2
+ "isolated_test_bench": false,
3
+ "profile": "smoke",
4
+ "library_path": "/absolute/path/to/real/CANPAL/library",
5
+ "devices": [
6
+ {
7
+ "device_id": "REPLACE_WITH_24_HEX_UID",
8
+ "channel": 0,
9
+ "fd": false,
10
+ "host": "192.0.2.1",
11
+ "port": 8001,
12
+ "reference": {
13
+ "interface": "pcan",
14
+ "channel": "PCAN_USBBUS1"
15
+ },
16
+ "controls": {
17
+ "disconnect_usb": [],
18
+ "connect_usb": [],
19
+ "remap_usb": [],
20
+ "disconnect_wlan": [],
21
+ "connect_wlan": []
22
+ }
23
+ },
24
+ {
25
+ "device_id": "REPLACE_WITH_24_HEX_UID",
26
+ "channel": 0,
27
+ "fd": true,
28
+ "host": "192.0.2.2",
29
+ "port": 8002,
30
+ "reference": {
31
+ "interface": "pcan",
32
+ "channel": "PCAN_USBBUS2"
33
+ },
34
+ "controls": {
35
+ "disconnect_usb": [],
36
+ "connect_usb": [],
37
+ "remap_usb": [],
38
+ "disconnect_wlan": [],
39
+ "connect_wlan": []
40
+ }
41
+ }
42
+ ],
43
+ "controls": {
44
+ "block_discovery": [],
45
+ "restore_discovery": []
46
+ }
47
+ }