Search code examples
pythonhexpyserial

convert string of hex characters into a binary string for serial commands in python


I actually solved my problem but I couldn't find a clear reason why I need to jump through these hoops

I am looking for a concise explanation and a better method.

I need to convert a string like this

command0 = 'FF 30 30 01 51 33 34 46 EF' 

to this

b'\xff00\x01Q34F\xef'

which is the hex equivalent

I put some random solutions i found together and came up with this

def convcom(data):
    return "".join([r"\x" + x for x in data.split()]).encode('utf-8').decode('unicode_escape').encode('ISO-8859-1')

Now that does produce the desired outcome, but here are some other things I tried that did not work.

I tried this

def convcom(data):
    return "".join([r"\x" + x for x in data.split()]).encode('utf-8')

but I kept getting this result

b'\\xFF\\x30\\x30\\x01\\x51\\x33\\x34\\x46\\xEF'

I tried other solutions like hexlify but nothing worked.

I also tried something to this effect

b"" + ""join([r"\x" + x for x in data.split()])

That just flat out failed with can't concat.

The only thing that finally worked was this

"".join([r"\x" + x for x in data.split()]).encode('utf-8').decode('unicode_escape').encode('ISO-8859-1')

Solution

  • you've already provide yourself a solution, but here's how i would do it

    def str_hex_to_byte(str_hex):
        return bytes([int("0x%s" % byte, 16) for byte in command0.split()])
    
    command0 = "FF 30 30 01 51 33 34 46 EF"
    str_hex_to_byte(command0)
    

    this will return a bytes object with b'\xff00\x01Q34F\xef'

    here's a little of explaination int() constructor takes two positional arguments first is a buffer and second its the base the first buffer will be "0xFF" which is a string that contains the decimal number 0xFF which is 255 in base 16 so that's why i send as second parameter 16 now the results its gonna be a list of int with base 16

    [0xFF, 0x30, 0x30, 0x01, 0x51, 0x33, 0x34, 0x46, 0xEF,]
    

    now we pass it to bytes() constructor that could receive a list of int with members inside the range 0-255 (basically UINT8) and that will be the return of our function

    hope this was useful, i didn't explain str.split() method because you already use it so not need to do that