CAN-ISO-TP

2.0.7 · active · verified Thu Apr 16

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.

Common errors

Warnings

Install

Imports

Quickstart

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.

import can
import isotp
import time
import os

# Configure CAN bus (uses 'virtual' bus by default for easy testing)
# For a real setup, replace 'virtual' with your bus type (e.g., 'socketcan', 'peak')
# and 'vcan0' with your channel. For Linux virtual CAN, ensure 'vcan0' is up:
# Example: sudo modprobe vcan; sudo ip link add dev vcan0 type vcan; sudo ip link set up vcan0

bus_type = os.environ.get('CAN_BUSTYPE', 'virtual')
can_channel = os.environ.get('CAN_CHANNEL', 'vcan0')

# Attempt to open the specified CAN bus. Fallback to a mock bus for script execution.
try:
    bus = can.Bus(channel=can_channel, bustype=bus_type)
    print(f"CAN bus opened successfully: {can_channel} ({bus_type})")
except Exception as e:
    print(f"Could not open CAN bus '{can_channel}' with type '{bus_type}'. Error: {e}")
    print("Falling back to a mock virtual bus for demonstration purposes.")
    bus = can.interface.Bus(bustype='virtual', channel='vcan0', is_extended_id=False)

# Define ISO-TP addressing parameters for a physical communication
# rxid: The CAN ID this ISO-TP stack expects to receive (from ECU).
# txid: The CAN ID this ISO-TP stack will send (to ECU).
addr = isotp.Address(
    isotp.TargetAddressType.N_PHYSICAL,
    rxid=0x7E8, 
    txid=0x7E0
)

# Create an ISO-TP stack using the high-level CanStack interface
stack = isotp.stack.CanStack(bus=bus, address=addr)

# Send an ISO-TP message (e.g., a diagnostic service request)
payload_to_send = b'\x22\xF1\x90\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A'
print(f"Sending ISO-TP message ({len(payload_to_send)} bytes): {payload_to_send.hex()}")
stack.send(payload_to_send, timeout=0.5) # Add a timeout for sending

# Wait a short moment for bus activity / reply
time.sleep(0.1)

# Attempt to receive an ISO-TP message (e.g., an ECU response)
print("Attempting to receive ISO-TP message (timeout=1.0s)...")
received_data = stack.recv(timeout=1.0) # Blocking receive with a timeout

if received_data is not None:
    print(f"Received ISO-TP message ({len(received_data)} bytes): {received_data.hex()}")
else:
    print("No ISO-TP message received within the timeout.")

# Clean up the CAN bus
bus.shutdown()
print("CAN bus shut down.")

view raw JSON →