Beispiel #1
0
    def init(self):
        global conversation
        self.detector = None
        self._interrupted = False
        print('''
********************************************************
*          wukong-robot - 中文语音对话机器人           *
*          (c) 2019 潘伟洲 <*****@*****.**>              *
*     https://github.com/wzpan/wukong-robot.git        *
********************************************************

            如需退出,可以按 Ctrl-4 组合键。

''')

        config.init()
        self._i2c = I2c()
        self._i2c.start()
        self._conversation = Conversation(self._i2c, self._profiling)
        self._conversation.say(
            '{} 你好!试试对我喊唤醒词叫醒我吧'.format(config.get('first_name', '主人')), True)
        self._observer = Observer()
        event_handler = ConfigMonitor(self._conversation)
        self._observer.schedule(event_handler, constants.CONFIG_PATH, False)
        self._observer.schedule(event_handler, constants.DATA_PATH, False)
        self._observer.start()
Beispiel #2
0
    def init(self):
        global conversation
        self.detector = None
        self._interrupted = False        
        print('''
********************************************************
*          wukong-robot - 中文语音对话机器人           *
*          (c) 2019 潘伟洲 <*****@*****.**>              *
*     https://github.com/wzpan/wukong-robot.git        *
********************************************************

            后台管理端:http://{}:{}
            如需退出,可以按 Ctrl-4 组合键

'''.format(config.get('/server/host', '0.0.0.0'), config.get('/server/port', '5000')))
        config.init()
        self._conversation = Conversation(self._profiling)
        self._conversation.say('{} 你好!试试对我喊唤醒词叫醒我吧'.format(config.get('first_name', '主人')), True)
        self._observer = Observer()
        event_handler = ConfigMonitor(self._conversation)
        self._observer.schedule(event_handler, constants.CONFIG_PATH, False)
        self._observer.schedule(event_handler, constants.DATA_PATH, False)
        self._observer.start()
        if config.get('/muse/enable', False):
            self._wakeup = multiprocessing.Event()
            self.bci = BCI.MuseBCI(self._wakeup)
            self.bci.start()
            thread.start_new_thread(self._loop_event, ())
Beispiel #3
0
 def init(self):
     global conversation
     self._interrupted = False
     config.init()
     self._conversation = Conversation()
     self._conversation.say(
         '{} 你好!试试对我喊唤醒词叫醒我吧'.format(config.get('first_name', '主人')), True)
     self._observer = Observer()
     event_handler = ConfigMonitor(self._conversation)
     self._observer.schedule(event_handler, constants.CONFIG_PATH, False)
     self._observer.schedule(event_handler, constants.DATA_PATH, False)
     self._observer.start()
Beispiel #4
0
    def init(self):
        global conversation
        self.detector = None
        self._interrupted = False
        print('''
********************************************************
*          jarvis- 中文语音对话机器人           *
********************************************************
            如需退出,可以按 Ctrl-4 组合键。

''')

        config.init()
        self._conversation = Conversation(self._profiling, wukong=self)
        self._conversation.say_call_back = server.onSay
        self._observer = Observer()
        event_handler = ConfigMonitor(self._conversation)
        self._observer.schedule(event_handler, constants.CONFIG_PATH, False)
        self._observer.schedule(event_handler, constants.DATA_PATH, False)
        self._observer.start()
Beispiel #5
0
 def init(self):
     global conversation
     self.detector = None
     self._thinking = False
     self._interrupted = False        
     config.init()
     self._conversation = Conversation(self._profiling)
     self._conversation.say('你好!我叫小布', True)
     self._observer = Observer()
     event_handler = ConfigMonitor(self._conversation)
     self._observer.schedule(event_handler, constants.CONFIG_PATH, False)
     self._observer.schedule(event_handler, constants.DATA_PATH, False)
     self._observer.start()
     if config.get('/LED/enable', False) and config.get('/LED/type') == 'aiy':
         thread.start_new_thread(self._init_aiy_button_event, ())
     if config.get('/muse/enable', False):
         self._wakeup = multiprocessing.Event()
         self.bci = BCI.MuseBCI(self._wakeup)
         self.bci.start()
         thread.start_new_thread(self._loop_event, ())
Beispiel #6
0
    def init(self):
        global conversation
        self.detector = None
        self._interrupted = False
        print('''
********************************************************
*                   中文语音对话机器人                   *
********************************************************
            如需退出,可以按 Ctrl-\ 组合键。
''')

        config.init()
        self._conversation = Conversation(self._profiling)
        self._conversation.say(
            '{},有事叫{}'.format(config.get('first_name', '主人'),
                              config.get('robot_name_cn', '八戒')), True)
        self._observer = Observer()
        event_handler = ConfigMonitor(self._conversation)
        self._observer.schedule(event_handler, constants.CONFIG_PATH, False)
        self._observer.schedule(event_handler, constants.DATA_PATH, False)
        self._observer.start()
Beispiel #7
0
    def init(self):
        global conversation
        self.detector = None
        self._interrupted = False
        print('''
*****************************************
*       <中文语音交互导盲机器人>        *
*             by gql                    *
*****************************************
           Exit: ctrl+4
''')

        config.init()
        self._conversation = Conversation(self._profiling)
        self._conversation.say(
            '{} 你好!我是智能导盲机器人,试试对我喊唤醒词叫醒我吧'.format(
                config.get('first_name', '主人')), True)
        self._observer = Observer()
        event_handler = ConfigMonitor(self._conversation)
        self._observer.schedule(event_handler, constants.CONFIG_PATH, False)
        self._observer.schedule(event_handler, constants.DATA_PATH, False)
        self._observer.start()
Beispiel #8
0
    def init(self):
        global conversation
        self.detector = None
        self._thinking = False
        self._interrupted = False
        print(
            """
********************************************************
*          wukong-robot - 中文语音对话机器人           *
*          (c) 2019 潘伟洲 <*****@*****.**>              *
*     https://github.com/wzpan/wukong-robot.git        *
********************************************************

            后台管理端:http://{}:{}
            如需退出,可以按 Ctrl-4 组合键

""".format(
                config.get("/server/host", "0.0.0.0"),
                config.get("/server/port", "5000"),
            )
        )
        config.init()
        self._conversation = Conversation(self._profiling)
        self._conversation.say(
            "{} 你好!试试对我喊唤醒词叫醒我吧".format(config.get("first_name", "主人")), True
        )
        self._observer = Observer()
        event_handler = ConfigMonitor(self._conversation)
        self._observer.schedule(event_handler, constants.CONFIG_PATH, False)
        self._observer.schedule(event_handler, constants.DATA_PATH, False)
        self._observer.start()
        if config.get("/LED/enable", False) and config.get("/LED/type") == "aiy":
            thread.start_new_thread(self._init_aiy_button_event, ())
        if config.get("/muse/enable", False):
            self._wakeup = multiprocessing.Event()
            self.bci = BCI.MuseBCI(self._wakeup)
            self.bci.start()
            thread.start_new_thread(self._loop_event, ())
Beispiel #9
0
    def init(self):
        global conversation
        self.detector = None
        self._interrupted = False
        print('''
********************************************************
*          xiaoyi-robot - 私人中医宝机器人             *
*                 计算机设计大赛                       *
*                                                      *
********************************************************

            如需退出,可以按 Ctrl-4 组合键。

''')
        
        config.init()
        self._conversation = Conversation()
        self._conversation.say('{} 你好!试试对我喊唤醒词叫醒我吧'.format(config.get('first_name', '主人')), True)
        self._observer = Observer()
        event_handler = ConfigMonitor(self._conversation)
        self._observer.schedule(event_handler, constants.CONFIG_PATH, False)
        self._observer.schedule(event_handler, constants.DATA_PATH, False)
        self._observer.start()
Beispiel #10
0
class Wukong(object):

    _profiling = False
    _dev = False

    def init(self):
        global conversation
        self.detector = None
        self._interrupted = False
        print('''
********************************************************
*                   中文语音对话机器人                   *
********************************************************
            如需退出,可以按 Ctrl-\ 组合键。
''')

        config.init()
        self._conversation = Conversation(self._profiling)
        self._conversation.say(
            '{},有事叫{}'.format(config.get('first_name', '主人'),
                              config.get('robot_name_cn', '八戒')), True)
        self._observer = Observer()
        event_handler = ConfigMonitor(self._conversation)
        self._observer.schedule(event_handler, constants.CONFIG_PATH, False)
        self._observer.schedule(event_handler, constants.DATA_PATH, False)
        self._observer.start()

    def _signal_handler(self, signal, frame):
        self._interrupted = True
        utils.clean()
        self._observer.stop()

    def _detected_callback(self):
        """唤醒回调函数"""
        if not utils.is_proper_time():
            logger.warning('勿扰模式开启中')
            return
        if self._conversation.isRecording:
            logger.warning('正在录音中,跳过')
            return
        #播放唤醒响应声
        Player.play(constants.getData('beep_hi.wav'))
        #开始收音
        logger.info('开始录音')
        self._conversation.interrupt()
        self._conversation.isRecording = True

    def _do_not_bother_on_callback(self):
        if config.get('/do_not_bother/hotword_switch', False):
            utils.do_not_bother = True
            Player.play(constants.getData('off.wav'))
            logger.info('勿扰模式打开')

    def _do_not_bother_off_callback(self):
        if config.get('/do_not_bother/hotword_switch', False):
            utils.do_not_bother = False
            Player.play(constants.getData('on.wav'))
            logger.info('勿扰模式关闭')

    def _interrupt_callback(self):
        return self._interrupted

    def run(self):
        self.init()

        # capture SIGINT signal, e.g., Ctrl+C
        signal.signal(signal.SIGINT, self._signal_handler)

        # site
        server.run(self._conversation, self)

        statistic.report(0)

        try:
            self.initDetector()
        except AttributeError:
            logger.error('初始化离线唤醒功能失败')
            pass

    def initDetector(self):
        """初始化唤醒探测器"""
        if self.detector is not None:
            self.detector.terminate()
        models = [
            constants.getHotwordModel(config.get('hotword', 'wukong.pmdl')),
            constants.getHotwordModel(utils.get_do_not_bother_on_hotword()),
            constants.getHotwordModel(utils.get_do_not_bother_off_hotword())
        ]
        #唤醒词检测函数,调整sensitivity参数可修改唤醒词检测的准确性
        self.detector = snowboydecoder.HotwordDetector(models,
                                                       sensitivity=config.get(
                                                           'sensitivity', 0.5))
        # main loop
        try:
            #唤醒参数设置及成功唤醒后的回调设置
            self.detector.start(
                detected_callback=[
                    self._detected_callback, self._do_not_bother_on_callback,
                    self._do_not_bother_off_callback
                ],
                audio_recorder_callback=self._conversation.converse,
                interrupt_check=self._interrupt_callback,
                silent_count_threshold=config.get('silent_threshold', 15),
                recording_timeout=config.get('recording_timeout', 5) * 4,
                sleep_time=0.03)
            #释放资源
            self.detector.terminate()
        except Exception as e:
            logger.critical('离线唤醒机制初始化失败:{}'.format(e))

    def md5(self, password):
        return hashlib.md5(password.encode('utf-8')).hexdigest()

    def update(self):
        updater = Updater()
        return updater.update()

    def fetch(self):
        updater = Updater()
        updater.fetch()

    def restart(self):
        logger.critical('程序重启...')
        try:
            self.detector.terminate()
        except AttributeError:
            pass
        python = sys.executable
        os.execl(python, python, *sys.argv)

    def profiling(self):
        logger.info('性能调优')
        self._profiling = True
        self.run()

    def dev(self):
        logger.info('使用测试环境')
        self._dev = True
        self.run()
Beispiel #11
0
class Wukong(object):

    _profiling = False
    _dev = False
    
    def init(self):
        global conversation
        self.detector = None
        self._interrupted = False        
        print('''
********************************************************
*          wukong-robot - 中文语音对话机器人           *
*          (c) 2019 潘伟洲 <*****@*****.**>              *
*     https://github.com/wzpan/wukong-robot.git        *
********************************************************

            后台管理端:http://{}:{}
            如需退出,可以按 Ctrl-4 组合键

'''.format(config.get('/server/host', '0.0.0.0'), config.get('/server/port', '5000')))
        config.init()
        self._conversation = Conversation(self._profiling)
        self._conversation.say('{} 你好!试试对我喊唤醒词叫醒我吧'.format(config.get('first_name', '主人')), True)
        self._observer = Observer()
        event_handler = ConfigMonitor(self._conversation)
        self._observer.schedule(event_handler, constants.CONFIG_PATH, False)
        self._observer.schedule(event_handler, constants.DATA_PATH, False)
        self._observer.start()
        if config.get('/muse/enable', False):
            self._wakeup = multiprocessing.Event()
            self.bci = BCI.MuseBCI(self._wakeup)
            self.bci.start()
            thread.start_new_thread(self._loop_event, ())

    def _loop_event(self):
        while True:
            self._wakeup.wait()
            self._conversation.interrupt()
            query = self._conversation.activeListen()
            self._conversation.doResponse(query)
            self._wakeup.clear()

    def _signal_handler(self, signal, frame):
        self._interrupted = True
        utils.clean()
        self._observer.stop()

    def _detected_callback(self):
        def start_record():
            logger.info('开始录音')            
            self._conversation.isRecording = True;
        if not utils.is_proper_time():
            logger.warning('勿扰模式开启中')
            return
        if self._conversation.isRecording:
            logger.warning('正在录音中,跳过')
            return
        self._conversation.interrupt()
        Player.play(constants.getData('beep_hi.wav'), onCompleted=start_record, wait=True)

    def _do_not_bother_on_callback(self):
        if config.get('/do_not_bother/hotword_switch', False):
            utils.do_not_bother = True
            Player.play(constants.getData('off.wav'))
            logger.info('勿扰模式打开')

    def _do_not_bother_off_callback(self):
        if config.get('/do_not_bother/hotword_switch', False):
            utils.do_not_bother = False
            Player.play(constants.getData('on.wav'))
            logger.info('勿扰模式关闭')

    def _interrupt_callback(self):
        return self._interrupted

    def run(self):
        self.init()

        # capture SIGINT signal, e.g., Ctrl+C
        signal.signal(signal.SIGINT, self._signal_handler)

        # site
        server.run(self._conversation, self)

        statistic.report(0)

        try:
            self.initDetector()
        except AttributeError:
            logger.error('初始化离线唤醒功能失败')
            pass

    def initDetector(self):
        if self.detector is not None:
            self.detector.terminate()
        if config.get('/do_not_bother/hotword_switch', False):
            models = [
                constants.getHotwordModel(config.get('hotword', 'wukong.pmdl')),
                constants.getHotwordModel(utils.get_do_not_bother_on_hotword()),
                constants.getHotwordModel(utils.get_do_not_bother_off_hotword())
            ]
        else:
            models = constants.getHotwordModel(config.get('hotword', 'wukong.pmdl'))
        self.detector = snowboydecoder.HotwordDetector(models, sensitivity=config.get('sensitivity', 0.5))
        # main loop
        try:
            if config.get('/do_not_bother/hotword_switch', False):
                callbacks = [self._detected_callback,
                             self._do_not_bother_on_callback,
                             self._do_not_bother_off_callback]
            else:
                callbacks = self._detected_callback
            self.detector.start(detected_callback=callbacks,
                                audio_recorder_callback=self._conversation.converse,
                                interrupt_check=self._interrupt_callback,
                                silent_count_threshold=config.get('silent_threshold', 15),
                                recording_timeout=config.get('recording_timeout', 5) * 4,
                                sleep_time=0.03)
            self.detector.terminate()
        except Exception as e:
            logger.critical('离线唤醒机制初始化失败:{}'.format(e))

    def help(self):
        print("""=====================================================================================
    python3 wukong.py [命令]
    可选命令:
      md5                      - 用于计算字符串的 md5 值,常用于密码设置
      update                   - 手动更新 wukong-robot
      upload [thredNum]        - 手动上传 QA 集语料,重建 solr 索引。
                                 threadNum 表示上传时开启的线程数(可选。默认值为 10)
      profiling                - 运行过程中打印耗时数据
      train <w1> <w2> <w3> <m> - 传入三个wav文件,生成snowboy的.pmdl模型
                                 w1, w2, w3 表示三个1~3秒的唤醒词录音
                                 m 表示snowboy的.pmdl模型
    如需更多帮助,请访问:https://wukong.hahack.com/#/run
=====================================================================================""")

    def md5(self, password):
        """
        计算字符串的 md5 值
        """
        return hashlib.md5(str(password).encode('utf-8')).hexdigest()

    def update(self):
        """
        更新 wukong-robot
        """
        updater = Updater()
        return updater.update()

    def fetch(self):
        """
        检测 wukong-robot 的更新
        """
        updater = Updater()
        updater.fetch()

    def upload(self, threadNum=10):
        """
        手动上传 QA 集语料,重建 solr 索引
        """
        try:
            qaJson = os.path.join(constants.TEMP_PATH, 'qa_json')
            make_json.run(constants.getQAPath(), qaJson)
            solr_tools.clear_documents(config.get('/anyq/host', '0.0.0.0'),
                                       'collection1',
                                       config.get('/anyq/solr_port', '8900')
            )
            solr_tools.upload_documents(config.get('/anyq/host', '0.0.0.0'),
                                        'collection1',
                                        config.get('/anyq/solr_port', '8900'),
                                        qaJson,
                                        threadNum
            )
        except Exception as e:
            logger.error("上传失败:{}".format(e))


    def restart(self):
        """
        重启 wukong-robot
        """
        logger.critical('程序重启...')
        try:
            self.detector.terminate()
        except AttributeError:
            pass
        python = sys.executable
        os.execl(python, python, * sys.argv)

    def profiling(self):
        """
        运行过程中打印耗时数据
        """
        logger.info('性能调优')
        self._profiling = True
        self.run()

    def dev(self):
        logger.info('使用测试环境')
        self._dev = True
        self.run()

    def train(self, w1, w2, w3, m):
        '''
        传入三个wav文件,生成snowboy的.pmdl模型
        '''
        def get_wave(fname):
            with open(fname, 'rb') as infile:
                return base64.b64encode(infile.read()).decode('utf-8')
        url = 'https://snowboy.kitt.ai/api/v1/train/'
        data = {
            "name": "wukong-robot",
            "language": "zh",
            "token": config.get('snowboy_token', ''),
            "voice_samples": [
                {"wave": get_wave(w1)},
                {"wave": get_wave(w2)},
                {"wave": get_wave(w3)}
            ]
        }
        response = requests.post(url, json=data)
        if response.ok:
            with open(m, "wb") as outfile:
                outfile.write(response.content)
            return 'Snowboy模型已保存至{}'.format(m)
        else:
            return "Snowboy模型生成失败,原因:{}".format(response.text)
Beispiel #12
0
import sys

import fire

from robot import config
from robot.Conversation import Conversation
from server import server
from wukong import Wukong

wukong = None
conversation = None

if __name__ == '__main__':
    if len(sys.argv) == 1:
        conversation = Conversation(False)
        wukong = Wukong(conversation)
        config.init()

        server.run(conversation, wukong)
        # wukong.run()
    else:
        fire.Fire(Wukong)
Beispiel #13
0
class Wukong(object):
    def init(self):
        global conversation
        self._interrupted = False
        config.init()
        self._conversation = Conversation()
        self._conversation.say(
            '{} 你好!试试对我喊唤醒词叫醒我吧'.format(config.get('first_name', '主人')), True)
        self._observer = Observer()
        event_handler = ConfigMonitor(self._conversation)
        self._observer.schedule(event_handler, constants.CONFIG_PATH, False)
        self._observer.schedule(event_handler, constants.DATA_PATH, False)
        self._observer.start()

    def _signal_handler(self, signal, frame):
        self._interrupted = True
        utils.clean()
        self._observer.stop()

    def _detected_callback(self):
        if not utils.is_proper_time():
            logger.warning('勿扰模式开启中')
            return
        snowboydecoder.play_audio_file(constants.getData('beep_hi.wav'))
        self._conversation.interrupt()

    def _do_not_bother_on_callback(self):
        utils.do_not_bother = True
        snowboydecoder.play_audio_file(constants.getData('off.wav'))
        logger.info('勿扰模式打开')

    def _do_not_bother_off_callback(self):
        utils.do_not_bother = False
        snowboydecoder.play_audio_file(constants.getData('on.wav'))
        logger.info('勿扰模式关闭')

    def _interrupt_callback(self):
        return self._interrupted

    def run(self):
        self.init()
        models = [
            constants.getHotwordModel(config.get('hotword', 'wukong.pmdl')),
            constants.getHotwordModel(utils.get_do_not_bother_on_hotword()),
            constants.getHotwordModel(utils.get_do_not_bother_off_hotword())
        ]

        # capture SIGINT signal, e.g., Ctrl+C
        signal.signal(signal.SIGINT, self._signal_handler)
        detector = snowboydecoder.HotwordDetector(models,
                                                  sensitivity=config.get(
                                                      'sensitivity', 0.5))
        print('Listening... Press Ctrl+C to exit')

        # site
        server.run()

        # main loop
        detector.start(detected_callback=[
            self._detected_callback, self._do_not_bother_on_callback,
            self._do_not_bother_off_callback
        ],
                       audio_recorder_callback=self._conversation.converse,
                       interrupt_check=self._interrupt_callback,
                       silent_count_threshold=5,
                       sleep_time=0.03)
        detector.terminate()

    def md5(self, password):
        return hashlib.md5(password.encode('utf-8')).hexdigest()

    def _pull(self):
        return call(['git', 'pull'], cwd=constants.APP_PATH, shell=False) == 0

    def _pip(self):
        return call(['pip', 'install', '-r', 'requirements.txt'],
                    cwd=constants.APP_PATH,
                    shell=False) == 0

    def update(self):
        if self._pull() and self._pip():
            logger.info('wukong-robot 更新成功!')
        else:
            logger.info('wukong-robot 更新失败!')
Beispiel #14
0
class Wukong(object):
    def init(self):
        global conversation
        self.detector = None
        self._interrupted = False
        print('''
********************************************************
*          wukong-robot - 中文语音对话机器人           *
*          (c) 2019 潘伟洲 <*****@*****.**>              *
*     https://github.com/wzpan/wukong-robot.git        *
********************************************************

            如需退出,可以按 Ctrl-4 组合键。

''')

        config.init()
        self._conversation = Conversation()
        self._conversation.say(
            '{} 你好!试试对我喊唤醒词叫醒我吧'.format(config.get('first_name', '主人')), True)
        self._observer = Observer()
        event_handler = ConfigMonitor(self._conversation)
        self._observer.schedule(event_handler, constants.CONFIG_PATH, False)
        self._observer.schedule(event_handler, constants.DATA_PATH, False)
        self._observer.start()

    def _signal_handler(self, signal, frame):
        self._interrupted = True
        utils.clean()
        self._observer.stop()

    def _detected_callback(self):
        if not utils.is_proper_time():
            logger.warning('勿扰模式开启中')
            return
        if self._conversation.isRecording:
            logger.warning('正在录音中,跳过')
            return
        Player.play(constants.getData('beep_hi.wav'))
        logger.info('开始录音')
        self._conversation.interrupt()
        self._conversation.isRecording = True

    def _do_not_bother_on_callback(self):
        if config.get('/hotword/hotword_switch', False):
            utils.do_not_bother = True
            Player.play(constants.getData('off.wav'))
            logger.info('勿扰模式打开')

    def _do_not_bother_off_callback(self):
        if config.get('/hotword/hotword_switch', False):
            utils.do_not_bother = False
            Player.play(constants.getData('on.wav'))
            logger.info('勿扰模式关闭')

    def _interrupt_callback(self):
        return self._interrupted

    def run(self):
        self.init()

        # capture SIGINT signal, e.g., Ctrl+C
        signal.signal(signal.SIGINT, self._signal_handler)

        # site
        server.run(self._conversation, self)

        statistic.report(0)

        self.initDetector()

    def initDetector(self):
        if self.detector is not None:
            self.detector.terminate()
        models = [
            constants.getHotwordModel(config.get('hotword', 'wukong.pmdl')),
            constants.getHotwordModel(utils.get_do_not_bother_on_hotword()),
            constants.getHotwordModel(utils.get_do_not_bother_off_hotword())
        ]
        self.detector = snowboydecoder.HotwordDetector(models,
                                                       sensitivity=config.get(
                                                           'sensitivity', 0.5))
        # main loop
        try:
            self.detector.start(
                detected_callback=[
                    self._detected_callback, self._do_not_bother_on_callback,
                    self._do_not_bother_off_callback
                ],
                audio_recorder_callback=self._conversation.converse,
                interrupt_check=self._interrupt_callback,
                silent_count_threshold=config.get('silent_threshold', 15),
                recording_timeout=config.get('recording_timeout', 5) * 4,
                sleep_time=0.03)
            self.detector.terminate()
        except Exception as e:
            logger.critical('离线唤醒机制初始化失败:{}'.format(e))

    def md5(self, password):
        return hashlib.md5(password.encode('utf-8')).hexdigest()

    def update(self):
        updater = Updater()
        return updater.update()

    def fetch(self):
        updater = Updater()
        updater.fetch()

    def restart(self):
        logger.critical('程序重启...')
        self.detector.terminate()
        python = sys.executable
        os.execl(python, python, *sys.argv)
