milhead2 / python-j1939

Breakout of j1939 from inside the python-can package
GNU Lesser General Public License v3.0
38 stars 20 forks source link

Periodic message using send_periodic() gives error message #14

Open johanbrus opened 4 years ago

johanbrus commented 4 years ago

I observed that although the send() command from the python-can library handles the 'pdu' message from the python-J1939 library fine, the send_periodic() command is gives the following error message:

File "C:\Program Files\Python37\lib\site-packages\can\broadcastmanager.py", line 125, in start
    name = "Cyclic send task for 0x%X" % (self.message.arbitration_id)
    TypeError: %X format: an integer is required, not ArbitrationID

Which is understandable as the arbitration_id argument which is found in the can.Message object is done differently in the python-j1939 way. However, I don't understand why the normal send() function seems to work fine.

Is this intended (maybe there is another way to send periodic messages with python-j1939?) or am I missing something?

Code for error reproduction:

import time
import j1939
if __name__ == "__main__":
    channel = 0
    bustype = 'kvaser'
    sourceaddr = 0xFE
    destaddr = 0xF1

    bus = j1939.Bus(channel=channel, bustype=bustype, timeout=0.01, broadcast=True)

    data = [0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF]
    pgn = j1939.PGN()
    pgn.value = 0xFECA # DM1 
    aid = j1939.ArbitrationID(pgn=pgn, source_address=sourceaddr, destination_address=destaddr)
    pdu = j1939.PDU(timestamp=0.0, arbitration_id=aid, data=data, info_strings=None)

    bus.send_periodic(pdu, 0.5, duration=10.0)
    #bus.send(pdu)
ashn-dot-dev commented 4 years ago

I ran into this same issue recently. I believe that send is overridden by j1939.Bus but send_periodic is not.

I ended up writing a function that polls for received messages using something along the lines of:

MSG_POLL_TIMEOUT_SEC = 0.025

def update(bus):
    """
    Messages are read via polling with timeout MSG_POLL_TIMEOUT_SEC.
    """
    assert isinstance(bus, j1939.Bus)
    recv_msg = lambda: bus.recv(MSG_POLL_TIMEOUT_SEC)
    msg = recv_msg()
    while msg:
        logging.debug(f"Received message:\n\t{str(msg)}")
        msg = recv_msg()

It's a bodge, but it worked for me. ¯\_(ツ)_/¯