33 from translator
import Translator
39 from cStringIO
import StringIO
42 class Port(threading.Thread):
43 """ Common base class for DataPort and ControlPort. Provides functionality to 44 recv/send novatel-formatted packets from the socket. Could in future 45 support LoggingPort and DisplayPort.""" 46 checksum_struct = struct.Struct(
"<hh")
57 """ Receive a packet from the port's socket. 58 Returns (header, pkt_str) 59 Returns None, None when no data. """ 61 header = msg.CommonHeader()
62 footer = msg.CommonFooter()
65 bytes_before_sync = []
67 sync = self.sock.recv(1)
69 bytes_before_sync =
''.join(bytes_before_sync)
70 if len(bytes_before_sync) > 0
and not bytes_before_sync.startswith(
"\r\n<OK"):
71 rospy.logwarn((
"Discarded %d bytes between end of previous message " +
72 "and next sync byte.") % len(bytes_before_sync))
73 rospy.logwarn(
"Discarded: %s" % repr(bytes_before_sync))
75 bytes_before_sync.append(sync)
77 sync = self.sock.recv(1)
79 raise ValueError(
"Bad sync2 byte, expected 0x44, received 0x%x" % ord(sync[0]))
80 sync = self.sock.recv(1)
82 raise ValueError(
"Bad sync3 byte, expected 0x12, received 0x%x" % ord(sync[0]))
85 header_length = ord(self.sock.recv(1)[0]) - 4
86 if header_length != header.translator().size:
87 raise ValueError(
"Bad header length. Expected %d, got %d" %
88 (header.translator().size, header_length))
90 except socket.timeout:
93 header_str = self.sock.recv(header_length)
94 header_data = StringIO(header_str)
95 header.translator().deserialize(header_data)
97 packet_str = self.sock.recv(header.length)
98 footer_data = StringIO(self.sock.recv(footer.translator().size))
100 return header, packet_str
102 def send(self, header, message):
103 """ Sends a header/msg/footer out the socket. Takes care of computing 104 length field for header and checksum field for footer. """ 106 msg_buff = StringIO()
107 message.translator().preserialize()
108 message.translator().serialize(msg_buff)
109 pad_count = -msg_buff.tell() % 4
110 msg_buff.write(
"\x00" * pad_count)
112 footer = msg.CommonFooter(end=msg.CommonFooter.END)
113 header.length = msg_buff.tell() + footer.translator().size
117 header.translator().serialize(buff)
118 buff.write(msg_buff.getvalue())
121 footer_start = buff.tell()
122 footer.translator().serialize(buff)
126 footer.checksum = 65536 - self.
_checksum(buff)
129 buff.seek(footer_start)
130 footer.translator().serialize(buff)
132 self.sock.send(buff.getvalue())
136 """ Compute novatel checksum. Expects a StringIO with a 137 size that is a multiple of four bytes. """ 141 data = buff.read(cls.checksum_struct.size)
146 pad_count = len(data) % 4
147 data = data +
"\x00" * pad_count
148 raise ValueError(
"Checksum data length is not a multiple of 4. %d" % len(data))
150 c1, c2 = cls.checksum_struct.unpack(data)
152 print(checksum, checksum % 65536)
153 return checksum % 65536
def __init__(self, sock, opts)
def send(self, header, message)