Beispiel #15
0
class Wukong(object):

    _profiling = False
    _dev = False

    def init(self):
        global conversation
        self.detector = None
        self._interrupted = False
        print('''
********************************************************
*          wukong-robot - 中文语音对话机器人           *
*          (c) 2019 潘伟洲 <*****@*****.**>              *
*     https://github.com/wzpan/wukong-robot.git        *
********************************************************

            后台管理端:http://{}:{}
            如需退出,可以按 Ctrl-4 组合键

'''.format(config.get('/server/host', '0.0.0.0'),
           config.get('/server/port', '5000')))
        config.init()
        self._conversation = Conversation(self._profiling)
        self._conversation.say(
            '{} 你好!试试对我喊唤醒词叫醒我吧'.format(config.get('first_name', '主人')), True)
        self._observer = Observer()
        event_handler = ConfigMonitor(self._conversation)
        self._observer.schedule(event_handler, constants.CONFIG_PATH, False)
        self._observer.schedule(event_handler, constants.DATA_PATH, False)
        self._observer.start()

    def _signal_handler(self, signal, frame):
        self._interrupted = True
        utils.clean()
        self._observer.stop()

    def _detected_callback(self):
        def start_record():
            logger.info('开始录音')
            self._conversation.isRecording = True

        if not utils.is_proper_time():
            logger.warning('勿扰模式开启中')
            return
        if self._conversation.isRecording:
            logger.warning('正在录音中,跳过')
            return
        self._conversation.interrupt()
        Player.play(constants.getData('beep_hi.wav'),
                    onCompleted=start_record,
                    wait=True)

    def _do_not_bother_on_callback(self):
        if config.get('/do_not_bother/hotword_switch', False):
            utils.do_not_bother = True
            Player.play(constants.getData('off.wav'))
            logger.info('勿扰模式打开')

    def _do_not_bother_off_callback(self):
        if config.get('/do_not_bother/hotword_switch', False):
            utils.do_not_bother = False
            Player.play(constants.getData('on.wav'))
            logger.info('勿扰模式关闭')

    def _interrupt_callback(self):
        return self._interrupted

    def run(self):
        self.init()

        # capture SIGINT signal, e.g., Ctrl+C
        signal.signal(signal.SIGINT, self._signal_handler)

        # site
        server.run(self._conversation, self)

        statistic.report(0)

        try:
            self.initDetector()
        except AttributeError:
            logger.error('初始化离线唤醒功能失败')
            pass

    def initDetector(self):
        if self.detector is not None:
            self.detector.terminate()
        if config.get('/do_not_bother/hotword_switch', False):
            models = [
                constants.getHotwordModel(config.get('hotword',
                                                     'wukong.pmdl')),
                constants.getHotwordModel(
                    utils.get_do_not_bother_on_hotword()),
                constants.getHotwordModel(
                    utils.get_do_not_bother_off_hotword())
            ]
        else:
            models = constants.getHotwordModel(
                config.get('hotword', 'wukong.pmdl'))
        self.detector = snowboydecoder.HotwordDetector(models,
                                                       sensitivity=config.get(
                                                           'sensitivity', 0.5))
        # main loop
        try:
            if config.get('/do_not_bother/hotword_switch', False):
                callbacks = [
                    self._detected_callback, self._do_not_bother_on_callback,
                    self._do_not_bother_off_callback
                ]
            else:
                callbacks = self._detected_callback
            self.detector.start(
                detected_callback=callbacks,
                audio_recorder_callback=self._conversation.converse,
                interrupt_check=self._interrupt_callback,
                silent_count_threshold=config.get('silent_threshold', 15),
                recording_timeout=config.get('recording_timeout', 5) * 4,
                sleep_time=0.03)
            self.detector.terminate()
        except Exception as e:
            logger.critical('离线唤醒机制初始化失败:{}'.format(e))

    def help(self):
        print(
            """=====================================================================================
    python3 wukong.py [命令]
    可选命令:
      md5                  - 用于计算字符串的 md5 值,常用于密码设置
      update               - 手动更新 wukong-robot
      upload [thredNum]    - 手动上传 QA 集语料,重建 solr 索引。
                             threadNum 表示上传时开启的线程数(可选。默认值为 10)
      profiling            - 运行过程中打印耗时数据
    如需更多帮助,请访问:https://wukong.hahack.com/#/run
====================================================================================="""
        )

    def md5(self, password):
        """
        计算字符串的 md5 值
        """
        return hashlib.md5(password.encode('utf-8')).hexdigest()

    def update(self):
        """
        更新 wukong-robot
        """
        updater = Updater()
        return updater.update()

    def fetch(self):
        """
        检测 wukong-robot 的更新
        """
        updater = Updater()
        updater.fetch()

    def upload(self, threadNum=10):
        """
        手动上传 QA 集语料,重建 solr 索引
        """
        try:
            qaJson = os.path.join(constants.TEMP_PATH, 'qa_json')
            make_json.run(constants.getQAPath(), qaJson)
            solr_tools.clear_documents(config.get('/anyq/host', '0.0.0.0'),
                                       'collection1',
                                       config.get('/anyq/solr_port', '8900'))
            solr_tools.upload_documents(config.get('/anyq/host',
                                                   '0.0.0.0'), 'collection1',
                                        config.get('/anyq/solr_port', '8900'),
                                        qaJson, threadNum)
        except Exception as e:
            logger.error("上传失败:{}".format(e))

    def restart(self):
        """
        重启 wukong-robot
        """
        logger.critical('程序重启...')
        try:
            self.detector.terminate()
        except AttributeError:
            pass
        python = sys.executable
        os.execl(python, python, *sys.argv)

    def profiling(self):
        """
        运行过程中打印耗时数据
        """
        logger.info('性能调优')
        self._profiling = True
        self.run()

    def dev(self):
        logger.info('使用测试环境')
        self._dev = True
        self.run()
Beispiel #16
0
def detectedCallback():
    global conversation
    if conversation:
        conversation.stop()
    Player.player('static/beep_hi.wav', False)

def signal_handler(signal, frame):
    global interrupted
    interrupted = True


def interrupt_callback():
    global interrupted
    return interrupted

conversation = Conversation()
server.run(conversation)
# 更改唤醒词为配置文件中的值,默认为snowboy文件夹中的
model = config.get('/snowboy/hotword','snowboy/resources/jarvis.pmdl')

# capture SIGINT signal, e.g., Ctrl+C
signal.signal(signal.SIGINT, signal_handler)

detector = snowboydecoder.HotwordDetector(model, sensitivity=config.get('/snowboy/sensitivity', 0.38))
print('""""""""""""""""""""""""""""""'
      'robot'
      '"""""""""""""""""""""""""""""""')
# Player.hello()
logger.info('Listening... Press Ctrl+C to exit')

