merge with master
commit
b917b62f90
|
@ -16,11 +16,12 @@
|
|||
# along with Mycroft Core. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
import serial
|
||||
import sys
|
||||
from Queue import Queue
|
||||
from threading import Thread
|
||||
|
||||
import serial
|
||||
|
||||
from mycroft.client.enclosure.arduino import EnclosureArduino
|
||||
from mycroft.client.enclosure.eyes import EnclosureEyes
|
||||
from mycroft.client.enclosure.mouth import EnclosureMouth
|
||||
|
@ -143,7 +144,7 @@ class Enclosure:
|
|||
self.eyes = EnclosureEyes(self.client, self.writer)
|
||||
self.mouth = EnclosureMouth(self.client, self.writer)
|
||||
self.system = EnclosureArduino(self.client, self.writer)
|
||||
self.__init_events()
|
||||
self.__register_events()
|
||||
|
||||
def __init_serial(self):
|
||||
try:
|
||||
|
@ -161,11 +162,30 @@ class Enclosure:
|
|||
"It is not possible to connect to serial port: " + self.port)
|
||||
raise
|
||||
|
||||
def __init_events(self):
|
||||
def __register_events(self):
|
||||
self.client.on('mycroft.paired', self.__update_events)
|
||||
self.client.on('recognizer_loop:wakeword', self.eyes.blink)
|
||||
self.__register_mouth_events()
|
||||
|
||||
def __register_mouth_events(self):
|
||||
self.client.on('recognizer_loop:listening', self.mouth.listen)
|
||||
self.client.on('recognizer_loop:audio_output_start', self.mouth.talk)
|
||||
self.client.on('recognizer_loop:audio_output_end', self.mouth.reset)
|
||||
self.client.on('recognizer_loop:wakeword', self.eyes.blink)
|
||||
|
||||
def __remove_mouth_events(self):
|
||||
self.client.remove('recognizer_loop:listening', self.mouth.listen)
|
||||
self.client.remove('recognizer_loop:audio_output_start',
|
||||
self.mouth.talk)
|
||||
self.client.remove('recognizer_loop:audio_output_end',
|
||||
self.mouth.reset)
|
||||
self.mouth.reset()
|
||||
|
||||
def __update_events(self, event=None):
|
||||
if event and event.metadata:
|
||||
if event.metadata.get('paired', False):
|
||||
self.__register_mouth_events()
|
||||
else:
|
||||
self.__remove_mouth_events()
|
||||
|
||||
def run(self):
|
||||
try:
|
||||
|
|
|
@ -81,7 +81,7 @@ class AudioConsumer(threading.Thread):
|
|||
"""
|
||||
|
||||
# In seconds, the minimum audio size to be sent to remote STT
|
||||
MIN_AUDIO_SIZE = 1.0
|
||||
MIN_AUDIO_SIZE = 0.5
|
||||
|
||||
def __init__(self, state, queue, emitter, wakeup_recognizer,
|
||||
mycroft_recognizer, remote_recognizer):
|
||||
|
|
|
@ -17,14 +17,15 @@
|
|||
|
||||
|
||||
import json
|
||||
from multiprocessing.pool import ThreadPool
|
||||
import time
|
||||
from mycroft.configuration.config import ConfigurationManager
|
||||
from mycroft.messagebus.message import Message
|
||||
import mycroft.util.log
|
||||
from multiprocessing.pool import ThreadPool
|
||||
|
||||
from pyee import EventEmitter
|
||||
from websocket import WebSocketApp
|
||||
|
||||
import mycroft.util.log
|
||||
from mycroft.configuration.config import ConfigurationManager
|
||||
from mycroft.messagebus.message import Message
|
||||
from mycroft.util import str2bool
|
||||
|
||||
__author__ = 'seanfitz'
|
||||
|
@ -99,6 +100,9 @@ class WebsocketClient(object):
|
|||
def once(self, event_name, func):
|
||||
self.emitter.once(event_name, func)
|
||||
|
||||
def remove(self, event_name, func):
|
||||
self.emitter.remove_listener(event_name, func)
|
||||
|
||||
def run_forever(self):
|
||||
self.client.run_forever()
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
|
||||
import shortuuid
|
||||
|
||||
from mycroft.configuration.config import ConfigurationManager
|
||||
from mycroft.identity import IdentityManager
|
||||
from mycroft.messagebus.client.ws import WebsocketClient
|
||||
|
@ -34,6 +35,7 @@ def generate_pairing_code():
|
|||
class DevicePairingClient(object):
|
||||
def __init__(self, config=_config, pairing_code=None):
|
||||
self.config = config
|
||||
self.paired = False
|
||||
self.ws_client = WebsocketClient(host=config.get("host"),
|
||||
port=config.get("port"),
|
||||
path=config.get("route"),
|
||||
|
@ -53,6 +55,7 @@ class DevicePairingClient(object):
|
|||
identity.owner = register_payload.get('user')
|
||||
self.identity_manager.update(identity)
|
||||
self.ws_client.close()
|
||||
self.paired = True
|
||||
|
||||
def send_device_info(self):
|
||||
msg = Message("device_info",
|
||||
|
@ -63,7 +66,8 @@ class DevicePairingClient(object):
|
|||
|
||||
self.ws_client.emit(msg)
|
||||
|
||||
def print_error(self, message):
|
||||
@staticmethod
|
||||
def print_error(message):
|
||||
print(repr(message))
|
||||
|
||||
def run(self):
|
||||
|
@ -76,5 +80,6 @@ class DevicePairingClient(object):
|
|||
def main():
|
||||
DevicePairingClient().run()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
|
@ -15,11 +15,12 @@
|
|||
# You should have received a copy of the GNU General Public License
|
||||
# along with Mycroft Core. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import threading
|
||||
from threading import Thread
|
||||
|
||||
from adapt.intent import IntentBuilder
|
||||
from os.path import dirname
|
||||
|
||||
from mycroft.messagebus.message import Message
|
||||
from mycroft.pairing.client import DevicePairingClient
|
||||
from mycroft.skills.core import MycroftSkill
|
||||
|
||||
|
@ -27,21 +28,41 @@ from mycroft.skills.core import MycroftSkill
|
|||
class PairingSkill(MycroftSkill):
|
||||
def __init__(self):
|
||||
super(PairingSkill, self).__init__(name="PairingSkill")
|
||||
self.client = None
|
||||
self.displaying = False
|
||||
|
||||
def initialize(self):
|
||||
intent = IntentBuilder("PairingIntent").require(
|
||||
"DevicePairingPhrase").build()
|
||||
"DevicePairingPhrase").build()
|
||||
self.load_data_files(dirname(__file__))
|
||||
self.register_intent(intent, handler=self.handle_pairing_request)
|
||||
|
||||
def handle_pairing_request(self, message):
|
||||
pairing_client = DevicePairingClient()
|
||||
pairing_code = pairing_client.pairing_code
|
||||
threading.Thread(target=pairing_client.run).start()
|
||||
self.enclosure.mouth_text("Pairing code is: " + pairing_code)
|
||||
if not self.client:
|
||||
self.displaying = False
|
||||
self.__emit_paired(False)
|
||||
self.client = DevicePairingClient()
|
||||
Thread(target=self.client.run).start()
|
||||
self.emitter.on("recognizer_loop:audio_output_start",
|
||||
self.__display_pairing_code)
|
||||
self.speak_dialog(
|
||||
"pairing.instructions",
|
||||
data={"pairing_code": ', ,'.join(pairing_code)})
|
||||
"pairing.instructions",
|
||||
data={"pairing_code": ', ,'.join(self.client.pairing_code)})
|
||||
|
||||
def __display_pairing_code(self, event=None):
|
||||
if self.client.paired:
|
||||
self.enclosure.mouth_talk()
|
||||
self.client = None
|
||||
self.__emit_paired(True)
|
||||
self.emitter.remove("recognizer_loop:audio_output_start",
|
||||
self.__display_pairing_code)
|
||||
elif not self.displaying:
|
||||
self.displaying = True
|
||||
self.enclosure.mouth_text(self.client.pairing_code)
|
||||
|
||||
def __emit_paired(self, paired):
|
||||
msg = Message('mycroft.paired', metadata={'paired': paired})
|
||||
self.emitter.emit(msg)
|
||||
|
||||
def stop(self):
|
||||
pass
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
# Copyright 2016 Mycroft AI, Inc.
|
||||
#
|
||||
# This file is part of Mycroft Core.
|
||||
#
|
||||
# Mycroft Core is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Mycroft Core is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Mycroft Core. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from os.path import dirname
|
||||
|
||||
from adapt.intent import IntentBuilder
|
||||
from mycroft.skills.core import MycroftSkill
|
||||
from mycroft.util.log import getLogger
|
||||
|
||||
__author__ = 'eward'
|
||||
|
||||
LOGGER = getLogger(__name__)
|
||||
|
||||
|
||||
class WelcomeSkill(MycroftSkill):
|
||||
|
||||
def __init__(self):
|
||||
super(WelcomeSkill, self).__init__(name="WelcomeSkill")
|
||||
|
||||
def initialize(self):
|
||||
self.load_data_files(dirname(__file__))
|
||||
|
||||
welcome_intent = IntentBuilder("WelcIntent").require("WelcKey").build()
|
||||
self.register_intent(welcome_intent, self.handle_welcome_intent)
|
||||
|
||||
def handle_welcome_intent(self, message):
|
||||
self.speak_dialog('Welcome')
|
||||
|
||||
def stop(self):
|
||||
pass
|
||||
|
||||
|
||||
def create_skill():
|
||||
return WelcomeSkill()
|
|
@ -0,0 +1 @@
|
|||
You're welcome.
|
|
@ -0,0 +1,2 @@
|
|||
thank you
|
||||
thanks
|
|
@ -190,3 +190,41 @@ class AudioConsumerTest(unittest.TestCase):
|
|||
self.assertIsNotNone(utterances)
|
||||
self.assertTrue(len(utterances) == 1)
|
||||
self.assertEquals("what's the weather next week", utterances[0])
|
||||
|
||||
def test_stop(self):
|
||||
self.queue.put(self.__create_sample_from_test_file('mycroft'))
|
||||
self.consumer.read_audio()
|
||||
|
||||
self.queue.put(self.__create_sample_from_test_file('stop'))
|
||||
self.recognizer.set_transcriptions(["stop"])
|
||||
monitor = {}
|
||||
|
||||
def utterance_callback(message):
|
||||
monitor['utterances'] = message.get('utterances')
|
||||
|
||||
self.loop.once('recognizer_loop:utterance', utterance_callback)
|
||||
self.consumer.read_audio()
|
||||
|
||||
utterances = monitor.get('utterances')
|
||||
self.assertIsNotNone(utterances)
|
||||
self.assertTrue(len(utterances) == 1)
|
||||
self.assertEquals("stop", utterances[0])
|
||||
|
||||
def test_record(self):
|
||||
self.queue.put(self.__create_sample_from_test_file('mycroft'))
|
||||
self.consumer.read_audio()
|
||||
|
||||
self.queue.put(self.__create_sample_from_test_file('record'))
|
||||
self.recognizer.set_transcriptions(["record"])
|
||||
monitor = {}
|
||||
|
||||
def utterance_callback(message):
|
||||
monitor['utterances'] = message.get('utterances')
|
||||
|
||||
self.loop.once('recognizer_loop:utterance', utterance_callback)
|
||||
self.consumer.read_audio()
|
||||
|
||||
utterances = monitor.get('utterances')
|
||||
self.assertIsNotNone(utterances)
|
||||
self.assertTrue(len(utterances) == 1)
|
||||
self.assertEquals("record", utterances[0])
|
||||
|
|
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue