Ver Fonte

update command neuron. Rename it "shell". Use parameter and can get the returned value

nico há 8 anos atrás
pai
commit
9fae93a8d9

+ 1 - 1
Docs/neuron_list.md

@@ -5,12 +5,12 @@ A neuron is a module you can use in your synapses. See the [complete neuron docu
 | Name                                               | Description                                                                             |
 |----------------------------------------------------|-----------------------------------------------------------------------------------------|
 | [ansible_task](../neurons/ansible_task/)           | Run an ansible playbook                                                                 |
-| [command](../neurons/command/)                     | Run a shell command                                                                     |
 | [gmail_checker](../neurons/gmail_checker/)         | Get the number of unread email and their subjects from a gmail account                  |
 | [kill_switch](../neurons/kill_switch/)             | Stop Jarvis process                                                                     |
 | [push_message](../neurons/push_message/)           | Send a push message to a remote device like Android/iOS/Windows Phone or Chrome browser |
 | [say](../neurons/say/)                             | Make Jarvis talk by using TTS                                                           |
 | [script](../neurons/script/)                       | Run an executable script                                                                |
+| [shell](../neurons/command/)                       | Run a shell command                                                                     |
 | [sleep](../neurons/sleep/)                         | Make Jarvis sleep for a while before continuing                                         |
 | [systemdate](../neurons/systemdate/)               | Give the local system date and time                                                     |
 | [tasker_autoremote](../neurons/tasker_autoremote/) | Send a message to Android tasker app                                                    |

+ 44 - 9
brain.yml

@@ -65,7 +65,8 @@
 
   - name: "Close rolling shutter"
     neurons:
-      - command: "curl http://192.168.0.22:5000/fermeture -d \"password=monpass\" -X POST"
+      - shell:
+          cmd: "curl http://192.168.0.22:5000/fermeture -d \"password=monpass\" -X POST"
       - say:
           message: "Fermeture en cours, monsieur"
     signals:
@@ -73,7 +74,8 @@
 
   - name: "Open rolling shutter"
     neurons:
-      - command: "curl http://192.168.0.22:5000/ouverture -d \"password=monpass\" -X POST"
+      - shell:
+          cmd: "curl http://192.168.0.22:5000/ouverture -d \"password=monpass\" -X POST"
       - say:
           message: "Ouverture en cours, monsieur"
     signals:
@@ -81,8 +83,10 @@
 
   - name: "Start steam"
     neurons:
-      - command: "curl -i --user admin:secret -H \"Content-Type: application/json\" -X POST -d '{\"app_name\":\"kodi\",\"state\":\"stop\"}' http://192.168.0.17:8000/app"
-      - command: "curl -i --user admin:secret -H \"Content-Type: application/json\" -X POST -d '{\"app_name\":\"steam\",\"state\":\"start\"}' http://192.168.0.17:8000/app"
+      - shell:
+          cmd: "curl -i --user admin:secret -H \"Content-Type: application/json\" -X POST -d '{\"app_name\":\"kodi\",\"state\":\"stop\"}' http://192.168.0.17:8000/app"
+      - shell:
+          cmd: "curl -i --user admin:secret -H \"Content-Type: application/json\" -X POST -d '{\"app_name\":\"steam\",\"state\":\"start\"}' http://192.168.0.17:8000/app"
       - say:
           message: "Lancement en cours, monsieur"
     signals:
@@ -90,8 +94,10 @@
 
   - name: "Start Kodi"
     neurons:
-      - command: "curl -i --user admin:secret -H \"Content-Type: application/json\" -X POST -d '{\"app_name\":\"steam\",\"state\":\"stop\"}' http://192.168.0.17:8000/app"
-      - command: "curl -i --user admin:secret -H \"Content-Type: application/json\" -X POST -d '{\"app_name\":\"kodi\",\"state\":\"start\"}' http://192.168.0.17:8000/app"
+      - shell:
+          cmd: "curl -i --user admin:secret -H \"Content-Type: application/json\" -X POST -d '{\"app_name\":\"steam\",\"state\":\"stop\"}' http://192.168.0.17:8000/app"
+      - shell:
+          cmd: "curl -i --user admin:secret -H \"Content-Type: application/json\" -X POST -d '{\"app_name\":\"kodi\",\"state\":\"start\"}' http://192.168.0.17:8000/app"
       - say:
           message: "Lancement en cours, monsieur"
     signals:
@@ -99,16 +105,18 @@
 
   - name: "Start music"
     neurons:
-      - command: "curl -i --user admin:secret -H \"Content-Type: application/json\" -X POST -d '{\"app_name\":\"music\",\"state\":\"start\"}' http://192.168.0.17:8000/app"
+      - shell:
+          cmd: "curl -i --user admin:secret -H \"Content-Type: application/json\" -X POST -d '{\"app_name\":\"music\",\"state\":\"start\"}' http://192.168.0.17:8000/app"
       - say:
-          message: "Musique lance, monsieur"
+          message: "Musique lancé, monsieur"
     signals:
       - order: "mais nous de la musique"
       - order: "musique rock"
 
   - name: "Stop music"
     neurons:
-      - command: "curl -i --user admin:secret -H \"Content-Type: application/json\" -X POST -d '{\"app_name\":\"music\",\"state\":\"stop\"}' http://192.168.0.17:8000/app"
+      - shell:
+          cmd: "curl -i --user admin:secret -H \"Content-Type: application/json\" -X POST -d '{\"app_name\":\"music\",\"state\":\"stop\"}' http://192.168.0.17:8000/app"
       - say:
           message: "musique stoppé, monsieur"
     signals:
@@ -162,3 +170,30 @@
           message: "lost"
     signals:
       - order: "où est mon téléphone"
+
+  - name: "test command"
+    neurons:
+      - shell:
+          cmd: "mplayer http://192.99.17.12:6410/"
+          async: True
+      - say:
+          message: "lancé"
+    signals:
+      - order: "test commande"
+
+  - name: "test stop"
+    neurons:
+      - shell:
+          cmd: "pkill mplayer"
+      - say:
+          message: "stopé"
+    signals:
+      - order: "test stop"
+
+  - name: "remove a file"
+    neurons:
+      - shell:
+          cmd: "rm ~/test.txt"
+          file_template: remove_file.j2
+    signals:
+      - order: "rm file"

+ 1 - 1
neurons/__init__.py

@@ -1,5 +1,5 @@
 from ansible_tasks import Ansible_tasks
-from command import Command
+from shell import Shell
 from kill_switch import Kill_switch
 from say import Say
 from script import Script

+ 0 - 1
neurons/command/__init__.py

@@ -1 +0,0 @@
-from command import Command

+ 0 - 12
neurons/command/command.py

@@ -1,12 +0,0 @@
-import subprocess
-
-from core.NeuronModule import NeuronModule
-
-
-class Command(NeuronModule):
-    def __init__(self, command, **kwargs):
-        super(Command, self).__init__(**kwargs)
-        p = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True)
-        (output, err) = p.communicate()
-
-

