Paul Long
Paul Long

Reputation: 23

how to update Python 2.7 decode to Python 3.7

I have a Python 2.7 script that decodes data received from a UR5 robot arm. spent many hours trying to get this to work in Python 3.7 with no success.

I have found that the way 2.7 and 3.7 receives/holds data is very different. I have tried multiple combinations of .decode() and encode() combinations. the desired outcome of the Python 3.7 script is -4.00047543309

Many thanks in advance

import socket
import time
import struct

HOST = "192.168.0.5" # The remote host
PORT = 30003

print "Starting Program"

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
packet_1 = s.recv(4)
packet_2 = s.recv(8)
packet_3 = s.recv(48)
packet_4 = s.recv(48)
packet_5 = s.recv(48)
packet_6 = s.recv(48)
packet_7 = s.recv(48) 
packet_8 = s.recv(48)
packet_9 = s.recv(48)
packet_10 = s.recv(48)
packet_11 = s.recv(48)

packet_12 = s.recv(8)
print packet_12
packet_12 = packet_12.encode("hex")
print packet_12
x = str(packet_12)
print packet_12
x = struct.unpack('!d', packet_12.decode('hex'))[0]
print x
print "X = ", x * 1000

s.close()
print "Program finish"

this code works and returns the following

Starting Program
¿pbÍruè
bf7062cd72750fe8
bf7062cd72750fe8
-0.00400047543309
X =  -4.00047543309
Program finish

the below code is what I have tried

import socket
import time
import struct
import codecs

HOST = '192.168.0.5'
PORT = 30003
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))

print ("Connected")
packet_1 = s.recv(4)
packet_2 = s.recv(8)
packet_3 = s.recv(48)
packet_4 = s.recv(48)
packet_5 = s.recv(48)
packet_6 = s.recv(48)
packet_7 = s.recv(48)
packet_8 = s.recv(48)
packet_9 = s.recv(48)
packet_10 = s.recv(48)
packet_11 = s.recv(48)

packet_12 = s.recv(8)
print (packet_12)

s.close()

print ("Program finish")

this returns

Connected
b'\xbfpb\xcdru\x0f\xe8'
Program finish

Upvotes: 2

Views: 647

Answers (1)

Blckknght
Blckknght

Reputation: 104722

You can pretty easily transform your packet_12 bytestring in Python 3 into all the different formats you're printing out in Python 2. They seem to be: ISO 8859-1, hexadecimal (printed twice, for some reason), a double-precision float, and the same float multiplied by 1000 with a string prefix.

import binascii
import struct

packet_12 = s.recv(8)
print(packet_12.decode('latin-1'))               # prints ¿pbÍruè
print(binascii.hexlify(packet_12).decode())      # prints bf7062cd72750fe8
x = struct.unpack('!d', packet_12)[0]
print(x)                                         # prints -0.004000475433091545
print(f"X = {x*1000}"}                           # prints X = -4.0004754330915455

The main difference between how Python 3 handles this data and how Python 2 handles it is that Python 3 is much more clear about what data is an encoded bytestring and what is decoded Unicode text. In all of the lines of code above, I print out either a Unicode string, or in the print(x) case, a number that Python will convert for me into a string.

It's worth noting though that the code for the most important part of this problem is almost exactly the same between Python versions. The struct module expects to be given a bytestring, which is exactly what you have in your packet_12 variable after the socket.recv call. The only real difference is that print is now a function. I took advantage of a new Python 3 feature, f-strings, to format the output, but print("X = ", x * 1000) would work just as well.

Upvotes: 3

Related Questions