canopen-bench 1.0.170__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.
- canopen_bench-1.0.170/LICENSE +21 -0
- canopen_bench-1.0.170/PKG-INFO +243 -0
- canopen_bench-1.0.170/README.md +198 -0
- canopen_bench-1.0.170/THIRD-PARTY-NOTICES.md +117 -0
- canopen_bench-1.0.170/canopen_bench/__init__.py +43 -0
- canopen_bench-1.0.170/canopen_bench/__main__.py +173 -0
- canopen_bench-1.0.170/canopen_bench/app.py +288 -0
- canopen_bench-1.0.170/canopen_bench/bus/__init__.py +3 -0
- canopen_bench-1.0.170/canopen_bench/bus/canopen_bus.py +830 -0
- canopen_bench-1.0.170/canopen_bench/bus/demo.py +583 -0
- canopen_bench-1.0.170/canopen_bench/bus/interface.py +252 -0
- canopen_bench-1.0.170/canopen_bench/core.py +7983 -0
- canopen_bench-1.0.170/canopen_bench/data.py +171 -0
- canopen_bench-1.0.170/canopen_bench/db.py +192 -0
- canopen_bench-1.0.170/canopen_bench/eds_od.py +228 -0
- canopen_bench-1.0.170/canopen_bench/flows/lss_standard.yaml +27 -0
- canopen_bench-1.0.170/canopen_bench/instruments/__init__.py +265 -0
- canopen_bench-1.0.170/canopen_bench/instruments/owon.py +175 -0
- canopen_bench-1.0.170/canopen_bench/instruments/toellner.py +238 -0
- canopen_bench-1.0.170/canopen_bench/lss.py +172 -0
- canopen_bench-1.0.170/canopen_bench/panels/DemoDevice.panel.yaml +35 -0
- canopen_bench-1.0.170/canopen_bench/panels/standard.panel.yaml +25 -0
- canopen_bench-1.0.170/canopen_bench/panelspec.py +454 -0
- canopen_bench-1.0.170/canopen_bench/plugin.py +782 -0
- canopen_bench-1.0.170/canopen_bench/report.py +870 -0
- canopen_bench-1.0.170/canopen_bench/seed/CiA301Base.eds +139 -0
- canopen_bench-1.0.170/canopen_bench/seed/DemoDevice.eds +261 -0
- canopen_bench-1.0.170/canopen_bench/static/app.js +2939 -0
- canopen_bench-1.0.170/canopen_bench/static/fonts/IBMPlexMono-Medium.woff2 +0 -0
- canopen_bench-1.0.170/canopen_bench/static/fonts/IBMPlexMono-Regular.woff2 +0 -0
- canopen_bench-1.0.170/canopen_bench/static/fonts/IBMPlexMono-SemiBold.woff2 +0 -0
- canopen_bench-1.0.170/canopen_bench/static/fonts/IBMPlexSans-Bold.woff2 +0 -0
- canopen_bench-1.0.170/canopen_bench/static/fonts/IBMPlexSans-Medium.woff2 +0 -0
- canopen_bench-1.0.170/canopen_bench/static/fonts/IBMPlexSans-Regular.woff2 +0 -0
- canopen_bench-1.0.170/canopen_bench/static/fonts/IBMPlexSans-SemiBold.woff2 +0 -0
- canopen_bench-1.0.170/canopen_bench/static/fonts/LICENSE.txt +93 -0
- canopen_bench-1.0.170/canopen_bench/static/index.html +14 -0
- canopen_bench-1.0.170/canopen_bench/static/styles.css +75 -0
- canopen_bench-1.0.170/canopen_bench/static/vendor/preact-htm.module.js +16 -0
- canopen_bench-1.0.170/canopen_bench/symbols.py +317 -0
- canopen_bench-1.0.170/canopen_bench/testReportStyle.css +57 -0
- canopen_bench-1.0.170/canopen_bench/testcases.py +700 -0
- canopen_bench-1.0.170/canopen_bench/usersettings.py +58 -0
- canopen_bench-1.0.170/canopen_bench/values.py +353 -0
- canopen_bench-1.0.170/canopen_bench.egg-info/PKG-INFO +243 -0
- canopen_bench-1.0.170/canopen_bench.egg-info/SOURCES.txt +74 -0
- canopen_bench-1.0.170/canopen_bench.egg-info/dependency_links.txt +1 -0
- canopen_bench-1.0.170/canopen_bench.egg-info/entry_points.txt +2 -0
- canopen_bench-1.0.170/canopen_bench.egg-info/requires.txt +16 -0
- canopen_bench-1.0.170/canopen_bench.egg-info/top_level.txt +1 -0
- canopen_bench-1.0.170/pyproject.toml +104 -0
- canopen_bench-1.0.170/setup.cfg +4 -0
- canopen_bench-1.0.170/tests/test_app.py +331 -0
- canopen_bench-1.0.170/tests/test_canopen_bus.py +824 -0
- canopen_bench-1.0.170/tests/test_core.py +4960 -0
- canopen_bench-1.0.170/tests/test_demo.py +611 -0
- canopen_bench-1.0.170/tests/test_demo_bus.py +63 -0
- canopen_bench-1.0.170/tests/test_dev_commands.py +232 -0
- canopen_bench-1.0.170/tests/test_executor.py +2731 -0
- canopen_bench-1.0.170/tests/test_frontend.py +635 -0
- canopen_bench-1.0.170/tests/test_instruments.py +561 -0
- canopen_bench-1.0.170/tests/test_lss.py +234 -0
- canopen_bench-1.0.170/tests/test_object_info.py +296 -0
- canopen_bench-1.0.170/tests/test_object_units.py +238 -0
- canopen_bench-1.0.170/tests/test_panels.py +1050 -0
- canopen_bench-1.0.170/tests/test_plugins.py +2265 -0
- canopen_bench-1.0.170/tests/test_production.py +235 -0
- canopen_bench-1.0.170/tests/test_repo_hygiene.py +258 -0
- canopen_bench-1.0.170/tests/test_report.py +966 -0
- canopen_bench-1.0.170/tests/test_shutdown_lets_go.py +76 -0
- canopen_bench-1.0.170/tests/test_single_instance.py +70 -0
- canopen_bench-1.0.170/tests/test_symbols.py +338 -0
- canopen_bench-1.0.170/tests/test_teach.py +493 -0
- canopen_bench-1.0.170/tests/test_testcases.py +537 -0
- canopen_bench-1.0.170/tests/test_usersettings.py +155 -0
- canopen_bench-1.0.170/tests/test_values.py +270 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 NobseVomBerg
|
|
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.
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: canopen-bench
|
|
3
|
+
Version: 1.0.170
|
|
4
|
+
Summary: CANopen Bench — web-based test bench and machine control for CANopen devices: scan, SDO access from EDS files, YAML test cases, firmware download, live CAN trace (IXXAT, PCAN, Vector, demo mode without hardware; vendor devices via plugins)
|
|
5
|
+
Author: NobseVomBerg
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/NobseVomBerg/CANopen-Bench
|
|
8
|
+
Project-URL: Issues, https://github.com/NobseVomBerg/CANopen-Bench/issues
|
|
9
|
+
Project-URL: Changelog, https://github.com/NobseVomBerg/CANopen-Bench/blob/main/CHANGELOG.md
|
|
10
|
+
Project-URL: Author, https://unsix.de/projekte.html
|
|
11
|
+
Keywords: canopen,can,can-bus,cia301,eds,test-bench,test-automation,machine-control,sdo,pdo,nmt,lss,firmware-update,python-can,ixxat,pcan,vector
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Environment :: Web Environment
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Intended Audience :: Manufacturing
|
|
16
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
17
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
23
|
+
Classifier: Topic :: Software Development :: Embedded Systems
|
|
24
|
+
Classifier: Topic :: Software Development :: Testing
|
|
25
|
+
Classifier: Topic :: System :: Hardware
|
|
26
|
+
Requires-Python: >=3.10
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
License-File: LICENSE
|
|
29
|
+
License-File: THIRD-PARTY-NOTICES.md
|
|
30
|
+
Requires-Dist: starlette>=0.37
|
|
31
|
+
Requires-Dist: uvicorn>=0.29
|
|
32
|
+
Requires-Dist: websockets>=12
|
|
33
|
+
Requires-Dist: python-can>=4.4
|
|
34
|
+
Requires-Dist: canopen>=2.3
|
|
35
|
+
Requires-Dist: packaging>=23
|
|
36
|
+
Requires-Dist: pyyaml>=6
|
|
37
|
+
Provides-Extra: serial
|
|
38
|
+
Requires-Dist: pyserial>=3.5; extra == "serial"
|
|
39
|
+
Provides-Extra: dev
|
|
40
|
+
Requires-Dist: pytest>=8; extra == "dev"
|
|
41
|
+
Requires-Dist: pytest-cov>=5; extra == "dev"
|
|
42
|
+
Requires-Dist: httpx>=0.27; extra == "dev"
|
|
43
|
+
Requires-Dist: ruff>=0.5; extra == "dev"
|
|
44
|
+
Dynamic: license-file
|
|
45
|
+
|
|
46
|
+
# CANopen Bench
|
|
47
|
+
|
|
48
|
+
Web tool to test and control CANopen devices on a hardware bench — scan,
|
|
49
|
+
object access, system tests, firmware download and a live CAN trace,
|
|
50
|
+
driven by the devices' EDS files. Python backend (Starlette +
|
|
51
|
+
canopen/python-can), no-build frontend (Preact/HTM), one self-contained
|
|
52
|
+
workspace folder per bench.
|
|
53
|
+
|
|
54
|
+

