コード例 #1
0
 def run(self):
     if not TTS.support(self._provider) :
         self.log(F('Неизвестный провайдер: {}', self._provider), logger.CRIT)
         self._file_path = self.cfg.path['tts_error']
         return self._unlock()
     msg = F('{} за {}{}: {}', *self._generating(), self._file_path)
     self.log(msg, logger.DEBUG if self._realtime else logger.INFO)
コード例 #2
0
    def rec_compile(self, model, username):
        if not self.cfg.detector.ALLOW_TRAINING:
            msg = F('{} не поддерживает тренировку моделей.',
                    self.cfg.detector)
            self.own.say(msg)
            self.log(msg, logger.WARN)
            return

        self._send_notify('model_compile', True)
        samples = []
        samples_miss = []
        for num in range(1, self.cfg.detector.SAMPLES_COUNT + 1):
            sample_path = self.cfg.path_to_sample(model, num)
            if not os.path.isfile(sample_path):
                samples_miss.append('{}.wav'.format(num))
            else:
                samples.append(sample_path)
        if len(samples) >= self.cfg.detector.SAMPLES_TRAINING:
            username = username if len(username) > 1 else None
            self._compile_model(model, samples, username)
        else:
            split, more = 4, ''
            if len(samples_miss) > 4:
                split, more = 3, F(' и еще {}', len(samples_miss) - 3)
            path = os.path.join(self.cfg.path['samples'], model)
            samples_miss = '{}{}'.format(', '.join(samples_miss[:split]), more)
            self.log(
                F('Ошибка компиляции - файлы {} не найдены в {}.',
                  samples_miss, path), logger.ERROR)
            self.own.say(F('Ошибка компиляции - файлы не найдены.'))
        self._send_notify('model_compile', False)
コード例 #3
0
    def _generating(self):
        sha1 = hashlib.sha1(self._msg.encode()).hexdigest()
        ext = 'opus' if self.cfg.yandex_api(self._provider) in (2, 3) else 'mp3'
        find_part = ''.join(('_', sha1, '.'))
        rname = find_part + ext
        use_cache = self.cfg.gt('cache', 'tts_size', 50) > 0
        msg_gen = '\'{}\' '.format(self._msg)

        if self._realtime:
            self.log('say {}'.format(msg_gen), logger.INFO)
            msg_gen = ''

        if use_cache and self._found_in_cache(find_part, ext):
            self._unlock()
            work_time = time.time() - self._start_time
            action = F('{}найдено в кэше', msg_gen)
            time_diff = ''
        else:
            if not use_cache and self._provider in ('rhvoice-rest', 'rhvoice'):
                ext = 'wav'
                self._buff_size *= 4
            self._file_path = os.path.join(self.cfg.gt('cache', 'path'), self._provider + rname) if use_cache else \
                '<{}><{}>'.format(sha1, ext)
            self._tts_gen(self._file_path if use_cache else None, ext, self._msg)
            self._unlock()
            work_time = time.time() - self._start_time
            action = F('{}сгенерированно {}', msg_gen, self._provider)
            reply = utils.pretty_time(self._work_time)
            diff = utils.pretty_time(work_time - self._work_time)
            time_diff = ' [reply:{}, diff:{}]'.format(reply, diff)
        return action, utils.pretty_time(work_time), time_diff
コード例 #4
0
    def models_load(self):
        def lower_warning():
            if self.detector.FAKE_MODELS:
                return
            l_name_ = file.lower()
            if l_name_ != file:
                msg_ = 'Please, rename {} to {} in {} for stability!'.format(
                    repr(file), repr(l_name_), self.path['models'])
                self.log(msg_, logger.WARN)

        models, paths, msg = [], [], None
        if self.detector.NO_MODELS:
            pass
        elif not (os.path.isdir(self.path['models'])
                  or self.detector.FAKE_MODELS):
            msg = F('Директория с моделями не найдена {}', self.path['models'])
        else:
            allow = self.get_allow_models()
            for file in self.get_all_models():
                full_path = file if self.detector.FAKE_MODELS else os.path.join(
                    self.path['models'], file)
                if self.detector.FAKE_MODELS or os.path.isfile(full_path):
                    lower_warning()
                    if not allow or file in allow:
                        paths.append(full_path)
                        models.append(file)

        self.models = ModelsStorage(paths,
                                    self['models'],
                                    models,
                                    no_models=self.detector.NO_MODELS)
        msg = msg or F('Загружено {} моделей', len(self.models))
        self.log(msg, logger.INFO)
        self.own.say_info(msg)
