コード例 #1
0
 def test_keyboard_interrupt(self):
     l1 = Lock('test')
     self.assertTrue(isfile(get_temp_path('mycroft', 'test.pid')))
     try:
         os.kill(os.getpid(), signal.SIGINT)
     except KeyboardInterrupt:
         pass
     self.assertFalse(isfile(get_temp_path('mycroft', 'test.pid')))
コード例 #2
0
ファイル: test_download.py プロジェクト: mcdonc/mycroft-core
    def test_multiple_existing(self, mock_glob):
        mock_glob.return_value = [
            get_temp_path('test.part'),
            get_temp_path('test.part.1'),
            get_temp_path('test.part.2')
        ]

        dest = get_temp_path('test')
        self.assertEqual(_get_download_tmp(dest), dest + '.part.3')
コード例 #3
0
ファイル: tts.py プロジェクト: MycroftAI/mycroft-core
    def __init__(self,
                 lang,
                 config,
                 validator,
                 audio_ext='wav',
                 phonetic_spelling=True,
                 ssml_tags=None):
        super(TTS, self).__init__()
        self.bus = None  # initalized in "init" step
        self.lang = lang or 'en-us'
        self.config = config
        self.validator = validator
        self.phonetic_spelling = phonetic_spelling
        self.audio_ext = audio_ext
        self.ssml_tags = ssml_tags or []

        self.voice = config.get("voice")
        self.filename = get_temp_path('tts.wav')
        self.enclosure = None
        random.seed()
        self.queue = Queue()
        self.playback = PlaybackThread(self.queue)
        self.playback.start()
        self.spellings = self.load_spellings()
        self.tts_name = type(self).__name__
        self.cache = TextToSpeechCache(self.config, self.tts_name,
                                       self.audio_ext)
        self.cache.clear()
コード例 #4
0
 def test_existing_lock(self, mock_kill):
     """ Test that an existing lock will kill the old pid. """
     l1 = Lock('test')
     self.assertTrue(isfile(get_temp_path('mycroft', 'test.pid')))
     l2 = Lock('test2')
     self.assertFalse(mock_kill.called)
     l2 = Lock('test')
     self.assertTrue(mock_kill.called)
コード例 #5
0
def _init_msm_lock():
    msm_lock = None
    try:
        msm_lock = ComboLock(get_temp_path('mycroft-msm.lck'))
        LOG.debug('mycroft-msm combo lock instantiated')
    except Exception:
        LOG.exception('Failed to create msm lock!')

    return msm_lock
コード例 #6
0
 def test_record_without_duration(self, mock_subprocess):
     mock_proc = mock.Mock(name='mock process')
     mock_subprocess.Popen.return_value = mock_proc
     rate = 16000
     channels = 1
     filename = get_temp_path('test.wav')
     duration = 0
     res = record(filename, duration, rate, channels)
     mock_subprocess.Popen.assert_called_once_with(
         ['arecord', '-r',
          str(rate), '-c',
          str(channels), filename])
     self.assertEqual(res, mock_proc)
コード例 #7
0
ファイル: skill_updater.py プロジェクト: mcdonc/mycroft-core
    def __init__(self, bus=None):
        self.msm_lock = ComboLock(get_temp_path('mycroft-msm.lck'))
        self.install_retries = 0
        self.config = Configuration.get()
        update_interval = self.config['skills']['update_interval']
        self.update_interval = int(update_interval) * ONE_HOUR
        self.dot_msm_path = os.path.join(self.msm.skills_dir, '.msm')
        self.next_download = self._determine_next_download_time()
        self._log_next_download_time()
        self.installed_skills = set()
        self.default_skill_install_error = False

        if bus:
            self._register_bus_handlers()
コード例 #8
0
ファイル: config.py プロジェクト: MycroftAI/mycroft-core
class RemoteConf(LocalConf):
    _lock = ComboLock(get_temp_path('remote-conf.lock'))
    """Config dictionary fetched from mycroft.ai."""
    def __init__(self, cache=None):
        super(RemoteConf, self).__init__(None)

        cache = cache or join(xdg.BaseDirectory.xdg_cache_home, 'mycroft',
                              'web_cache.json')
        from mycroft.api import is_paired
        if not is_paired():
            self.load_local(cache)
            return

        try:
            # Here to avoid cyclic import
            from mycroft.api import DeviceApi
            api = DeviceApi()
            setting = api.get_settings()

            location = None
            try:
                location = api.get_location()
            except RequestException as e:
                LOG.error(
                    "RequestException fetching remote location: {}".format(
                        str(e)))
                if exists(cache) and isfile(cache):
                    location = load_commented_json(cache).get('location')

            if location:
                setting["location"] = location
            # Remove server specific entries
            config = {}
            translate_remote(config, setting)
            for key in config:
                self.__setitem__(key, config[key])
            self.store(cache)

        except RequestException as e:
            LOG.error(
                "RequestException fetching remote configuration: {}".format(
                    str(e)))
            self.load_local(cache)

        except Exception as e:
            LOG.error("Failed to fetch remote configuration: %s" % repr(e),
                      exc_info=True)
            self.load_local(cache)
