Skip to content

Commit 7fae269

Browse files
committed
Add transport over CAN FD using Linux SocketCAN
1 parent ea8aa7a commit 7fae269

1 file changed

Lines changed: 34 additions & 0 deletions

File tree

compost_rpc/compost_rpc.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1098,6 +1098,40 @@ def receive(self) -> bytes:
10981098
return header + data
10991099

11001100

1101+
class SocketCanFdTransport(Transport):
1102+
"""Linux SocketCAN transport for CAN FD. Supports max 64-byte messages.
1103+
Sends the Compost frame as payload."""
1104+
1105+
CAN_FD_HEADER = Struct("@IBB2x") # SocketCAN CAN FD frame header
1106+
CAN_MTU = 16 # Classical CAN frame
1107+
CANFD_MTU = 72 # CAN FD frame
1108+
1109+
def __init__(self, interface: str, can_id_rx: int, can_id_tx: int) -> None:
1110+
self.socket = socket.socket(socket.AF_CAN, socket.SOCK_RAW, socket.CAN_RAW)
1111+
self.socket.setsockopt(socket.SOL_CAN_RAW, socket.CAN_RAW_FD_FRAMES, 1)
1112+
self.socket.bind((interface, ))
1113+
self.can_id_rx = can_id_rx
1114+
self.can_id_tx = can_id_tx
1115+
1116+
def send(self, msg: bytes):
1117+
length = 4 + 4 * msg[0]
1118+
if length > 64:
1119+
raise ValueError("Message length exceeds 64 bytes")
1120+
can_frame = (self.CAN_FD_HEADER.pack(self.can_id_tx, length, 0) + msg).ljust(self.CANFD_MTU, b"\x00")
1121+
self.socket.send(can_frame)
1122+
1123+
def receive(self) -> bytes:
1124+
while True:
1125+
cf, ancillary_data, msg_flags, addr = self.socket.recvmsg(self.CANFD_MTU)
1126+
if len(cf) != self.CANFD_MTU:
1127+
continue # Ignore non-FD frames
1128+
can_id, length, flags = self.CAN_FD_HEADER.unpack(cf[0:8])
1129+
if can_id != self.can_id_rx:
1130+
continue # Ignore frames with wrong CAN ID
1131+
assert length <= 64
1132+
return cf[8:8 + length]
1133+
1134+
11011135
class _Session:
11021136

11031137
_TXN_MAX = 255

0 commit comments

Comments
 (0)