Controller Area Network interface module for Python providing common abstractions for CAN hardware devices and message handling utilities
—
Support for 20+ different CAN hardware interfaces enabling cross-platform CAN communication on Linux, Windows, and macOS. Python-CAN provides a unified API that abstracts hardware differences while allowing access to interface-specific features.
Discover available CAN interfaces and their configurations automatically.
VALID_INTERFACES: frozenset[str]
"""Set of all supported interface names."""
def detect_available_configs() -> list[dict]:
"""
Detect all available CAN configurations across all interfaces.
Returns:
List of configuration dictionaries suitable for Bus() constructor
Each dict contains interface-specific connection parameters
Note: May be time-consuming as it probes all interfaces
"""Native Linux CAN interface with kernel-level filtering and high performance.
# Interface name: 'socketcan'
# Channels: 'can0', 'can1', 'vcan0', etc.
# Features: Hardware filtering, high throughput, native Linux support
bus = can.Bus(channel='can0', interface='socketcan')Professional CAN interfaces from Vector Informatik for automotive development.
# Interface name: 'vector'
# Channels: Hardware-dependent (e.g., 0, 1 for CANoe/CANalyzer)
# Features: High-precision timestamps, advanced filtering, automotive protocols
bus = can.Bus(channel=0, interface='vector', app_name='MyApp')PCAN interfaces for automotive and industrial applications.
# Interface name: 'pcan'
# Channels: 'PCAN_USBBUS1', 'PCAN_USBBUS2', etc.
# Features: Wide hardware range, Windows/Linux support
bus = can.Bus(channel='PCAN_USBBUS1', interface='pcan', bitrate=500000)Professional CAN interfaces with advanced features and analysis tools.
# Interface name: 'kvaser'
# Channels: Hardware channel numbers (0, 1, 2, etc.)
# Features: Advanced timestamps, scripting support, extensive hardware range
bus = can.Bus(channel=0, interface='kvaser')Software-only CAN interface for testing and simulation without hardware.
# Interface name: 'virtual'
# Channels: Any string identifier
# Features: No hardware required, multiple virtual buses, message routing
bus = can.Bus(channel='test', interface='virtual')CAN communication over serial connections using various protocols.
# Interface name: 'serial'
# Channels: Serial port names ('/dev/ttyUSB0', 'COM1', etc.)
# Features: Low-cost hardware, works with many adapters
bus = can.Bus(channel='/dev/ttyUSB0', interface='serial',
baudrate=115200, timeout=0.1)Various USB-to-CAN adapter support including common low-cost interfaces.
# Interface name: 'usb2can'
# Channels: Device-dependent
# Features: Plug-and-play USB, multiple vendor support
bus = can.Bus(channel=0, interface='usb2can')HMS Industrial Networks (IXXAT) CAN interfaces for industrial applications.
# Interface name: 'ixxat'
# Channels: Hardware channel numbers
# Features: Industrial-grade hardware, Windows support
bus = can.Bus(channel=0, interface='ixxat', bitrate=250000)Support for many other CAN hardware vendors and protocols.
# National Instruments
'nican' # NI-CAN interfaces
'nixnet' # NI-XNET interfaces
# Specialized hardware
'gs_usb' # Candlelight/GS_USB compatible devices
'cantact' # CANtact devices
'slcan' # Serial Line CAN protocol
'robotell' # Robotell CAN interfaces
'canalystii' # CANalyst-II devices
'systec' # SYS TEC electronic devices
'seeedstudio' # Seeed Studio CAN devices
'neousys' # Neousys CAN devices
'etas' # ETAS CAN interfaces
# Network protocols
'udp_multicast' # UDP multicast CAN
'socketcand' # SocketCAN daemonAccess to interface-specific configuration options and capabilities.
def _get_class_for_interface(interface: str) -> type[BusABC]:
"""
Get the bus class for a specific interface.
Parameters:
- interface: Interface name from VALID_INTERFACES
Returns:
Bus class for the interface
Raises:
- NotImplementedError: Unknown interface
- CanInterfaceNotImplementedError: Interface not available
"""import can
# Find all available CAN configurations
configs = can.detect_available_configs()
for config in configs:
print(f"Interface: {config['interface']}")
print(f"Channel: {config['channel']}")
print(f"Additional options: {config}")
print("---")
# Use first available configuration
if configs:
bus = can.Bus(**configs[0])
print(f"Connected to: {bus.channel_info}")
bus.shutdown()import can
import platform
# Choose interface based on platform
system = platform.system()
if system == "Linux":
# Use SocketCAN on Linux
interface = 'socketcan'
channel = 'can0'
elif system == "Windows":
# Use Vector or PCAN on Windows
interface = 'vector' # or 'pcan'
channel = 0 # or 'PCAN_USBBUS1'
else:
# Use virtual interface as fallback
interface = 'virtual'
channel = 'test'
bus = can.Bus(channel=channel, interface=interface)
print(f"Using {interface} interface on {system}")import can
# SocketCAN with kernel filtering
socketcan_bus = can.Bus(
channel='can0',
interface='socketcan',
can_filters=[
{"can_id": 0x123, "can_mask": 0x7FF, "extended": False}
]
)
# Vector with application name and specific timing
vector_bus = can.Bus(
channel=0,
interface='vector',
app_name='MyCANApp',
bitrate=500000,
data_bitrate=2000000 # CAN FD data phase
)
# PCAN with specific bitrate
pcan_bus = can.Bus(
channel='PCAN_USBBUS1',
interface='pcan',
bitrate=250000
)
# Serial interface with custom parameters
serial_bus = can.Bus(
channel='/dev/ttyUSB0',
interface='serial',
baudrate=115200,
timeout=0.1
)import can
try:
bus = can.Bus(channel='can0', interface='socketcan')
print("SocketCAN interface available")
except can.CanInterfaceNotImplementedError:
print("SocketCAN not available, trying virtual interface")
try:
bus = can.Bus(channel='test', interface='virtual')
print("Using virtual interface")
except can.CanInterfaceNotImplementedError:
print("No interfaces available")
bus = None
if bus:
# Use the bus
bus.shutdown()import can
import threading
import time
def bridge_messages(source_bus, dest_bus, stop_event):
"""Bridge messages between two CAN buses."""
while not stop_event.is_set():
msg = source_bus.recv(timeout=0.1)
if msg:
try:
dest_bus.send(msg)
print(f"Bridged: {msg}")
except Exception as e:
print(f"Bridge error: {e}")
# Create buses on different interfaces
bus1 = can.Bus(channel='can0', interface='socketcan')
bus2 = can.Bus(channel='test', interface='virtual')
# Start bidirectional bridging
stop_event = threading.Event()
thread1 = threading.Thread(target=bridge_messages, args=(bus1, bus2, stop_event))
thread2 = threading.Thread(target=bridge_messages, args=(bus2, bus1, stop_event))
thread1.start()
thread2.start()
# Run for 10 seconds
time.sleep(10)
stop_event.set()
thread1.join()
thread2.join()
bus1.shutdown()
bus2.shutdown()from typing import Dict, List, Any, Tuple
from abc import ABC
# Backend configuration
BACKENDS: Dict[str, Tuple[str, str]]
"""Maps interface names to (module_name, class_name) tuples."""
# Auto-detected configuration
AutoDetectedConfig = Dict[str, Any]
"""Configuration dictionary suitable for Bus() constructor."""
# Interface capabilities
class BusABC(ABC):
"""Abstract base class defining interface requirements."""
@staticmethod
def _detect_available_configs() -> List[AutoDetectedConfig]:
"""Detect configurations for this specific interface."""Install with Tessl CLI
npx tessl i tessl/pypi-python-can