コード例 #5
0
    def _external_check(self):
        while self._queue.qsize() and self.work:
            try:
                (cmd, data, lvl, late) = self._queue.get_nowait()
            except queue.Empty:
                self.log(F('Пустая очередь? Impossible!'), logger.ERROR)
                continue
            if late:
                late = time.time() - late
            msg = F('Получено {}:{}, lvl={} опоздание {} секунд.', cmd,
                    repr(data)[:300], lvl, int(late))
            if late > self.MAX_LATE:
                self.log(F('{} Игнорирую.', msg), logger.WARN)
                continue
            else:
                self.log(msg, logger.DEBUG)

            if cmd == 'tts':
                self.own.say(data, lvl=lvl)
            elif cmd == 'ask' and data:
                self._detected_parse(True, *self.own.listen(data))
            elif cmd == 'voice' and not data:
                self._detected_parse(False, *self.own.listen(voice=True))
            elif cmd in self.DATA_CALL:
                self.DATA_CALL[cmd](data)
            elif cmd in self.ARGS_CALL:
                self.ARGS_CALL[cmd](*data)
            else:
                self.log(
                    F('Не верный вызов, WTF? {}:{}, lvl={}', cmd,
                      repr(data)[:300], lvl), logger.ERROR)
コード例 #6
0
def majordomo(self, _, phrase):
    if not phrase:
        self.log(F('Вы ничего не сказали?'), logger.DEBUG)
        return

    if not self.own.has_subscribers('cmd'):
        if not self.cfg['smarthome']['ip']:
            self.log(F('IP сервера не задан.'), logger.CRIT)
            return Say(
                F('IP сервера не задан, исправьте это! Мой IP адрес: {}',
                  self.cfg.gts('ip')))
        else:
            msg = F('Невозможно доставить - маршрут не найден')
            self.log(msg, logger.CRIT)
            return Say(msg)

    # FIX: 'Скажи ' -> 'скажи '
    if phrase.startswith(F('Скажи ')):
        phrase = phrase[0].lower() + phrase[1:]

    kwargs = {'qry': phrase}
    if self.model:
        kwargs['username'] = self.cfg.gt('persons', self.model)
    if self.rms:
        kwargs.update(zip(('rms_min', 'rms_max', 'rms_avg'), self.rms))
    self.own.send_notify('cmd', **kwargs)
コード例 #7
0
def lock(self, phrase, *_):
    if self.get_one_way is lock:
        if phrase == F('блокировка'):
            return Set(one_way=None), Say(F('Блокировка снята'))
        else:
            return Say(F('блокировка'))
    else:
        return Set(one_way=lock), Say(F('Блокировка включена'))
コード例 #8
0
def debug(_, phrase, *__):
    if phrase == F('выход'):
        return Set(debug=False), Say(
            F('Внимание! Выход из режима разработчика'))
    elif phrase == F('режим разработчика'):
        msg = 'Внимание! Включён режим разработчика. Для возврата в обычный режим скажите \'выход\''
        return Set(debug=True), Say(F(msg))
    return Next
コード例 #9
0
 def _detected(self, model_name, phrase, msg, cb):
     self.own.voice_activated_callback()
     no_hello = self.cfg.gts('no_hello')
     hello = ''
     if phrase and self.own.sys_say_chance and not no_hello:
         hello = F('{} слушает', phrase)
     self.log(F('Голосовая активация по {}{}', model_name, msg), logger.INFO)
     cb(hello, *self.own.listen(hello, voice=no_hello), model_name)
コード例 #10
0
 def rec_play(self, model, sample):
     file = self.cfg.path_to_sample(model, sample)
     if os.path.isfile(file):
         self.own.say(file, is_file=True)
     else:
         self.own.say(
             F('Ошибка воспроизведения - файл {} не найден',
               '{}.wav'.format(sample)))
         self.log(F('Файл {} не найден.', file), logger.WARN)
