Open Enclavet opened 7 years ago
Frame control frames generally go out to the address of
Well... not necessarily ... The ECU in general listen to 7DF and its "own" assigned ID. I think it is better to not send the control frame with arbid-8 but with the ID that initiated the request. We did some tests on an ECU from a 2008 Audi A4 (US) and the ecu did not even respond on some obd reqs with IDs 7e0 to 7e7 but on 7df and also expected the control frame to be from 7df.
This may vary from manufacturer to manufacturer and I actually need to do some tests as soon as I have a rental car again (guess in two weeks). Maybe this is also just the case if obd reqs are handled by only one ecu and not multiple.
I'm unsure if the id - 8 thing is standard, or just convention. ECUs should be responding on their physical address, eg, 0x7E8.
Currently this listens for frame control messages on the rx_id, which I believe is the correc thing to do. We may wish to send them on a different ID when 0x7E8 is provided as the address though. There may also be a need to listen on multiple IDs when using the 0x7DF address.
For now, I recommend specifying physical addresses, eg, 0x7E0 and 0x7E8.
What I found is from a test using a well known OBD2 reader. I am creating an application that will simulate an ECU. I was responding to a Mode 09 PID 04 request for VIN which would be multiple frames. I get the request from the Reader, I send the data using the isotp standard send method. I see the first frame go out to the Reader and it hangs. I notice int he code for the multiple frame sending of pyvit isotp that it will wait for the FC frame. I look at the CAN and see the FC message come to 7E0.
This is the case where the reader is requesting multiple frames. Here is the wikipedia regarding the request and reply addresses:
The PID query and response occurs on the vehicle's CAN bus. Standard OBD requests and responses use functional addresses. The diagnostic reader initiates a query using CAN ID 7DFh[clarification needed], which acts as a broadcast address, and accepts responses from any ID in the range 7E8h to 7EFh. ECUs that can respond to OBD queries listen both to the functional broadcast ID of 7DFh and one assigned ID in the range 7E0h to 7E7h. Their response has an ID of their assigned ID plus 8 e.g. 7E8h through 7EFh.
New thought on this: what if we used a mask and filter approach instead? This would allow you to select a range of IDs, so that you could send on 0x7DF and receive on 0x7EX, where X = 0x0 - 0xF (ie, 0x7E0 to 0x7EF).
Thoughts?
Do either of you possibly have an easy to understand example of how to generate ISOTP frames?
In my case I'm trying to do exactly what @Enclavet is doing, and generate a VIN Response.
I'm currently cheating with VIN and sending a response with cansend directly:
VINResp = 'cansend can0 7E8#1014490201355445 && sleep 0.1 && ' \
'cansend can0 7E8#214D5535324E3636 &&' \
'cansend can0 7E8#225A323236373433'
While above is static, I understand how to generate the VIN bytes, but I'm just not too sure how to interact with ISOTP directly in pyvit to send the response. Ideally I could just parse the 17 bytes of the VIN and ISOTP takes that data directly and handles the flow control and response generation. Any help is appreciated.
Thanks,
Matt
I'm a little confused on this as well.
I have a handheld device sending the ECU 7E0#0322F12100000000
(which is UDS Read Data By identifier PID 0xF121 from what I can tell)
The ECU responds:
(1555797334.207277) can0 7E8#037F2278AAAAAAAA
(1555797334.294185) can0 7E8#102162F121313737
I send the control frame 7E0#3004000000000000
but the ECU never sends any more data...
@brandonros,
I send the control frame 7E0#3004000000000000 but the ECU never sends any more data...
That's because isn't accounting for ID - 8 (0x7E8 - 8 = 0x7E0). In other words, the issue @Enclavet stated at the beginning in https://github.com/linklayer/pyvit/issues/16#issue-202368986
If you try sending a control frame like so on another console:
watch -n 1 cansend vcan0 7E8#3000000000000000
*, you'll hopefully find that pyvit now replies to the control frame.
So to get your application working with a control frame response using ID 0x7E0, you need to edit the following lines in isotp.py
if self.rx_arb_id:
- let_frame_pass = rx_frame.arb_id == self.rx_arb_id
+ let_frame_pass = ((rx_frame.arb_id == self.rx_arb_id) or
+ (rx_frame.arb_id == self.rx_arb_id-8) and
+ rx_frame.data[0] == 0x30)
else:
let_frame_pass = True
Hope that helps :-)
Thanks,
Matt
*This simply sends the control frame on vcan0 once per second.
You should change the flow control message if statement to below:
Frame control frames generally go out to the address of the specific device and not 7DF (rx request arbid).
If you had an ECU with 7E8, the flow control message would go to 7E0.