Exemple #1
0
    def _hack_check_for_duplicates(self):
        # TEMPORARY HACK:  Look for multiple instance of the
        # OwO-speech-client and/or OwO-skills services, which could
        # happen when upgrading a shipping Mark 1 from release 0.8.17 or
        # before.  When found, force the unit to reboot.
        import psutil

        LOG.info("Hack to check for duplicate service instances")

        count_instances = 0
        needs_reboot = False
        for process in psutil.process_iter():
            if process.cmdline() == ['python2.7',
                                     '/usr/local/bin/OwO-speech-client']:
                count_instances += 1
        if (count_instances > 1):
            LOG.info("Duplicate OwO-speech-client found")
            needs_reboot = True

        count_instances = 0
        for process in psutil.process_iter():
            if process.cmdline() == ['python2.7',
                                     '/usr/local/bin/OwO-skills']:
                count_instances += 1
        if (count_instances > 1):
            LOG.info("Duplicate OwO-skills found")
            needs_reboot = True

        if needs_reboot:
            LOG.info("Hack reboot...")
            self.reader.process("unit.reboot")
            self.bus.emit(Message("enclosure.eyes.spin"))
            self.bus.emit(Message("enclosure.mouth.reset"))
Exemple #2
0
    def _do_net_check(self):
        # TODO: This should live in the derived Enclosure, e.g. Enclosure_Mark1
        LOG.info("Checking internet connection")
        if not connected():  # and self.conn_monitor is None:
            if has_been_paired():
                # TODO: Enclosure/localization
                self.speak("This unit is not connected to the Internet. "
                           "Either plug in a network cable or hold the "
                           "button on top for two seconds, then select "
                           "wifi from the menu")
            else:
                # Begin the unit startup process, this is the first time it
                # is being run with factory defaults.

                # TODO: This logic should be in Enclosure_Mark1
                # TODO: Enclosure/localization

                # Don't listen to mic during this out-of-box experience
                self.bus.emit(Message("owo.mic.mute"))
                # Setup handler to unmute mic at the end of on boarding
                # i.e. after pairing is complete
                self.bus.once('owo.paired', self._handle_pairing_complete)

                self.speak(owo.dialog.get('owo.intro'))
                wait_while_speaking()
                time.sleep(2)  # a pause sounds better than just jumping in

                # Kick off wifi-setup automatically
                data = {'allow_timeout': False, 'lang': self.lang}
                self.bus.emit(Message('system.wifi.setup', data))
Exemple #3
0
def load_vocab_from_file(path, vocab_type, bus):
    """Load OwO vocabulary from file
    The vocab is sent to the intent handler using the message bus

    Args:
        path:           path to vocabulary file (*.voc)
        vocab_type:     keyword name
        bus:            OwO messagebus connection
        skill_id(str):  skill id
    """
    if path.endswith('.voc'):
        with open(path, 'r') as voc_file:
            for line in voc_file.readlines():
                if line.startswith("#"):
                    continue
                parts = line.strip().split("|")
                entity = parts[0]
                bus.emit(
                    Message("register_vocab", {
                        'start': entity,
                        'end': vocab_type
                    }))
                for alias in parts[1:]:
                    bus.emit(
                        Message("register_vocab", {
                            'start': alias,
                            'end': vocab_type,
                            'alias_of': entity
                        }))
 def test_ClientServer(self):
     """This is the test to send a message from each of the websockets
     to the other.
     """
     # Send the messages
     self.ws2.emit(Message('ws1.message'))
     self.ws1.emit(Message('ws2.message'))
     # allow time for messages to be processed
     time.sleep(0.2)
     # Check that both of the handlers were called.
     self.assertTrue(self.handle1)
     self.assertTrue(self.handle2)
 def test_deserialize(self):
     """This test's the deserialize method
     """
     messages = []
     # create the messages from the serialized strings above
     messages.append(Message.deserialize(self.serialized[0]))
     messages.append(Message.deserialize(self.serialized[1]))
     messages.append(Message.deserialize(self.serialized[2]))
     # check the created messages match the strings
     self.assertEqual(messages[0].serialize(), self.serialized[0])
     self.assertEqual(messages[1].serialize(), self.serialized[1])
     self.assertEqual(messages[2].serialize(), self.serialized[2])
