Go to the documentation of this file.00001
00002
00003
00004 from StringIO import StringIO
00005
00006 import rospy
00007
00008 import sqlalchemy
00009 from sqlalchemy.types import Integer, Binary
00010
00011 from abstract_db_interface import AbstractDBInterface
00012
00013 class DBInterface(AbstractDBInterface):
00014 @property
00015 def interface_type(self):
00016 return "serialization"
00017
00018 def getter_callback(self, msg):
00019 """Execute the getter service and return the response"""
00020
00021 response = self.getter_service_class._response_class()
00022
00023
00024 id_ = msg.id
00025 query = self.table.select(whereclause=(self.table.c.id == id_))
00026 connection = self.engine.connect()
00027 with connection.begin():
00028 result = connection.execute(query).fetchone()
00029 connection.close()
00030 if not result:
00031 err = 'No element with id {} in database table {}'.format(
00032 id_, self.table.name)
00033 rospy.logerr(err)
00034 raise ValueError(err)
00035
00036 response.deserialize(result['serialized_content'])
00037 return response
00038
00039 def setter_callback(self, msg):
00040 """Execute the setter service and return the reponse"""
00041 buf = StringIO()
00042 msg.serialize(buf)
00043
00044
00045 insert_args = {'serialized_content': buf.getvalue()}
00046 connection = self.engine.connect()
00047 with connection.begin():
00048 result = connection.execute(self.table.insert(), insert_args)
00049 connection.close()
00050 return_id = result.inserted_primary_key[0]
00051
00052
00053 response = self.setter_service_class._response_class()
00054 response.id = return_id
00055 self._set_timestamp(rospy.Time.now())
00056 return response
00057
00058 def _generate_schema(self):
00059 """Generate schema from response class
00060
00061 Recusrively generate tables for the type of the 'descriptor' variable
00062 in the response class.
00063 """
00064
00065 self._add_interface_description()
00066
00067 column_id = sqlalchemy.Column('id', Integer,
00068 primary_key=True,
00069 nullable=False)
00070 column_content = sqlalchemy.Column('serialized_content', Binary)
00071 self.table = sqlalchemy.Table(self.interface_name,
00072 self.metadata,
00073 column_id,
00074 column_content,
00075 extend_existing=True)
00076
00077
00078 self.metadata.create_all()
00079
00080
00081 def interface_factory(interface_name, getter_srv_msg, setter_srv_msg):
00082 """generate the interface class and run the getter and setter services
00083
00084 Example of call: interface_factory('laser_descriptor',
00085 'lama_interface/get_laser_descriptor',
00086 'lama_interface/set_laser_descriptor').
00087
00088 Parameters
00089 ----------
00090 - interface_name: str, uniquely identifies an interface between jockeys
00091 and the database.
00092 - getter_srv_msg: str, identifies the service message used when retrieving
00093 a descriptor from the database. For example
00094 'lama_interfaces/GetVectorLaserScan'.
00095 Service definition must be in form:
00096 int32 id
00097 ---
00098 * descriptor
00099 - setter_srv_msg: str, identifies the service message used when adding
00100 a descriptor to the database. For example
00101 'lama_interfaces/SetVectorLaserScan'.
00102 Service definition must be in form:
00103 * descriptor
00104 ---
00105 int32 id
00106
00107 This function should be called only once with each parameter set because
00108 it starts ROS services and an error is raised if services are started
00109 twice.
00110 """
00111 if getter_srv_msg.endswith('.srv'):
00112 getter_srv_msg = getter_srv_msg[:-4]
00113 if setter_srv_msg.endswith('.srv'):
00114 setter_srv_msg = setter_srv_msg[:-4]
00115 iface = DBInterface(interface_name, getter_srv_msg, setter_srv_msg,
00116 start=True)
00117 return iface