diff --git a/ovos_core/skill_manager.py b/ovos_core/skill_manager.py index eaf9963b74e..e14df42da0d 100644 --- a/ovos_core/skill_manager.py +++ b/ovos_core/skill_manager.py @@ -16,12 +16,14 @@ import os from os.path import basename from threading import Thread, Event, Lock -from time import sleep, monotonic -from ovos_backend_client.pairing import is_paired from ovos_bus_client.apis.enclosure import EnclosureAPI from ovos_bus_client.client import MessageBusClient from ovos_bus_client.message import Message +from ovos_workshop.skill_launcher import SKILL_MAIN_MODULE +from ovos_workshop.skill_launcher import SkillLoader, PluginSkillLoader +from time import sleep, monotonic + from ovos_config.config import Configuration from ovos_config.locations import get_xdg_config_save_path from ovos_plugin_manager.skills import find_skill_plugins @@ -31,8 +33,6 @@ from ovos_utils.log import LOG from ovos_utils.network_utils import is_connected from ovos_utils.process_utils import ProcessStatus, StatusCallbackMap, ProcessState -from ovos_workshop.skill_launcher import SKILL_MAIN_MODULE -from ovos_workshop.skill_launcher import SkillLoader, PluginSkillLoader def _shutdown_skill(instance): @@ -194,8 +194,6 @@ def _define_message_bus_events(self): self.bus.on('skillmanager.deactivate', self.deactivate_skill) self.bus.on('skillmanager.keep', self.deactivate_except) self.bus.on('skillmanager.activate', self.activate_skill) - self.bus.once('mycroft.skills.initialized', - self.handle_check_device_readiness) self.bus.once('mycroft.skills.trained', self.handle_initial_training) # Load skills waiting for connectivity @@ -206,111 +204,6 @@ def _define_message_bus_events(self): self.bus.on("mycroft.internet.disconnected", self.handle_internet_disconnected) self.bus.on("mycroft.gui.unavailable", self.handle_gui_disconnected) - def is_device_ready(self): - """Check if the device is ready by waiting for various services to start. - - Returns: - bool: True if the device is ready, False otherwise. - Raises: - TimeoutError: If the device is not ready within a specified timeout. - """ - is_ready = False - # Different setups will have different needs - # eg, a server does not care about audio - # pairing -> device is paired - # internet -> device is connected to the internet - NOT IMPLEMENTED - # skills -> skills reported ready - # speech -> stt reported ready - # audio -> audio playback reported ready - # gui -> gui websocket reported ready - NOT IMPLEMENTED - # enclosure -> enclosure/HAL reported ready - NOT IMPLEMENTED - services = {k: False for k in - self.config.get("ready_settings", ["skills"])} - start = monotonic() - while not is_ready: - is_ready = self.check_services_ready(services) - if is_ready: - break - elif monotonic() - start >= 60: - raise TimeoutError( - f'Timeout waiting for services start. services={services}') - else: - sleep(3) - return is_ready - - def handle_check_device_readiness(self, message): - """Handle the check device readiness event.""" - ready = False - while not ready: - try: - ready = self.is_device_ready() - except TimeoutError: - if is_paired(): - LOG.warning("OVOS should already have reported ready!") - sleep(5) - - LOG.info("Mycroft is all loaded and ready to roll!") - self.bus.emit(message.reply('mycroft.ready')) - - def check_services_ready(self, services): - """Report if all specified services are ready. - - Args: - services (iterable): Service names to check. - Returns: - bool: True if all specified services are ready, False otherwise. - """ - backend_type = self.config.get("server", {}).get("backend_type", "offline") - for ser, rdy in services.items(): - if rdy: - # already reported ready - continue - if ser in ["pairing", "setup"]: - - def setup_finish_interrupt(message): - nonlocal services - services[ser] = True - - # if setup finishes naturally be ready early - self.bus.once("ovos.setup.finished", setup_finish_interrupt) - - # pairing service (setup skill) needs to be available - # in offline mode (default) is_paired always returns True - # but setup skill may enable backend - # wait for backend selection event - response = self.bus.wait_for_response( - Message('ovos.setup.state.get', - context={"source": "skills", - "destination": "ovos-setup"}), - 'ovos.setup.state') - if response: - state = response.data['state'] - LOG.debug(f"Setup state: {state}") - if state == "finished": - services[ser] = True - elif not services[ser] and backend_type == "selene": - # older verson / alternate setup skill installed - services[ser] = is_paired(ignore_errors=True) - elif ser in ["gui", "enclosure"]: - # not implemented - services[ser] = True - continue - elif ser in ["skills"]: - services[ser] = self.status.check_ready() - continue - elif ser in ["network_skills"]: - services[ser] = self._network_loaded.is_set() - continue - elif ser in ["internet_skills"]: - services[ser] = self._internet_loaded.is_set() - continue - response = self.bus.wait_for_response( - Message(f'mycroft.{ser}.is_ready', - context={"source": "skills", "destination": ser})) - if response and response.data['status']: - services[ser] = True - return all([services[ser] for ser in services]) - @property def skills_config(self): """Get the skills service configuration. @@ -468,35 +361,6 @@ def _load_plugin_skill(self, skill_id, skill_plugin): return skill_loader if load_status else None - def load_priority(self): - """DEPRECATED: Load priority skills based on the specified order in the configuration.""" - skill_ids = {os.path.basename(skill_path): skill_path - for skill_path in self._get_skill_directories()} - priority_skills = self.skills_config.get("priority_skills") or [] - if priority_skills: - update_code = """priority skills have been deprecated and support will be removed in a future release - Update skills with the following: - - from ovos_utils.process_utils import RuntimeRequirements - from ovos_utils import classproperty - - class MyPrioritySkill(OVOSSkill): - @classproperty - def network_requirements(self): - return RuntimeRequirements(internet_before_load=False, - network_before_load=False, - requires_internet=False, - requires_network=False) - """ - LOG.warning(update_code) - for skill_id in priority_skills: - LOG.info(f"Please refactor {skill_id} to specify offline network requirements") - skill_path = skill_ids.get(skill_id) - if skill_path is not None: - self._load_skill(skill_path) - else: - LOG.error(f'Priority skill {skill_id} can\'t be found') - def handle_initial_training(self, message): """Handle the initial intent training completion event. @@ -509,45 +373,13 @@ def handle_initial_training(self, message): def run(self): """Run the skill manager thread.""" - self.load_priority() - self.status.set_alive() self._load_on_startup() - if self.skills_config.get("wait_for_internet", False): - LOG.warning("`wait_for_internet` is a deprecated option, update to " - "specify `network_skills` or `internet_skills` in " - "`ready_settings`") - # NOTE - self._connected_event will never be set - # if PHAL plugin is not running to emit the connected events - while not self._connected_event.is_set(): - # Ensure we don't block here forever if the plugin is not installed - self._sync_skill_loading_state() - sleep(1) - LOG.debug("Internet Connected") - else: - # trigger a sync so we dont need to wait for the plugin to volunteer info - self._sync_skill_loading_state() + # trigger a sync so we dont need to wait for the plugin to volunteer info + self._sync_skill_loading_state() - if "network_skills" in self.config.get("ready_settings"): - self._network_event.wait() # Wait for user to connect to network - if self._network_loaded.wait(self._network_skill_timeout): - LOG.debug("Network skills loaded") - else: - LOG.error("Gave up waiting for network skills to load") - if "internet_skills" in self.config.get("ready_settings"): - self._connected_event.wait() # Wait for user to connect to network - if self._internet_loaded.wait(self._network_skill_timeout): - LOG.debug("Internet skills loaded") - else: - LOG.error("Gave up waiting for internet skills to load") - if not all((self._network_loaded.is_set(), - self._internet_loaded.is_set())): - self.bus.emit(Message( - 'mycroft.skills.error', - {'internet_loaded': self._internet_loaded.is_set(), - 'network_loaded': self._network_loaded.is_set()})) self.bus.emit(Message('mycroft.skills.initialized')) # wait for initial intents training @@ -556,12 +388,7 @@ def run(self): sleep(0.5) self.status.set_ready() - if self._gui_event.is_set() and self._connected_event.is_set(): - LOG.info("Skills all loaded!") - elif not self._connected_event.is_set(): - LOG.info("Offline Skills loaded, waiting for Internet to load more!") - elif not self._gui_event.is_set(): - LOG.info("Skills loaded, waiting for GUI to load more!") + self.bus.emit(Message('mycroft.ready')) # Scan the file folder that contains Skills. If a Skill is updated, # unload the existing version from memory and reload from the disk.