Source

python-socket-examples / raw_can.py

'''
https://gitorious.org/linux-can

Add a virtual can interface:
    sudo modprobe vcan
    sudo ip link add dev vcan0 type vcan
    sudo ifconfig vcan0 up

Then watch along in wireshark.
'''

from common_can import *

can_filter_fmt = "=2I"
can_filter_size = struct.calcsize(can_filter_fmt)

def filtered_receiver(start, stop_event):
    '''
    A "filtered" receiver only gets can messages with the ID it signs up for.
    '''
    # create a raw socket and bind it to the 'vcan0' interface
    s = socket.socket(socket.AF_CAN, socket.SOCK_RAW, socket.CAN_RAW)
    
    # Create the filter
    can_id   = 0x200 # Filter messages with this id frame
    can_mask = 0xF00
    rfilter = struct.pack(can_filter_fmt, can_id, can_mask)
    s.setsockopt(socket.SOL_CAN_RAW, socket.CAN_RAW_FILTER, rfilter)
    
    s.bind(('vcan0',))
    start.set()
    while not stop_event.is_set():
        cf = s.recv(can_frame_size)
        print('Filtered can receiver got:\ncan_id=%x, can_dlc=%x, data=%s' % dissect_can_frame(cf))
    print("Stopping the receiver")

def sender():
    # create a raw socket and bind it to the 'vcan0' interface
    s = socket.socket(socket.AF_CAN, socket.SOCK_RAW, socket.CAN_RAW)
    s.bind(('vcan0',))
    
    def send_can_frame(cf):
        try:
            s.send(cf)
        except OSError:
            print('Error sending CAN frame')
    
    for i in range(255):
        outgoing_data = bytearray(8)
        outgoing_data[:4] = b'\x01\x02\x03\x00'
        outgoing_data[5] = i
        send_can_frame(build_can_frame(0x01, outgoing_data))
        send_can_frame(build_can_frame(0x200, outgoing_data))

start = threading.Event()
stop = threading.Event()
threading.Thread(target=filtered_receiver, args=(start,stop)).start()
start.wait()    # block until the reader is ready to receive messages.
sending_thread = threading.Thread(target=sender)
sending_thread.start()
sending_thread.join()
# Once the sender has finished stop reading
stop.set()
# Force the reader to finish by sending one last message
sender()