+ 105 - 0
neurons/shell/Readme.md

@@ -0,0 +1,105 @@
+# shell
+
+## Synopsis
+
+Run a shell command on the local system where Kalliope is installed.
+
+
+## Options
+
+| parameter | required | default | choices  | comment                                                                     |
+|-----------|----------|---------|----------|-----------------------------------------------------------------------------|
+| cmd       | yes      |         |          | The shell command to run                                                    |
+| async     | no       | False   |          | If True, Kalliope will not wait for the end of the execution of the command |
+
+
+## Return Values
+
+Values are only returned by the neuron if the async mode is set to `False`.
+
+| Name       | Description                                                                                           | Type   | sample                        |
+|------------|-------------------------------------------------------------------------------------------------------|--------|-------------------------------|
+| output     | The shell output of the command if any. The command "date" will retun "Sun Oct 16 15:50:45 CEST 2016" | string | Sun Oct 16 15:50:45 CEST 2016 |
+| returncode | The returned code of the command. Return 0 if the command was succesfuly exectued, else 1             | int    | 0                             |
+
+
+## Synapses example
+
+Simple that will create a file locally
+```
+  - name: "create a local file"
+    neurons:
+      - shell:
+          cmd: "touch ~/test.txt"
+    signals:
+      - order: "touch"
+```
+
+We want to launch our favorite web radio. This command, which it call mplayer, will block the entire Kalliope process if we 
+wait for the result unless the mplayer process is killed. So we add async parameter. 
+``` 
+  - name: "run web radio"
+    neurons:
+      - shell:
+          cmd: "mplayer http://192.99.17.12:6410/"
+          async: True
+      - say:
+          message: "web radio lanched"
+    signals:
+      - order: "run web radio"
+```
+If the parameter `async` is set to True, the neuron will not return any values.
+
+
+Then, we can kill the player process with another synapse
+```
+  - name: "stop web radio"
+    neurons:
+      - shell:
+          cmd: "pkill mplayer"
+      - say:
+          message: "web radio stopped"
+    signals:
+      - order: "stop web radio"
+```
+
+Make Kalliope add two number and speak out loud the result. Here you should hear "4".
+```
+  - name: "get the result of the addition: 1 + 3"
+    neurons:
+      - shell:
+          cmd: "echo $(expr \"1\" + \"3\")"
+          say_template: "{{ output }}"
+    signals:
+      - order: "addition"
+```
+
+Let's use a file template. We try to remove the file `~/test.txt` and make Kalliope gice us the result depending of the 
+returned error code.
+If the file is present on the system, you will hear "The command has succeeded" and so the file has been deleted. 
+If you run it a second time, the command will fail as the file is not anymore present and so you should hear 
+"The command has failed". See the template example bellow.
+```
+  - name: "remove a file"
+    neurons:
+      - shell:
+          cmd: "rm ~/test.txt"
+          file_template: remove_file.j2
+    signals:
+      - order: "rm file"
+```
+
+## Templates example 
+
+Template `remove_file.j2` used in the remove file example remove_file.j2
+```
+{% if returncode == 0 %}
+    The command succeeded
+{% else %}
+    The command failled
+{% endif %}
+```
+
+## Notes
+
+> **Note:** If the parameter `async` is set to True, the neuron will not return any values.

