durand


Namedurand JSON
Version 0.4.13 PyPI version JSON
download
home_pagehttps://github.com/semiversus/python-durand
SummaryCANopen library providing functionality to implement responder nodes
upload_time2024-09-12 05:22:25
maintainerNone
docs_urlNone
authorGünther Jena
requires_python>=3.7
licenseMIT license
keywords canopen can node ds301
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            ================================================
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"
}
        
Elapsed time: 0.73654s