0

I have a cangen process running that's sending out CAN traffic 1/second. (cangen can1 -D 1021324354c0ffee -L 8). I've connected my can1 and can0 ports together, and I can see that can1 traffic on can0 in my python3 program just fine, via

    can_interface='can0'
    bus=can.interface.Bus(can_interface, bustype='socketcan_native')
    while True:
        msg=bus.recv()
        print(msg)

This causes a line like the following to print on stdout: Timestamp: 1606022413.287309 ID: 0746 S DLC: 8 11 22 33 44 de ad be ef Channel: can0

I want to send that 'msg' information as a UDP packet on my network. But I still don't understand the strings-vs-bytes distinction of python, so the obvious doesn't work:

    sent = sock.sendto(msg, server_address)

What transmogrification must I do to the CAN msg to make it suitable for use as an arg to sendto()?

I do realize that msg is really (whatever python calls) a structure, and I can access the various components of msg via msg.data, msg.timestamp, and msg.dlc. If I could take all of these msg components and concatenate them into a string and then send that, or a hexified version of that, I'd be happy. Or maybe some such string already exists, and I just need to convert that string into bytes to make sendto() happy. I've tried all sorts of permutations to no avail. Help?

  • `sendto()` expects `bytes`. Maybe try `sent = sock.sendto(bytes(msg), server_address)`. – GordonAitchJay Nov 22 '20 at 05:51
  • When I try that, a UDP message is received. But its length varies from 3 to 8 bytes, and seems to be truncating the data part of the msg at random places. It never includes the timestamp or any other part of the msg.data other than the msg.data itself. – Bob Colwell Nov 22 '20 at 06:10
  • What is `msg`? What does this print: `print(type(msg), msg)`. – GordonAitchJay Nov 22 '20 at 06:23
  • sorry about the formatting here, can't seem to put CR/LF where I want them in a comment. >>> bus = can.interface.Bus('can0', bustype='socketcan_native') >>> msg=bus.recv() >>> print(type(msg),msg) Timestamp: 1606062856.917673 ID: 0775 S DLC: 8 10 21 32 43 54 c0 ff ee Channel: can0 >>> – Bob Colwell Nov 22 '20 at 16:40
  • Also ran across this: https://python-can.readthedocs.io/en/master/_modules/can/message.html, in which the __str__ string gets set up with all of the message fields included. If I could just convert that to a bytearray, I think, the sendto() might be happy with it as an arg, and voila...?? – Bob Colwell Nov 22 '20 at 16:45
  • I'm sure it does, thank you for bringing it to my attention. It helps greatly. On the sending end I now have sent=sock.sendto(bytes(CAN_msg), server_address). On the UDP server, I have rawdata,address=sock.recvfrom(), then stringdata=Message(data=bytearray(rawdata)) followed by a print(stringdata). This mostly sorta works, but about 1/3rd of the received packets are truncated, and the Timestamp is printing as all-zeroes. Further pointers gratefully solicited. – Bob Colwell Nov 22 '20 at 19:02
  • 1
    Another clue: I have a second prototype server written in C. It agrees: some of the incoming UDP packets are truncated. And the truncated packets include a "data length" field that accurately reflects the truncation. I realize UDP doesn't guarantee end-to-end delivery but I thought the potential losses were in transmission, not at the sender...? – Bob Colwell Nov 22 '20 at 20:31
  • `sock.sendto(bytes(CAN_msg), server_address)` returns the number of bytes sent. How does this compare to what your server written in C receives? – GordonAitchJay Nov 24 '20 at 12:54
  • Number of bytes sent match: sender and receiver agree. The truncation was happening because cangen -L x doesn't force the messages to be x bytes, as promised by the man page. I've now managed to convert my data to strings, combine the strings into one message, turn that into bytes(), and decode at the server. It was not easy. Thank you for your help! – Bob Colwell Nov 26 '20 at 05:15

0 Answers0