Go to the documentation of this file.00001
00002
00003 import rospy
00004 from bluetooth import *
00005 import select
00006 import base64
00007 from std_msgs.msg import String as StringMsg
00008 from glass_server.srv import RobotConfiguration
00009 from glass_server.msg import TextMessage
00010 from glass_server.msg import ImageMessage
00011 from PIL import Image
00012 import cStringIO as StringIO
00013 from threading import Lock, Event
00014 import itertools
00015 import logging
00016
00017 class GlassServer():
00018
00019 def __init__(self):
00020
00021 self._server_sock = BluetoothSocket( RFCOMM )
00022 self._server_sock.bind(("",PORT_ANY))
00023 self._server_sock.listen(1)
00024
00025 self._client_sock = None
00026 self._client_info = None
00027
00028 self._uuid = "00001101-0000-1000-8000-00805F9B34FB"
00029
00030 self._send_queue = ""
00031 self._config_success = False
00032
00033 self._robotDict = {}
00034
00035 self._lock = Lock()
00036 self._talkback_event = Event()
00037
00038
00039 self._text_sub = rospy.Subscriber("/glass_server/text_messages", TextMessage, self.textMessageCallback)
00040 self._image_sub = rospy.Subscriber("/glass_server/image_messages", ImageMessage, self.ImageMessageCallback)
00041
00042
00043 self._voice_pub = rospy.Publisher("/recognizer/output", StringMsg)
00044
00045 self.run()
00046
00047 def run(self):
00048 port = self._server_sock.getsockname()[1]
00049
00050 advertise_service( self._server_sock, "GlassServer",
00051 service_id = self._uuid,
00052 service_classes = [ self._uuid, SERIAL_PORT_CLASS ],
00053 profiles = [ SERIAL_PORT_PROFILE ],
00054
00055 )
00056
00057 rospy.loginfo("Waiting for connection on RFCOMM channel %d" % port)
00058
00059 self._client_sock, self._client_info = self._server_sock.accept()
00060 self._client_sock.setblocking(1)
00061
00062 rospy.loginfo("Accepted connection from " + str(self._client_info))
00063
00064 try:
00065
00066 self._config_srv = rospy.Service("robot_configuration", RobotConfiguration, self.robotConfig)
00067
00068 while not rospy.is_shutdown():
00069 data = ""
00070
00071
00072
00073 data = self._client_sock.recv(1024)
00074
00075 if len(data) > 0:
00076 rospy.loginfo("received: \"%s\"" % data)
00077
00078 if data == "end connection\n":
00079 break
00080 elif data == "Confirm connection\n":
00081 self._lock.acquire()
00082 self._client_sock.send("Connection confirmed\n")
00083 self._lock.release()
00084 elif data == "configuration complete\n":
00085
00086 self._config_success = True
00087 elif data == "Delivery failed":
00088 pass
00089 elif data == "_NEXT_\n":
00090 self._talkback_event.set()
00091 elif not data == "":
00092
00093
00094 msg = StringMsg()
00095 msg.data = data
00096 self._voice_pub.publish(msg)
00097 self.sendCommandToRobot(data)
00098
00099
00100 self._config_srv = None
00101 rospy.loginfo("Disconnecting")
00102 self._client_sock.close()
00103 self._server_sock.close()
00104 rospy.loginfo("all done")
00105
00106 except IOError, e:
00107 rospy.loginfo("Error")
00108 print e
00109
00110
00111 def writeToGlass(self, string_data):
00112 rospy.loginfo("Sending: " + string_data)
00113 success = False
00114 try:
00115 self._lock.acquire()
00116
00117 packetSize = 10000
00118 numPackets = len(string_data) / packetSize + (1 if (len(string_data) % packetSize > 0) else 0)
00119
00120 rospy.loginfo("Setting up header")
00121 first_msg = "<msg>" + str(numPackets) + "_DELIM_" + str(packetSize) + "</msg>"
00122
00123
00124 rospy.loginfo("Sending header")
00125 self._client_sock.send(first_msg)
00126
00127 rospy.loginfo("Creating groups")
00128 groups = self.grouper(string_data, packetSize)
00129 rospy.loginfo(groups)
00130 rospy.loginfo("Creating and sending packets")
00131 for i in range(len(groups)):
00132 msg = "<pkt><index>" + str(i+1) + "</index>" + groups[i] + "</pkt>"
00133 pkt_slack = packetSize - len(msg)
00134 msg += " " * pkt_slack
00135 rospy.loginfo("Sending")
00136 self._client_sock.send(msg)
00137 rospy.loginfo("Sent " + str(i+1) + " packets! Size=" + str(len(msg)))
00138 self._talkback_event.wait()
00139 self._talkback_event.clear()
00140
00141 rospy.loginfo("Message sent")
00142 success = True
00143 except Exception, ex:
00144 logging.exception("Error on send!")
00145 rospy.loginfo("Error on send!")
00146 finally:
00147 rospy.loginfo("Releasing write lock")
00148 self._lock.release()
00149
00150 def robotConfig(self, msg):
00151 rospy.loginfo("Recieved configuration for " + msg.name)
00152 stringToSend = "robot_configuration" + "_DELIM_" + msg.name \
00153 + "_DELIM_" + msg.info \
00154 + "_DELIM_" + msg.vocab
00155 self.writeToGlass(stringToSend)
00156 self._robotDict[msg.name] = rospy.Publisher("/" + msg.name.lower().replace(" ", "_") + "/voice_command", StringMsg)
00157 rospy.loginfo("Configuration written to Glass. Waiting for response")
00158
00159 while(not self._config_success):
00160 pass
00161 self._config_success = False
00162
00163 rospy.loginfo("Sending service response")
00164 return True
00165
00166 def sendCommandToRobot(self, data):
00167 splitData = data.split(":")
00168 targetRobot = splitData[0]
00169 command = splitData[1][1:]
00170
00171 if targetRobot == "All":
00172 for (robot_name, publisher) in self._robotDict.iteritems():
00173 msg = StringMsg()
00174 msg.data = command
00175 publisher.publish(msg)
00176 else:
00177 publisher = self._robotDict[targetRobot]
00178 msg = StringMsg()
00179 msg.data = command
00180 publisher.publish(msg)
00181
00182 def textMessageCallback(self, msg):
00183 rospy.loginfo("Recieved text message from " + msg.sender)
00184 stringToSend = "text_message" + "_DELIM_" + msg.sender \
00185 + "_DELIM_" + msg.text \
00186 + "_DELIM_" + str(msg.priority)
00187 self.writeToGlass(stringToSend)
00188
00189 def ImageMessageCallback(self, msg):
00190 rospy.loginfo("Received image message from " + msg.sender)
00191
00192 image_str = msg.base64_image
00193 image_raw = base64.b64decode(image_str)
00194 stream = StringIO.StringIO(image_raw)
00195 image = Image.open(stream)
00196 width, height = image.size
00197 if width > height:
00198 newW = 100
00199 newH = newW * height / width
00200 else:
00201 newH = 100
00202 newW = newH * width / height
00203 newSize = newW, newH
00204 image = image.resize(newSize)
00205
00206 image_stream = StringIO.StringIO()
00207 image.save(image_stream, format="JPEG")
00208 image_str = base64.b64encode(image_stream.read())
00209
00210 stringToSend = "image_message" + "_DELIM_" + msg.sender \
00211 + "_DELIM_" + msg.text \
00212 + "_DELIM_" + msg.base64_image \
00213 + "_DELIM_" + str(msg.priority)
00214 self.writeToGlass(stringToSend)
00215
00216 def grouper(self, seq, size):
00217 return [seq[pos:pos + size] for pos in range(0, len(seq), size)]
00218
00219
00220 if __name__ == '__main__':
00221 try:
00222 rospy.init_node('glass_server')
00223 rospy.loginfo("Node Initialized")
00224 instance = GlassServer()
00225 except rospy.ROSInterruptException:
00226 pass