Exemple #6
0
    def check_state(self):
        """
            Check if an event should be triggered.
        """
        with self.event_lock:
            # Check all events
            pending_messages = []
            for event in self.events:
                current_time = time.time()
                e = self.events[event]
                # Get scheduled times that has passed
                passed = [(t, r, d) for (t, r, d) in e if t <= current_time]
                # and remaining times that we're still waiting for
                remaining = [(t, r, d) for t, r, d in e if t > current_time]
                # Trigger registered methods
                for sched_time, repeat, data in passed:
                    pending_messages.append(Message(event, data))
                    # if this is a repeated event add a new trigger time
                    if repeat:
                        next_time = repeat_time(sched_time, repeat)
                        remaining.append((next_time, repeat, data))
                # update list of events
                self.events[event] = remaining

        # Remove events have are now completed
        self.clear_empty()

        # Finally, emit the queued up events that triggered
        for msg in pending_messages:
            self.bus.emit(msg)
Exemple #7
0
 def eyes_timed_spin(self, length):
     """Make the eyes 'roll' for the given time.
     Args:
         length (int): duration in milliseconds of roll, None = forever
     """
     self.bus.emit(Message("enclosure.eyes.timedspin",
                           {'length': length}))
Exemple #8
0
def simple_cli():
    global bus
    global bSimple
    bSimple = True
    bus = WebsocketClient()  # OwO messagebus connection
    event_thread = Thread(target=connect)
    event_thread.setDaemon(True)
    event_thread.start()
    bus.on('speak', handle_speak)
    try:
        while True:
            # Sleep for a while so all the output that results
            # from the previous command finishes before we print.
            time.sleep(1.5)
            print("Input (Ctrl+C to quit):")
            line = sys.stdin.readline()
            bus.emit(
                Message("recognizer_loop:utterance",
                        {'utterances': [line.strip()]}))
    except KeyboardInterrupt as e:
        # User hit Ctrl+C to quit
        print("")
    except KeyboardInterrupt as e:
        LOG.exception(e)
        event_thread.exit()
        sys.exit()
Exemple #9
0
 def mouth_text(self, text=""):
     """Display text (scrolling as needed)
     Args:
         text (str): text string to display
     """
     self.display_manager.set_active(self.name)
     self.bus.emit(Message("enclosure.mouth.text", {'text': text}))
Exemple #10
0
def handle_utterance(event):
    LOG.info("Utterance: " + str(event['utterances']))
    context = {'client_name': 'OwO_listener'}
    if 'ident' in event:
        ident = event.pop('ident')
        context['ident'] = ident
    bus.emit(Message('recognizer_loop:utterance', event, context))
Exemple #11
0
    def register_entity_file(self, entity_file):
        """ Register an Entity file with the intent service.

        An Entity file lists the exact values that an entity can hold.
        For example:

        === ask.day.intent ===
        Is it {weekend}?

        === weekend.entity ===
        Saturday
        Sunday

        Args:
            entity_file (string): name of file that contains examples of an
                                  entity.  Must end with '.entity'
        """
        if entity_file.endswith('.entity'):
            entity_file = entity_file.replace('.entity', '')

        filename = self.find_resource(entity_file + ".entity", 'vocab')
        if not filename:
            raise ValueError('Unable to find "' + entity_file + '.entity"')
        name = str(self.skill_id) + ':' + entity_file

        self.bus.emit(
            Message("padatious:register_entity", {
                "file_name": filename,
                "name": name
            }))
Exemple #12
0
    def get_scheduled_event_status(self, name):
        """
            Get scheduled event data and return the amount of time left

            Args:
                name (str): Name of event

            Return:
                int: the time left in seconds
        """
        event_name = self._unique_name(name)
        data = {'name': event_name}

        # making event_status an object so it's refrence can be changed
        event_status = [None]
        finished_callback = [False]

        def callback(message):
            if message.data is not None:
                event_time = int(message.data[0][0])
                current_time = int(time.time())
                time_left_in_seconds = event_time - current_time
                event_status[0] = time_left_in_seconds
            finished_callback[0] = True

        emitter_name = 'owo.event_status.callback.{}'.format(event_name)
        self.bus.once(emitter_name, callback)
        self.bus.emit(Message('owo.scheduler.get_event', data=data))

        start_wait = time.time()
        while finished_callback[0] is False and time.time() - start_wait < 3.0:
            time.sleep(0.1)
        if time.time() - start_wait > 3.0:
            raise Exception("Event Status Messagebus Timeout")
        return event_status[0]
