webserver.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 import roslib
00003 roslib.load_manifest('roswww')
00004 import rospy
00005 
00006 import socket
00007 import subprocess
00008 
00009 import tornado.ioloop
00010 import tornado.web
00011 
00012 def run(*args):
00013     '''run the provided command and return its stdout'''
00014     args = sum([(arg if type(arg) == list else [arg]) for arg in args], [])
00015     return subprocess.Popen(args, stdout=subprocess.PIPE).communicate()[0].strip()
00016 
00017 def split_words(text):
00018     '''return a list of lines where each line is a list of words'''
00019     return [line.strip().split() for line in text.split('\n')]
00020 
00021 def get_packages():
00022     ''' Find the names and locations of all packages '''
00023     lines = split_words(run('rospack', 'list'))
00024     packages = [{ 'name': name, 'path': path } for name, path in lines]
00025     return packages
00026 
00027 class MainHandler(tornado.web.RequestHandler):
00028     
00029     def initialize(self, packages):
00030         self.packages = packages
00031         
00032     def get(self):
00033         self.write("<h1>ROS web server successfully started.</h1><h3>Package List</h3>")
00034         for package in self.packages:
00035             self.write("<div style='font-size: 10px'>"+package['name']+"</div>")
00036             
00037 def create_webserver(packages):
00038     handlers = [(r"/", MainHandler, {"packages": packages})]
00039     
00040     for package in packages:
00041         handler = ("/"+package['name']+"/(.*)", tornado.web.StaticFileHandler, {"path": package['path']+"/www", "default_filename": "index.html" })
00042         handlers.append(handler)       
00043         
00044     rospy.loginfo("Webserver initialized for %d packages", len(packages))
00045     application = tornado.web.Application(handlers)
00046     
00047     return application
00048 
00049 def bind_webserver(application):    
00050     """ See if there's a default port, use 80 if not """
00051     default_port, start_port, end_port = get_webserver_params()
00052     
00053     """ First, we try the default http port 80 """
00054     bound = bind_to_port(application, default_port)
00055     
00056     if not bound:
00057         """ Otherwise bind any available port within the specified range """
00058         bound = bind_in_range(application, start_port, end_port)
00059         
00060     return bound
00061 
00062 def get_webserver_params():
00063     try:
00064         default_port = rospy.get_param("http/default", 80)
00065         start_port = rospy.get_param("http/range_start", 8000)
00066         end_port = rospy.get_param("http/range_end", 9000)
00067         return (default_port, start_port, end_port)
00068     except socket.error as err:
00069         if err.errno == 111:
00070             # Roscore isn't started or cannot be contacted
00071             rospy.logwarn("Could not contact ROS master. Is a roscore running? Error: %s", err.strerror)
00072             return 80, 8000, 9000
00073         else:
00074             raise
00075         
00076 def start_webserver(application):
00077     try: 
00078         tornado.ioloop.IOLoop.instance().start()
00079     except KeyboardInterrupt:
00080         rospy.loginfo("Webserver shutting down")    
00081 
00082 def bind_to_port(application, portno):
00083     rospy.loginfo("Attempting to start webserver on port %d", portno)
00084     try:
00085         application.listen(portno)
00086         rospy.loginfo("Webserver successfully started on port %d", portno)
00087     except socket.error as err:
00088         # Socket exceptions get handled, all other exceptions propagated
00089         if err.errno==13:
00090             rospy.logwarn("Insufficient priveliges to run webserver on port %d. Error: %s", portno, err.strerror)
00091             rospy.loginfo("-- Try re-running as super-user: sudo su; source ~/.bashrc)")
00092         elif err.errno==98:
00093             rospy.logwarn("There is already a webserver running on port %d. Error: %s", portno, err.strerror)
00094             rospy.loginfo("-- Try stopping your web server. For example, to stop apache: sudo /etc/init.d/apache2 stop")
00095         else:
00096             rospy.logerr("An error occurred attempting to listen on port %d: %s", portno, err.strerror)
00097         return False
00098     return True
00099     
00100 def bind_in_range(application, start_port, end_port):
00101     if (end_port > start_port):
00102         for i in range(start_port, end_port):
00103             if bind_to_port(application, i):
00104                 return True
00105     return False
00106 
00107 def run_webserver():
00108     try:
00109         packages = get_packages()
00110         server = create_webserver(packages)
00111         bound = bind_webserver(server)
00112         if (bound):
00113             start_webserver(server)
00114         else:
00115             raise Exception()
00116     except Exception as exc:
00117         rospy.logerr("Unable to bind webserver.  Exiting.  %s" % exc)
00118 
00119 if __name__=='__main__':
00120     run_webserver()


roswww
Author(s): Jonathan Mace
autogenerated on Thu Jan 2 2014 11:53:30