diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f10e2b78..04ffb9b57 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,7 @@ Features xlFlushReceiveQueue to xldriver (#1387). * Vector: Raise a CanInitializationError, if the CAN settings can not be applied according to the arguments of ``VectorBus.__init__`` (#1426). +* Ixxat bus now implements BusState api and detects errors (#1141) Bug Fixes --------- diff --git a/README.rst b/README.rst index 11404785a..79b985129 100644 --- a/README.rst +++ b/README.rst @@ -62,7 +62,7 @@ Library Version Python ------------------------------ ----------- 2.x 2.6+, 3.4+ 3.x 2.7+, 3.5+ - 4.x *(currently on develop)* 3.7+ + 4.x 3.7+ ============================== =========== @@ -74,7 +74,7 @@ Features - receiving, sending, and periodically sending messages - normal and extended arbitration IDs - `CAN FD `__ support -- many different loggers and readers supporting playback: ASC (CANalyzer format), BLF (Binary Logging Format by Vector), CSV, SQLite and Canutils log +- many different loggers and readers supporting playback: ASC (CANalyzer format), BLF (Binary Logging Format by Vector), TRC, CSV, SQLite, and Canutils log - efficient in-kernel or in-hardware filtering of messages on supported interfaces - bus configuration reading from a file or from environment variables - command line tools for working with CAN buses (see the `docs `__) @@ -84,6 +84,8 @@ Features Example usage ------------- +``pip install python-can`` + .. code:: python # import the library @@ -117,9 +119,6 @@ Discussion If you run into bugs, you can file them in our `issue tracker `__ on GitHub. -There is also a `python-can `__ -mailing list for development discussion. - `Stackoverflow `__ has several questions and answers tagged with ``python+can``. diff --git a/can/interfaces/cantact.py b/can/interfaces/cantact.py index 9ad7fbef8..d735b7ee3 100644 --- a/can/interfaces/cantact.py +++ b/can/interfaces/cantact.py @@ -20,7 +20,7 @@ except ImportError: cantact = None logger.warning( - "The CANtact module is not installed. Install it using `python -m pip install cantact`" + "The CANtact module is not installed. Install it using `pip install cantact`" ) diff --git a/can/interfaces/udp_multicast/bus.py b/can/interfaces/udp_multicast/bus.py index 7f74c685f..2ba1205b1 100644 --- a/can/interfaces/udp_multicast/bus.py +++ b/can/interfaces/udp_multicast/bus.py @@ -55,7 +55,7 @@ class UdpMulticastBus(BusABC): .. warning:: This interface does not make guarantees on reliable delivery and message ordering, and also does not implement rate limiting or ID arbitration/prioritization under high loads. Please refer to the section - :ref:`other_virtual_interfaces` for more information on this and a comparison to alternatives. + :ref:`virtual_interfaces_doc` for more information on this and a comparison to alternatives. :param channel: A multicast IPv4 address (in `224.0.0.0/4`) or an IPv6 address (in `ff00::/8`). This defines which version of IP is used. See diff --git a/can/interfaces/virtual.py b/can/interfaces/virtual.py index cc71469b5..25b7abfb0 100644 --- a/can/interfaces/virtual.py +++ b/can/interfaces/virtual.py @@ -51,7 +51,7 @@ class VirtualBus(BusABC): .. warning:: This interface guarantees reliable delivery and message ordering, but does *not* implement rate limiting or ID arbitration/prioritization under high loads. Please refer to the section - :ref:`other_virtual_interfaces` for more information on this and a comparison to alternatives. + :ref:`virtual_interfaces_doc` for more information on this and a comparison to alternatives. """ def __init__( diff --git a/doc/api.rst b/doc/api.rst index 23342f992..053bd34a4 100644 --- a/doc/api.rst +++ b/doc/api.rst @@ -17,33 +17,9 @@ A form of CAN interface is also required. listeners asyncio bcm + errors bit_timing + utils internal-api -Utilities ---------- - - -.. autofunction:: can.detect_available_configs - - -.. _notifier: - -Notifier --------- - -The Notifier object is used as a message distributor for a bus. Notifier creates a thread to read messages from the bus and distributes them to listeners. - -.. autoclass:: can.Notifier - :members: - - -.. _errors: - -Errors ------- - -.. automodule:: can.exceptions - :members: - :show-inheritance: diff --git a/doc/bus.rst b/doc/bus.rst index 4db49ee29..06a740829 100644 --- a/doc/bus.rst +++ b/doc/bus.rst @@ -3,48 +3,55 @@ Bus --- -The :class:`~can.BusABC` class, as the name suggests, provides an abstraction of a CAN bus. -The bus provides a wrapper around a physical or virtual CAN Bus. -An interface specific instance of the :class:`~can.BusABC` is created by the :class:`~can.Bus` -class, for example:: +The :class:`~can.Bus` provides a wrapper around a physical or virtual CAN Bus. + +An interface specific instance is created by instantiating the :class:`~can.Bus` +class with a particular ``interface``, for example:: vector_bus = can.Bus(interface='vector', ...) -That bus is then able to handle the interface specific software/hardware interactions -and implements the :class:`~can.BusABC` API. +The created bus is then able to handle the interface specific software/hardware interactions +while giving the user the same top level API. A thread safe bus wrapper is also available, see `Thread safe bus`_. -.. autoclass:: can.Bus - :class-doc-from: class - :show-inheritance: - :members: - :inherited-members: - -.. autoclass:: can.bus.BusState - :members: - :undoc-members: - Transmitting '''''''''''' Writing individual messages to the bus is done by calling the :meth:`~can.BusABC.send` method -and passing a :class:`~can.Message` instance. Periodic sending is controlled by the -:ref:`broadcast manager `. +and passing a :class:`~can.Message` instance. + +.. code-block:: python + :emphasize-lines: 8 + + with can.Bus() as bus: + msg = can.Message( + arbitration_id=0xC0FFEE, + data=[0, 25, 0, 1, 3, 1, 4, 1], + is_extended_id=True + ) + try: + bus.send(msg) + print(f"Message sent on {bus.channel_info}") + except can.CanError: + print("Message NOT sent") +Periodic sending is controlled by the :ref:`broadcast manager `. + Receiving ''''''''' Reading from the bus is achieved by either calling the :meth:`~can.BusABC.recv` method or by directly iterating over the bus:: - for msg in bus: - print(msg.data) + with can.Bus() as bus: + for msg in bus: + print(msg.data) -Alternatively the :class:`~can.Listener` api can be used, which is a list of :class:`~can.Listener` -subclasses that receive notifications when new messages arrive. +Alternatively the :ref:`listeners_doc` api can be used, which is a list of various +:class:`~can.Listener` implementations that receive and handle messages from a :class:`~can.Notifier`. Filtering @@ -67,6 +74,20 @@ Example defining two filters, one to pass 11-bit ID ``0x451``, the other to pass See :meth:`~can.BusABC.set_filters` for the implementation. +Bus API +''''''' + +.. autoclass:: can.Bus + :class-doc-from: class + :show-inheritance: + :members: + :inherited-members: + +.. autoclass:: can.bus.BusState + :members: + :undoc-members: + + Thread safe bus ''''''''''''''' diff --git a/doc/errors.rst b/doc/errors.rst new file mode 100644 index 000000000..bc954738a --- /dev/null +++ b/doc/errors.rst @@ -0,0 +1,8 @@ +.. _errors: + +Error Handling +============== + +.. automodule:: can.exceptions + :members: + :show-inheritance: diff --git a/doc/history.rst b/doc/history.rst index 9ae0581b0..73371af4c 100644 --- a/doc/history.rst +++ b/doc/history.rst @@ -1,5 +1,5 @@ -History and Roadmap -=================== +History +======= Background ---------- diff --git a/doc/index.rst b/doc/index.rst index f24831c7c..505c8b87b 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -8,22 +8,22 @@ different hardware devices, and a suite of utilities for sending and receiving messages on a CAN bus. **python-can** runs any where Python runs; from high powered computers -with commercial `CAN to usb` devices right down to low powered devices running +with commercial `CAN to USB` devices right down to low powered devices running linux such as a BeagleBone or RaspberryPi. More concretely, some example uses of the library: -- Passively logging what occurs on a CAN bus. For example monitoring a +* Passively logging what occurs on a CAN bus. For example monitoring a commercial vehicle using its **OBD-II** port. -- Testing of hardware that interacts via CAN. Modules found in - modern cars, motocycles, boats, and even wheelchairs have had components tested +* Testing of hardware that interacts via CAN. Modules found in + modern cars, motorcycles, boats, and even wheelchairs have had components tested from Python using this library. -- Prototyping new hardware modules or software algorithms in-the-loop. Easily +* Prototyping new hardware modules or software algorithms in-the-loop. Easily interact with an existing bus. -- Creating virtual modules to prototype CAN bus communication. +* Creating virtual modules to prototype CAN bus communication. Brief example of the library in action: connecting to a CAN bus, creating and sending a message: @@ -37,12 +37,14 @@ Brief example of the library in action: connecting to a CAN bus, creating and se Contents: .. toctree:: - :maxdepth: 2 + :maxdepth: 1 installation configuration api interfaces + virtual-interfaces + plugin-interface scripts development history diff --git a/doc/installation.rst b/doc/installation.rst index bfce72180..6b2a2cfb2 100644 --- a/doc/installation.rst +++ b/doc/installation.rst @@ -2,15 +2,24 @@ Installation ============ -Install ``can`` with ``pip``: -:: +Install the ``can`` package from PyPi with ``pip`` or similar:: $ pip install python-can -As most likely you will want to interface with some hardware, you may -also have to install platform dependencies. Be sure to check any other -specifics for your hardware in :doc:`interfaces`. + + +.. warning:: + As most likely you will want to interface with some hardware, you may + also have to install platform dependencies. Be sure to check any other + specifics for your hardware in :doc:`interfaces`. + + Many interfaces can install their dependencies at the same time as ``python-can``, + for instance the interface ``serial`` includes the ``pyserial`` dependency which can + be installed with the ``serial`` extra:: + + $ pip install python-can[serial] + GNU/Linux dependencies @@ -99,7 +108,7 @@ To install ``python-can`` using the CANtact driver backend: If ``python-can`` is already installed, the CANtact backend can be installed separately: -``python3 -m pip install cantact`` +``pip install cantact`` Additional CANtact documentation is available at `cantact.io `__. diff --git a/doc/interfaces.rst b/doc/interfaces.rst index 54d70ca86..cc686d2d5 100644 --- a/doc/interfaces.rst +++ b/doc/interfaces.rst @@ -1,14 +1,18 @@ .. _can interface modules: -CAN Interface Modules ---------------------- +Hardware Interfaces +=================== **python-can** hides the low-level, device-specific interfaces to controller area network adapters in interface dependant modules. However as each hardware device is different, you should carefully go through your interface's documentation. -The available interfaces are: +.. note:: + The *Interface Names* are listed in :doc:`configuration`. + + +The available hardware interfaces are: .. toctree:: :maxdepth: 1 @@ -32,63 +36,6 @@ The available interfaces are: interfaces/socketcan interfaces/socketcand interfaces/systec - interfaces/udp_multicast interfaces/usb2can interfaces/vector - interfaces/virtual - -The *Interface Names* are listed in :doc:`configuration`. - - -.. _plugin interface: - -Plugin Interface -^^^^^^^^^^^^^^^^ - -External packages can register new interfaces by using the ``can.interface`` entry point -in its project configuration. The format of the entry point depends on your project -configuration format (*pyproject.toml*, *setup.cfg* or *setup.py*). - -In the following example ``module`` defines the location of your bus class inside your -package e.g. ``my_package.subpackage.bus_module`` and ``classname`` is the name of -your :class:`can.BusABC` subclass. - -.. tab:: pyproject.toml (PEP 621) - - .. code-block:: toml - - # Note the quotes around can.interface in order to escape the dot . - [project.entry-points."can.interface"] - interface_name = "module:classname" - -.. tab:: setup.cfg - - .. code-block:: ini - - [options.entry_points] - can.interface = - interface_name = module:classname - -.. tab:: setup.py - - .. code-block:: python - - from setuptools import setup - - setup( - # ..., - entry_points = { - 'can.interface': [ - 'interface_name = module:classname' - ] - } - ) - -The ``interface_name`` can be used to -create an instance of the bus in the **python-can** API: - -.. code-block:: python - - import can - bus = can.Bus(interface="interface_name", channel=0) diff --git a/doc/interfaces/canalystii.rst b/doc/interfaces/canalystii.rst index 375e1b754..b48782259 100644 --- a/doc/interfaces/canalystii.rst +++ b/doc/interfaces/canalystii.rst @@ -12,7 +12,7 @@ Windows, Linux and Mac. .. note:: - The backend driver depends on `pyusb ` so a ``pyusb`` backend driver library such as ``libusb`` must be installed. On Windows a tool such as `Zadig ` can be used to set the Canalyst-II USB device driver to ``libusb-win32``. + The backend driver depends on `pyusb `_ so a ``pyusb`` backend driver library such as ``libusb`` must be installed. On Windows a tool such as `Zadig `_ can be used to set the Canalyst-II USB device driver to ``libusb-win32``. Limitations ----------- diff --git a/doc/interfaces/etas.rst b/doc/interfaces/etas.rst index 2b59a4eee..7986142be 100644 --- a/doc/interfaces/etas.rst +++ b/doc/interfaces/etas.rst @@ -3,19 +3,22 @@ ETAS This interface adds support for CAN interfaces by `ETAS`_. The ETAS BOA_ (Basic Open API) is used. + +Installation +------------ + Install the "ETAS ECU and Bus Interfaces – Distribution Package". -Only Windows is supported by this interface. -The Linux kernel v5.13 (and greater) natively supports ETAS ES581.4, ES582.1 and ES584.1 USB modules. -To use these under Linux, please refer to :ref:`SocketCAN`. -Bus ---- +.. warning:: + Only Windows is supported by this interface. -.. autoclass:: can.interfaces.etas.EtasBus - :members: + The Linux kernel v5.13 (and greater) natively supports ETAS ES581.4, ES582.1 and ES584.1 + USB modules. To use these under Linux, please refer to the :ref:`SocketCAN` interface + documentation. -Configuration file ------------------- + +Configuration +------------- The simplest configuration file would be:: @@ -31,5 +34,13 @@ To find available URIs, use :meth:`~can.detect_available_configs`:: for c in configs: print(c) + +Bus +--- + +.. autoclass:: can.interfaces.etas.EtasBus + :members: + + .. _ETAS: https://www.etas.com/ .. _BOA: https://www.etas.com/de/downloadcenter/18102.php diff --git a/doc/interfaces/gs_usb.rst b/doc/interfaces/gs_usb.rst index 232786fb7..af69581be 100755 --- a/doc/interfaces/gs_usb.rst +++ b/doc/interfaces/gs_usb.rst @@ -1,9 +1,10 @@ .. _gs_usb: -CAN driver for Geschwister Schneider USB/CAN devices and bytewerk.org candleLight USB CAN interfaces -================================================================================================================== +Geschwister Schneider and candleLight +===================================== -Windows/Linux/Mac CAN driver based on usbfs or WinUSB WCID for Geschwister Schneider USB/CAN devices and candleLight USB CAN interfaces. +Windows/Linux/Mac CAN driver based on usbfs or WinUSB WCID for Geschwister Schneider USB/CAN devices +and candleLight USB CAN interfaces. Install: ``pip install "python-can[gs_usb]"`` @@ -17,13 +18,19 @@ Usage: pass device ``index`` (starting from 0) if using automatic device detecti Alternatively, pass ``bus`` and ``address`` to open a specific device. The parameters can be got by ``pyusb`` as shown below: -:: +.. code-block:: python import usb import can dev = usb.core.find(idVendor=0x1D50, idProduct=0x606F) - bus = can.Bus(bustype="gs_usb", channel=dev.product, bus=dev.bus, address=dev.address, bitrate=250000) + bus = can.Bus( + bustype="gs_usb", + channel=dev.product, + bus=dev.bus, + address=dev.address, + bitrate=250000 + ) Supported devices @@ -39,21 +46,29 @@ Windows, Linux and Mac. .. note:: - The backend driver depends on `pyusb ` so a ``pyusb`` backend driver library such as ``libusb`` must be installed. On Windows a tool such as `Zadig ` can be used to set the USB device driver to ``libusb-win32``. + The backend driver depends on `pyusb `_ so a ``pyusb`` backend driver library such as + ``libusb`` must be installed. + + On Windows a tool such as `Zadig `_ can be used to set the USB device driver to + ``libusb-win32``. -Supplementary Info on ``gs_usb`` ------------------------------------ +Supplementary Info +------------------ The firmware implementation for Geschwister Schneider USB/CAN devices and candleLight USB CAN can be found in `candle-usb/candleLight_fw `_. The Linux kernel driver can be found in `linux/drivers/net/can/usb/gs_usb.c `_. -The ``gs_usb`` interface in ``PythonCan`` relys on upstream ``gs_usb`` package, which can be found in `https://pypi.org/project/gs-usb/ `_ or `https://github.com/jxltom/gs_usb `_. -The ``gs_usb`` package is using ``pyusb`` as backend, which brings better crossplatform compatibility. +The ``gs_usb`` interface in ``python-can`` relies on upstream ``gs_usb`` package, which can be found in +`https://pypi.org/project/gs-usb/ `_ or +`https://github.com/jxltom/gs_usb `_. + +The ``gs_usb`` package uses ``pyusb`` as backend, which brings better cross-platform compatibility. Note: The bitrate ``10K``, ``20K``, ``50K``, ``83.333K``, ``100K``, ``125K``, ``250K``, ``500K``, ``800K`` and ``1M`` are supported in this interface, as implemented in the upstream ``gs_usb`` package's ``set_bitrate`` method. -Note: Message filtering is not supported in Geschwister Schneider USB/CAN devices and bytewerk.org candleLight USB CAN interfaces. +.. warning:: + Message filtering is not supported in Geschwister Schneider USB/CAN devices and bytewerk.org candleLight USB CAN interfaces. Bus --- diff --git a/doc/interfaces/ixxat.rst b/doc/interfaces/ixxat.rst index 02e707c1c..61df70638 100644 --- a/doc/interfaces/ixxat.rst +++ b/doc/interfaces/ixxat.rst @@ -1,9 +1,9 @@ .. _ixxatdoc: -IXXAT Virtual CAN Interface -=========================== +IXXAT Virtual Communication Interface +===================================== -Interface to `IXXAT `__ Virtual CAN Interface V3 SDK. Works on Windows. +Interface to `IXXAT `__ Virtual Communication Interface V3 SDK. Works on Windows. The Linux ECI SDK is currently unsupported, however on Linux some devices are supported with :doc:`socketcan`. @@ -14,33 +14,8 @@ Modifying cyclic messages is not possible. You will need to stop it, and then start a new periodic message. -Bus ---- - -.. autoclass:: can.interfaces.ixxat.IXXATBus - :members: - -Implementation based on vcinpl.dll -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. autoclass:: can.interfaces.ixxat.canlib_vcinpl.IXXATBus - :members: - -.. autoclass:: can.interfaces.ixxat.canlib_vcinpl.CyclicSendTask - :members: - -Implementation based on vcinpl2.dll -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. autoclass:: can.interfaces.ixxat.canlib_vcinpl2.IXXATBus - :members: - -.. autoclass:: can.interfaces.ixxat.canlib_vcinpl2.CyclicSendTask - :members: - - -Configuration file ------------------- +Configuration +------------- The simplest configuration file would be:: [default] @@ -91,6 +66,32 @@ To get a list of all connected IXXAT you can use the function ``get_ixxat_hwids( Found IXXAT with hardware id 'HW107422'. +Bus +--- + +.. autoclass:: can.interfaces.ixxat.IXXATBus + :members: + +Implementation based on vcinpl.dll +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. autoclass:: can.interfaces.ixxat.canlib_vcinpl.IXXATBus + :members: + +.. autoclass:: can.interfaces.ixxat.canlib_vcinpl.CyclicSendTask + :members: + +Implementation based on vcinpl2.dll +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. autoclass:: can.interfaces.ixxat.canlib_vcinpl2.IXXATBus + :members: + +.. autoclass:: can.interfaces.ixxat.canlib_vcinpl2.CyclicSendTask + :members: + + + Internals --------- diff --git a/doc/interfaces/kvaser.rst b/doc/interfaces/kvaser.rst index 4e0062cfa..f2c93f85b 100644 --- a/doc/interfaces/kvaser.rst +++ b/doc/interfaces/kvaser.rst @@ -20,7 +20,7 @@ Internals The Kvaser :class:`~can.Bus` object with a physical CAN Bus can be operated in two modes; ``single_handle`` mode with one shared bus handle used for both reading and writing to the CAN bus, or with two separate bus handles. -Two separate handles are needed if receiving and sending messages are done in +Two separate handles are needed if receiving and sending messages in different threads (see `Kvaser documentation `_). @@ -40,7 +40,7 @@ in the ``recv`` method. If a message does not match any of the filters, Custom methods -~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~ This section contains Kvaser driver specific methods. diff --git a/doc/interfaces/neovi.rst b/doc/interfaces/neovi.rst index 588c5e914..0baf08055 100644 --- a/doc/interfaces/neovi.rst +++ b/doc/interfaces/neovi.rst @@ -1,7 +1,7 @@ -neoVI -===== +Intrepid Control Systems neoVI +============================== -.. warning:: +.. note:: This ``ICS neoVI`` documentation is a work in progress. Feedback and revisions are most welcome! @@ -14,16 +14,16 @@ wrapper on Windows. Installation ------------ -This neoVI interface requires the installation of the ICS neoVI DLL and python-ics +This neoVI interface requires the installation of the ICS neoVI DLL and ``python-ics`` package. - Download and install the Intrepid Product Drivers `Intrepid Product Drivers `__ -- Install python-ics +- Install ``python-can`` with the ``neovi`` extras: .. code-block:: bash - pip install python-ics + pip install python-ics[neovi] Configuration diff --git a/doc/interfaces/nican.rst b/doc/interfaces/nican.rst index 4d2a40717..6e802a3d4 100644 --- a/doc/interfaces/nican.rst +++ b/doc/interfaces/nican.rst @@ -1,7 +1,7 @@ -NI-CAN -====== +National Instruments NI-CAN +=========================== -This interface adds support for CAN controllers by `National Instruments`_. +This interface adds support for NI-CAN controllers by `National Instruments`_. .. warning:: diff --git a/doc/interfaces/nixnet.rst b/doc/interfaces/nixnet.rst index 36d1a8ef0..8cf2ee72d 100644 --- a/doc/interfaces/nixnet.rst +++ b/doc/interfaces/nixnet.rst @@ -1,12 +1,12 @@ -NI-XNET -======= +National Instruments NI-XNET +============================ This interface adds support for NI-XNET CAN controllers by `National Instruments`_. -.. warning:: +.. note:: - NI-XNET only seems to support windows platforms. + NI-XNET only supports windows platforms. Bus diff --git a/doc/interfaces/pcan.rst b/doc/interfaces/pcan.rst index feb40b195..790264627 100644 --- a/doc/interfaces/pcan.rst +++ b/doc/interfaces/pcan.rst @@ -3,7 +3,7 @@ PCAN Basic API ============== -Interface to `Peak-System `__'s PCAN-Basic API. +Interface to `Peak-System `__'s PCAN-Basic API. Configuration ------------- @@ -18,15 +18,9 @@ Here is an example configuration file for using `PCAN-USB The socketcan package is an implementation of CAN protocols -> (Controller Area Network) for Linux. CAN is a networking technology -> which has widespread use in automation, embedded devices, and -> automotive fields. While there have been other CAN implementations -> for Linux based on character devices, SocketCAN uses the Berkeley -> socket API, the Linux network stack and implements the CAN device -> drivers as network interfaces. The CAN socket API has been designed -> as similar as possible to the TCP/IP protocols to allow programmers, -> familiar with network programming, to easily learn how to use CAN -> sockets. +The SocketCAN documentation can be found in the `Linux kernel docs`_ in the +``networking`` directory. Quoting from the SocketCAN Linux documentation: + + The socketcan package is an implementation of CAN protocols + (Controller Area Network) for Linux. CAN is a networking technology + which has widespread use in automation, embedded devices, and + automotive fields. While there have been other CAN implementations + for Linux based on character devices, SocketCAN uses the Berkeley + socket API, the Linux network stack and implements the CAN device + drivers as network interfaces. The CAN socket API has been designed + as similar as possible to the TCP/IP protocols to allow programmers, + familiar with network programming, to easily learn how to use CAN + sockets. .. important:: diff --git a/doc/interfaces/socketcand.rst b/doc/interfaces/socketcand.rst index 3c05bcc85..2f313470c 100644 --- a/doc/interfaces/socketcand.rst +++ b/doc/interfaces/socketcand.rst @@ -4,7 +4,7 @@ socketcand Interface ==================== `Socketcand `__ is part of the `Linux-CAN `__ project, providing a -Network-to-CAN bridge as Linux damon. It implements a specific +Network-to-CAN bridge as a Linux damon. It implements a specific `TCP/IP based communication protocol `__ to transfer CAN frames and control commands. @@ -24,7 +24,7 @@ daemon running on a remote Raspberry Pi: try: while True: msg = bus.recv() - print (msg) + print(msg) except KeyboardInterrupt: pass diff --git a/doc/interfaces/systec.rst b/doc/interfaces/systec.rst index 0aa4d9444..6b04fdfe0 100644 --- a/doc/interfaces/systec.rst +++ b/doc/interfaces/systec.rst @@ -28,12 +28,6 @@ The interface supports following devices: - USB-CANmodul1 G4, - USB-CANmodul2 G4. -Bus ---- - -.. autoclass:: can.interfaces.systec.ucanbus.UcanBus - :members: - Configuration ------------- @@ -57,6 +51,14 @@ Optional parameters: * ``state`` (default BusState.ACTIVE) BusState of the channel * ``receive_own_messages`` (default False) If messages transmitted should also be received back + +Bus +--- + +.. autoclass:: can.interfaces.systec.ucanbus.UcanBus + :members: + + Internals --------- diff --git a/doc/interfaces/udp_multicast.rst b/doc/interfaces/udp_multicast.rst index f2775727c..b15354ed5 100644 --- a/doc/interfaces/udp_multicast.rst +++ b/doc/interfaces/udp_multicast.rst @@ -16,7 +16,7 @@ sufficiently reliable for this interface to function properly. .. note:: For an overview over the different virtual buses in this library and beyond, please refer - to the section :ref:`other_virtual_interfaces`. It also describes important limitations + to the section :ref:`virtual_interfaces_doc`. It also describes important limitations of this interface. Please refer to the `Bus class documentation`_ below for configuration options and useful resources diff --git a/doc/interfaces/usb2can.rst b/doc/interfaces/usb2can.rst index 56243d41d..1ac9dd61f 100644 --- a/doc/interfaces/usb2can.rst +++ b/doc/interfaces/usb2can.rst @@ -1,36 +1,35 @@ USB2CAN Interface ================= -OVERVIEW --------- - The `USB2CAN `_ is a cheap CAN interface based on an ARM7 chip (STR750FV2). There is support for this device on Linux through the :doc:`socketcan` interface and for Windows using this ``usb2can`` interface. - -WINDOWS SUPPORT ---------------- - Support though windows is achieved through a DLL very similar to the way the PCAN functions. The API is called CANAL (CAN Abstraction Layer) which is a separate project designed to be used with VSCP which is a socket like messaging system -that is not only cross platform but also supports other types of devices. This device can be used through one of three ways -1)Through python-can -2)CANAL API either using the DLL and C/C++ or through the python wrapper that has been added to this project -3)VSCP -Using python-can is strongly suggested as with little extra work the same interface can be used on both Windows and Linux. +that is not only cross platform but also supports other types of devices. + + +Installation +------------ + +1. To install on Windows download the USB2CAN Windows driver. It is compatible with XP, Vista, Win7, Win8/8.1. (Written against driver version v1.0.2.1) + +2. Install the appropriate version of `pywin32 `_ (win32com) + +3. Download the USB2CAN CANAL DLL from the USB2CAN website. + Place this in either the same directory you are running usb2can.py from or your DLL folder in your python install. + Note that only a 32-bit version is currently available, so this only works in a 32-bit Python environment. + + +Internals +--------- -WINDOWS INSTALL ---------------- +This interface originally written against CANAL DLL version ``v1.0.6``. - 1. To install on Windows download the USB2CAN Windows driver. It is compatible with XP, Vista, Win7, Win8/8.1. (Written against driver version v1.0.2.1) - 2. Install the appropriate version of `pywin32 `_ (win32com) - 3. Download the USB2CAN CANAL DLL from the USB2CAN website. Place this in either the same directory you are running usb2can.py from or your DLL folder in your python install. - Note that only a 32-bit version is currently available, so this only works in a 32-bit Python environment. - (Written against CANAL DLL version v1.0.6) Interface Layout ----------------- +~~~~~~~~~~~~~~~~ - ``usb2canabstractionlayer.py`` This file is only a wrapper for the CANAL API that the interface expects. There are also a couple of constants here to try and make dealing with the @@ -50,20 +49,26 @@ Interface Layout Interface Specific Items ------------------------ -There are a few things that are kinda strange about this device and are not overly obvious about the code or things that are not done being implemented in the DLL. - -1. You need the Serial Number to connect to the device under Windows. This is part of the "setup string" that configures the device. There are a few options for how to get this. - 1. Use usb2canWin.py to find the serial number - 2. Look on the device and enter it either through a prompt/barcode scanner/hardcode it.(Not recommended) - 3. Reprogram the device serial number to something and do that for all the devices you own. (Really Not Recommended, can no longer use multiple devices on one computer) +There are a few things that are kinda strange about this device and are not overly obvious about the code or things that +are not done being implemented in the DLL. + +1. You need the Serial Number to connect to the device under Windows. This is part of the "setup string" that configures the device. There are a few options for how to get this. + + 1. Use ``usb2canWin.py`` to find the serial number. + 2. Look on the device and enter it either through a prompt/barcode scanner/hardcode it. (Not recommended) + 3. Reprogram the device serial number to something and do that for all the devices you own. (Really Not Recommended, can no longer use multiple devices on one computer) -2. In usb2canabstractionlayer.py there is a structure called CanalMsg which has a unsigned byte array of size 8. In the usb2canInterface file it passes in an unsigned byte array of - size 8 also which if you pass less than 8 bytes in it stuffs it with extra zeros. So if the data "01020304" is sent the message would look like "0102030400000000". - There is also a part of this structure called sizeData which is the actual length of the data that was sent not the stuffed message (in this case would be 4). - What then happens is although a message of size 8 is sent to the device only the length of information so the first 4 bytes of information would be sent. This - is done because the DLL expects a length of 8 and nothing else. So to make it compatible that has to be sent through the wrapper. If usb2canInterface sent an - array of length 4 with sizeData of 4 as well the array would throw an incompatible data type error. There is a Wireshark file posted in Issue #36 that demonstrates - that the bus is only sending the data and not the extra zeros. +2. In ``usb2canabstractionlayer.py`` there is a structure called ``CanalMsg`` which has a unsigned byte array of size 8. + In the ``usb2canInterface`` file it passes in an unsigned byte array of size 8 also which if you pass less than 8 + bytes in it stuffs it with extra zeros. So if the data ``"01020304"`` is sent the message would look like + ``"0102030400000000"``. + + There is also a part of this structure called ``sizeData`` which is the actual length of the data that was sent not + the stuffed message (in this case would be 4). What then happens is although a message of size 8 is sent to the device + only the first 4 bytes of information would be sent. This is done because the DLL expects a length of 8 and nothing + else. So to make it compatible that has to be sent through the wrapper. If ``usb2canInterface`` sent an + array of length 4 with sizeData of 4 as well the array would throw an incompatible data type error. + 3. The masking features have not been implemented currently in the CANAL interface in the version currently on the USB2CAN website. @@ -79,12 +84,16 @@ Bus .. autoclass:: can.interfaces.usb2can.Usb2canBus +Exceptions +---------- + +.. autoexception:: can.interfaces.usb2can.usb2canabstractionlayer.CanalError -Internals ---------- + +Miscellaneous +------------- .. autoclass:: can.interfaces.usb2can.Usb2CanAbstractionLayer :members: :undoc-members: -.. autoexception:: can.interfaces.usb2can.usb2canabstractionlayer.CanalError diff --git a/doc/interfaces/vector.rst b/doc/interfaces/vector.rst index 7f9aa1f3f..56961e7e2 100644 --- a/doc/interfaces/vector.rst +++ b/doc/interfaces/vector.rst @@ -3,6 +3,9 @@ Vector This interface adds support for CAN controllers by `Vector`_. Only Windows is supported. +Configuration +------------- + By default this library uses the channel configuration for CANalyzer. To use a different application, open **Vector Hardware Configuration** program and create a new application and assign the channels you may want to use. diff --git a/doc/interfaces/virtual.rst b/doc/interfaces/virtual.rst index 29976ed47..7569ffeb9 100644 --- a/doc/interfaces/virtual.rst +++ b/doc/interfaces/virtual.rst @@ -8,79 +8,9 @@ Any `VirtualBus` instances connecting to the same channel (from within the same process) will receive each others messages. If messages shall be sent across process or host borders, consider using the -:ref:`udp_multicast_doc` and refer to (:ref:`the next section `) +:ref:`udp_multicast_doc` and refer to :ref:`virtual_interfaces_doc` for a comparison and general discussion of different virtual interfaces. -.. _other_virtual_interfaces: - -Other Virtual Interfaces ------------------------- - -There are quite a few implementations for CAN networks that do not require physical -CAN hardware. -This section also describes common limitations of current virtual interfaces. - -Comparison -'''''''''' - -The following table compares some known virtual interfaces: - -+----------------------------------------------------+-----------------------------------------------------------------------+---------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ -| **Name** | **Availability** | **Applicability** | **Implementation** | -| | +-----------+-------------+-------------+--------------------+---------------------------------------------+---------------------------------------------------------------------+ -| | | **Within | **Between | **Via (IP) | **Without Central | **Transport | **Serialization | -| | | Process** | Processes** | Networks** | Server** | Technology** | Format** | -+----------------------------------------------------+-----------------------------------------------------------------------+-----------+-------------+-------------+--------------------+---------------------------------------------+---------------------------------------------------------------------+ -| ``virtual`` (this) | *included* | ✓ | ✗ | ✗ | ✓ | Singleton & Mutex | none | -| | | | | | | (reliable) | | -+----------------------------------------------------+-----------------------------------------------------------------------+-----------+-------------+-------------+--------------------+---------------------------------------------+---------------------------------------------------------------------+ -| ``udp_multicast`` (:ref:`doc `) | *included* | ✓ | ✓ | ✓ | ✓ | UDP via IP multicast | custom using `msgpack `__ | -| | | | | | | (unreliable) | | -+----------------------------------------------------+-----------------------------------------------------------------------+-----------+-------------+-------------+--------------------+---------------------------------------------+---------------------------------------------------------------------+ -| *christiansandberg/ | `external `__ | ✓ | ✓ | ✓ | ✗ | Websockets via TCP/IP | custom binary | -| python-can-remote* | | | | | | (reliable) | | -+----------------------------------------------------+-----------------------------------------------------------------------+-----------+-------------+-------------+--------------------+---------------------------------------------+---------------------------------------------------------------------+ -| *windelbouwman/ | `external `__ | ✓ | ✓ | ✓ | ✗ | `ZeroMQ `__ via TCP/IP | custom binary [#f1]_ | -| virtualcan* | | | | | | (reliable) | | -+----------------------------------------------------+-----------------------------------------------------------------------+-----------+-------------+-------------+--------------------+---------------------------------------------+---------------------------------------------------------------------+ - -.. [#f1] - The only option in this list that implements interoperability with other languages - out of the box. For the others (except the first intra-process one), other programs written - in potentially different languages could effortlessly interface with the bus - once they mimic the serialization format. The last one, however, has already implemented - the entire bus functionality in *C++* and *Rust*, besides the Python variant. - -Common Limitations -'''''''''''''''''' - -**Guaranteed delivery** and **message ordering** is one major point of difference: -While in a physical CAN network, a message is either sent or in queue (or an explicit error occurred), -this may not be the case for virtual networks. -The ``udp_multicast`` bus for example, drops this property for the benefit of lower -latencies by using unreliable UDP/IP instead of reliable TCP/IP (and because normal IP multicast -is inherently unreliable, as the recipients are unknown by design). The other three buses faithfully -model a physical CAN network in this regard: They ensure that all recipients actually receive -(and acknowledge each message), much like in a physical CAN network. They also ensure that -messages are relayed in the order they have arrived at the central server and that messages -arrive at the recipients exactly once. Both is not guaranteed to hold for the best-effort -``udp_multicast`` bus as it uses UDP/IP as a transport layer. - -**Central servers** are, however, required by interfaces 3 and 4 (the external tools) to provide -these guarantees of message delivery and message ordering. The central servers receive and distribute -the CAN messages to all other bus participants, unlike in a real physical CAN network. -The first intra-process ``virtual`` interface only runs within one Python process, effectively the -Python instance of :class:`~can.interfaces.virtual.VirtualBus` acts as a central server. -Notably the ``udp_multicast`` bus does not require a central server. - -**Arbitration and throughput** are two interrelated functions/properties of CAN networks which -are typically abstracted in virtual interfaces. In all four interfaces, an unlimited amount -of messages can be sent per unit of time (given the computational power of the machines and -networks that are involved). In a real CAN/CAN FD networks, however, throughput is usually much -more restricted and prioritization of arbitration IDs is thus an important feature once the bus -is starting to get saturated. None of the interfaces presented above support any sort of throttling -or ID arbitration under high loads. - Example ------- diff --git a/doc/internal-api.rst b/doc/internal-api.rst index 3ef599598..b8c108fb5 100644 --- a/doc/internal-api.rst +++ b/doc/internal-api.rst @@ -7,6 +7,15 @@ Here we document the odds and ends that are more helpful for creating your own i or listeners but generally shouldn't be required to interact with python-can. +BusABC +------ + +The :class:`~can.BusABC` class, as the name suggests, provides an abstraction of a CAN bus. +The bus provides a wrapper around a physical or virtual CAN Bus. + +An interface specific instance of the :class:`~can.BusABC` is created by the :class:`~can.Bus` +class, see :ref:`bus` for the user facing API. + .. _businternals: diff --git a/doc/listeners.rst b/doc/listeners.rst index ad18aff24..260854d2a 100644 --- a/doc/listeners.rst +++ b/doc/listeners.rst @@ -1,5 +1,18 @@ -Listeners -========= + +Reading and Writing Messages +============================ + +.. _notifier: + +Notifier +-------- + +The Notifier object is used as a message distributor for a bus. Notifier creates a thread to read messages from the bus and distributes them to listeners. + +.. autoclass:: can.Notifier + :members: + +.. _listeners_doc: Listener -------- @@ -12,6 +25,12 @@ message, or by calling the method **on_message_received**. Listeners are registered with :ref:`notifier` object(s) which ensure they are notified whenever a new message is received. +.. literalinclude:: ../examples/print_notifier.py + :language: python + :linenos: + :emphasize-lines: 8,9 + + Subclasses of Listener that do not override **on_message_received** will cause :class:`NotImplementedError` to be thrown when a message is received on the CAN bus. @@ -191,3 +210,20 @@ The following class can be used to read messages from BLF file: .. autoclass:: can.BLFReader :members: + +TRC +---- + +Implements basic support for the TRC file format. + + +.. note:: + Comments and contributions are welcome on what file versions might be relevant. + +.. autoclass:: can.TRCWriter + :members: + +The following class can be used to read messages from TRC file: + +.. autoclass:: can.TRCReader + :members: diff --git a/doc/plugin-interface.rst b/doc/plugin-interface.rst new file mode 100644 index 000000000..14c3f51d5 --- /dev/null +++ b/doc/plugin-interface.rst @@ -0,0 +1,54 @@ + +.. _plugin interface: + +Plugin Interface +================ + +External packages can register new interfaces by using the ``can.interface`` entry point +in its project configuration. The format of the entry point depends on your project +configuration format (*pyproject.toml*, *setup.cfg* or *setup.py*). + +In the following example ``module`` defines the location of your bus class inside your +package e.g. ``my_package.subpackage.bus_module`` and ``classname`` is the name of +your :class:`can.BusABC` subclass. + +.. tab:: pyproject.toml (PEP 621) + + .. code-block:: toml + + # Note the quotes around can.interface in order to escape the dot . + [project.entry-points."can.interface"] + interface_name = "module:classname" + +.. tab:: setup.cfg + + .. code-block:: ini + + [options.entry_points] + can.interface = + interface_name = module:classname + +.. tab:: setup.py + + .. code-block:: python + + from setuptools import setup + + setup( + # ..., + entry_points = { + 'can.interface': [ + 'interface_name = module:classname' + ] + } + ) + +The ``interface_name`` can be used to +create an instance of the bus in the **python-can** API: + +.. code-block:: python + + import can + + bus = can.Bus(interface="interface_name", channel=0) + diff --git a/doc/scripts.rst b/doc/scripts.rst index 6b9bdf504..5a615afa7 100644 --- a/doc/scripts.rst +++ b/doc/scripts.rst @@ -1,7 +1,7 @@ Scripts ======= -The following modules are callable from python-can. +The following modules are callable from ``python-can``. They can be called for example by ``python -m can.logger`` or ``can_logger.py`` (if installed using pip). diff --git a/doc/utils.rst b/doc/utils.rst new file mode 100644 index 000000000..a87d411a9 --- /dev/null +++ b/doc/utils.rst @@ -0,0 +1,7 @@ +Utilities +--------- + + +.. autofunction:: can.detect_available_configs + + diff --git a/doc/virtual-interfaces.rst b/doc/virtual-interfaces.rst new file mode 100644 index 000000000..70ac601fa --- /dev/null +++ b/doc/virtual-interfaces.rst @@ -0,0 +1,77 @@ + +.. _virtual_interfaces_doc: + +Virtual Interfaces +================== + +There are quite a few implementations for CAN networks that do not require physical +CAN hardware. The built in virtual interfaces are: + +.. toctree:: + :maxdepth: 1 + + interfaces/virtual + interfaces/udp_multicast + + +Comparison +---------- + +The following table compares some known virtual interfaces: + ++----------------------------------------------------+-----------------------------------------------------------------------+---------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ +| **Name** | **Availability** | **Applicability** | **Implementation** | +| | +-----------+-------------+-------------+--------------------+---------------------------------------------+---------------------------------------------------------------------+ +| | | **Within | **Between | **Via (IP) | **Without Central | **Transport | **Serialization | +| | | Process** | Processes** | Networks** | Server** | Technology** | Format** | ++----------------------------------------------------+-----------------------------------------------------------------------+-----------+-------------+-------------+--------------------+---------------------------------------------+---------------------------------------------------------------------+ +| ``virtual`` (this) | *included* | ✓ | ✗ | ✗ | ✓ | Singleton & Mutex | none | +| | | | | | | (reliable) | | ++----------------------------------------------------+-----------------------------------------------------------------------+-----------+-------------+-------------+--------------------+---------------------------------------------+---------------------------------------------------------------------+ +| ``udp_multicast`` (:ref:`doc `) | *included* | ✓ | ✓ | ✓ | ✓ | UDP via IP multicast | custom using `msgpack `__ | +| | | | | | | (unreliable) | | ++----------------------------------------------------+-----------------------------------------------------------------------+-----------+-------------+-------------+--------------------+---------------------------------------------+---------------------------------------------------------------------+ +| *christiansandberg/ | `external `__ | ✓ | ✓ | ✓ | ✗ | Websockets via TCP/IP | custom binary | +| python-can-remote* | | | | | | (reliable) | | ++----------------------------------------------------+-----------------------------------------------------------------------+-----------+-------------+-------------+--------------------+---------------------------------------------+---------------------------------------------------------------------+ +| *windelbouwman/ | `external `__ | ✓ | ✓ | ✓ | ✗ | `ZeroMQ `__ via TCP/IP | custom binary [#f1]_ | +| virtualcan* | | | | | | (reliable) | | ++----------------------------------------------------+-----------------------------------------------------------------------+-----------+-------------+-------------+--------------------+---------------------------------------------+---------------------------------------------------------------------+ + +.. [#f1] + The only option in this list that implements interoperability with other languages + out of the box. For the others (except the first intra-process one), other programs written + in potentially different languages could effortlessly interface with the bus + once they mimic the serialization format. The last one, however, has already implemented + the entire bus functionality in *C++* and *Rust*, besides the Python variant. + +Common Limitations +------------------ + +**Guaranteed delivery** and **message ordering** is one major point of difference: +While in a physical CAN network, a message is either sent or in queue (or an explicit error occurred), +this may not be the case for virtual networks. +The ``udp_multicast`` bus for example, drops this property for the benefit of lower +latencies by using unreliable UDP/IP instead of reliable TCP/IP (and because normal IP multicast +is inherently unreliable, as the recipients are unknown by design). The other three buses faithfully +model a physical CAN network in this regard: They ensure that all recipients actually receive +(and acknowledge each message), much like in a physical CAN network. They also ensure that +messages are relayed in the order they have arrived at the central server and that messages +arrive at the recipients exactly once. Both is not guaranteed to hold for the best-effort +``udp_multicast`` bus as it uses UDP/IP as a transport layer. + +**Central servers** are, however, required by interfaces 3 and 4 (the external tools) to provide +these guarantees of message delivery and message ordering. The central servers receive and distribute +the CAN messages to all other bus participants, unlike in a real physical CAN network. +The first intra-process ``virtual`` interface only runs within one Python process, effectively the +Python instance of :class:`~can.interfaces.virtual.VirtualBus` acts as a central server. +Notably the ``udp_multicast`` bus does not require a central server. + +**Arbitration and throughput** are two interrelated functions/properties of CAN networks which +are typically abstracted in virtual interfaces. In all four interfaces, an unlimited amount +of messages can be sent per unit of time (given the computational power of the machines and +networks that are involved). In a real CAN/CAN FD networks, however, throughput is usually much +more restricted and prioritization of arbitration IDs is thus an important feature once the bus +is starting to get saturated. None of the interfaces presented above support any sort of throttling +or ID arbitration under high loads. + diff --git a/examples/print_notifier.py b/examples/print_notifier.py new file mode 100755 index 000000000..bbead7d15 --- /dev/null +++ b/examples/print_notifier.py @@ -0,0 +1,19 @@ +import time +import can + + +def main(): + + with can.Bus(receive_own_messages=True) as bus: + print_listener = can.Printer() + can.Notifier(bus, [print_listener]) + + bus.send(can.Message(arbitration_id=1, is_extended_id=True)) + bus.send(can.Message(arbitration_id=2, is_extended_id=True)) + bus.send(can.Message(arbitration_id=1, is_extended_id=False)) + + time.sleep(1.0) + + +if __name__ == "__main__": + main() diff --git a/examples/vcan_filtered.py b/examples/vcan_filtered.py index a43fbe821..d48a9d8cb 100755 --- a/examples/vcan_filtered.py +++ b/examples/vcan_filtered.py @@ -16,7 +16,7 @@ def main(): can_filters = [{"can_id": 1, "can_mask": 0xF, "extended": True}] bus.set_filters(can_filters) - # print all incoming messages, wich includes the ones sent, + # print all incoming messages, which includes the ones sent, # since we set receive_own_messages to True # assign to some variable so it does not garbage collected notifier = can.Notifier(bus, [can.Printer()]) # pylint: disable=unused-variable