コード例 #9
0
ファイル: config.py プロジェクト: MycroftAI/mycroft-core
class LocalConf(dict):
    """Config dictionary from file."""
    _lock = ComboLock(get_temp_path('local-conf.lock'))

    def __init__(self, path):
        super(LocalConf, self).__init__()
        if path:
            self.path = path
            self.load_local(path)

    def load_local(self, path):
        """Load local json file into self.

        Args:
            path (str): file to load
        """
        if exists(path) and isfile(path):
            try:
                config = load_commented_json(path)
                for key in config:
                    self.__setitem__(key, config[key])

                LOG.debug("Configuration {} loaded".format(path))
            except Exception as e:
                LOG.error("Error loading configuration '{}'".format(path))
                LOG.error(repr(e))
        else:
            LOG.debug("Configuration '{}' not defined, skipping".format(path))

    def store(self, path=None):
        """Cache the received settings locally.

        The cache will be used if the remote is unreachable to load settings
        that are as close to the user's as possible.
        """
        with self._lock:
            path = path or self.path
            config_dir = dirname(path)
            if not exists(config_dir):
                os.makedirs(config_dir)

            with open(path, 'w') as f:
                json.dump(self, f, indent=2)

    def merge(self, conf):
        merge_dict(self, conf)
コード例 #10
0
ファイル: test_download.py プロジェクト: mcdonc/mycroft-core
 def test_no_existing(self, mock_glob):
     mock_glob.return_value = []
     dest = get_temp_path('test')
     self.assertEqual(_get_download_tmp(dest), dest + '.part')
コード例 #11
0
ファイル: test_download.py プロジェクト: mcdonc/mycroft-core
from threading import Event
from unittest import TestCase, mock

from mycroft.util.download import (download, _running_downloads,
                                   _get_download_tmp)
from mycroft.util.file_utils import get_temp_path

TEST_URL = 'http://example.com/mycroft-test.tar.gz'
TEST_DEST = get_temp_path('file.tar.gz')


@mock.patch('mycroft.util.download.subprocess')
@mock.patch('mycroft.util.download.os')
class TestDownload(TestCase):
    def setUp(self):
        """Remove any cached instance."""
        for key in list(_running_downloads.keys()):
            _running_downloads.pop(key)

    def test_download_basic(self, mock_os, mock_subprocess):
        """Test the basic download call."""
        mock_subprocess.call.return_value = 0

        downloader = download(url=TEST_URL, dest=TEST_DEST)
        downloader.join()
        mock_subprocess.call.assert_called_once_with([
            'wget', '-c', TEST_URL, '-O', TEST_DEST + '.part', '--tries=20',
            '--read-timeout=5'
        ])
        self.assertTrue(downloader.done)
