Skip to content

Commit

Permalink
First pass of documentation update (#102)
Browse files Browse the repository at this point in the history

 - Updated docuemntation
 - Replaced `squash_stmin_requirements ` with `override_receiver_stmin`
  • Loading branch information
pylessard authored Nov 29, 2023
1 parent 7031e98 commit 3992f78
Show file tree
Hide file tree
Showing 13 changed files with 244 additions and 162 deletions.
2 changes: 1 addition & 1 deletion doc/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
# built documents.
#
# The short X.Y version.
version = u'1.9'
version = u'2.0'
# The full version, including alpha/beta/rc tags.
release = version

Expand Down
26 changes: 25 additions & 1 deletion doc/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,28 @@ Python support for IsoTP Transport protocol (ISO-15765)

This project is a Python package meant to provide support for IsoTP (ISO-15765) protocol written in Python 3. The code is published under MIT license on GitHub (`pylessard/python-can-isotp <https://github.com/pylessard/python-can-isotp>`_).

This package contains a Python implementation of the protocol that works in the user space that may or may not be coupled with `python-can <https://python-can.readthedocs.io>`_. It also contains a wrapper for a simplified usage of the `Linux SocketCAN IsoTP kernel module <https://github.com/hartkopp/can-isotp>`__
This package contains a Python implementation of the protocol in pure python that works in the user space that may or may not be coupled with `python-can <https://python-can.readthedocs.io>`_.
It also contains a wrapper for a simplified usage of the `Linux SocketCAN IsoTP kernel module <https://github.com/hartkopp/can-isotp>`_

.. note:: You are looking at the isotp v2.x documentation. The legacy `v1.x documentation <https://can-isotp.readthedocs.io/en/v1.x>`_ is still online.

V2.x changes
------------

V2.x addressed several flaws that were present in v1.x. The main change is regarding the timing capabilities of the module. V2.x can achieve much better timing performance than
the previous version by performing blocking IO operations. The CanStack object is also able to use the python-can Notifier which behave better performance-wise

Here is the major API changes to v2.x that might make an application designed with v1.x to break

- The Transport Layer timing is handled into an internal thread, removing the need for the user to periodically call the ``process()`` function.
- The user provided CAN layer receive function ``rxfn`` is expected be blocking for better performance (using the OS asynchronous read capabilities). Non-blocking ``rxfn`` are possible, but the execution of the transport layer will be throttled by calls to ``sleeps()`` to avoid bloating the CPU usage; possibly degrading overall timing
- Some parameter have been modified.

1. ``squash_stmin_requirement`` has been removed and replaced by ``override_receiver_stmin``
2. Deprecated ``ll_data_length`` parameter is not supported anymore. Replaced by ``tx_data_length``

- The transport layer can perform blocking sends, allowing an UDS layer to better handle its timeouts (P2/P2* vs P6 timeouts)
- Some methods dedicated to internal usage have been prefixed with an underscore (``_``) to indicates that they are internals
- The CanStack object uses a Notifier instead of performing ``bus.recv()`` solving the popular issue of a CanStack depleting the receive queue and starving other modules from their incoming messages
- The ``isotp.socket.recv()`` method does not return ``None`` on timeout anymore.
The API now comply with the Python socket API and will raise the proper exception in case of timeout.
120 changes: 48 additions & 72 deletions doc/source/isotp/examples.rst
Original file line number Diff line number Diff line change
@@ -1,99 +1,76 @@
Examples
========

.. _example_transmit_no_thread_can_stack:
.. _example_transmit_can_stack:

Basic transmission with python-can
----------------------------------

.. code-block:: python
import isotp
import logging
import time
import isotp
import logging
import time
from can.interfaces.vector import VectorBus
from can.interfaces.vector import VectorBus
def my_error_handler(error):
logging.warning('IsoTp error happened : %s - %s' % (error.__class__.__name__, str(error)))
def my_error_handler(error):
# Called by a different thread. Make it thread safe.
logging.warning('IsoTp error happened : %s - %s' % (error.__class__.__name__, str(error)))
bus = VectorBus(channel=0, bitrate=500000)
addr = isotp.Address(isotp.AddressingMode.Normal_11bits, rxid=0x123, txid=0x456)
bus = VectorBus(channel=0, bitrate=500000)
addr = isotp.Address(isotp.AddressingMode.Normal_11bits, rxid=0x123, txid=0x456)
stack = isotp.CanStack(bus, address=addr, error_handler=my_error_handler)
stack.send(b'Hello, this is a long payload sent in small chunks')
stack = isotp.CanStack(bus, address=addr, error_handler=my_error_handler)
stack.start()
stack.send(b'Hello, this is a long payload sent in small chunks')
while stack.transmitting():
stack.process()
time.sleep(stack.sleep_time())
while stack.transmitting():
time.sleep(stack.sleep_time())
print("Payload transmission done.")
bus.shutdown()
print("Payload transmission done.")
stack.stop()
bus.shutdown()
-----

.. _example_receive_threaded_can_stack:
.. _example_transmit_can_stack_blocking_send:

Threaded reception with python-can
Basic blocking transmission
----------------------------------

.. code-block:: python
import isotp
import logging
import time
import threading
from can.interfaces.socketcan import SocketcanBus
class ThreadedApp:
def __init__(self):
self.exit_requested = False
self.bus = SocketcanBus(channel='vcan0')
addr = isotp.Address(isotp.AddressingMode.Normal_11bits, rxid=0x123, txid=0x456)
self.stack = isotp.CanStack(self.bus, address=addr, error_handler=self.my_error_handler)
def start(self):
self.exit_requested = False
self.thread = threading.Thread(target = self.thread_task)
self.thread.start()
def stop(self):
self.exit_requested = True
if self.thread.isAlive():
self.thread.join()
def my_error_handler(self, error):
logging.warning('IsoTp error happened : %s - %s' % (error.__class__.__name__, str(error)))
def thread_task(self):
while self.exit_requested == False:
self.stack.process() # Non-blocking
time.sleep(self.stack.sleep_time()) # Variable sleep time based on state machine state
def shutdown(self):
self.stop()
self.bus.shutdown()
if __name__ == '__main__':
app = ThreadedApp()
app.start()
print('Waiting for payload - maximum 5 sec')
t1 = time.time()
while time.time() - t1 < 5:
if app.stack.available():
payload = app.stack.recv()
print("Received payload : %s" % (payload))
break
time.sleep(0.2)
print("Exiting")
app.shutdown()
import isotp
import logging
import time
from can.interfaces.vector import VectorBus
def my_error_handler(error):
# Called by a different thread. Make it thread safe.
logging.warning('IsoTp error happened : %s - %s' % (error.__class__.__name__, str(error)))
bus = SocketcanBus(channel='vcan0')
addr = isotp.Address(isotp.AddressingMode.Normal_11bits, rxid=0x123, txid=0x456)
params = {
'blocking_send' : True
}
stack = isotp.CanStack(bus, address=addr, error_handler=my_error_handler, params=params)
stack.start()
try:
stack.send(b'Hello, this is a long payload sent in small chunks', timeout=1.0)
except isotp.BlockingSendFailure:
# Catches all failure, including isotp.BlockingSendTimeout
print("Failed to transmit")
print("Payload transmission done.")
stack.stop()
bus.shutdown()
-----


.. _example_addressing:

Different type of addresses
Expand Down Expand Up @@ -129,7 +106,6 @@ Sending with functional addressing (broadcast)
stack.send(b'Hello', isotp.TargetAddressType.Functional) # Payload must fit a Single Frame. Functional addressing only works with Single Frames
while stack.transmitting():
stack.process()
time.sleep(stack.sleep_time())
bus.shutdown()
Expand Down
Loading

0 comments on commit 3992f78

Please sign in to comment.