oceancoding
oceancoding

Reputation: 11

Reading/Converting byte-like hex objects from PySerial

I've been trying to cobble together a solution to this problem from various related threads but I can't seem to get them working together. A lot of the posts I find seem to be dealing with ascii/binary values, and my problem relates to translating hex values. I'm new to Python, and I've been struggling with the syntax.

System: Windows 10. Python 3.6. IDE is Spyder.

Issue: I'm communicating with a device over an RS232 serial port that only communicates in hex. I've managed to successfully send a command to the device using the pySerial module and receive a reply, but I can't figure out how to convert the reply into a parseable format for the next step in my workflow.

Code so far:

import serial
import sys

port = "COM3"
baud = 9600
bytesize=8
parity='N'
stopbits=1
timeout=10 # this timeout is large due to another problem I'm having, but 
             didn't want to complicate this post with.

# Commands

# open the serial port
ser = serial.Serial(port, baud, bytesize, parity, stopbits, timeout)

if ser.isOpen():
    print(ser.name + ' is open...')

# Query. This sends an 'are you awake' message to the device.
ser.write(bytearray.fromhex("23 00 00 80 B0 00 00 01"))        

The above command is being sent to the device as a "byte-like object" according to Python, which displays as the format: b'\x23\x00\x00\x80\xb0\x00\x00\x01'

print('Receiving...')

# wait for timeout before displaying what was read. The device returns a 
variable number of bytes each time it communicates, and I haven't figured 
out a way to handle that yet.
    out = ser.read()

print(out)
ser.close()
print(port+' is closed.')

This is where my problem is. ser.read() returns another byte-like object. For example, from the above ser.write() command: b'\x13\x11'. These are in fact the values I'm expecting from this command (hex values of "13" and "11"), I just don't know how to handle them now.

What I want to do is parse out the long string of returned hex characters (when I send a non-query command this will be 250+ characters, delimited by "\x") into individual array elements that I can then manipulate/replace/convert back into decimal integer values. I'll eventually be wanting to convert these hex values into their decimal equivalents and writing those decimal values to a CSV text file, so that I can later plot the values.

I've tried (these are not sequential commands, it's a list of attempted commands):

out = ser.readline()    

out.split("\x")
out.split("\")
out.split("\\")

out_string = out.decode("utf-8")

binascii.hexlify(out)
binascii.hexlify(bytearray(out))

...and others I can't remember.  

Please, any help you can offer would be greatly appreciated. This feels like it should be a simple thing to do, and my poor computer is running out of memory with all the tabs I have open. Thank you in advance to anyone who replies.

Upvotes: 0

Views: 5217

Answers (1)

Zapho Oxx
Zapho Oxx

Reputation: 355

Your out is a sequence of bytes. If you want to read out a specific number of bytes only you could just use

out = ser.read(n) # where n is the number of bytes you want e.g. n = 8

Your out should look something like this:

out = b'\x21\x45\xed\xca\xfe' # I chose random values here

So to get a list of int's you can do:

for b in out:
  int_list.append(b)

or

int_list = [b for b in out]

If you want byte pairs you can do (not sure if this is the best way though):

for i in range(0,len(out),2): # loop to every second value
  pair = out[i].to_bytes(1,'little')+out[i+1].to_bytes(1,'little') # the first argument refers to the number of bytes and the second to the endianess.
  print(pair)

That produces the following for me:

>>> b = b'\x32\x34\xe8\x90\x32\xab'
>>> for i in range(0,len(out),2):
...     pair = out[i].to_bytes(1,'little')+out[i+1].to_bytes(1,'little')
...     print(pair)
...
b'24'
b'\xe8\x90'
b'2\xab'

if you search for specific error bytes e.g. e = b'\xff' you can do

if e in out:
  do_substitute(e with your byte value)

Upvotes: 0

Related Questions