================================================
Python Durand - CANopen Responder Device Library
================================================
CANopen library to implement responder nodes.
Backends:
- CAN interfaces via python-can_
.. header
Synopsis
========
- Pure python implementation
- Under MIT license (2021 Günther Jena)
- Source is hosted on GitHub.com_
- Tested on Python 3.7, 3.8, 3.9 and 3.10
- Unit tested with pytest_, coding style done with Black_, static type checked with mypy_, static code checked with Pylint_, documented with Sphinx_
- Supporting CiA301_ (EN 50325-4)
.. _pytest: https://docs.pytest.org/en/latest
.. _Black: https://black.readthedocs.io/en/stable/
.. _mypy: http://mypy-lang.org/
.. _Pylint: https://www.pylint.org/
.. _Sphinx: http://www.sphinx-doc.org
.. _GitHub.com: https://github.com/semiversus/python-durand
.. _CiA301: http://can-cia.org/standardization/technical-documents
Feature List
============
* Object dictionary
* provides callbacks for *validation*, *update*, *download* and *read*
* supports records, arrays and variables
* EDS support
* dynamically generation of EDS file
* automatically provided via object 0x1021 ("Store EDS")
* up to 128 SDO servers
* expetited, segmented and block transfer for up- and download
* COB-IDs dynamically configurable
* custom up- and download handlers supported
* up to 512 TPDOs and 512 RPDOs
* dynamically configurable
* transmission types: synchronous (acyclic and every nth sync) and event driven
* inhibit time supported
* EMCY producer service
* COB-ID dynamically configurable
* inhibit time supported
* Heartbeat producer service
* dynamically configurable
* NMT slave service
* boot-up service
* callback for state change provided
* SYNC consumer service
* COB-ID dynamically configurable
* callback for received sync provided
* CiA305 Layer Setting Service
* fast scan supported
* bitrate and node id configuring supported
* identify remote responder supported
* CAN interface abstraction
* python-can_ fully supported
* automatic CAN id filtering by subscripted services
* Scheduling supporting threaded and async operation
TODO
* build object dictionary via reading an EDS file
* supporting MPDOs
* TIME consumer service
* Up- and download handler as io streams
Examples
========
Creating a node
---------------
.. code-block:: python
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 have a CiA-301 compliant node running. Layer Setting Service is also supported out of the box.
Adding objects
--------------
.. code-block:: python
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
Access values
-------------
The objects can be read and written directly by accessing the object dictionary:
.. code-block:: python
print(f'Value of Parameter 1: {od.read(0x2000, 0)}')
od.write(0x2001, 1, value=0xAA)
Add callbacks
-------------
A more event driven approach is using of callbacks. Following callbacks are available:
* `validate_callbacks` - called before a value in the object dictionary is going to be 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 a object is read (return value is used )
.. code-block:: python
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 Parmeter 1: {v}'))
od.set_read_callback(0x2001, 1, lambda: 17)
PDO mapping
-----------
PDOs can dynamically mapped via the SDO server or programmatically. The PDO indices
start at 0.
.. code-block:: python
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)
Install
=======
.. code-block:: bash
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)
.. _python-canopen: https://github.com/christiansandberg/canopen
.. _python-can: https://github.com/hardbyte/python-can
Raw data
{
"_id": null,
"home_page": "https://github.com/semiversus/python-durand",
"name": "durand",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.7",
"maintainer_email": null,
"keywords": "canopen can node ds301",
"author": "G\u00fcnther Jena",
"author_email": "guenther@jena.at",
"download_url": "https://files.pythonhosted.org/packages/1b/cb/9dea282920e5a8814c48e428d0ebf7570a624e9016ed23aa5d5a807fe0d6/durand-0.4.13.tar.gz",
"platform": null,
"description": "================================================\nPython Durand - CANopen Responder Device Library\n================================================\n\nCANopen library to implement responder nodes.\n\nBackends:\n\n- CAN interfaces via python-can_\n\n.. header\n\nSynopsis\n========\n\n- Pure python implementation\n- Under MIT license (2021 G\u00fcnther Jena)\n- Source is hosted on GitHub.com_\n- Tested on Python 3.7, 3.8, 3.9 and 3.10\n- Unit tested with pytest_, coding style done with Black_, static type checked with mypy_, static code checked with Pylint_, documented with Sphinx_\n- Supporting CiA301_ (EN 50325-4)\n\n.. _pytest: https://docs.pytest.org/en/latest\n.. _Black: https://black.readthedocs.io/en/stable/\n.. _mypy: http://mypy-lang.org/\n.. _Pylint: https://www.pylint.org/\n.. _Sphinx: http://www.sphinx-doc.org\n.. _GitHub.com: https://github.com/semiversus/python-durand\n.. _CiA301: http://can-cia.org/standardization/technical-documents\n\nFeature List\n============\n\n* Object dictionary\n\n * provides callbacks for *validation*, *update*, *download* and *read*\n * supports records, arrays and variables\n\n* EDS support\n\n * dynamically generation of EDS file\n * automatically provided via object 0x1021 (\"Store EDS\")\n\n* up to 128 SDO servers\n\n * expetited, segmented and block transfer for up- and download\n * COB-IDs dynamically configurable\n * custom up- and download handlers supported\n\n* up to 512 TPDOs and 512 RPDOs\n\n * dynamically configurable\n * transmission types: synchronous (acyclic and every nth sync) and event driven\n * inhibit time supported\n\n* EMCY producer service\n\n * COB-ID dynamically configurable\n * inhibit time supported\n\n* Heartbeat producer service\n\n * dynamically configurable\n\n* NMT slave service\n\n * boot-up service\n * callback for state change provided\n\n* SYNC consumer service\n\n * COB-ID dynamically configurable\n * callback for received sync provided\n\n* CiA305 Layer Setting Service\n\n * fast scan supported\n * bitrate and node id configuring supported\n * identify remote responder supported\n\n* CAN interface abstraction\n \n * python-can_ fully supported\n * automatic CAN id filtering by subscripted services\n\n* Scheduling supporting threaded and async operation\n\nTODO\n * build object dictionary via reading an EDS file\n * supporting MPDOs\n * TIME consumer service\n * Up- and download handler as io streams\n\nExamples\n========\n\nCreating a node\n---------------\n\n.. code-block:: python\n\n import can\n from durand import CANBusNetwork, Node, Variable, Record, DatatypeEnum\n\n bus = can.Bus(bustype='socketcan', channel='vcan0')\n network = CANBusNetwork(bus)\n\n node = Node(network, node_id=0x01)\n\nCongratulations! You have a CiA-301 compliant node running. Layer Setting Service is also supported out of the box.\n\nAdding objects\n--------------\n\n.. code-block:: python\n\n od = node.object_dictionary\n\n # add variable at index 0x2000\n od[0x2000] = Variable(DatatypeEnum.UNSIGNED16, access='rw', value=10, name='Parameter 1')\n\n # add record at index 0x2001\n record = Record(name='Parameter Record')\n record[1] = Variable(DatatypeEnum.UNSIGNED8, access='ro', value=0, name='Parameter 2a')\n record[2] = Variable(DatatypeEnum.REAL32, access='rw', value=0, name='Parameter 2b')\n od[0x2001] = record\n\nAccess values\n-------------\n\nThe objects can be read and written directly by accessing the object dictionary:\n\n.. code-block:: python\n\n print(f'Value of Parameter 1: {od.read(0x2000, 0)}')\n od.write(0x2001, 1, value=0xAA)\n\nAdd callbacks\n-------------\n\nA more event driven approach is using of callbacks. Following callbacks are available:\n\n* `validate_callbacks` - called before a value in the object dictionary is going to be updated\n* `update_callbacks` - called when the value has been changed (via `od.write` or via CAN bus)\n* `download_callbacks` - called when the value has been changed via CAN bus\n* `read_callback` - called when a object is read (return value is used )\n\n.. code-block:: python\n\n od.validate_callbacks[(0x2000, 0)].add(lambda v: v % 2 == 0)\n od.update_callbacks[(0x2001, 2)].add(lambda v: print(f'Update for Parameter 2b: {v}'))\n od.download_callbacks[(0x2000, 0)].add(lambda v: print(f'Download for Parmeter 1: {v}'))\n od.set_read_callback(0x2001, 1, lambda: 17)\n\nPDO mapping\n-----------\n\nPDOs can dynamically mapped via the SDO server or programmatically. The PDO indices\nstart at 0.\n\n.. code-block:: python\n\n node.tpdo[0].mapping = [(0x2001, 1), (0x2001, 2)]\n node.tpdo[0].transmission_type = 1 # transmit on every SYNC\n\n node.rpdo[0].mapping = [(0x2000, 0)]\n node.tpdo[0].transmission_type = 255 # event driven (processed when received)\n\nInstall\n=======\n\n.. code-block:: bash\n\n pip install durand\n\nCredits\n=======\n\nThis library would not be possible without:\n\n* python-canopen_: CANopen library (by Christian Sandberg)\n* python-can_: CAN interface library (by Brian Thorne)\n\n.. _python-canopen: https://github.com/christiansandberg/canopen\n.. _python-can: https://github.com/hardbyte/python-can\n",
"bugtrack_url": null,
"license": "MIT license",
"summary": "CANopen library providing functionality to implement responder nodes",
"version": "0.4.13",
"project_urls": {
"Homepage": "https://github.com/semiversus/python-durand"
},
"split_keywords": [
"canopen",
"can",
"node",
"ds301"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "9f71aed2b1e696b94e8c7d16b878f2d4b0a125c0626c86014c60ea9c2658c95a",
"md5": "c808636d8c0a888dda1ad1cc1f937955",
"sha256": "bc9180d920333f90c0265df99eac68287f31505321157d0d966a5e8194ea81d3"
},
"downloads": -1,
"filename": "durand-0.4.13-py3-none-any.whl",
"has_sig": false,
"md5_digest": "c808636d8c0a888dda1ad1cc1f937955",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.7",
"size": 31134,
"upload_time": "2024-09-12T05:22:24",
"upload_time_iso_8601": "2024-09-12T05:22:24.517743Z",
"url": "https://files.pythonhosted.org/packages/9f/71/aed2b1e696b94e8c7d16b878f2d4b0a125c0626c86014c60ea9c2658c95a/durand-0.4.13-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "1bcb9dea282920e5a8814c48e428d0ebf7570a624e9016ed23aa5d5a807fe0d6",
"md5": "628fb49d3fdb12fa472b8278fa2c07c2",
"sha256": "a2d4b63664a790ab05424e105730ebfb9cf80c5afcecf32d26696201ed7d57ba"
},
"downloads": -1,
"filename": "durand-0.4.13.tar.gz",
"has_sig": false,
"md5_digest": "628fb49d3fdb12fa472b8278fa2c07c2",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.7",
"size": 36282,
"upload_time": "2024-09-12T05:22:25",
"upload_time_iso_8601": "2024-09-12T05:22:25.663031Z",
"url": "https://files.pythonhosted.org/packages/1b/cb/9dea282920e5a8814c48e428d0ebf7570a624e9016ed23aa5d5a807fe0d6/durand-0.4.13.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-09-12 05:22:25",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "semiversus",
"github_project": "python-durand",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "durand"
}