pylessard / python-udsoncan

Python implementation of UDS (ISO-14229) standard.
MIT License
575 stars 199 forks source link

Date format, for Service 0x22 date fields? (e.g. ECU mfg date, ECU install date) #167

Closed raleighlittles closed 1 year ago

raleighlittles commented 1 year ago

This isn't really a bug request or a feature, but a question about the format of data returned when you use the "Read Data by Identifier" object to query a date, for example: ECU Manufacturing Date (DID of 0xF18B). What format exactly is this in?

I'm not specifically using this project for anything, though I have a CanEdge logger that can send UDS query commands, but it returns the raw CAN transaction data itself, that looks like this for example:

[ 31 112   0   0   0   0   0   0]
[ 4 65 60  2  8  0  0  0]
[  3 127  34  49   0   0   0   0]
[128 232  30 127 208   0  38   3]
[255 224   0  24   0  16 255 227]
[ 51 131  45   0   8 255 232   0]
[ 31 164  50 211  56   0  57  16]
[255   0   0   0   0  25  64 206]
[ 32  30  31 164   0   0   0 128]
[0 0 0 0 0 0 0 0]
[213 255   0   7 135 177  92   3]
[255  48 255   4 255 255   0   0]
[  0   1 207   0   0   0   0   0]
[64 64  0  0  0  0  0  0]
[101  70  84 170   0   0   0   0]
[  0   0   3 223 131 179 224   8]
[254  19  64   0  50   0   0   0]

And I'm having trouble trying to make sense of this.

If you have a forum of any kind that would be more appropriate for this question, let me know and I'll move it to there.

pylessard commented 1 year ago

Hi Let's start with the data you shared. I am not able to make sense of it. I see some pattern into it, but it doesn't look like an UDS communication. Generally, CAN messages have an ID and a DLC, it's useful to have them in the logs. And we also dump logs in hexadecimal, with leading 0 to have 2 chars. Makes it much more readable.

Now, how does that all work. First thing to know is that there generally is 2 protocol involved, ISOTP (ISO15765) and UDS (ISO14229). ISOTP is the transport layer that is used to send long frame of data over many small pieces of 8 bytes. UDS works at the application level. So, if you look at a can log, you must first identify the isotp frames.

The UDS standard defines how to read a DID. it's something like 0x22, 0x12, 0x34. That would request for DID 1234. The data returned by the device can be in any format, it is not standardized and solely depends on the ECU manufacturer. This python project requires the user to define codecs object that can do the encoding and decoding. You can look at an example here

Some DID number are standard though, like this F18B, Even if they are standard, it doesn't mean that the data format is. Maybe there is an industry convention, I really cannot tell. But I can tell that ISO-14229 does not define the format and it is explicitly specified that it's up to the manufacturer to define the format.

Hope that help a little bit. If you want more help, share a full CAN log. As I said, I don't know what I'm looking at above.

raleighlittles commented 1 year ago

@pylessard First of all, thank you so much for responding. I apologize for not providing more context.

I'll start from the top. The CanEdge logger that I use records files in MDF/MF4 format. I use this library called "asammdf" to decode it, and convert it to a CSV. Something like this:

mdf = asammdf.MDF(canedge_mf4_file_path, use_display_names=True)
mdf.to_dataframe().to_csv("original.csv") # original because this contains the raw traffic

These are the row headers in the generated CSV file:

'timestamps',
 'CAN_DataFrame.CAN_DataFrame.BusChannel',
 'CAN_DataFrame.CAN_DataFrame.ID',
 'CAN_DataFrame.CAN_DataFrame.IDE',
 'CAN_DataFrame.CAN_DataFrame.DLC',
 'CAN_DataFrame.CAN_DataFrame.DataLength',
 'CAN_DataFrame.CAN_DataFrame.DataBytes',
 'CAN_DataFrame.CAN_DataFrame.Dir',
 'CAN_DataFrame.CAN_DataFrame.BusChannel_0',
 'CAN_DataFrame.CAN_DataFrame.ID_0',
 'CAN_DataFrame.CAN_DataFrame.IDE_0',
 'CAN_DataFrame.CAN_DataFrame.DLC_0',
 'CAN_DataFrame.CAN_DataFrame.DataLength_0',
 'CAN_DataFrame.CAN_DataFrame.DataBytes_0',
 'CAN_DataFrame.CAN_DataFrame.Dir_0'

The file contains regular OBD data (different PIDs that I chose to record), as well as some of the responses to UDS commands.

Here's an example from the file where I used Service 9 PID 02 to read my vehicle's VIN:

timestamps,CAN_DataFrame.CAN_DataFrame.BusChannel,CAN_DataFrame.CAN_DataFrame.ID,CAN_DataFrame.CAN_DataFrame.IDE,CAN_DataFrame.CAN_DataFrame.DLC,CAN_DataFrame.CAN_DataFrame.DataLength,CAN_DataFrame.CAN_DataFrame.DataBytes,CAN_DataFrame.CAN_DataFrame.Dir,CAN_DataFrame.CAN_DataFrame.BusChannel_0,CAN_DataFrame.CAN_DataFrame.ID_0,CAN_DataFrame.CAN_DataFrame.IDE_0,CAN_DataFrame.CAN_DataFrame.DLC_0,CAN_DataFrame.CAN_DataFrame.DataLength_0,CAN_DataFrame.CAN_DataFrame.DataBytes_0,CAN_DataFrame.CAN_DataFrame.Dir_0
27.52245,1.0,2024,0.0,8,8,[16 20 73  2  1 51 78 49],0.0,1.0,2016,0.0,8,8,[ 2  9  2 85 85 85 85 85],1.0
27.525100000000002,1.0,352,0.0,7,7,[ 51 131  33   0   8 255 232   0],0.0,1.0,2016,0.0,8,8,[ 2  9  2 85 85 85 85 85],1.0
27.5253,1.0,384,0.0,8,8,[31 89 50 19 56  0 52 16],0.0,1.0,2016,0.0,8,8,[ 2  9  2 85 85 85 85 85],1.0

My VIN starts with "3N1", which shows up in ASCII as "51 78 49". After I saw that this was working, I started looking for responses for UDS traffic -- I am specifically querying the various date fields because I thought they'd be easiest to decode.

For the ECU manufacturing date, I searched the CSV file for 241 157 (the decimal equivalent of 0xF19D) and then examined the data bytes from those rows; that forms the table that I pasted in my first message.

Here's an example of the data in a spreadsheet so you can see what I mean:

image

The DLC column is 2 to the left of the highlighted one. The full CSV file is 93 MB so I can't upload the whole thing to Github, but I added it to Google Drive: https://drive.google.com/file/d/1WAJM6mC6NrMR20DQAk65s2CQwiurqDye/view?usp=drive_link

pylessard commented 1 year ago

Okay, look at the CAN ID of your messages. Generally, a UDS communication will use the same ID pair for transmit and reception. I see many IDs, so I think the raw data that you have is mix of many thing. The only message that looks like a UDS message is line 4, 037f2231 that's actually a denial to respond to a ReadDataByIdentifier with error code RequestOutOfRange. All the rest looks like gibberish, which make me believe that your RX ID is 7E8 (2024). Tx ID must be something like 7E7 or7E9 (just a guess). Aything not using these ID is something else than a UDS communication.

pylessard commented 1 year ago

Anything else I can do?