Beispiel #17
0
class Main(object):
    _profiling = False
    _dev = False

    def init(self):
        global conversation
        self.detector = None
        self._interrupted = False
        print('''
*****************************************
*       <中文语音交互导盲机器人>        *
*             by gql                    *
*****************************************
           Exit: ctrl+4
''')

        config.init()
        self._conversation = Conversation(self._profiling)
        self._conversation.say(
            '{} 你好!我是智能导盲机器人,试试对我喊唤醒词叫醒我吧'.format(
                config.get('first_name', '主人')), True)
        self._observer = Observer()
        event_handler = ConfigMonitor(self._conversation)
        self._observer.schedule(event_handler, constants.CONFIG_PATH, False)
        self._observer.schedule(event_handler, constants.DATA_PATH, False)
        self._observer.start()

    def _signal_handler(self, signal, frame):
        self._interrupted = True
        utils.clean()
        self._observer.stop()

    def _detected_callback(self):
        print("3")
        if not utils.is_proper_time():
            logger.warning('勿扰模式开启中')
            return
        if self._conversation.isRecording:
            logger.warning('正在录音中,跳过')
            return
        self._conversation.say('在“滴”声后,说出你想去的地方')
        time.sleep(4)
        Player.play(constants.getData('beep_hi.wav'))
        logger.info('开始录音')
        self._conversation.interrupt()
        self._conversation.isRecording = True

    def _do_not_bother_on_callback(self):
        if config.get('/do_not_bother/hotword_switch', False):
            utils.do_not_bother = True
            Player.play(constants.getData('off.wav'))
            logger.info('勿扰模式打开')

    def _do_not_bother_off_callback(self):
        if config.get('/do_not_bother/hotword_switch', False):
            utils.do_not_bother = False
            Player.play(constants.getData('on.wav'))
            logger.info('勿扰模式关闭')

    def _interrupt_callback(self):
        return self._interrupted

    def run(self):
        self.init()

        # capture SIGINT signal, e.g., Ctrl+C
        signal.signal(signal.SIGINT, self._signal_handler)

        # site
        server.run(self._conversation, self)

        statistic.report(0)

        try:
            self.initDetector()
        except AttributeError:
            logger.error('初始化离线唤醒功能失败')
            pass

    def initDetector(self):
        if self.detector is not None:
            self.detector.terminate()

        models = [
            constants.getHotwordModel(config.get('hotword', 'xiaofeng.pmdl'))
        ]

        # gql 检测唤醒词
        self.detector = snowboydecoder.HotwordDetector(models,
                                                       sensitivity=config.get(
                                                           'sensitivity', 0.5))

        # main loop
        try:
            callbacks = self._detected_callback

            self.detector.start(
                detected_callback=callbacks,
                audio_recorder_callback=self._conversation.converse,
                interrupt_check=self._interrupt_callback,
                silent_count_threshold=config.get('silent_threshold', 15),
                recording_timeout=config.get('recording_timeout', 5) * 4,
                sleep_time=0.03)
            self.detector.terminate()
        except Exception as e:
            print("error")
            logger.critical('离线唤醒机制初始化失败:{}'.format(e))

    def md5(self, password):
        return hashlib.md5(password.encode('utf-8')).hexdigest()

    def update(self):
        updater = Updater()
        return updater.update()

    def fetch(self):
        updater = Updater()
        updater.fetch()

    def restart(self):
        logger.critical('程序重启...')
        try:
            self.detector.terminate()
        except AttributeError:
            pass
        python = sys.executable
        os.execl(python, python, *sys.argv)

    def profiling(self):
        logger.info('性能调优')
        self._profiling = True
        self.run()

    def dev(self):
        logger.info('使用测试环境')
        self._dev = True
        self.run()
Beispiel #18
0
class Wukong(object):
    _profiling = False
    _dev = False

    wakes = ['在的,Sir', '您说', '怎么了', 'Hello', 'Hi']

    def init(self):
        global conversation
        self.detector = None
        self._interrupted = False
        print('''
********************************************************
*          jarvis- 中文语音对话机器人           *
********************************************************
            如需退出,可以按 Ctrl-4 组合键。

''')

        config.init()
        self._conversation = Conversation(self._profiling, wukong=self)
        self._conversation.say_call_back = server.onSay
        self._observer = Observer()
        event_handler = ConfigMonitor(self._conversation)
        self._observer.schedule(event_handler, constants.CONFIG_PATH, False)
        self._observer.schedule(event_handler, constants.DATA_PATH, False)
        self._observer.start()

    def _signal_handler(self, signal, frame):
        self._interrupted = True
        utils.clean()
        self._observer.stop()

    # 语音唤醒回调
    def _detected_callback(self):
        if not utils.is_proper_time():
            logger.warning('勿扰模式开启中')
            return
        if self._conversation.isRecording:
            logger.warning('正在录音中,跳过')
            return

        server.onSay("{\"action_info\": \"wake\",\"msg\": \"唤醒\"}")
        # self._conversation.say(random.choice(self.wakes))
        Player.play(constants.getData('bee_wake.mp3'))
        logger.info('开始录音')
        self._conversation.interrupt()
        self._conversation.isRecording = True

    # 录音完成回调
    def _recored_callback(self, fp):
        server.onSay("{\"action_info\": \"think\",\"msg\": \"思考\"}")
        logger.info('结束录音 开始思考')
        Player.play(constants.getData('bee_complte.mp3'))
        self._conversation.converse(fp, self._end_think)

    # 结束思考回调
    def _end_think(self):
        server.onSay("{\"action_info\": \"stop_think\",\"msg\": \"思考结束\"}")
        logger.info("结束思考")

    """
    手动唤醒
    """

    def wake(self):
        self.detector.active_now()
        logger.info("手动唤醒!!")

    def _do_not_bother_on_callback(self):
        if config.get('/do_not_bother/hotword_switch', False):
            utils.do_not_bother = True
            Player.play(constants.getData('off.wav'))
            logger.info('勿扰模式打开')

    def _do_not_bother_off_callback(self):
        if config.get('/do_not_bother/hotword_switch', False):
            utils.do_not_bother = False
            Player.play(constants.getData('on.wav'))
            logger.info('勿扰模式关闭')

    def f**k(self):
        logger.info("????? v")

    def _interrupt_callback(self):
        return self._interrupted

    # 启动完成语音提示
    def say_allcomplete(self):
        self._conversation.say(
            '{} 已经启动'.format(config.get('first_name', 'jarvis')), True)

    def run(self):
        self.init()
        KeyHandler.start(self)
        # capture SIGINT signal, e.g., Ctrl+C
        signal.signal(signal.SIGINT, self._signal_handler)

        # site
        server.run(self._conversation, self)
        # statistic.report(0)
        # t = threading.Thread(target=self.openBrawer)
        # t.start()
        # Player.play(constants.getData('robot_open.mp3'), onCompleted=self.say_allcomplete(), volum=0.7)

        try:
            self.initDetector()
        except AttributeError:
            logger.error('初始化离线唤醒功能失败')
            pass

    def initDetector(self):
        if self.detector is not None:
            self.detector.terminate()
        models = [
            constants.getHotwordModel(config.get('hotword', 'wukong.pmdl')),
            constants.getHotwordModel(utils.get_do_not_bother_on_hotword()),
            constants.getHotwordModel(utils.get_do_not_bother_off_hotword())
        ]
        for item in models:
            logger.info(item)

        self.detector = snowboydecoder.HotwordDetector(models,
                                                       sensitivity=config.get(
                                                           'sensitivity', 0.5))
        # main loop
        try:
            self.detector.start(
                detected_callback=[
                    self._detected_callback, self._do_not_bother_on_callback,
                    self._do_not_bother_off_callback, self.f**k
                ],
                audio_recorder_callback=self._recored_callback,
                interrupt_check=self._interrupt_callback,
                silent_count_threshold=config.get('silent_threshold', 15),
                recording_timeout=config.get('recording_timeout', 5) * 4,
                sleep_time=0.03)
            self.detector.terminate()
        except Exception as e:
            logger.critical('离线唤醒机制初始化失败:{}'.format(e))

    def md5(self, password):
        return hashlib.md5(password.encode('utf-8')).hexdigest()

    def update(self):
        updater = Updater()
        return updater.update()

    def fetch(self):
        updater = Updater()
        updater.fetch()

    def restart(self):
        logger.critical('程序重启...')
        try:
            self.detector.terminate()
        except AttributeError:
            pass
        python = sys.executable
        os.execl(python, python, *sys.argv)

    def profiling(self):
        logger.info('性能调优')
        self._profiling = True
        self.run()

    def dev(self):
        logger.info('使用测试环境')
        self._dev = True
        self.run()

    def openBrawer(self):
        pass