Exemple #13
0
    def default_shutdown(self):
        """Parent function called internally to shut down everything.

        Shuts down known entities and calls skill specific shutdown method.
        """
        try:
            self.shutdown()
        except Exception as e:
            LOG.error('Skill specific shutdown function encountered '
                      'an error: {}'.format(repr(e)))
        # Store settings
        if exists(self._dir):
            self.settings.store()
            self.settings.stop_polling()
        # removing events
        self.cancel_all_repeating_events()
        for e, f in self.events:
            self.bus.remove(e, f)
        self.events = []  # Remove reference to wrappers

        self.bus.emit(
            Message("detach_skill", {"skill_id": str(self.skill_id) + ":"}))
        try:
            self.stop()
        except:
            LOG.error("Failed to stop skill: {}".format(self.name),
                      exc_info=True)
Exemple #14
0
 def test_open_envelope(self):
     name = 'Jerome'
     intent = IntentBuilder(name).require('Keyword')
     intent.name = name
     m = Message("register_intent", intent.__dict__)
     unpacked_intent = open_intent_envelope(m)
     self.assertEqual(intent.__dict__, unpacked_intent.__dict__)
Exemple #15
0
 def track_start(self, track):
     """
         Callback method called from the services to indicate start of
         playback of a track.
     """
     self.bus.emit(Message('owo.audio.playing_track', data={'track':
                                                            track}))
Exemple #16
0
    def run(self):
        """ Load skills and update periodically from disk and internet """

        self.remove_git_locks()
        self._connected_event.wait()
        has_loaded = False

        # check if skill updates are enabled
        update = Configuration.get()["skills"]["auto_update"]

        # Scan the file folder that contains Skills.  If a Skill is updated,
        # unload the existing version from memory and reload from the disk.
        while not self._stop_event.is_set():
            # Update skills once an hour if update is enabled
            if time.time() >= self.next_download and update:
                self.download_skills()

            # Look for recently changed skill(s) needing a reload
            # checking skills dir and getting all skills there
            skill_paths = glob(join(self.msm.skills_dir, '*/'))
            still_loading = False
            for skill_path in skill_paths:
                still_loading = (self._load_or_reload_skill(skill_path)
                                 or still_loading)
            if not has_loaded and not still_loading and len(skill_paths) > 0:
                has_loaded = True
                self.bus.emit(Message('owo.skills.initialized'))

            self._unload_removed(skill_paths)
            # Pause briefly before beginning next scan
            time.sleep(2)
Exemple #17
0
 def remove_context(self, context):
     """
         remove_context removes a keyword from from the context manager.
     """
     if not isinstance(context, str):
         raise ValueError('context should be a string')
     self.bus.emit(Message('remove_context', {'context': context}))
Exemple #18
0
    def make_active(self):
        """ Bump skill to active_skill list in intent_service

        This enables converse method to be called even without skill being
        used in last 5 minutes.
        """
        self.bus.emit(
            Message('active_skill_request', {"skill_id": self.skill_id}))
Exemple #19
0
 def register_regex(self, regex_str):
     """ Register a new regex.
         Args:
             regex_str: Regex string
     """
     regex = munge_regex(regex_str, self.skill_id)
     re.compile(regex)  # validate regex
     self.bus.emit(Message('register_vocab', {'regex': regex}))
Exemple #20
0
 def eyes_color(self, r=255, g=255, b=255):
     """Change the eye color to the given RGB color
     Args:
         r (int): 0-255, red value
         g (int): 0-255, green value
         b (int): 0-255, blue value
     """
     self.bus.emit(Message("enclosure.eyes.color",
                           {'r': r, 'g': g, 'b': b}))