コード例 #11
0
ファイル: updater.py プロジェクト: georgsp/mdmTerminal2
 def _up_dependency(self, name: str, updater):
     to_update = self.cfg.gt('update', name)
     packages = updater(to_update)
     if packages:
         msg = F('Зависимости {} {}обновлены: {}').format(
             name, '' if to_update else F('не '), packages)
         event = '{}_{}'.format(name, 'yes' if to_update else 'no')
         self._notify_update(event)
         self.log(msg, logger.DEBUG if to_update else logger.WARN)
コード例 #12
0
 def lang_init(self):
     lang = self.gts('lang')
     err = languages.set_lang(lang, self.gts('lang_check'))
     if err:
         self.log(F('Ошибка инициализации языка {}: {}', repr(lang), err),
                  logger.ERROR)
     msg = F('Локализация {} загружена за {}', lang,
             utils.pretty_time(languages.set_lang.load_time))
     self.log(msg, logger.INFO)
コード例 #13
0
ファイル: backup.py プロジェクト: xjhsxjh/mdmTerminal2
 def _remove_candidates(self, files: list):
     for file in files:
         path = os.path.join(self.cfg.path['backups'], file)
         try:
             os.remove(path)
         except OSError as e:
             self.log(F('Ошибка удаления старого бэкапа {}: {}', file, e),
                      logger.WARN)
         else:
             self.log(F('Удален старый бэкап {}', file))
コード例 #14
0
 def get_mic_index(self):
     device_index = self.cfg.gts('mic_index', -1)
     if device_index > self.max_mic_index:
         if self.max_mic_index >= 0:
             mics = F('Доступны {}, от 0 до {}.', self.max_mic_index + 1, self.max_mic_index)
         else:
             mics = F('Микрофоны не найдены')
         self.log(F('Не верный индекс микрофона {}. {}', device_index, mics), logger.WARN)
         return None
     return None if device_index < 0 else device_index
コード例 #15
0
def __now_i_set_emo(self, key):
    if key == self.cfg.get('emotion', 'unset'):
        return Say(F('Я уже {}.', YANDEX_EMOTION[key]))

    self.cfg['yandex']['emotion'] = key
    self.cfg.config_save()
    return Say(
        F(
            'Теперь я очень {} {}.', YANDEX_EMOTION[key],
            YANDEX_SPEAKER.get(self.cfg['yandex'].get('speaker', 'unset'),
                               F('Ошибка'))))
コード例 #16
0
def __now_i_set_speaker(self, key, prov: dict, speakers: dict, yandex=False):
    if key == prov.get('speaker', 'unset'):
        return Say(F('Я уже {}.', speakers[key]))

    prov['speaker'] = key
    self.cfg.config_save()
    return Say(
        F(
            'Теперь меня зовут {}, а еще я {}.', speakers[key],
            YANDEX_EMOTION.get(self.cfg['yandex'].get('emotion', 'unset'),
                               F('Ошибка')) if yandex else F('без характера')))
コード例 #17
0
 def load_dict(self, name: str, format_='json') -> dict or None:
     file_path = os.path.join(self.path['data'],
                              name + DATA_FORMATS.get(format_, '.json'))
     if not os.path.isfile(file_path):
         self.log(F('Файл не найден (это нормально): {}', file_path))
         return None
     try:
         return utils.dict_from_file(file_path)
     except RuntimeError as e:
         self.log(F('Ошибка загрузки {}: {}', file_path, str(e)),
                  logger.ERROR)
         return None
コード例 #18
0
 def voice_record(self, hello: str or None, save_to: str, convert_rate=None, convert_width=None, limit=8):
     if self.max_mic_index == -2:
         self.log(F('Микрофоны не найдены'), logger.ERROR)
         return F('Микрофоны не найдены')
     self._lock.acquire()
     self._start_stt_event()
     try:
         return self._voice_record(hello, save_to, convert_rate, convert_width, limit)
     finally:
         self.own.clear_lvl()
         self._stop_stt_event()
         self._lock.release()
コード例 #19
0
 def _send_cmd(self, kwargs: dict):
     username = kwargs.pop('username', None)
     try:
         self.log(
             F('Запрос был успешен: {}',
               self._send('cmd', kwargs, username)), logger.DEBUG)
     except RuntimeError as e:
         self._skip.got_error()
         e = '[{}] {}'.format(self.own.srv_ip, e)
         self.log(F('Ошибка коммуникации с сервером: {}', e), logger.ERROR)
         self.own.say(F('Ошибка коммуникации с сервером: {}', ''))
     else:
         self._skip.clear()
