-
-
Notifications
You must be signed in to change notification settings - Fork 195
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Read Data by Identifier as an unformatted raw content dump? #152
Comments
Here's my existing Python code... `#!/usr/bin/python3 import sys def error(): def initialize(module, identifier):
if len(sys.argv) < 3: module = sys.argv[1] Here's some sample output: (Ignore the "UNKNOWN RESPONSE".) Basically, what I need is, regardless of DID, for it to print a raw hex dump of the output. |
It's doable, but the end result may not respect the standard. Here's why. I'm sure you can see the problem right away. Either you pass the DID size as an input parameter of your program, or you read one DID at the time and assume that the device is not giving you extra bytes; in that case, you can print the response payload. The latter is the part that is "non-standard". Basically, you need a Codec that does 2 things. Pass the data as is (no interpretation) and reads the whole payload.
Cheers |
Another approach, maybe more suited for your use case, would be to not use the This example should be useful to you. Since you want to craft a request but not interpret the resposne (which the client does), you could do something like : request = services.ReadDataByIdentifier.make_request(0x1234, my_didconfig)
my_connection.send(request)
response = my_connection.wait_frame(timeout=1, exception=False)
if response:
print("Gotten data : %s" % response.data) In the above example, didconfig is the same config used by the client. The didconfig is not necessary to craft the request, it is just validated to fail early instead of sending a request and waiting for a response to then fail. I should have made that parameter optional.. you can put any valid configuration that won't affect the request. You could even be more clever and use the client request = services.ReadDataByIdentifier.make_request(0x1234, my_didconfig)
try:
response = client.send_request(request)
print("Gotten data : %s" % response.data)
except TimeoutException as e:
print("No response")
except NegativeResponseException as e:
print("server said no. Payload : " + str(e.response.data))
except InvalidResponseException as e:
print("Server is drunk. Payload: " + str(e.response.data))
except UnexpectedResponseException: # Only happen if you use the client methods. `send_request` will never raise this.
pass You may have notice the usage of the exception. I wanted to show it to you because you use none in your above code. :)
Ok, that's enough. Have fun |
I'll admit, I'm a less than stellar programmer. But at first blush, I think you've given me what I'm looking for... and then gone the extra mile to give me even more! Thank you. A question, since I have your attention. I'm not at that point just yet, but If I find myself over my head with udsoncan or can-isotp issues, do you (or do your know someone) that'll do minor works-for-hire with these modules? I'm doing some reverse-engineering work on the Wrangler JL as a hobby, but I don't know Python. If I end up reaching a dead-end, I wouldn't mind seeking a higher power with dollars in hand. (Assuming such a statement does not violate GitHub TOS or anything.) Thanks again, |
Alright. This being said, I will kindly ask that you still do an effort on your side. Many people reach out to me without having done their homework. I have very little patience for that. As for how to use all of this. I suggest you go through the doc from beginning to end. What needs to be understood if that everything works in layer. udsoncan is on top of isotp and this is on top of the CAN layer (python-can, socketcan). Each layer can be configured.
Your application logic comes on top of UDS. I tried to built the udsoncan project in 3 levels
You can hook at the level you want. The client is the nicest. |
You're a good man, thank you! I'll put in the work with what you've given me so far, and I'll let you know if I need a bit more help. BTW, I thought you should know, I've had some mixed success using ChatGPT to write code with your modules. I actually used ChatGPT (in the example above) to convert my BASH script into code which at least reads the VIN from my BCM. ChatGPT version 3.5 (and the new 4.0) are both aware of your module. Here's the writing prompt I've been having some success with. Unfortunately, much of the time, ChatGPT gets confused how some of the various parts of your modules fit together. Anyhow, I thought you'd find this interesting. Here's my writing prompt...
|
I thought of another way around the problem. Let's keep on using the VIN as an example. A normal (healthy) DID 0xF190 request from my BCM would look like this (candump output): can1 620 [8] 03 22 F1 90 00 00 00 00 So I thought, maybe if I keep on using iso-tp but don't use udsoncan for this, it might work out better? So I tried this piece of code...
But when I did, my CAN bus message looked like this, which my ECU ignored: can1 620 [4] 03 22 F1 90 So I decided to pad things with zeros... That produced the following CAN bus message which my ECU also ignored: can1 620 [8] 07 22 F1 90 00 00 00 00 So I know that I should be telling isotp to always pad my messages so that they're eight bytes long, and I know that there's got to be an option for it, but I'm just not finding it. What am I overlooking here? I need to be producing THIS, and I want to use ISO-TP so that I can handle the long responses from the ECU: can1 620 [8] 03 22 F1 90 00 00 00 00 |
Yes. If you are interested in the raw payload and read 1 DID at the time, you can skip the UDS layer and hook directly on Isotp layer. The CanStack accepts an optional Config dict. All here : https://can-isotp.readthedocs.io/en/latest/isotp/implementation.html#parameters You want tx_data_min_length and tx_padding |
I'm thinking about your use case. You basically want the isotp stack and the UDS logic in 2 separate program and pipe them with bash.
or more generically :
You can achieve that # wrangle_did_config.py
from udsoncan import AsciiCodec
didconfig = {
0xF190 : AsciiCodec(15)
} # request_did.py
from wrangle_did_config import didconfig
from udsoncan.services import ReadDataByIdentifier
import binascii
# ... Parse stdin
request =ReadDataByIdentifier.make_request(did_number, didconfig)
payload_ascii = binascii.hexlify(request.get_payload()).decode('ascii')
printf(payload_ascii ) #did_decode.py
from wrangle_did_config import didconfig
from udsoncan.services import ReadDataByIdentifier
import binascii
# ... Parse stdin
response_payload = binascii.unhexlify(input_payload_ascii)
response = udsoncan.Response.from_payload(response_payload)
ReadDataByIdentifier.interpret_response(response, didconfig)
for did in response.service_data.values:
printf("0x%04x: %s" % (did, response.service_data.values[did])) # Need to be convertible to string #isotp_send.py
from isotp import CanStack
# ... setup you can stack
# parse stdin
data= binascii.unhexlify(input_payload_ascii)
stack.send(data)
while stack.transmitting():
stack.process()
time.sleep(stack.sleep_time())
if stack.available():
payload = app.stack.recv()
payload_ascii = binascii.hexlify(payload).decode('ascii')
print(payload_ascii ) I haven't tested this piece of code, but you get the idea. You can even replace the isotp_Send.py by the linux utility isotp_send written by @hartkopp. |
When you do some padding up to the 8 byte length, the padding is usually done with fill bytes 0xAA or 0x55 to prevent stuff-bits on the CAN bus bitstream layer.
|
Pier, With a bunch of work, I managed to make an even better Python version of my 'rid' script without the udsoncan package. I've included it below. But, wow, given all the help you're providing and all that good information, I think I'm going to go back and reprogram it with the udsoncan package. Especially because I want to take advantage of all the other services that are available. Thank you so much for your help... especially the tx_data_min_length and tx_padding tip that got my over my initial hurdles. Despite telling ChatGPT what version of the modules I'm writing for, it sometimes insists on trying to use ll_data_length, tx_dl, rx_dl, and rx_padding. I don't know if it was hallucinating those or not, but I now actively tell it not to try that. Anyhow, here's version 1 of my code without udsoncan. Next version coming will be with it!
|
That's nice :) |
Do try it out - I oscillate between amazed and very disappointed, depending
on the task I give it :)
…On Fri, 17 Mar 2023 at 13:22, Pier-Yves Lessard ***@***.***> wrote:
That's nice :)
I do find the AI part interesting (like everybody), but I'm not yet sold
to the idea of having it write code. Nothing beats knowledge and riguors to
achieve quality
—
Reply to this email directly, view it on GitHub
<#152 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AADIII7CDEXO4HS4VNG4QODW4RQPTANCNFSM6AAAAAAV4GUXVE>
.
You are receiving this because you are subscribed to this thread.Message
ID: ***@***.***>
--
***@***.***
https://parallelpoints.com/ <http://parallelpoints.com/>
|
I think I have it. I'll be working on this some more tomorrow. Yes, I'm only doing a single call now, but I see the value in calling multiple DIDs at the same time, and it's something that I'll want to demonstrate to my community so that they can take advantage of such a powerful feature!
|
Carefull with the codec len of 0. That's not supported |
Is it still relevant to keep this issue open? |
Looks like I got tied up. Let's put a pin in it for now. I'm sure I'll be revisiting this topic soon. It will be interesting and useful to query multiple DIDs at once, so I'm sure I'm going to be pulled back this way again soon! Thank you for such useful CAN modules! |
I have an existing shell script where you provide the name (address) of a module, and you provide an identifier, and it prints the contents of that location as a series of hexadecimal characters. (No matter what the location, it's encoding, or it's length, it simply provides a raw hex output of it's contents.) For reference, I recently republished it here:
https://old.reddit.com/r/CarHacking/comments/11rgykl/a_gift_from_the_wrangler_community_for_other/
So it's general purpose. You don't have to specify how the data is encoded. You just receive the data, and from there you can work with it as you wish and use other tools to manipulate it into a workable format. (Basically, in the spirit of your standard UNIX tool which does something small and can be chained with other things.)
How can/would I do this with python-udsoncan?
PS: I was so happy to make my first SocketCAN / ISO-TP / UDSonCAN connection to pull the VIN (0xF190) from my BCM. I'm hoping to convert everything we've be doing so far with the Jeep Wrangler JL to take advantage of your modules!
The text was updated successfully, but these errors were encountered: