mirror of
https://github.com/node-red/node-red.git
synced 2025-03-01 10:36:34 +00:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
@@ -17,6 +17,8 @@
|
||||
<!-- Sample html file that corresponds to the 99-sample.js file -->
|
||||
<!-- This creates and configures the onscreen elements of the node -->
|
||||
|
||||
<!-- If you use this as a template, replace IBM Corp. with your own name. -->
|
||||
|
||||
<!-- First, the content of the edit dialog is defined. -->
|
||||
|
||||
<script type="text/x-red" data-template-name="sample">
|
||||
@@ -24,7 +26,7 @@
|
||||
|
||||
<!-- Each of the following divs creates a field in the edit dialog. -->
|
||||
<!-- Generally, there should be an input for each property of the node. -->
|
||||
<!-- The for and id attributes identify the corresponding property -->
|
||||
<!-- The for and id attributes identify the corresponding property -->
|
||||
<!-- (with the 'node-input-' prefix). -->
|
||||
<!-- The available icon classes are defined in Twitter Bootstrap -->
|
||||
<div class="form-row">
|
||||
@@ -38,7 +40,6 @@
|
||||
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||
<input type="text" id="node-input-name" placeholder="Name">
|
||||
</div>
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
|
@@ -14,38 +14,39 @@
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
// If you use this as a template, replace IBM Corp. with your own name.
|
||||
|
||||
// Sample Node-RED node file
|
||||
|
||||
// Require main module
|
||||
var RED = require("../../red/red");
|
||||
|
||||
// The main node definition - most things happen in here
|
||||
function SampleNode(n) {
|
||||
function SampleNode(n) {
|
||||
// Create a RED node
|
||||
RED.nodes.createNode(this,n);
|
||||
|
||||
|
||||
// Store local copies of the node configuration (as defined in the .html)
|
||||
this.topic = n.topic;
|
||||
|
||||
|
||||
// Do whatever you need to do in here - declare callbacks etc
|
||||
// Note: this sample doesn't do anything much - it will only send
|
||||
// this message once at startup...
|
||||
// Look at other real nodes for some better ideas of what to do....
|
||||
var msg = {};
|
||||
msg.topic = node.topic;
|
||||
msg.topic = this.topic;
|
||||
msg.payload = "Hello world !"
|
||||
|
||||
|
||||
// send out the message to the rest of the workspace.
|
||||
this.send(msg);
|
||||
|
||||
this.on("close", function() {
|
||||
// Called when the node is shutdown - eg on redeploy.
|
||||
// Allows ports to be closed, connections dropped etc.
|
||||
// eg: this.client.disconnect();
|
||||
});
|
||||
}
|
||||
|
||||
// Register the node by name. This must be called before overriding any of the
|
||||
// Node functions.
|
||||
RED.nodes.registerType("sample",SampleNode);
|
||||
|
||||
|
||||
SampleNode.prototype.close = function() {
|
||||
// Called when the node is shutdown - eg on redeploy.
|
||||
// Allows ports to be closed, connections dropped etc.
|
||||
// eg: this.client.disconnect();
|
||||
}
|
||||
|
@@ -37,7 +37,7 @@
|
||||
category: 'advanced-function',
|
||||
color:"#E6E0F8",
|
||||
defaults: {
|
||||
useEyes: {value:"false"},
|
||||
useEyes: {value:false},
|
||||
name: {value:""},
|
||||
},
|
||||
inputs:1,
|
||||
|
@@ -202,7 +202,7 @@
|
||||
},
|
||||
oneditprepare: function() {
|
||||
var repeattype = "none";
|
||||
if (Number(this.repeat) != 0) {
|
||||
if (this.repeat != "") {
|
||||
repeattype = "interval";
|
||||
$("#inject-time-interval-units option").filter(function() {return $(this).val() == "s";}).attr('selected',true);
|
||||
$("#inject-time-interval-count").val(this.repeat);
|
||||
@@ -210,7 +210,7 @@
|
||||
} else if (this.crontab) {
|
||||
var cronparts = this.crontab.split(" ");
|
||||
var days = cronparts[4];
|
||||
if (Number(cronparts[0]) && Number(cronparts[1])) {
|
||||
if (!isNaN(cronparts[0]) && !isNaN(cronparts[1])) {
|
||||
repeattype = "time";
|
||||
// Fixed time
|
||||
var time = cronparts[1]+":"+cronparts[0];
|
||||
|
@@ -21,7 +21,7 @@
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-func"><i class="icon-wrench"></i> Function</label>
|
||||
<input type="hidden" id="node-input-func">
|
||||
<input type="hidden" id="node-input-func" autofocus="autofocus">
|
||||
<div style="height: 250px;" class="node-text-editor" id="node-input-func-editor" ></div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
@@ -85,6 +85,7 @@
|
||||
editor:that.editor, // the field name the main text body goes to
|
||||
fields:['name','outputs']
|
||||
});
|
||||
$("#node-input-name").focus();
|
||||
|
||||
});
|
||||
},
|
||||
|
@@ -22,7 +22,7 @@
|
||||
|
||||
<div class="form-row">
|
||||
<label for="node-input-template"><i class="icon-wrench"></i> Template</label>
|
||||
<input type="hidden" id="node-input-template">
|
||||
<input type="hidden" id="node-input-template" autofocus="autofocus">
|
||||
<div style="height: 250px;" class="node-text-editor" id="node-input-template-editor" ></div>
|
||||
</div>
|
||||
|
||||
@@ -79,7 +79,7 @@
|
||||
editor:that.editor, // the field name the main text body goes to
|
||||
fields:['name']
|
||||
});
|
||||
|
||||
$("#node-input-name").focus();
|
||||
});
|
||||
},
|
||||
oneditsave: function() {
|
||||
|
@@ -21,7 +21,7 @@
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-info" style="width: 100% !important;"><i class="icon-file"></i> More</label>
|
||||
<input type="hidden" id="node-input-info">
|
||||
<input type="hidden" id="node-input-info" autofocus="autofocus">
|
||||
<div style="height: 250px;" class="node-text-editor" id="node-input-info-editor" ></div>
|
||||
</div>
|
||||
<div class="form-tips">Tip: this isn't meant for War and Peace - but useful notes can be kept here.</div>
|
||||
@@ -75,6 +75,7 @@
|
||||
showFoldingRuler:false,
|
||||
contents: $("#node-input-info").val()
|
||||
});
|
||||
$("#node-input-name").focus();
|
||||
});
|
||||
},
|
||||
oneditsave: function() {
|
||||
|
@@ -138,7 +138,7 @@
|
||||
category: 'config',
|
||||
defaults: {
|
||||
//baud: {baud:"57600",required:true},
|
||||
repeat: {value:"25",required:true,validate:RED.validators.number()},
|
||||
repeat: {value:"50",required:true,validate:RED.validators.number()},
|
||||
device: {value:"",required:true}
|
||||
},
|
||||
label: function() {
|
||||
|
@@ -25,46 +25,46 @@ function ArduinoNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.device = n.device;
|
||||
this.repeat = n.repeat||25;
|
||||
util.log("[firmata] Opening"+this.device);
|
||||
util.log("[firmata] Opening "+this.device);
|
||||
var node = this;
|
||||
|
||||
// var tou = setInterval(function() {
|
||||
// if (!arduinoReady) {
|
||||
// clearInterval(tou);
|
||||
|
||||
arduinoReady = false;
|
||||
if (thisboard == null) {
|
||||
this.board = new firmata.Board(this.device, function(err) {
|
||||
if (err) {
|
||||
util.log("[firmata] "+err);
|
||||
return;
|
||||
node.toun = setInterval(function() {
|
||||
if (!arduinoReady) {
|
||||
if (thisboard == null) {
|
||||
node.board = new firmata.Board(node.device, function(err) {
|
||||
if (err) {
|
||||
console.log("[firmata] error: ",err);
|
||||
return;
|
||||
}
|
||||
arduinoReady = true;
|
||||
thisboard = node.board;
|
||||
clearInterval(node.toun);
|
||||
util.log('[firmata] Arduino connected');
|
||||
});
|
||||
}
|
||||
arduinoReady = true;
|
||||
util.log('[firmata] Arduino connected');
|
||||
});
|
||||
thisboard = this.board;
|
||||
}
|
||||
else {
|
||||
util.log("[firmata] Arduino already connected");
|
||||
this.board = thisboard;
|
||||
console.log(this.board._events);
|
||||
this.board.removeAllListeners();
|
||||
arduinoReady = true;
|
||||
}
|
||||
else {
|
||||
node.board = thisboard;
|
||||
node.board.removeAllListeners();
|
||||
arduinoReady = true;
|
||||
clearInterval(node.toun);
|
||||
node.toun = false;
|
||||
util.log("[firmata] Arduino already connected");
|
||||
}
|
||||
} else { util.log("[firmata] Waiting for Firmata"); }
|
||||
}, 10000); // wait for firmata to connect to arduino
|
||||
|
||||
// } else { util.log("[firmata] Waiting for Firmata"); }
|
||||
// }, 1000); // wait for firmata to disconnect from arduino
|
||||
|
||||
this._close = function() {
|
||||
this.on('close', function() {
|
||||
//this.board.sp.close(function() { console.log("[firmata] Serial port closed"); arduinoReady = false; });
|
||||
arduinoReady = false;
|
||||
if (node.toun) {
|
||||
clearInterval(node.toun);
|
||||
util.log("[firmata] arduino wait loop stopped");
|
||||
}
|
||||
util.log("[firmata] Stopped");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
RED.nodes.registerType("arduino-board",ArduinoNode);
|
||||
|
||||
ArduinoNode.prototype.close = function() {
|
||||
this._close();
|
||||
}
|
||||
|
||||
// The Input Node
|
||||
function DuinoNodeIn(n) {
|
||||
@@ -78,11 +78,13 @@ function DuinoNodeIn(n) {
|
||||
this.board = this.serverConfig.board;
|
||||
this.repeat = this.serverConfig.repeat;
|
||||
var node = this;
|
||||
|
||||
var tout = setInterval(function() {
|
||||
if (arduinoReady) {
|
||||
clearInterval(tout);
|
||||
console.log(node.state,node.pin,node.board.MODES[node.state]);
|
||||
|
||||
node.toui = setInterval(function() {
|
||||
if (thisboard != null) {
|
||||
node.board = thisboard;
|
||||
clearInterval(node.toui);
|
||||
node.toui = false;
|
||||
//console.log(node.state,node.pin,node.board.MODES[node.state]);
|
||||
node.board.pinMode(node.pin, node.board.MODES[node.state]);
|
||||
node.board.setSamplingInterval(node.repeat);
|
||||
var oldrdg = "";
|
||||
@@ -103,23 +105,21 @@ function DuinoNodeIn(n) {
|
||||
}
|
||||
}
|
||||
else { node.log("Waiting for Arduino"); }
|
||||
}, 2000); // loop to wait for firmata to connect to arduino
|
||||
|
||||
this._close = function() {
|
||||
clearInterval(this._interval);
|
||||
util.log("[arduino] input eventlistener stopped");
|
||||
}
|
||||
}, 5000); // loop to wait for firmata to connect to arduino
|
||||
|
||||
this.on('close', function() {
|
||||
if (node.toui) {
|
||||
clearInterval(node.toui);
|
||||
util.log("[firmata] input wait loop stopped");
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
util.log("[arduino] Serial Port not Configured");
|
||||
util.log("[firmata] Serial Port not Configured");
|
||||
}
|
||||
}
|
||||
RED.nodes.registerType("arduino in",DuinoNodeIn);
|
||||
|
||||
DuinoNodeIn.prototype.close = function() {
|
||||
this._close();
|
||||
}
|
||||
|
||||
|
||||
// The Output Node
|
||||
function DuinoNodeOut(n) {
|
||||
@@ -132,10 +132,10 @@ function DuinoNodeOut(n) {
|
||||
if (typeof this.serverConfig === "object") {
|
||||
this.board = this.serverConfig.board;
|
||||
var node = this;
|
||||
|
||||
|
||||
this.on("input", function(msg) {
|
||||
//console.log(msg);
|
||||
if (arduinoReady) {
|
||||
if (thisboard != null) {
|
||||
if (node.state == "OUTPUT") {
|
||||
if ((msg.payload == true)||(msg.payload == 1)||(msg.payload.toString().toLowerCase() == "on")) {
|
||||
node.board.digitalWrite(node.pin, node.board.HIGH);
|
||||
@@ -161,17 +161,26 @@ function DuinoNodeOut(n) {
|
||||
}
|
||||
//else { console.log("Arduino not ready"); }
|
||||
});
|
||||
|
||||
var touo = setInterval(function() {
|
||||
if (arduinoReady) {
|
||||
clearInterval(touo);
|
||||
//console.log(node.state,node.pin,node.board.MODES[node.state]);
|
||||
|
||||
node.touo = setInterval(function() {
|
||||
if (thisboard != null) {
|
||||
clearInterval(node.touo);
|
||||
node.touo = false;
|
||||
node.board = thisboard;
|
||||
node.board.pinMode(node.pin, node.board.MODES[node.state]);
|
||||
}
|
||||
else { util.log("[firmata] waiting for arduino to connect"); }
|
||||
}, 5000); // loop to wait for firmata to connect to arduino
|
||||
|
||||
this.on('close', function() {
|
||||
if (node.touo) {
|
||||
clearInterval(node.touo);
|
||||
util.log("[firmata] output wait loop stopped");
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
util.log("[arduino] Serial Port not Configured");
|
||||
util.log("[firmata] Serial Port not Configured");
|
||||
}
|
||||
}
|
||||
RED.nodes.registerType("arduino out",DuinoNodeOut);
|
||||
|
@@ -57,7 +57,7 @@ RED.nodes.registerType("http in",HTTPIn);
|
||||
|
||||
function HTTPOut(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
|
||||
var node = this;
|
||||
this.on("input",function(msg) {
|
||||
if (msg.res) {
|
||||
if (msg.headers) {
|
||||
@@ -65,6 +65,8 @@ function HTTPOut(n) {
|
||||
}
|
||||
var statusCode = msg.statusCode || 200;
|
||||
msg.res.send(statusCode,msg.payload);
|
||||
} else {
|
||||
node.warn("No response object");
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -80,9 +82,9 @@ function HTTPRequest(n) {
|
||||
this.on("input",function(msg) {
|
||||
|
||||
var opts = urllib.parse(msg.url||url);
|
||||
opts.method = msg.method||method;
|
||||
opts.method = (msg.method||method).toUpperCase();
|
||||
if (msg.headers) {
|
||||
opts.header = headers;
|
||||
opts.header = msg.headers;
|
||||
}
|
||||
var req = httplib.request(opts,function(res) {
|
||||
res.setEncoding('utf8');
|
||||
@@ -103,7 +105,7 @@ function HTTPRequest(n) {
|
||||
msg.statusCode = err.code;
|
||||
node.send(msg);
|
||||
});
|
||||
if (msg.payload) {
|
||||
if (msg.payload && (method == "PUSH" || method == "PUT") ) {
|
||||
if (typeof msg.payload === "string" || Buffer.isBuffer(msg.payload)) {
|
||||
req.write(msg.payload);
|
||||
} else if (typeof msg.payload == "number") {
|
||||
|
@@ -30,7 +30,7 @@ function TcpIn(n) {
|
||||
this.server = (typeof n.server == 'boolean')?n.server:(n.server == "server");
|
||||
this.closing = false;
|
||||
var node = this;
|
||||
|
||||
|
||||
if (!node.server) {
|
||||
var buffer = null;
|
||||
var client;
|
||||
@@ -41,13 +41,13 @@ function TcpIn(n) {
|
||||
buffer = (node.datatype == 'buffer')? new Buffer(0):"";
|
||||
node.log("connected to "+node.host+":"+node.port);
|
||||
});
|
||||
|
||||
|
||||
client.on('data', function (data) {
|
||||
if (node.datatype != 'buffer') {
|
||||
data = data.toString(node.datatype);
|
||||
}
|
||||
if (node.stream) {
|
||||
if ((typeof data) === "string" && node.newline != "") {
|
||||
if ((node.datatype) === "utf8" && node.newline != "") {
|
||||
buffer = buffer+data;
|
||||
var parts = buffer.split(node.newline);
|
||||
for (var i = 0;i<parts.length-1;i+=1) {
|
||||
@@ -100,7 +100,7 @@ function TcpIn(n) {
|
||||
if (node.datatype != 'buffer') {
|
||||
data = data.toString(node.datatype);
|
||||
}
|
||||
|
||||
|
||||
if (node.stream) {
|
||||
if ((typeof data) === "string" && node.newline != "") {
|
||||
buffer = buffer+data;
|
||||
@@ -128,21 +128,21 @@ function TcpIn(n) {
|
||||
node.send(msg);
|
||||
buffer = null;
|
||||
}
|
||||
});
|
||||
});
|
||||
socket.on('error',function(err) {
|
||||
node.log(err);
|
||||
});
|
||||
});
|
||||
server.listen(node.port);
|
||||
node.log('listening on port '+node.port);
|
||||
|
||||
|
||||
this._close = function() {
|
||||
this.closing = true;
|
||||
server.close();
|
||||
node.log('stopped listening on port '+node.port);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
RED.nodes.registerType("tcp in",TcpIn);
|
||||
@@ -150,4 +150,3 @@ RED.nodes.registerType("tcp in",TcpIn);
|
||||
TcpIn.prototype.close = function() {
|
||||
this._close();
|
||||
}
|
||||
|
||||
|
176
nodes/io/32-udp.html
Normal file
176
nodes/io/32-udp.html
Normal file
@@ -0,0 +1,176 @@
|
||||
<!--
|
||||
Copyright 2013 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.
|
||||
-->
|
||||
|
||||
<!-- The Input Node -->
|
||||
<script type="text/x-red" data-template-name="udp in">
|
||||
<div class="form-row">
|
||||
<label for="node-input-port"><i class="icon-inbox"></i> Listen</label>
|
||||
on port <input type="text" id="node-input-port" placeholder="Port" style="width: 45px">
|
||||
for <select id="node-input-multicast" style='width:40%'>
|
||||
<option value="false">udp messages</option>
|
||||
<option value="true">multicast messages</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-row node-input-group">
|
||||
<label for="node-input-group"><i class="icon-list"></i> Group</label>
|
||||
<input type="text" id="node-input-group" placeholder="225.0.18.83">
|
||||
</div>
|
||||
<div class="form-row node-input-iface">
|
||||
<label for="node-input-iface"><i class="icon-random"></i> Interface</label>
|
||||
<input type="text" id="node-input-iface" placeholder="eth0">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-datatype"><i class="icon-file"></i> Output</label>
|
||||
<select id="node-input-datatype" style="width: 70%;">
|
||||
<option value="buffer">a Buffer</option>
|
||||
<option value="utf8">a String</option>
|
||||
<option value="base64">a Base64 encoded string</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||
<input type="text" id="node-input-name" placeholder="Name">
|
||||
</div>
|
||||
<div class="form-tips">Tip: Make sure your firewall will allow the data in.</div>
|
||||
<script>
|
||||
$("#node-input-multicast").change(function() {
|
||||
var id = $("#node-input-multicast option:selected").val();
|
||||
if (id == "false") {
|
||||
$(".node-input-group").hide();
|
||||
$(".node-input-iface").hide();
|
||||
}
|
||||
else {
|
||||
$(".node-input-group").show();
|
||||
$(".node-input-iface").show();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="udp in">
|
||||
<p>A udp input node, that produces a <b>msg.payload</b> containing a <i>BUFFER</i>, string, or base64 encoded string. Supports multicast.</p>
|
||||
<p>It also provides <b>msg.fromip</b> in the form ipaddress:port .</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('udp in',{
|
||||
category: 'input',
|
||||
color:"Silver",
|
||||
defaults: {
|
||||
name: {value:""},
|
||||
host: {value:""},
|
||||
iface: {value:""},
|
||||
port: {value:"",required:true,validate:RED.validators.number()},
|
||||
datatype: {value:"buffer",required:true},
|
||||
multicast: {value:"false"},
|
||||
group: {value:"",validate:function(v) { return (this.multicast !== "true")||v.length > 0;} }
|
||||
},
|
||||
inputs:0,
|
||||
outputs:1,
|
||||
icon: "bridge-dash.png",
|
||||
label: function() {
|
||||
if (this.multicast=="false") {
|
||||
return this.name||"udp "+this.port;
|
||||
}
|
||||
else return this.name||"udp "+(this.group+":"+this.port);
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name?"node_label_italic":"";
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
<!-- The Output Node -->
|
||||
<script type="text/x-red" data-template-name="udp out">
|
||||
<div class="form-row">
|
||||
<label for="node-input-port"><i class="icon-envelope"></i> Send a</label>
|
||||
<select id="node-input-multicast" style='width:40%'>
|
||||
<option value="false">udp message</option>
|
||||
<option value="broad">broadcast message</option>
|
||||
<option value="multi">multicast message</option>
|
||||
</select>
|
||||
to port <input type="text" id="node-input-port" placeholder="Port" style="width: 45px">
|
||||
</div>
|
||||
<div class="form-row node-input-addr">
|
||||
<label for="node-input-addr" id="node-input-addr-label"><i class="icon-list"></i> Address</label>
|
||||
<input type="text" id="node-input-addr" placeholder="destination ip" style="width: 70%;">
|
||||
</div>
|
||||
<div class="form-row node-input-iface">
|
||||
<label for="node-input-iface"><i class="icon-random"></i> Interface</label>
|
||||
<input type="text" id="node-input-iface" placeholder="eth0">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label> </label>
|
||||
<input type="checkbox" id="node-input-base64" placeholder="base64" style="display: inline-block; width: auto; vertical-align: top;">
|
||||
<label for="node-input-base64" style="width: 70%;">Decode Base64 encoded payload ?</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>
|
||||
$("#node-input-multicast").change(function() {
|
||||
var id = $("#node-input-multicast option:selected").val();
|
||||
console.log(id,$("#node-input-addr")[0].placeholder);
|
||||
if (id !== "multi") {
|
||||
$(".node-input-iface").hide();
|
||||
$("#node-input-addr-label").html('<i class="icon-list"></i> Address');
|
||||
$("#node-input-addr")[0].placeholder = 'destination ip';
|
||||
}
|
||||
else {
|
||||
$(".node-input-iface").show();
|
||||
$("#node-input-addr-label").html('<i class="icon-list"></i> Group');
|
||||
$("#node-input-addr")[0].placeholder = '225.0.18.83';
|
||||
}
|
||||
if (id === "broad") {
|
||||
$("#node-input-addr")[0].placeholder = '255.255.255.255';
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="udp out">
|
||||
<p>This node sends <b>msg.payload</b> to the designated udp host and port. Supports multicast.</p>
|
||||
<p>If you select broadcast either set the address to the local broadcast ip address, or maybe try 255.255.255.255, which is the global broadcast address.</p>
|
||||
<p>On some systems you may need to be root to use broadcast.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('udp out',{
|
||||
category: 'output',
|
||||
color:"Silver",
|
||||
defaults: {
|
||||
name: {value:""},
|
||||
addr: {value:"",required:true},
|
||||
//group: {value:""},
|
||||
iface: {value:""},
|
||||
port: {value:"",required:true,validate:RED.validators.number()},
|
||||
base64: {value:false,required:true},
|
||||
multicast: {value:"false"}
|
||||
},
|
||||
inputs:1,
|
||||
outputs:0,
|
||||
icon: "bridge-dash.png",
|
||||
align: "right",
|
||||
label: function() {
|
||||
return this.name||"udp "+(this.addr+":"+this.port);
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name?"node_label_italic":"";
|
||||
}
|
||||
});
|
||||
</script>
|
115
nodes/io/32-udp.js
Normal file
115
nodes/io/32-udp.js
Normal file
@@ -0,0 +1,115 @@
|
||||
/**
|
||||
* Copyright 2013 IBM Corp.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
var RED = require("../../red/red");
|
||||
var dgram = require('dgram');
|
||||
|
||||
// The Input Node
|
||||
function UDPin(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.group = n.group;
|
||||
this.port = n.port;
|
||||
this.host = n.host || null;
|
||||
this.datatype = n.datatype;
|
||||
this.iface = n.iface || null;
|
||||
this.multicast = n.multicast;
|
||||
var node = this;
|
||||
|
||||
var server = dgram.createSocket('udp4');
|
||||
|
||||
server.on("error", function (err) {
|
||||
console.log("udp listener error:\n" + err.stack);
|
||||
server.close();
|
||||
});
|
||||
|
||||
server.on('message', function (message, remote) {
|
||||
var msg;
|
||||
if (node.datatype =="base64") { msg = { payload:message.toString('base64'), fromip:remote.address+':'+remote.port }; }
|
||||
else if (node.datatype =="utf8") { msg = { payload:message.toString('utf8'), fromip:remote.address+':'+remote.port }; }
|
||||
else { msg = { payload:message, fromip:remote.address+':'+remote.port }; }
|
||||
node.send(msg);
|
||||
});
|
||||
|
||||
server.on('listening', function () {
|
||||
var address = server.address();
|
||||
node.log('udp listener at ' + address.address + ":" + address.port);
|
||||
if (node.multicast == "true") {
|
||||
server.setBroadcast(true)
|
||||
server.setMulticastTTL(128);
|
||||
server.addMembership(node.group,node.iface);
|
||||
node.log("udp multicast group "+node.group);
|
||||
}
|
||||
});
|
||||
|
||||
node.on("close", function() {
|
||||
try {
|
||||
server.close();
|
||||
node.log('udp listener stopped');
|
||||
}
|
||||
catch (err) { console.log(err); }
|
||||
});
|
||||
|
||||
server.bind(node.port,node.host);
|
||||
}
|
||||
RED.nodes.registerType("udp in",UDPin);
|
||||
|
||||
|
||||
// The Output Node
|
||||
function UDPout(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
//this.group = n.group;
|
||||
this.port = n.port;
|
||||
this.base64 = n.base64;
|
||||
this.addr = n.addr;
|
||||
this.iface = n.iface || null;
|
||||
this.multicast = n.multicast;
|
||||
var node = this;
|
||||
|
||||
var sock = dgram.createSocket('udp4'); // only use ipv4 for now
|
||||
sock.bind(node.port); // have to bind before you can enable broadcast...
|
||||
if (this.multicast != "false") {
|
||||
sock.setBroadcast(true); // turn on broadcast
|
||||
if (this.multicast == "multi") {
|
||||
sock.setMulticastTTL(128);
|
||||
sock.addMembership(node.addr,node.iface); // Add to the multicast group
|
||||
node.log('udp multicast ready : '+node.addr+":"+node.port);
|
||||
}
|
||||
else node.log('udp broadcast ready : '+node.addr+":"+node.port);
|
||||
}
|
||||
else node.log('udp ready : '+node.addr+":"+node.port);
|
||||
|
||||
node.on("input", function(msg) {
|
||||
if (msg.payload != null) {
|
||||
//console.log("UDP:",msg.payload);
|
||||
var message;
|
||||
if (node.base64) { message = new Buffer(b64string, 'base64'); }
|
||||
else { message = new Buffer(""+msg.payload); }
|
||||
console.log("UDP send :",node.addr,node.port);
|
||||
sock.send(message, 0, message.length, node.port, node.addr, function(err, bytes) {
|
||||
if (err) node.error("udp : "+err);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
node.on("close", function() {
|
||||
try {
|
||||
sock.close();
|
||||
node.log('udp output stopped');
|
||||
}
|
||||
catch (err) { console.log(err); }
|
||||
});
|
||||
}
|
||||
RED.nodes.registerType("udp out",UDPout);
|
@@ -29,8 +29,8 @@
|
||||
pathname += "/";
|
||||
}
|
||||
var callback = encodeURIComponent(location.protocol+"//"+location.hostname+":"+location.port+pathname+"twitter/"+twitterConfigNodeId+"/auth/callback");
|
||||
|
||||
$("#node-config-twitter-row").html('Click <a id="node-config-twitter-start" href="/twitter/'+twitterConfigNodeId+'/auth?callback='+callback+'" target="_blank">here</a> to authenticate with Twitter.');
|
||||
|
||||
$("#node-config-twitter-row").html('Click <a id="node-config-twitter-start" href="/twitter/'+twitterConfigNodeId+'/auth?callback='+callback+'" target="_blank"><b>here</b></a> to authenticate with Twitter.');
|
||||
$("#node-config-twitter-start").click(function() {
|
||||
twitterConfigNodeIntervalId = window.setTimeout(pollTwitterCredentials,2000);
|
||||
});
|
||||
@@ -102,34 +102,33 @@
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-template-name="twitter in">
|
||||
<div class="form-row">
|
||||
<label for="node-input-twitter"><i class="icon-user"></i> Twitter</label>
|
||||
<div class="form-row">
|
||||
<label for="node-input-twitter"><i class="icon-user"></i> Log in as</label>
|
||||
<input type="text" id="node-input-twitter">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-user"><i class="icon-search"></i> Search</label>
|
||||
<select type="text" id="node-input-user" style="display: inline-block; vertical-align: middle; width:60%;">
|
||||
<option value="false">all public tweets</option>
|
||||
<option value="true">the tweets of who you follow</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-tags"><i class="icon-tag"></i> Tags</label>
|
||||
<input type="text" id="node-input-tags" placeholder="comma-separated tags">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label> </label>
|
||||
<input type="checkbox" id="node-input-user" placeholder="Name" style="display: inline-block; width: auto; vertical-align: top;">
|
||||
<label for="node-input-user" style="width: 70%;">Tick to use user stream<br/>(rather than status/filter)</label>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-topic"><i class="icon-tasks"></i> Topic</label>
|
||||
<input type="text" id="node-input-topic" placeholder="Topic">
|
||||
<label for="node-input-tags"><i class="icon-tags"></i> for</label>
|
||||
<input type="text" id="node-input-tags" placeholder="comma-separated words, @ids, #tags">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||
<input type="text" id="node-input-name" placeholder="Name">
|
||||
</div>
|
||||
<div class="form-tips">Tip: the Senders name gets appended to the topic heirarchy
|
||||
</div>
|
||||
<div class="form-tips">Tip: Use commas without spaces between multiple search terms. Comma = OR, Space = AND.
|
||||
<br/>The Twitter API WILL NOT deliver 100% of all tweets.
|
||||
<br/>Tweets of who you follow will include their retweets and favourites.</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="twitter in">
|
||||
<p>Twitter input node. Watches the public stream for tweets containing the configured search term.</p>
|
||||
<p>Sets the <b>msg.topic</b> to the configured topic and then appends the senders screen name.</p>
|
||||
<p>Twitter input node. Watches either the public or the user's stream for tweets containing the configured search term.</p>
|
||||
<p>Sets the <b>msg.topic</b> to <i>tweets/</i> and then appends the senders screen name.</p>
|
||||
<p>Sets <b>msg.location</b> to the tweeters location if known.</p>
|
||||
</script>
|
||||
|
||||
@@ -140,7 +139,7 @@
|
||||
defaults: {
|
||||
twitter: {type:"twitter-credentials",required:true},
|
||||
tags: {value:"",required:true},
|
||||
user: {value:false},
|
||||
user: {value:"false",required:true},
|
||||
name: {value:""},
|
||||
topic: {value:"tweets"}
|
||||
},
|
||||
|
@@ -24,14 +24,13 @@ function TwitterNode(n) {
|
||||
}
|
||||
RED.nodes.registerType("twitter-credentials",TwitterNode);
|
||||
|
||||
|
||||
function TwitterInNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.active = true;
|
||||
this.user = n.user;
|
||||
this.tags = n.tags.replace(/ /g,'');
|
||||
this.twitter = n.twitter;
|
||||
this.topic = n.topic;
|
||||
this.topic = n.topic||"tweets";
|
||||
this.twitterConfig = RED.nodes.getNode(this.twitter);
|
||||
var credentials = RED.nodes.getCredentials(this.twitter);
|
||||
|
||||
@@ -47,11 +46,12 @@ function TwitterInNode(n) {
|
||||
if (this.tags !== "") {
|
||||
try {
|
||||
var thing = 'statuses/filter';
|
||||
if (this.user) { thing = 'user'; }
|
||||
if (this.user == "true") { thing = 'user'; }
|
||||
function setupStream() {
|
||||
if (node.active) {
|
||||
twit.stream(thing, { track: [node.tags] }, function(stream) {
|
||||
//twit.stream('user', { track: [node.tags] }, function(stream) {
|
||||
//twit.stream('site', { track: [node.tags] }, function(stream) {
|
||||
//twit.stream('statuses/filter', { track: [node.tags] }, function(stream) {
|
||||
node.stream = stream;
|
||||
stream.on('data', function(tweet) {
|
||||
@@ -101,8 +101,6 @@ TwitterInNode.prototype.close = function() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function TwitterOutNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.topic = n.topic;
|
||||
|
@@ -16,7 +16,7 @@
|
||||
|
||||
<script type="text/x-red" data-template-name="notify">
|
||||
<div class="form-row">
|
||||
<label for="node-input-title"><i class="icon-tag"></i> Title</label>
|
||||
<label for="node-input-title"><i class="icon-flag"></i> Title</label>
|
||||
<input type="text" id="node-input-title" placeholder="Node-RED">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
|
@@ -37,7 +37,7 @@ if (pushkey) {
|
||||
function ProwlNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.title = n.title;
|
||||
this.priority = n.priority * 1;
|
||||
this.priority = parseInt(n.priority);
|
||||
if (this.priority > 2) this.priority = 2;
|
||||
if (this.priority < -2) this.priority = -2;
|
||||
var node = this;
|
||||
|
@@ -65,12 +65,12 @@
|
||||
<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">Sending complete object will stringify the whole msg object before sending.</div>
|
||||
<div class="form-tips">Sending the complete object will stringify the whole msg object before sending.</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="irc out">
|
||||
<p>Connects to a channel on an IRC server</p>
|
||||
<p>If you send something with NO msg.topic it will go to the channel - otherwise it will go to the id in the <b>msg.topic</b> field.</p>
|
||||
<p>Sends messages to a channel on an IRC server</p>
|
||||
<p>If you send something with NO <b>msg.topic</b> it will go to the configured channel - otherwise it will go to the id in the <b>msg.topic</b> field.</p>
|
||||
<p>You can either just send the <b>msg.payload</b>, or you can send the complete <b>msg</b> object.</p>
|
||||
</script>
|
||||
|
||||
@@ -103,7 +103,7 @@
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-config-input-channel"><i class="icon-tasks"></i> Channel</label>
|
||||
<input type="text" id="node-config-input-channel" placeholder="#testing1234">
|
||||
<input type="text" id="node-config-input-channel" placeholder="#node-red">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-config-input-nickname"><i class="icon-tasks"></i> Nickname</label>
|
||||
|
@@ -16,6 +16,7 @@
|
||||
|
||||
var RED = require("../../red/red");
|
||||
var irc = require("irc");
|
||||
var util = require("util");
|
||||
|
||||
// The Server Definition - this opens (and closes) the connection
|
||||
function IRCServerNode(n) {
|
||||
@@ -23,40 +24,38 @@ function IRCServerNode(n) {
|
||||
this.server = n.server;
|
||||
this.channel = n.channel;
|
||||
this.nickname = n.nickname;
|
||||
this.ircclient = new irc.Client(this.server, this.nickname, {
|
||||
channels: [this.channel]
|
||||
this.ircclient = null;
|
||||
this.on("close", function() {
|
||||
if (this.ircclient != null) {
|
||||
this.ircclient.disconnect();
|
||||
}
|
||||
});
|
||||
this._close = function() {
|
||||
this.ircclient.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
RED.nodes.registerType("irc-server",IRCServerNode);
|
||||
|
||||
IRCServerNode.prototype.close = function() {
|
||||
this._close();
|
||||
}
|
||||
|
||||
|
||||
// The Input Node
|
||||
function IrcInNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.ircserver = n.ircserver;
|
||||
this.serverConfig = RED.nodes.getNode(this.ircserver);
|
||||
if (this.serverConfig.ircclient == null) {
|
||||
this.serverConfig.ircclient = new irc.Client(this.serverConfig.server, this.serverConfig.nickname, {
|
||||
channels: [this.serverConfig.channel]
|
||||
});
|
||||
this.serverConfig.ircclient.addListener('error', function(message) {
|
||||
util.log('[irc] '+ JSON.stringify(message));
|
||||
});
|
||||
}
|
||||
this.ircclient = this.serverConfig.ircclient;
|
||||
var node = this;
|
||||
|
||||
|
||||
this.ircclient.addListener('message', function (from, to, message) {
|
||||
console.log(from + ' => ' + to + ': ' + message);
|
||||
var msg = { "topic":from, "to":to, "payload":message };
|
||||
node.send(msg);
|
||||
});
|
||||
|
||||
this.ircclient.addListener('error', function(message) {
|
||||
node.error(JSON.stringify(message));
|
||||
});
|
||||
|
||||
}
|
||||
RED.nodes.registerType("irc in",IrcInNode);
|
||||
|
||||
@@ -66,12 +65,20 @@ function IrcOutNode(n) {
|
||||
this.sendAll = n.sendObject;
|
||||
this.ircserver = n.ircserver;
|
||||
this.serverConfig = RED.nodes.getNode(this.ircserver);
|
||||
this.ircclient = this.serverConfig.ircclient;
|
||||
this.channel = this.serverConfig.channel;
|
||||
if (this.serverConfig.ircclient == null) {
|
||||
this.serverConfig.ircclient = new irc.Client(this.serverConfig.server, this.serverConfig.nickname, {
|
||||
channels: [this.serverConfig.channel]
|
||||
});
|
||||
this.serverConfig.ircclient.addListener('error', function(message) {
|
||||
util.log('[irc] '+ JSON.stringify(message));
|
||||
});
|
||||
}
|
||||
this.ircclient = this.serverConfig.ircclient;
|
||||
var node = this;
|
||||
|
||||
this.on("input", function(msg) {
|
||||
console.log(msg);
|
||||
//console.log(msg,node.channel);
|
||||
if (node.sendAll) {
|
||||
node.ircclient.say(node.channel, JSON.stringify(msg));
|
||||
}
|
||||
|
@@ -14,8 +14,17 @@
|
||||
* 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);
|
||||
};
|
||||
})();
|
||||
|
||||
var RED = require("../../red/red");
|
||||
var xmpp = require('simple-xmpp');
|
||||
console.warn = orig;
|
||||
|
||||
try {
|
||||
var xmppkey = require("../../settings").xmpp || require("../../../xmppkeys.js");
|
||||
@@ -97,17 +106,13 @@ function XmppNode(n) {
|
||||
}
|
||||
});
|
||||
|
||||
this._close = function() {
|
||||
this.on("close", function() {
|
||||
xmpp.setPresence('offline');
|
||||
//xmpp.conn.end();
|
||||
// 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)).
|
||||
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.");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
RED.nodes.registerType("xmpp",XmppNode);
|
||||
|
||||
XmppNode.prototype.close = function() {
|
||||
this._close();
|
||||
}
|
||||
|
Reference in New Issue
Block a user