コード例 #20
0
ファイル: backup.py プロジェクト: xjhsxjh/mdmTerminal2
 def _check_file(self, filename: str) -> tuple:
     if self.work:
         return F('Демон еще работает'), None
     if not utils.is_valid_base_filename(filename):
         return F('Некорректное имя файла: {}', repr(filename)), None
     path = os.path.join(self.cfg.path['backups'], filename)
     if not os.path.isfile(path):
         return F('Файл не найден: {}', path), None
     try:
         self._get_zip_timestamp(path)
     except Exception as e:
         return F('Архив поврежден: {}: {}', filename, e), None
     return None, path
コード例 #21
0
ファイル: server.py プロジェクト: georgsp/mdmTerminal2
 def _open_socket(self) -> bool:
     self._socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
     self._socket.settimeout(1)
     try:
         self._socket.bind(self._local)
     except OSError as e:
         say = F('Ошибка запуска сервера{}.',
                 F(' - адрес уже используется') if e.errno == 98 else '')
         self.log(F('Ошибка запуска сервера на {}:{}: {}', *self._local, e),
                  logger_.CRIT)
         self.own.say(say)
         return False
     self._socket.listen(1)
     return True
コード例 #22
0
    def _config_save(self):
        wtime = time.time()

        config = ConfigParserOnOff()
        for key, val in self.items():
            if isinstance(val, dict):
                config[key] = val

        with open(self.path['settings'], 'w', encoding='utf8') as configfile:
            config.write(configfile)
        self.log(
            F('Конфигурация сохранена за {}',
              utils.pretty_time(time.time() - wtime)), logger.INFO)
        self.own.say_info(F('Конфигурация сохранена!'))
コード例 #23
0
 def _print_info(self):
     active, inactive, disable = [], [], []
     for module in self.all.values():
         if not module['enable']:
             disable.append(module['name'])
         elif module['mode'] in (NM, ANY):
             active.append(module['name'])
         else:
             inactive.append(module['name'])
     if disable:
         self._log(F('Отключенные модули: {}', ', '.join(disable)))
     if inactive:
         self._log(F('Неактивные модули: {}', ', '.join(inactive)))
     if active:
         self._log(F('Активные модули: {}', ', '.join(active)), logger.INFO)
コード例 #24
0
 def config_load(self):
     wtime = time.time()
     if not os.path.isfile(self.path['settings']):
         msg = 'Файл настроек не найден по пути {}. Для первого запуска это нормально'
         self.log(F(msg, self.path['settings']), logger.INFO)
         return True
     updater = ConfigUpdater(self, self.log)
     count = updater.from_ini(self.path['settings'])
     wtime = time.time() - wtime
     self.lang_init()
     self.log(
         F('Загружено {} опций за {}', count, utils.pretty_time(wtime)),
         logger.INFO)
     self.own.say_info(F('Конфигурация загружена!'))
     return updater.save_ini
コード例 #25
0
def who_am_i(self, *_):
    def get_yandex_emo():
        return YANDEX_EMOTION.get(self.cfg.gt('yandex', 'emotion', 'unset'),
                                  F('Ошибка'))

    speakers = __tts_selector(self.cfg)
    if speakers is None:
        return Say(F('Не поддерживается для {}', self.cfg.gts('providertts')))

    speaker = self.cfg[self.cfg.gts('providertts')].get('speaker', 'unset')
    emotion = F(
        ' Я очень {}.',
        get_yandex_emo()) if self.cfg.gts('providertts') == 'yandex' else ''
    return Say(
        F('Меня зовут {}.{}', speakers.get(speaker, F('Ошибка')), emotion))
