Source

python-socket-examples / real_raw_can.py

'''
Assumes a can0 interface with a device connected somewhat 
like "button_can.lua" that is sending heartbeat messages
with ID=0xFF and direction messages with ID=0x42 whenever
a button press is detected.

To add can interface:
    sudo ip link set can0 up type can bitrate 1000000

To start eLua spamming messages:
    miniterm.py --port=/dev/ttyUSB0 --baud=115200
    
    lua /mmc/bcan.lua
    
Should be able to watch along in wireshark.
'''
import time
import logging

from common_can import *

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

def filtered_receiver(stop_event, can_id=0x00FF, outgoing=None):
    '''
    A "filtered" receiver only receives can messages 
    with the given ID.
        
    :param threading.Event stop_event:
        Set when this should stop waiting.
    
    :param int can_id:
        Filter messages with this id frame.
    
    :param queue.Queue outgoing:
        If given received data will be passed in order into this queue
    '''
    # create a raw socket
    s = socket.socket(socket.AF_CAN, socket.SOCK_RAW, socket.CAN_RAW)
    
    # We can only filter on just the bits of the can_id in this mask:
    can_mask = 0x00F0
    # Create the filter
    rfilter = struct.pack(can_filter_fmt, can_id, can_mask)
    
    # Pass those filter options to the kernel via socket.setsockopt
    s.setsockopt(socket.SOL_CAN_RAW, socket.CAN_RAW_FILTER, rfilter)
    
    #bind our CAN socket to the 'can0' network interface
    s.bind(('can0',))
    
    start_time = time.time()
    while not stop_event.is_set():
        cf = s.recv(can_frame_size)
        frame_id, frame_dlc, frame_data = dissect_can_frame(cf)
        elapsed = time.time() - start_time
        if outgoing is not None:
            outgoing.put(frame_data)
        else:
            print('%6.3f - Filtered can receiver received data: %s' % (elapsed, frame_data))
    print("Stopping the filtered receiver")


if __name__ == "__main__":
    stop = threading.Event()
    # Start a heartbeat monitor
    threading.Thread(target=filtered_receiver, args=(stop,)).start()
    # Start a direction message monitor
    threading.Thread(target=filtered_receiver, args=(stop,0x0042)).start()
    time.sleep(5)
    stop.set()