Beispiel #1
0
    def __init__(self):
        self.running = False
        self.news = NewsReader()
        self.thread_queue = Queue()
        self.voice_parser = VoiceInputParser(self)
        self.clap_detector = ClapDetector(self.thread_queue)
        self.cur_speech_process = None
        self.speech_q = Queue()
        self.last_update = datetime.now()
        self.alarms = []
        self.alarm_tones = []
        self.alarm_index = 0
        self.cur_alarm_process = None
        self.state = States.Idle

        self.weather = Weather()
Beispiel #2
0
class Bot():
    def __init__(self):
        self.running = False
        self.news = NewsReader()
        self.thread_queue = Queue()
        self.voice_parser = VoiceInputParser(self)
        self.clap_detector = ClapDetector(self.thread_queue)
        self.cur_speech_process = None
        self.speech_q = Queue()
        self.last_update = datetime.now()
        self.alarms = []
        self.alarm_tones = []
        self.alarm_index = 0
        self.cur_alarm_process = None
        self.state = States.Idle

        self.weather = Weather()

    """
    Runs the robot state machine
    """

    def run(self):
        self.running = True

        # create thread to listen for voice input
        # self.voice_parser.start()
        try:
            while (self.running):
                if self.state == States.Idle:
                    """
                    Idle state
                    """
                    if not self.clap_detector.running():
                        self.clap_detector.start()
                    self.check_clap()

                elif self.state == States.Speaking:
                    """
                    Speaking state
                    """
                    if not self.clap_detector.running():
                        self.clap_detector.start()
                    self.check_clap()
                    if not self.speech_q.empty():
                        self.speak(self.speech_q.get())
                    else:
                        self.state = States.Idle
                else:
                    pass

                # check for alarms
                for time in self.alarms:
                    self.check_alarm(time)

        except (Exception, KeyboardInterrupt, SystemExit) as e:
            print "\rExiting main"
            traceback.print_exc()
            self.clap_detector.stop()
            sys.exit(0)

    """
    Check the thread queue for clap detection
    If clapped, receive a new command
    """

    def check_clap(self):
        if not self.thread_queue.empty() and self.thread_queue.get() == 'clap':
            self.thread_queue.queue.clear()
            self.stop_talking()
            self.receive_command()

    def listen(self):
        # stop the clap detector thread when listening for command
        # self.clap_detector.stop()
        self.speak('What can I do for you?')
        # response =
        # self.clap_detector.start()
        return self.voice_parser.listen()

    def receive_command(self):
        # response = self.listen()
        self.speak('What can I do for you?')
        self.speech_q.queue.clear()
        response = None
        while not response:
            response = self.voice_parser.listen()
        print response

        if response == "what's your name":
            self.queue_speech('My name is Faraday')
            self.state = States.Speaking
        elif response == 'who are you':
            self.queue_speech('I am your friend')
            self.state = States.Speaking
        elif response == 'are you a robot':
            self.queue_speech('Yes')
            self.state = States.Speaking

        elif 'weather' in response:
            tomorrow = 'tomorrow' in response
            self.queue_speech(self.weather.get_weather(tomorrow))
            self.state = States.Speaking

        if 'news' in response:
            self.read_news()

        if 'read' in response:
            num_dict = {
                'one': 1,
                'two': 2,
                'three': 3,
                'four': 4,
                'five': 5,
                'six': 6,
                'seven': 7,
                'eight': 8,
                'nine': 9
            }
            arr = response.split(' ')

            for a in ['article', 'articles']:
                if a in arr:
                    num = arr[arr.index(a) + 1]
                    try:
                        index = int(num)
                    except:
                        index = num_dict[num]
                    self.read_full_article(int(index) - 1)

        if 'train' in response:
            self.clap_detector.stop()
            if 'no claps' in response:
                self.clap_detector.train_noclaps(samples=20)
            elif 'claps' in response:
                self.clap_detector.train_claps(samples=20)

        print 'done'

    def stop(self):
        self.running = False

    # Update all bot data
    def update_data(self):
        # update news
        self.news.update()
        self.last_update = datetime.now()

    # add speech to the queue for consumption
    def queue_speech(self, text):
        print 'queuing'
        self.speech_q.put(text)

    # Speak the given text
    def speak(self, text):
        print text
        # open a speech commanbd subprocess
        self.cur_speech_process = subprocess.Popen('%s %s "%s" %s' %\
         (SPEAK_COMMAND, VOICE, str(text), VOICE_SPEED), shell=True)
        # wait for the process to finish
        self.cur_speech_process.communicate()

    def stop_talking(self):
        print 'stop talking'
        try:
            if self.cur_speech_process:
                self.cur_speech_process.kill()
            if self.cur_alarm_process:
                self.cur_alarm_process.kill()
        except OSError:
            traceback.print_exc()

    def set_alarm(self, date, tone):
        self.alarms += [date]
        self.alarm_tones += [tone]

    def check_alarm(self, time):
        now = datetime.now()
        if now > time and now < time + timedelta(milliseconds=10):
            self.alarm_index = (self.alarm_index + 1) % len(self.alarms)
            self.raise_alarm()

    def raise_alarm(self):
        # execute(self.cur_alarm_process, 'afplay %s' % self.alarm_tones[self.alarm_index])
        self.cur_alarm_process = subprocess.Popen(
            'afplay %s' % self.alarm_tones[self.alarm_index], shell=True)
        self.cur_alarm_process.communicate()

    """
    Read the news headlines one by one.
    User commands:
    'read article <index>': read the full article
    'abstract article <index>': read the abstract
    'repeat current': start over current article
    'repeat all': start over
    """

    def read_news(self):
        self.queue_speech('Today\'s headlines')
        # time.sleep(1)
        headlines = [article['title'][0] for article in self.news.articles]

        # read the headlines
        for i, h in enumerate(headlines):
            self.queue_speech(i + 1)
            text = h.encode('utf-8').replace('\"', '\\"')
            self.queue_speech(text)
        self.state = States.Speaking

    def read_full_article(self, index):
        self.queue_speech('Reading article ' + str(index + 1))
        lines = self.news.articles[index]['snippet']
        for line in lines:
            text = line.encode('utf-8').replace('\"', '\\"')
            self.queue_speech(text)
        self.state = States.Speaking