services.py
Go to the documentation of this file.
00001 # Software License Agreement (BSD License)
00002 #
00003 # Copyright (c) 2012, Willow Garage, Inc.
00004 # All rights reserved.
00005 #
00006 # Redistribution and use in source and binary forms, with or without
00007 # modification, are permitted provided that the following conditions
00008 # are met:
00009 #
00010 #  * Redistributions of source code must retain the above copyright
00011 #    notice, this list of conditions and the following disclaimer.
00012 #  * Redistributions in binary form must reproduce the above
00013 #    copyright notice, this list of conditions and the following
00014 #    disclaimer in the documentation and/or other materials provided
00015 #    with the distribution.
00016 #  * Neither the name of Willow Garage, Inc. nor the names of its
00017 #    contributors may be used to endorse or promote products derived
00018 #    from this software without specific prior written permission.
00019 #
00020 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00021 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00022 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00023 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00024 # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00025 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00026 # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00027 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00028 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00029 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00030 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00031 # POSSIBILITY OF SUCH DAMAGE.
00032 
00033 from threading import Thread
00034 from rospy import ServiceProxy
00035 from rosservice import get_service_type
00036 from rosbridge_library.internal.ros_loader import get_service_class
00037 from rosbridge_library.internal.ros_loader import get_service_request_instance
00038 from rosbridge_library.internal.message_conversion import populate_instance
00039 from rosbridge_library.internal.message_conversion import extract_values
00040 
00041 
00042 class InvalidServiceException(Exception):
00043     def __init__(self, servicename):
00044         Exception.__init__(self, "Service %s does not exist" % servicename)
00045 
00046 
00047 class ServiceCaller(Thread):
00048 
00049     def __init__(self, service, args, success_callback, error_callback):
00050         """ Create a service caller for the specified service.  Use start()
00051         to start in a separate thread or run() to run in this thread.
00052 
00053         Keyword arguments:
00054         service          -- the name of the service to call
00055         args             -- arguments to pass to the service.  Can be an
00056         ordered list, or a dict of name-value pairs.  Anything else will be
00057         treated as though no arguments were provided (which is still valid for
00058         some kinds of service)
00059         success_callback -- a callback to call with the JSON result of the
00060         service call
00061         error_callback   -- a callback to call if an error occurs.  The
00062         callback will be passed the exception that caused the failure
00063 
00064          """
00065         Thread.__init__(self)
00066         self.daemon = True
00067         self.service = service
00068         self.args = args
00069         self.success = success_callback
00070         self.error = error_callback
00071 
00072     def run(self):
00073         try:
00074             # Call the service and pass the result to the success handler
00075             self.success(call_service(self.service, self.args))
00076         except Exception as e:
00077             # On error, just pass the exception to the error handler
00078             self.error(e)
00079 
00080 
00081 def args_to_service_request_instance(service, inst, args):
00082     """ Populate a service request instance with the provided args
00083 
00084     args can be a dictionary of values, or a list, or None
00085 
00086     Propagates any exceptions that may be raised. """
00087     msg = {}
00088     if isinstance(args, list):
00089         msg = dict(zip(inst.__slots__, args))
00090     elif isinstance(args, dict):
00091         msg = args
00092 
00093     # Populate the provided instance, propagating any exceptions
00094     populate_instance(msg, inst)
00095 
00096 
00097 def call_service(service, args=None):
00098     # Given the service name, fetch the type and class of the service,
00099     # and a request instance
00100     service_type = get_service_type(service)
00101     if service_type is None:
00102         raise InvalidServiceException(service)
00103     service_class = get_service_class(service_type)
00104     inst = get_service_request_instance(service_type)
00105 
00106     # Populate the instance with the provided args
00107     args_to_service_request_instance(service, inst, args)
00108 
00109     # Call the service
00110     proxy = ServiceProxy(service, service_class)
00111     response = proxy.call(inst)
00112 
00113     # Turn the response into JSON and pass to the callback
00114     json_response = extract_values(response)
00115 
00116     return json_response


rosbridge_library
Author(s): Jonathan Mace
autogenerated on Thu Jan 2 2014 11:53:35