Forráskód Böngészése

add Trigger adpater class

nico 8 éve
szülő
commit
74ccf40aa6
9 módosított fájl, 141 hozzáadás és 35 törlés
  1. 16 20
      core/MainController.py
  2. 12 8
      core/TriggerLauncher.py
  3. 30 1
      core/Utils.py
  4. 1 2
      jarvis.py
  5. 5 2
      settings.yml
  6. 18 2
      test.py
  7. 1 0
      trigger/__init__.py
  8. 1 0
      trigger/snowboy/__init__.py
  9. 57 0
      trigger/snowboy/snowboy.py

+ 16 - 20
core/MainController.py

@@ -1,7 +1,7 @@
 from core.ConfigurationManager import SettingLoader
-from core.JarvisTrigger import JarvisTrigger
 from core.OrderAnalyser import OrderAnalyser
 from core.OrderListener import OrderListener
+from core.TriggerLauncher import TriggerLauncher
 
 from neurons import Say
 
@@ -13,31 +13,19 @@ class MainController:
         self.settings = SettingLoader.get_settings()
 
         # create an order listener object
-        self.order_listener = OrderListener(self.get_analyse_order_callback())
+        self.order_listener = OrderListener(self.analyse_order)
         # Wait that the jarvis trigger is pronounced by the user
-        self.jarvis_triger = JarvisTrigger(self)
+        self.trigger_instance = self._get_default_trigger()
+        self.trigger_instance.start()
 
-    def start(self):
-        self.jarvis_triger.start()
-
-    def pause_jarvis_trigger(self):
-        """
-        The hotwork to wake up jarvis has been detected, we pause the snowboy process
-        :return:
-        """
-        self.jarvis_triger.pause()
-
-    def unpause_jarvis_trigger(self):
-        self.jarvis_triger.unpause()
-
-    def hotword_detected(self):
+    def callback(self):
         """
         # we have detected the hotword, we can now pause the Jarvis Trigger for a while
         # The user can speak out loud his order during this time.
         :return:
         """
         # pause the snowboy process
-        self.pause_jarvis_trigger()
+        self.trigger_instance.pause()
         Say(message=self.settings.random_wake_up_answers)
         self.order_listener.load_stt_plugin()
 
@@ -48,6 +36,14 @@ class MainController:
         """
         order_analyser = OrderAnalyser(order, main_controller=self, brain_file=self.brain_file)
         order_analyser.start()
+        # restart the trigger when the order analyser has finish his job
+        self.trigger_instance.unpause()
 
-    def get_analyse_order_callback(self):
-        return self.analyse_order
+    def _get_default_trigger(self):
+        """
+        Return an instance of the default trigger
+        :return:
+        """
+        for trigger in self.settings.triggers:
+            if trigger.name == self.settings.default_trigger_name:
+                return TriggerLauncher.get_trigger(trigger, callback=self.callback)

+ 12 - 8
core/TriggerLauncher.py

@@ -1,5 +1,7 @@
 import logging
 
+from core import Utils
+
 logging.basicConfig()
 logger = logging.getLogger("jarvis")
 
@@ -9,16 +11,18 @@ class TriggerLauncher(object):
         pass
 
     @classmethod
-    def start_trigger(cls, trigger_name, callback, parameters=None):
+    def get_trigger(cls, trigger, callback):
         """
-
-        :param trigger_name: Name of the trigger class to instantiate
+        Start a trigger module
+        :param trigger: trigger object to instantiate
+        :type trigger: Trigger
         :param callback: Callback function to call when the trigger
         catch the magic word
-        :param parameters: Dict of parameter to send to the trigger
         :return:
         """
-        pass
-        # plugin = neuron.name.capitalize()
-        # plugin = plugin.capitalize()
-        # _run_plugin(plugin, neuron.parameters)
+        # add the callback method to parameters
+        trigger.parameters["callback"] = callback
+        logger.debug("TriggerLauncher: Start trigger %s with parameters: %s" % (trigger.name, trigger.parameters))
+        return Utils.get_dynamic_class_instantiation("trigger", trigger.name.capitalize(),
+                                                                 trigger.parameters)
+

+ 30 - 1
core/Utils.py

@@ -1,3 +1,11 @@
+import logging
+
+logging.basicConfig()
+logger = logging.getLogger("jarvis")
+
+
+class ModuleNotFoundError(Exception):
+    pass
 
 
 class Utils(object):
@@ -43,4 +51,25 @@ class Utils(object):
 
     @classmethod
     def print_underline(cls, text_to_print):
-        print cls.color_list["UNDERLINE"] + text_to_print + cls.color_list["ENDLINE"]
+        print cls.color_list["UNDERLINE"] + text_to_print + cls.color_list["ENDLINE"]
+
+    @classmethod
+    def get_dynamic_class_instantiation(cls, package_name, module_name, parameters=None):
+
+        logger.debug("Run plugin %s with parameter %s" % (module_name, parameters))
+        mod = __import__(package_name, fromlist=[module_name])
+        try:
+            klass = getattr(mod, module_name)
+        except AttributeError:
+            logger.debug("Error: No module named %s " % module_name)
+            raise ModuleNotFoundError("The module %s does not exist in package %s" % (module_name, package_name))
+
+        if klass is not None:
+            # run the plugin
+            if not parameters:
+                return klass()
+            elif isinstance(parameters, dict):
+                return klass(**parameters)
+            else:
+                return klass(parameters)
+        return None

+ 1 - 2
jarvis.py

@@ -70,8 +70,7 @@ def main():
             # catch signal for killing on Ctrl+C pressed
             signal.signal(signal.SIGINT, signal_handler)
             # start the main controller
-            main_controller = MainController(brain_file=brain_file)
-            main_controller.start()
+            MainController(brain_file=brain_file)
 
     if args.action == "gui":
         ShellGui()

+ 5 - 2
settings.yml

@@ -34,6 +34,7 @@ speech_to_text:
 # Text to Spreech engines configuration
 # Available engine are:
 # - pico2wave
+# - voxygen
 text_to_speech:
   - pico2wave:
       language: "fr"
@@ -42,7 +43,9 @@ text_to_speech:
       voice: "michel"
       cache: True
 
-
+# Trigger engine configuration
+# Available engine are:
+# - snowboy
 triggers:
   - snowboy:
-      pmdl_file: "jarviss.pmdl"
+      pmdl_file: "trigger/snowboy/resources/jarviss.pmdl"

+ 18 - 2
test.py

@@ -1,10 +1,14 @@
 # coding=utf-8
 import os
 
+from core.ConfigurationManager import SettingLoader
 from core.CrontabManager import CrontabManager
 from core.OrderAnalyser import OrderAnalyser
 
 import logging
+
+from core.TriggerLauncher import TriggerLauncher
+
 logging.basicConfig()
 logger = logging.getLogger("jarvis")
 
@@ -19,5 +23,17 @@ logger = logging.getLogger("jarvis")
 #
 # os.system(cmd)
 
-crontab_manager = CrontabManager(brain_file="/home/nico/Documents/jarvis/test.yml")
-crontab_manager.load_events_in_crontab()
+# crontab_manager = CrontabManager(brain_file="/home/nico/Documents/jarvis/test.yml")
+# crontab_manager.load_events_in_crontab()
+
+
+def callback():
+    print "callback called"
+
+
+settings = SettingLoader.get_settings()
+
+
+for trigger in settings.triggers:
+    if trigger.name == settings.default_trigger_name:
+        TriggerLauncher.start_trigger(trigger, callback=callback)

+ 1 - 0
trigger/__init__.py

@@ -0,0 +1 @@
+from snowboy.snowboy import Snowboy

+ 1 - 0
trigger/snowboy/__init__.py

@@ -0,0 +1 @@
+from snowboy import Snowboy

+ 57 - 0
trigger/snowboy/snowboy.py

@@ -0,0 +1,57 @@
+from trigger.snowboy import snowboydecoder
+
+
+class MissingParameterException(Exception):
+    pass
+
+
+class Snowboy(object):
+
+    def __init__(self, **kwargs):
+        print "loaded"
+        # pause listening boolean
+        self.interrupted = False
+
+        # callback function to call when hotword caught
+        self.callback = kwargs.get('callback', None)
+        if self.callback is None:
+            raise MissingParameterException("callback function is required with snowboy")
+
+        # get the pmdl file to load
+        self.pmdl = kwargs.get('pmdl_file', None)
+
+        if self.pmdl is None:
+            raise MissingParameterException("Pmdl file is required with snowboy")
+
+    def interrupt_callback(self):
+        """
+        This function will be passed to snowboy to stop the main thread
+        :return:
+        """
+        return self.interrupted
+
+    def start(self):
+        """
+        Start the snowboy thread and wait for a Jarvis trigger word
+        :return:
+        """
+        print "started"
+        detector = snowboydecoder.HotwordDetector(self.pmdl, sensitivity=0.5)
+
+        # start snowboy loop
+        detector.start(detected_callback=self.callback,
+                       interrupt_check=self.interrupt_callback,
+                       sleep_time=0.03)
+
+        # we wait that a callback
+        detector.terminate()
+
+    def pause(self):
+        """
+        Stop the Snowboy main thread
+        :return:
+        """
+        self.interrupted = True
+
+    def unpause(self):
+        self.interrupted = False