{"id":7064,"library":"can-isotp","title":"CAN-ISO-TP","description":"can-isotp is a Python module that implements the ISO 15765-2 (ISO-TP) protocol on top of python-can. It enables communication over CAN bus for sending and receiving messages larger than 8 bytes, handling segmentation and flow control. The current version is 2.0.7, with frequent bugfix releases and major updates introducing significant API changes.","status":"active","version":"2.0.7","language":"en","source_language":"en","source_url":"https://github.com/pylessard/python-can-isotp","tags":["CAN bus","ISO-TP","automotive","diagnostics","networking"],"install":[{"cmd":"pip install can-isotp","lang":"bash","label":"Install `can-isotp`"}],"dependencies":[{"reason":"Provides the underlying CAN bus interface for `can-isotp`.","package":"python-can"}],"imports":[{"note":"CanStack is the high-level interface for ISO-TP communication, internally managing the TransportLayer.","symbol":"CanStack","correct":"import isotp\nstack = isotp.stack.CanStack(...)"},{"note":"Used to define ISO-TP addressing parameters (Rx/Tx CAN IDs, addressing type).","symbol":"Address","correct":"import isotp\naddr = isotp.Address(...)"},{"note":"Enum for specifying the ISO-TP addressing format (e.g., N_PHYSICAL for direct, N_FUNCTIONAL for broadcast).","symbol":"TargetAddressType","correct":"import isotp\naddr = isotp.Address(isotp.TargetAddressType.N_PHYSICAL, ...)"},{"note":"The lower-level ISO-TP protocol implementation. `CanStack` is generally preferred for common use cases.","symbol":"TransportLayer","correct":"from isotp.protocol import TransportLayer"}],"quickstart":{"code":"import can\nimport isotp\nimport time\nimport os\n\n# Configure CAN bus (uses 'virtual' bus by default for easy testing)\n# For a real setup, replace 'virtual' with your bus type (e.g., 'socketcan', 'peak')\n# and 'vcan0' with your channel. For Linux virtual CAN, ensure 'vcan0' is up:\n# Example: sudo modprobe vcan; sudo ip link add dev vcan0 type vcan; sudo ip link set up vcan0\n\nbus_type = os.environ.get('CAN_BUSTYPE', 'virtual')\ncan_channel = os.environ.get('CAN_CHANNEL', 'vcan0')\n\n# Attempt to open the specified CAN bus. Fallback to a mock bus for script execution.\ntry:\n    bus = can.Bus(channel=can_channel, bustype=bus_type)\n    print(f\"CAN bus opened successfully: {can_channel} ({bus_type})\")\nexcept Exception as e:\n    print(f\"Could not open CAN bus '{can_channel}' with type '{bus_type}'. Error: {e}\")\n    print(\"Falling back to a mock virtual bus for demonstration purposes.\")\n    bus = can.interface.Bus(bustype='virtual', channel='vcan0', is_extended_id=False)\n\n# Define ISO-TP addressing parameters for a physical communication\n# rxid: The CAN ID this ISO-TP stack expects to receive (from ECU).\n# txid: The CAN ID this ISO-TP stack will send (to ECU).\naddr = isotp.Address(\n    isotp.TargetAddressType.N_PHYSICAL,\n    rxid=0x7E8, \n    txid=0x7E0\n)\n\n# Create an ISO-TP stack using the high-level CanStack interface\nstack = isotp.stack.CanStack(bus=bus, address=addr)\n\n# Send an ISO-TP message (e.g., a diagnostic service request)\npayload_to_send = b'\\x22\\xF1\\x90\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\x09\\x0A'\nprint(f\"Sending ISO-TP message ({len(payload_to_send)} bytes): {payload_to_send.hex()}\")\nstack.send(payload_to_send, timeout=0.5) # Add a timeout for sending\n\n# Wait a short moment for bus activity / reply\ntime.sleep(0.1)\n\n# Attempt to receive an ISO-TP message (e.g., an ECU response)\nprint(\"Attempting to receive ISO-TP message (timeout=1.0s)...\")\nreceived_data = stack.recv(timeout=1.0) # Blocking receive with a timeout\n\nif received_data is not None:\n    print(f\"Received ISO-TP message ({len(received_data)} bytes): {received_data.hex()}\")\nelse:\n    print(\"No ISO-TP message received within the timeout.\")\n\n# Clean up the CAN bus\nbus.shutdown()\nprint(\"CAN bus shut down.\")\n","lang":"python","description":"This quickstart demonstrates setting up a virtual CAN bus and an ISO-TP `CanStack` to send and receive a multi-frame message. It includes robust error handling for CAN bus initialization and provides an example of a diagnostic service request and response."},"warnings":[{"fix":"Remove explicit calls to `TransportLayer.process()`. If using `TransportLayer` directly, adapt `rxfn` to respect timeout. Update `squash_stmin_requirement` to `override_receiver_stmin` in configurations.","message":"Version 2.0 introduced significant breaking changes. The `TransportLayer.process()` method was removed as the layer now manages its own timing on an internal thread. Additionally, the `rxfn` callback now expects a blocking function with a timeout, and `squash_stmin_requirement` was renamed to `override_receiver_stmin`.","severity":"breaking","affected_versions":">=2.0"},{"fix":"Upgrade `can-isotp` to version 2.0.6 or newer to resolve this bug. Alternatively, avoid using `blocking_send=True` for single-frame messages in older versions.","message":"Sending single-frame messages (payloads fitting into a single CAN frame) may fail or behave incorrectly when `blocking_send=True` in versions prior to 2.0.6.","severity":"gotcha","affected_versions":"<2.0.6"},{"fix":"Upgrade `can-isotp` to version 2.0.7 or newer to fix the unresponsiveness issue with `NotifierBasedCanStack`.","message":"The `NotifierBasedCanStack` could become unresponsive when a large number of CAN error frames were received, leading to communication stalls.","severity":"gotcha","affected_versions":"<2.0.7"},{"fix":"Ensure you are using `can-isotp` version 2.0.1 or newer for full compatibility with Python 3.7+.","message":"Compatibility issues with Python 3.7 to 3.9 were present in early 2.x releases (e.g., 2.0.0).","severity":"gotcha","affected_versions":"2.0.0-2.0.0"}],"env_vars":null,"last_verified":"2026-04-16T00:00:00.000Z","next_check":"2026-07-15T00:00:00.000Z","problems":[{"fix":"Remove calls to `process()`. As of v2.0, `TransportLayer` manages its own timing internally on a dedicated thread. If using `isotp.stack.CanStack`, this is handled automatically.","cause":"Attempting to call the `process()` method on an `isotp.protocol.TransportLayer` instance after upgrading to `can-isotp` v2.0 or newer.","error":"AttributeError: 'TransportLayer' object has no attribute 'process'"},{"fix":"Replace `squash_stmin_requirement` with `override_receiver_stmin`.","cause":"Using the deprecated `squash_stmin_requirement` parameter in the constructor of `isotp.stack.CanStack` or `isotp.protocol.TransportLayer` after upgrading to `can-isotp` v2.0 or newer.","error":"TypeError: __init__() got an unexpected keyword argument 'squash_stmin_requirement'"},{"fix":"Upgrade `can-isotp` to version 2.0.6 or newer to resolve this sending issue.","cause":"A bug in `can-isotp` versions prior to 2.0.6 prevented correct sending of single-frame messages when `blocking_send` was set to `True`.","error":"ISO-TP single-frame messages fail to send or are dropped when blocking_send=True"},{"fix":"Upgrade `can-isotp` to version 2.0.7 or newer to fix the unresponsiveness issue.","cause":"In `can-isotp` versions prior to 2.0.7, the `NotifierBasedCanStack` could become unresponsive under high error frame rates due to an internal blocking condition.","error":"CAN communication becomes unresponsive or freezes when many error frames are present"}]}