3 usage: %(progname)s [--debug] 41 import roslib; roslib.load_manifest(PKG_NAME)
56 import BaseHTTPServer, select, socket, SocketServer, urlparse
57 SocketServer.ThreadingMixIn.daemon_threads =
True 62 import roslib.scriptutil
67 from rosservice
import ROSServiceException
68 from genpy.message
import MessageException
69 from roslib
import rosenv
77 parts = topic.split(
":", 2)
85 return topic, subtopic, params
92 self.
lock = threading.Lock()
97 self.
cond = threading.Condition()
102 for topic
in self.map.keys():
103 rwt = self.
map[topic]
113 if topic
in self.
map:
119 maintopic, subtopic, params =
splitTopic(topic)
123 if topic
in self.
map:
124 return self.
map[topic]
126 self.
map[maintopic] = main_rwt
129 handlerClass = self.webserver._subtopics[
"%s:%s" % (maintopic, subtopic)]
130 rwt = handlerClass(topic, self, main_rwt)
131 self.
map[topic] = rwt
137 return self.map.get(topic,
None)
164 self.factory.cond.acquire()
165 m = roslib.scriptutil.get_master()
167 code, _, topics = m.getPublishedTopics(
'/'+PKG_NAME,
'/')
171 for t, topic_type
in topics:
172 if t == self.
topic:
break 176 msg_class = roslib.message.get_message_class(topic_type)
182 print self.
topic, msg_class
185 except ROSWebException:
189 rospy.signal_shutdown(str(e))
192 self.factory.cond.release()
201 self.factory.cond.acquire()
203 self.messages.append((self.factory.counter, data))
204 self.factory.counter = self.factory.counter + 1
208 rwt.subtopic_callback(data)
210 self.factory.cond.notifyAll()
212 self.factory.cond.release()
215 self.subtopics.append((rwt, subtopic))
224 self.maintopic, self.subtopic, params =
splitTopic(topic)
225 main_rwt.subscribeSubTopic(self, self.subtopic)
233 newmsg = self.transform(msg)
235 if not newmsg:
return 237 self.messages.append((self.factory.counter, newmsg))
238 self.factory.counter = self.factory.counter + 1
239 self.messages = self.messages[-1:]
245 def __init__(self, topic, factory, thread, intopics=[]):
258 self.factory.subscribe(_topic)
261 self.thread.setCallback(self.
callback)
266 self.factory.cond.acquire()
268 self.messages.append((self.factory.counter, data))
269 self.factory.counter = self.factory.counter + 1
272 self.factory.cond.notifyAll()
274 self.factory.cond.release()
280 BaseHTTPServer.BaseHTTPRequestHandler.__init__(self, *args)
283 rwt = self.server.factory.subscribe(topic)
286 except ROSWebException, e:
287 self.server.factory.unsubscribe(topic)
289 rospy.logwarn(
"Cannot subscribe to %s" % topic)
290 self.failed_topics.append(topic)
299 rwt = self.server.factory.get(topic)
301 rwttopics.append((topic, rwt))
304 if rwt: rwttopics.append((topic, rwt))
306 if len(rwttopics) == 0:
307 rospy.logwarn(
"no valid topics")
311 (messages, lastSince) = self.
_get_messages(rwttopics, since, nowait)
313 buf = cStringIO.StringIO()
315 buf.write(
'"since": %s,' % lastSince)
316 buf.write(
'"msgs": [')
318 for (topic, msg)
in messages:
320 if _i > 1: buf.write(
',')
322 buf.write(
'"topic": "%s",' % topic)
338 self.server.factory.cond.acquire()
341 if since > self.server.factory.counter:
343 rospy.logerr(
"invalid since counter, reseting... %s" % (since, ))
348 for topic, rwt
in rwttopics:
350 for t,msg
in rwt.messages:
352 messages.append((topic, msg))
353 lastSince = max(t, lastSince)
357 return messages, lastSince
361 self.server.factory.cond.wait()
364 for topic, rwt
in rwttopics:
366 for t,msg
in rwt.messages:
368 messages.append((topic, msg))
369 lastSince = max(t, lastSince)
371 self.server.factory.cond.release()
372 return (messages, lastSince)
378 host_port = netloc[:i], int(netloc[i+1:])
380 host_port = netloc, 80
382 try: soc.connect(host_port)
383 except socket.error, arg:
387 self.send_error(404, msg)
393 self.send_response(retcode)
396 buf = callback +
"=" + buf +
";\nvar _xsajax$transport_status=200;" 397 self.send_header(
'Content-Type',
'text/javascript')
399 self.send_header(
'Content-Type',
'application/json')
402 acceptEncoding = self.headers.get(
'Accept-Encoding',
'')
403 if acceptEncoding.find(
'gzip') != -1:
404 zbuf = cStringIO.StringIO()
405 zfile = gzip.GzipFile(
None,
"wb", 9, zbuf)
410 buf = zbuf.getvalue()
411 self.send_header(
'Content-encoding',
'gzip')
413 self.send_header(
'Content-Length', str(len(buf)))
415 if self.headers.get(
"Connection",
'').lower() ==
"keep-alive":
416 self.send_header(
'Connection',
'keep-alive')
418 self.send_header(
"Access-Control-Allow-Origin",
"*")
423 self.wfile.write(buf)
424 except socket.error, (ecode, reason):
441 host, port = self.client_address[:2]
445 cstring = self.headers.get(
'Cookie',
'')
447 cookie = Cookie.BaseCookie()
450 path_parts = path.split(
"/")
457 if cookie.has_key(
'MB_L1'):
458 l1 = cookie[
'MB_L1'].value
459 if l1.startswith(
"V1/"):
461 parts = code.split(
":", 1)
473 name =
"/".join(path_parts[3:])
474 callback = qdict.get(
"callback", [
''])[0]
477 service_class = rosservice.get_service_class_by_name(
"/" + name)
478 except ROSServiceException:
482 request = service_class._request_class()
484 args = qdict.get(
'args',
None)
486 args = qdict.get(
'json', [
'{}'])[0]
489 now = rospy.get_rostime()
490 keys = {
'now': now,
'auto': rospy.Header(stamp=now) }
491 roslib.message.fill_message_args(request, args, keys=keys)
492 except MessageException:
493 raise ROSServiceException(
"Not enough arguments to call service.\n"+\
494 "Args should be: [%s], but are actually [%s] " %
495 (roslib.message.get_printable_message_args(request), args))
497 rospy.logdebug(
"service call: name=%s, args=%s" % (name, args))
498 rospy.wait_for_service(name)
499 service_proxy = rospy.ServiceProxy(name, service_class)
501 msg = service_proxy(request)
502 except rospy.ServiceException:
507 rospy.logdebug(
"service call: name=%s, resp=%s" % (name, msg))
512 topic = string.join(path_parts[3:],
"/")
514 callback = qdict.get(
"callback", [
''])[0]
515 topic_type = qdict.get(
"topic_type", [
''])[0]
517 message_klass = roslib.message.get_message_class(topic_type)
519 message = message_klass()
521 args = qdict.get(
'args',
None)
523 args = qdict.get(
'json', [
'{}'])[0]
526 now = rospy.get_rostime()
527 keys = {
'now': now,
'auto': rospy.Header(stamp=now) }
528 roslib.message.fill_message_args(message, args, keys=keys)
529 except MessageException:
530 raise ROSServiceException(
"Not enough arguments to call service.\n"+\
531 "Args should be: [%s], but are actually [%s] " %
532 (roslib.message.get_printable_message_args(message), args))
534 rospy.logdebug(
"publish: topic=%s, topic_type=%s, args=%s" % (topic, topic_type, args))
536 pub = rospy.Publisher(topic, message_klass, latch=
True)
540 except rospy.ServiceException:
548 since = int(qdict.get(
'since', [
'0'])[0])
549 topics = qdict.get(
"topic",
"")
550 callback = qdict.get(
"callback", [
''])[0]
551 nowait = int(qdict.get(
'nowait', [
'0'])[0])
552 self.
_do_GET_topic(topics, since, nowait=nowait, callback=callback)
560 stored_cookie = open(
"/var/ros/user_cookie.dat").read()
561 request_cookie = self.headers.get(
'Cookie',
'')
562 if stored_cookie.find(request_cookie) == -1:
563 rospy.logwarn(
"cookie did not match stored cookie \n%s\n%s" % (stored_cookie, request_cookie))
570 (scm, netloc, path, params, query, fragment) = urlparse.urlparse(
572 qdict = cgi.parse_qs(query)
573 pdict = cgi.parse_qs(str(self.rfile._rbuf))
578 for handler
in self.server._handlers:
579 if path.startswith(handler[
'url']):
580 handler[
'handler'](self, path, qdict)
583 netloc =
"localhost:80" 586 soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
589 soc.send(
"%s %s %s\r\n" % (
591 urlparse.urlunparse((
'',
'', path, params, query,
'')),
592 self.request_version))
593 self.headers[
'Connection'] =
'close' 594 del self.headers[
'Proxy-Connection']
595 for key_val
in self.headers.items():
596 soc.send(
"%s: %s\r\n" % key_val)
601 self.connection.close()
605 iw = (self.connection, soc)
611 (ins, _, exs) = select.select(iw, ow, iw, 3)
616 out = self.connection
617 elif i
is self.connection:
624 while bytes_sent != len(data):
625 n = out.send(data[bytes_sent:])
630 if count == max_idling:
break 636 self.server.accesslog_fp.write(
"%s - - [%s] %s\n" %
638 self.log_date_time_string(),
640 self.server.accesslog_fp.flush()
646 master = roslib.scriptutil.get_master()
649 master.getSystemState(
'/rostopic')
657 SocketServer.ThreadingMixIn,
658 BaseHTTPServer.HTTPServer):
660 threading.Thread.__init__(self)
661 SocketServer.TCPServer.__init__(self, hostport, handlerClass)
665 logfn = os.path.join(rosenv.get_log_dir(),
"access_log")
677 h = {
'url': urlprefix,
'handler': handler}
678 self._handlers.append(h)
684 plugins = roslib.rospack.rospack_plugins(PKG_NAME)
685 for (package, plugin)
in plugins:
687 roslib.load_manifest(package)
688 mods = plugin.split(
'.')
689 mod = __import__(plugin)
690 for sub_mod
in mods[1:]:
691 mod = getattr(mod, sub_mod)
693 mod.config_plugin(self)
695 except Exception, reason:
696 rospy.logerr(
"plugin %s got exception %s" % (plugin, reason))
703 self.factory.registerVirtualTopic(
"/topics", ut)
708 self.factory.registerVirtualTopic(
"/parameters", ut)
712 self.handle_request()
719 rospy.init_node(PKG_NAME, disable_signals=
True)
723 web_server.setDaemon(
True)
725 rospy.loginfo(
"starting Web server")
731 rospy.signal_shutdown(PKG_NAME +
' exiting')
732 if web_server: web_server.server_close()
741 print __doc__ % vars()
746 return open(os.path.join(
"/etc/ros/env",
"ROBOT")).read().strip()
750 def main(argv, stdout, environ):
752 optlist, args = getopt.getopt(argv[1:],
"", [
"help",
"debug"])
755 for (field, val)
in optlist:
756 if field ==
"--help":
759 elif field ==
"--debug":
762 global running, error_log
770 signal.signal(signal.SIGINT, signal_handler)
774 rospy.loginfo(
"starting")
779 traceback.print_exc()
782 if error_log_fp: error_log_fp.close()
784 if __name__ ==
'__main__':
785 main(sys.argv, sys.stdout, os.environ)
def _do_GET_topic(self, topics, since, nowait=False, callback=None)
def __registerVirtualTopics(self)
def subtopic_callback(self, msg)
def subscribeSubTopic(self, rwt, subtopic)
def _send_responsepage(self, retcode=200, buf="{}", callback=None)
def __init__(self, hostport, handlerClass)
def topic_callback(self, data)
def main(argv, stdout, environ)
def ros_message_to_json(msg)
def send_forbidden(self, buf="{}", callback=None)
def unsubscribe(self, topic)
def registerVirtualTopic(self, topic, thread)
Factory for ROSWebTopic instances.
def _connect_to(self, netloc, soc)
def register_subtopic(self, topic, handlerClass)
def __init__(self, webserver)
def _read_write(self, soc, max_idling=20)
def register_handler(self, urlprefix, handler)
def __init__(self, topic, factory)
def __init__(self, topic, factory, main_rwt)
def _get_messages(self, rwttopics, since, nowait=False)
def handle_ROS(self, path, qdict)
def log_message(self, format, args)
def __init__(self, topic, factory, thread, intopics=[])
def signal_handler(signal, frame)
messages
no locks needed since this will be called from the main topic
def send_failure(self, buf="{}", callback=None)
def subscribe(self, topic)
def subscribe(self, topic)
def send_success(self, buf="{}", callback=None)