Python Durand - CANopen Responder Device Library
A CANopen library to implement responder nodes.
Backends:
CAN interfaces via python-can
Synopsis
Pure Python implementation
Licensed under MIT (2021 Günther Jena)
Source code hosted on GitHub.com
Tested on Python 3.7, 3.8, 3.9, and 3.10
Unit tested with pytest, coding style enforced with Black, static type checking with mypy, static code analysis with Pylint, documentation generated with Sphinx
Supports CiA301 (EN 50325-4)
Feature List
Object Dictionary:
Provides callbacks for validation, update, download, and read operations
Supports records, arrays, and variables
EDS Support:
Dynamic generation of EDS files
Automatically provided via object 0x1021 (“Store EDS”)
SDO Servers:
Supports up to 128 SDO servers
Expedited, segmented, and block transfer for upload and download
Dynamically configurable COB-IDs
Custom upload and download handlers supported
PDO Support:
Up to 512 TPDOs and 512 RPDOs
Dynamically configurable
Transmission types: synchronous (acyclic and every nth sync) and event-driven
Supports inhibit time
EMCY Producer Service:
Dynamically configurable COB-ID
Supports inhibit time
Heartbeat Producer Service:
Dynamically configurable
NMT Slave Service:
Boot-up service
Callback for state change provided
SYNC Consumer Service:
Dynamically configurable COB-ID
Callback for received sync provided
CiA305 Layer Setting Service:
Supports fast scan
Configurable bitrate and node ID
Identify remote responder supported
CAN Interface Abstraction:
Full support for python-can
Automatic CAN ID filtering by subscribed services
Scheduling:
Supports threaded and async operation
TODO:
Build object dictionary via reading an EDS file
Support MPDOs
TIME consumer service
Up- and download handler as I/O streams
Examples
Creating a Node:
import can
from durand import CANBusNetwork, Node, Variable, Record, DatatypeEnum
bus = can.Bus(bustype='socketcan', channel='vcan0')
network = CANBusNetwork(bus)
node = Node(network, node_id=0x01)
Congratulations! You now have a CiA-301 compliant node running. The Layer Setting Service is also supported out of the box.
Adding Objects:
od = node.object_dictionary
# Add variable at index 0x2000
od[0x2000] = Variable(DatatypeEnum.UNSIGNED16, access='rw', value=10, name='Parameter 1')
# Add record at index 0x2001
record = Record(name='Parameter Record')
record[1] = Variable(DatatypeEnum.UNSIGNED8, access='ro', value=0, name='Parameter 2a')
record[2] = Variable(DatatypeEnum.REAL32, access='rw', value=0, name='Parameter 2b')
od[0x2001] = record
Accessing Values:
The objects can be read and written directly by accessing the object dictionary:
print(f'Value of Parameter 1: {od.read(0x2000, 0)}')
od.write(0x2001, 1, value=0xAA)
Adding Callbacks:
A more event-driven approach is to use callbacks. The following callbacks are available:
validate_callbacks: Called before a value in the object dictionary is updated
update_callbacks: Called when the value has been changed (via od.write or via CAN bus)
download_callbacks: Called when the value has been changed via CAN bus
read_callback: Called when an object is read (return value is used)
od.validate_callbacks[(0x2000, 0)].add(lambda v: v % 2 == 0)
od.update_callbacks[(0x2001, 2)].add(lambda v: print(f'Update for Parameter 2b: {v}'))
od.download_callbacks[(0x2000, 0)].add(lambda v: print(f'Download for Parameter 1: {v}'))
od.set_read_callback(0x2001, 1, lambda: 17)
PDO Mapping:
PDOs can be dynamically mapped via the SDO server or programmatically. The PDO indices start at 0.
node.tpdo[0].mapping = [(0x2001, 1), (0x2001, 2)]
node.tpdo[0].transmission_type = 1 # Transmit on every SYNC
node.rpdo[0].mapping = [(0x2000, 0)]
node.tpdo[0].transmission_type = 255 # Event-driven (processed when received)
Installation
pip install durand
Credits
This library would not be possible without:
python-canopen: CANopen library (by Christian Sandberg)
python-can: CAN interface library (by Brian Thorne)
Metadata
Release files for durand 0.5.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| durand-0.5.0.tar.gz | 37.4 kB | Without provenance | Details for durand-0.5.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| durand-0.5.0-py3-none-any.whl | Python 3 | none | any | Details for durand-0.5.0-py3-none-any.whl |
Total release size: 69.0 kB
Release files / durand-0.5.0.tar.gz
| Download URL | durand-0.5.0.tar.gz |
|---|---|
| Size | 37.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
496afa9dce1747ca06186df4c0932da64692ff1b5bd3b6ebcc114f750d9a3f59
|
|
BLAKE2b-256 checksum How to use checksums |
5d65368ebbb343c441bb8891d6595b5d5bc6bf978feaba872e4291a1ae819e46
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.9.22
|
Release files / durand-0.5.0-py3-none-any.whl
| Download URL | durand-0.5.0-py3-none-any.whl |
|---|---|
| Size | 31.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a864e83877900a43fb4231b36cea41e9b36773cfb3b7f80ae2199a80cb24836e
|
|
BLAKE2b-256 checksum How to use checksums |
55fd9fb92ac8efea37609d85fc6180f283917c8a57ba7bdbe4854fb606e6e5f8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.9.22
|
Security for durand 0.5.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.