コード例 #26
0
ファイル: updater.py プロジェクト: georgsp/mdmTerminal2
 def _fallback(self, up, hash_=None, mode='fallback'):
     self.log(F('Выполняется откат обновления.'), logger.DEBUG)
     try:
         if hash_:
             up.set_old_hash(hash_)
         up.fallback()
     except RuntimeError as e:
         self._notify_update('{}_failed'.format(mode))
         self.log(F('Во время отката обновления возникла ошибка: {}', e),
                  logger.CRIT)
         return F('Откат невозможен.')
     else:
         self._notify_update('{}_ok'.format(mode))
         self.log(F('Откат обновления выполнен успешно.'), logger.INFO)
         return F('Выполнен откат.')
コード例 #27
0
 def _set_music_volume(self, value, quiet=False):
     if value is not None:
         try:
             value_clean = clean_volume(value)
         except RuntimeError as e:
             msg = F('Недопустимое значение: {}', value)
             self.log('{}, {}'.format(msg, e), logger.WARN)
             if not quiet:
                 self.own.say(msg)
             return
         self.own.music_real_volume = value_clean
     value = self.own.music_real_volume
     self.log(F('Громкость музыки {} процентов', value))
     if not quiet:
         self.own.say(F('Громкость музыки {} процентов', value))
コード例 #28
0
    def stop_all_systems(self):
        self._cfg.config_save(final=True)
        self.join_thread(self._plugins)
        self._mm.stop()
        self.join_thread(self._discovery)
        self.join_thread(self._server)
        self.join_thread(self._terminal)
        self.join_thread(self._backup)
        self.join_thread(self._updater)
        self.join_thread(self._notifier)
        self.join_thread(self._duplex_pool)

        self._play.quiet()
        self._play.kill_popen()
        self._play.say_info(F('Голосовой терминал завершает свою работу.'))

        self._stt.stop()
        self._play.stop()
        self.join_thread(self._music)

        if self._restore_filename:
            self._backup.restore(self._restore_filename)
            self._restore_filename = ''

        self.join_thread(self._logger.remote_log)
        self._pub.stopping = True
        self._logger.join()
        self._pub.join()

        self._pub.report()
コード例 #29
0
    def _listen(self, hello: str, voice) -> tuple:
        lvl = 5  # Включаем монопольный режим
        commands = None

        if self.cfg.gts('alarmkwactivated'):
            self.own.play(self.cfg.path['ding'], lvl, blocking=2)
        else:
            self.own.set_lvl(lvl)
            self.own.kill_popen()
        self.log('audio devices: {}'.format(pyaudio.PyAudio().get_device_count() - 1), logger.DEBUG)

        hello = hello or self.sys_say.hello
        file_path = self.own.tts(hello) if not voice and hello else None

        if self.cfg.gts('blocking_listener'):
            audio, record_time, energy, rms = self._block_listen(hello, lvl, file_path)
        else:
            audio, record_time, energy, rms = self._non_block_listen(hello, lvl, file_path)

        self.log(F('Голос записан за {}', utils.pretty_time(record_time)), logger.INFO)
        # Выключаем монопольный режим
        self.own.clear_lvl()

        if self.cfg.gts('alarmstt'):
            self.own.play(self.cfg.path['dong'])
        if audio is not None:
            commands = self.voice_recognition(audio)

        if commands:
            self.log(utils.recognition_msg(commands, energy, rms), logger.INFO)
        return commands, rms
コード例 #30
0
    def _voice_record(self, hello: str or None, save_to: str, convert_rate, convert_width, limit):
        lvl = 5  # Включаем монопольный режим

        if hello is not None:
            self.own.say(self.own.tts(hello)(), lvl, True, is_file=True, blocking=120)
        else:
            self.own.set_lvl(lvl)
        r = sr.Recognizer(record_callback=self.own.record_callback)
        mic = sr.Microphone(device_index=self.get_mic_index())
        vad = self.own.get_vad_detector(mic)
        self.own.play(self.cfg.path['ding'], lvl, blocking=3)
        with mic as source:
            record_time = time.time()
            try:
                adata = r.listen1(source=source, vad=vad, timeout=5, phrase_time_limit=limit)
            except sr.WaitTimeoutError as e:
                return str(e)
            if time.time() - record_time < 0.5:
                return F('Во время записи произошел сбой, это нужно исправить')
        try:
            os.makedirs(os.path.dirname(save_to), exist_ok=True)
            with open(save_to, "wb") as f:
                f.write(adata.get_wav_data(convert_rate, convert_width))
        except IOError as err:
            return str(err)
        else:
            return None