+ 1 - 0
neurons/shell/__init__.py

@@ -0,0 +1 @@
+from shell import Shell

+ 54 - 0
neurons/shell/shell.py

@@ -0,0 +1,54 @@
+import logging
+import subprocess
+import threading
+from core.NeuronModule import NeuronModule, MissingParameterException
+
+logging.basicConfig()
+logger = logging.getLogger("kalliope")
+
+
+class AsyncShell(threading.Thread):
+    def __init__(self, cmd):
+        self.stdout = None
+        self.stderr = None
+        self.cmd = cmd
+        threading.Thread.__init__(self)
+
+    def run(self):
+        p = subprocess.Popen(self.cmd,
+                             shell=True,
+                             stdout=subprocess.PIPE,
+                             stderr=subprocess.PIPE)
+
+        self.stdout, self.stderr = p.communicate()
+
+
+class Shell(NeuronModule):
+    def __init__(self, **kwargs):
+        super(Shell, self).__init__(**kwargs)
+
+        # get the command
+        cmd = kwargs.get('cmd', None)
+        # get if the user select a blocking command or not
+        async = kwargs.get('async', False)
+
+        if cmd is None:
+            raise MissingParameterException("cmd parameter required")
+
+        # run the command
+        if not async:
+            p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
+            (output, err) = p.communicate()
+            message = {
+                "output": output,
+                "returncode": p.returncode
+            }
+            self.say(message)
+
+        else:
+            async_shell = AsyncShell(cmd=cmd)
+            async_shell.start()
+
+
+
+

+ 5 - 0
templates/remove_file.j2

@@ -0,0 +1,5 @@
+{% if returncode == 0 %}
+    The command has succeeded
+{% else %}
+    The command has failed
+{% endif %}

+ 3 - 2
test.py

@@ -12,8 +12,9 @@ logger = logging.getLogger("kalliope")
 logger.setLevel(logging.DEBUG)
 
 
-
-order = "test heure"
+# order = "musique rock"
+# order = "stop la musique"
+order = "rm file"
 oa = OrderAnalyser(order)
 oa.start()