33 from translator
import Translator
40 from cStringIO
import StringIO
43 class Port(threading.Thread):
45 """ Common base class for DataPort and ControlPort. Provides functionality to 46 recv/send novatel-formatted packets from the socket. Could in future 47 support LoggingPort and DisplayPort.""" 48 checksum_struct = struct.Struct(
"<hh")
59 """ Receive a packet from the port's socket. 60 Returns (header, pkt_str) 61 Returns None, None when no data. """ 63 header = msg.CommonHeader()
64 footer = msg.CommonFooter()
67 bytes_before_sync = []
69 sync = self.sock.recv(1)
71 bytes_before_sync =
''.join(bytes_before_sync)
72 if len(bytes_before_sync) > 0
and not bytes_before_sync.startswith(
"\r\n<OK"):
73 rospy.logwarn((
"Discarded %d bytes between end of previous message " +
74 "and next sync byte.") % len(bytes_before_sync))
75 rospy.logwarn(
"Discarded: %s" % repr(bytes_before_sync))
77 bytes_before_sync.append(sync)
79 sync = self.sock.recv(1)
81 raise ValueError(
"Bad sync2 byte, expected 0x44, received 0x%x" % ord(sync[0]))
82 sync = self.sock.recv(1)
84 raise ValueError(
"Bad sync3 byte, expected 0x12, received 0x%x" % ord(sync[0]))
87 header_length = ord(self.sock.recv(1)[0]) - 4
88 if header_length != header.translator().size:
89 raise ValueError(
"Bad header length. Expected %d, got %d" %
90 (header.translator().size, header_length))
92 except (socket.timeout, serial.SerialTimeoutException)
as e:
93 rospy.logwarn(
"Connection timeout... %s" % str(e))
96 header_str = self.sock.recv(header_length)
97 header_data = StringIO(header_str)
98 header.translator().deserialize(header_data)
100 packet_str = self.sock.recv(header.length)
101 footer_data = StringIO(self.sock.recv(footer.translator().size))
103 return header, packet_str
105 def send(self, header, message):
106 """ Sends a header/msg/footer out the socket. Takes care of computing 107 length field for header and checksum field for footer. """ 109 msg_buff = StringIO()
110 message.translator().preserialize()
111 message.translator().serialize(msg_buff)
112 pad_count = -msg_buff.tell() % 4
113 msg_buff.write(
"\x00" * pad_count)
115 footer = msg.CommonFooter(end=msg.CommonFooter.END)
116 header.length = msg_buff.tell() + footer.translator().size
120 header.translator().serialize(buff)
121 buff.write(msg_buff.getvalue())
124 footer_start = buff.tell()
125 footer.translator().serialize(buff)
129 footer.checksum = 65536 - self.
_checksum(buff)
132 buff.seek(footer_start)
133 footer.translator().serialize(buff)
135 self.sock.send(buff.getvalue())
139 """ Compute novatel checksum. Expects a StringIO with a 140 size that is a multiple of four bytes. """ 144 data = buff.read(cls.checksum_struct.size)
149 pad_count = len(data) % 4
150 data = data +
"\x00" * pad_count
151 raise ValueError(
"Checksum data length is not a multiple of 4. %d" % len(data))
153 c1, c2 = cls.checksum_struct.unpack(data)
155 print(checksum, checksum % 65536)
156 return checksum % 65536
def __init__(self, sock, opts)
def send(self, header, message)