コード例 #12
0
ファイル: __init__.py プロジェクト: mcdonc/mycroft-core
    def process(self, data):
        # TODO: Look into removing this emit altogether.
        # We need to check if any other serial bus messages
        # are handled by other parts of the code
        if "mycroft.stop" not in data:
            self.bus.emit(Message(data))

        if "Command: system.version" in data:
            # This happens in response to the "system.version" message
            # sent during the construction of Enclosure()
            self.bus.emit(Message("enclosure.started"))

        if "mycroft.stop" in data:
            if has_been_paired():
                create_signal('buttonPress')
                self.bus.emit(Message("mycroft.stop"))

        if "volume.up" in data:
            self.bus.emit(
                Message("mycroft.volume.increase", {'play_sound': True}))

        if "volume.down" in data:
            self.bus.emit(
                Message("mycroft.volume.decrease", {'play_sound': True}))

        if "system.test.begin" in data:
            self.bus.emit(Message('recognizer_loop:sleep'))

        if "system.test.end" in data:
            self.bus.emit(Message('recognizer_loop:wake_up'))

        if "mic.test" in data:
            mixer = Mixer()
            prev_vol = mixer.getvolume()[0]
            mixer.setvolume(35)
            self.bus.emit(
                Message("speak", {'utterance': "I am testing one two three"}))

            time.sleep(0.5)  # Prevents recording the loud button press
            record(get_temp_path('test.wav', 3.0))
            mixer.setvolume(prev_vol)
            play_wav(get_temp_path('test.wav')).communicate()

            # Test audio muting on arduino
            subprocess.call('speaker-test -P 10 -l 0 -s 1', shell=True)

        if "unit.shutdown" in data:
            # Eyes to soft gray on shutdown
            self.bus.emit(
                Message("enclosure.eyes.color", {
                    'r': 70,
                    'g': 65,
                    'b': 69
                }))
            self.bus.emit(
                Message("enclosure.eyes.timedspin", {'length': 12000}))
            self.bus.emit(Message("enclosure.mouth.reset"))
            time.sleep(0.5)  # give the system time to pass the message
            self.bus.emit(Message("system.shutdown"))

        if "unit.reboot" in data:
            # Eyes to soft gray on reboot
            self.bus.emit(
                Message("enclosure.eyes.color", {
                    'r': 70,
                    'g': 65,
                    'b': 69
                }))
            self.bus.emit(Message("enclosure.eyes.spin"))
            self.bus.emit(Message("enclosure.mouth.reset"))
            time.sleep(0.5)  # give the system time to pass the message
            self.bus.emit(Message("system.reboot"))

        if "unit.setwifi" in data:
            self.bus.emit(Message("system.wifi.setup", {'lang': self.lang}))

        if "unit.factory-reset" in data:
            self.bus.emit(
                Message("speak", {
                    'utterance':
                    mycroft.dialog.get("reset to factory defaults")
                }))
            subprocess.call('rm ~/.mycroft/identity/identity2.json',
                            shell=True)
            self.bus.emit(Message("system.wifi.reset"))
            self.bus.emit(Message("system.ssh.disable"))
            wait_while_speaking()
            self.bus.emit(Message("enclosure.mouth.reset"))
            self.bus.emit(Message("enclosure.eyes.spin"))
            self.bus.emit(Message("enclosure.mouth.reset"))
            time.sleep(5)  # give the system time to process all messages
            self.bus.emit(Message("system.reboot"))

        if "unit.enable-ssh" in data:
            # This is handled by the wifi client
            self.bus.emit(Message("system.ssh.enable"))
            self.bus.emit(
                Message("speak",
                        {'utterance': mycroft.dialog.get("ssh enabled")}))

        if "unit.disable-ssh" in data:
            # This is handled by the wifi client
            self.bus.emit(Message("system.ssh.disable"))
            self.bus.emit(
                Message("speak",
                        {'utterance': mycroft.dialog.get("ssh disabled")}))

        if "unit.enable-learning" in data or "unit.disable-learning" in data:
            enable = 'enable' in data
            word = 'enabled' if enable else 'disabled'

            LOG.info("Setting opt_in to: " + word)
            new_config = {'opt_in': enable}
            user_config = LocalConf(USER_CONFIG)
            user_config.merge(new_config)
            user_config.store()

            self.bus.emit(
                Message("speak",
                        {'utterance': mycroft.dialog.get("learning " + word)}))
コード例 #13
0
 def test_delete_lock(self):
     l1 = Lock('test')
     self.assertTrue(isfile(get_temp_path('mycroft', 'test.pid')))
     l1.delete()
     self.assertFalse(isfile(get_temp_path('mycroft', 'test.pid')))
コード例 #14
0
 def test_create_lock(self):
     l1 = Lock('test')
     self.assertTrue(isfile(get_temp_path('mycroft', 'test.pid')))
コード例 #15
0
 def setUp(self):
     if exists(get_temp_path('mycroft')):
         rmtree(get_temp_path('mycroft'))
