Module Robot
[hide private]
[frames] | no frames]

Source Code for Module Robot

  1  # Robot.py 
  2  # Remote mode 
  3  # TigerJython version 
  4   
  5   
  6  import socket, sys, time 
  7  from threading import Thread, Lock 
  8  from Tools import * 
  9  from SensorThread import SensorThread 
 10  from RobotInstance import RobotInstance 
 11  from ch.aplu.raspi import * 
 12  import thread 
 13   
 14   
15 -class RaspiException(Exception):
16 pass
17
18 -def onClose():
19 robot = RobotInstance.getRobot() 20 if robot == None: 21 return 22 robot.exit()
23
24 -class KeyListener(ButtonKeyListener):
25 - def buttonPressed(self, keyCode):
26 robot = RobotInstance.getRobot() 27 if robot == None: 28 return 29 if keyCode == 27: # ESCAPE 30 robot.escapeHit = True 31 if robot._buttonEvent != None: 32 robot._buttonEvent(SharedConstants.BUTTON_PRESSED) 33 elif keyCode == 10: # ENTER 34 robot.enterHit = True 35 elif keyCode == 37: # CURSOR_LEFT 36 robot.leftHit = True 37 elif keyCode == 38: # CURSOR_UP 38 robot.upHit = True 39 elif keyCode == 39: # CURSOR_RIGHT 40 robot.rightHit = True 41 elif keyCode == 40: # CURSOR_DOWN 42 robot.downHit = True
43
44 - def buttonReleased(self, keyCode):
45 robot = RobotInstance.getRobot() 46 if robot == None: 47 return 48 if keyCode == 27: # ESCAPE 49 if robot._buttonEvent != None: 50 robot._buttonEvent(SharedConstants.BUTTON_RELEASED)
51
52 - def buttonLongPressed(self, keyCode):
53 robot = RobotInstance.getRobot() 54 if robot == None: 55 return 56 if keyCode == 27: # ESCAPE 57 if robot._buttonEvent != None: 58 robot._buttonEvent(SharedConstants.BUTTON_LONGPRESSED)
59 60 61 # -------------------------------- global constants ------------------------- 62 receiverTimeout = 10 63 64 # -------------------------------- class Response ---------------------------
65 -class Response():
66 OK = "0" 67 SEND_FAILED = "-1" 68 ILLEGAL_METHOD = "-2" 69 ILLEGAL_INSTANCE = "-3" 70 CMD_ERROR = "-4" 71 ILLEGAL_PORT = "-5" 72 CREATION_FAILED = "-6"
73 74 # -------------------------------- class Receiver ---------------------------
75 -class Receiver(Thread):
76 - def __init__(self, robot):
77 Thread.__init__(self) 78 self.robot = robot
79
80 - def run(self):
81 Tools.debug("Receiver thread started") 82 while self.robot.isReceiverRunning: 83 try: 84 self.robot.isReceiverUp = True 85 self.robot.receiverResponse = self.readResponse() 86 except: 87 Tools.debug("Exception in Receiver.run()") 88 self.robot.isReceiverRunning = False 89 self.robot.closeConnection() 90 Tools.debug("Receiver thread terminated")
91
92 - def readResponse(self):
93 Tools.debug("Calling readResponse") 94 bufSize = 4096 95 data = "" 96 while (not self.robot.isBinaryReply and not "\n" == data[-1:]) or \ 97 (self.robot.isBinaryReply and not "\xff\xd9\n" in data[-3:]): 98 # eof tag for jpeg files and the added \n, 99 # we are not sure 100% that this sequence is never embedded in image 100 # but it is very improbable to fit the last three bytes of the 4096 size block 101 try: 102 reply = self.robot.sock.recv(bufSize) 103 except: 104 raise Exception("Exception from blocking sock.recv()") 105 data += reply 106 if not self.robot.isBinaryReply: 107 data = data.decode("UTF-8") 108 data = data[:-1] # Remove trailing \n 109 self.robot.isBinaryReply = False 110 return data
111 112 # ------------------------ Class Robot -------------------------------------------------
113 -class Robot(object):
114 ''' 115 Class that creates or returns a single MyRobot instance. 116 '''
117 - def __new__(cls, ipAddress = "", buttonEvent = None):
118 if RobotInstance.getRobot() == None: 119 r = MyRobot(ipAddress, buttonEvent) 120 RobotInstance.setRobot(r) 121 for parts in RobotInstance._partsToRegister: 122 parts._setup(r) 123 return r 124 else: 125 return RobotInstance.getRobot()
126 127 # -------------------------------- class Robot --------------------------
128 -class MyRobot():
129 _myInstance = None
130 - def __init__(self, ipAddress = "", buttonEvent = None):
131 if MyRobot._myInstance != None: 132 raise Exception("Only one instance of MyRobot allowed") 133 134 self.panel = ConnectPanel.create() 135 if ipAddress == "": 136 ipAddress_port = self.panel.askIPAddress() 137 if ipAddress_port == "": 138 raise RaspiException("No IP address given.") 139 else: 140 ipAddress_port = ipAddress 141 ipList = ipAddress_port.split(":") 142 self.ipAddress = ipList[0] 143 if len(ipList) == 2: 144 self.port = int(ipList[1]) 145 else: 146 self.port = SharedConstants.PORT 147 self.isBinaryReply = False 148 self.isReceiverUp = False 149 self.isReceiverRunning = False 150 self.isExited = False 151 self.buttonHit = False 152 self.escapeHit = False 153 self.enterHit = False 154 self.upHit = False 155 self.downHit = False 156 self.leftHit = False 157 self.rightHit = False 158 self.sensorThread = None 159 self._buttonEvent = buttonEvent 160 self.isConn = False 161 self.lock = Lock() 162 self.panel.show() 163 self.panel.addCloseListener(onClose) 164 self.panel.addButtonKeyListener(KeyListener()) 165 msg = "Connecting to " + self.ipAddress + ":" + str(self.port) + "..." 166 print msg, 167 self.panel.setText(msg) 168 if self.connect(): 169 print "Connection established." 170 self.panel.showConnect(self.ipAddress + ":" + str(self.port)) 171 Tools.delay(4000) # wait until "Conn" timed message has finished 172 else: 173 self.panel.showFail(self.ipAddress, self.port) 174 raise RaspiException("Connection failed.") 175 MyRobot._myInstance = self 176 Tools.delay(2000)
177
178 - def registerSensor(self, sensor):
179 if self.sensorThread == None: 180 self.sensorThread = SensorThread() 181 self.sensorThread.start() 182 self.sensorThread.add(sensor)
183
184 - def startReceiver(self):
185 Tools.debug("Starting Receiver thread") 186 self.isReceiverRunning = True 187 receiver = Receiver(self) 188 receiver.start() 189 while not self.isReceiverUp: 190 time.sleep(0.001) 191 time.sleep(0.1)
192
193 - def sendCommand(self, cmd):
194 self.lock.acquire() 195 Tools.debug("sendCommand() with cmd = " + cmd) 196 if not self.isConn: 197 raise RaspiException("Exception in Robot: sendCommand)() failed (Connection closed).") 198 return Response.SEND_FAILED 199 try: 200 self.receiverResponse = None 201 cmd += "\n"; # Append \n 202 self.sock.sendall(cmd) 203 reply = self.waitForReply() # Throws exception if timeout 204 self.lock.release() 205 return reply 206 except: 207 Tools.debug("Exception in sendCommand(): " + str(sys.exc_info()[1])) 208 self.closeConnection() 209 210 Tools.debug("Not connected. Returned: SEND_FAILED") 211 self.lock.release() 212 return Response.SEND_FAILED
213
214 - def waitForReply(self):
215 Tools.debug("Calling waitForReply") 216 startTime = time.clock() 217 while self.isConn and self.receiverResponse == None and time.clock() - startTime < receiverTimeout: 218 time.sleep(0.01) 219 if self.receiverResponse == None: 220 raise RaspiException("Exception in Robot: waitForReply failed.") 221 Tools.debug("Response = " + self.receiverResponse) 222 return self.receiverResponse
223
224 - def closeConnection(self):
225 if not self.isConn: 226 return 227 self.isConn = False 228 Tools.debug("Closing socket") 229 self.sock.shutdown(socket.SHUT_WR) 230 self.sock.close()
231
232 - def connect(self):
233 self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 234 try: 235 self.sock.connect((self.ipAddress, self.port)) 236 self.isConn = True 237 except Exception, err: 238 # print Exception, err 239 Tools.debug("Connection failed.") 240 return False 241 self.startReceiver() 242 return True
243
244 - def exit(self):
245 if self.isExited: 246 return 247 if self.sensorThread != None: 248 self.sensorThread.stop() 249 self.sensorThread.join(2000) 250 self.isExited = True 251 self.closeConnection() 252 self.escapeHit = True # Take it out of isEscapeHit() 253 self.buttonHit = True # Take it out of isButtonHit() 254 msg = "Connection closed." 255 print msg 256 self.panel.setText(msg) 257 Tools.delay(5000) 258 self.panel.dispose()
259
260 - def isConnected(self):
261 Tools.delay(1) 262 return self.isConn
263
264 - def getVersion(self):
265 return self.sendCommand("robot.getVersion")
266
267 - def getIPAddresses(self):
268 return self.sendCommand("robot.getIPAddresses")
269
270 - def getCurrentDevices(self):
271 return self.sendCommand("robot.getCurrentDevices")
272
273 - def setSoundVolume(self, volume):
274 return self.sendCommand("robot.setSoundVolume." + str(volume))
275
276 - def playTone(self, frequency, duration):
277 return self.sendCommand("robot.playTone." + str(int(frequency + 0.5)) + "." + str(int(duration + 0.5)))
278
279 - def initSound(self, soundFile, volume):
280 return self.sendCommand("robot.initSound." + soundFile + "." + str(int(volume)))
281
282 - def playSound(self):
283 return self.sendCommand("robot.playSound")
284
285 - def stopSound(self):
286 return self.sendCommand("robot.stopSound")
287
288 - def fadeooutSound(self, time):
289 return self.sendCommand("robot.fadeoutSound." + str(int(time)))
290
291 - def playSound(self):
292 return self.sendCommand("robot.playSound")
293
294 - def pauseSound(self):
295 return self.sendCommand("robot.pauseSound")
296
297 - def resumeSound(self):
298 return self.sendCommand("robot.resumeSound")
299
300 - def rewindSound(self):
301 return self.sendCommand("robot.rewindSound")
302
303 - def isSoundPlaying(self):
304 rc = self.sendCommand("robot.isSoundPlaying") 305 if rc == "1": 306 return True 307 return False
308
309 - def isButtonHit(self):
310 Tools.delay(1) 311 if self.buttonHit: 312 self.buttonHit = False 313 return True 314 rc = self.sendCommand("robot.isButtonHit") 315 if rc == "1": 316 return True 317 return False
318
319 - def isEscapeHit(self):
320 Tools.delay(1) 321 if self.escapeHit: 322 self.escapeHit = False 323 return True 324 return False
325
326 - def isEnterHit(self):
327 Tools.delay(1) 328 if self.enterHit: 329 self.enterHit = False 330 return True 331 return False
332
333 - def isUpHit(self):
334 Tools.delay(1) 335 if self.upHit: 336 self.upHit = False 337 return True 338 return False
339
340 - def isDownHit(self):
341 Tools.delay(1) 342 if self.downHit: 343 self.downHit = False 344 return True 345 return False
346
347 - def isLeftHit(self):
348 Tools.delay(1) 349 if self.leftHit: 350 self.leftHit = False 351 return True 352 return False
353
354 - def isRightHit(self):
355 Tools.delay(1) 356 if self.rightHit: 357 self.rightHit = False 358 return True 359 return False
360
361 - def addButtonListener(self, listener):
362 self._buttonEvent = listener
363