Beispiel #19
0
class Xiaobu(object):

    _profiling = False
    _dev = False
    _response_wav = [
        "response1.wav",
        "response2.wav",
        "response3.wav",
        "response4.wav",
        "response5.wav",
    ]
    
    def init(self):
        global conversation
        self.detector = None
        self._thinking = False
        self._interrupted = False        
        config.init()
        self._conversation = Conversation(self._profiling)
        self._conversation.say('你好!我叫小布', True)
        self._observer = Observer()
        event_handler = ConfigMonitor(self._conversation)
        self._observer.schedule(event_handler, constants.CONFIG_PATH, False)
        self._observer.schedule(event_handler, constants.DATA_PATH, False)
        self._observer.start()
        if config.get('/LED/enable', False) and config.get('/LED/type') == 'aiy':
            thread.start_new_thread(self._init_aiy_button_event, ())
        if config.get('/muse/enable', False):
            self._wakeup = multiprocessing.Event()
            self.bci = BCI.MuseBCI(self._wakeup)
            self.bci.start()
            thread.start_new_thread(self._loop_event, ())

    def _loop_event(self):
        while True:
            self._wakeup.wait()
            self._conversation.interrupt()
            query = self._conversation.activeListen()
            self._conversation.doResponse(query)
            self._wakeup.clear()

    def _signal_handler(self, signal, frame):
        self._interrupted = True
        utils.clean()
        self._observer.stop()

    def _detected_callback(self):
        def start_record():
            logger.info('开始录音')    
            print('开始录音') 
            self._conversation.isRecording = True;
        if not utils.is_proper_time():
            logger.warning('勿扰模式开启中')
            return
        if self._conversation.isRecording:
            logger.warning('正在录音中,跳过')
            return
        self._conversation.interrupt()
        if config.get('/LED/enable', False):
            LED.wakeup()
        Player.play(constants.getData(random.choice(self._response_wav)), onCompleted=start_record, wait=True)
        with open("../communication/InPut.txt", "w") as file_writer:
            file_writer.write("true")

    def _do_not_bother_on_callback(self):
        if config.get('/do_not_bother/hotword_switch', False):
            utils.do_not_bother = True
            Player.play(constants.getData('off.wav'))
            logger.info('勿扰模式打开')

    def _do_not_bother_off_callback(self):
        if config.get('/do_not_bother/hotword_switch', False):
            utils.do_not_bother = False
            Player.play(constants.getData('on.wav'))
            logger.info('勿扰模式关闭')

    def _interrupt_callback(self):
        return self._interrupted

    def _init_aiy_button_event(self):
        from aiy.board import Board
        with Board() as board:
            while True:
                board.button.wait_for_press()
                self._conversation.interrupt()
                query = self._conversation.activeListen()
                self._conversation.doResponse(query)

    def run(self):
        self.init()

        # capture SIGINT signal, e.g., Ctrl+C
        signal.signal(signal.SIGINT, self._signal_handler)

        try:
            self.initDetector()
        except AttributeError:
            logger.error('初始化离线唤醒功能失败')
            pass

    def initDetector(self):
        if self.detector is not None:
            self.detector.terminate()
        if config.get('/do_not_bother/hotword_switch', False):
            models = [
                constants.getHotwordModel(config.get('hotword', 'xiaobu.pmdl')),
                constants.getHotwordModel(utils.get_do_not_bother_on_hotword()),
                constants.getHotwordModel(utils.get_do_not_bother_off_hotword())
            ]
        else:
            models = constants.getHotwordModel(config.get('hotword', 'xiaobu.pmdl'))
        self.detector = snowboydecoder.HotwordDetector(models, sensitivity=config.get('sensitivity', 0.5))
        # main loop
        try:
            if config.get('/do_not_bother/hotword_switch', False):
                callbacks = [self._detected_callback,
                             self._do_not_bother_on_callback,
                             self._do_not_bother_off_callback]
            else:
                callbacks = self._detected_callback
            self.detector.start(detected_callback=callbacks,
                                audio_recorder_callback=self._conversation.converse,
                                interrupt_check=self._interrupt_callback,
                                silent_count_threshold=config.get('silent_threshold', 15),
                                recording_timeout=config.get('recording_timeout', 5) * 4,
                                sleep_time=0.03)
            self.detector.terminate()
        except Exception as e:
            logger.critical('离线唤醒机制初始化失败:{}'.format(e))

    def help(self):
        print("""=====================================================================================
    python3 xiaobu.py [命令]
    可选命令:
      train <w1> <w2> <w3> <m> - 传入三个wav文件,生成snowboy的.pmdl模型
                                 w1, w2, w3 表示三个1~3秒的唤醒词录音
                                 m 表示snowboy的.pmdl模型
=====================================================================================""")

    def profiling(self):
        """
        运行过程中打印耗时数据
        """
        logger.info('性能调优')
        self._profiling = True
        self.run()

    def train(self, w1, w2, w3, m):
        '''
        传入三个wav文件,生成snowboy的.pmdl模型
        '''
        def get_wave(fname):
            with open(fname, 'rb') as infile:
                return base64.b64encode(infile.read()).decode('utf-8')
        url = 'https://snowboy.kitt.ai/api/v1/train/'
        data = {
            "name": "xiaobu",
            "language": "zh",
            "token": config.get('snowboy_token', '', True),
            "voice_samples": [
                {"wave": get_wave(w1)},
                {"wave": get_wave(w2)},
                {"wave": get_wave(w3)}
            ]
        }
        response = requests.post(url, json=data)
        if response.ok:
            with open(m, "wb") as outfile:
                outfile.write(response.content)
            return 'Snowboy模型已保存至{}'.format(m)
        else:
            return "Snowboy模型生成失败,原因:{}".format(response.text)
