bridge.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 @bridge.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 # ROS
30 import rospy
31 from novatel_msgs.msg import *
32 from std_msgs.msg import String
33 
34 # Package modules
35 from novatel_span_driver.data import DataPort
36 from novatel_span_driver.monitor import Monitor
37 
38 # Standard
39 import socket
40 import serial
41 import struct
42 from cStringIO import StringIO
43 import time
44 
45 from novatel_span_driver import translator
46 
47 DEFAULT_IP = '198.161.73.9'
48 DEFAULT_PORT = 3001
49 DEFAULT_DEV_NO = '/dev/ttyUSB0'
50 DEFAULT_BAUDRATE = 115200
51 
52 SOCKET_TIMEOUT = 100.0
53 socks = []
54 ports = {}
55 monitor = Monitor(ports)
56 
57 
58 def init():
59  # Pass this parameter to use pcap data rather than a socket to a device.
60  # For testing the node itself--to exercise downstream algorithms, use a bag.
61  pcap_file_name = rospy.get_param('~pcap_file', False)
62 
63  if not pcap_file_name:
64  connect_type = rospy.get_param('~connect_type', False)
65  if not connect_type:
66  rospy.logfatal("Failed to fetch parameter: connect_type, please configure it as 'TCP' or 'SERIAL'")
67  exit(1)
68 
69  sock = create_sock('data', connect_type)
70  else:
71  sock = create_test_sock(pcap_file_name)
72 
73  ports['data'] = DataPort(sock)
74 
75  configure_receiver(sock)
76 
77  for name, port in ports.items():
78  port.start()
79  rospy.loginfo("Port %s thread started." % name)
80  monitor.start()
81 
82  rospy.on_shutdown(shutdown)
83 
84 
85 def create_sock(name, connect_type):
86  try:
87  if "TCP" == connect_type:
88  ip = rospy.get_param('~ip', DEFAULT_IP)
89  port = rospy.get_param('~port', DEFAULT_PORT)
90  sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
91  ip_port = (ip, port)
92  sock.connect(ip_port)
93  rospy.loginfo("Successfully connected to %%s port at %s:%d" % ip_port % name)
94  elif "SERIAL" == connect_type:
95  dev_no = rospy.get_param('~dev_no', DEFAULT_DEV_NO)
96  baud = rospy.get_param('~baudrate', DEFAULT_BAUDRATE)
97  sock = serial.Serial(port=dev_no, baudrate=baud, timeout=SOCKET_TIMEOUT, rtscts=True, dsrdtr=True)
98  rospy.loginfo("Successfully connected to %%s port at %s:%d" % (dev_no, baud) % name)
99 
100  # make methods dynamically for make serial obj be compatible with socket obj
101  from types import MethodType
102  sock.recv = MethodType(serial.Serial.read, sock, serial.Serial)
103  sock.send = MethodType(serial.Serial.write, sock, serial.Serial)
104  sock.settimeout = MethodType(lambda *args, **kwargs: None, sock, serial.Serial)
105  sock.shutdown = MethodType(lambda *args, **kwargs: None, sock, serial.Serial)
106  else:
107  rospy.logfatal("Connect type: %s isn't supported yet, please configure it as 'TCP' or 'SERIAL'"
108  % connect_type)
109  exit(1)
110  except (socket.error, serial.SerialException) as e:
111  rospy.logfatal("Couldn't connect to port at %s:%s" % (name, str(e)))
112  exit(1)
113  sock.settimeout(SOCKET_TIMEOUT)
114  socks.append(sock)
115  return sock
116 
117 
118 def create_test_sock(pcap_filename):
119  rospy.sleep(0.1)
120 
121  try:
122  import pcapy
123  except ImportError:
124  import pure_pcapy as pcapy
125 
126  from StringIO import StringIO
127  from impacket import ImpactDecoder
128 
129  body_list = []
130  if pcap_filename.endswith("gz"):
131  # From: http://projects.honeynet.org/honeysnap/changeset/35/trunk/honeysnap/__init__.py
132  import tempfile
133  import gzip
134  tmph, tmpf = tempfile.mkstemp()
135  tmph = open(tmpf, 'wb')
136  gfile = gzip.open(pcap_filename)
137  tmph.write(gfile.read())
138  gfile.close()
139  tmph.close()
140  pcap_filename = tmpf
141 
142  cap = pcapy.open_offline(pcap_filename)
143  decoder = ImpactDecoder.EthDecoder()
144 
145  while True:
146  header, payload = cap.next()
147  if not header:
148  break
149  try:
150  tcp = decoder.decode(payload).child().child()
151  body_list.append(tcp.child().get_packet())
152  except AttributeError:
153  print(decoder.decode(payload))
154  raise
155 
156  data_io = StringIO(''.join(body_list))
157 
158  class MockSocket(object):
159 
160  def recv(self, byte_count):
161  rospy.sleep(0.002)
162  data = data_io.read(byte_count)
163  if data == "":
164  rospy.signal_shutdown("Test completed.")
165  return data
166 
167  def settimeout(self, timeout):
168  pass
169 
170  return MockSocket()
171 
172 
174  receiver_config = rospy.get_param('~configuration', None)
175 
176  if receiver_config is not None:
177  imu_connect = receiver_config.get('imu_connect', None)
178  if imu_connect is not None:
179  rospy.loginfo("Sending IMU connection string to SPAN system.")
180  port.send('connectimu ' + imu_connect['port'] + ' ' + imu_connect['type'] + '\r\n')
181 
182  logger = receiver_config.get('log_request', [])
183  rospy.loginfo("Enabling %i log outputs from SPAN system." % len(logger))
184  for log in logger:
185  port.send('log ' + log + ' ontime ' + str(logger[log]) + '\r\n')
186 
187  commands = receiver_config.get('command', [])
188  rospy.loginfo("Sending %i user-specified initialization commands to SPAN system." % len(commands))
189  for cmd in commands:
190  port.send(cmd + ' ' + str(commands[cmd]) + '\r\n')
191 
192 
193 def shutdown():
194  monitor.finish.set()
195  monitor.join()
196  rospy.loginfo("Thread monitor finished.")
197  for name, port in ports.items():
198  port.finish.set()
199  port.join()
200  rospy.loginfo("Port %s thread finished." % name)
201  for sock in socks:
202  sock.shutdown(socket.SHUT_RDWR)
203  sock.close()
204  rospy.loginfo("Sockets closed.")
def create_sock(name, connect_type)
Definition: bridge.py:85
def create_test_sock(pcap_filename)
Definition: bridge.py:118
def configure_receiver(port)
Definition: bridge.py:173


novatel_span_driver
Author(s): NovAtel Support
autogenerated on Mon Sep 2 2019 03:58:19