port.py
Go to the documentation of this file.
1 #! /usr/bin/env python
2 # -*- coding: utf-8 -*-
3 
4 # Software License Agreement (BSD)
5 #
6 # file @port.py
7 # authors Mike Purvis <mpurvis@clearpathrobotics.com>
8 # NovAtel <novatel.com/support>
9 # copyright Copyright (c) 2012, Clearpath Robotics, Inc., All rights reserved.
10 # Copyright (c) 2014, NovAtel Inc., All rights reserved.
11 #
12 # Redistribution and use in source and binary forms, with or without modification, are permitted provided that
13 # the following conditions are met:
14 # * Redistributions of source code must retain the above copyright notice, this list of conditions and the
15 # following disclaimer.
16 # * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
17 # following disclaimer in the documentation and/or other materials provided with the distribution.
18 # * Neither the name of Clearpath Robotics nor the names of its contributors may be used to endorse or promote
19 # products derived from this software without specific prior written permission.
20 #
21 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WAR-
22 # RANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, IN-
24 # DIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
25 # OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 
29 import rospy
30 import novatel_msgs.msg as msg
31 
32 # Node source
33 from translator import Translator
34 
35 # Python
36 import threading
37 import socket
38 import struct
39 from cStringIO import StringIO
40 
41 
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")
47 
48  def __init__(self, sock, **opts):
49  super(Port, self).__init__()
50  self.sock = sock
51  self.opts = opts
52  self.daemon = False
53  self.finish = threading.Event()
54  self.bSerial = False
55 
56  def recv(self, d=False):
57  """ Receive a packet from the port's socket.
58  Returns (header, pkt_str)
59  Returns None, None when no data. """
60 
61  header = msg.CommonHeader()
62  footer = msg.CommonFooter()
63 
64  try:
65  bytes_before_sync = []
66  while True:
67  sync = self.sock.recv(1)
68  if sync == "\xAA":
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))
74  break
75  bytes_before_sync.append(sync)
76 
77  sync = self.sock.recv(1)
78  if sync != "\x44":
79  raise ValueError("Bad sync2 byte, expected 0x44, received 0x%x" % ord(sync[0]))
80  sync = self.sock.recv(1)
81  if sync != "\x12":
82  raise ValueError("Bad sync3 byte, expected 0x12, received 0x%x" % ord(sync[0]))
83 
84  # Four byte offset to account for 3 sync bytes and one header length byte already consumed.
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))
89 
90  except socket.timeout:
91  return None, None
92 
93  header_str = self.sock.recv(header_length)
94  header_data = StringIO(header_str)
95  header.translator().deserialize(header_data)
96 
97  packet_str = self.sock.recv(header.length)
98  footer_data = StringIO(self.sock.recv(footer.translator().size))
99 
100  return header, packet_str
101 
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. """
105 
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)
111 
112  footer = msg.CommonFooter(end=msg.CommonFooter.END)
113  header.length = msg_buff.tell() + footer.translator().size
114 
115  # Write header and message to main buffer.
116  buff = StringIO()
117  header.translator().serialize(buff)
118  buff.write(msg_buff.getvalue())
119 
120  # Write footer.
121  footer_start = buff.tell()
122  footer.translator().serialize(buff)
123 
124  # Compute checksum.
125  buff.seek(0)
126  footer.checksum = 65536 - self._checksum(buff)
127 
128  # Rewrite footer with correct checksum.
129  buff.seek(footer_start)
130  footer.translator().serialize(buff)
131 
132  self.sock.send(buff.getvalue())
133 
134  @classmethod
135  def _checksum(cls, buff):
136  """ Compute novatel checksum. Expects a StringIO with a
137  size that is a multiple of four bytes. """
138  checksum = 0
139 
140  while True:
141  data = buff.read(cls.checksum_struct.size)
142 
143  if len(data) == 0:
144  break
145  if len(data) < 4:
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))
149  print(data)
150  c1, c2 = cls.checksum_struct.unpack(data)
151  checksum += c1 + c2
152  print(checksum, checksum % 65536) # novatel 32 bit crc
153  return checksum % 65536
def _checksum(cls, buff)
Definition: port.py:135
def __init__(self, sock, opts)
Definition: port.py:48
def recv(self, d=False)
Definition: port.py:56
def send(self, header, message)
Definition: port.py:102


novatel_span_driver
Author(s): NovAtel Support
autogenerated on Wed Apr 3 2019 02:52:53