Beispiel #20
0
class Wukong(object):

    _profiling = False
    _dev = False

    def init(self):
        global conversation
        self.detector = None
        self._thinking = False
        self._interrupted = False
        print("""
********************************************************
*          wukong-robot - 中文语音对话机器人           *
*          (c) 2019 潘伟洲 <*****@*****.**>              *
*     https://github.com/wzpan/wukong-robot.git        *
********************************************************

            后台管理端:http://{}:{}
            如需退出,可以按 Ctrl-4 组合键

""".format(
            config.get("/server/host", "0.0.0.0"),
            config.get("/server/port", "5001"),
        ))
        config.init()
        self._conversation = Conversation(self._profiling)
        self._conversation.say(
            "{} 你好!试试对我喊唤醒词叫醒我吧".format(config.get("first_name", "主人")), True)
        self._observer = Observer()
        event_handler = ConfigMonitor(self._conversation)
        self._observer.schedule(event_handler, constants.CONFIG_PATH, False)
        self._observer.schedule(event_handler, constants.DATA_PATH, False)
        self._observer.start()
        if config.get("/LED/enable",
                      False) and config.get("/LED/type") == "aiy":
            thread.start_new_thread(self._init_aiy_button_event, ())
        if config.get("/muse/enable", False):
            self._wakeup = multiprocessing.Event()
            self.bci = BCI.MuseBCI(self._wakeup)
            self.bci.start()
            thread.start_new_thread(self._loop_event, ())

    def _loop_event(self):
        while True:
            self._wakeup.wait()
            self._conversation.interrupt()
            query = self._conversation.activeListen()
            self._conversation.doResponse(query)
            self._wakeup.clear()

    def _signal_handler(self, signal, frame):
        self._interrupted = True
        utils.clean()
        self._observer.stop()

    def _detected_callback(self):
        def start_record():
            logger.info("开始录音")
            self._conversation.isRecording = True
            utils.setRecordable(True)

        if not utils.is_proper_time():
            logger.warning("勿扰模式开启中")
            return
        if self._conversation.isRecording:
            logger.warning("正在录音中,跳过")
            return
        self._conversation.interrupt()
        if config.get("/LED/enable", False):
            LED.wakeup()
        utils.setRecordable(False)
        Player.play(constants.getData("beep_hi.wav"),
                    onCompleted=start_record,
                    wait=True)

    def _do_not_bother_on_callback(self):
        if config.get("/do_not_bother/hotword_switch", False):
            self.switch_on_do_not_bother()

    def _do_not_bother_off_callback(self):
        if config.get("/do_not_bother/hotword_switch", False):
            self.switch_off_do_not_bother()

    def _interrupt_callback(self):
        return self._interrupted

    def _init_aiy_button_event(self):
        from aiy.board import Board

        with Board() as board:
            while True:
                board.button.wait_for_press()
                self._conversation.interrupt()
                query = self._conversation.activeListen()
                self._conversation.doResponse(query)

    def run(self):
        self.init()

        # capture SIGINT signal, e.g., Ctrl+C
        signal.signal(signal.SIGINT, self._signal_handler)

        # site
        server.run(self._conversation, self)

        statistic.report(0)

        try:
            self.initDetector()
        except AttributeError:
            logger.error("初始化离线唤醒功能失败")
            pass

    def initDetector(self):
        if self.detector is not None:
            self.detector.terminate()
        if config.get("/do_not_bother/hotword_switch", False):
            models = [
                constants.getHotwordModel(config.get("hotword",
                                                     "wukong.pmdl")),
                constants.getHotwordModel(
                    utils.get_do_not_bother_on_hotword()),
                constants.getHotwordModel(
                    utils.get_do_not_bother_off_hotword()),
            ]
        else:
            models = constants.getHotwordModel(
                config.get("hotword", "wukong.pmdl"))
        self.detector = snowboydecoder.HotwordDetector(models,
                                                       sensitivity=config.get(
                                                           "sensitivity", 0.5))
        # main loop
        try:
            if config.get("/do_not_bother/hotword_switch", False):
                callbacks = [
                    self._detected_callback,
                    self._do_not_bother_on_callback,
                    self._do_not_bother_off_callback,
                ]
            else:
                callbacks = self._detected_callback
            self.detector.start(
                detected_callback=callbacks,
                audio_recorder_callback=self._conversation.converse,
                interrupt_check=self._interrupt_callback,
                silent_count_threshold=config.get("silent_threshold", 15),
                recording_timeout=config.get("recording_timeout", 5) * 4,
                sleep_time=0.03,
            )
            self.detector.terminate()
        except Exception as e:
            logger.critical("离线唤醒机制初始化失败:{}".format(e))

    def help(self):
        print(
            """=====================================================================================
    python3 wukong.py [命令]
    可选命令:
      md5                      - 用于计算字符串的 md5 值,常用于密码设置
      update                   - 手动更新 wukong-robot
      upload [thredNum]        - 手动上传 QA 集语料,重建 solr 索引。
                                 threadNum 表示上传时开启的线程数(可选。默认值为 10)
      profiling                - 运行过程中打印耗时数据
    如需更多帮助,请访问:https://wukong.hahack.com/#/run
====================================================================================="""
        )

    def md5(self, password):
        """
        计算字符串的 md5 值
        """
        return hashlib.md5(str(password).encode("utf-8")).hexdigest()

    def update(self):
        """
        更新 wukong-robot
        """
        updater = Updater()
        return updater.update()

    def fetch(self):
        """
        检测 wukong-robot 的更新
        """
        updater = Updater()
        updater.fetch()

    def upload(self, threadNum=10):
        """
        手动上传 QA 集语料,重建 solr 索引
        """
        try:
            qaJson = os.path.join(constants.TEMP_PATH, "qa_json")
            make_json.run(constants.getQAPath(), qaJson)
            solr_tools.clear_documents(
                config.get("/anyq/host", "0.0.0.0"),
                "collection1",
                config.get("/anyq/solr_port", "8900"),
            )
            solr_tools.upload_documents(
                config.get("/anyq/host", "0.0.0.0"),
                "collection1",
                config.get("/anyq/solr_port", "8900"),
                qaJson,
                threadNum,
            )
        except Exception as e:
            logger.error("上传失败:{}".format(e))

    def restart(self):
        """
        重启 wukong-robot
        """
        logger.critical("程序重启...")
        try:
            self.detector.terminate()
        except AttributeError:
            pass
        python = sys.executable
        os.execl(python, python, *sys.argv)

    def switch_on_do_not_bother(self):
        """
        打开勿扰模式
        """
        utils.do_not_bother = True
        Player.play(constants.getData("off.wav"))
        logger.info("勿扰模式打开")

    def switch_off_do_not_bother(self):
        """
        关闭勿扰模式
        """
        utils.do_not_bother = False
        Player.play(constants.getData("on.wav"))
        logger.info("勿扰模式关闭")

    def profiling(self):
        """
        运行过程中打印耗时数据
        """
        logger.info("性能调优")
        self._profiling = True
        self.run()

    def dev(self):
        logger.info("使用测试环境")
        self._dev = True
        self.run()