From b5581fbdf43fa819bf387bdbef6ecd593f77be7c Mon Sep 17 00:00:00 2001 From: garethflynn Date: Thu, 28 Jan 2021 13:28:30 +0000 Subject: [PATCH 1/2] added ability to run local shell scripts --- harmony-span.js | 23 +++++++++++++++++++++++ public/config/scripts.js | 24 ++++++++++++++++++++++-- 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/harmony-span.js b/harmony-span.js index 1df0128..fad91b6 100644 --- a/harmony-span.js +++ b/harmony-span.js @@ -8,6 +8,7 @@ const request = require("request"); const mqtt = require("mqtt"); const yaml = require("node-yaml"); const ip = require("ip"); +const { exec } = require("child_process"); const CONFIG_FILE = "config.yaml"; const DEFAULT_HOST = "127.0.0.1"; @@ -216,6 +217,28 @@ function triggerAction(buttonFunction) { let button = conf.buttons[buttonIndex]; if (button.enabled) { switch (button.action) { + case "SCRIPT": + // check if script file exists + if (fs.existsSync(button.scriptLocation)) { + // file exists, so try to run it + colorout.log("debug", "Running script file: " + button.scriptLocation); + exec(button.scriptLocation, (error, stdout, stderr) => { + if (error){ + colorout.log("error", "Error running script file " + button.scriptLocation + ". Error Message:\n" + error.message); + return; + } + if (stderr){ + colorout.log("error", "Error running script file " + button.scriptLocation + ". STDERR:\n" + stderr); + return; + } + colorout.log("debug", "Output of script file " + button.scriptLocation + ":\n" + stdout); + }); + } + else{ + // file doesn't exist + colorout.log("error", "Script file " + button.scriptLocation + " doesn't exist.") + } + break; case "GET": request(button.url, function(error, response, body) { if (error != null) { diff --git a/public/config/scripts.js b/public/config/scripts.js index 0fb305d..5ad484a 100644 --- a/public/config/scripts.js +++ b/public/config/scripts.js @@ -8,7 +8,8 @@ var Button = Backbone.Model.extend({ mqttTopic: "", mqttMessage: "", action: "", - enabled: false + enabled: false, + scriptLocation: "" } }); @@ -41,6 +42,10 @@ var ButtonRowView = Backbone.View.extend({ "[<%= action %>] <%= mqttTopic %>\n" + "<%= mqttMessage %>\n" + "<% } %>" + + "<% if (action == \"SCRIPT\") { %>" + + "[<%= action %>] <%= scriptLocation %>\n" + + "<%= scriptLocation %>\n" + + "<% } %>" + "<%= enabled ? \"yes\" : \"no\" %>\n" + "\" class=\"edit btn btn-sm btn-primary\">edit" ), @@ -112,6 +117,7 @@ var ButtonConfigView = Backbone.View.extend({ "
\n" + "\n" + "\" placeholder=\"E.g. harmony\" requird>\n" + + "\" placeholder=\"E.g. harmony\" required>\n" + "
\n" + "
\n" + "\n" + "\n" + "
\n" + + "<% } else if (mode == \"SCRIPT\") { %>" + + "
\n" + + "\n" + + "\" placeholder=\"E.g. ./scripts/DisneyPlus.sh\" required>\n" + + "
\n" + "<% } %>" + "
\n" + " checked<% } %>>\n" + @@ -201,6 +212,15 @@ var ButtonConfigView = Backbone.View.extend({ mqttMessage : this.$el.find("#mqttMessage").val().trim(), enabled: enabled }); + } else if (action == "SCRIPT") { + this.model.clear(); + this.model.set({ + id: id, + name: name, + action: action, + scriptLocation: this.$el.find("#scriptLocation").val().trim(), + enabled: enabled + }); } this.model.save(); }, From fcd6fe97f6d2f8201369684ad65ce66aae0f5dfe Mon Sep 17 00:00:00 2001 From: garethflynn Date: Thu, 28 Jan 2021 13:38:46 +0000 Subject: [PATCH 2/2] added shell script info --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 55d68b8..edf2e13 100644 --- a/README.md +++ b/README.md @@ -36,8 +36,12 @@ In the Advanced Options menu (orange button), you can also add a body and header At this point you can do whatever you want with the buttons - To make your lights turn on and off when you play and pause a movie, just add the HarmonySpan buttons that are linked to your 'lights on' and 'lights off' webhook URLs with the Pause and Play buttons on the activity you use to watch a movie. For more information, check Logitech's documentation on creating button sequences. https://support.myharmony.com/en-es/creating-button-sequences +To trigger a shell script, edit a button, choose SCRIPT from the dropdown, enter the location of your script and check Enabled. You will need to ensure file permissions are appropriately set to allow Harmony Span to execute your scripts. + Click the Submit Settings button once you fill in all of the fields for the button you're working with. Switching buttons without submitting your changes will delete the new values you put in for the first button. + + ## How It Works Logitech allows you to control 'IP devices' over your local network (think Roku, NVIDIA SHIELD, Apple TV) rather than controlling them with IR. This works because each device broadcasts to a local Simple Service Discovery Protocol (SSDP) IP (``239.255.255.250``, chances are you can see traffic on it in your network with Wireshark) to let other devices in the network know that they can be controlled.