Exemple #21
0
 def eyes_volume(self, volume):
     """Indicate the volume using the eyes
     Args:
         volume (int): 0 to 11
     """
     if volume < 0 or volume > 11:
         raise ValueError('volume ({}) must be between 0-11'.
                          format(str(volume)))
     self.bus.emit(Message("enclosure.eyes.volume", {'volume': volume}))
Exemple #22
0
    def __init__(self, config, bus, name='mopidy'):
        self.connection_attempts = 0
        self.bus = bus
        self.config = config
        self.name = name

        self.mopidy = None
        self.bus.on('MopidyServiceConnect', self._connect)
        self.bus.emit(Message('MopidyServiceConnect'))
Exemple #23
0
    def update_scheduled_event(self, name, data=None):
        """
            Change data of event.

            Args:
                name (str):   Name of event
        """
        data = data or {}
        data = {'event': self._unique_name(name), 'data': data}
        self.bus.emit(Message('owo.schedule.update_event', data=data))
Exemple #24
0
def handle_stop(event):
    """
        handle stop message
    """
    global _last_stop_signal
    if check_for_signal("isSpeaking", -1):
        _last_stop_signal = time.time()
        tts.playback.clear_queue()
        tts.playback.clear_visimes()
        bus.emit(Message("owo.stop.handled", {"by": "TTS"}))
Exemple #25
0
 def eyes_look(self, side):
     """Make the eyes look to the given side
     Args:
         side (str): 'r' for right
                     'l' for left
                     'u' for up
                     'd' for down
                     'c' for crossed
     """
     self.bus.emit(Message("enclosure.eyes.look", {'side': side}))
Exemple #26
0
 def eyes_fill(self, percentage):
     """Use the eyes as a type of progress meter
     Args:
         amount (int): 0-49 fills the right eye, 50-100 also covers left
     """
     if percentage < 0 or percentage > 100:
         raise ValueError('percentage ({}) must be between 0-100'.
                          format(str(percentage)))
     self.bus.emit(Message("enclosure.eyes.fill",
                           {'percentage': percentage}))
Exemple #27
0
 def eyes_setpixel(self, idx, r=255, g=255, b=255):
     """Set individual pixels of the Mark 1 neopixel eyes
     Args:
         idx (int): 0-11 for the right eye, 12-23 for the left
         r (int): The red value to apply
         g (int): The green value to apply
         b (int): The blue value to apply
     """
     if idx < 0 or idx > 23:
         raise ValueError('idx ({}) must be between 0-23'.format(str(idx)))
     self.bus.emit(Message("enclosure.eyes.setpixel",
                           {'idx': idx, 'r': r, 'g': g, 'b': b}))
Exemple #28
0
    def register_vocabulary(self, entity, entity_type):
        """ Register a word to a keyword

            Args:
                entity:         word to register
                entity_type:    Intent handler entity to tie the word to
        """
        self.bus.emit(
            Message('register_vocab', {
                'start': entity,
                'end': to_alnum(self.skill_id) + entity_type
            }))
Exemple #29
0
    def _track_info(self, message):
        """
            Returns track info on the message bus.

            Args:
                message: message bus message, not used but required
        """
        if self.current:
            track_info = self.current.track_info()
        else:
            track_info = {}
        self.bus.emit(
            Message('owo.audio.service.track_info_reply', data=track_info))
Exemple #30
0
    def on_no_internet(self, event=None):
        if connected():
            # One last check to see if connection was established
            return

        if time.time() - Enclosure._last_internet_notification < 30:
            # don't bother the user with multiple notifications with 30 secs
            return

        Enclosure._last_internet_notification = time.time()

        # TODO: This should go into EnclosureMark1 subclass of Enclosure.
        if has_been_paired():
            # Handle the translation within that code.
            self.bus.emit(Message("speak", {
                'utterance': "This device is not connected to the Internet. "
                             "Either plug in a network cable or hold the "
                             "button on top for two seconds, then select "
                             "wifi from the menu"}))
        else:
            # enter wifi-setup mode automatically
            self.bus.emit(Message('system.wifi.setup', {'lang': self.lang}))