|
|
55
|
+
|
|
56
|
+
## Try it — no hardware needed
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
pip install canopen-bench
|
|
60
|
+
canopen-bench # → http://127.0.0.1:8000
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
No virtualenv needed to just run it. From a clone, `pip install .`
|
|
64
|
+
installs the same thing from the checkout — without `-e`, which installs
|
|
65
|
+
the package for editing, and that is what `## Development` below is for.
|
|
66
|
+
|
|
67
|
+
`canopen-bench` is a shortcut the install writes; the module runs just as
|
|
68
|
+
well by itself, and from a clone's root it runs that checkout:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
python -m canopen_bench # same thing, same options
|
|
72
|
+
python -m canopen_bench --port 8001 --host 0.0.0.0
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Two reasons to prefer it. It runs *this* directory rather than whatever
|
|
76
|
+
`canopen-bench` happens to point at, which matters as soon as a second
|
|
77
|
+
copy or a second virtualenv is around. And it needs only the
|
|
78
|
+
dependencies, not the package itself: `pip install starlette uvicorn
|
|
79
|
+
websockets canopen python-can pyyaml` (the `dependencies` list in
|
|
80
|
+
`pyproject.toml`) and a clone is enough — worth knowing on a bench
|
|
81
|
+
machine where you would rather not install anything.
|
|
82
|
+
|
|
83
|
+
Note the underscore: the distribution is `canopen-bench`, the module is
|
|
84
|
+
`canopen_bench`. `python -m canopen-bench` cannot work — a hyphen is not
|
|
85
|
+
valid in a Python module name.
|
|
86
|
+
|
|
87
|
+
Pick **Demo mode** on the Setup page, **Connect**, **Scan**: virtual
|
|
88
|
+
devices are generated from the bundled `canopen_bench/seed/DemoDevice.eds`
|
|
89
|
+
(installed into
|
|
90
|
+
the workspace on first run). SDO reads/writes are answered from the EDS
|
|
91
|
+
object dictionary — including realistic aborts on out-of-range writes —
|
|
92
|
+
and every access shows up in the Trace like real bus traffic.
|
|
93
|
+
|
|
94
|
+

