This is not a course or a diploma! I haven't been a student for a long time. This is an attempt to write another free software for "home" car diagnostics. And I'm not very good at Python. That's why I'm asking for help.
Source data:
There is some device that is connected to the computer via a USB port. The computer and the device exchange data in symbolic form. In fact, this is a classic connection: the device plays the role of a server, and the computer plays the role of a terminal. If this tells anyone anything, then this device is an OBD-II adapter (On-Board Diagnostics - a device for diagnosing cars) ELM327.
The system works according to a very simple principle - the server retus a response to the client's (terminal's) request (command). Here is an example of a response request:
> atiELM327 v1.5> atdpAUTO, ISO 15765-4 (CAN 11/250))
This is what the response string ""ELM327 v1 looks like.5"" in hex format:
45 4C>45 4C 4D 33 span> 32<"">32 37 20 76 31 2E 35 0D 0D 3EAnd so the response string is ""AUTO, ISO 15765-4 (CAN 11/250)"":
41/span> 55="">55 54 4F 2C 20 49 53n class="">53 4F n> 4F 20<"">20 31 35 37 "">37 36 35 2D 34 pan class="">20 28 43 41 4E 20 31 31 2F 32/span> 35="">35 30 29 0D 0D 30D 0D 3E First, the response string uses the \r character instead of the \n character. (There is no problem here. This is easily fixed.) Secondly, the response ends with the character 'gt;' (hex code = 0x3E), which complicates the program code for processing the response. There is no unsolvable problem here either.
The problem that I can't overcome is that in Python-3 I can't really get a string of characters from the port. In Python 2.7, the request-response works without problems.
Here is the code for the second Python:
def/span> show_responseesponse(port): while True: resp = '' ss="">'' while True: ch = port.read(1) if len(ch) == 1: # print ch if ch == '\r': resp += '\n' else: resp += ch if resp[-2:] == '\n>': print resp[:-2], breakpan>], break
For the third Python, this is the code (of course!) This doesn't fit. I don't mean replacing the print operator for Python-2 with the print() function for Python-3. It's all easy to fix.
The problem is receiving data from the serial port. If in the second Python it is enough to do (simplistically speaking) like this:
ch =port.read(1)print ch, then in the third Python, the read() function retus not a string of characters, but a string of bytes.ring of bytes.
I am a security officer. And for me, a byte is from and in Africa bytes. From my point of view, both a byte and an ASCII character (not multibyte utf-8 characters!!!, but a one-byte ASCII character from the first half of the code table) are the same set of bits. Therefore, the read() function in the serial module for the second Python, which retus a string of characters, and the read() function in the serial module for the third Python, which retus a string of bytes, should give the same result.
But in practice, instead of a string of bytes ""45 4C 4D 33 32 ..."" (the response to the ati command in the second Python), in the third Python I get only three bytes ""7F BF ED"". And I can't get anything else. The exchange between the ELM327 and the computer takes place in bytes (characters ?) in the range 0..0x7F. It doesn't even smell like Cyrillic! Where do such strange codes come from -- 0xBF and 0xED ?
What am I doing wrong?
Here is the code for the third Python:
def/span> show_responseesponse(port): #print('show_response') while True: resp = '''' while True: b = port.r>: b = port.read(1) if len(b) != 0: print('0x{0:02X}'./span>.format(b[0])) #if ch == '\r': # resp += '\n' #else: # resp += ch if resp[-2:] == '\n>': print(resp[:-2], end='') break /pre>
The initialization of the port for the second and third Python is almost the same:
#!/usr/bin/env python3#coding:utf8import serialimport timefrom multiprocessing import Process...if __name__ == '__main__': try: port = serial.Serial(""/dev/ttyUSB0"", 38400, timeout=0.2) except serial.SerialException: printn: print('Connection failed') ex') exit(1) port.flushOutput() port.flushInput() p1 = Process(target=show_response, args=(port,)) p1.daemon = True p1.start(> p1.start() command(port) pri">print('Bye-bye!')I installed the serial package from standard repositories -- on one computer (Ubuntu-10.04), this was the package configuration for the second Python ($sudo apt-get install python-serial), on another computer (Debian-8) - for the third Python (# apt-get install python3-serial).
I don't understand where to dig? Someone write me a magic pendulum in the right direction, otherwise I'll die without understanding the essence of Python's byte manipulation.
UPDATE 08.08.2015 - 00:53
I changed the program, since it's generally microscopic. Now the port is stupidly opened, the device -- 'ati\r' command is stupidly given, and everything that pours out of the port in response to this command is stupidly displayed on the console - no processes, no tricks, nothing superfluous! Nevertheless, the output to the console is exactly the same.
Here is the text of this program:
#!/usr/bin/env python3#coding:utf8import serialimport timeif __name__ == '__main__': try: port = serial.Serial(""/dev/ttyUSB0"", 38400, timeout=1) except serial.SerialException: printclass="">print('Connection failed') exit(1) port.flushOutput() port.flushInput() # Send requestrequest cmd = bytes('ati\r', 'utf-8') port.write(cmd) time.sleepe.sleep(0.1) # Accept the response and output it to the console whilewhile True: e: print('.') resp =port.readline() # Output n class=""># Output option 1 if len(resp) > 0: print">print('[{0:d>'[{0:d}] = '.format(len(resp)), end = '') s="">'') for b inin resp: print('0x{0:02X} '.format(b), end=") "' # Output option 2 string =str(port.readline()) iflen(string) > 0: print('[{0:d}] ='.format(len(string)), end = ") for ch in string: print('0x{0:02X}'.format(ord(ch)), end=") "' "' # Output option 3 string = str(port.readline()) if len(string) >
question@mail.ru
·