Browse Source

Merge pull request #68 from kalliope-project/dev

Dev
Nicolas Marcq 8 năm trước cách đây
mục cha
commit
1e19473049

+ 0 - 29
Docs/automated_install.md

@@ -1,29 +0,0 @@
-# kalliope automated install
-
-Clone the project
-```
-cd
-git clone https://github.com/kalliope-project/kalliope.git
-```
-
-Run the install script.
-```
-./kalliope/install/install_kalliope.sh
-```
-
->**Note:** The install script must not be ran as root or with sudo. 
-You will be prompted to enter your sudo password during the installation process.
-
-To ensure that you can record your voice, run the following command to capture audio input from your microphone
-```
-rec test.wav
-```
-
-Press CTRL-C after capturing a sample of your voice.
-
-Then play the recorded audio file
-```
-play test.wav
-```
-
-If everything is ok, you can start playing with Kalliope. First, let's take a look to the [default settings](settings.md).

+ 0 - 47
Docs/dev_env_install.md

@@ -1,47 +0,0 @@
-# Dev environment installation
-
-This documentation aims at explaining step by step manual deployment of Kalliope.
-
-Tested env
-- Ubuntu 16.04
-- Raspbian Jessie 
-
-
-
-## Prerequisites
-
-### Packages installation
-To make Kalliope work, you will have to install a certain number of libraries
-
-On Ubuntu distribution :
-```
-sudo apt-get install python-pip python-dev libsmpeg0 libttspico-utils libsmpeg0 flac dialog libffi-dev libffi-dev libssl-dev portaudio19-dev build-essential libssl-dev libffi-dev sox libatlas3-base mplayer
-```
-
-### Test your env
-Run the following command to capture audio from your microphone
-```
-rec test.wav
-```
-
-Then play the recorded audio file
-```
-play test.wav
-```
-
-## Installation
-
-### Get the sources
-Clone the project
-```
-git clone https://github.com/kalliope-project/kalliope.git
-```
-
-### Python lib
-
-Install libs
-```
-sudo pip install -r install/files/python_requirements.txt
-```
-
-If you are running kalliope on a Raspberry Pi, you must perform some other step by [following the dedicated documentation](RPi.md).

+ 54 - 0
Docs/installation/debian_jessie.md

@@ -0,0 +1,54 @@
+# Kalliope installation on Debian Jessie
+
+## Automated install
+
+Clone the project
+```
+cd
+git clone https://github.com/kalliope-project/kalliope.git
+```
+
+Edit `/etc/apt/sources.list` and check that your mirror accept "non-free" package
+```
+deb http://ftp.fr.debian.org/debian/ jessie main contrib non-free
+deb-src http://ftp.fr.debian.org/debian/ jessie main contrib non-free
+```
+
+Run the install script.
+```
+./kalliope/install/install_kalliope.sh
+```
+
+## Manual install
+
+To make Kalliope work, you will have to install a certain number of libraries:
+```
+sudo apt-get update
+sudo apt-get install git python-pip python-dev libsmpeg0 libttspico-utils libsmpeg0 flac dialog libffi-dev libffi-dev libssl-dev portaudio19-dev build-essential libssl-dev libffi-dev sox libatlas3-base mplayer
+```
+
+Clone the project
+```
+git clone https://github.com/kalliope-project/kalliope.git
+```
+
+Install libs
+```
+sudo pip install -r install/files/python_requirements.txt
+```
+
+## Test your env
+
+To ensure that you can record your voice, run the following command to capture audio input from your microphone
+```
+rec test.wav
+```
+
+Press CTRL-C after capturing a sample of your voice.
+
+Then play the recorded audio file
+```
+mplayer test.wav
+```
+
+If everything is ok, you can start playing with Kalliope. First, take a look to the [default settings](settings.md).

+ 42 - 2
Docs/RPi.md → Docs/installation/raspbian_jessie.md

@@ -1,3 +1,36 @@
+# Kalliope installation on Raspbian
+
+## Automated install
+
+Clone the project
+```
+cd
+git clone https://github.com/kalliope-project/kalliope.git
+```
+
+Run the install script.
+```
+./kalliope/install/install_kalliope.sh
+```
+
+## Manual install
+
+To make Kalliope work, you will have to install a certain number of libraries:
+```
+sudo apt-get update
+sudo apt-get install git python-pip python-dev libsmpeg0 libttspico-utils libsmpeg0 flac dialog libffi-dev libffi-dev libssl-dev portaudio19-dev build-essential libssl-dev libffi-dev sox libatlas3-base mplayer
+```
+
+Clone the project
+```
+git clone https://github.com/kalliope-project/kalliope.git
+```
+
+Install libs
+```
+sudo pip install -r install/files/python_requirements.txt
+```
+
 # Raspberry Pi configuration
 
 This documentation deals with the special configuration needed for get kalliope working on a RPi.
