Closed CSG2019 closed 3 years ago
Hi, I will check soon.
I do not know KWP2000, so I have to review this protocol first. If you have good documentation you can share, I will take it.
Hi again, I've been able to put my hand on the ISO-14230-3 standard. Looking at it, there is indeed a lot of similarities between KWP200 and UDS. Unfortunately, the message you get doesn't seem compatible with the UDS format; so you are out of luck here.
Still, the format seems very easy to decode. I see that the data seems to be conveyed over ISO-TP protocol, so you can use a library that support that protocol to extract the data payload. Then, you do:
dtc_id
, status
. (or any names you want to give them)Good luck
Hi pylessard, Thank you for the reply and suggestions. I think your idea of how to deal with these data payload is very professional and correct. I have tried to run the he below code, it can be sent and get all the responses on the CAN as I want. But I still don't know how to collect the data payload(the data in the red box in above picture). So I come here to ask if it is possible to extract all response data through this UDS library. If you have a good idea or example, please share me. Thank you very much.
import can
import udsoncan
def read_dtc():
can_filters = [{"can_id": 0x18DAF110, "can_mask": 0x1FFFFFFF, "extended": True}]
bus = can.Bus(bustype='vector', app_name='CANoe', channel=[0], can_filters=can_filters)
test_msg = can.Message(arbitration_id=0x18DA10F1, dlc=8,
data=[0x04, 0x18, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00])
bus.send(test_msg, timeout=1)
try:
while True:
message = bus.recv(timeout=1)
if message.arbitration_id == 0x18DAF110 and message.data[0] == 0x10:
response_length = message.data[1]
dtc_number = (response_length - 2) / 3
print(dtc_number)
continue_frame = can.Message(arbitration_id=0x18DA10F1, dlc=8,
data=[0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])
bus.send(continue_frame)
break
else:
pass
finally:
bus.shutdown()
if __name__ == "__main__":
read_dtc()
Ah! I understand. What you need is a library able to decode IsoTP, not UDS. IsoTP (ISO-15765) is the transport protocol that is traditionally used with UDS. This transport protocol takes care of reassembling the can messages into a single payload of data.
I have another repository that does that. Have a look at https://github.com/pylessard/python-can-isotp The documentation is here : https://can-isotp.readthedocs.io/en/latest/
There is enough examples for you to be able to find your way. Once you have a working IsoTP link establish, what you need to do is send the same request, but remove the first byte as it is a IsoTP header that will be handled by the protocol. So send "1800FF00" (without the leading 04).
Once you send this payload, call the process()
method until you have received the whole payload which you can verify and read with available()
and recv()
.
The data you will get will be the data circled in red including "582E" at the beginning.
Regards
Thank you very much for the quick reply and suggestion, it's really great, I will take a look and give the feedback later.
To get you started, you can follow this small example (untested)
import isotp
import time
import can
can_filters = [{"can_id": 0x18DAF110, "can_mask": 0x1FFFFFFF, "extended": True}] # Based on your example
bus = can.Bus(bustype='vector', app_name='CANoe', channel=[0], can_filters=can_filters) # Based on your example. Have you fogotten the bitrate?
addr = isotp.Address(isotp.AddressingMode.Normal_29bits, rxid=0x18DAF110, txid=0x18DA10F1) # Based on your example
stack = isotp.CanStack(bus, address=addr)
stack.send(b'\x18\x00\xFF\x00') #Request DTC service
while not stack.available(): # Wait for a response. This may hang if none is received. You can do better with threads
stack.process()
time.sleep(stack.sleep_time())
payload = stack.recv() # That's the data you want. 582EC15570...
bus.shutdown()
according your suggestion and guidance. I tried to make a small changes and run it:
import isotp
import time
import can
bus = can.Bus(bustype='vector', app_name='CANoe', channel=[0], bitrate=500000) # the default bitrate should be 500k
addr = isotp.Address(isotp.AddressingMode.Normal_29bits, rxid=0x18DAF110, txid=0x18DA10F1)
isotp_params = {
'stmin': 00,
'blocksize': 0,
'wftmax': 0,
'll_data_length': 8,
'tx_padding': 0,
'rx_flowcontrol_timeout': 1000,
'rx_consecutive_frame_timeout': 1000,
'squash_stmin_requirement': False
}
stack = isotp.CanStack(bus, address=addr, params=isotp_params)
stack.send(b'\x18\x00\xFF\x00') # Request DTC service
while not stack.available(): # Wait for a response. This may hang if none is received. You can do better with threads
stack.process()
time.sleep(stack.sleep_time())
payload = stack.recv() # That's the data you want. 582EC15570...
print(len(payload))
print(payload)
bus.shutdown()
and the print result is:
140
bytearray(b'X.\xc1Up\xc1!p\xd1>p\xc1~p\xc1(p\xc1)p\xc1\x03p\xd1\x99p\xc1hp\x06Ep\x06\'p\x06\x88p\x053p\x01\x98\xf0\x01-\xf0\x01\x08\xf0\x01#\xf0\x02"\xf0\xd1\x86p\xc1@\xf0\xd1Ap\xd1\xc2\xf0\xd2\xa8p\xc1QP\xc1\x01P\xd1\x0cP\x04\x80P\xd1\x10P\xd1 P\x04\x98P\xd1\nP\x05#P\xd1\x0eP\x01\x92P\x01\x18P\x14WP\xc4"P\xc1%P\xd2\x0cP\x00\xebP\x00}P\x01\x13P\x00\xcbP\x01\xc0P*\xb8P,4P')
It seems that I have got all 140 bytes. and the type of the payload is a bytearray. I am not familiar with this type, is it possible to convert the HEX? Thank you.
Alright, so you made it.
bytearray
is a python native format. You can access bytes with square bracket (like a list).
The easiest way to convert to a hex string is to use the binascii
module
import binascii
str = binascii.hexlify(payload)
Also, where did you take the list of parameters for the isotp stack? ll_data_length
is deprecated and is not present in the online documentation. It should be replaced by tx_data_length
.
Regards
Hi pylessard, Thank you so much for your patient explanation. Now I can convert that hex string according to your method.
Before this, when I run the below code, I found the command is not I want, so I tried to refer to the UDS document and made some minor config changes. At that time, I am not sure where the problem is, but When I changed the config, the response seems to be ok.
the code:
stack = isotp.CanStack(bus, address=addr)
stack.send(b'\x18\x00\xFF\x00\x00\x00\x00\x00') #Request DTC service
the running result: (but I hope it's 04 18 00 FF 00 00 00 00)
the list of parameters refer to below link(use PythonIsoTpConnection with a fictive Vector interface): https://udsoncan.readthedocs.io/en/latest/udsoncan/examples.html
Probably that your ECU expects some zero padding.
Try setting the parameter tx_padding
to 0 and tx_data_min_length
to 8. All your can frame will be 8 bytes longs and holes will be filled with 00
I'm closing that issue. Good luck!
yes, you are right. I will try later. I have no question about this topic. thank you for your help.
Dear friend, I want to read the DTC list. but my diagnostic protocol is not UDS, that's KWP2000 based on CAN. So, when I send the command to ECU, I want to get the response from ECU and print the DTC list. below picture is the communication with tester and ECU. the length is 140 bytes(0x8c), and the DTC list is below read box, Actually, it's very similar with UDS DTC reading. But it seems that I can't use this library directly. So, My question is whether there is a function or method can extract theses data then print them. Can I do this by import Response from udsoncan.Response? if you have a good idea, please share me. thanks in advance. :)