Skip to content

Latest commit

 

History

History
231 lines (156 loc) · 5.89 KB

File metadata and controls

231 lines (156 loc) · 5.89 KB

Working with python-can in Linux

Overview

python-can is a powerful Python library for working with CAN (Controller Area Network) interfaces. It provides a convenient API for sending, receiving, logging, and interpreting CAN messages, and is widely used in vehicle diagnostics, research, and cybersecurity tasks.

This tutorial will walk you through installing, configuring, and using python-can on a Linux system with SocketCAN support.


Learning Objectives

By the end of this chapter, you will be able to:

  • Install and configure python-can on a Linux machine
  • Set up a virtual or physical CAN interface using SocketCAN
  • Write and run Python scripts that send and receive CAN messages
  • Understand best practices for logging and analyzing CAN traffic

1. Prerequisites

  • A Linux system (Ubuntu or Debian-based preferred)
  • python3 and pip installed
  • CAN interface (USB-CAN adapter like PEAK, ValueCAN, or virtual vcan)

2. Installation

Install the python-can package using pip:

pip install python-can

To verify installation:

python3 -c "import can; print(can.__version__)"

To set the default interface to using the .canrc configuration file for python-can, you need to create or edit the .canrc file in your home directory. Here is a step-by-step guide:

Step 1: Create or Edit .canrc

Create a .canrc file in your home directory if it doesn't already exist, and configure it to use vcan0 as the default interface.

nano ~/.canrc

Add the following content to the .canrc file:

[default]
interface = socketcan
channel = vcan0
#channel = can0
bitrate = 500000

This configuration sets socketcan as the interface type, vcan0 as the channel, and a bitrate of 500000. Change channel to your interface name like vcan0 or can0.

Step 2: Python Script to Use the Configuration

Here's how you can create a Python script that uses the vcan0 interface configured in .canrc:

import can

def setup_can_interface():
    # Set up the CAN bus using the default interface set in .canrc
    can_bus = can.interface.Bus()
    return can_bus

def main():
    # Set up the CAN interface
    can_bus = setup_can_interface()

    # Example: Send a CAN message
    message = can.Message(arbitration_id=0x123, data=[0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88], is_extended_id=False)
    try:
        can_bus.send(message)
        print("Message sent on vcan0")
    except can.CanError:
        print("Message NOT sent")

    # Example: Receive a CAN message
    try:
        received_message = can_bus.recv(timeout=1.0)
        if received_message:
            print(f"Message received: {received_message}")
        else:
            print("No message received within timeout period")
    except can.CanError:
        print("Error receiving message")

if __name__ == "__main__":
    main()

Explanation:

  1. Setup CAN Interface:

    • The setup_can_interface function initializes the CAN interface using the configuration specified in the .canrc file.
  2. Main Function:

    • It sets up the CAN interface by calling setup_can_interface.
    • It sends a sample CAN message.
    • It receives a CAN message with a timeout of 1 second.

Running the Script

After setting up the vcan0 interface and configuring the .canrc file, you can run the Python script:

python your_script_name.py

Make sure to replace your_script_name.py with the actual name of your Python script file.

This example sets python-can to use vcan0 as the default CAN interface based on the .canrc configuration. You can change this to can0 or whatever other interface you wish to use.


3. Configuring the CAN Interface

A. Using Virtual CAN (vcan) for Testing

Create and bring up a virtual CAN interface:

sudo modprobe vcan
sudo ip link add dev vcan0 type vcan
sudo ip link set up vcan0

B. Using a Physical CAN Adapter

For a USB CAN adapter using SocketCAN:

sudo ip link set can0 up type can bitrate 500000
sudo ifconfig can0 up

Replace can0 with the correct interface name (ip link show can help).


4. Sending and Receiving Messages

A. Minimal Listener Script

import can

bus = can.interface.Bus(channel='vcan0', bustype='socketcan')
print("Listening for messages...")
for msg in bus:
    print(msg)

B. Sending a CAN Message

import can

bus = can.interface.Bus(channel='vcan0', bustype='socketcan')
msg = can.Message(arbitration_id=0x123, data=[0x11, 0x22, 0x33], is_extended_id=False)

try:
    bus.send(msg)
    print("Message sent")
except can.CanError:
    print("Message NOT sent")

5. Logging CAN Traffic to a File

Use can.Logger to save messages:

import can

bus = can.interface.Bus(channel='vcan0', bustype='socketcan')
logger = can.Logger("logfile.log")

for i in range(10):
    msg = bus.recv(timeout=1.0)
    if msg:
        logger(msg)
        print(f"Logged: {msg}")

6. Best Practices

  • Use virtual CAN for testing before touching a real vehicle
  • Log everything — CAN traffic is noisy and transient
  • Introduce delays when sending many messages to avoid buffer overflows
  • Always match bitrate with the vehicle network

7. Troubleshooting

Issue Solution
OSError: No such device Interface not set up — check with ip link
can.CanError on send Bus might be down or misconfigured
No messages received Try candump any in another terminal

8. Additional Resources

  • python-can documentation
  • can-utils (candump, cansend) for quick CLI tests
  • SocketCAN developer documentation
  • Open DBC databases for message decoding