Add support for watchdog in skills and speech client

If no watchdog is provided a dummy function will be called
pull/2601/head
Åke Forslund 2020-03-28 08:29:24 +01:00
parent 09b1deb511
commit a1fdae3415
5 changed files with 22 additions and 10 deletions

View File

@ -207,7 +207,7 @@ def connect_bus_events(bus):
bus.on('message', create_echo_function('VOICE'))
def main(ready_hook=on_ready, error_hook=on_error):
def main(ready_hook=on_ready, error_hook=on_error, watchdog=lambda: None):
global bus
global loop
global config
@ -219,7 +219,7 @@ def main(ready_hook=on_ready, error_hook=on_error):
config = Configuration.get()
# Register handlers on internal RecognizerLoop bus
loop = RecognizerLoop()
loop = RecognizerLoop(watchdog)
connect_loop_events(loop)
connect_bus_events(bus)
create_daemon(bus.run_forever)

View File

@ -275,10 +275,15 @@ class RecognizerLoop(BaseEventEmitter):
""" EventEmitter loop running speech recognition.
Local wake word recognizer and remote general speech recognition.
Arguments:
watchdog: (callable) function to call periodically indicating
operational status.
"""
def __init__(self):
def __init__(self, watchdog=None):
super(RecognizerLoop, self).__init__()
self._watchdog = watchdog
self.mute_calls = 0
self._load_config()
@ -305,7 +310,7 @@ class RecognizerLoop(BaseEventEmitter):
# TODO - localization
self.wakeup_recognizer = self.create_wakeup_recognizer()
self.responsive_recognizer = ResponsiveRecognizer(
self.wakeword_recognizer)
self.wakeword_recognizer, self._watchdog)
self.state = RecognizerLoopState()
def create_wake_word_recognizer(self):

View File

@ -336,7 +336,8 @@ class ResponsiveRecognizer(speech_recognition.Recognizer):
# Time between pocketsphinx checks for the wake word
SEC_BETWEEN_WW_CHECKS = 0.2
def __init__(self, wake_word_recognizer):
def __init__(self, wake_word_recognizer, watchdog=None):
self._watchdog = watchdog or (lambda: None) # Default to dummy func
self.config = Configuration.get()
listener_config = self.config.get('listener')
self.upload_url = listener_config['wake_word_upload']['url']
@ -474,6 +475,7 @@ class ResponsiveRecognizer(speech_recognition.Recognizer):
# Periodically write the energy level to the mic level file.
if num_chunks % 10 == 0:
self._watchdog()
self.write_mic_level(energy, source)
return byte_data
@ -654,6 +656,7 @@ class ResponsiveRecognizer(speech_recognition.Recognizer):
# Periodically output energy level stats. This can be used to
# visualize the microphone input, e.g. a needle on a meter.
if mic_write_counter % 3:
self._watchdog()
self.write_mic_level(energy, source)
mic_write_counter += 1

View File

@ -181,7 +181,7 @@ def on_error(e='Unknown'):
LOG.info('Skill service failed to launch ({})'.format(repr(e)))
def main(ready_hook=on_ready, error_hook=on_error):
def main(ready_hook=on_ready, error_hook=on_error, watchdog=None):
reset_sigint_handler()
# Create PID file, prevent multiple instances of this service
mycroft.lock.Lock('skills')
@ -193,7 +193,7 @@ def main(ready_hook=on_ready, error_hook=on_error):
bus = _start_message_bus_client()
_register_intent_services(bus)
event_scheduler = EventScheduler(bus)
skill_manager = _initialize_skill_manager(bus)
skill_manager = _initialize_skill_manager(bus, watchdog)
_wait_for_internet_connection()
@ -244,14 +244,14 @@ def _register_intent_services(bus):
bus.on('intent_failure', FallbackSkill.make_intent_failure_handler(bus))
def _initialize_skill_manager(bus):
def _initialize_skill_manager(bus, watchdog):
"""Create a thread that monitors the loaded skills, looking for updates
Returns:
SkillManager instance or None if it couldn't be initialized
"""
try:
skill_manager = SkillManager(bus)
skill_manager = SkillManager(bus, watchdog)
skill_manager.load_priority()
except MsmException:
# skill manager couldn't be created, wait for network connection and

View File

@ -110,14 +110,17 @@ def _shutdown_skill(instance):
class SkillManager(Thread):
_msm = None
def __init__(self, bus):
def __init__(self, bus, watchdog=None):
"""Constructor
Arguments:
bus (event emitter): Mycroft messagebus connection
watchdog (callable): optional watchdog function
"""
super(SkillManager, self).__init__()
self.bus = bus
# Set watchdog to argument or function returning None
self._watchdog = watchdog or (lambda: None)
self._stop_event = Event()
self._connected_event = Event()
self.config = Configuration.get()
@ -243,6 +246,7 @@ class SkillManager(Thread):
self.skill_updater.post_manifest()
self.upload_queue.send()
self._watchdog()
sleep(2) # Pause briefly before beginning next scan
except Exception:
LOG.exception('Something really unexpected has occured '