SerialClient.py
Go to the documentation of this file.
1 
33 
34 __author__ = "mferguson@willowgarage.com (Michael Ferguson)"
35 
36 import array
37 import errno
38 import imp
39 import io
40 import multiprocessing
41 import queue
42 import socket
43 import struct
44 import sys
45 import threading
46 import time
47 
48 from serial import Serial, SerialException, SerialTimeoutException
49 
50 import roslib
51 import rospy
52 from std_msgs.msg import Time
53 from rosserial_msgs.msg import TopicInfo, Log
54 from rosserial_msgs.srv import RequestParamRequest, RequestParamResponse
55 
56 import diagnostic_msgs.msg
57 
58 ERROR_MISMATCHED_PROTOCOL = "Mismatched protocol version in packet: lost sync or rosserial_python is from different ros release than the rosserial client"
59 ERROR_NO_SYNC = "no sync with device"
60 ERROR_PACKET_FAILED = "Packet Failed : Failed to read msg data"
61 
62 def load_pkg_module(package, directory):
63  #check if its in the python path
64  path = sys.path
65  try:
66  imp.find_module(package)
67  except ImportError:
68  roslib.load_manifest(package)
69  try:
70  m = __import__( package + '.' + directory )
71  except ImportError:
72  rospy.logerr( "Cannot import package : %s"% package )
73  rospy.logerr( "sys.path was " + str(path) )
74  return None
75  return m
76 
77 def load_message(package, message):
78  m = load_pkg_module(package, 'msg')
79  m2 = getattr(m, 'msg')
80  return getattr(m2, message)
81 
82 def load_service(package,service):
83  s = load_pkg_module(package, 'srv')
84  s = getattr(s, 'srv')
85  srv = getattr(s, service)
86  mreq = getattr(s, service+"Request")
87  mres = getattr(s, service+"Response")
88  return srv,mreq,mres
89 
90 class Publisher:
91  """
92  Publisher forwards messages from the serial device to ROS.
93  """
94  def __init__(self, topic_info):
95  """ Create a new publisher. """
96  self.topic = topic_info.topic_name
97 
98  # find message type
99  package, message = topic_info.message_type.split('/')
100  self.message = load_message(package, message)
101  if self.message._md5sum == topic_info.md5sum:
102  self.publisher = rospy.Publisher(self.topic, self.message, queue_size=10)
103  else:
104  raise Exception('Checksum does not match: ' + self.message._md5sum + ',' + topic_info.md5sum)
105 
106  def handlePacket(self, data):
107  """ Forward message to ROS network. """
108  m = self.message()
109  m.deserialize(data)
110  self.publisher.publish(m)
111 
112 
114  """
115  Subscriber forwards messages from ROS to the serial device.
116  """
117 
118  def __init__(self, topic_info, parent):
119  self.topic = topic_info.topic_name
120  self.id = topic_info.topic_id
121  self.parent = parent
122 
123  # find message type
124  package, message = topic_info.message_type.split('/')
125  self.message = load_message(package, message)
126  if self.message._md5sum == topic_info.md5sum:
127  self.subscriber = rospy.Subscriber(self.topic, self.message, self.callback)
128  else:
129  raise Exception('Checksum does not match: ' + self.message._md5sum + ',' + topic_info.md5sum)
130 
131  def callback(self, msg):
132  """ Forward message to serial device. """
133  data_buffer = io.BytesIO()
134  msg.serialize(data_buffer)
135  self.parent.send(self.id, data_buffer.getvalue())
136 
137  def unregister(self):
138  rospy.loginfo("Removing subscriber: %s", self.topic)
139  self.subscriber.unregister()
140 
142  """
143  ServiceServer responds to requests from ROS.
144  """
145 
146  def __init__(self, topic_info, parent):
147  self.topic = topic_info.topic_name
148  self.parent = parent
149 
150  # find message type
151  package, service = topic_info.message_type.split('/')
152  s = load_pkg_module(package, 'srv')
153  s = getattr(s, 'srv')
154  self.mreq = getattr(s, service+"Request")
155  self.mres = getattr(s, service+"Response")
156  srv = getattr(s, service)
157  self.service = rospy.Service(self.topic, srv, self.callback)
158 
159  # response message
160  self.data = None
161 
162  def unregister(self):
163  rospy.loginfo("Removing service: %s", self.topic)
164  self.service.shutdown()
165 
166  def callback(self, req):
167  """ Forward request to serial device. """
168  data_buffer = io.BytesIO()
169  req.serialize(data_buffer)
170  self.response = None
171  self.parent.send(self.id, data_buffer.getvalue())
172  while self.response is None:
173  pass
174  return self.response
175 
176  def handlePacket(self, data):
177  """ Forward response to ROS network. """
178  r = self.mres()
179  r.deserialize(data)
180  self.response = r
181 
182 
184  """
185  ServiceServer responds to requests from ROS.
186  """
187 
188  def __init__(self, topic_info, parent):
189  self.topic = topic_info.topic_name
190  self.parent = parent
191 
192  # find message type
193  package, service = topic_info.message_type.split('/')
194  s = load_pkg_module(package, 'srv')
195  s = getattr(s, 'srv')
196  self.mreq = getattr(s, service+"Request")
197  self.mres = getattr(s, service+"Response")
198  srv = getattr(s, service)
199  rospy.loginfo("Starting service client, waiting for service '" + self.topic + "'")
200  rospy.wait_for_service(self.topic)
201  self.proxy = rospy.ServiceProxy(self.topic, srv)
202 
203  def handlePacket(self, data):
204  """ Forward request to ROS network. """
205  req = self.mreq()
206  req.deserialize(data)
207  # call service proxy
208  resp = self.proxy(req)
209  # serialize and publish
210  data_buffer = io.BytesIO()
211  resp.serialize(data_buffer)
212  self.parent.send(self.id, data_buffer.getvalue())
213 
215  """
216  RosSerialServer waits for a socket connection then passes itself, forked as a
217  new process, to SerialClient which uses it as a serial port. It continues to listen
218  for additional connections. Each forked process is a new ros node, and proxies ros
219  operations (e.g. publish/subscribe) from its connection to the rest of ros.
220  """
221  def __init__(self, tcp_portnum, fork_server=False):
222  rospy.loginfo("Fork_server is: %s" % fork_server)
223  self.tcp_portnum = tcp_portnum
224  self.fork_server = fork_server
225 
226  def listen(self):
227  self.serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
228  self.serversocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
229  #bind the socket to a public host, and a well-known port
230  self.serversocket.bind(("", self.tcp_portnum)) #become a server socket
231  self.serversocket.listen(1)
232  self.serversocket.settimeout(1)
233 
234  #accept connections
235  rospy.loginfo("Waiting for socket connection")
236  while not rospy.is_shutdown():
237  try:
238  clientsocket, address = self.serversocket.accept()
239  except socket.timeout:
240  continue
241 
242  #now do something with the clientsocket
243  rospy.loginfo("Established a socket connection from %s on port %s" % address)
244  self.socket = clientsocket
245  self.isConnected = True
246 
247  if self.fork_server: # if configured to launch server in a separate process
248  rospy.loginfo("Forking a socket server process")
249  process = multiprocessing.Process(target=self.startSocketServer, args=address)
250  process.daemon = True
251  process.start()
252  rospy.loginfo("launched startSocketServer")
253  else:
254  rospy.loginfo("calling startSerialClient")
255  self.startSerialClient()
256  rospy.loginfo("startSerialClient() exited")
257 
258  def startSerialClient(self):
259  client = SerialClient(self)
260  try:
261  client.run()
262  except KeyboardInterrupt:
263  pass
264  except RuntimeError:
265  rospy.loginfo("RuntimeError exception caught")
266  self.isConnected = False
267  except socket.error:
268  rospy.loginfo("socket.error exception caught")
269  self.isConnected = False
270  finally:
271  rospy.loginfo("Client has exited, closing socket.")
272  self.socket.close()
273  for sub in client.subscribers.values():
274  sub.unregister()
275  for srv in client.services.values():
276  srv.unregister()
277 
278  def startSocketServer(self, port, address):
279  rospy.loginfo("starting ROS Serial Python Node serial_node-%r" % address)
280  rospy.init_node("serial_node_%r" % address)
281  self.startSerialClient()
282 
283  def flushInput(self):
284  pass
285 
286  def write(self, data):
287  if not self.isConnected:
288  return
289  length = len(data)
290  totalsent = 0
291 
292  while totalsent < length:
293  try:
294  totalsent += self.socket.send(data[totalsent:])
295  except BrokenPipeError:
296  raise RuntimeError("RosSerialServer.write() socket connection broken")
297 
298  def read(self, rqsted_length):
299  self.msg = b''
300  if not self.isConnected:
301  return self.msg
302 
303  while len(self.msg) < rqsted_length:
304  chunk = self.socket.recv(rqsted_length - len(self.msg))
305  if chunk == b'':
306  raise RuntimeError("RosSerialServer.read() socket connection broken")
307  self.msg = self.msg + chunk
308  return self.msg
309 
310  def inWaiting(self):
311  try: # the caller checks just for <1, so we'll peek at just one byte
312  chunk = self.socket.recv(1, socket.MSG_DONTWAIT|socket.MSG_PEEK)
313  if chunk == b'':
314  raise RuntimeError("RosSerialServer.inWaiting() socket connection broken")
315  return len(chunk)
316  except BlockingIOError:
317  return 0
318 
319 class SerialClient(object):
320  """
321  ServiceServer responds to requests from the serial device.
322  """
323  header = b'\xff'
324 
325  # hydro introduces protocol ver2 which must match node_handle.h
326  # The protocol version is sent as the 2nd sync byte emitted by each end
327  protocol_ver1 = b'\xff'
328  protocol_ver2 = b'\xfe'
329  protocol_ver = protocol_ver2
330 
331  def __init__(self, port=None, baud=57600, timeout=5.0, fix_pyserial_for_test=False):
332  """ Initialize node, connect to bus, attempt to negotiate topics. """
333 
334  self.read_lock = threading.RLock()
335 
336  self.write_lock = threading.RLock()
337  self.write_queue = queue.Queue()
338  self.write_thread = None
339 
340  self.lastsync = rospy.Time(0)
341  self.lastsync_lost = rospy.Time(0)
342  self.lastsync_success = rospy.Time(0)
343  self.last_read = rospy.Time(0)
344  self.last_write = rospy.Time(0)
345  self.timeout = timeout
346  self.synced = False
347  self.fix_pyserial_for_test = fix_pyserial_for_test
348 
349  self.publishers = dict() # id:Publishers
350  self.subscribers = dict() # topic:Subscriber
351  self.services = dict() # topic:Service
352 
353  def shutdown():
354  self.txStopRequest()
355  rospy.loginfo('shutdown hook activated')
356  rospy.on_shutdown(shutdown)
357 
358  self.pub_diagnostics = rospy.Publisher('/diagnostics', diagnostic_msgs.msg.DiagnosticArray, queue_size=10)
359 
360  if port is None:
361  # no port specified, listen for any new port?
362  pass
363  elif hasattr(port, 'read'):
364  #assume its a filelike object
365  self.port=port
366  else:
367  # open a specific port
368  while not rospy.is_shutdown():
369  try:
370  if self.fix_pyserial_for_test:
371  # see https://github.com/pyserial/pyserial/issues/59
372  self.port = Serial(port, baud, timeout=self.timeout, write_timeout=10, rtscts=True, dsrdtr=True)
373  else:
374  self.port = Serial(port, baud, timeout=self.timeout, write_timeout=10)
375  break
376  except SerialException as e:
377  rospy.logerr("Error opening serial: %s", e)
378  time.sleep(3)
379 
380  if rospy.is_shutdown():
381  return
382 
383  time.sleep(0.1) # Wait for ready (patch for Uno)
384 
385  self.buffer_out = -1
386  self.buffer_in = -1
387 
388  self.callbacks = dict()
389  # endpoints for creating new pubs/subs
390  self.callbacks[TopicInfo.ID_PUBLISHER] = self.setupPublisher
391  self.callbacks[TopicInfo.ID_SUBSCRIBER] = self.setupSubscriber
392  # service client/servers have 2 creation endpoints (a publisher and a subscriber)
393  self.callbacks[TopicInfo.ID_SERVICE_SERVER+TopicInfo.ID_PUBLISHER] = self.setupServiceServerPublisher
394  self.callbacks[TopicInfo.ID_SERVICE_SERVER+TopicInfo.ID_SUBSCRIBER] = self.setupServiceServerSubscriber
395  self.callbacks[TopicInfo.ID_SERVICE_CLIENT+TopicInfo.ID_PUBLISHER] = self.setupServiceClientPublisher
396  self.callbacks[TopicInfo.ID_SERVICE_CLIENT+TopicInfo.ID_SUBSCRIBER] = self.setupServiceClientSubscriber
397  # custom endpoints
398  self.callbacks[TopicInfo.ID_PARAMETER_REQUEST] = self.handleParameterRequest
399  self.callbacks[TopicInfo.ID_LOG] = self.handleLoggingRequest
400  self.callbacks[TopicInfo.ID_TIME] = self.handleTimeRequest
401 
402  rospy.sleep(2.0)
403  self.requestTopics()
404  self.lastsync = rospy.Time.now()
405 
406  def requestTopics(self):
407  """ Determine topics to subscribe/publish. """
408  rospy.loginfo('Requesting topics...')
409 
410  # TODO remove if possible
411  if not self.fix_pyserial_for_test:
412  with self.read_lock:
413  self.port.flushInput()
414 
415  # request topic sync
416  self.write_queue.put(self.header + self.protocol_ver + b"\x00\x00\xff\x00\x00\xff")
417 
418  def txStopRequest(self):
419  """ Send stop tx request to client before the node exits. """
420  if not self.fix_pyserial_for_test:
421  with self.read_lock:
422  self.port.flushInput()
423 
424  self.write_queue.put(self.header + self.protocol_ver + b"\x00\x00\xff\x0b\x00\xf4")
425  rospy.loginfo("Sending tx stop request")
426 
427  def tryRead(self, length):
428  try:
429  read_start = time.time()
430  bytes_remaining = length
431  result = bytearray()
432  while bytes_remaining != 0 and time.time() - read_start < self.timeout:
433  with self.read_lock:
434  received = self.port.read(bytes_remaining)
435  if len(received) != 0:
436  self.last_read = rospy.Time.now()
437  result.extend(received)
438  bytes_remaining -= len(received)
439 
440  if bytes_remaining != 0:
441  raise IOError("Returned short (expected %d bytes, received %d instead)." % (length, length - bytes_remaining))
442 
443  return bytes(result)
444  except Exception as e:
445  raise IOError("Serial Port read failure: %s" % e)
446 
447  def run(self):
448  """ Forward recieved messages to appropriate publisher. """
449 
450  # Launch write thread.
451  if self.write_thread is None:
452  self.write_thread = threading.Thread(target=self.processWriteQueue)
453  self.write_thread.daemon = True
454  self.write_thread.start()
455 
456  # Handle reading.
457  data = ''
458  read_step = None
459  while self.write_thread.is_alive() and not rospy.is_shutdown():
460  if (rospy.Time.now() - self.lastsync).to_sec() > (self.timeout * 3):
461  if self.synced:
462  rospy.logerr("Lost sync with device, restarting...")
463  else:
464  rospy.logerr("Unable to sync with device; possible link problem or link software version mismatch such as hydro rosserial_python with groovy Arduino")
465  self.lastsync_lost = rospy.Time.now()
466  self.sendDiagnostics(diagnostic_msgs.msg.DiagnosticStatus.ERROR, ERROR_NO_SYNC)
467  self.requestTopics()
468  self.lastsync = rospy.Time.now()
469 
470  # This try-block is here because we make multiple calls to read(). Any one of them can throw
471  # an IOError if there's a serial problem or timeout. In that scenario, a single handler at the
472  # bottom attempts to reconfigure the topics.
473  try:
474  with self.read_lock:
475  if self.port.inWaiting() < 1:
476  time.sleep(0.001)
477  continue
478 
479  # Find sync flag.
480  flag = [0, 0]
481  read_step = 'syncflag'
482  flag[0] = self.tryRead(1)
483  if (flag[0] != self.header):
484  continue
485 
486  # Find protocol version.
487  read_step = 'protocol'
488  flag[1] = self.tryRead(1)
489  if flag[1] != self.protocol_ver:
490  self.sendDiagnostics(diagnostic_msgs.msg.DiagnosticStatus.ERROR, ERROR_MISMATCHED_PROTOCOL)
491  rospy.logerr("Mismatched protocol version in packet (%s): lost sync or rosserial_python is from different ros release than the rosserial client" % repr(flag[1]))
492  protocol_ver_msgs = {
493  self.protocol_ver1: 'Rev 0 (rosserial 0.4 and earlier)',
494  self.protocol_ver2: 'Rev 1 (rosserial 0.5+)',
495  b'\xfd': 'Some future rosserial version'
496  }
497  if flag[1] in protocol_ver_msgs:
498  found_ver_msg = 'Protocol version of client is ' + protocol_ver_msgs[flag[1]]
499  else:
500  found_ver_msg = "Protocol version of client is unrecognized"
501  rospy.loginfo("%s, expected %s" % (found_ver_msg, protocol_ver_msgs[self.protocol_ver]))
502  continue
503 
504  # Read message length, checksum (3 bytes)
505  read_step = 'message length'
506  msg_len_bytes = self.tryRead(3)
507  msg_length, _ = struct.unpack("<hB", msg_len_bytes)
508 
509  # Validate message length checksum.
510  if sum(array.array("B", msg_len_bytes)) % 256 != 255:
511  rospy.loginfo("Wrong checksum for msg length, length %d, dropping message." % (msg_length))
512  continue
513 
514  # Read topic id (2 bytes)
515  read_step = 'topic id'
516  topic_id_header = self.tryRead(2)
517  topic_id, = struct.unpack("<H", topic_id_header)
518 
519  # Read serialized message data.
520  read_step = 'data'
521  try:
522  msg = self.tryRead(msg_length)
523  except IOError:
524  self.sendDiagnostics(diagnostic_msgs.msg.DiagnosticStatus.ERROR, ERROR_PACKET_FAILED)
525  rospy.loginfo("Packet Failed : Failed to read msg data")
526  rospy.loginfo("expected msg length is %d", msg_length)
527  raise
528 
529  # Reada checksum for topic id and msg
530  read_step = 'data checksum'
531  chk = self.tryRead(1)
532  checksum = sum(array.array('B', topic_id_header + msg + chk))
533 
534  # Validate checksum.
535  if checksum % 256 == 255:
536  self.synced = True
537  self.lastsync_success = rospy.Time.now()
538  try:
539  self.callbacks[topic_id](msg)
540  except KeyError:
541  rospy.logerr("Tried to publish before configured, topic id %d" % topic_id)
542  self.requestTopics()
543  time.sleep(0.001)
544  else:
545  rospy.loginfo("wrong checksum for topic id and msg")
546 
547  except IOError as exc:
548  rospy.logwarn('Last read step: %s' % read_step)
549  rospy.logwarn('Run loop error: %s' % exc)
550  # One of the read calls had an issue. Just to be safe, request that the client
551  # reinitialize their topics.
552  with self.read_lock:
553  self.port.flushInput()
554  with self.write_lock:
555  self.port.flushOutput()
556  self.requestTopics()
557  self.write_thread.join()
558 
559  def setPublishSize(self, size):
560  if self.buffer_out < 0:
561  self.buffer_out = size
562  rospy.loginfo("Note: publish buffer size is %d bytes" % self.buffer_out)
563 
564  def setSubscribeSize(self, size):
565  if self.buffer_in < 0:
566  self.buffer_in = size
567  rospy.loginfo("Note: subscribe buffer size is %d bytes" % self.buffer_in)
568 
569  def setupPublisher(self, data):
570  """ Register a new publisher. """
571  try:
572  msg = TopicInfo()
573  msg.deserialize(data)
574  pub = Publisher(msg)
575  self.publishers[msg.topic_id] = pub
576  self.callbacks[msg.topic_id] = pub.handlePacket
577  self.setPublishSize(msg.buffer_size)
578  rospy.loginfo("Setup publisher on %s [%s]" % (msg.topic_name, msg.message_type) )
579  except Exception as e:
580  rospy.logerr("Creation of publisher failed: %s", e)
581 
582  def setupSubscriber(self, data):
583  """ Register a new subscriber. """
584  try:
585  msg = TopicInfo()
586  msg.deserialize(data)
587  if not msg.topic_name in list(self.subscribers.keys()):
588  sub = Subscriber(msg, self)
589  self.subscribers[msg.topic_name] = sub
590  self.setSubscribeSize(msg.buffer_size)
591  rospy.loginfo("Setup subscriber on %s [%s]" % (msg.topic_name, msg.message_type) )
592  elif msg.message_type != self.subscribers[msg.topic_name].message._type:
593  old_message_type = self.subscribers[msg.topic_name].message._type
594  self.subscribers[msg.topic_name].unregister()
595  sub = Subscriber(msg, self)
596  self.subscribers[msg.topic_name] = sub
597  self.setSubscribeSize(msg.buffer_size)
598  rospy.loginfo("Change the message type of subscriber on %s from [%s] to [%s]" % (msg.topic_name, old_message_type, msg.message_type) )
599  except Exception as e:
600  rospy.logerr("Creation of subscriber failed: %s", e)
601 
603  """ Register a new service server. """
604  try:
605  msg = TopicInfo()
606  msg.deserialize(data)
607  self.setPublishSize(msg.buffer_size)
608  try:
609  srv = self.services[msg.topic_name]
610  except KeyError:
611  srv = ServiceServer(msg, self)
612  rospy.loginfo("Setup service server on %s [%s]" % (msg.topic_name, msg.message_type) )
613  self.services[msg.topic_name] = srv
614  if srv.mres._md5sum == msg.md5sum:
615  self.callbacks[msg.topic_id] = srv.handlePacket
616  else:
617  raise Exception('Checksum does not match: ' + srv.mres._md5sum + ',' + msg.md5sum)
618  except Exception as e:
619  rospy.logerr("Creation of service server failed: %s", e)
620 
622  """ Register a new service server. """
623  try:
624  msg = TopicInfo()
625  msg.deserialize(data)
626  self.setSubscribeSize(msg.buffer_size)
627  try:
628  srv = self.services[msg.topic_name]
629  except KeyError:
630  srv = ServiceServer(msg, self)
631  rospy.loginfo("Setup service server on %s [%s]" % (msg.topic_name, msg.message_type) )
632  self.services[msg.topic_name] = srv
633  if srv.mreq._md5sum == msg.md5sum:
634  srv.id = msg.topic_id
635  else:
636  raise Exception('Checksum does not match: ' + srv.mreq._md5sum + ',' + msg.md5sum)
637  except Exception as e:
638  rospy.logerr("Creation of service server failed: %s", e)
639 
641  """ Register a new service client. """
642  try:
643  msg = TopicInfo()
644  msg.deserialize(data)
645  self.setPublishSize(msg.buffer_size)
646  try:
647  srv = self.services[msg.topic_name]
648  except KeyError:
649  srv = ServiceClient(msg, self)
650  rospy.loginfo("Setup service client on %s [%s]" % (msg.topic_name, msg.message_type) )
651  self.services[msg.topic_name] = srv
652  if srv.mreq._md5sum == msg.md5sum:
653  self.callbacks[msg.topic_id] = srv.handlePacket
654  else:
655  raise Exception('Checksum does not match: ' + srv.mreq._md5sum + ',' + msg.md5sum)
656  except Exception as e:
657  rospy.logerr("Creation of service client failed: %s", e)
658 
660  """ Register a new service client. """
661  try:
662  msg = TopicInfo()
663  msg.deserialize(data)
664  self.setSubscribeSize(msg.buffer_size)
665  try:
666  srv = self.services[msg.topic_name]
667  except KeyError:
668  srv = ServiceClient(msg, self)
669  rospy.loginfo("Setup service client on %s [%s]" % (msg.topic_name, msg.message_type) )
670  self.services[msg.topic_name] = srv
671  if srv.mres._md5sum == msg.md5sum:
672  srv.id = msg.topic_id
673  else:
674  raise Exception('Checksum does not match: ' + srv.mres._md5sum + ',' + msg.md5sum)
675  except Exception as e:
676  rospy.logerr("Creation of service client failed: %s", e)
677 
678  def handleTimeRequest(self, data):
679  """ Respond to device with system time. """
680  t = Time()
681  t.data = rospy.Time.now()
682  data_buffer = io.BytesIO()
683  t.serialize(data_buffer)
684  self.send( TopicInfo.ID_TIME, data_buffer.getvalue() )
685  self.lastsync = rospy.Time.now()
686 
687  def handleParameterRequest(self, data):
688  """ Send parameters to device. Supports only simple datatypes and arrays of such. """
689  req = RequestParamRequest()
690  req.deserialize(data)
691  resp = RequestParamResponse()
692  try:
693  param = rospy.get_param(req.name)
694  except KeyError:
695  rospy.logerr("Parameter %s does not exist"%req.name)
696  return
697 
698  if param is None:
699  rospy.logerr("Parameter %s does not exist"%req.name)
700  return
701 
702  if isinstance(param, dict):
703  rospy.logerr("Cannot send param %s because it is a dictionary"%req.name)
704  return
705  if not isinstance(param, list):
706  param = [param]
707  #check to make sure that all parameters in list are same type
708  t = type(param[0])
709  for p in param:
710  if t!= type(p):
711  rospy.logerr('All Paramers in the list %s must be of the same type'%req.name)
712  return
713  if t == int or t == bool:
714  resp.ints = param
715  if t == float:
716  resp.floats =param
717  if t == str:
718  resp.strings = param
719  data_buffer = io.BytesIO()
720  resp.serialize(data_buffer)
721  self.send(TopicInfo.ID_PARAMETER_REQUEST, data_buffer.getvalue())
722 
723  def handleLoggingRequest(self, data):
724  """ Forward logging information from serial device into ROS. """
725  msg = Log()
726  msg.deserialize(data)
727  if msg.level == Log.ROSDEBUG:
728  rospy.logdebug(msg.msg)
729  elif msg.level == Log.INFO:
730  rospy.loginfo(msg.msg)
731  elif msg.level == Log.WARN:
732  rospy.logwarn(msg.msg)
733  elif msg.level == Log.ERROR:
734  rospy.logerr(msg.msg)
735  elif msg.level == Log.FATAL:
736  rospy.logfatal(msg.msg)
737 
738  def send(self, topic, msg):
739  """
740  Queues data to be written to the serial port.
741  """
742  self.write_queue.put((topic, msg))
743 
744  def _write(self, data):
745  """
746  Writes raw data over the serial port. Assumes the data is formatting as a packet. http://wiki.ros.org/rosserial/Overview/Protocol
747  """
748  with self.write_lock:
749  self.port.write(data)
750  self.last_write = rospy.Time.now()
751 
752  def _send(self, topic, msg_bytes):
753  """
754  Send a message on a particular topic to the device.
755  """
756  length = len(msg_bytes)
757  if self.buffer_in > 0 and length > self.buffer_in:
758  rospy.logerr("Message from ROS network dropped: message larger than buffer.\n%s" % msg)
759  return -1
760  else:
761  # frame : header (1b) + version (1b) + msg_len(2b) + msg_len_chk(1b) + topic_id(2b) + msg(nb) + msg_topic_id_chk(1b)
762  length_bytes = struct.pack('<h', length)
763  length_checksum = 255 - (sum(array.array('B', length_bytes)) % 256)
764  length_checksum_bytes = struct.pack('B', length_checksum)
765 
766  topic_bytes = struct.pack('<h', topic)
767  msg_checksum = 255 - (sum(array.array('B', topic_bytes + msg_bytes)) % 256)
768  msg_checksum_bytes = struct.pack('B', msg_checksum)
769 
770  self._write(self.header + self.protocol_ver + length_bytes + length_checksum_bytes + topic_bytes + msg_bytes + msg_checksum_bytes)
771  return length
772 
773  def processWriteQueue(self):
774  """
775  Main loop for the thread that processes outgoing data to write to the serial port.
776  """
777  while not rospy.is_shutdown():
778  if self.write_queue.empty():
779  time.sleep(0.01)
780  else:
781  data = self.write_queue.get()
782  while True:
783  try:
784  if isinstance(data, tuple):
785  topic, msg = data
786  self._send(topic, msg)
787  elif isinstance(data, bytes):
788  self._write(data)
789  else:
790  rospy.logerr("Trying to write invalid data type: %s" % type(data))
791  break
792  except SerialTimeoutException as exc:
793  rospy.logerr('Write timeout: %s' % exc)
794  time.sleep(1)
795  except RuntimeError as exc:
796  rospy.logerr('Write thread exception: %s' % exc)
797  break
798 
799 
800  def sendDiagnostics(self, level, msg_text):
801  msg = diagnostic_msgs.msg.DiagnosticArray()
802  status = diagnostic_msgs.msg.DiagnosticStatus()
803  status.name = "rosserial_python"
804  msg.header.stamp = rospy.Time.now()
805  msg.status.append(status)
806 
807  status.message = msg_text
808  status.level = level
809 
810  status.values.append(diagnostic_msgs.msg.KeyValue())
811  status.values[0].key="last sync"
812  if self.lastsync.to_sec()>0:
813  status.values[0].value=time.ctime(self.lastsync.to_sec())
814  else:
815  status.values[0].value="never"
816 
817  status.values.append(diagnostic_msgs.msg.KeyValue())
818  status.values[1].key="last sync lost"
819  status.values[1].value=time.ctime(self.lastsync_lost.to_sec())
820 
821  self.pub_diagnostics.publish(msg)
rosserial_python.SerialClient.RosSerialServer.startSocketServer
def startSocketServer(self, port, address)
Definition: SerialClient.py:278
rosserial_python.SerialClient.ServiceServer.mres
mres
Definition: SerialClient.py:155
rosserial_python.SerialClient.ServiceServer.response
response
Definition: SerialClient.py:170
rosserial_python.SerialClient.SerialClient.__init__
def __init__(self, port=None, baud=57600, timeout=5.0, fix_pyserial_for_test=False)
Definition: SerialClient.py:331
rosserial_python.SerialClient.ServiceServer.parent
parent
Definition: SerialClient.py:148
rosserial_python.SerialClient.ServiceClient.handlePacket
def handlePacket(self, data)
Definition: SerialClient.py:203
rosserial_python.SerialClient.ServiceServer.service
service
Definition: SerialClient.py:157
rosserial_python.SerialClient.SerialClient.run
def run(self)
Definition: SerialClient.py:447
rosserial_python.SerialClient.RosSerialServer.write
def write(self, data)
Definition: SerialClient.py:286
rosserial_python.SerialClient.SerialClient.setPublishSize
def setPublishSize(self, size)
Definition: SerialClient.py:559
rosserial_python.SerialClient.Subscriber.message
message
Definition: SerialClient.py:125
rosserial_python.SerialClient.Subscriber.__init__
def __init__(self, topic_info, parent)
Definition: SerialClient.py:118
rosserial_python.SerialClient.Publisher
Definition: SerialClient.py:90
rosserial_python.SerialClient.load_pkg_module
def load_pkg_module(package, directory)
Definition: SerialClient.py:62
rosserial_python.SerialClient.ServiceServer.callback
def callback(self, req)
Definition: SerialClient.py:166
rosserial_python.SerialClient.Subscriber.parent
parent
Definition: SerialClient.py:121
rosserial_python.SerialClient.RosSerialServer.fork_server
fork_server
Definition: SerialClient.py:224
rosserial_python.SerialClient.SerialClient.write_queue
write_queue
Definition: SerialClient.py:337
rosserial_python.SerialClient.SerialClient.publishers
publishers
Definition: SerialClient.py:349
rosserial_python.SerialClient.RosSerialServer.serversocket
serversocket
Definition: SerialClient.py:227
rosserial_python.SerialClient.SerialClient.write_lock
write_lock
Definition: SerialClient.py:336
rosserial_python.SerialClient.SerialClient.buffer_in
buffer_in
Definition: SerialClient.py:386
rosserial_python.SerialClient.ServiceServer.mreq
mreq
Definition: SerialClient.py:154
rosserial_python.SerialClient.SerialClient.sendDiagnostics
def sendDiagnostics(self, level, msg_text)
Definition: SerialClient.py:800
rosserial_python.SerialClient.SerialClient.services
services
Definition: SerialClient.py:351
rosserial_python.SerialClient.ServiceServer.unregister
def unregister(self)
Definition: SerialClient.py:162
rosserial_python.SerialClient.Subscriber.subscriber
subscriber
Definition: SerialClient.py:127
rosserial_python.SerialClient.SerialClient.processWriteQueue
def processWriteQueue(self)
Definition: SerialClient.py:773
rosserial_python.SerialClient.Publisher.__init__
def __init__(self, topic_info)
Definition: SerialClient.py:94
rosserial_python.SerialClient.SerialClient.timeout
timeout
Definition: SerialClient.py:345
rosserial_python.SerialClient.ServiceServer.handlePacket
def handlePacket(self, data)
Definition: SerialClient.py:176
rosserial_python.SerialClient.SerialClient.write_thread
write_thread
Definition: SerialClient.py:338
rosserial_python.SerialClient.RosSerialServer.tcp_portnum
tcp_portnum
Definition: SerialClient.py:223
rosserial_python.SerialClient.SerialClient.lastsync_lost
lastsync_lost
Definition: SerialClient.py:341
rosserial_python.SerialClient.RosSerialServer.isConnected
isConnected
Definition: SerialClient.py:245
rosserial_python.SerialClient.ServiceServer.data
data
Definition: SerialClient.py:160
rosserial_python.SerialClient.RosSerialServer.startSerialClient
def startSerialClient(self)
Definition: SerialClient.py:258
rosserial_python.SerialClient.ServiceClient.mreq
mreq
Definition: SerialClient.py:196
rosserial_python.SerialClient.SerialClient.setupSubscriber
def setupSubscriber(self, data)
Definition: SerialClient.py:582
rosserial_python.SerialClient.ServiceClient.__init__
def __init__(self, topic_info, parent)
Definition: SerialClient.py:188
rosserial_python.SerialClient.SerialClient.read_lock
read_lock
Definition: SerialClient.py:334
rosserial_python.SerialClient.Subscriber
Definition: SerialClient.py:113
rosserial_python.SerialClient.Publisher.handlePacket
def handlePacket(self, data)
Definition: SerialClient.py:106
rosserial_python.SerialClient.SerialClient.tryRead
def tryRead(self, length)
Definition: SerialClient.py:427
rosserial_python.SerialClient.ServiceServer.topic
topic
Definition: SerialClient.py:147
rosserial_python.SerialClient.Publisher.publisher
publisher
Definition: SerialClient.py:102
rosserial_python.SerialClient.ServiceClient.parent
parent
Definition: SerialClient.py:190
rosserial_python.SerialClient.SerialClient._send
def _send(self, topic, msg_bytes)
Definition: SerialClient.py:752
rosserial_python.SerialClient.RosSerialServer.socket
socket
Definition: SerialClient.py:244
rosserial_python.SerialClient.SerialClient.lastsync_success
lastsync_success
Definition: SerialClient.py:342
rosserial_python.SerialClient.SerialClient.synced
synced
Definition: SerialClient.py:346
rosserial_python.SerialClient.load_service
def load_service(package, service)
Definition: SerialClient.py:82
rosserial_python.SerialClient.Subscriber.id
id
Definition: SerialClient.py:120
rosserial_python.SerialClient.ServiceServer.__init__
def __init__(self, topic_info, parent)
Definition: SerialClient.py:146
rosserial_python.SerialClient.SerialClient.setupServiceServerPublisher
def setupServiceServerPublisher(self, data)
Definition: SerialClient.py:602
rosserial_python.SerialClient.Subscriber.unregister
def unregister(self)
Definition: SerialClient.py:137
rosserial_python.SerialClient.SerialClient.buffer_out
buffer_out
Definition: SerialClient.py:385
rosserial_python.SerialClient.ServiceClient.topic
topic
Definition: SerialClient.py:189
rosserial_python.SerialClient.SerialClient.setupServiceServerSubscriber
def setupServiceServerSubscriber(self, data)
Definition: SerialClient.py:621
rosserial_python.SerialClient.SerialClient
Definition: SerialClient.py:319
rosserial_python.SerialClient.RosSerialServer.read
def read(self, rqsted_length)
Definition: SerialClient.py:298
rosserial_python.SerialClient.RosSerialServer.flushInput
def flushInput(self)
Definition: SerialClient.py:283
rosserial_python.SerialClient.load_message
def load_message(package, message)
Definition: SerialClient.py:77
rosserial_python.SerialClient.ServiceClient.proxy
proxy
Definition: SerialClient.py:201
rosserial_python.SerialClient.SerialClient.last_read
last_read
Definition: SerialClient.py:343
rosserial_python.SerialClient.SerialClient.protocol_ver2
string protocol_ver2
Definition: SerialClient.py:328
rosserial_python.SerialClient.Publisher.message
message
Definition: SerialClient.py:100
rosserial_python.SerialClient.SerialClient.setupServiceClientPublisher
def setupServiceClientPublisher(self, data)
Definition: SerialClient.py:640
rosserial_python.SerialClient.SerialClient.handleLoggingRequest
def handleLoggingRequest(self, data)
Definition: SerialClient.py:723
rosserial_python.SerialClient.SerialClient.port
port
Definition: SerialClient.py:365
rosserial_python.SerialClient.SerialClient.txStopRequest
def txStopRequest(self)
Definition: SerialClient.py:418
rosserial_python.SerialClient.ServiceClient.mres
mres
Definition: SerialClient.py:197
rosserial_python.SerialClient.SerialClient.protocol_ver
string protocol_ver
Definition: SerialClient.py:329
rosserial_python.SerialClient.SerialClient.handleParameterRequest
def handleParameterRequest(self, data)
Definition: SerialClient.py:687
rosserial_python.SerialClient.RosSerialServer.inWaiting
def inWaiting(self)
Definition: SerialClient.py:310
rosserial_python.SerialClient.ServiceClient
Definition: SerialClient.py:183
rosserial_python.SerialClient.RosSerialServer
Definition: SerialClient.py:214
rosserial_python.SerialClient.SerialClient.header
string header
Definition: SerialClient.py:323
rosserial_python.SerialClient.SerialClient.lastsync
lastsync
Definition: SerialClient.py:340
rosserial_python.SerialClient.Publisher.topic
topic
Definition: SerialClient.py:96
rosserial_python.SerialClient.SerialClient.handleTimeRequest
def handleTimeRequest(self, data)
Definition: SerialClient.py:678
rosserial_python.SerialClient.ServiceServer
Definition: SerialClient.py:141
rosserial_python.SerialClient.Subscriber.callback
def callback(self, msg)
Definition: SerialClient.py:131
rosserial_python.SerialClient.RosSerialServer.msg
msg
Definition: SerialClient.py:299
rosserial_python.SerialClient.RosSerialServer.listen
def listen(self)
Definition: SerialClient.py:226
rosserial_python.SerialClient.SerialClient.subscribers
subscribers
Definition: SerialClient.py:350
rosserial_python.SerialClient.Subscriber.topic
topic
Definition: SerialClient.py:119
rosserial_python.SerialClient.SerialClient.callbacks
callbacks
Definition: SerialClient.py:388
rosserial_python.SerialClient.RosSerialServer.__init__
def __init__(self, tcp_portnum, fork_server=False)
Definition: SerialClient.py:221
rosserial_python.SerialClient.SerialClient.pub_diagnostics
pub_diagnostics
Definition: SerialClient.py:358
rosserial_python.SerialClient.SerialClient.requestTopics
def requestTopics(self)
Definition: SerialClient.py:406
rosserial_python.SerialClient.SerialClient.setupServiceClientSubscriber
def setupServiceClientSubscriber(self, data)
Definition: SerialClient.py:659
rosserial_python.SerialClient.SerialClient.protocol_ver1
string protocol_ver1
Definition: SerialClient.py:327
rosserial_python.SerialClient.SerialClient.fix_pyserial_for_test
fix_pyserial_for_test
Definition: SerialClient.py:347
rosserial_python.SerialClient.SerialClient._write
def _write(self, data)
Definition: SerialClient.py:744
rosserial_python.SerialClient.SerialClient.send
def send(self, topic, msg)
Definition: SerialClient.py:738
rosserial_python.SerialClient.SerialClient.setSubscribeSize
def setSubscribeSize(self, size)
Definition: SerialClient.py:564
rosserial_python.SerialClient.SerialClient.setupPublisher
def setupPublisher(self, data)
Definition: SerialClient.py:569
rosserial_python.SerialClient.SerialClient.last_write
last_write
Definition: SerialClient.py:344


rosserial_python
Author(s): Michael Ferguson
autogenerated on Wed Mar 2 2022 00:58:10