Merge remote-tracking branch 'upstream/master'
Conflicts: social/xmpp/92-xmpp.html social/xmpp/92-xmpp.js
Before Width: | Height: | Size: 719 B After Width: | Height: | Size: 1.3 KiB |
@ -19,14 +19,12 @@ var util = require("util");
|
||||
var exec = require('child_process').exec;
|
||||
var fs = require('fs');
|
||||
|
||||
if (!fs.existsSync("/usr/local/bin/gpio")) {
|
||||
exec("cat /proc/cpuinfo | grep BCM27",function(err,stdout,stderr) {
|
||||
if (stdout.indexOf('BCM27') > -1) {
|
||||
util.log('[37-rpi-piface.js] Error: Cannot find Wiring-Pi "gpio" command');
|
||||
}
|
||||
// else not on a Pi so don't worry anyone with needless messages.
|
||||
});
|
||||
return;
|
||||
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 names of pins to Gordon's gpio PiFace pin numbers
|
||||
@ -109,13 +107,16 @@ function PiFACEInNode(n) {
|
||||
}
|
||||
}
|
||||
});
|
||||
}, 250);
|
||||
}, 200);
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
node.error("Invalid PiFACE pin: "+node.pin);
|
||||
}
|
||||
node.on("close", function() {
|
||||
clearInterval(node._interval);
|
||||
});
|
||||
}
|
||||
|
||||
function PiFACEOutNode(n) {
|
||||
@ -141,21 +142,10 @@ function PiFACEOutNode(n) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
exec("gpio load spi",function(err,stdout,stderr) {
|
||||
if (err) {
|
||||
util.log('[37-rpi-piface.js] Error: "gpio load spi" command failed for some reason.');
|
||||
}
|
||||
exec("gpio -p reset",function(err,stdout,stderr) {
|
||||
if (err) {
|
||||
util.log('[37-rpi-piface.js] Error: "gpio -p reset" command failed for some reason.');
|
||||
}
|
||||
RED.nodes.registerType("rpi-piface in",PiFACEInNode);
|
||||
RED.nodes.registerType("rpi-piface out",PiFACEOutNode);
|
||||
PiFACEInNode.prototype.close = function() {
|
||||
clearInterval(this._interval);
|
||||
}
|
||||
PiFACEOutNode.prototype.close = function() {
|
||||
}
|
||||
});
|
||||
RED.nodes.registerType("rpi-piface in",PiFACEInNode);
|
||||
RED.nodes.registerType("rpi-piface out",PiFACEOutNode);
|
||||
});
|
||||
|
@ -18,7 +18,7 @@
|
||||
<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="-" disabled>select input</option>
|
||||
<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>
|
||||
@ -64,7 +64,7 @@
|
||||
<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="-" disabled>select output</option>
|
||||
<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>
|
||||
|
@ -67,7 +67,7 @@ function PibrellaIn(n) {
|
||||
this.pin = pintable[n.pin];
|
||||
var node = this;
|
||||
|
||||
if (this.pin) {
|
||||
if (node.pin) {
|
||||
exec("gpio mode "+node.pin+" in", function(err,stdout,stderr) {
|
||||
if (err) node.error(err);
|
||||
else {
|
||||
@ -90,11 +90,11 @@ function PibrellaIn(n) {
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.error("Invalid GPIO pin: "+this.pin);
|
||||
node.error("Invalid GPIO pin: "+node.pin);
|
||||
}
|
||||
|
||||
this.on("close", function() {
|
||||
clearInterval(this._interval);
|
||||
node.on("close", function() {
|
||||
clearInterval(node._interval);
|
||||
});
|
||||
}
|
||||
|
||||
@ -103,7 +103,7 @@ function PibrellaOut(n) {
|
||||
this.pin = pintable[n.pin];
|
||||
var node = this;
|
||||
|
||||
if (this.pin == "1") {
|
||||
if (node.pin == "1") {
|
||||
exec("gpio mode 1 pwm");
|
||||
process.nextTick(function() {
|
||||
exec("gpio pwm-ms");
|
||||
@ -121,7 +121,7 @@ function PibrellaOut(n) {
|
||||
});
|
||||
});
|
||||
}
|
||||
else if (this.pin) {
|
||||
else if (node.pin) {
|
||||
process.nextTick(function() {
|
||||
exec("gpio mode "+node.pin+" out", function(err,stdout,stderr) {
|
||||
if (err) node.error(err);
|
||||
@ -142,31 +142,31 @@ function PibrellaOut(n) {
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.error("Invalid GPIO pin: "+this.pin);
|
||||
node.error("Invalid GPIO pin: "+node.pin);
|
||||
}
|
||||
|
||||
this.on("close", function() {
|
||||
exec("gpio mode "+this.pin+" in");
|
||||
node.on("close", function() {
|
||||
exec("gpio mode "+node.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");
|
||||
});
|
||||
//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,7 +27,7 @@
|
||||
<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><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,
|
||||
<p>You can also use the @cheerlight colour names - red, amber, green, blue, cyan, magenta, yellow, orange, pink, purple,
|
||||
white, warmwhite, black</p>
|
||||
</script>
|
||||
|
||||
|
@ -16,17 +16,43 @@
|
||||
|
||||
<script type="text/x-red" data-template-name="rawserial in">
|
||||
<div class="form-row">
|
||||
<label for="node-input-port"><i class="icon-random"></i> Port</label>
|
||||
<label for="node-input-port"><i class="fa fa-random"></i> Port</label>
|
||||
<input type="text" id="node-input-port" placeholder="COM1">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-split"><i class="icon-edit"></i> Split on</label>
|
||||
<input type="text" id="node-input-split" placeholder="\n">
|
||||
<label for="node-input-out"><i class="fa fa-cut"></i> split input</label>
|
||||
<select type="text" id="node-input-out" style="width:52%;">
|
||||
<option value="char">when character received is</option>
|
||||
<option value="time">after a fixed timeout of</option>
|
||||
</select>
|
||||
<input type="text" id="node-input-splitc" style="width:50px;">
|
||||
<span id="node-units"></span>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||
<label for="node-input-bin"><i class="fa fa-sign-in"></i> and deliver</label>
|
||||
<select type="text" id="node-input-bin" style="width: 77%;">
|
||||
<option value="false">ascii strings</option>
|
||||
<option value="true">binary buffers</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||
<input type="text" id="node-input-name" placeholder="Name">
|
||||
</div>
|
||||
<script>
|
||||
var previous = null;
|
||||
$("#node-input-out").on('focus', function () { previous = this.value; }).change(function() {
|
||||
if (previous == null) { previous = $("#node-input-out").val(); }
|
||||
if ($("#node-input-out").val() == "char") {
|
||||
if (previous != "char") { $("#node-input-splitc").val("\\n"); }
|
||||
$("#node-units").text("");
|
||||
}
|
||||
else {
|
||||
if (previous != "time") { $("#node-input-splitc").val("0"); }
|
||||
$("#node-units").text("ms");
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="rawserial in">
|
||||
@ -44,7 +70,9 @@
|
||||
color:"BurlyWood",
|
||||
defaults: {
|
||||
name: {value:""},
|
||||
split: {value:""},
|
||||
splitc: {value:"\n"},
|
||||
out: {value:"char"},
|
||||
bin: {value:"false"},
|
||||
port: {value:"", required:true}
|
||||
},
|
||||
inputs:0,
|
||||
@ -61,11 +89,11 @@
|
||||
|
||||
<script type="text/x-red" data-template-name="rawserial out">
|
||||
<div class="form-row">
|
||||
<label for="node-input-port"><i class="icon-random"></i> Port</label>
|
||||
<label for="node-input-port"><i class="fa fa-random"></i> Port</label>
|
||||
<input type="text" id="node-input-port" placeholder="COM1">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||
<input type="text" id="node-input-name" placeholder="Name">
|
||||
</div>
|
||||
</script>
|
||||
|
@ -29,36 +29,67 @@ if (!plat.match(/^win/)) {
|
||||
function RawSerialInNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.port = n.port;
|
||||
this.split = n.split||null;
|
||||
if (this.split == '\\n') this.split = "\n";
|
||||
if (this.split == '\\r') this.split = "\r";
|
||||
this.splitc = n.splitc||null;
|
||||
this.out = n.out||"char";
|
||||
this.bin = n.bin||false;
|
||||
if (this.splitc == '\\n') this.splitc = "\n";
|
||||
if (this.splitc == '\\r') this.splitc = "\r";
|
||||
if (!isNaN(parseInt(this.splitc))) { this.splitc = parseInt(this.splitc); }
|
||||
var node = this;
|
||||
|
||||
var setupSerial = function() {
|
||||
node.inp = fs.createReadStream(pre+node.port);
|
||||
node.log("opened "+pre+node.port);
|
||||
node.inp.setEncoding('utf8');
|
||||
node.log("open "+pre+node.port);
|
||||
node.tout = null;
|
||||
var line = "";
|
||||
var buf = new Buffer(32768);
|
||||
var i = 0;
|
||||
node.inp.on('data', function (data) {
|
||||
if (node.split != null) {
|
||||
if (data == node.split) {
|
||||
node.send({payload:line});
|
||||
line = "";
|
||||
for (var z = 0; z < data.length; z++) {
|
||||
if ((node.out === "time") && (node.splitc != 0)) {
|
||||
if (node.tout) {
|
||||
i += 1;
|
||||
buf[i] = data[z];
|
||||
}
|
||||
else {
|
||||
node.tout = setTimeout(function () {
|
||||
node.tout = null;
|
||||
var m = new Buffer(i+1);
|
||||
buf.copy(m,0,0,i+1);
|
||||
if (node.bin !== "true") { m = m.toString(); }
|
||||
node.send({"payload": m});
|
||||
}, node.splitc);
|
||||
i = 0;
|
||||
buf[0] = data[z];
|
||||
}
|
||||
}
|
||||
else if ((node.out == "char") && (node.splitc != null)) {
|
||||
buf[i] = data[z];
|
||||
i += 1;
|
||||
if ((data[z] === node.splitc.charCodeAt(0)) || (i === 32768)) {
|
||||
var m = new Buffer(i);
|
||||
buf.copy(m,0,0,i);
|
||||
if (node.bin !== "true") { m = m.toString(); }
|
||||
node.send({"payload":m});
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (node.bin !== "true") { node.send({"payload": String.fromCharCode(data[z])}); }
|
||||
else { node.send({"payload": new Buffer([data[z]])});}
|
||||
}
|
||||
else { line += data; }
|
||||
}
|
||||
else { node.send({payload:data}); }
|
||||
});
|
||||
//node.inp.on('end', function (error) {console.log("End", error);});
|
||||
node.inp.on('close', function (error) {
|
||||
util.log("[rawserial] "+node.port+" closed");
|
||||
node.log(node.port+" closed");
|
||||
node.tout = setTimeout(function() {
|
||||
setupSerial();
|
||||
},settings.serialReconnectTime);
|
||||
});
|
||||
node.inp.on('error', function(error) {
|
||||
if (error.code == "ENOENT") { util.log("[rawserial] port "+node.port+" not found"); }
|
||||
else { util.log("[rawserial] "+node.port+" error "+error); }
|
||||
if (error.code == "ENOENT") { node.log(node.port+" not found"); }
|
||||
else { node.log(node.port+" error "+error); }
|
||||
node.tout = setTimeout(function() {
|
||||
setupSerial();
|
||||
},settings.serialReconnectTime);
|
||||
@ -87,18 +118,18 @@ function RawSerialOutNode(n) {
|
||||
node.oup.write(msg.payload);
|
||||
}
|
||||
});
|
||||
node.oup.on('open', function (error) { util.log("[rawserial] opened "+node.port); });
|
||||
node.oup.on('end', function (error) { console.log("End",error); });
|
||||
node.oup.on('open', function (error) { node.log("opened "+node.port); });
|
||||
node.oup.on('end', function (error) { node.log("end :"+error); });
|
||||
node.oup.on('close', function (error) {
|
||||
util.log("[rawserial] "+node.port+" closed");
|
||||
node.log(node.port+" closed");
|
||||
node.tout = setTimeout(function() {
|
||||
setupSerial();
|
||||
},settings.serialReconnectTime);
|
||||
});
|
||||
node.oup.on('error', function(error) {
|
||||
if (error.code == "EACCES") { util.log("[rawserial] can't access port "+node.port); }
|
||||
else if (error.code == "EIO") { util.log("[rawserial] can't write to port "+node.port); }
|
||||
else { util.log("[rawserial] "+node.port+" error "+error); }
|
||||
if (error.code == "EACCES") { node.log("can't access port "+node.port); }
|
||||
else if (error.code == "EIO") { node.log("can't write to port "+node.port); }
|
||||
else { node.log(node.port+" error "+error); }
|
||||
node.tout = setTimeout(function() {
|
||||
setupSerial();
|
||||
},settings.serialReconnectTime);
|
||||
|
169
io/stomp/18-stomp.html
Normal file
@ -0,0 +1,169 @@
|
||||
<!--
|
||||
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="stomp in">
|
||||
<div class="form-row">
|
||||
<label for="node-input-server" style="width: 110px;"><i class="icon-bookmark"></i> Server</label>
|
||||
<input type="text" id="node-input-server">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-topic" style="width: 110px;"><i class="icon-envelope"></i> Destination</label>
|
||||
<input type="text" id="node-input-topic" placeholder="topic or queue">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name" style="width: 110px;"><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="stomp in">
|
||||
<p>Connects to a server using the Stomp protocol to receive messages.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('stomp in',{
|
||||
category: 'input',
|
||||
color:"#e8cfe8",
|
||||
defaults: {
|
||||
name: {value:""},
|
||||
server: {type:"stomp-server",required:true},
|
||||
topic: {value:"",required:true}
|
||||
},
|
||||
inputs:0,
|
||||
outputs:1,
|
||||
icon: "bridge.png",
|
||||
label: function() {
|
||||
return this.name||"stomp";
|
||||
},
|
||||
labelStyle: function() {
|
||||
return (this.name)?"node_label_italic":"";
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-template-name="stomp out">
|
||||
<div class="form-row">
|
||||
<label for="node-input-server" style="width: 110px;"><i class="icon-bookmark"></i> Server</label>
|
||||
<input type="text" id="node-input-server">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-topic" style="width: 110px;"><i class="icon-envelope"></i> Destination</label>
|
||||
<input type="text" id="node-input-topic" placeholder="topic or queue">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name" style="width: 110px;"><i class="icon-tag"></i> Name</label>
|
||||
<input type="text" id="node-input-name" placeholder="Name">
|
||||
</div>
|
||||
<div class="form-tips">The <b>Destination</b> field is optional. If not set uses the <b>msg.topic</b> property of the message.</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="stomp out">
|
||||
<p>Connects to an Stomp capable server to send messages.</p>
|
||||
<p>The <b>Destination</b> field is optional. If set it overrides the <b>msg.topic</b> property of the message.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('stomp out',{
|
||||
category: 'output',
|
||||
color:"#e8cfe8",
|
||||
defaults: {
|
||||
name: {value:""},
|
||||
server: {type:"stomp-server",required:true},
|
||||
topic: {value:""}
|
||||
},
|
||||
inputs:1,
|
||||
outputs:0,
|
||||
icon: "bridge.png",
|
||||
align: "right",
|
||||
label: function() {
|
||||
return this.name||"stomp";
|
||||
},
|
||||
labelStyle: function() {
|
||||
return (this.name)?"node_label_italic":"";
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-template-name="stomp-server">
|
||||
<div class="form-row node-input-server">
|
||||
<label for="node-config-input-server"><i class="icon-bookmark"></i> Server</label>
|
||||
<input class="input-append-left" type="text" id="node-config-input-server" placeholder="localhost" style="width: 45%;" >
|
||||
<label for="node-config-input-port" style="margin-left: 10px; width: 35px; "> Port</label>
|
||||
<input type="text" id="node-config-input-port" placeholder="Port" style="width:45px">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-config-input-user"><i class="icon-user"></i> Username</label>
|
||||
<input type="text" id="node-config-input-user">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-config-input-pass"><i class="icon-lock"></i> Password</label>
|
||||
<input type="password" id="node-config-input-pass">
|
||||
</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 type="text/javascript">
|
||||
RED.nodes.registerType('stomp-server',{
|
||||
category: 'config',
|
||||
defaults: {
|
||||
server: {required:true},
|
||||
port: {value:61618,required:true,validate:RED.validators.number()},
|
||||
name: {}
|
||||
},
|
||||
label: function() {
|
||||
return (this.name?this.name:this.server+":"+this.port);
|
||||
},
|
||||
oneditprepare: function() {
|
||||
$.getJSON('stomp-server/'+this.id,function(data) {
|
||||
if (data.user) {
|
||||
$('#node-config-input-user').val(data.user);
|
||||
}
|
||||
if (data.hasPassword) {
|
||||
$('#node-config-input-pass').val('__PWRD__');
|
||||
} else {
|
||||
$('#node-config-input-pass').val('');
|
||||
}
|
||||
if (data.global) $('#node-config-cred-tip').show();
|
||||
else $('#node-config-cred-tip').hide();
|
||||
});
|
||||
},
|
||||
oneditsave: function() {
|
||||
var credentials = {};
|
||||
var newUser = $('#node-config-input-user').val();
|
||||
var newPass = $('#node-config-input-pass').val();
|
||||
credentials.user = newUser;
|
||||
if (newPass != '__PWRD__') {
|
||||
credentials.password = newPass;
|
||||
}
|
||||
$.ajax({
|
||||
url: 'stomp-server/'+this.id,
|
||||
type: 'POST',
|
||||
data: credentials,
|
||||
success: function(result){}
|
||||
});
|
||||
},
|
||||
ondelete: function() {
|
||||
$.ajax({
|
||||
url: 'stomp-server/'+this.id,
|
||||
type: 'DELETE',
|
||||
success: function(result) {}
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
180
io/stomp/18-stomp.js
Normal file
@ -0,0 +1,180 @@
|
||||
/**
|
||||
* 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.
|
||||
**/
|
||||
|
||||
module.exports = function(RED) {
|
||||
"use strict";
|
||||
var StompClient = require('stomp-client');
|
||||
var querystring = require('querystring');
|
||||
|
||||
function StompServerNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.server = n.server;
|
||||
this.port = n.port;
|
||||
this.name = n.name;
|
||||
var credentials = RED.nodes.getCredentials(n.id);
|
||||
if (credentials) {
|
||||
this.username = credentials.user;
|
||||
this.password = credentials.password;
|
||||
}
|
||||
}
|
||||
RED.nodes.registerType("stomp-server",StompServerNode);
|
||||
|
||||
RED.httpAdmin.get('/stomp-server/:id',function(req,res) {
|
||||
var credentials = RED.nodes.getCredentials(req.params.id);
|
||||
if (credentials) {
|
||||
res.send(JSON.stringify({user:credentials.user,hasPassword:(credentials.password&&credentials.password!="")}));
|
||||
} else {
|
||||
res.send(JSON.stringify({}));
|
||||
}
|
||||
});
|
||||
|
||||
RED.httpAdmin.delete('/stomp-server/:id',function(req,res) {
|
||||
RED.nodes.deleteCredentials(req.params.id);
|
||||
res.send(200);
|
||||
});
|
||||
|
||||
RED.httpAdmin.post('/stomp-server/: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.user == null || newCreds.user == "") {
|
||||
delete credentials.user;
|
||||
} else {
|
||||
credentials.user = newCreds.user;
|
||||
}
|
||||
if (newCreds.password == "") {
|
||||
delete credentials.password;
|
||||
} else {
|
||||
credentials.password = newCreds.password||credentials.password;
|
||||
}
|
||||
RED.nodes.addCredentials(req.params.id,credentials);
|
||||
res.send(200);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
function StompInNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.server = n.server;
|
||||
this.topic = n.topic;
|
||||
|
||||
this.serverConfig = RED.nodes.getNode(this.server);
|
||||
this.host = this.serverConfig.server;
|
||||
this.port = this.serverConfig.port;
|
||||
this.userid = this.serverConfig.username;
|
||||
this.password = this.serverConfig.password;
|
||||
|
||||
var node = this;
|
||||
var msg = {topic:this.topic};
|
||||
var closing = false;
|
||||
|
||||
node.client = new StompClient(node.host, node.port, node.userid, node.password, '1.0');
|
||||
node.status({fill:"grey",shape:"ring",text:"connecting"});
|
||||
|
||||
var doConnect = function() {
|
||||
node.client.connect(function(sessionId) {
|
||||
node.status({fill:"green",shape:"dot",text:"connected"});
|
||||
node.log('subscribed to: '+node.topic);
|
||||
node.client.subscribe(node.topic, function(body, headers) {
|
||||
msg.payload = JSON.parse(body);
|
||||
node.send(msg);
|
||||
});
|
||||
}, function(error) {
|
||||
node.status({fill:"grey",shape:"dot",text:"error"});
|
||||
node.warn(error);
|
||||
});
|
||||
}
|
||||
|
||||
node.client.on("disconnect", function() {
|
||||
node.status({fill:"red",shape:"ring",text:"disconnected"});
|
||||
if (!closing) {
|
||||
setTimeout( function () { doConnect(); }, 15000);
|
||||
}
|
||||
});
|
||||
|
||||
node.client.on("error", function(error) {
|
||||
node.status({fill:"grey",shape:"dot",text:"error"});
|
||||
node.log(error);
|
||||
});
|
||||
|
||||
doConnect();
|
||||
|
||||
node.on("close", function(done) {
|
||||
closing = true;
|
||||
if (node.client) {
|
||||
node.client.on("disconnect", function() {
|
||||
done();
|
||||
});
|
||||
//node.client.unsubscribe(node.topic);
|
||||
node.client.disconnect();
|
||||
} else { done(); }
|
||||
});
|
||||
}
|
||||
RED.nodes.registerType("stomp in",StompInNode);
|
||||
|
||||
|
||||
function StompOutNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.server = n.server;
|
||||
this.topic = n.topic;
|
||||
|
||||
this.serverConfig = RED.nodes.getNode(this.server);
|
||||
this.host = this.serverConfig.server;
|
||||
this.port = this.serverConfig.port;
|
||||
this.userid = this.serverConfig.username;
|
||||
this.password = this.serverConfig.password;
|
||||
|
||||
var node = this;
|
||||
var msg = {topic:this.topic};
|
||||
var closing = false;
|
||||
|
||||
node.client = new StompClient(node.host, node.port, node.userid, node.password, '1.0');
|
||||
node.status({fill:"grey",shape:"ring",text:"connecting"});
|
||||
|
||||
node.client.connect( function(sessionId) {
|
||||
node.status({fill:"green",shape:"dot",text:"connected"});
|
||||
}, function(error) {
|
||||
node.status({fill:"grey",shape:"dot",text:"error"});
|
||||
node.warn(error);
|
||||
});
|
||||
|
||||
node.client.on("disconnect", function() {
|
||||
node.status({fill:"red",shape:"ring",text:"disconnected"});
|
||||
if (!closing) {
|
||||
setTimeout( function () { node.client.connect(); }, 15000);
|
||||
}
|
||||
});
|
||||
|
||||
node.client.on("error", function(error) {
|
||||
node.log(error);
|
||||
});
|
||||
|
||||
node.on("input", function(msg) {
|
||||
node.client.publish(node.topic || msg.topic, msg.payload);
|
||||
});
|
||||
|
||||
node.on("close", function(done) {
|
||||
closing = true;
|
||||
if (client) { client.disconnect(); }
|
||||
});
|
||||
}
|
||||
RED.nodes.registerType("stomp out",StompOutNode);
|
||||
|
||||
}
|
@ -24,7 +24,7 @@
|
||||
|
||||
<script type="text/x-red" data-help-name="mpd out">
|
||||
<p>MPD music control output node.</p>
|
||||
<p>Expects <b>msg.payload</b> to be a valid mpc command. Currently only simple commands that expect no reply are supported.</p>
|
||||
<p>Expects <b>msg.payload</b> to be a valid mpc command. Currently only simple commands that expect no reply are supported. play, pause, next, previous, stop, etc.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
@ -57,7 +57,7 @@
|
||||
|
||||
<script type="text/x-red" data-help-name="mpd in">
|
||||
<p>MPD music control input node.</p>
|
||||
<p>Creates a <b>msg.payload</b> object with Artist, Album, Track, Genre and Date.</p>
|
||||
<p>Creates a <b>msg.payload</b> object containing Artist, Album, Track, Genre and Date.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
@ -21,15 +21,13 @@ var komponist = require('komponist');
|
||||
var mpc = null;
|
||||
exec("which mpd",function(err,stdout,stderr) {
|
||||
if (stdout.indexOf('mpd') == -1) {
|
||||
util.log('[69-mpd.js] Error: Cannot find "mpd" command. Please install MPD.');
|
||||
return;
|
||||
throw 'Error: Cannot find "mpd" command. Please install MPD.';
|
||||
}
|
||||
});
|
||||
|
||||
exec("netstat -an | grep LISTEN | grep 6600",function(err,stdout,stderr) {
|
||||
if (stdout.indexOf('6600') == -1) {
|
||||
util.log('[69-mpd.js] Warning: MPD daemon not listening on port 6600. Please start MPD.');
|
||||
return;
|
||||
throw '[69-mpd.js] Error: MPD daemon not listening on port 6600. Please start MPD.';
|
||||
}
|
||||
komponist.createConnection(6600, 'localhost', function(err, client) {
|
||||
if (err) node.error("MPD: Failed to connect to MPD server");
|
||||
@ -46,19 +44,18 @@ function MPDOut(n) {
|
||||
if (mpc != null) {
|
||||
this.on("input", function(msg) {
|
||||
if (msg != null) {
|
||||
console.log(msg);
|
||||
try {
|
||||
//node.mpc.command(msg.payload);
|
||||
node.mpc.command(msg.payload, msg.param, function(err, results) {
|
||||
if (err) { console.log("MPD: Error:",err); }
|
||||
if (err) { node.log("error: "+err); }
|
||||
//else { console.log(results); }
|
||||
});
|
||||
} catch (err) { console.log("MPD: Error:",err); }
|
||||
} catch (err) { node.log("error: "+err); }
|
||||
}
|
||||
});
|
||||
|
||||
node.mpc.on('error', function(err) {
|
||||
console.log("MPD: Error:",err);
|
||||
node.log("error: "+err);
|
||||
});
|
||||
}
|
||||
else { node.warn("MPD not running"); }
|
||||
@ -76,7 +73,7 @@ function MPDIn(n) {
|
||||
|
||||
function getSong() {
|
||||
node.mpc.currentsong(function(err, info) {
|
||||
if (err) console.log(err);
|
||||
if (err) node.log(err);
|
||||
else {
|
||||
var msg = {payload:{},topic:"music"};
|
||||
msg.payload.Artist = info.Artist;
|
||||
|
@ -32,6 +32,7 @@
|
||||
<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" id="node-tip"><b>Note:</b> Using credentials from global pushkey.js file.</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="prowl">
|
||||
@ -69,6 +70,8 @@
|
||||
} else {
|
||||
$('#node-config-input-pushkey').val('');
|
||||
}
|
||||
if (data.global) $('#node-tip').show();
|
||||
else $('#node-tip').hide();
|
||||
});
|
||||
},
|
||||
oneditsave: function() {
|
||||
|
@ -75,7 +75,13 @@ RED.httpAdmin.get('/prowl/:id',function(req,res) {
|
||||
var credentials = RED.nodes.getCredentials(req.params.id);
|
||||
if (credentials) {
|
||||
res.send(JSON.stringify({hasPassword:(credentials.pushkey&&credentials.pushkey!="")}));
|
||||
} else {
|
||||
}
|
||||
else if (pushkeys && pushkeys.prowlkey) {
|
||||
RED.nodes.addCredentials(req.params.id,{pushkey:pushkeys.prowlkey,global:true});
|
||||
credentials = RED.nodes.getCredentials(req.params.id);
|
||||
res.send(JSON.stringify({hasPassword:(credentials.pushkey&&credentials.pushkey!=""),global:credentials.global}));;
|
||||
}
|
||||
else {
|
||||
res.send(JSON.stringify({}));
|
||||
}
|
||||
});
|
||||
|
184
social/pusher/114-pusher.html
Normal file
@ -0,0 +1,184 @@
|
||||
<!--
|
||||
|
||||
Copyright 2014 Charalampos Doukas, @BuildingIoT
|
||||
|
||||
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="pusher in">
|
||||
<div class="form-row">
|
||||
<label for="node-input-channel"><i class="icon-random"></i> Channel</label>
|
||||
<input type="text" id="node-input-channel" placeholder="my_channel">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-eventname"><i class="icon-tasks"></i> Event</label>
|
||||
<input type="text" id="node-input-eventname" placeholder="test_event_name">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-appkey_sub"><i class="icon-lock"></i> App Key</label>
|
||||
<input type="text" id="node-input-appkey_sub" placeholder="key">
|
||||
</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>
|
||||
|
||||
<!-- Next, some simple help text is provided for the node. -->
|
||||
<script type="text/x-red" data-help-name="pusher in">
|
||||
<p>Pusher input mode. Use this node to subscribe to a Pusher channel/event. You need a valid Pusher App key.</p>
|
||||
</script>
|
||||
|
||||
<!-- Finally, the node type is registered along with all of its properties -->
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('pusher in',{
|
||||
category: 'social-input', // the palette category
|
||||
color:"#A9D0F5",
|
||||
defaults: { // defines the editable properties of the node
|
||||
name: {value:""}, // along with default values.
|
||||
channel: {value:"", required:true},
|
||||
eventname: {value:"", required:true}
|
||||
},
|
||||
inputs:0, // set the number of inputs - only 0 or 1
|
||||
outputs:1, // set the number of outputs - 0 to n
|
||||
icon: "pusher.png", // set the icon (held in public/icons)
|
||||
label: function() { // sets the default label contents
|
||||
return this.name||"pusher";
|
||||
},
|
||||
labelStyle: function() { // sets the class to apply to the label
|
||||
return this.name?"node_label_italic":"";
|
||||
},
|
||||
oneditsave: function() {
|
||||
var credentials = {};
|
||||
var newAppKey_sub = $('#node-input-appkey_sub').val();
|
||||
credentials.pusherappkey_sub = newAppKey_sub;
|
||||
$.ajax({
|
||||
url: 'pusher/'+this.id,
|
||||
type: 'POST',
|
||||
data: credentials,
|
||||
success: function(result){}
|
||||
});
|
||||
},
|
||||
oneditprepare: function() {
|
||||
$.getJSON('pusher/'+this.id,function(data) {
|
||||
if (data.pusherappkey_sub) {
|
||||
$('#node-input-appkey_sub').val(data.pusherappkey_sub);
|
||||
}
|
||||
});
|
||||
},
|
||||
ondelete: function() {
|
||||
$.ajax({
|
||||
url: 'pusher/'+this.id,
|
||||
type: 'DELETE',
|
||||
success: function(result) {}
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-template-name="pusher out">
|
||||
<div class="form-row">
|
||||
<label for="node-input-channel"><i class="icon-random"></i> Channel</label>
|
||||
<input type="text" id="node-input-channel" placeholder="my_channel">
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<label for="node-input-eventname"><i class="icon-tasks"></i> Event</label>
|
||||
<input type="text" id="node-input-eventname" placeholder="test_event_name">
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<label for="node-input-appid"><i class="icon-tag"></i> App ID</label>
|
||||
<input type="text" id="node-input-appid" placeholder="app_id">
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<label for="node-input-appkey"><i class="icon-lock"></i> App Key</label>
|
||||
<input type="text" id="node-input-appkey" placeholder="key">
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<label for="node-input-topic"><i class="icon-asterisk"></i> App Secret</label>
|
||||
<input type="password" id="node-input-appsecret" placeholder="secret">
|
||||
</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>
|
||||
|
||||
<!-- Next, some simple help text is provided for the node. -->
|
||||
<script type="text/x-red" data-help-name="pusher out">
|
||||
<p>Pusher output node for sending messages to a specific channel/event. You need an App key, secret and ID of a Pusher app. The node will send the payload of the incoming message.</p>
|
||||
</script>
|
||||
|
||||
<!-- Finally, the node type is registered along with all of its properties -->
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('pusher out',{
|
||||
category: 'social-output', // the palette category
|
||||
color:"#A9D0F5",
|
||||
defaults: { // defines the editable properties of the node
|
||||
name: {value:""}, // along with default values.
|
||||
channel: {value:"", required:true},
|
||||
eventname: {value:"", required:true}
|
||||
},
|
||||
inputs:1, // set the number of inputs - only 0 or 1
|
||||
outputs:0, // set the number of outputs - 0 to n
|
||||
icon: "pusher.png", // set the icon (held in public/icons)
|
||||
align: "right",
|
||||
label: function() { // sets the default label contents
|
||||
return this.name||"pusher";
|
||||
},
|
||||
labelStyle: function() { // sets the class to apply to the label
|
||||
return this.name?"node_label_italic":"";
|
||||
},
|
||||
oneditsave: function() {
|
||||
var credentials = {};
|
||||
var newAppID = $('#node-input-appid').val();
|
||||
var newAppKey = $('#node-input-appkey').val();
|
||||
var newAppSecret = $('#node-input-appsecret').val();
|
||||
credentials.pusherappid = newAppID;
|
||||
credentials.pusherappkey = newAppKey;
|
||||
credentials.pusherappsecret = newAppSecret;
|
||||
$.ajax({
|
||||
url: 'pusher/'+this.id,
|
||||
type: 'POST',
|
||||
data: credentials,
|
||||
success: function(result){}
|
||||
});
|
||||
},
|
||||
oneditprepare: function() {
|
||||
$.getJSON('pusher/'+this.id,function(data) {
|
||||
if (data.pusherappid) {
|
||||
$('#node-input-appid').val(data.pusherappid);
|
||||
}
|
||||
if (data.pusherappkey) {
|
||||
$('#node-input-appkey').val(data.pusherappkey);
|
||||
}
|
||||
if (data.pusherappsecret) {
|
||||
$('#node-input-appsecret').val(data.pusherappsecret);
|
||||
}
|
||||
});
|
||||
},
|
||||
ondelete: function() {
|
||||
$.ajax({
|
||||
url: 'pusher/'+this.id,
|
||||
type: 'DELETE',
|
||||
success: function(result) {}
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
158
social/pusher/114-pusher.js
Normal file
@ -0,0 +1,158 @@
|
||||
/**
|
||||
* pusher.js
|
||||
* Subscription module for the Pusher service (www.pusher.com)
|
||||
* Requires 'pusher' and 'pusher-client' modules.
|
||||
*
|
||||
* Copyright 2014 Charalampos Doukas, @BuildingIoT
|
||||
*
|
||||
* 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 Pusher = require('pusher');
|
||||
var PusherClient = require('pusher-client');
|
||||
|
||||
// Require main module
|
||||
var RED = require(process.env.NODE_RED_HOME+"/red/red");
|
||||
|
||||
//node for subscribing to an event/channel
|
||||
function PusherNode(n) {
|
||||
// Create a RED node
|
||||
RED.nodes.createNode(this,n);
|
||||
|
||||
var node = this;
|
||||
var credentials = RED.nodes.getCredentials(n.id);
|
||||
|
||||
if ((credentials) && (credentials.hasOwnProperty("pusherappkey_sub"))) { this.appkey = credentials.pusherappkey_sub; }
|
||||
else { this.error("No Pusher app key set for input node"); }
|
||||
|
||||
//get parameters from user
|
||||
this.channel = n.channel;
|
||||
this.eventname = n.eventname;
|
||||
|
||||
//create a subscription to the channel and event defined by user
|
||||
var socket = new PusherClient(''+this.appkey);
|
||||
var my_channel = socket.subscribe(''+this.channel);
|
||||
socket.bind(''+this.eventname,
|
||||
function(data) {
|
||||
var msg = {};
|
||||
if (data.hasOwnProperty("payload")) { msg.payload = data.payload; }
|
||||
else { msg.payload = data; }
|
||||
node.send(msg);
|
||||
}
|
||||
);
|
||||
|
||||
this.on("close", function() {
|
||||
socket.disconnect();
|
||||
});
|
||||
}
|
||||
|
||||
//Node for sending Pusher events
|
||||
function PusherNodeSend(n) {
|
||||
// Create a RED node
|
||||
RED.nodes.createNode(this,n);
|
||||
|
||||
var node = this;
|
||||
|
||||
var credentials = RED.nodes.getCredentials(n.id);
|
||||
|
||||
if ((credentials) && (credentials.hasOwnProperty("pusherappid"))) { this.appid = credentials.pusherappid; }
|
||||
else { this.error("No Pusher api token set"); }
|
||||
if ((credentials) && (credentials.hasOwnProperty("pusherappsecret"))) { this.appsecret = credentials.pusherappsecret; }
|
||||
else { this.error("No Pusher user secret set"); }
|
||||
if ((credentials) && (credentials.hasOwnProperty("pusherappkey"))) { this.appkey = credentials.pusherappkey; }
|
||||
else { this.error("No Pusher user key set"); }
|
||||
|
||||
//get parameters from user
|
||||
this.channel = n.channel;
|
||||
this.eventname = n.eventname;
|
||||
|
||||
var pusher = new Pusher({
|
||||
appId: this.appid,
|
||||
key: this.appkey,
|
||||
secret: this.appsecret
|
||||
});
|
||||
|
||||
this.on("input", function(msg){
|
||||
pusher.trigger(this.channel, this.eventname, {
|
||||
"payload": msg.payload
|
||||
});
|
||||
});
|
||||
|
||||
this.on("close", function() {
|
||||
});
|
||||
}
|
||||
|
||||
//debugging on the output:
|
||||
var displayResult = function(result) {
|
||||
node.log(result);
|
||||
};
|
||||
|
||||
var displayError = function(err) {
|
||||
node.log("Error: "+err);
|
||||
};
|
||||
|
||||
RED.nodes.registerType("pusher in",PusherNode);
|
||||
RED.nodes.registerType("pusher out",PusherNodeSend);
|
||||
|
||||
var querystring = require('querystring');
|
||||
|
||||
RED.httpAdmin.get('/pusher/:id',function(req,res) {
|
||||
var credentials = RED.nodes.getCredentials(req.params.id);
|
||||
if (credentials) {
|
||||
res.send(JSON.stringify({pusherappid:credentials.pusherappid,pusherappsecret:credentials.pusherappsecret, pusherappkey:credentials.pusherappkey, pusherappkey_sub:credentials.pusherappkey_sub}));
|
||||
} else {
|
||||
res.send(JSON.stringify({}));
|
||||
}
|
||||
});
|
||||
|
||||
RED.httpAdmin.delete('/pusher/:id',function(req,res) {
|
||||
RED.nodes.deleteCredentials(req.params.id);
|
||||
res.send(200);
|
||||
});
|
||||
|
||||
RED.httpAdmin.post('/pusher/: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.pusherappid == null || newCreds.pusherappid == "") {
|
||||
delete credentials.pusherappid;
|
||||
} else {
|
||||
credentials.pusherappid = newCreds.pusherappid;
|
||||
}
|
||||
if (newCreds.pusherappkey == "") {
|
||||
delete credentials.pusherappkey;
|
||||
} else {
|
||||
credentials.pusherappkey = newCreds.pusherappkey||credentials.pusherappkey;
|
||||
}
|
||||
|
||||
if (newCreds.pusherappsecret == "") {
|
||||
delete credentials.pusherappsecret;
|
||||
} else {
|
||||
credentials.pusherappsecret = newCreds.pusherappsecret||credentials.pusherappsecret;
|
||||
}
|
||||
|
||||
if (newCreds.pusherappkey_sub == "") {
|
||||
delete credentials.pusherappkey_sub;
|
||||
} else {
|
||||
credentials.pusherappkey_sub = newCreds.pusherappkey_sub||credentials.pusherappkey_sub;
|
||||
}
|
||||
|
||||
RED.nodes.addCredentials(req.params.id,credentials);
|
||||
res.send(200);
|
||||
});
|
||||
});
|
BIN
social/pusher/icons/pusher.png
Normal file
After Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 553 B After Width: | Height: | Size: 383 B |
@ -1,5 +1,5 @@
|
||||
<!--
|
||||
Copyright 2013 IBM Corp.
|
||||
Copyright 2013,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.
|
||||
@ -14,7 +14,56 @@
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<script type="text/x-red" data-template-name="xmpp">
|
||||
<script type="text/x-red" data-template-name="xmpp in">
|
||||
<div class="form-row">
|
||||
<label for="node-input-server"><i class="icon-bookmark"></i> Server</label>
|
||||
<input type="text" id="node-input-server">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-to"><i class="icon-envelope"></i> Buddy</label>
|
||||
<input type="text" id="node-input-to" placeholder="joe@gmail.com">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label> </label>
|
||||
<input type="checkbox" id="node-input-join" placeholder="" style="display: inline-block; width: auto; vertical-align: top;">
|
||||
<label for="node-input-join" style="width: 70%;">Is a Chat Room ?</label>
|
||||
</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="xmpp in">
|
||||
<p>Connects to an XMPP server to receive messages.</p>
|
||||
<p>The <b>Buddy</b> field is the id of the buddy or room you want to receive messages from.</p>
|
||||
<p>Incoming messages will appear as <b>msg.payload</b> on the first output, while <b>msg.topic</b> will contain who it is from.</p>
|
||||
<p>The second output will show the presence and status of a user in <b>msg.payload</b>. Again <b>msg.topic</b> will hold the user.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('xmpp in',{
|
||||
category: 'social-input',
|
||||
color:"#F4F492",
|
||||
defaults: {
|
||||
name: {value:""},
|
||||
server: {type:"xmpp-server",required:true},
|
||||
to: {value:"",required:true},
|
||||
join: {value:false}
|
||||
},
|
||||
inputs:0,
|
||||
outputs:2,
|
||||
icon: "xmpp.png",
|
||||
label: function() {
|
||||
return this.name||"xmpp";
|
||||
},
|
||||
labelStyle: function() {
|
||||
return (this.name)?"node_label_italic":"";
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-template-name="xmpp out">
|
||||
<div class="form-row">
|
||||
<label for="node-input-server"><i class="icon-bookmark"></i> Server</label>
|
||||
<input type="text" id="node-input-server">
|
||||
@ -33,10 +82,6 @@
|
||||
<input type="checkbox" id="node-input-join" placeholder="" style="display: inline-block; width: auto; vertical-align: top;">
|
||||
<label for="node-input-join" style="width: 70%;">Is a Chat Room ?</label>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-nick"><i class="icon-user"></i> Nickname</label>
|
||||
<input type="text" id="node-input-nick" placeholder="Joe">
|
||||
</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">
|
||||
@ -44,35 +89,34 @@
|
||||
<div class="form-tips">The <b>To</b> field is optional. If not set uses the <b>msg.topic</b> property of the message.</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="xmpp">
|
||||
<p>Connects to an XMPP server to send and receive messages.</p>
|
||||
<p>Incoming messages will appear as <b>msg.payload</b> on the first output, while <b>msg.topic</b> will contain who it is from.</p>
|
||||
<p>The second output will user presence and status in <b>msg.payload</b>.</p>
|
||||
<p>The <b>To</b> field is optional. If not set uses the <b>msg.topic</b> property of the message.</p>
|
||||
<script type="text/x-red" data-help-name="xmpp out">
|
||||
<p>Connects to an XMPP server to send messages.</p>
|
||||
<p>The <b>To</b> field is optional. If not set the <b>msg.topic</b> property of the message is used.</p>
|
||||
<p>If you are joining a room then the <b>To</b> field must be filled in.</p>
|
||||
|
||||
<p>You may also send a msg with <b>msg.presence</b> to set your presence to one of <i>chat, away, dnd</i> or <i>xa</i>.
|
||||
If you do so then the <b>msg.payload</b> will set your status message.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('xmpp',{
|
||||
category: 'advanced-function',
|
||||
color:"Silver",
|
||||
RED.nodes.registerType('xmpp out',{
|
||||
category: 'social-output',
|
||||
color:"#F4F492",
|
||||
defaults: {
|
||||
name: {value:""},
|
||||
server: {type:"xmpp-server",required:true},
|
||||
to: {value:""},
|
||||
join: {value:false},
|
||||
sendObject: {value:false},
|
||||
nick: {value:""}
|
||||
sendObject: {value:false}
|
||||
},
|
||||
inputs:1,
|
||||
outputs:2,
|
||||
outputs:0,
|
||||
icon: "xmpp.png",
|
||||
align: "right",
|
||||
label: function() {
|
||||
return this.name||"xmpp";
|
||||
},
|
||||
labelStyle: function() {
|
||||
return (this.name||!this.server)?"node_label_italic":"";
|
||||
return (this.name)?"node_label_italic":"";
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@ -84,6 +128,10 @@
|
||||
<label for="node-config-input-port" style="margin-left: 10px; width: 35px; "> Port</label>
|
||||
<input type="text" id="node-config-input-port" placeholder="Port" style="width:45px">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-config-input-nickname"><i class="icon-user"></i> Nickname</label>
|
||||
<input type="text" id="node-config-input-nickname" placeholder="Joe">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-config-input-user"><i class="icon-user"></i> Username</label>
|
||||
<input type="text" id="node-config-input-user">
|
||||
@ -92,6 +140,7 @@
|
||||
<label for="node-config-input-pass"><i class="icon-lock"></i> Password</label>
|
||||
<input type="password" id="node-config-input-pass">
|
||||
</div>
|
||||
<div class="form-tips" id="node-config-cred-tip"><b>Note:</b> Using credentials from global xmppkey.js file.</div>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
@ -100,49 +149,38 @@
|
||||
defaults: {
|
||||
server: {required:true},
|
||||
port: {value:5222,required:true,validate:RED.validators.number()},
|
||||
user: {required:true},
|
||||
pass: {required:true}
|
||||
|
||||
nickname: {}
|
||||
},
|
||||
label: function() {
|
||||
return (this.user?this.user+"@":"")+this.server+":"+this.port;
|
||||
return (this.nickname?this.nickname+"@":"")+this.server+":"+this.port;
|
||||
},
|
||||
oneditprepare: function() {
|
||||
$.getJSON('xmpp-server/'+this.id,function(data) {
|
||||
if (data.user) {
|
||||
$('#node-config-input-user').val(data.user);
|
||||
}
|
||||
if (data.server) {
|
||||
$('#node-config-input-server').val(data.server);
|
||||
}
|
||||
if (data.port) {
|
||||
$('#node-config-input-port').val(data.port);
|
||||
}
|
||||
if (data.hasPassword) {
|
||||
$('#node-config-input-pass').val('__PWRD__');
|
||||
} else {
|
||||
$('#node-config-input-pass').val('');
|
||||
}
|
||||
|
||||
if (data.global) $('#node-config-cred-tip').show();
|
||||
else $('#node-config-cred-tip').hide();
|
||||
});
|
||||
},
|
||||
oneditsave: function() {
|
||||
var credentials = {};
|
||||
var newUser = $('#node-config-input-user').val();
|
||||
var newPass = $('#node-config-input-pass').val();
|
||||
//var newServer = $('#node-config-input-server').val();
|
||||
//var newPort = $('#node-config-input-port').val();
|
||||
var credentials = {};
|
||||
credentials.user = newUser;
|
||||
if (newPass != '__PWRD__') {
|
||||
credentials.password = newPass;
|
||||
}
|
||||
//credentials.server = newServer;
|
||||
//credentials.port = newPort;
|
||||
$.ajax({
|
||||
url: 'xmpp-server/'+this.id,
|
||||
type: 'POST',
|
||||
data: credentials,
|
||||
success:function(result){}
|
||||
success: function(result){}
|
||||
});
|
||||
},
|
||||
ondelete: function() {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2013 IBM Corp.
|
||||
* Copyright 2013,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.
|
||||
@ -14,33 +14,23 @@
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
var orig=console.warn;
|
||||
console.warn=(function() { // suppress warning from stringprep when not needed)
|
||||
var orig=console.warn;
|
||||
return function() {
|
||||
//orig.apply(console, arguments);
|
||||
};
|
||||
})();
|
||||
module.exports = function(RED) {
|
||||
"use strict";
|
||||
var XMPP = require('simple-xmpp');
|
||||
|
||||
var RED = require(process.env.NODE_RED_HOME+"/red/red");
|
||||
var xmpp = require('simple-xmpp');
|
||||
console.warn = orig;
|
||||
|
||||
try {
|
||||
var xmppkey = RED.settings.xmpp || require(process.env.NODE_RED_HOME+"/../xmppkeys.js");
|
||||
} catch(err) {
|
||||
// throw new Error("Failed to load XMPP credentials");
|
||||
}
|
||||
try { var xmppkey = RED.settings.xmpp || require(process.env.NODE_RED_HOME+"/../xmppkeys.js"); }
|
||||
catch(err) { }
|
||||
|
||||
function XMPPServerNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.server = n.server;
|
||||
this.port = n.port;
|
||||
this.nickname = n.nickname;
|
||||
var credentials = RED.nodes.getCredentials(n.id);
|
||||
if (credentials) {
|
||||
this.username = credentials.user;
|
||||
this.password = credentials.password;
|
||||
}
|
||||
}
|
||||
}
|
||||
RED.nodes.registerType("xmpp-server",XMPPServerNode);
|
||||
|
||||
@ -51,9 +41,9 @@ RED.httpAdmin.get('/xmpp-server/:id',function(req,res) {
|
||||
if (credentials) {
|
||||
res.send(JSON.stringify({user:credentials.user,hasPassword:(credentials.password&&credentials.password!="")}));
|
||||
} else if (xmppkey && xmppkey.jid && xmppkey.password) {
|
||||
RED.nodes.addCredentials(req.params.id,{user:xmppkey.jid,password:xmppkey.password});
|
||||
credentials = RED.nodes.getCredentials(req.params.id);
|
||||
res.send(JSON.stringify({user:credentials.user,hasPassword:(credentials.password&&credentials.password!="")}));
|
||||
RED.nodes.addCredentials(req.params.id,{user:xmppkey.jid, password:xmppkey.password, global:true});
|
||||
credentials = RED.nodes.getCredentials(req.params.id);
|
||||
res.send(JSON.stringify({user:credentials.user,global:credentials.global,hasPassword:(credentials.password&&credentials.password!="")}));
|
||||
} else {
|
||||
res.send(JSON.stringify({}));
|
||||
}
|
||||
@ -88,46 +78,28 @@ RED.httpAdmin.post('/xmpp-server/:id',function(req,res) {
|
||||
});
|
||||
|
||||
|
||||
function XmppNode(n) {
|
||||
function XmppInNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.server = n.server;
|
||||
try {
|
||||
this.serverConfig = RED.nodes.getNode(this.server);
|
||||
} catch (err) {
|
||||
}
|
||||
if (this.serverConfig){
|
||||
this.host = this.serverConfig.server;
|
||||
this.port = this.serverConfig.port;
|
||||
this.jid = this.serverConfig.username;
|
||||
this.password = this.serverConfig.password;
|
||||
} else if (xmppkey) {
|
||||
console.warn("no serverConfig found, trying old creds file");
|
||||
this.host = n.server;
|
||||
this.port = n.port;
|
||||
this.jid = xmppkey.jid;
|
||||
this.password = xmppkey.password;
|
||||
}
|
||||
|
||||
this.serverConfig = RED.nodes.getNode(this.server);
|
||||
this.host = this.serverConfig.server;
|
||||
this.port = this.serverConfig.port;
|
||||
this.nick = this.serverConfig.nickname || "Node-RED";
|
||||
this.userid = this.serverConfig.username;
|
||||
this.password = this.serverConfig.password;
|
||||
|
||||
this.join = n.join || false;
|
||||
this.nick = n.nick || "Node-RED";
|
||||
this.sendAll = n.sendObject;
|
||||
this.to = n.to || "";
|
||||
var node = this;
|
||||
|
||||
setTimeout(function() {
|
||||
xmpp.connect({
|
||||
jid : node.jid,
|
||||
password : node.password,
|
||||
host : node.host,
|
||||
port : node.port,
|
||||
skipPresence : true,
|
||||
reconnect : false
|
||||
});
|
||||
}, 5000);
|
||||
var xmpp = new XMPP.SimpleXMPP();
|
||||
|
||||
xmpp.on('online', function() {
|
||||
node.log('connected to '+node.server);
|
||||
xmpp.setPresence('online', node.nick+' online');
|
||||
node.log('connected to '+node.host+":"+node.port);
|
||||
node.status({fill:"green",shape:"dot",text:"connected"});
|
||||
//xmpp.setPresence('online', node.nick+' online');
|
||||
if (node.join) {
|
||||
xmpp.join(node.to+'/'+node.nick);
|
||||
}
|
||||
@ -156,39 +128,126 @@ function XmppNode(n) {
|
||||
});
|
||||
|
||||
xmpp.on('error', function(err) {
|
||||
console.error(err);
|
||||
console.error("error",err);
|
||||
});
|
||||
|
||||
xmpp.on('close', function(err) {
|
||||
node.log('connection closed');
|
||||
node.status({fill:"red",shape:"ring",text:"not connected"});
|
||||
});
|
||||
|
||||
xmpp.on('subscribe', function(from) {
|
||||
xmpp.acceptSubscription(from);
|
||||
});
|
||||
|
||||
this.on("input", function(msg) {
|
||||
var to = msg.topic;
|
||||
if (node.to != "") { to = node.to; }
|
||||
if (node.sendAll) {
|
||||
xmpp.send(to, JSON.stringify(msg), node.join);
|
||||
}
|
||||
else {
|
||||
xmpp.send(to, msg.payload, node.join);
|
||||
}
|
||||
});
|
||||
// Now actually make the connection
|
||||
try {
|
||||
xmpp.connect({
|
||||
jid : node.userid,
|
||||
password : node.password,
|
||||
host : node.host,
|
||||
port : node.port,
|
||||
skipPresence : true,
|
||||
reconnect : false
|
||||
});
|
||||
} catch(e) {
|
||||
node.error("Bad xmpp configuration");
|
||||
node.status({fill:"red",shape:"ring",text:"not connected"});
|
||||
}
|
||||
|
||||
this.on("close", function() {
|
||||
xmpp.setPresence('offline');
|
||||
try {
|
||||
xmpp.disconnect();
|
||||
// TODO - DCJ NOTE... this is not good. It leaves the connection up over a restart - which will end up with bad things happening...
|
||||
// (but requires the underlying xmpp lib to be fixed, which does have an open bug request on fixing the close method - and a work around.
|
||||
// see - https://github.com/simple-xmpp/node-simple-xmpp/issues/12 for the fix
|
||||
} catch(e) {
|
||||
this.warn("Due to an underlying bug in the xmpp library this does not disconnect old sessions. This is bad... A restart would be better.");
|
||||
}
|
||||
node.on("close", function(done) {
|
||||
//xmpp.setPresence('offline');
|
||||
if (xmpp.conn) { xmpp.conn.end(); }
|
||||
xmpp = null;
|
||||
done();
|
||||
});
|
||||
}
|
||||
RED.nodes.registerType("xmpp in",XmppInNode);
|
||||
|
||||
RED.nodes.registerType("xmpp",XmppNode);
|
||||
function XmppOutNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.server = n.server;
|
||||
|
||||
this.serverConfig = RED.nodes.getNode(this.server);
|
||||
this.host = this.serverConfig.server;
|
||||
this.port = this.serverConfig.port;
|
||||
this.nick = this.serverConfig.nickname || "Node-RED";
|
||||
this.userid = this.serverConfig.username;
|
||||
this.password = this.serverConfig.password;
|
||||
|
||||
this.join = n.join || false;
|
||||
this.sendAll = n.sendObject;
|
||||
this.to = n.to || "";
|
||||
var node = this;
|
||||
|
||||
var xmpp = new XMPP.SimpleXMPP();
|
||||
|
||||
xmpp.on('online', function() {
|
||||
node.log('connected to '+node.host+":"+node.port);
|
||||
node.status({fill:"green",shape:"dot",text:"connected"});
|
||||
xmpp.setPresence('online', node.nick+' online');
|
||||
if (node.join) {
|
||||
xmpp.join(node.to+'/'+node.nick);
|
||||
}
|
||||
});
|
||||
|
||||
xmpp.on('error', function(err) {
|
||||
console.error("error",err);
|
||||
});
|
||||
|
||||
xmpp.on('close', function(err) {
|
||||
node.log('connection closed');
|
||||
node.status({fill:"red",shape:"ring",text:"not connected"});
|
||||
});
|
||||
|
||||
xmpp.on('subscribe', function(from) {
|
||||
xmpp.acceptSubscription(from);
|
||||
});
|
||||
|
||||
// Now actually make the connection
|
||||
try {
|
||||
xmpp.connect({
|
||||
jid : node.userid,
|
||||
password : node.password,
|
||||
host : node.host,
|
||||
port : node.port,
|
||||
skipPresence : true,
|
||||
reconnect : false
|
||||
});
|
||||
} catch(e) {
|
||||
node.error("Bad xmpp configuration");
|
||||
node.status({fill:"red",shape:"ring",text:"not connected"});
|
||||
}
|
||||
|
||||
node.on("input", function(msg) {
|
||||
if (msg.presence) {
|
||||
if (['away', 'dnd', 'xa','chat'].indexOf(msg.presence) > -1 ) {
|
||||
xmpp.setPresence(msg.presence, msg.payload);
|
||||
}
|
||||
else { node.warn("Can't set presence - invalid value"); }
|
||||
}
|
||||
else {
|
||||
var to = msg.topic;
|
||||
if (node.to != "") { to = node.to; }
|
||||
if (node.sendAll) {
|
||||
xmpp.send(to, JSON.stringify(msg), node.join);
|
||||
}
|
||||
else if (msg.payload) {
|
||||
if (typeof(msg.payload) === "object") {
|
||||
xmpp.send(to, JSON.stringify(msg.payload), node.join);
|
||||
} else {
|
||||
xmpp.send(to, msg.payload.toString(), node.join);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
node.on("close", function() {
|
||||
xmpp.setPresence('offline');
|
||||
if (xmpp.conn) { xmpp.conn.end(); }
|
||||
xmpp = null;
|
||||
});
|
||||
}
|
||||
RED.nodes.registerType("xmpp out",XmppOutNode);
|
||||
|
||||
}
|
||||
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 1.0 KiB |
BIN
storage/leveldb/icons/leveldb.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 625 B After Width: | Height: | Size: 582 B |
@ -14,44 +14,47 @@
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
var RED = require(process.env.NODE_RED_HOME+"/red/red");
|
||||
var SunCalc = require('suncalc');
|
||||
module.exports = function(RED) {
|
||||
var SunCalc = require('suncalc');
|
||||
|
||||
function SunNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.lat = n.lat;
|
||||
this.lon = n.lon;
|
||||
this.start = n.start;
|
||||
this.end = n.end;
|
||||
function SunNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.lat = n.lat;
|
||||
this.lon = n.lon;
|
||||
this.start = n.start;
|
||||
this.end = n.end;
|
||||
|
||||
var node = this;
|
||||
var oldval = null;
|
||||
var node = this;
|
||||
var oldval = null;
|
||||
|
||||
this.tick = setInterval(function() {
|
||||
var now = new Date();
|
||||
var hour = now.getUTCHours();
|
||||
var mins = now.getUTCMinutes();
|
||||
var times = SunCalc.getTimes(now, node.lat, node.lon);
|
||||
var hour1 = times[node.start].getUTCHours();
|
||||
var mins1 = times[node.start].getUTCMinutes();
|
||||
var hour2 = times[node.end].getUTCHours();
|
||||
var mins2 = times[node.end].getUTCMinutes();
|
||||
var e1 = (hour*60+mins) - (hour1*60+mins1);
|
||||
var e2 = (hour*60+mins) - (hour2*60+mins2);
|
||||
var moon = SunCalc.getMoonIllumination(now).fraction;
|
||||
msg = { payload:0, topic:"sun", moon:moon };
|
||||
if ((e1 > 0) & (e2 < 0)) { msg.payload = 1; }
|
||||
if (oldval == null) { oldval = msg.payload; }
|
||||
if (msg.payload != oldval) {
|
||||
oldval = msg.payload;
|
||||
msg2 = msg;
|
||||
node.send( [msg,msg2] );
|
||||
}
|
||||
else { node.send(msg); }
|
||||
}, 60000);
|
||||
this.tick = setInterval(function() {
|
||||
var now = new Date();
|
||||
var hour = now.getUTCHours();
|
||||
var mins = now.getUTCMinutes();
|
||||
var times = SunCalc.getTimes(now, node.lat, node.lon);
|
||||
var hour1 = times[node.start].getUTCHours();
|
||||
var mins1 = times[node.start].getUTCMinutes();
|
||||
var hour2 = times[node.end].getUTCHours();
|
||||
var mins2 = times[node.end].getUTCMinutes();
|
||||
var e1 = (hour*60+mins) - (hour1*60+mins1);
|
||||
var e2 = (hour*60+mins) - (hour2*60+mins2);
|
||||
var moon = SunCalc.getMoonIllumination(now).fraction;
|
||||
msg = { payload:0, topic:"sun", moon:moon };
|
||||
if ((e1 > 0) & (e2 < 0)) { msg.payload = 1; }
|
||||
if (oldval == null) { oldval = msg.payload; }
|
||||
if (msg.payload == 1) { node.status({fill:"yellow",shape:"dot",text:"day"}); }
|
||||
else { node.status({fill:"blue",shape:"dot",text:"night"}); }
|
||||
if (msg.payload != oldval) {
|
||||
oldval = msg.payload;
|
||||
msg2 = msg;
|
||||
node.send( [msg,msg2] );
|
||||
}
|
||||
else { node.send(msg); }
|
||||
}, 60000);
|
||||
|
||||
this.on("close", function() {
|
||||
clearInterval(this.tick);
|
||||
});
|
||||
this.on("close", function() {
|
||||
clearInterval(this.tick);
|
||||
});
|
||||
}
|
||||
RED.nodes.registerType("sunrise",SunNode);
|
||||
}
|
||||
RED.nodes.registerType("sunrise",SunNode);
|
||||
|
Before Width: | Height: | Size: 383 B After Width: | Height: | Size: 581 B |