mirror of
https://github.com/node-red/node-red-nodes.git
synced 2023-10-10 13:36:58 +02:00
commit
de655a6dde
@ -16,13 +16,7 @@
|
|||||||
|
|
||||||
// Require main module
|
// Require main module
|
||||||
var RED = require(process.env.NODE_RED_HOME + "/red/red");
|
var RED = require(process.env.NODE_RED_HOME + "/red/red");
|
||||||
|
var bonescript = require("bonescript");
|
||||||
// Require bonescript
|
|
||||||
try {
|
|
||||||
var bonescript = require("bonescript");
|
|
||||||
} catch (err) {
|
|
||||||
require("util").log("[145-BBB-hardware] Error: cannot find module 'bonescript'");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Node constructor for bbb-analogue-in
|
// Node constructor for bbb-analogue-in
|
||||||
function AnalogueInputNode(n) {
|
function AnalogueInputNode(n) {
|
||||||
|
@ -52,10 +52,11 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script type="text/x-red" data-help-name="rpi-piface in">
|
<script type="text/x-red" data-help-name="rpi-piface in">
|
||||||
<p>Raspberry Pi PiFace input node. Generates a <b>msg.payload</b> with either a 0 or 1 depending on the state of the input pin. Requires the gpio command to work.</p>
|
<p>Raspberry Pi PiFace input node. Generates a <b>msg.payload</b> with either a 0 or 1 depending on the state of the input pin.</p>
|
||||||
<p>You may also enable the input pullup resitor if required.</p>
|
<p>You may also enable the input pullup resistor if required.</p>
|
||||||
<p>The <b>msg.topic</b> is set to <i>pi/{the pin number}</i></p>
|
<p>The <b>msg.topic</b> is set to <i>piface/{the pin number}</i></p>
|
||||||
<p><b>Note:</b> This node currently polls the pin every 250mS. This is not ideal as it loads the cpu, and will be rewritten shortly to try to use interrupts.</p>
|
<p>Requires the WiringPi gpio command in order to work.</p>
|
||||||
|
<p><b>Note:</b> This node currently polls the pin every 250mS. This is not ideal as it loads the cpu.</p>
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
@ -103,9 +104,9 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script type="text/x-red" data-help-name="rpi-piface out">
|
<script type="text/x-red" data-help-name="rpi-piface out">
|
||||||
<p>Raspberry Pi PiFace output node. The PiFace board must be fitted. Requires the gpio command to work.</p>
|
<p>Raspberry Pi PiFace output node. The PiFace board must be fitted.</p>
|
||||||
<p>Expects a <b>msg.payload</b> with either a 0 or 1 (or true or false).</p>
|
<p>Will set the selected relay, LED, or pin on or off depending on the value passed in. Expects a <b>msg.payload</b> with either a 1 or 0 (or true or false).</p>
|
||||||
<p>Will set the selected relay, LED, or pin on or off depending on the value passed in.</p>
|
<p>Requires the WiringPi gpio command in order to work.</p>
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
@ -57,6 +57,33 @@ var pintable = {
|
|||||||
"LED 6":"206",
|
"LED 6":"206",
|
||||||
"LED 7":"207"
|
"LED 7":"207"
|
||||||
}
|
}
|
||||||
|
var tablepin = {
|
||||||
|
// WiringPi : Physical
|
||||||
|
"200":"S1",
|
||||||
|
"201":"S2",
|
||||||
|
"202":"S3",
|
||||||
|
"203":"S4",
|
||||||
|
"204":"I5",
|
||||||
|
"205":"I6",
|
||||||
|
"206":"I7",
|
||||||
|
"207":"I8",
|
||||||
|
"208":"O0",
|
||||||
|
"209":"O1",
|
||||||
|
"210":"O2",
|
||||||
|
"211":"O3",
|
||||||
|
"212":"O4",
|
||||||
|
"213":"O5",
|
||||||
|
"214":"O6",
|
||||||
|
"215":"O7",
|
||||||
|
"200":"L0",
|
||||||
|
"201":"L1",
|
||||||
|
"202":"L2",
|
||||||
|
"203":"L3",
|
||||||
|
"204":"L4",
|
||||||
|
"205":"L5",
|
||||||
|
"206":"L6",
|
||||||
|
"207":"L7"
|
||||||
|
}
|
||||||
|
|
||||||
function PiFACEInNode(n) {
|
function PiFACEInNode(n) {
|
||||||
RED.nodes.createNode(this,n);
|
RED.nodes.createNode(this,n);
|
||||||
@ -76,7 +103,7 @@ function PiFACEInNode(n) {
|
|||||||
var previousState = node.buttonState;
|
var previousState = node.buttonState;
|
||||||
node.buttonState = Number(stdout);
|
node.buttonState = Number(stdout);
|
||||||
if (previousState !== -1) {
|
if (previousState !== -1) {
|
||||||
var msg = {topic:"pi/"+node.pin, payload:node.buttonState};
|
var msg = {topic:"piface/"+tablepin[node.pin], payload:node.buttonState};
|
||||||
node.send(msg);
|
node.send(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
111
hardware/Pi/38-rpi-pibrella.html
Normal file
111
hardware/Pi/38-rpi-pibrella.html
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
<!--
|
||||||
|
Copyright 2014 IBM Corp.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<script type="text/x-red" data-template-name="rpi-pibrella in">
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-pin"><i class="icon-asterisk"></i> Input</label>
|
||||||
|
<select type="text" id="node-input-pin" style="width: 150px;">
|
||||||
|
<option value="-">select input</option>
|
||||||
|
<option value="Red Button">Red Button</option>
|
||||||
|
<option value="In A">In A</option>
|
||||||
|
<option value="In B">In B</option>
|
||||||
|
<option value="In C">In C</option>
|
||||||
|
<option value="In D">In D</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||||
|
<input type="text" id="node-input-name" placeholder="Name">
|
||||||
|
</div>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/x-red" data-help-name="rpi-pibrella in">
|
||||||
|
<p>Raspberry Pi Pibrella input node. Generates a <b>msg.payload</b> with either a 0 or 1 depending on the state of the input pin.</p>
|
||||||
|
<p>The <b>msg.topic</b> is set to <i>pibrella/{the pin id}</i>, A, B, C, D or R</p>
|
||||||
|
<p><b>Note:</b> This node currently polls the pin every 250mS. This is not ideal as it loads the cpu.</p>
|
||||||
|
<p>Requires the WiringPi gpio command in order to work.</p>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
RED.nodes.registerType('rpi-pibrella in',{
|
||||||
|
category: 'advanced-input',
|
||||||
|
color:"#c6dbef",
|
||||||
|
defaults: {
|
||||||
|
name: { value:"" },
|
||||||
|
pin: { value:"",required:true,validate:RED.validators.regex(/ /) }
|
||||||
|
},
|
||||||
|
inputs:0,
|
||||||
|
outputs:1,
|
||||||
|
icon: "rpi.png",
|
||||||
|
label: function() {
|
||||||
|
return this.name||this.pin||"Pibrella";
|
||||||
|
},
|
||||||
|
labelStyle: function() {
|
||||||
|
return this.name?"node_label_italic":"";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
<script type="text/x-red" data-template-name="rpi-pibrella out">
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-pin"><i class="icon-asterisk"></i> Output</label>
|
||||||
|
<select type="text" id="node-input-pin" style="width: 150px;">
|
||||||
|
<option value="-">select output</option>
|
||||||
|
<option value="Red LED">Red LED</option>
|
||||||
|
<option value="Amber LED">Amber LED</option>
|
||||||
|
<option value="Green LED">Green LED</option>
|
||||||
|
<option value="Out E">Out E</option>
|
||||||
|
<option value="Out F">Out F</option>
|
||||||
|
<option value="Out G">Out G</option>
|
||||||
|
<option value="Out H">Out H</option>
|
||||||
|
<option value="Buzzer ">Buzzer</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||||
|
<input type="text" id="node-input-name" placeholder="Name">
|
||||||
|
</div>
|
||||||
|
<div class="form-tips">Buzzer takes <b>msg.payload</b> between 2 (high) and 512 (low), or 0 for off.</div>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/x-red" data-help-name="rpi-pibrella out">
|
||||||
|
<p>Raspberry Pi Pibrella output node. The Pibrella board must be fitted.</p>
|
||||||
|
<p>Will set the selected output high (on) or low (off) depending on the value passed in. Expects a <b>msg.payload</b> with either a 0 or 1 (or true or false).</p>
|
||||||
|
<p>The Buzzer is a divider so low numbers are high notes. 0 is off, and the sensible lowest note is around 250-300. 2 is the highest note. 1 is just a buzz (so you can use 0/1 type inputs).</p>
|
||||||
|
<p>Requires the WiringPi gpio command in order to work.</p>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
RED.nodes.registerType('rpi-pibrella out',{
|
||||||
|
category: 'advanced-output',
|
||||||
|
color:"#c6dbef",
|
||||||
|
defaults: {
|
||||||
|
name: { value:"" },
|
||||||
|
pin: { value:"",required:true,validate:RED.validators.regex(/ /) }
|
||||||
|
},
|
||||||
|
inputs:1,
|
||||||
|
outputs:0,
|
||||||
|
icon: "rpi.png",
|
||||||
|
align: "right",
|
||||||
|
label: function() {
|
||||||
|
return this.name||this.pin||"Pibrella";
|
||||||
|
},
|
||||||
|
labelStyle: function() {
|
||||||
|
return this.name?"node_label_italic":"";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
172
hardware/Pi/38-rpi-pibrella.js
Normal file
172
hardware/Pi/38-rpi-pibrella.js
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2014 IBM Corp.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
**/
|
||||||
|
|
||||||
|
var RED = require(process.env.NODE_RED_HOME+"/red/red");
|
||||||
|
var util = require("util");
|
||||||
|
var exec = require('child_process').exec;
|
||||||
|
var fs = require('fs');
|
||||||
|
|
||||||
|
if (!fs.existsSync("/dev/ttyAMA0")) { // unlikely if not on a Pi
|
||||||
|
throw "Info : Ignoring Raspberry Pi specific node.";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fs.existsSync("/usr/local/bin/gpio")) { // gpio command not installed
|
||||||
|
throw "Info : Can't find Raspberry Pi wiringPi gpio command.";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map physical P1 pins to Gordon's Wiring-Pi Pins (as they should be V1/V2 tolerant)
|
||||||
|
var pintable = {
|
||||||
|
// Physical : WiringPi
|
||||||
|
"Amber LED":"0",
|
||||||
|
"Buzzer ":"1",
|
||||||
|
"Red LED":"2",
|
||||||
|
"Out E":"3",
|
||||||
|
"Out F":"4",
|
||||||
|
"Out G":"5",
|
||||||
|
"Out H":"6",
|
||||||
|
"Green LED":"7",
|
||||||
|
"In C":"10",
|
||||||
|
"In B":"11",
|
||||||
|
"In D":"12",
|
||||||
|
"In A":"13",
|
||||||
|
"Red Button":"14",
|
||||||
|
}
|
||||||
|
var tablepin = {
|
||||||
|
// WiringPi : Physical
|
||||||
|
"0":"Amber",
|
||||||
|
"1":"Buzzer",
|
||||||
|
"2":"Red",
|
||||||
|
"3":"E",
|
||||||
|
"4":"F",
|
||||||
|
"5":"G",
|
||||||
|
"6":"H",
|
||||||
|
"7":"Green",
|
||||||
|
"10":"C",
|
||||||
|
"11":"B",
|
||||||
|
"12":"D",
|
||||||
|
"13":"A",
|
||||||
|
"14":"R",
|
||||||
|
}
|
||||||
|
|
||||||
|
function PibrellaIn(n) {
|
||||||
|
RED.nodes.createNode(this,n);
|
||||||
|
this.buttonState = -1;
|
||||||
|
this.pin = pintable[n.pin];
|
||||||
|
var node = this;
|
||||||
|
|
||||||
|
if (this.pin) {
|
||||||
|
exec("gpio mode "+node.pin+" in", function(err,stdout,stderr) {
|
||||||
|
if (err) node.error(err);
|
||||||
|
else {
|
||||||
|
node._interval = setInterval( function() {
|
||||||
|
exec("gpio read "+node.pin, function(err,stdout,stderr) {
|
||||||
|
if (err) node.error(err);
|
||||||
|
else {
|
||||||
|
if (node.buttonState !== Number(stdout)) {
|
||||||
|
var previousState = node.buttonState;
|
||||||
|
node.buttonState = Number(stdout);
|
||||||
|
if (previousState !== -1) {
|
||||||
|
var msg = {topic:"pibrella/"+tablepin[node.pin], payload:node.buttonState};
|
||||||
|
node.send(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, 200);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.error("Invalid GPIO pin: "+this.pin);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.on("close", function() {
|
||||||
|
clearInterval(this._interval);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function PibrellaOut(n) {
|
||||||
|
RED.nodes.createNode(this,n);
|
||||||
|
this.pin = pintable[n.pin];
|
||||||
|
var node = this;
|
||||||
|
|
||||||
|
if (this.pin == "1") {
|
||||||
|
exec("gpio mode 1 pwm");
|
||||||
|
process.nextTick(function() {
|
||||||
|
exec("gpio pwm-ms");
|
||||||
|
node.on("input", function(msg) {
|
||||||
|
var out = Number(msg.payload);
|
||||||
|
if (out == 1) { // fixed buzz
|
||||||
|
exec("gpio pwm 1 511");
|
||||||
|
exec("gpio pwmc 100");
|
||||||
|
}
|
||||||
|
else if ((out >= 2) && (out <= 9999)) { // set buzz to a value
|
||||||
|
exec("gpio pwm 1 511");
|
||||||
|
exec("gpio pwmc "+out);
|
||||||
|
}
|
||||||
|
else { exec("gpio pwm 1 0"); } // turn it off
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if (this.pin) {
|
||||||
|
process.nextTick(function() {
|
||||||
|
exec("gpio mode "+node.pin+" out", function(err,stdout,stderr) {
|
||||||
|
if (err) node.error(err);
|
||||||
|
else {
|
||||||
|
node.on("input", function(msg) {
|
||||||
|
if (msg.payload === "true") msg.payload = true;
|
||||||
|
if (msg.payload === "false") msg.payload = false;
|
||||||
|
var out = Number(msg.payload);
|
||||||
|
if ((out == 0)|(out == 1)) {
|
||||||
|
exec("gpio write "+node.pin+" "+out, function(err,stdout,stderr) {
|
||||||
|
if (err) node.error(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else node.warn("Invalid input - not 0 or 1");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.error("Invalid GPIO pin: "+this.pin);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.on("close", function() {
|
||||||
|
exec("gpio mode "+this.pin+" in");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
exec("gpio mode 0 out",function(err,stdout,stderr) {
|
||||||
|
if (err) {
|
||||||
|
util.log('[36-rpi-gpio.js] Error: "gpio" command failed for some reason.');
|
||||||
|
}
|
||||||
|
exec("gpio mode 1 out");
|
||||||
|
exec("gpio mode 2 out");
|
||||||
|
exec("gpio mode 3 out");
|
||||||
|
exec("gpio mode 4 out");
|
||||||
|
exec("gpio mode 5 out");
|
||||||
|
exec("gpio mode 6 out");
|
||||||
|
exec("gpio mode 7 out");
|
||||||
|
exec("gpio mode 10 in");
|
||||||
|
exec("gpio mode 11 in");
|
||||||
|
exec("gpio mode 12 in");
|
||||||
|
exec("gpio mode 13 in");
|
||||||
|
exec("gpio mode 14 in");
|
||||||
|
});
|
||||||
|
|
||||||
|
RED.nodes.registerType("rpi-pibrella in",PibrellaIn);
|
||||||
|
RED.nodes.registerType("rpi-pibrella out",PibrellaOut);
|
@ -27,6 +27,8 @@
|
|||||||
<p>See <i><a href="http://www.piborg.com/ledborg/install" target="_new">the PiBorg site</a></i> for more information.</p>
|
<p>See <i><a href="http://www.piborg.com/ledborg/install" target="_new">the PiBorg site</a></i> for more information.</p>
|
||||||
<p>You can also now use a <b>msg.payload</b> in the standard hex format "#rrggbb". The clip levels are :</p>
|
<p>You can also now use a <b>msg.payload</b> in the standard hex format "#rrggbb". The clip levels are :</p>
|
||||||
<p><pre>0x00 - 0x57 = off<br/>0x58 - 0xA7 = 50%<br/>0xA8 - 0xFF = fully on</pre></p>
|
<p><pre>0x00 - 0x57 = off<br/>0x58 - 0xA7 = 50%<br/>0xA8 - 0xFF = fully on</pre></p>
|
||||||
|
<p>You can also use the @cheerlight colour names - red, amber, green, blue, cyan, magenta, yeloow, orange, pink, purple,
|
||||||
|
white, warmwhite, black</p>
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
@ -20,8 +20,7 @@ var fs = require('fs');
|
|||||||
|
|
||||||
// check if /dev/ledborg exists - if not then don't even show the node.
|
// check if /dev/ledborg exists - if not then don't even show the node.
|
||||||
if (!fs.existsSync("/dev/ledborg")) {
|
if (!fs.existsSync("/dev/ledborg")) {
|
||||||
util.log("[78-ledborg.js] Warning: PiBorg hardware : LedBorg not found");
|
throw "Info : PiBorg hardware : LedBorg not found";
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function LedBorgNode(n) {
|
function LedBorgNode(n) {
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
|
|
||||||
|
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<script type="text/x-red" data-template-name="Discover">
|
<script type="text/x-red" data-template-name="Discover">
|
||||||
@ -28,27 +29,25 @@
|
|||||||
|
|
||||||
<!-- Next, some simple help text is provided for the node. -->
|
<!-- Next, some simple help text is provided for the node. -->
|
||||||
<script type="text/x-red" data-help-name="Discover">
|
<script type="text/x-red" data-help-name="Discover">
|
||||||
<p>This node looks for a Philips Hue Bridge in the local network.</p>
|
<p>This node looks for a Philips Hue Bridge in the local network.</p><p> The node has 2 outputs, the first one contains the IP address of the first discovered bridge and the second one the lights registered to that bridge (in JSON format).</p> <p>To use the node you need to have obtained a valid auth token (or username) from your Philips Hue Bridge. Read <a href="http://developers.meethue.com/gettingstarted.html" target="_blank">here</a> on how to do this.</p>
|
||||||
<p> The node has 2 outputs, the first one contains the IP address of the first discovered bridge and the second one the lights registered to that bridge (in JSON format).</p>
|
|
||||||
<p>To use the node you need to have obtained a valid auth token (or username) from your Philips Hue Bridge. Read <a href="http://developers.meethue.com/gettingstarted.html" target="_blank">here</a> on how to do this.</p>
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- Finally, the node type is registered along with all of its properties -->
|
<!-- Finally, the node type is registered along with all of its properties -->
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
RED.nodes.registerType('Discover',{
|
RED.nodes.registerType('Discover',{
|
||||||
category: 'advanced-input',
|
category: 'advanced-input', // the palette category
|
||||||
color:"#EFEFEF",
|
color:"#EFEFEF",
|
||||||
defaults: {
|
defaults: { // defines the editable properties of the node
|
||||||
name: {value:""},
|
name: {value:""}, // along with default values.
|
||||||
username: {value:"", required:true}
|
username: {value:"", required:true}
|
||||||
},
|
},
|
||||||
inputs:1,
|
inputs:1, // set the number of inputs - only 0 or 1
|
||||||
outputs:2,
|
outputs:2, // set the number of outputs - 0 to n
|
||||||
icon: "hue.png",
|
icon: "huediscover.png", // set the icon (held in public/icons)
|
||||||
label: function() {
|
label: function() { // sets the default label contents
|
||||||
return this.name||"Discover";
|
return this.name||this.topic||"Discover";
|
||||||
},
|
},
|
||||||
labelStyle: function() {
|
labelStyle: function() { // sets the class to apply to the label
|
||||||
return this.name?"node_label_italic":"";
|
return this.name?"node_label_italic":"";
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
|
|
||||||
|
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<script type="text/x-red" data-template-name="HueNode">
|
<script type="text/x-red" data-template-name="HueNode">
|
||||||
@ -35,6 +36,11 @@
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-brightness"><i class="icon-tag"></i>Change Brightness (0->100):</label>
|
||||||
|
<input type="text" id="node-input-brightness" placeholder="brightness">
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="form-row">
|
<div class="form-row">
|
||||||
<label for="node-input-color"><i class="icon-tag"></i>Select color:</label>
|
<label for="node-input-color"><i class="icon-tag"></i>Select color:</label>
|
||||||
<input type="text" id="node-input-color" placeholder="color">
|
<input type="text" id="node-input-color" placeholder="color">
|
||||||
@ -50,29 +56,38 @@
|
|||||||
<script type="text/x-red" data-help-name="HueNode">
|
<script type="text/x-red" data-help-name="HueNode">
|
||||||
<p>This node implements some basic functionality for managing a Philips Hue wireless Lamp system.</p>
|
<p>This node implements some basic functionality for managing a Philips Hue wireless Lamp system.</p>
|
||||||
<p>To use it you need to have obtained a valid auth token (or username) from your Philips Hue Bridge. Read <a href="http://developers.meethue.com/gettingstarted.html" target="_blank">here</a> on how to do this.</p>
|
<p>To use it you need to have obtained a valid auth token (or username) from your Philips Hue Bridge. Read <a href="http://developers.meethue.com/gettingstarted.html" target="_blank">here</a> on how to do this.</p>
|
||||||
<p>You can enter the ID (1, 2, ...) of a Lamp and turn it ON or OFF and also set its color. </p><p>By setting the status to AUTO, you can set the ON/OFF status as a message payload (e.g., msg.payload="ON") and the color through the message topic (e.g., msg.topic="EBF5FF") on the node input. Please note, in case you use both, the status selection overides the msg.payload!</p><p>Also, if you pass something like msg.payload="ALERT" the Lamp will flash once.</p>
|
<p>You can enter the ID (1, 2, ...) of a Lamp and turn it ON or OFF, set the color and the brightness (0->100). </p><p>By setting the status to AUTO, you can set the lamp parameters using the message on the input node as follows:</p>
|
||||||
|
<ul>
|
||||||
|
<li>msg.lamp sets the lamp ID</li>
|
||||||
|
<li>msg.color sets the lamp color (e.g., msg.color="DF0101" will set the color to red)</li>
|
||||||
|
<li>msg.brightness sets the lamp brightness (e.g., msg.brightness=50)</li>
|
||||||
|
<li>msg.payload is used to se the lamp status (on/off/alert) (e.g., msg.payload="alert" will flash the Lamp once</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p>Please note, by setting the status to AUTO on the node configuration, the rest of the node parameters are ignored, you need to set all parameters through the message input.</p>
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- Finally, the node type is registered along with all of its properties -->
|
<!-- Finally, the node type is registered along with all of its properties -->
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
RED.nodes.registerType('HueNode',{
|
RED.nodes.registerType('HueNode',{
|
||||||
category: 'advanced-input',
|
category: 'advanced-input', // the palette category
|
||||||
color:"#EFEFEF",
|
color:"#EFEFEF",
|
||||||
defaults: {
|
defaults: { // defines the editable properties of the node
|
||||||
name: {value:""},
|
name: {value:""}, // along with default values.
|
||||||
username: {value:"", required:true},
|
username: {value:"", required:true},
|
||||||
discovery_mode: {value: "", required:false},
|
discovery_mode: {value: "", required:false},
|
||||||
lamp_id: {value:"", required:false},
|
lamp_id: {value:"", required:false},
|
||||||
color: {value:"EBF5FF"},
|
color: {value:"EBF5FF"},
|
||||||
|
brightness: {value:"100"},
|
||||||
lamp_status:{}
|
lamp_status:{}
|
||||||
},
|
},
|
||||||
inputs:1,
|
inputs:1, // set the number of inputs - only 0 or 1
|
||||||
outputs:1,
|
outputs:1, // set the number of outputs - 0 to n
|
||||||
icon: "hue.png",
|
icon: "huemanage.png", // set the icon (held in public/icons)
|
||||||
label: function() {
|
label: function() { // sets the default label contents
|
||||||
return this.name||"HueNode";
|
return this.name||this.topic||"HueNode";
|
||||||
},
|
},
|
||||||
labelStyle: function() {
|
labelStyle: function() { // sets the class to apply to the label
|
||||||
return this.name?"node_label_italic":"";
|
return this.name?"node_label_italic":"";
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -18,14 +18,19 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
**/
|
**/
|
||||||
|
|
||||||
|
|
||||||
//Require node-hue-api
|
//Require node-hue-api
|
||||||
var hue = require("node-hue-api");
|
var hue = require("node-hue-api");
|
||||||
var HueApi = require("node-hue-api").HueApi;
|
var HueApi = require("node-hue-api").HueApi;
|
||||||
|
|
||||||
|
// Require main module
|
||||||
var RED = require(process.env.NODE_RED_HOME+"/red/red");
|
var RED = require(process.env.NODE_RED_HOME+"/red/red");
|
||||||
|
|
||||||
//store the IP address of the Hue Gateway
|
//store the IP address of the Hue Gateway
|
||||||
var gw_ipaddress = "";
|
var gw_ipaddress = "";
|
||||||
var username, lamp_status, lamp_id, color;
|
|
||||||
|
|
||||||
|
var username, lamp_status, lamp_id, color, brightness;
|
||||||
|
|
||||||
function hexToRgb(hex) {
|
function hexToRgb(hex) {
|
||||||
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
||||||
@ -36,21 +41,32 @@ function hexToRgb(hex) {
|
|||||||
} : null;
|
} : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// The main node definition - most things happen in here
|
// The main node definition - most things happen in here
|
||||||
function HueNode(n) {
|
function HueNode(n) {
|
||||||
// Create a RED node
|
// Create a RED node
|
||||||
RED.nodes.createNode(this,n);
|
RED.nodes.createNode(this,n);
|
||||||
|
|
||||||
|
var node = this;
|
||||||
|
|
||||||
//get parameters from user
|
//get parameters from user
|
||||||
this.username = n.username;
|
this.username = n.username;
|
||||||
this.lamp_status = n.lamp_status;
|
this.lamp_status = n.lamp_status;
|
||||||
this.lamp_id = n.lamp_id;
|
this.lamp_id = n.lamp_id;
|
||||||
this.color = n.color;
|
this.color = n.color;
|
||||||
var node = this;
|
this.brightness = n.brightness;
|
||||||
|
|
||||||
|
|
||||||
|
// Store local copies of the node configuration (as defined in the .html)
|
||||||
|
this.topic = n.topic;
|
||||||
|
|
||||||
|
|
||||||
var msg = {};
|
var msg = {};
|
||||||
|
|
||||||
|
msg.topic = this.topic;
|
||||||
|
|
||||||
this.on("input", function(msg){
|
this.on("input", function(msg){
|
||||||
|
var myMsg = msg;
|
||||||
//set the lamp status
|
//set the lamp status
|
||||||
//first locate the Hue gateway:
|
//first locate the Hue gateway:
|
||||||
hue.locateBridges(function(err, result) {
|
hue.locateBridges(function(err, result) {
|
||||||
@ -63,35 +79,62 @@ function HueNode(n) {
|
|||||||
//save the IP address of the 1st bridge found
|
//save the IP address of the 1st bridge found
|
||||||
this.gw_ipaddress = result[0].ipaddress;
|
this.gw_ipaddress = result[0].ipaddress;
|
||||||
|
|
||||||
|
|
||||||
//set light status
|
//set light status
|
||||||
var api = new HueApi(this.gw_ipaddress, node.username);
|
var api = new HueApi(this.gw_ipaddress, node.username);
|
||||||
var lightState = hue.lightState;
|
var lightState = hue.lightState;
|
||||||
var state = lightState.create();
|
var state = lightState.create();
|
||||||
|
|
||||||
var status;
|
var status;
|
||||||
if(msg.payload=="ALERT"){
|
var lamp = -1;
|
||||||
status = "ALERT";
|
|
||||||
|
//check for AUTO status (lamp settings set through node input)
|
||||||
|
if(node.lamp_status=="AUTO") {
|
||||||
|
var color;
|
||||||
|
var brightness;
|
||||||
|
|
||||||
|
//get lamp id from msg.lamp:
|
||||||
|
lamp = myMsg.lamp;
|
||||||
|
|
||||||
|
//get brightness:
|
||||||
|
brightness = myMsg.brightness;
|
||||||
|
|
||||||
|
//get colour either from msg.color or msg.topic
|
||||||
|
if(myMsg.color!=null && myMsg.color.length>0) {
|
||||||
|
color = myMsg.color;
|
||||||
|
}
|
||||||
|
else if(myMsg.topic!=null && myMsg.topic.length>0) {
|
||||||
|
color = myMsg.topic;
|
||||||
}
|
}
|
||||||
else if(node.lamp_status=="ON" || msg.payload=="ON") status = "ON";
|
|
||||||
else if(node.lamp_status=="OFF" || msg.payload=="OFF") status = "OFF";
|
|
||||||
|
|
||||||
|
|
||||||
if(status=="ALERT") {
|
//check the payload for on/off/alert:
|
||||||
api.setLightState(node.lamp_id, state.alert()).then(displayResult).fail(displayError).done();
|
//case of ALERT:
|
||||||
|
if(myMsg.payload=="ALERT" || myMsg.payload=="alert"){
|
||||||
|
api.setLightState(lamp, state.alert()).then(displayResult).fail(displayError).done();
|
||||||
}
|
}
|
||||||
else if(status=="ON") {
|
|
||||||
if(node.color==null) {
|
//case of ON:
|
||||||
api.setLightState(node.lamp_id, state.on().rgb(hexToRgb(msg.topic).r,hexToRgb(msg.topic).g,hexToRgb(msg.topic).b)).then(displayResult).fail(displayError).done();
|
if(myMsg.payload=="ON" || myMsg.payload=="on") {
|
||||||
|
api.setLightState(lamp, state.on().rgb(hexToRgb(color).r,hexToRgb(color).g,hexToRgb(color).b).brightness(brightness)).then(displayResult).fail(displayError).done();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
api.setLightState(node.lamp_id, state.on().rgb(hexToRgb(node.color).r,hexToRgb(node.color).g,hexToRgb(node.color).b)).then(displayResult).fail(displayError).done();
|
api.setLightState(lamp, state.off()).then(displayResult).fail(displayError).done();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
//set lamp according to node settings
|
||||||
|
if(node.lamp_status=="ON")
|
||||||
|
api.setLightState(node.lamp_id, state.on().rgb(hexToRgb(node.color).r,hexToRgb(node.color).g,hexToRgb(node.color).b).brightness(node.brightness)).then(displayResult).fail(displayError).done();
|
||||||
|
else
|
||||||
api.setLightState(node.lamp_id, state.off()).then(displayResult).fail(displayError).done();
|
api.setLightState(node.lamp_id, state.off()).then(displayResult).fail(displayError).done();
|
||||||
}
|
}
|
||||||
|
|
||||||
msg2.payload = 'Light with ID: '+node.lamp_id+ ' was set to '+status;
|
if(lamp!=-1)
|
||||||
|
msg2.payload = 'Light with ID: '+lamp+ ' was set to '+myMsg.payload;
|
||||||
|
else
|
||||||
|
msg2.payload = 'Light with ID: '+node.lamp_id+ ' was set to '+node.lamp_status;
|
||||||
node.send(msg2);
|
node.send(msg2);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -104,6 +147,7 @@ function HueNode(n) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
this.on("close", function() {
|
this.on("close", function() {
|
||||||
// Called when the node is shutdown - eg on redeploy.
|
// Called when the node is shutdown - eg on redeploy.
|
||||||
// Allows ports to be closed, connections dropped etc.
|
// Allows ports to be closed, connections dropped etc.
|
||||||
@ -121,6 +165,9 @@ var displayError = function(err) {
|
|||||||
console.error(err);
|
console.error(err);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Register the node by name. This must be called before overriding any of the
|
// Register the node by name. This must be called before overriding any of the
|
||||||
// Node functions.
|
// Node functions.
|
||||||
RED.nodes.registerType("HueNode",HueNode);
|
RED.nodes.registerType("HueNode",HueNode);
|
||||||
|
@ -118,7 +118,7 @@ function enable(node) {
|
|||||||
} else {
|
} else {
|
||||||
node.stag.unnotifyHumidity(function() {});
|
node.stag.unnotifyHumidity(function() {});
|
||||||
}
|
}
|
||||||
if (node.accelometer){
|
if (node.accelerometer){
|
||||||
node.stag.notifyAccelerometer(function() {});
|
node.stag.notifyAccelerometer(function() {});
|
||||||
} else {
|
} else {
|
||||||
node.stag.unnotifyAccelerometer(function() {});
|
node.stag.unnotifyAccelerometer(function() {});
|
||||||
|
@ -21,8 +21,8 @@ var fs = require('fs');
|
|||||||
var plat = require('os').platform();
|
var plat = require('os').platform();
|
||||||
var pre = "\\\\.\\";
|
var pre = "\\\\.\\";
|
||||||
|
|
||||||
if (! plat.match(/^win/)) {
|
if (!plat.match(/^win/)) {
|
||||||
util.log("[26-rawserial.js] Advise: Only really needed for Windows boxes without serialport npm module installed.");
|
util.log("[26-rawserial.js] Info : only really needed for Windows boxes without serialport npm module installed.");
|
||||||
pre = "";
|
pre = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
<p>Uses Growl to provide a desktop popup containing the <b>msg.payload</b>. Only useful on the local machine.</p>
|
<p>Uses Growl to provide a desktop popup containing the <b>msg.payload</b>. Only useful on the local machine.</p>
|
||||||
<p>Optionally uses <b>msg.topic</b> as the title.</p>
|
<p>Optionally uses <b>msg.topic</b> as the title.</p>
|
||||||
<p>Uses Growl so should work cross platform but will need pre-reqs installed... see <i><a href="https://npmjs.org/package/growl" target="_new">this link.</a></i></p>
|
<p>Uses Growl so should work cross platform but will need pre-reqs installed... see <i><a href="https://npmjs.org/package/growl" target="_new">this link.</a></i></p>
|
||||||
<p>If installing on Windows you MUST read the install instructions ... especially the bit about adding growlnotify to your path... or it WON'T work.</p>
|
<p>If installing on Windows you MUST read the install instructions ... especially the bit about adding growlnotify to your path... or it WILL NOT work.</p>
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
@ -16,14 +16,14 @@
|
|||||||
|
|
||||||
var RED = require(process.env.NODE_RED_HOME+"/red/red");
|
var RED = require(process.env.NODE_RED_HOME+"/red/red");
|
||||||
var growl = require('growl');
|
var growl = require('growl');
|
||||||
var imagefile = process.env.NODE_RED_HOME+"/public/mqtt-node-red.png";
|
var imagefile = process.env.NODE_RED_HOME+"/public/node-red.png";
|
||||||
|
|
||||||
function NotifyNode(n) {
|
function NotifyNode(n) {
|
||||||
RED.nodes.createNode(this,n);
|
RED.nodes.createNode(this,n);
|
||||||
this.title = n.title;
|
this.title = n.title;
|
||||||
var node = this;
|
var node = this;
|
||||||
this.on("input",function(msg) {
|
this.on("input",function(msg) {
|
||||||
var titl = this.title||msg.topic;
|
var titl = this.title || msg.topic;
|
||||||
if (typeof(msg.payload) == 'object') {
|
if (typeof(msg.payload) == 'object') {
|
||||||
msg.payload = JSON.stringify(msg.payload);
|
msg.payload = JSON.stringify(msg.payload);
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,17 @@
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
<script type="text/x-red" data-template-name="twilio out">
|
<script type="text/x-red" data-template-name="twilio out">
|
||||||
|
<div class="form-row" id="node-input-credentials-row">
|
||||||
|
<label for="node-input-creds"><i class="icon-folder-close"></i> Credentials</label>
|
||||||
|
<select id="node-input-creds">
|
||||||
|
<option value="global">Use global credentials</option>
|
||||||
|
<option value="local">Use local credentials</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="form-row" id="node-input-twilio-row">
|
||||||
|
<label for="node-input-twilio"><i class="icon-user"></i> Twilio</label>
|
||||||
|
<input type="text" id="node-input-twilio">
|
||||||
|
</div>
|
||||||
<div class="form-row">
|
<div class="form-row">
|
||||||
<label for="node-input-number"><i class="icon-envelope"></i> SMS to</label>
|
<label for="node-input-number"><i class="icon-envelope"></i> SMS to</label>
|
||||||
<input type="text" id="node-input-number" placeholder="01234 5678901">
|
<input type="text" id="node-input-number" placeholder="01234 5678901">
|
||||||
@ -24,26 +35,104 @@
|
|||||||
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||||
<input type="text" id="node-input-name" placeholder="Name">
|
<input type="text" id="node-input-name" placeholder="Name">
|
||||||
</div>
|
</div>
|
||||||
<div class="form-tips">Tip - leave Number blank to use <b>msg.topic</b> to set the number.</div>
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script type="text/x-red" data-help-name="twilio out">
|
<script type="text/x-red" data-help-name="twilio out">
|
||||||
<p>Uses Twilio to send the <b>msg.payload</b> as a SMS to the configured number.</p>
|
<p>Sends an SMS message using the Twilio service.</p>
|
||||||
<p>Uses <b>msg.topic</b> to set the phone number, if not already set in the properties.</p>
|
<p><code>msg.payload</code> is used as the body of the message. The node can be configured with the number
|
||||||
<p>You MUST configure both your Account SID and the Auth Token. Either into settings.js like this</p>
|
to send the message to. Alternatively, if the number is left blank, it can be set using <code>msg.topic</code>.</p>
|
||||||
<p><pre>twilio: { account:'My-ACCOUNT-SID', authtoken:'TWILIO-TOKEN', from:'FROM-NUMBER' },</pre></p>
|
<p>You must have an account with Twilio to use this node. You can register for one <a href="https://www.twilio.com/">here</a>.</p>
|
||||||
<p>Or as a twiliokey.js file in the directory <b>above</b> node-red.<p>
|
<p>You can either set your account details within the node, or provide it globally using either the settings file or a file
|
||||||
<p><pre>module.exports = { account:'My-ACCOUNT-SID', authtoken:'TWILIO-TOKEN',from:'FROM-NUMBER' }</pre></p>
|
called 'twiliokey.js' located in the directory above node-red.</p>
|
||||||
|
<p>To use the settings.js file, add an entry such as:
|
||||||
|
<pre>twilio: { account:'My-ACCOUNT-SID', authtoken:'TWILIO-TOKEN', from:'FROM-NUMBER' }</pre></p>
|
||||||
|
<p>To use the 'twiliokey.js' file in the directory <b>above</b> node-red, use the following format:
|
||||||
|
<pre>module.exports = { account:'My-ACCOUNT-SID', authtoken:'TWILIO-TOKEN',from:'FROM-NUMBER' }</pre></p>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/x-red" data-template-name="twilio-api">
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-config-input-sid">Account SID</label>
|
||||||
|
<input type="text" id="node-config-input-sid">
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-config-input-from"><i class="icon-envelope"></i> From</label>
|
||||||
|
<input type="text" id="node-config-input-from" placeholder="01234 5678901">
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-config-input-token"><i class="icon-lock"></i> Token</label>
|
||||||
|
<input type="password" id="node-config-input-token">
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-config-input-name"><i class="icon-tag"></i> Name</label>
|
||||||
|
<input type="text" id="node-config-input-name" placeholder="Name">
|
||||||
|
</div>
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
|
||||||
|
var hasGlobal = false;
|
||||||
|
$.getJSON('twilio-api/global',function(data) {
|
||||||
|
hasGlobal = data.hasToken;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
RED.nodes.registerType('twilio-api',{
|
||||||
|
category: 'config',
|
||||||
|
defaults: {
|
||||||
|
sid: {value:"",required:true},
|
||||||
|
from: {value:"",required:true},
|
||||||
|
// token -> credentials
|
||||||
|
name: { value: ""}
|
||||||
|
},
|
||||||
|
label: function() {
|
||||||
|
return this.name||this.from;
|
||||||
|
},
|
||||||
|
oneditprepare: function() {
|
||||||
|
$.getJSON('twilio-api/'+this.id,function(data) {
|
||||||
|
if (data.hasToken) {
|
||||||
|
$('#node-config-input-token').val('__PWRD__');
|
||||||
|
} else {
|
||||||
|
$('#node-config-input-token').val('');
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
},
|
||||||
|
oneditsave: function() {
|
||||||
|
var newToken = $('#node-config-input-token').val();
|
||||||
|
if (newToken != '__PWRD__') {
|
||||||
|
var credentials = {};
|
||||||
|
credentials.token = newToken;
|
||||||
|
$.ajax({
|
||||||
|
url: 'twilio-api/'+this.id,
|
||||||
|
type: 'POST',
|
||||||
|
data: credentials,
|
||||||
|
success:function(result){}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ondelete: function() {
|
||||||
|
$.ajax({
|
||||||
|
url: 'twilio-api/'+this.id,
|
||||||
|
type: 'DELETE',
|
||||||
|
success: function(result) {}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
RED.nodes.registerType('twilio out',{
|
RED.nodes.registerType('twilio out',{
|
||||||
category: 'output',
|
category: 'output',
|
||||||
defaults: {
|
defaults: {
|
||||||
|
twilio:{type:"twilio-api",validate:function(v) {
|
||||||
|
return hasGlobal || (v && v!="_ADD_");
|
||||||
|
}},
|
||||||
number: {value:""},
|
number: {value:""},
|
||||||
name: {value:""}
|
name: {value:""}
|
||||||
},
|
},
|
||||||
color:"#ed1c24",
|
color:"#FF595F",
|
||||||
inputs:1,
|
inputs:1,
|
||||||
outputs:0,
|
outputs:0,
|
||||||
icon: "twilio.png",
|
icon: "twilio.png",
|
||||||
@ -53,7 +142,29 @@
|
|||||||
},
|
},
|
||||||
labelStyle: function() {
|
labelStyle: function() {
|
||||||
return this.name?"node_label_italic":"";
|
return this.name?"node_label_italic":"";
|
||||||
|
},
|
||||||
|
oneditprepare: function() {
|
||||||
|
if (hasGlobal) {
|
||||||
|
$("#node-input-creds").change(function() {
|
||||||
|
var val = $(this).val();
|
||||||
|
if (val == "global") {
|
||||||
|
$("#node-input-twilio-row").hide();
|
||||||
|
} else {
|
||||||
|
$("#node-input-twilio-row").show();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
$("#node-input-credentials-row").show();
|
||||||
|
if (!this.twilio) {
|
||||||
|
$("#node-input-creds").val("global");
|
||||||
|
} else {
|
||||||
|
$("#node-input-creds").val("local");
|
||||||
|
}
|
||||||
|
$("#node-input-creds").change();
|
||||||
|
} else {
|
||||||
|
$("#node-input-credentials-row").hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
@ -17,47 +17,97 @@
|
|||||||
|
|
||||||
var RED = require(process.env.NODE_RED_HOME+"/red/red");
|
var RED = require(process.env.NODE_RED_HOME+"/red/red");
|
||||||
var util = require('util');
|
var util = require('util');
|
||||||
|
var twilio = require('twilio');
|
||||||
// Either add a line like this to settings.js
|
|
||||||
// twilio: { account:'My-ACCOUNT-SID', authtoken:'TWILIO-TOKEN',from:'FROM-NUMBER' },
|
|
||||||
// Or as a twiliokey.js file in the directory ABOVE node-red.
|
|
||||||
// module.exports = { account:'My-ACCOUNT-SID', authtoken:'TWILIO-TOKEN',from:'FROM-NUMBER' }
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
var twiliokey = RED.settings.twilio || require(process.env.NODE_RED_HOME+"/../twiliokey.js");
|
var twiliokey = RED.settings.twilio || require(process.env.NODE_RED_HOME+"/../twiliokey.js");
|
||||||
}
|
}
|
||||||
catch(err) {
|
catch(err) {
|
||||||
util.log("[56-twilio.js] Error: Failed to load Twilio credentials");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (twiliokey) {
|
var querystring = require('querystring');
|
||||||
var twilioClient = require('twilio')(twiliokey.account, twiliokey.authtoken);
|
|
||||||
var fromNumber = twiliokey.from;
|
RED.httpAdmin.get('/twilio-api/global',function(req,res) {
|
||||||
|
res.send(JSON.stringify({hasToken:!(twiliokey && twiliokey.account && twiliokey.authtoken)}));
|
||||||
|
});
|
||||||
|
RED.httpAdmin.get('/twilio-api/:id',function(req,res) {
|
||||||
|
var credentials = RED.nodes.getCredentials(req.params.id);
|
||||||
|
if (credentials) {
|
||||||
|
res.send(JSON.stringify({hasToken:(credentials.token&&credentials.token!="")}));
|
||||||
|
} else {
|
||||||
|
res.send(JSON.stringify({}));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
RED.httpAdmin.delete('/twilio-api/:id',function(req,res) {
|
||||||
|
RED.nodes.deleteCredentials(req.params.id);
|
||||||
|
res.send(200);
|
||||||
|
});
|
||||||
|
|
||||||
|
RED.httpAdmin.post('/twilio-api/:id',function(req,res) {
|
||||||
|
var body = "";
|
||||||
|
req.on('data', function(chunk) {
|
||||||
|
body+=chunk;
|
||||||
|
});
|
||||||
|
req.on('end', function(){
|
||||||
|
var newCreds = querystring.parse(body);
|
||||||
|
var credentials = RED.nodes.getCredentials(req.params.id)||{};
|
||||||
|
if (newCreds.token == "") {
|
||||||
|
delete credentials.token;
|
||||||
|
} else {
|
||||||
|
credentials.token = newCreds.token;
|
||||||
|
}
|
||||||
|
RED.nodes.addCredentials(req.params.id,credentials);
|
||||||
|
res.send(200);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function TwilioAPINode(n) {
|
||||||
|
RED.nodes.createNode(this,n);
|
||||||
|
this.sid = n.sid;
|
||||||
|
this.from = n.from;
|
||||||
|
this.name = n.name;
|
||||||
|
var credentials = RED.nodes.getCredentials(n.id);
|
||||||
|
if (credentials) {
|
||||||
|
this.token = credentials.token;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
RED.nodes.registerType("twilio-api",TwilioAPINode);
|
||||||
|
|
||||||
|
|
||||||
function TwilioOutNode(n) {
|
function TwilioOutNode(n) {
|
||||||
RED.nodes.createNode(this,n);
|
RED.nodes.createNode(this,n);
|
||||||
this.number = n.number;
|
this.number = n.number;
|
||||||
|
|
||||||
|
this.api = RED.nodes.getNode(n.twilio);
|
||||||
|
|
||||||
|
if (this.api) {
|
||||||
|
this.twilioClient = twilio(this.api.sid,this.api.token);
|
||||||
|
this.fromNumber = this.api.from;
|
||||||
|
} else if (twiliokey) {
|
||||||
|
this.twilioClient = twilio(twiliokey.account, twiliokey.authtoken);
|
||||||
|
this.fromNumber = twiliokey.from;
|
||||||
|
} else {
|
||||||
|
this.error("missing twilio credentials");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var node = this;
|
var node = this;
|
||||||
this.on("input",function(msg) {
|
this.on("input",function(msg) {
|
||||||
if (typeof(msg.payload) == 'object') {
|
if (typeof(msg.payload) == 'object') {
|
||||||
msg.payload = JSON.stringify(msg.payload);
|
msg.payload = JSON.stringify(msg.payload);
|
||||||
}
|
}
|
||||||
if (twiliokey) {
|
|
||||||
try {
|
try {
|
||||||
// Send SMS
|
// Send SMS
|
||||||
var tonum = node.number || msg.topic;
|
var tonum = node.number || msg.topic;
|
||||||
twilioClient.sendMessage( {to: tonum, from: fromNumber, body: msg.payload}, function(err, response) {
|
node.twilioClient.sendMessage( {to: tonum, from: node.fromNumber, body: msg.payload}, function(err, response) {
|
||||||
if (err) node.error(err);
|
if (err) {
|
||||||
//console.log(response);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
catch (err) {
|
|
||||||
node.error(err);
|
node.error(err);
|
||||||
}
|
}
|
||||||
}
|
//console.log(response);
|
||||||
else {
|
});
|
||||||
node.warn("Twilio credentials not set/found. See node info.");
|
} catch (err) {
|
||||||
|
node.error(err);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ function SunNode(n) {
|
|||||||
var mins2 = times[node.end].getUTCMinutes();
|
var mins2 = times[node.end].getUTCMinutes();
|
||||||
var e1 = (hour*60+mins) - (hour1*60+mins1);
|
var e1 = (hour*60+mins) - (hour1*60+mins1);
|
||||||
var e2 = (hour*60+mins) - (hour2*60+mins2);
|
var e2 = (hour*60+mins) - (hour2*60+mins2);
|
||||||
var moon = parseInt(SunCalc.getMoonFraction(now)*100)/100;
|
var moon = SunCalc.getMoonIllumination(now).fraction;
|
||||||
msg = { payload:0, topic:"sun", moon:moon };
|
msg = { payload:0, topic:"sun", moon:moon };
|
||||||
if ((e1 > 0) & (e2 < 0)) { msg.payload = 1; }
|
if ((e1 > 0) & (e2 < 0)) { msg.payload = 1; }
|
||||||
if (oldval == null) { oldval = msg.payload; }
|
if (oldval == null) { oldval = msg.payload; }
|
||||||
|
Loading…
Reference in New Issue
Block a user