@@ -88,13 +121,20 @@ Restart alsa to apply changes
 sudo /etc/init.d/alsa-utils restart
 ```
 
-Do not forget to test recording your voice:
+You can adjust the microphone sensibility by running alsamixer:
+```
+alsamixer
+```
+And then select your microphone device by pressing F6 and finally move up the `mic` sensibility level
+![logo](../../images/alsamixer_mic_level.png)
 
-Capture audio from your microphone
+To ensure that you can record your voice, run the following command to capture audio input from your microphone
 ```
 rec test.wav
 ```
 
+Press CTRL-C after capturing a sample of your voice.
+
 Then play the recorded audio file
 ```
 mplayer test.wav

+ 48 - 0
Docs/installation/ubuntu_16.04.md

@@ -0,0 +1,48 @@
+# Kalliope installation on Ubuntu 16.04
+
+## Automated install
+
+Clone the project
+```
+cd
+git clone https://github.com/kalliope-project/kalliope.git
+```
+
+Run the install script.
+```
+./kalliope/install/install_kalliope.sh
+```
+
+## Manual install
+
+To make Kalliope work, you will have to install a certain number of libraries:
+```
+sudo apt-get update
+sudo apt-get install git python-pip python-dev libsmpeg0 libttspico-utils libsmpeg0 flac dialog libffi-dev libffi-dev libssl-dev portaudio19-dev build-essential libssl-dev libffi-dev sox libatlas3-base mplayer
+```
+
+Clone the project
+```
+git clone https://github.com/kalliope-project/kalliope.git
+```
+
+Install libs
+```
+sudo pip install -r install/files/python_requirements.txt
+```
+
+## Test your env
+
+To ensure that you can record your voice, run the following command to capture audio input from your microphone
+```
+rec test.wav
+```
+
+Press CTRL-C after capturing a sample of your voice.
+
+Then play the recorded audio file
+```
+mplayer test.wav
+```
+
+If everything is ok, you can start playing with Kalliope. First, take a look to the [default settings](settings.md).

+ 0 - 1
Docs/microphone_rpi.md

@@ -1 +0,0 @@
-# Tested microphone on Rpi

+ 4 - 4
README.md

@@ -8,7 +8,7 @@ Kalliope is based on audio input recognition, so it recognize an order pronounce
 You can create your own Kalliope bot, by simply choosing and composing the existing modules without writing any code. But, if you need a particular module, you can
 write it by yourself and add it to your project. You can also propose it to the community.
 
-Kalliope can run on all Linux distribution including a Raspberry Pi and it's multi-lang. The only thing you need is a microphone.
+Kalliope can run on all Linux Debian based distribution including a Raspberry Pi and it's multi-lang. The only thing you need is a microphone.
 
 Kalliope is easy-peasy to use, see the hello world
 ```
@@ -22,9 +22,9 @@ Kalliope is easy-peasy to use, see the hello world
 
 ## Installation
 
-- [Automated installation](Docs/automated_install.md)
-- [Manual installation for developement](Docs/dev_env_install.md)
-- [Raspberry Pi configuration](Docs/RPi.md)
+- [Raspbian Jessie(Raspberry pi)](Docs/installation/raspbian_jessie.md)
+- [Ubuntu 16.04](Docs/installation/ubuntu_16.04.md)
+- [Debian Jessie](Docs/installation/debian_jessie.md)
 
 ## Usage
 

+ 126 - 0
core/Tests/test_dynamic_loading.py

@@ -0,0 +1,126 @@
+import inspect
+import os
+import unittest
+
+
+class TestDynamicLoading(unittest.TestCase):
+
+    """
+    Test case for dynamic loading of python class
+    This is used to test we can successfully import:
+    - STT engine
+    - TTS engine
+    - Trigger engine
+    - All core neurons
+    """
+
+    def setUp(self):
+        # get current script directory path. We are in /an/unknown/path/kalliope/core/Tests
+        cur_script_directory = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
+        # get parent dir. Now we are in /an/unknown/path/kalliope
+        root_dir = os.path.normpath(cur_script_directory + os.sep + os.pardir + os.sep + os.pardir)
+
+        # get the neuron dir
+        self.neurons_dir = os.path.normpath(root_dir + os.sep + "neurons")
+
+        # get stt dir
+        self.stt_dir = os.path.normpath(root_dir + os.sep + "stt")
+
+        # get tts dir
+        self.tts_dir = os.path.normpath(root_dir + os.sep + "tts")
+
+        # get trigger dir
+        self.trigger_dir = os.path.normpath(root_dir + os.sep + "trigger")
+
+    def test_01_packages_present(self):
+        """
+        Check that the neurons folder exist in the root of the project
+        """
+        self.assertTrue(os.path.isdir(self.neurons_dir))
+        self.assertTrue(os.path.isdir(self.stt_dir))
+        self.assertTrue(os.path.isdir(self.tts_dir))
+        self.assertTrue(os.path.isdir(self.trigger_dir))
+
+    def test_02_can_import_neurons(self):
+        """
+        Try to import each neurons that are present in the neurons package
+        :return:
+        """
+        neurons = self.get_package_in_folder(self.neurons_dir)
+        package_name = "neurons"
+        for neuron_name in neurons:
+            module_name = neuron_name.capitalize()
+            self.dynamic_import(package_name, module_name)
+
+    def test_03_can_import_stt(self):
+        """
+        Try to import each neurons that are present in the neurons package
+        :return:
+        """
+        stts = self.get_package_in_folder(self.stt_dir)
+        package_name = "stt"
+        for stt_name in stts:
+            module_name = stt_name.capitalize()
+            self.dynamic_import(package_name, module_name)
+
+    def test_04_can_import_tts(self):
+        """
+        Try to import each neurons that are present in the neurons package
+        :return:
+        """
+        ttss = self.get_package_in_folder(self.tts_dir)
+        package_name = "tts"
+        for tts_name in ttss:
+            module_name = tts_name.capitalize()
+            self.dynamic_import(package_name, module_name)
+
+    def test_05_can_import_trigger(self):
+        """
+        Try to import each neurons that are present in the neurons package
+        :return:
+        """
+        triggers = self.get_package_in_folder(self.trigger_dir)
+        package_name = "trigger"
+        for trigger in triggers:
+            module_name = trigger.capitalize()
+            self.dynamic_import(package_name, module_name)
+
+    @staticmethod
+    def get_package_in_folder(folder):
+        """
+        receive a path in <folder>, return a list of package in that folder.
+        The function test if elements in that path are directory and return a list of those directory
+        :param folder: Path of a folder to return package
+        :return: list of package name
+        """
+        # get the list of neurons in the neurons packages
+        el_folder = os.listdir(folder)
+        # we keep only package. Because we have _init_.py or other stuff in what listdir returned
+        packages_in_folder = list()
+        for el in el_folder:
+            if os.path.isdir(folder + os.sep + el):
+                packages_in_folder.append(el)
+        return packages_in_folder
+
+    def dynamic_import(self, package_name, module_name):
+        """
+        Dynamic import of a module by its name.
+        package name can be:
+        - triggers
+        - neurons
+        - stt
+        - tts
+        :param package_name: name of the mother package
+        :param module_name: module name to load
+        :return:
+        """
+        module_name_with_path = package_name + "." + module_name.lower() + "." + module_name.lower()
+        mod = __import__(module_name_with_path, fromlist=[module_name])
+        try:
+            getattr(mod, module_name)
+        except AttributeError:
+            self.fail("The module %s does not exist in package %s" % (module_name, package_name))
+
+
+if __name__ == '__main__':
+    unittest.main()

BIN
images/alsamixer_mic_level.png


+ 35 - 25
neurons/ansible_playbook/ansible_playbook.py

@@ -4,32 +4,42 @@ from ansible.vars import VariableManager
 from ansible.inventory import Inventory
 from ansible.executor.playbook_executor import PlaybookExecutor
 
-from core.NeuronModule import NeuronModule
+from core.NeuronModule import NeuronModule, MissingParameterException
 
 
 class Ansible_playbook(NeuronModule):
-    def __init__(self, task_file, **kwargs):
+    def __init__(self, **kwargs):
         super(Ansible_playbook, self).__init__(**kwargs)
-        Options = namedtuple('Options',
-                             ['connection', 'forks', 'become', 'become_method', 'become_user', 'check', 'listhosts',
-                              'listtasks', 'listtags', 'syntax', 'module_path'])
-
-        variable_manager = VariableManager()
-        loader = DataLoader()
-        options = Options(connection='local', forks=100, become=None, become_method=None, become_user=None, check=False,
-                          listhosts=False, listtasks=False, listtags=False, syntax=False, module_path="")
-        passwords = dict(vault_pass='secret')
-
-        inventory = Inventory(loader=loader, variable_manager=variable_manager, host_list='localhost')
-        variable_manager.set_inventory(inventory)
-        playbooks = [task_file]
-
-        executor = PlaybookExecutor(
-            playbooks=playbooks,
-            inventory=inventory,
-            variable_manager=variable_manager,
-            loader=loader,
-            options=options,
-            passwords=passwords)
-
-        executor.run()
+
+        self.task_file = kwargs.get('task_file', None)
+
+        # check if parameters have been provided
+        if self._is_parameters_ok():
+
+            Options = namedtuple('Options',
+                                 ['connection', 'forks', 'become', 'become_method', 'become_user', 'check', 'listhosts',
+                                  'listtasks', 'listtags', 'syntax', 'module_path'])
+
+            variable_manager = VariableManager()
+            loader = DataLoader()
+            options = Options(connection='local', forks=100, become=None, become_method=None, become_user=None, check=False,
+                              listhosts=False, listtasks=False, listtags=False, syntax=False, module_path="")
+            passwords = dict(vault_pass='secret')
+
+            inventory = Inventory(loader=loader, variable_manager=variable_manager, host_list='localhost')
+            variable_manager.set_inventory(inventory)
+            playbooks = [self.task_file]
+
+            executor = PlaybookExecutor(
+                playbooks=playbooks,
+                inventory=inventory,
+                variable_manager=variable_manager,
+                loader=loader,
+                options=options,
+                passwords=passwords)
+
+            executor.run()
+
+    def _is_parameters_ok(self):
+        if self.task_file is None:
+            raise MissingParameterException("task_file parameter required")