Reputation: 23
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
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