|
|
95
|
+
|
|
96
|
+
## Features
|
|
97
|
+
|
|
98
|
+
- **Setup** — adapter/bitrate/scan-range, EDS registry with identity
|
|
99
|
+
matching (0x1018), machine control: adopt the bench's expected state,
|
|
100
|
+
scan & verify against it, re-address via exchangeable flow files.
|
|
101
|
+
- **Production view**: a switch to a reduced bench for the end of a line,
|
|
102
|
+
showing the procedures a vendor package ships (flows marked
|
|
103
|
+
`grade: production`, e.g. flash a board) with their firmware choices,
|
|
104
|
+
a Start button, instructions and progress.
|
|
105
|
+
- **Objects** — EDS object browser with read/write, favorites
|
|
106
|
+
(auto-saved), typed RAW rows (SDO / PDO / NMT with per-row node-id),
|
|
107
|
+
last-known values per device serial number.
|
|
108
|
+
- **Tests** — declarative YAML test cases
|
|
109
|
+
(`docs/ablaeufe/testfall-format.md`, examples in
|
|
110
|
+
`examples/testcases/`) executed for real against the selected device.
|
|
111
|
+
A run leaves HTML behind: one file per case, one summary, and a JSON
|
|
112
|
+
sibling. From those, "Overview by variant" folds the last so many days
|
|
113
|
+
into one collapsible section per hardware variant — runs, successes
|
|
114
|
+
and last verdict per case — which is how you tell one broken variant
|
|
115
|
+
from a broken device family.
|
|
116
|
+
- **Bench instruments** — a remote-controllable lab power supply is set
|
|
117
|
+
from the Setup page and from a test case (`psu` step), which is what
|
|
118
|
+
keeps an under-voltage case automated instead of asking an operator to
|
|
119
|
+
turn a knob. Serial port, `pip install ".[serial]"`; drivers in
|
|
120
|
+
`canopen_bench/instruments/`.
|
|
121
|
+
- **SWDL** — firmware download; the files come from a folder you point at
|
|
122
|
+
(often the firmware project's build output, drag & drop works too), and
|
|
123
|
+
what each one is comes from the extension that knows the format.
|
|
124
|
+
Download protocols are manufacturer-specific and ship as vendor
|
|
125
|
+
extension packages (see the note on the page).
|
|
126
|
+
- **Trace** — live monitor, newest frame at the top, scrollable back
|
|
127
|
+
through the whole 200k-frame ring buffer or an opened capture rather
|
|
128
|
+
than a screenful. Class + device filters, ms/µs timestamps, capture
|
|
129
|
+
save/load, and autosave — every recorded frame written to a capture
|
|
130
|
+
file as it arrives, kept for two weeks, for the endurance runs that are
|
|
131
|
+
longer than the ring is deep.
|
|
132
|
+
|
|
133
|
+
## Hardware
|
|
134
|
+
|
|
135
|
+
Which adapters the tool talks to, via python-can. Names are the
|
|
136
|
+
manufacturers' — see the trademark note in `THIRD-PARTY-NOTICES.md`;
|
|
137
|
+
this project is not affiliated with any of them, and the table says what
|
|
138
|
+
has been exercised, not what is warranted.
|
|
139
|
+
|
|
140
|
+
| Adapter | Driver | State |
|
|
141
|
+
|---|---|---|
|
|
142
|
+
| IXXAT USB-to-CAN | VCI4 (Windows) | in regular use on the author's bench |
|
|
143
|
+
| PCAN-USB | PCANBasic | wired up, never run — no such adapter here |
|
|
144
|
+
| Vector VN1600 (VN1610/VN1630) | XL driver (Windows) | run against a VN1630 |
|
|
145
|
+
| Demo mode | — | no hardware, EDS-driven simulation |
|
|
146
|
+
| other adapters (e.g. CPC-USB) | via plugin packages | separate install |
|
|
147
|
+
|
|
148
|
+
Everything above demo mode goes through python-can's own backends, so
|
|
149
|
+
adapter support tracks python-can. The Vector entry exists because plain
|
|
150
|
+
CAN on a VN1600 needs only Vector's freely downloadable XL driver — the
|
|
151
|
+
CANoe/CANalyzer licences are for their applications, not for talking to
|
|
152
|
+
the hardware — and a lot of that hardware outlives the software budget
|
|
153
|
+
it was bought with. Bring-up checklists live in
|
|
154
|
+
`docs/ablaeufe/A-01-verbinden.md` and `A-02-scan.md`.
|
|
155
|
+
|
|
156
|
+
## Workspaces
|
|
157
|
+
|
|
158
|
+
Every subfolder of the data folder is one workspace: its own sqlite db,
|
|
159
|
+
EDS files, trace captures and flow files. Create and switch workspaces on
|
|
160
|
+
the Setup page; copy a folder to clone or back up a bench. The data folder
|
|
161
|
+
is chosen under Setup > Folders and kept per user (`%APPDATA%\CANopen-Bench`,
|
|
162
|
+
`~/.config/canopen-bench`), so the bench finds it wherever it is started
|
|
163
|
+
from; on the first start it is `./data` where there is one, else
|
|
164
|
+
`~/CANopen-Bench`. `--data <folder>` names it for one start (a second bench
|
|
165
|
+
beside the everyday one, a mounted Docker volume). `--db <path>` remains as an expert override for a
|
|
166
|
+
single explicit database file.
|
|
167
|
+
|
|
168
|
+
Flows and EDS files a package ships are written over in the workspace on
|
|
169
|
+
every start, like its test cases: an update arrives without anybody
|
|
170
|
+
looking for the old copy. A file of one's own goes in under another name.
|
|
171
|
+
|
|
172
|
+
## Docker
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
docker build -t canopen-bench .
|
|
176
|
+
docker run -p 8000:8000 -v canopen-bench:/data canopen-bench
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
All workspaces live on the `/data` volume. Demo mode works out of the
|
|
180
|
+
box; USB CAN adapters need the device passed through
|
|
181
|
+
(`--device=/dev/bus/usb`). The tool has no authentication — keep the
|
|
182
|
+
port on a trusted network (see `SECURITY.md`).
|
|
183
|
+
|
|
184
|
+
## Extending
|
|
185
|
+
|
|
186
|
+
Vendor- and device-specific functionality (adapter cards, EDS seeds,
|
|
187
|
+
firmware catalogs, addressing procedures with session identities, demo
|
|
188
|
+
protocol simulations, trace decoders, EMCY code tables, custom
|
|
189
|
+
test-step primitives, SWDL strategies) lives in separate pip packages
|
|
190
|
+
registered under the
|
|
191
|
+
`canopen_bench.plugins` entry-point group — installing one activates it.
|
|
192
|
+
In multi-workspace mode this needs no shell at all: Setup > Extensions
|
|
193
|
+
installs a plugin package (`.whl`) straight from the browser, active
|
|
194
|
+
immediately — its own dependencies are not installed with it, and the
|
|
195
|
+
state log names any this Python lacks, with the pip command that adds
|
|
196
|
+
them. Guide with hook table and a minimal example:
|
|
197
|
+
`docs/extending.md`; API: `canopen_bench/plugin.py`. A complete worked
|
|
198
|
+
example ships in this repo under
|
|
199
|
+
[`plugins/cob-cpcusb/`](https://github.com/NobseVomBerg/CANopen-Bench/tree/main/plugins/cob-cpcusb) — python-can driver plus
|
|
200
|
+
adapter card, its own tests, MIT. It is a separate distribution, not part
|
|
201
|
+
of the `canopen-bench` package: install it only if you have that
|
|
202
|
+
adapter.
|
|
203
|
+
|
|
204
|
+
## Documentation
|
|
205
|
+
|
|
206
|
+
- `IMPLEMENTATION.md` — architecture and design decisions
|
|
207
|
+
- `CONTRIBUTING.md` — dev setup, test conventions, what goes where
|
|
208
|
+
- `docs/extending.md` — plugin guide
|
|
209
|
+
- `docs/ablaeufe/` — operational sequence specs (German)
|
|
210
|
+
- `docs/ablaeufe/testfall-format.md` — YAML test-case format
|
|
211
|
+
|
|
212
|
+
## Development
|
|
213
|
+
|
|
214
|
+
```bash
|
|
215
|
+
python -m venv .venv && . .venv/bin/activate
|
|
216
|
+
pip install -e ".[dev]" # editable + pytest/ruff
|
|
217
|
+
pytest # core suite
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
`CONTRIBUTING.md` has the rest: what CI checks, where things belong, the
|
|
221
|
+
versioning rule.
|
|
222
|
+
|
|
223
|
+
Behind a TLS-inspecting corporate proxy, pip fails with
|
|
224
|
+
`CERTIFICATE_VERIFY_FAILED` on pypi.org: the proxy's CA is trusted by the
|
|
225
|
+
operating system but not by the certificate bundle Python ships. On
|
|
226
|
+
pip 23.2+, `--use-feature=truststore` makes pip use the OS store
|
|
227
|
+
instead. On older pip that route is closed — it needs the `truststore`
|
|
228
|
+
package, which also comes from pypi.org — so export the OS root
|
|
229
|
+
certificates to a PEM and point pip at it with `--cert`, or set it once
|
|
230
|
+
with `pip config set global.cert <file>`. Either way certificate
|
|
231
|
+
verification stays on.
|
|
232
|
+
|
|
233
|
+
## License & author
|
|
234
|
+
|
|
235
|
+
Core application: MIT (`LICENSE`). Plugin packages are licensed
|
|
236
|
+
independently — vendor plugins proprietary, `cob-cpcusb` MIT.
|
|
237
|
+
Bundled and depended-on third-party components, and the trademark note
|
|
238
|
+
(CANopen® and CiA® belong to CAN in Automation e.V.; this is not a
|
|
239
|
+
CiA-certified or CiA-affiliated tool), are listed in
|
|
240
|
+
[`THIRD-PARTY-NOTICES.md`](https://github.com/NobseVomBerg/CANopen-Bench/blob/main/THIRD-PARTY-NOTICES.md).
|
|
241
|
+
|
|
242
|
+
Created by NobseVomBerg · [unsix.de](https://unsix.de) ·
|
|
243
|
+
[GitHub](https://github.com/NobseVomBerg/CANopen-Bench)
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
# CANopen Bench
|
|
2
|
+
|
|
3
|
+
Web tool to test and control CANopen devices on a hardware bench — scan,
|
|
4
|
+
object access, system tests, firmware download and a live CAN trace,
|
|
5
|
+
driven by the devices' EDS files. Python backend (Starlette +
|
|
6
|
+
canopen/python-can), no-build frontend (Preact/HTM), one self-contained
|
|
7
|
+
workspace folder per bench.
|
|
8
|
+
|
|
9
|
+

|
|
10
|
+
|
|
11
|
+
## Try it — no hardware needed
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pip install canopen-bench
|
|
15
|
+
canopen-bench # → http://127.0.0.1:8000
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
No virtualenv needed to just run it. From a clone, `pip install .`
|
|
19
|
+
installs the same thing from the checkout — without `-e`, which installs
|
|
20
|
+
the package for editing, and that is what `## Development` below is for.
|
|
21
|
+
|
|
22
|
+
`canopen-bench` is a shortcut the install writes; the module runs just as
|
|
23
|
+
well by itself, and from a clone's root it runs that checkout:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
python -m canopen_bench # same thing, same options
|
|
27
|
+
python -m canopen_bench --port 8001 --host 0.0.0.0
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Two reasons to prefer it. It runs *this* directory rather than whatever
|
|
31
|
+
`canopen-bench` happens to point at, which matters as soon as a second
|
|
32
|
+
copy or a second virtualenv is around. And it needs only the
|
|
33
|
+
dependencies, not the package itself: `pip install starlette uvicorn
|
|
34
|
+
websockets canopen python-can pyyaml` (the `dependencies` list in
|
|
35
|
+
`pyproject.toml`) and a clone is enough — worth knowing on a bench
|
|
36
|
+
machine where you would rather not install anything.
|
|
37
|
+
|
|
38
|
+
Note the underscore: the distribution is `canopen-bench`, the module is
|
|
39
|
+
`canopen_bench`. `python -m canopen-bench` cannot work — a hyphen is not
|
|
40
|
+
valid in a Python module name.
|
|
41
|
+
|
|
42
|
+
Pick **Demo mode** on the Setup page, **Connect**, **Scan**: virtual
|
|
43
|
+
devices are generated from the bundled `canopen_bench/seed/DemoDevice.eds`
|
|
44
|
+
(installed into
|
|
45
|
+
the workspace on first run). SDO reads/writes are answered from the EDS
|
|
46
|
+
object dictionary — including realistic aborts on out-of-range writes —
|
|
47
|
+
and every access shows up in the Trace like real bus traffic.
|
|
48
|
+
|
|
49
|
+

|
|
50
|
+
|
|
51
|
+
## Features
|
|
52
|
+
|
|
53
|
+
- **Setup** — adapter/bitrate/scan-range, EDS registry with identity
|
|
54
|
+
matching (0x1018), machine control: adopt the bench's expected state,
|
|
55
|
+
scan & verify against it, re-address via exchangeable flow files.
|
|
56
|
+
- **Production view**: a switch to a reduced bench for the end of a line,
|
|
57
|
+
showing the procedures a vendor package ships (flows marked
|
|
58
|
+
`grade: production`, e.g. flash a board) with their firmware choices,
|
|
59
|
+
a Start button, instructions and progress.
|
|
60
|
+
- **Objects** — EDS object browser with read/write, favorites
|
|
61
|
+
(auto-saved), typed RAW rows (SDO / PDO / NMT with per-row node-id),
|
|
62
|
+
last-known values per device serial number.
|
|
63
|
+
- **Tests** — declarative YAML test cases
|
|
64
|
+
(`docs/ablaeufe/testfall-format.md`, examples in
|
|
65
|
+
`examples/testcases/`) executed for real against the selected device.
|
|
66
|
+
A run leaves HTML behind: one file per case, one summary, and a JSON
|
|
67
|
+
sibling. From those, "Overview by variant" folds the last so many days
|
|
68
|
+
into one collapsible section per hardware variant — runs, successes
|
|
69
|
+
and last verdict per case — which is how you tell one broken variant
|
|
70
|
+
from a broken device family.
|
|
71
|
+
- **Bench instruments** — a remote-controllable lab power supply is set
|
|
72
|
+
from the Setup page and from a test case (`psu` step), which is what
|
|
73
|
+
keeps an under-voltage case automated instead of asking an operator to
|
|
74
|
+
turn a knob. Serial port, `pip install ".[serial]"`; drivers in
|
|
75
|
+
`canopen_bench/instruments/`.
|
|
76
|
+
- **SWDL** — firmware download; the files come from a folder you point at
|
|
77
|
+
(often the firmware project's build output, drag & drop works too), and
|
|
78
|
+
what each one is comes from the extension that knows the format.
|
|
79
|
+
Download protocols are manufacturer-specific and ship as vendor
|
|
80
|
+
extension packages (see the note on the page).
|
|
81
|
+
- **Trace** — live monitor, newest frame at the top, scrollable back
|
|
82
|
+
through the whole 200k-frame ring buffer or an opened capture rather
|
|
83
|
+
than a screenful. Class + device filters, ms/µs timestamps, capture
|
|
84
|
+
save/load, and autosave — every recorded frame written to a capture
|
|
85
|
+
file as it arrives, kept for two weeks, for the endurance runs that are
|
|
86
|
+
longer than the ring is deep.
|
|
87
|
+
|
|
88
|
+
## Hardware
|
|
89
|
+
|
|
90
|
+
Which adapters the tool talks to, via python-can. Names are the
|
|
91
|
+
manufacturers' — see the trademark note in `THIRD-PARTY-NOTICES.md`;
|
|
92
|
+
this project is not affiliated with any of them, and the table says what
|
|
93
|
+
has been exercised, not what is warranted.
|
|
94
|
+
|
|
95
|
+
| Adapter | Driver | State |
|
|
96
|
+
|---|---|---|
|
|
97
|
+
| IXXAT USB-to-CAN | VCI4 (Windows) | in regular use on the author's bench |
|
|
98
|
+
| PCAN-USB | PCANBasic | wired up, never run — no such adapter here |
|
|
99
|
+
| Vector VN1600 (VN1610/VN1630) | XL driver (Windows) | run against a VN1630 |
|
|
100
|
+
| Demo mode | — | no hardware, EDS-driven simulation |
|
|
101
|
+
| other adapters (e.g. CPC-USB) | via plugin packages | separate install |
|
|
102
|
+
|
|
103
|
+
Everything above demo mode goes through python-can's own backends, so
|
|
104
|
+
adapter support tracks python-can. The Vector entry exists because plain
|
|
105
|
+
CAN on a VN1600 needs only Vector's freely downloadable XL driver — the
|
|
106
|
+
CANoe/CANalyzer licences are for their applications, not for talking to
|
|
107
|
+
the hardware — and a lot of that hardware outlives the software budget
|
|
108
|
+
it was bought with. Bring-up checklists live in
|
|
109
|
+
`docs/ablaeufe/A-01-verbinden.md` and `A-02-scan.md`.
|
|
110
|
+
|
|
111
|
+
## Workspaces
|
|
112
|
+
|
|
113
|
+
Every subfolder of the data folder is one workspace: its own sqlite db,
|
|
114
|
+
EDS files, trace captures and flow files. Create and switch workspaces on
|
|
115
|
+
the Setup page; copy a folder to clone or back up a bench. The data folder
|
|
116
|
+
is chosen under Setup > Folders and kept per user (`%APPDATA%\CANopen-Bench`,
|
|
117
|
+
`~/.config/canopen-bench`), so the bench finds it wherever it is started
|
|
118
|
+
from; on the first start it is `./data` where there is one, else
|
|
119
|
+
`~/CANopen-Bench`. `--data <folder>` names it for one start (a second bench
|
|
120
|
+
beside the everyday one, a mounted Docker volume). `--db <path>` remains as an expert override for a
|
|
121
|
+
single explicit database file.
|
|
122
|
+
|
|
123
|
+
Flows and EDS files a package ships are written over in the workspace on
|
|
124
|
+
every start, like its test cases: an update arrives without anybody
|
|
125
|
+
looking for the old copy. A file of one's own goes in under another name.
|
|
126
|
+
|
|
127
|
+
## Docker
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
docker build -t canopen-bench .
|
|
131
|
+
docker run -p 8000:8000 -v canopen-bench:/data canopen-bench
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
All workspaces live on the `/data` volume. Demo mode works out of the
|
|
135
|
+
box; USB CAN adapters need the device passed through
|
|
136
|
+
(`--device=/dev/bus/usb`). The tool has no authentication — keep the
|
|
137
|
+
port on a trusted network (see `SECURITY.md`).
|
|
138
|
+
|
|
139
|
+
## Extending
|
|
140
|
+
|
|
141
|
+
Vendor- and device-specific functionality (adapter cards, EDS seeds,
|
|
142
|
+
firmware catalogs, addressing procedures with session identities, demo
|
|
143
|
+
protocol simulations, trace decoders, EMCY code tables, custom
|
|
144
|
+
test-step primitives, SWDL strategies) lives in separate pip packages
|
|
145
|
+
registered under the
|
|
146
|
+
`canopen_bench.plugins` entry-point group — installing one activates it.
|
|
147
|
+
In multi-workspace mode this needs no shell at all: Setup > Extensions
|
|
148
|
+
installs a plugin package (`.whl`) straight from the browser, active
|
|
149
|
+
immediately — its own dependencies are not installed with it, and the
|
|
150
|
+
state log names any this Python lacks, with the pip command that adds
|
|
151
|
+
them. Guide with hook table and a minimal example:
|
|
152
|
+
`docs/extending.md`; API: `canopen_bench/plugin.py`. A complete worked
|
|
153
|
+
example ships in this repo under
|
|
154
|
+
[`plugins/cob-cpcusb/`](https://github.com/NobseVomBerg/CANopen-Bench/tree/main/plugins/cob-cpcusb) — python-can driver plus
|
|
155
|
+
adapter card, its own tests, MIT. It is a separate distribution, not part
|
|
156
|
+
of the `canopen-bench` package: install it only if you have that
|
|
157
|
+
adapter.
|
|
158
|
+
|
|
159
|
+
## Documentation
|
|
160
|
+
|
|
161
|
+
- `IMPLEMENTATION.md` — architecture and design decisions
|
|
162
|
+
- `CONTRIBUTING.md` — dev setup, test conventions, what goes where
|
|
163
|
+
- `docs/extending.md` — plugin guide
|
|
164
|
+
- `docs/ablaeufe/` — operational sequence specs (German)
|
|
165
|
+
- `docs/ablaeufe/testfall-format.md` — YAML test-case format
|
|
166
|
+
|
|
167
|
+
## Development
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
python -m venv .venv && . .venv/bin/activate
|
|
171
|
+
pip install -e ".[dev]" # editable + pytest/ruff
|
|
172
|
+
pytest # core suite
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
`CONTRIBUTING.md` has the rest: what CI checks, where things belong, the
|
|
176
|
+
versioning rule.
|
|
177
|
+
|
|
178
|
+
Behind a TLS-inspecting corporate proxy, pip fails with
|
|
179
|
+
`CERTIFICATE_VERIFY_FAILED` on pypi.org: the proxy's CA is trusted by the
|
|
180
|
+
operating system but not by the certificate bundle Python ships. On
|
|
181
|
+
pip 23.2+, `--use-feature=truststore` makes pip use the OS store
|
|
182
|
+
instead. On older pip that route is closed — it needs the `truststore`
|
|
183
|
+
package, which also comes from pypi.org — so export the OS root
|
|
184
|
+
certificates to a PEM and point pip at it with `--cert`, or set it once
|
|
185
|
+
with `pip config set global.cert <file>`. Either way certificate
|
|
186
|
+
verification stays on.
|
|
187
|
+
|
|
188
|
+
## License & author
|
|
189
|
+
|
|
190
|
+
Core application: MIT (`LICENSE`). Plugin packages are licensed
|
|
191
|
+
independently — vendor plugins proprietary, `cob-cpcusb` MIT.
|
|
192
|
+
Bundled and depended-on third-party components, and the trademark note
|
|
193
|
+
(CANopen® and CiA® belong to CAN in Automation e.V.; this is not a
|
|
194
|
+
CiA-certified or CiA-affiliated tool), are listed in
|
|
195
|
+
[`THIRD-PARTY-NOTICES.md`](https://github.com/NobseVomBerg/CANopen-Bench/blob/main/THIRD-PARTY-NOTICES.md).
|
|
196
|
+
|
|
197
|
+
Created by NobseVomBerg · [unsix.de](https://unsix.de) ·
|
|
198
|
+
[GitHub](https://github.com/NobseVomBerg/CANopen-Bench)
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# Third-party notices
|
|
2
|
+
|
|
3
|
+
CANopen Bench itself is MIT-licensed (see `LICENSE`). It bundles and
|
|
4
|
+
depends on the components below, which keep their own licenses. This
|
|
5
|
+
file is the attribution required by those licenses; it travels with the
|
|
6
|
+
wheel, the sdist and the Docker image.
|
|
7
|
+
|
|
8
|
+
## Bundled in this repository
|
|
9
|
+
|
|
10
|
+
Shipped as source inside the package (`canopen_bench/static/vendor/`),
|
|
11
|
+
so these notices apply to every copy of CANopen Bench:
|
|
12
|
+
|
|
13
|
+
| Component | License | Copyright |
|
|
14
|
+
|---|---|---|
|
|
15
|
+
| [Preact](https://preactjs.com) | MIT | © 2015-present Jason Miller |
|
|
16
|
+
| [htm](https://github.com/developit/htm) | Apache-2.0 | © 2018 Jason Miller |
|
|
17
|
+
| [IBM Plex](https://github.com/IBM/plex) | OFL-1.1 | © 2017 IBM Corp. |
|
|
18
|
+
|
|
19
|
+
Preact and htm are combined into the single bundle
|
|
20
|
+
`canopen_bench/static/vendor/preact-htm.module.js`, which carries the
|
|
21
|
+
same notices in its file header. The bundle is unmodified upstream
|
|
22
|
+
output — CANopen Bench adds no code to it.
|
|
23
|
+
|
|
24
|
+
### OFL-1.1 (IBM Plex)
|
|
25
|
+
|
|
26
|
+
`canopen_bench/static/fonts/` holds seven woff2 files, IBM's own
|
|
27
|
+
unmodified builds taken from the `@ibm/plex-sans` (1.1.0) and
|
|
28
|
+
`@ibm/plex-mono` (2.5.0) packages. The full license text ships beside
|
|
29
|
+
them as `fonts/LICENSE.txt`, as the OFL requires.
|
|
30
|
+
|
|
31
|
+
The copyright line reserves the font name: *"Copyright © 2017 IBM Corp.
|
|
32
|
+
with Reserved Font Name 'Plex'"*. Bundling the fonts with software of any
|
|
33
|
+
license is explicitly allowed, so shipping them inside this MIT package
|
|
34
|
+
is fine and does not affect its license. What the reserved name does
|
|
35
|
+
forbid is calling a **modified** version Plex — which is why these files
|
|
36
|
+
are shipped whole rather than subsetted to save bandwidth. Anyone
|
|
37
|
+
subsetting or otherwise rebuilding them has to rename the result.
|
|
38
|
+
|
|
39
|
+
### MIT (Preact)
|
|
40
|
+
|
|
41
|
+
> Permission is hereby granted, free of charge, to any person obtaining a
|
|
42
|
+
> copy of this software and associated documentation files (the
|
|
43
|
+
> "Software"), to deal in the Software without restriction, including
|
|
44
|
+
> without limitation the rights to use, copy, modify, merge, publish,
|
|
45
|
+
> distribute, sublicense, and/or sell copies of the Software, and to
|
|
46
|
+
> permit persons to whom the Software is furnished to do so, subject to
|
|
47
|
+
> the following conditions:
|
|
48
|
+
>
|
|
49
|
+
> The above copyright notice and this permission notice shall be included
|
|
50
|
+
> in all copies or substantial portions of the Software.
|
|
51
|
+
>
|
|
52
|
+
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
53
|
+
> OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
54
|
+
> MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
55
|
+
> IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
56
|
+
> CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
57
|
+
> TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
58
|
+
> SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
59
|
+
|
|
60
|
+
### Apache-2.0 (htm)
|
|
61
|
+
|
|
62
|
+
Licensed under the Apache License, Version 2.0. You may obtain a copy of
|
|
63
|
+
the License at <http://www.apache.org/licenses/LICENSE-2.0>. Unless
|
|
64
|
+
required by applicable law or agreed to in writing, software distributed
|
|
65
|
+
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
|
|
66
|
+
OR CONDITIONS OF ANY KIND, either express or implied. See the License for
|
|
67
|
+
the specific language governing permissions and limitations under it.
|
|
68
|
+
|
|
69
|
+
## Runtime dependencies
|
|
70
|
+
|
|
71
|
+
Installed by pip, not vendored — but a Docker image built from this
|
|
72
|
+
repository contains them, and distributing that image distributes them:
|
|
73
|
+
|
|
74
|
+
| Package | License |
|
|
75
|
+
|---|---|
|
|
76
|
+
| [python-can](https://github.com/hardbyte/python-can) | **LGPL-3.0-only** |
|
|
77
|
+
| [canopen](https://github.com/christiansandberg/canopen) | MIT |
|
|
78
|
+
| [Starlette](https://github.com/encode/starlette) | BSD-3-Clause |
|
|
79
|
+
| [Uvicorn](https://github.com/encode/uvicorn) | BSD-3-Clause |
|
|
80
|
+
| [websockets](https://github.com/python-websockets/websockets) | BSD-3-Clause |
|
|
81
|
+
| [PyYAML](https://github.com/yaml/pyyaml) | MIT |
|
|
82
|
+
| [packaging](https://github.com/pypa/packaging) | Apache-2.0 OR BSD-2-Clause |
|
|
83
|
+
|
|
84
|
+
**python-can is LGPL-3.0.** CANopen Bench imports it as an unmodified
|
|
85
|
+
library and neither copies nor modifies its source, so the LGPL's
|
|
86
|
+
obligations attach to python-can alone, not to CANopen Bench. If you
|
|
87
|
+
redistribute a Docker image or any other bundle built from this
|
|
88
|
+
repository, you are conveying python-can and must pass on its license
|
|
89
|
+
text and let recipients replace it with a modified version — with a
|
|
90
|
+
pip-installed package that is already the case, since it can simply be
|
|
91
|
+
reinstalled.
|
|
92
|
+
|
|
93
|
+
## Plugin packages
|
|
94
|
+
|
|
95
|
+
Plugins are separate distributions with their own licensing; installing
|
|
96
|
+
one does not change the license of this package. The public
|
|
97
|
+
[`cob-cpcusb`](plugins/cob-cpcusb/)
|
|
98
|
+
is MIT. Check each plugin's own `LICENSE` before redistributing an
|
|
99
|
+
environment that contains it — a copyleft or proprietary plugin puts its
|
|
100
|
+
own obligations on that environment.
|
|
101
|
+
|
|
102
|
+
## Trademarks
|
|
103
|
+
|
|
104
|
+
CANopen® and CiA® are registered trademarks of
|
|
105
|
+
[CAN in Automation e.V.](https://www.can-cia.org/) CANopen Bench is an
|
|
106
|
+
independent project and is neither affiliated with, endorsed by, nor
|
|
107
|
+
certified by CAN in Automation. References to CiA specifications
|
|
108
|
+
(CiA 301, CiA 305, CiA 402, …) describe which published behaviour this
|
|
109
|
+
tool implements; they are not a claim of conformance, and this tool is
|
|
110
|
+
not a CiA conformance test tool.
|
|
111
|
+
|
|
112
|
+
IXXAT® is a trademark of HMS Networks. PCAN® is a trademark of
|
|
113
|
+
PEAK-System Technik GmbH. CPC-USB is a product of EMS Dr. Thomas Wünsche.
|
|
114
|
+
All other product names are the property of their respective owners and
|
|
115
|
+
are used here solely to state which hardware this software interoperates
|
|
116
|
+
with. Their use implies no affiliation with or endorsement by those
|
|
117
|
+
companies.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"""CANopen Bench — web tool to test and control CANopen devices."""
|
|
2
|
+
import re
|
|
3
|
+
from importlib.metadata import PackageNotFoundError
|
|
4
|
+
from importlib.metadata import version as _pkg_version
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def _read_version() -> str:
|
|
9
|
+
"""The one place the version is read from.
|
|
10
|
+
|
|
11
|
+
pyproject.toml first: this project bumps the version on every commit
|
|
12
|
+
and does not tag releases, so a source checkout is the normal way to
|
|
13
|
+
run it — and the installed metadata of an editable install goes stale
|
|
14
|
+
until the next `pip install -e`, happily reporting an old number.
|
|
15
|
+
Wheel installs have no pyproject next to the package and fall through
|
|
16
|
+
to the (then correct) metadata.
|
|
17
|
+
|
|
18
|
+
The file is scanned for the version line rather than parsed as TOML:
|
|
19
|
+
``tomllib`` only exists from Python 3.11, and on 3.10 falling back to
|
|
20
|
+
the metadata would quietly reintroduce exactly the staleness this
|
|
21
|
+
function exists to avoid. Adding a ``tomli`` dependency to read one
|
|
22
|
+
line is not worth it.
|
|
23
|
+
|
|
24
|
+
Kept in this module rather than in ``core`` so that reading the
|
|
25
|
+
version costs no imports beyond the standard library.
|
|
26
|
+
"""
|
|
27
|
+
try:
|
|
28
|
+
pp = Path(__file__).resolve().parent.parent / "pyproject.toml"
|
|
29
|
+
for line in pp.read_text(encoding="utf-8").splitlines():
|
|
30
|
+
# first `version = "..."` in the file; [project] declares it
|
|
31
|
+
# before any other table can (build-system has no version key)
|
|
32
|
+
match = re.match(r'\s*version\s*=\s*["\'](?P<v>[^"\']+)["\']', line)
|
|
33
|
+
if match:
|
|
34
|
+
return match.group("v")
|
|
35
|
+
except OSError:
|
|
36
|
+
pass
|
|
37
|
+
try:
|
|
38
|
+
return _pkg_version("canopen-bench")
|
|
39
|
+
except PackageNotFoundError: # bare checkout without install
|
|
40
|
+
return "dev"
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
__version__ = _read_version()
|