Merge remote-tracking branch 'upstream/master'

Conflicts:
	social/xmpp/92-xmpp.html
	social/xmpp/92-xmpp.js
This commit is contained in:
Ben Hardill 2014-06-19 23:52:40 +01:00
commit 42ad8920cb
24 changed files with 1081 additions and 235 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 719 B

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -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);
});

View File

@ -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>

View File

@ -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);

View File

@ -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>

View File

@ -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>

View File

@ -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
View 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
View 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);
}

View File

@ -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">

View File

@ -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;

View File

@ -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() {

View File

@ -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({}));
}
});

View 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
View 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);
});
});

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 553 B

After

Width:  |  Height:  |  Size: 383 B

View File

@ -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>&nbsp;</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() {

View File

@ -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);
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 625 B

After

Width:  |  Height:  |  Size: 582 B

View File

@ -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);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 383 B

After

Width:  |  Height:  |  Size: 581 B