コード例 #16
0
ファイル: audio_test.py プロジェクト: mcdonc/mycroft-core
def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('-f',
                        '--filename',
                        dest='filename',
                        default=get_temp_path('test.wav'),
                        help="Filename for saved audio (Default:{}".format(
                            get_temp_path('test.wav')))
    parser.add_argument('-d',
                        '--duration',
                        dest='duration',
                        type=int,
                        default=10,
                        help="Duration of recording in seconds (Default: 10)")
    parser.add_argument('-v',
                        '--verbose',
                        dest='verbose',
                        action='store_true',
                        default=False,
                        help="Add extra output regarding the recording")
    parser.add_argument('-l',
                        '--list',
                        dest='show_devices',
                        action='store_true',
                        default=False,
                        help="List all availabile input devices")
    args = parser.parse_args()

    if args.show_devices:
        print(" Initializing... ")
        pa = pyaudio.PyAudio()

        print(" ====================== Audio Devices ======================")
        print("  Index    Device Name")
        for device_index in range(pa.get_device_count()):
            dev = pa.get_device_info_by_index(device_index)
            if dev['maxInputChannels'] > 0:
                print('   {}:       {}'.format(device_index, dev['name']))
        print()

    config = Configuration.get()
    if "device_name" in config["listener"]:
        dev = config["listener"]["device_name"]
    elif "device_index" in config["listener"]:
        dev = "Device at index {}".format(config["listener"]["device_index"])
    else:
        dev = "Default device"
    samplerate = config["listener"]["sample_rate"]
    play_cmd = config["play_wav_cmdline"].replace("%1", "WAV_FILE")
    print(" ========================== Info ===========================")
    print(" Input device: {} @ Sample rate: {} Hz".format(dev, samplerate))
    print(" Playback commandline: {}".format(play_cmd))
    print()
    print(" ===========================================================")
    print(" ==         STARTING TO RECORD, MAKE SOME NOISE!          ==")
    print(" ===========================================================")

    if not args.verbose:
        with mute_output():
            record(args.filename, args.duration)
    else:
        record(args.filename, args.duration)

    print(" ===========================================================")
    print(" ==           DONE RECORDING, PLAYING BACK...             ==")
    print(" ===========================================================")
    status = play_wav(args.filename).wait()
    if status:
        print('An error occured while playing back audio ({})'.format(status))
コード例 #17
0
class Lock:  # python 3+ 'class Lock'
    """
    Create and maintains the PID lock file for this application process.
    The PID lock file is located in /tmp/mycroft/*.pid.  If another process
    of the same type is started, this class will 'attempt' to stop the
    previously running process and then change the process ID in the lock file.
    """

    #
    # Class constants
    DIRECTORY = get_temp_path('mycroft')
    FILE = '/{}.pid'

    #
    # Constructor
    def __init__(self, service):
        """
        Builds the instance of this object.  Holds the lock until the
        object is garbage collected.

        service: Text string.  The name of the service application
        to be locked (ie: skills, voice)
        """
        super(Lock, self).__init__()  # python 3+ 'super().__init__()'
        self.__pid = os.getpid()  # PID of this application
        self.path = Lock.DIRECTORY + Lock.FILE.format(service)
        self.set_handlers()  # set signal handlers
        self.create()

    #
    # Reset the signal handlers to the 'delete' function
    def set_handlers(self):
        """
        Trap both SIGINT and SIGTERM to gracefully clean up PID files
        """
        self.__handlers = {
            SIGINT: Signal(SIGINT, self.delete),
            SIGTERM: Signal(SIGTERM, self.delete)
        }

    #
    # Check to see if the PID already exists
    #  If it does exits perform several things:
    #    Stop the current process
    #    Delete the exiting file
    def exists(self):
        """
        Check if the PID lock file exists.  If it does
        then send a SIGKILL signal to the process defined by the value
        in the lock file.  Catch the keyboard interrupt exception to
        prevent propagation if stopped by use of Ctrl-C.
        """
        if not os.path.isfile(self.path):
            return
        with open(self.path, 'r') as L:
            try:
                os.kill(int(L.read()), SIGKILL)
            except Exception as E:
                pass

    #
    # Create a lock file for this server process
    def touch(self):
        """
        If needed, create the '/tmp/mycroft' directory than open the
        lock file for writting and store the current process ID (PID)
        as text.
        """
        if not os.path.exists(Lock.DIRECTORY):
            os.makedirs(Lock.DIRECTORY)
        with open(self.path, 'w') as L:
            L.write('{}'.format(self.__pid))

    #
    # Create the PID file
    def create(self):
        """
        Checks to see if a lock file for this service already exists,
        if so have it killed.  In either case write the process ID of
        the current service process to to the existing or newly created
        lock file in /tmp/mycroft/
        """
        self.exists()  # check for current running process
        self.touch()

    #
    # Delete the PID file - but only if it has not been overwritten
    # by a duplicate service application
    def delete(self, *args):
        """
        If the PID lock file contains the PID of this process delete it.

        *args: Ignored.  Required as this fuction is called as a signel
        handler.
        """
        try:
            with open(self.path, 'r') as L:
                pid = int(L.read())
                if self.__pid == pid:
                    os.unlink(self.path)
        except IOError:
            pass