Skip to content
This repository has been archived by the owner on May 7, 2021. It is now read-only.

Using ISO-TP Dispatcher functionality #42

Open
mattie47 opened this issue Apr 29, 2019 · 1 comment
Open

Using ISO-TP Dispatcher functionality #42

mattie47 opened this issue Apr 29, 2019 · 1 comment

Comments

@mattie47
Copy link

mattie47 commented Apr 29, 2019

Hi,

I was hoping someone here might be able to help with an example of how to use the dispatcher in a loop and if a condition is met, send a relevant response.

Currently I've just been interacting with Pyvit in a simple while loop with dev.recv. However I'm not sure how to interact with the dispatcher given things are threaded.

Basically, I have a simple program using Pyvit acting as an ECU to send things such as RPM and Speed when requested by a connected device.

As an example:

#!/usr/bin/env python3

from pyvit import can
from pyvit.hw import socketcan

import os,sys,termios,tty,time

SupportedPIDsRequest = "0201000000000000"

RPMRequest = "02010C0000000000"
VINReq = "0209020000000000"

RPMResp = 'cansend vcan0 7E8#04410C1094000000'
VINResp = 'cansend vcan0 7E8#1014490201355445 && sleep 0.1 && ' \
          'cansend vcan0 7E8#214D5535324E3636 &&' \
          'cansend vcan0 7E8#225A323236373433'

def resp_function():
    resp = can.Frame(0x7E8)
    resp.data = frameData
    dev.send(resp)
    print(resp)
    return resp

dev = socketcan.SocketCanDev("vcan0")
dev.start()

while True:
    CanFrameRecv = dev.recv()

    if CanFrameRecv.arb_id == int(0x7DF):
        if (bytes(CanFrameRecv.data)) == bytes.fromhex(SupportedPIDsRequest):
            print('\nSupported PIDs Request  : ' + SupportedPIDsRequest)

            frameData = [0x06, 0x41, 0x00, 0x00, 0x18, 0x30, 0x01]
            response = resp_function()
            print('Supported PIDs Response : ' + str(resp_function().data))

        elif (bytes(CanFrameRecv.data)) == bytes.fromhex(RPMRequest):
            print('\nRPM Request Received    : ' + RPMRequest)
            print('RPM Response            : ' + RPMResp)
            os.system(RPMResp)    
        elif (bytes(CanFrameRecv.data)) == bytes.fromhex(VINReq):
            print('VIN Req          : ' + VINReq)
            print(VINResp)
            os.system(VINResp)

As you can see, I'm "cheating" with the VIN, and just sending the frames out without actually checking if a frame control message is received. I want to improve this, and actually use the ISO-TP functionality.

My issue is I've struggled to get ISO-TP messages working nicely.

Using the isotp_test I was able to get an idea on how to send an ISO-TP frame, provided you send a frame control message.

#!/usr/bin/env python3

import threading
from multiprocessing import Queue

from pyvit.hw import socketcan
from pyvit.dispatch import Dispatcher
from pyvit.proto.isotp import IsotpInterface

dev = socketcan.SocketCanDev("vcan0")
disp = Dispatcher(dev)
recv_queue = Queue()
disp.add_receiver(recv_queue)

# set up an isotp interface Sender/Receiver arb id
sender = IsotpInterface(disp, 0x7DF, 0x7E8)
receiver = IsotpInterface(disp, 0x7E8, 0x7DF)
disp.start()

""" ISOTP transmission and reception of a multi-frame message"""
print("payload creation")
payload = [0x49, 0x02, 0x01, 0x31, 0x41, 0x31, 0x4A, 0x43, 0x35, 0x34, 0x34, 0x34, 0x52, 0x37, 0x32, 0x35, 0x32, 0x33, 0x36, 0x37]

# we need to run this in a thread so that the flow control frame is
# sent and received, as IsotpInterfaces block
print("starting tx_thread")
tx_thread = threading.Thread(target=sender.send, args=(payload,))
tx_thread.start()

# we'll receive data in this thread
resp = receiver.recv()

# wait for the transmitting thread to finish, then verify the result
tx_thread.join()

## I'm really not too sure what the above " .join"actually does....

print("finished")

Example:

pi@rpi-hos:~/repos/pyvit $ python3 print_all_frames.py
payload creation
starting tx_thread
[16, 20, 73, 2, 1, 49, 65, 49] <SEND CONTROL FRAME>
[33, 74, 67, 53, 52, 52, 52, 82]
[34, 55, 50, 53, 50, 51, 54, 55]
finished

I'm just not sure how to interact with the Dispatcher send and receive methods/threads within a while loop.

I'm starting to get the impression my main loop should also be a thread but again not sure how to do this.

Sorry if this is an annoying question - I'm still pretty new to python.

Thanks,

Matt

@mattie47
Copy link
Author

So I had another go:

#!/usr/bin/env python3

import threading
from multiprocessing import Queue

from pyvit.hw import socketcan
from pyvit.dispatch import Dispatcher
from pyvit.proto.isotp import IsotpInterface

dev = socketcan.SocketCanDev("vcan0")
disp = Dispatcher(dev)
recv_queue = Queue()
disp.add_receiver(recv_queue)

# set up an isotp interface Sender/Receiver arb id
sender = IsotpInterface(disp, 0x7DF, 0x7E8)
receiver = IsotpInterface(disp, 0x7E8, 0x7DF)
disp.start()


def vin():
    payload = [0x49, 0x02, 0x01, 0x31, 0x41, 0x31, 0x4A, 0x43, 0x35, 0x34, 0x34, 0x34, 0x52, 0x37, 0x32, 0x35, 0x32, 0x33, 0x36, 0x37]
    tx_thread = threading.Thread(target=sender.send, args=(payload,))
    tx_thread.start()
    resp = receiver.recv()
    print(resp)
    # resp
    # tx_thread.join()
    resp = []
    print("finished")


while True:
    CanFrameRecv = IsotpInterface.recv(receiver) # This works
    print(CanFrameRecv)

    if CanFrameRecv == [0x09, 0x02]:
        print("It is!")
        vin()

So the above "sort of" works, but still a tad buggy.

If I have tx_thread.join() in the function, and send VIN Req but no Control Frame, then it holds up the while loop from all other received frames until the thread control frame timeout.

The other issue, is that if you send a control frame, followed by the Vin Req, it'll immediately send the follow up frames. I tried adding resp = [] into the function in hope that it would clear the queue, but after playing around, I see this doesn't appear to make a difference.

Anyone able to give me a hand with this?

Thanks,

Matt

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant