Source

python-socket-examples / common_can.py

Full commit
import threading
import socket
import struct
import sys

req_version = (3,3)
cur_version = sys.version_info
if cur_version < req_version:
    raise ImportError("This Python isn't cool enough for this tom foolery.")

# from linux/can.h
#CAN_BCM = 2

# from linux/can/bcm.h
#TX_SEND = 4

""" CAN frame packing/unpacking (see 'struct can_frame' in <linux/can.h>)
/**
 * struct can_frame - basic CAN frame structure
 * @can_id:  the CAN ID of the frame and CAN_*_FLAG flags, see above.
 * @can_dlc: the data length field of the CAN frame
 * @data:    the CAN frame payload.
 */
struct can_frame {
    canid_t can_id;  /* 32 bit CAN_ID + EFF/RTR/ERR flags */
    __u8    can_dlc; /* data length code: 0 .. 8 */
    __u8    data[8] __attribute__((aligned(8)));
};
"""
can_frame_fmt = "=IB3x8s"
can_frame_size = struct.calcsize(can_frame_fmt)

def build_can_frame(can_id, data):
    can_dlc = len(data)
    data = data.ljust(8, b'\x00')
    return struct.pack(can_frame_fmt, can_id, can_dlc, data)

def dissect_can_frame(frame):
    can_id, can_dlc, data = struct.unpack(can_frame_fmt, frame)
    return (can_id, can_dlc, data[:can_dlc])