mirror of
https://github.com/OpenVoiceOS/OpenVoiceOS
synced 2025-02-23 23:27:38 +01:00
376 lines
14 KiB
Diff
376 lines
14 KiB
Diff
From ae33770b5b842b9ac51fa7eefcb9b3808590f2e8 Mon Sep 17 00:00:00 2001
|
|
From: jarbasal <jarbasai@mailfence.com>
|
|
Date: Thu, 18 Feb 2021 18:28:31 +0000
|
|
Subject: [PATCH 1/4] enclosure cleanup
|
|
|
|
---
|
|
mycroft/client/enclosure/base.py | 39 ++++++
|
|
mycroft/client/enclosure/generic/__init__.py | 139 +------------------
|
|
2 files changed, 42 insertions(+), 136 deletions(-)
|
|
|
|
diff --git a/mycroft/client/enclosure/base.py b/mycroft/client/enclosure/base.py
|
|
index 4d26a42f43f..7d55040d13b 100644
|
|
--- a/mycroft/client/enclosure/base.py
|
|
+++ b/mycroft/client/enclosure/base.py
|
|
@@ -23,6 +23,7 @@
|
|
from mycroft.util.log import LOG
|
|
|
|
import json
|
|
+import time
|
|
import tornado.web as web
|
|
from tornado import ioloop
|
|
from tornado.websocket import WebSocketHandler
|
|
@@ -70,6 +71,10 @@ def __init__(self):
|
|
# Create Message Bus Client
|
|
self.bus = MessageBusClient()
|
|
|
|
+ # TODO: this requires the Enclosure to be up and running before the
|
|
+ # training is complete.
|
|
+ self.bus.on('mycroft.skills.trained', self.is_device_ready)
|
|
+
|
|
self.gui = create_gui_service(self, config['gui_websocket'])
|
|
# This datastore holds the data associated with the GUI provider. Data
|
|
# is stored in Namespaces, so you can have:
|
|
@@ -115,6 +120,40 @@ def stop(self):
|
|
"""Perform any enclosure shutdown processes."""
|
|
pass
|
|
|
|
+ def is_device_ready(self, message):
|
|
+ is_ready = False
|
|
+ # Bus service assumed to be alive if messages sent and received
|
|
+ # Enclosure assumed to be alive if this method is running
|
|
+ services = {'audio': False, 'speech': False, 'skills': False}
|
|
+ start = time.monotonic()
|
|
+ while not is_ready:
|
|
+ is_ready = self.check_services_ready(services)
|
|
+ if is_ready:
|
|
+ break
|
|
+ elif time.monotonic() - start >= 60:
|
|
+ raise Exception('Timeout waiting for services start.')
|
|
+ else:
|
|
+ time.sleep(3)
|
|
+
|
|
+ if is_ready:
|
|
+ LOG.info("Mycroft is all loaded and ready to roll!")
|
|
+ self.bus.emit(Message('mycroft.ready'))
|
|
+
|
|
+ return is_ready
|
|
+
|
|
+ def check_services_ready(self, services):
|
|
+ """Report if all specified services are ready.
|
|
+
|
|
+ services (iterable): service names to check.
|
|
+ """
|
|
+ for ser in services:
|
|
+ services[ser] = False
|
|
+ response = self.bus.wait_for_response(Message(
|
|
+ 'mycroft.{}.is_ready'.format(ser)))
|
|
+ if response and response.data['status']:
|
|
+ services[ser] = True
|
|
+ return all([services[ser] for ser in services])
|
|
+
|
|
######################################################################
|
|
# GUI client API
|
|
@property
|
|
diff --git a/mycroft/client/enclosure/generic/__init__.py b/mycroft/client/enclosure/generic/__init__.py
|
|
index 3c47a545943..23c4fde794c 100644
|
|
--- a/mycroft/client/enclosure/generic/__init__.py
|
|
+++ b/mycroft/client/enclosure/generic/__init__.py
|
|
@@ -12,144 +12,11 @@
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
#
|
|
-import subprocess
|
|
-import time
|
|
-import sys
|
|
-from threading import Thread, Timer
|
|
-
|
|
-import mycroft.dialog
|
|
from mycroft.client.enclosure.base import Enclosure
|
|
-from mycroft.api import has_been_paired
|
|
-from mycroft.audio import wait_while_speaking
|
|
-from mycroft.enclosure.display_manager import \
|
|
- init_display_manager_bus_connection
|
|
-from mycroft.messagebus.message import Message
|
|
-from mycroft.util import connected
|
|
-from mycroft.util.log import LOG
|
|
|
|
|
|
class EnclosureGeneric(Enclosure):
|
|
"""
|
|
- Serves as a communication interface between a simple text frontend and
|
|
- Mycroft Core. This is used for Picroft or other headless systems,
|
|
- and/or for users of the CLI.
|
|
- """
|
|
-
|
|
- _last_internet_notification = 0
|
|
-
|
|
- def __init__(self):
|
|
- super().__init__()
|
|
-
|
|
- # Notifications from mycroft-core
|
|
- self.bus.on('enclosure.notify.no_internet', self.on_no_internet)
|
|
- # TODO: this requires the Enclosure to be up and running before the
|
|
- # training is complete.
|
|
- self.bus.on('mycroft.skills.trained', self.is_device_ready)
|
|
-
|
|
- # initiates the web sockets on display manager
|
|
- # NOTE: this is a temporary place to connect the display manager
|
|
- init_display_manager_bus_connection()
|
|
-
|
|
- # verify internet connection and prompt user on bootup if needed
|
|
- if not connected():
|
|
- # We delay this for several seconds to ensure that the other
|
|
- # clients are up and connected to the messagebus in order to
|
|
- # receive the "speak". This was sometimes happening too
|
|
- # quickly and the user wasn't notified what to do.
|
|
- Timer(5, self._do_net_check).start()
|
|
-
|
|
- def is_device_ready(self, message):
|
|
- is_ready = False
|
|
- # Bus service assumed to be alive if messages sent and received
|
|
- # Enclosure assumed to be alive if this method is running
|
|
- services = {'audio': False, 'speech': False, 'skills': False}
|
|
- start = time.monotonic()
|
|
- while not is_ready:
|
|
- is_ready = self.check_services_ready(services)
|
|
- if is_ready:
|
|
- break
|
|
- elif time.monotonic() - start >= 60:
|
|
- raise Exception('Timeout waiting for services start.')
|
|
- else:
|
|
- time.sleep(3)
|
|
-
|
|
- if is_ready:
|
|
- LOG.info("Mycroft is all loaded and ready to roll!")
|
|
- self.bus.emit(Message('mycroft.ready'))
|
|
-
|
|
- return is_ready
|
|
-
|
|
- def check_services_ready(self, services):
|
|
- """Report if all specified services are ready.
|
|
-
|
|
- services (iterable): service names to check.
|
|
- """
|
|
- for ser in services:
|
|
- services[ser] = False
|
|
- response = self.bus.wait_for_response(Message(
|
|
- 'mycroft.{}.is_ready'.format(ser)))
|
|
- if response and response.data['status']:
|
|
- services[ser] = True
|
|
- return all([services[ser] for ser in services])
|
|
-
|
|
- 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 set up your "
|
|
- "wifi connection."}))
|
|
- else:
|
|
- # enter wifi-setup mode automatically
|
|
- self.bus.emit(Message('system.wifi.setup', {'lang': self.lang}))
|
|
-
|
|
- def speak(self, text):
|
|
- self.bus.emit(Message("speak", {'utterance': text}))
|
|
-
|
|
- def _handle_pairing_complete(self, _):
|
|
- """
|
|
- Handler for 'mycroft.paired', unmutes the mic after the pairing is
|
|
- complete.
|
|
- """
|
|
- self.bus.emit(Message("mycroft.mic.unmute"))
|
|
-
|
|
- def _do_net_check(self):
|
|
- # TODO: This should live in the derived Enclosure, e.g. EnclosureMark1
|
|
- 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 setup your "
|
|
- "wifi connection.")
|
|
- else:
|
|
- # Begin the unit startup process, this is the first time it
|
|
- # is being run with factory defaults.
|
|
-
|
|
- # TODO: This logic should be in EnclosureMark1
|
|
- # TODO: Enclosure/localization
|
|
-
|
|
- # Don't listen to mic during this out-of-box experience
|
|
- self.bus.emit(Message("mycroft.mic.mute"))
|
|
- # Setup handler to unmute mic at the end of on boarding
|
|
- # i.e. after pairing is complete
|
|
- self.bus.once('mycroft.paired', self._handle_pairing_complete)
|
|
-
|
|
- self.speak(mycroft.dialog.get('mycroft.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))
|
|
+ Serves as a communication interface between GUI and
|
|
+ Mycroft Core. This is used for Picroft or other headless systems
|
|
+ """
|
|
\ No newline at end of file
|
|
|
|
From a5ab14ae5acc5c88fef2dbb23a6729d1eff5ca9e Mon Sep 17 00:00:00 2001
|
|
From: jarbasal <jarbasai@mailfence.com>
|
|
Date: Thu, 18 Feb 2021 19:24:59 +0000
|
|
Subject: [PATCH 2/4] only report ready after pairing
|
|
|
|
---
|
|
mycroft/client/enclosure/base.py | 22 +++++++++++++++-------
|
|
1 file changed, 15 insertions(+), 7 deletions(-)
|
|
|
|
diff --git a/mycroft/client/enclosure/base.py b/mycroft/client/enclosure/base.py
|
|
index 7d55040d13b..aacefe46449 100644
|
|
--- a/mycroft/client/enclosure/base.py
|
|
+++ b/mycroft/client/enclosure/base.py
|
|
@@ -16,7 +16,7 @@
|
|
|
|
from collections import namedtuple
|
|
from threading import Lock
|
|
-
|
|
+from mycroft.api import is_paired
|
|
from mycroft.configuration import Configuration
|
|
from mycroft.messagebus.client import MessageBusClient
|
|
from mycroft.util import create_daemon, start_message_bus_client
|
|
@@ -73,7 +73,8 @@ def __init__(self):
|
|
|
|
# TODO: this requires the Enclosure to be up and running before the
|
|
# training is complete.
|
|
- self.bus.on('mycroft.skills.trained', self.is_device_ready)
|
|
+ self.bus.once('mycroft.skills.trained',
|
|
+ self.handle_check_device_readiness)
|
|
|
|
self.gui = create_gui_service(self, config['gui_websocket'])
|
|
# This datastore holds the data associated with the GUI provider. Data
|
|
@@ -120,7 +121,7 @@ def stop(self):
|
|
"""Perform any enclosure shutdown processes."""
|
|
pass
|
|
|
|
- def is_device_ready(self, message):
|
|
+ def is_device_ready(self):
|
|
is_ready = False
|
|
# Bus service assumed to be alive if messages sent and received
|
|
# Enclosure assumed to be alive if this method is running
|
|
@@ -134,12 +135,19 @@ def is_device_ready(self, message):
|
|
raise Exception('Timeout waiting for services start.')
|
|
else:
|
|
time.sleep(3)
|
|
+ return is_ready
|
|
|
|
- if is_ready:
|
|
- LOG.info("Mycroft is all loaded and ready to roll!")
|
|
- self.bus.emit(Message('mycroft.ready'))
|
|
+ def handle_check_device_readiness(self, message):
|
|
|
|
- return is_ready
|
|
+ def handle_ready(message=None):
|
|
+ if self.is_device_ready():
|
|
+ LOG.info("Mycroft is all loaded and ready to roll!")
|
|
+ self.bus.emit(Message('mycroft.ready'))
|
|
+
|
|
+ if not is_paired():
|
|
+ self.bus.once("mycroft.paired", handle_ready)
|
|
+ else:
|
|
+ handle_ready()
|
|
|
|
def check_services_ready(self, services):
|
|
"""Report if all specified services are ready.
|
|
|
|
From 4d67450e0e1b9d86a1d452f7e683500335224d3b Mon Sep 17 00:00:00 2001
|
|
From: jarbasal <jarbasai@mailfence.com>
|
|
Date: Sun, 21 Feb 2021 15:01:30 +0000
|
|
Subject: [PATCH 3/4] pairing non sense
|
|
|
|
---
|
|
mycroft/skills/__main__.py | 12 ++++--------
|
|
mycroft/stt/__init__.py | 2 +-
|
|
2 files changed, 5 insertions(+), 9 deletions(-)
|
|
|
|
diff --git a/mycroft/skills/__main__.py b/mycroft/skills/__main__.py
|
|
index 0d0cc378edf..bca66ccdfc1 100644
|
|
--- a/mycroft/skills/__main__.py
|
|
+++ b/mycroft/skills/__main__.py
|
|
@@ -39,10 +39,10 @@
|
|
from mycroft.util.lang import set_active_lang
|
|
from mycroft.util.log import LOG
|
|
from mycroft.util.process_utils import ProcessStatus, StatusCallbackMap
|
|
-from .core import FallbackSkill
|
|
-from .event_scheduler import EventScheduler
|
|
-from .intent_service import IntentService
|
|
-from .skill_manager import SkillManager
|
|
+from mycroft.skills.core import FallbackSkill
|
|
+from mycroft.skills.event_scheduler import EventScheduler
|
|
+from mycroft.skills.intent_service import IntentService
|
|
+from mycroft.skills.skill_manager import SkillManager
|
|
|
|
RASPBERRY_PI_PLATFORMS = ('mycroft_mark_1', 'picroft', 'mycroft_mark_2pi')
|
|
|
|
@@ -127,10 +127,6 @@ def _ensure_device_is_paired(self):
|
|
Pairing cannot be performed if there is no connection to the back end.
|
|
So skip pairing if the backend is down.
|
|
"""
|
|
- if not self.is_paired and not self.backend_down:
|
|
- LOG.info('Device not paired, invoking the pairing skill')
|
|
- payload = dict(utterances=["pair my device"], lang="en-us")
|
|
- self.bus.emit(Message("recognizer_loop:utterance", payload))
|
|
|
|
def _update_device_attributes_on_backend(self):
|
|
"""Communicate version information to the backend.
|
|
diff --git a/mycroft/stt/__init__.py b/mycroft/stt/__init__.py
|
|
index 5028f20ea1d..a0d49a6e510 100644
|
|
--- a/mycroft/stt/__init__.py
|
|
+++ b/mycroft/stt/__init__.py
|
|
@@ -285,7 +285,7 @@ def wrapper(*args, **kwargs):
|
|
if e.response.status_code == 401:
|
|
LOG.warning('Access Denied at mycroft.ai')
|
|
# phrase to start the pairing process
|
|
- return 'pair my device'
|
|
+ return None
|
|
else:
|
|
raise
|
|
return wrapper
|
|
|
|
From 87113e92f3909a13c1007d6f935398aa98d96be3 Mon Sep 17 00:00:00 2001
|
|
From: jarbasal <jarbasai@mailfence.com>
|
|
Date: Sun, 21 Feb 2021 20:45:50 +0000
|
|
Subject: [PATCH 4/4] pairing trigger
|
|
|
|
---
|
|
mycroft/skills/__main__.py | 6 +++---
|
|
1 file changed, 3 insertions(+), 3 deletions(-)
|
|
|
|
diff --git a/mycroft/skills/__main__.py b/mycroft/skills/__main__.py
|
|
index bca66ccdfc1..609fb0ee932 100644
|
|
--- a/mycroft/skills/__main__.py
|
|
+++ b/mycroft/skills/__main__.py
|
|
@@ -123,10 +123,10 @@ def _display_skill_loading_notification(self):
|
|
|
|
def _ensure_device_is_paired(self):
|
|
"""Determine if device is paired, if not automatically start pairing.
|
|
-
|
|
- Pairing cannot be performed if there is no connection to the back end.
|
|
- So skip pairing if the backend is down.
|
|
"""
|
|
+ if not self.is_paired:
|
|
+ LOG.info('Device not paired, invoking the pairing skill')
|
|
+ self.bus.emit(Message("mycroft.not.paired"))
|
|
|
|
def _update_device_attributes_on_backend(self):
|
|
"""Communicate version information to the backend.
|