class LisaClient(LineReceiver): """ Lisa TCP client """ def __init__(self): self.factory = None self.configuration = ConfigManagerSingleton.get().getConfiguration() self.listener = None self.debug_input = False self.debug_output = False if self.configuration.has_key("debug"): if self.configuration["debug"].has_key("debug_input"): self.debug_input = self.configuration["debug"]["debug_input"] if self.configuration["debug"].has_key("debug_output"): self.debug_output = self.configuration["debug"]["debug_output"] self.zone = "" if self.configuration.has_key("zone"): self.zone = self.configuration["zone"] def sendMessage(self, message, type="chat", dict=None): if dict: line = json.dumps( { "from": unicode(platform.node()), "type": type, "body": unicode(message), "zone": self.zone, "outcome": dict, } ) else: line = json.dumps( {"from": unicode(platform.node()), "type": type, "body": unicode(message), "zone": self.zone} ) if self.debug_output: log.msg("OUTPUT: %s" % line) # send line to the server self.sendLine(line) def lineReceived(self, data): """ Data received callback The nolistener in configuration is here to let the travis build pass without loading gst """ datajson = json.loads(data) if self.debug_input == True: log.msg("INPUT: " + unicode(datajson)) if datajson.has_key("type"): if datajson["type"] == "chat": if datajson.has_key("nolistener") == False: Speaker.speak(datajson["body"]) elif datajson["type"] == "command": if datajson["command"] == "LOGIN": # Get Bot name botname = unicode(datajson["bot_name"]) log.msg("setting botname to %s" % botname) self.botname = botname # Send TTS if datajson.has_key("nolistener") == False: Speaker.start() Speaker.speak(datajson["body"]) # Create listener if datajson.has_key("nolistener") == False and not self.listener: self.listener = Listener(lisa_client=self, botname=botname) # TODO seems a bit more complicated than I thought. I think the reply will be another type like "answer" # TODO and will contains a unique ID. On server side, the question will be stored in mongodb so it will # TODO let possible the multi user / multi client. Questions need to implement a lifetime too. # TODO For the soundqueue, I will need a callback system to be sure to play the audio before recording elif datajson["command"] == "ASK": if datajson.has_key("nolistener") == False: Speaker.speak(datajson["body"]) # Start record if datajson.has_key("nolistener") == False and self.listener: self.listener.record() else: # Send to TTS queue if datajson.has_key("nolistener") == False: Speaker.speak(datajson["body"]) def connectionMade(self): """ Callback on established connections """ log.msg("Connected to the server.") # Set SSL encryption if self.configuration.has_key("enable_secure_mode") and self.configuration["enable_secure_mode"] == True: ctx = ClientTLSContext() self.transport.startTLS(ctx, self.factory) # Login to server self.sendMessage(message="LOGIN", type="command") def connectionLost(self, reason): """ Callback on connection loss """ # Stop listener log.msg("Lost connection with server : " + reason.getErrorMessage()) if self.listener: self.listener.stop()
class LisaClientFactory(ReconnectingClientFactory): #----------------------------------------------------------------------------- def __init__(self): self.configuration = ConfigManager.getConfiguration() self._ = self.configuration['trans'] self.active_protocol = None self.warn_on_connect = False self.running_state = True self.listener = None #----------------------------------------------------------------------------- def startFactory(self): # Create workers if self.listener is None: self.listener = Listener(factory = self) Speaker.start(listener = self.listener) #----------------------------------------------------------------------------- def setBotName(self, botname): # Restart listener with new botname self.listener.setBotName(botname) #----------------------------------------------------------------------------- def sendChatToServer(self, message, outcome = None): # If not connected to the server if self.active_protocol is None: Speaker.speak(self._('no_server')) self.warn_on_connect = True return # Send chat to server self.active_protocol.sendChatToServer(message = message, outcome = outcome) #----------------------------------------------------------------------------- def setContinuousMode(self, enabled, wit_context = None): # Change continuous mode in recorder self.listener.setContinuousMode(enabled = enabled, wit_context = wit_context) #----------------------------------------------------------------------------- def buildProtocol(self, addr): # Reset retry delay self.resetDelay() # Warn on connection if self.warn_on_connect == True: Speaker.speak(self._('back_ready')) self.warn_on_connect = False # Return protocol self.active_protocol = LisaClient(factory = self) return self.active_protocol #----------------------------------------------------------------------------- def clientConnectionLost(self, connector, reason): # Delete current connection self.active_protocol = None # Retry connection to the server log.err('Lost connection. Reason: {0}'.format(reason.getErrorMessage())) if self.running_state == True: ReconnectingClientFactory.clientConnectionLost(self, connector, reason) #----------------------------------------------------------------------------- def clientConnectionFailed(self, connector, reason): # Retry self.resetDelay() log.err('Connection failed. Reason: {0}'.format(reason.getErrorMessage())) if self.running_state == True: ReconnectingClientFactory.clientConnectionFailed(self, connector, reason) #----------------------------------------------------------------------------- def stop(self): # Stop workers self.running_state = False self.listener.stop() self.listener = None Speaker.stop()