mirror of
https://github.com/node-red/node-red.git
synced 2025-03-01 10:36:34 +00:00
Got to start somewhere
This commit is contained in:
121
nodes/io/10-mqtt.html
Normal file
121
nodes/io/10-mqtt.html
Normal file
@@ -0,0 +1,121 @@
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
<script type="text/x-red" data-template-name="mqtt in">
|
||||
<div class="form-row">
|
||||
<label for="node-input-broker"><i class="icon-tag"></i> Broker</label>
|
||||
<input type="text" id="node-input-broker">
|
||||
</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">
|
||||
</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="mqtt in">
|
||||
<p>MQTT input node. Connects to the specified broker and subscribes to the specified topic. The topic may contain MQTT wildcards.</p>
|
||||
<p>Outputs an object called <b>msg</b> containing <b>msg.topic, msg.payload, msg.qos</b> and <b>msg.retain</b>. <b>msg.payload</b> is a String.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('mqtt in',{
|
||||
category: 'input',
|
||||
defaults: {
|
||||
name: {value:""},
|
||||
topic: {value:"",required:true},
|
||||
broker: {type:"mqtt-broker", required:true}
|
||||
},
|
||||
color:"#c6dbef",
|
||||
inputs:0,
|
||||
outputs:1,
|
||||
icon: "bridge.png",
|
||||
label: function() {
|
||||
return this.name||this.topic;
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name?"node_label_italic":"";
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-template-name="mqtt out">
|
||||
<div class="form-row">
|
||||
<label for="node-input-broker"><i class="icon-tag"></i> Broker</label>
|
||||
<input type="text" id="node-input-broker">
|
||||
</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">
|
||||
</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="mqtt out">
|
||||
<p>Connects to a MQTT broker and publishes <b>msg.payload</b> either to the <b>msg.topic</b> OR to the topic specified in the edit window. The value in the edit window has precedence.</p>
|
||||
<p><b>msg.qos</b> and <b>msg.retain</b> may also optionally have been set. If not set they are set to 0 and false respectively.</p>
|
||||
<p>If <b>msg.payload</b> contains a buffer or an object it will be stringified before being sent.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('mqtt out',{
|
||||
category: 'output',
|
||||
defaults: {
|
||||
name: {value:""},
|
||||
topic: {value:""},
|
||||
broker: {type:"mqtt-broker", required:true}
|
||||
},
|
||||
color:"#c6dbef",
|
||||
inputs:1,
|
||||
outputs:0,
|
||||
icon: "bridge.png",
|
||||
align: "right",
|
||||
label: function() {
|
||||
return this.name||this.topic;
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name?"node_label_italic":"";
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-template-name="mqtt-broker">
|
||||
<div class="form-row node-input-broker">
|
||||
<label for="node-config-input-broker"><i class="icon-bookmark"></i> Broker</label>
|
||||
<input class="input-append-left" type="text" id="node-config-input-broker" placeholder="Broker" style="width: 40%;" >
|
||||
<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>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('mqtt-broker',{
|
||||
category: 'config',
|
||||
defaults: {
|
||||
broker: {value:"localhost",required:true},
|
||||
port: {value:1883,required:true,validate:RED.validators.number()}
|
||||
},
|
||||
label: function() {
|
||||
return this.broker+":"+this.port;
|
||||
}
|
||||
});
|
||||
</script>
|
90
nodes/io/10-mqtt.js
Normal file
90
nodes/io/10-mqtt.js
Normal file
@@ -0,0 +1,90 @@
|
||||
/**
|
||||
* 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 connectionPool = require("./lib/mqttConnectionPool");
|
||||
var util = require("util");
|
||||
|
||||
function MQTTBrokerNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.broker = n.broker;
|
||||
this.port = n.port;
|
||||
}
|
||||
RED.nodes.registerType("mqtt-broker",MQTTBrokerNode);
|
||||
|
||||
|
||||
function MQTTInNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.topic = n.topic;
|
||||
this.broker = n.broker;
|
||||
this.brokerConfig = RED.nodes.getNode(this.broker);
|
||||
if (this.brokerConfig) {
|
||||
this.client = connectionPool.get(this.brokerConfig.broker,this.brokerConfig.port);
|
||||
var node = this;
|
||||
this.client.subscribe(this.topic,2,function(topic,payload,qos,retain) {
|
||||
var msg = {topic:topic,payload:payload,qos:qos,retain:retain};
|
||||
if ((node.brokerConfig.broker == "localhost")||(node.brokerConfig.broker == "127.0.0.1")) {
|
||||
msg._topic = topic;
|
||||
}
|
||||
node.send(msg);
|
||||
});
|
||||
this.client.connect();
|
||||
} else {
|
||||
this.error("missing broker configuration");
|
||||
}
|
||||
}
|
||||
|
||||
RED.nodes.registerType("mqtt in",MQTTInNode);
|
||||
|
||||
MQTTInNode.prototype.close = function() {
|
||||
if (this.client) {
|
||||
this.client.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function MQTTOutNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
|
||||
this.topic = n.topic;
|
||||
this.broker = n.broker;
|
||||
|
||||
this.brokerConfig = RED.nodes.getNode(this.broker);
|
||||
|
||||
if (this.brokerConfig) {
|
||||
this.client = connectionPool.get(this.brokerConfig.broker,this.brokerConfig.port);
|
||||
this.on("input",function(msg) {
|
||||
if (msg != null) {
|
||||
if (this.topic) {
|
||||
msg.topic = this.topic;
|
||||
}
|
||||
this.client.publish(msg);
|
||||
}
|
||||
});
|
||||
this.client.connect();
|
||||
} else {
|
||||
this.error("missing broker configuration");
|
||||
}
|
||||
}
|
||||
|
||||
RED.nodes.registerType("mqtt out",MQTTOutNode);
|
||||
|
||||
MQTTOutNode.prototype.close = function() {
|
||||
if (this.client) {
|
||||
this.client.disconnect();
|
||||
}
|
||||
}
|
||||
|
85
nodes/io/21-httpin.html
Normal file
85
nodes/io/21-httpin.html
Normal file
@@ -0,0 +1,85 @@
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
<script type="text/x-red" data-template-name="http in">
|
||||
<div class="form-row">
|
||||
<label for="node-input-method"><i class="icon-tasks"></i> Method</label>
|
||||
<select type="text" id="node-input-method" style="width: 150px;">
|
||||
<option value="get">GET</option>
|
||||
<option value="post">POST</option>
|
||||
<option value="put">PUT</option>
|
||||
<option value="delete">DELETE</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-topic"><i class="icon-globe"></i> url</label>
|
||||
<input type="text" id="node-input-url" placeholder="/url">
|
||||
</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="http in">
|
||||
<p>Provides an input node for http requests, allowing the creation of simple web services.</p>
|
||||
<p>The resulting message has the following properties:
|
||||
<ul>
|
||||
<li>msg.req : <a href="http://expressjs.com/api.html#req">http request</a></li>
|
||||
<li>msg.res : <a href="http://expressjs.com/api.html#res">http response</a></li>
|
||||
</ul>
|
||||
</p>
|
||||
<p>For POST/PUT requests, the body is available under <code>msg.req.body</code>. This
|
||||
uses the <a href="http://expressjs.com/api.html#bodyParser">Express bodyParser middleware</a> to parse the content to a JSON object.
|
||||
</p>
|
||||
<p>
|
||||
By default, this expects the body of the request to be url encoded:
|
||||
<pre>foo=bar&this=that</pre>
|
||||
</p>
|
||||
<p>
|
||||
To send JSON encoded data, the content-type header of the request must be set to
|
||||
<code>application/json</code>.
|
||||
</p>
|
||||
<p>
|
||||
<b>Note: </b>This node does not send any response to the http request. This must be done within
|
||||
a subsequent Function node. The <a href="http://expressjs.com/api.html#res">Express response documentation</a>
|
||||
describes how this should be done.
|
||||
<pre>msg.res.send(200, 'Thanks for the request ');<br/>return msg;</pre>
|
||||
</p>
|
||||
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('http in',{
|
||||
category: 'input',
|
||||
color:"rgb(231, 231, 174)",
|
||||
defaults: {
|
||||
name: {value:""},
|
||||
url: {value:"",required:true},
|
||||
method: {value:"get",required:true}
|
||||
},
|
||||
inputs:0,
|
||||
outputs:1,
|
||||
icon: "white-globe.png",
|
||||
label: function() {
|
||||
return this.name||"["+this.method+"] "+this.url;
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name?"node_label_italic":"";
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
51
nodes/io/21-httpin.js
Normal file
51
nodes/io/21-httpin.js
Normal file
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* 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 util = require("util");
|
||||
|
||||
function HTTPIn(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.url = n.url;
|
||||
this.method = n.method;
|
||||
|
||||
var node = this;
|
||||
this.callback = function(req,res) {
|
||||
node.send({req:req,res:res});
|
||||
}
|
||||
if (this.method == "get") {
|
||||
RED.app.get(this.url,this.callback);
|
||||
} else if (this.method == "post") {
|
||||
RED.app.post(this.url,this.callback);
|
||||
} else if (this.method == "put") {
|
||||
RED.app.put(this.url,this.callback);
|
||||
} else if (this.method == "delete") {
|
||||
RED.app.delete(this.url,this.callback);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
HTTPIn.prototype.close = function() {
|
||||
var routes = redUI.app.routes[this.method];
|
||||
for (var i in routes) {
|
||||
if (routes[i].path == this.url) {
|
||||
routes.splice(i,1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RED.nodes.registerType("http in",HTTPIn);
|
53
nodes/io/23-watch.html
Normal file
53
nodes/io/23-watch.html
Normal file
@@ -0,0 +1,53 @@
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
<script type="text/x-red" data-template-name="watch">
|
||||
<div class="form-row node-input-filename">
|
||||
<label for="node-input-files"><i class="icon-file"></i> File(s)</label>
|
||||
<input type="text" id="node-input-files" placeholder="File(s) or Directory">
|
||||
</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="watch">
|
||||
<p>Watches a file or directory for any changes.</p>
|
||||
<p>You can enter a list of comma separated files, or directories if you like. You will need to put " around any that have spaces in.</p>
|
||||
<p>The filename of the file that actually changed is put into <b>msg.payload</b>, while a stringified version of the watched criteria is returned in <b>msg.topic</b>.</p>
|
||||
<p>Of course in Linux, <i>everything</i> could be a file and thus watched...</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('watch',{
|
||||
category: 'advanced-input',
|
||||
defaults: {
|
||||
name: {value:""},
|
||||
files: {value:"",required:true}
|
||||
},
|
||||
color:"BurlyWood",
|
||||
inputs:0,
|
||||
outputs:1,
|
||||
icon: "watch.png",
|
||||
label: function() {
|
||||
return this.name||this.files;
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name?"node_label_italic":"";
|
||||
}
|
||||
});
|
||||
</script>
|
45
nodes/io/23-watch.js
Normal file
45
nodes/io/23-watch.js
Normal file
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* 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 notify = require("fs.notify");
|
||||
|
||||
function WatchNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
|
||||
this.files = n.files.split(",");
|
||||
for (var f in this.files) {
|
||||
this.files[f] = this.files[f].trim();
|
||||
}
|
||||
var node = this;
|
||||
var notifications = new notify(this.files);
|
||||
notifications.on('change', function (file) {
|
||||
node.log('file changed '+file);
|
||||
var msg = { payload: file, topic: JSON.stringify(node.files) };
|
||||
node.send(msg);
|
||||
});
|
||||
|
||||
this._close = function() {
|
||||
notifications.close();
|
||||
}
|
||||
}
|
||||
|
||||
RED.nodes.registerType("watch",WatchNode);
|
||||
|
||||
WatchNode.prototype.close = function() {
|
||||
this._close();
|
||||
}
|
||||
|
146
nodes/io/25-serial.html
Normal file
146
nodes/io/25-serial.html
Normal file
@@ -0,0 +1,146 @@
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
<script type="text/x-red" data-template-name="serial in">
|
||||
<div class="form-row node-input-serial">
|
||||
<label for="node-input-serial"><i class="icon-bullhorn"></i> Serial Port</label>
|
||||
<input type="text" id="node-input-serial">
|
||||
</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="serial in">
|
||||
<p>Reads data from a local serial port.</p>
|
||||
<p>Keeps reading from the serial port until it sees \n (default) or the character(s) requested. Only sets <b>msg.payload</b>.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('serial in',{
|
||||
category: 'input',
|
||||
defaults: {
|
||||
name: {name:""},
|
||||
serial: {type:"serial-port",required:true}
|
||||
},
|
||||
color:"BurlyWood",
|
||||
inputs:0,
|
||||
outputs:1,
|
||||
icon: "serial.png",
|
||||
label: function() {
|
||||
return this.name||(this.serial)?RED.nodes.node(this.serial).label():"serial";
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name?"node_label_italic":"";
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
<script type="text/x-red" data-template-name="serial out">
|
||||
<div class="form-row node-input-serial">
|
||||
<label for="node-input-serial"><i class="icon-bullhorn"></i> Serial Port</label>
|
||||
<input type="text" id="node-input-serial">
|
||||
</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="serial out">
|
||||
<p>Provides a connection to an outbound serial port.</p>
|
||||
<p>Only the <b>msg.payload</b> is sent.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('serial out',{
|
||||
category: 'output',
|
||||
defaults: {
|
||||
name: {name:""},
|
||||
serial: {type:"serial-port",required:true}
|
||||
},
|
||||
color:"BurlyWood",
|
||||
inputs:1,
|
||||
outputs:0,
|
||||
icon: "serial.png",
|
||||
align: "right",
|
||||
label: function() {
|
||||
return this.name||((this.serial)?RED.nodes.node(this.serial).label():"serial");
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name?"node_label_italic":"";
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<script type="text/x-red" data-template-name="serial-port">
|
||||
<div class="form-row">
|
||||
<label for="node-config-input-serialport"><i class="icon-bullhorn"></i> Serial Port</label>
|
||||
<input type="text" id="node-config-input-serialport" placeholder="/dev/ttyUSB0" style="width:50%;">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-config-input-serialbaud"><i class="icon-wrench"></i> Baud Rate</label>
|
||||
<select type="text" id="node-config-input-serialbaud" style="width: 150px;">
|
||||
<option value="115200">115200</option>
|
||||
<option value="57600">57600</option>
|
||||
<option value="38400">38400</option>
|
||||
<option value="19200">19200</option>
|
||||
<option value="9600">9600</option>
|
||||
<option value="4800">4800</option>
|
||||
<option value="2400">2400</option>
|
||||
<option value="1800">1800</option>
|
||||
<option value="1200">1200</option>
|
||||
<option value="600">600</option>
|
||||
<option value="300">300</option>
|
||||
<option value="200">200</option>
|
||||
<option value="150">150</option>
|
||||
<option value="134">134</option>
|
||||
<option value="110">110</option>
|
||||
<option value="75">75</option>
|
||||
<option value="50">50</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-config-input-newline"><i class="icon-text-width"></i> New line</label>
|
||||
<input type="text" id="node-config-input-newline">
|
||||
</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('serial-port',{
|
||||
category: 'config',
|
||||
defaults: {
|
||||
//name: {value:""},
|
||||
serialport: {value:"",required:true},
|
||||
serialbaud: {value:57600,required:true},
|
||||
newline: {value:"\\n"}
|
||||
},
|
||||
label: function() {
|
||||
//return this.name||this.serialport;
|
||||
return this.serialport+":"+this.serialbaud;
|
||||
}
|
||||
});
|
||||
</script>
|
181
nodes/io/25-serial.js
Normal file
181
nodes/io/25-serial.js
Normal file
@@ -0,0 +1,181 @@
|
||||
/**
|
||||
* 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 events = require("events");
|
||||
var util = require("util");
|
||||
var serialp = require("serialport");
|
||||
var settings = RED.settings;
|
||||
|
||||
// TODO: 'serialPool' should be encapsulated in SerialPortNode
|
||||
|
||||
function SerialPortNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.serialport = n.serialport;
|
||||
this.serialbaud = n.serialbaud * 1;
|
||||
this.newline = n.newline;
|
||||
}
|
||||
RED.nodes.registerType("serial-port",SerialPortNode);
|
||||
|
||||
|
||||
function SerialOutNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.serial = n.serial;
|
||||
this.serialConfig = RED.nodes.getNode(this.serial);
|
||||
|
||||
if (this.serialConfig) {
|
||||
var node = this;
|
||||
try {
|
||||
node.port = serialPool.get(this.serialConfig.serialport,this.serialConfig.serialbaud,this.serialConfig.newline);
|
||||
} catch(err) {
|
||||
this.error(err);
|
||||
return;
|
||||
}
|
||||
|
||||
node.port.on("ready",function() {
|
||||
node.on("input",function(msg) {
|
||||
//console.log("{",msg,"}");
|
||||
node.port.write(msg.payload,function(err,res) {
|
||||
if (err) {
|
||||
node.error(err);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
} else {
|
||||
this.error("missing serial config");
|
||||
}
|
||||
}
|
||||
|
||||
RED.nodes.registerType("serial out",SerialOutNode);
|
||||
|
||||
SerialOutNode.prototype.close = function() {
|
||||
if (this.serialConfig) {
|
||||
serialPool.close(this.serialConfig.serialport);
|
||||
}
|
||||
}
|
||||
|
||||
function SerialInNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.serial = n.serial;
|
||||
this.serialConfig = RED.nodes.getNode(this.serial);
|
||||
|
||||
if (this.serialConfig) {
|
||||
var node = this;
|
||||
try {
|
||||
this.port = serialPool.get(this.serialConfig.serialport,this.serialConfig.serialbaud,this.serialConfig.newline);
|
||||
} catch(err) {
|
||||
this.error(err);
|
||||
return;
|
||||
}
|
||||
|
||||
this.port.on('data', function(msg) {
|
||||
// console.log("{",msg,"}");
|
||||
var m = { "payload": msg };
|
||||
node.send(m);
|
||||
});
|
||||
} else {
|
||||
this.error("missing serial config");
|
||||
}
|
||||
}
|
||||
|
||||
RED.nodes.registerType("serial in",SerialInNode);
|
||||
|
||||
SerialInNode.prototype.close = function() {
|
||||
if (this.serialConfig) {
|
||||
try {
|
||||
serialPool.close(this.serialConfig.serialport);
|
||||
} catch(err) {
|
||||
}
|
||||
this.warn("Deploying with serial-port nodes is known to occasionally cause Node-RED to hang. This is due to an open issue with the underlying module.");
|
||||
}
|
||||
}
|
||||
|
||||
var serialPool = function() {
|
||||
var connections = {};
|
||||
return {
|
||||
get:function(port,baud,newline,callback) {
|
||||
var id = port;
|
||||
if (!connections[id]) {
|
||||
connections[id] = function() {
|
||||
var obj = {
|
||||
_emitter: new events.EventEmitter(),
|
||||
serial: null,
|
||||
_closing: false,
|
||||
tout: null,
|
||||
on: function(a,b) { this._emitter.on(a,b); },
|
||||
close: function(cb) { this.serial.close(cb)},
|
||||
write: function(m,cb) { this.serial.write(m,cb)},
|
||||
}
|
||||
newline = newline.replace("\\n","\n").replace("\\r","\r");
|
||||
var setupSerial = function() {
|
||||
obj.serial = new serialp.SerialPort(port,{
|
||||
baudrate: baud,
|
||||
parser: serialp.parsers.readline(newline)
|
||||
});
|
||||
obj.serial.on('error', function(err) {
|
||||
util.log("[serial] serial port "+port+" error "+err);
|
||||
obj.tout = setTimeout(function() {
|
||||
setupSerial();
|
||||
},settings.serialReconnectTime);
|
||||
});
|
||||
obj.serial.on('close', function() {
|
||||
if (!obj._closing) {
|
||||
util.log("[serial] serial port "+port+" closed unexpectedly");
|
||||
obj.tout = setTimeout(function() {
|
||||
setupSerial();
|
||||
},settings.serialReconnectTime);
|
||||
}
|
||||
});
|
||||
obj.serial.on('open',function() {
|
||||
util.log("[serial] serial port "+port+" opened at "+baud+" baud");
|
||||
obj.serial.flush();
|
||||
obj._emitter.emit('ready');
|
||||
});
|
||||
obj.serial.on('data',function(d) {
|
||||
obj._emitter.emit('data',d);
|
||||
});
|
||||
}
|
||||
setupSerial();
|
||||
return obj;
|
||||
}();
|
||||
}
|
||||
return connections[id];
|
||||
},
|
||||
close: function(port) {
|
||||
if (connections[port]) {
|
||||
if (connections[port].tout != null) clearTimeout(connections[port].tout);
|
||||
connections[port]._closing = true;
|
||||
try {
|
||||
connections[port].close(function() {
|
||||
util.log("[serial] serial port closed");
|
||||
});
|
||||
} catch(err) {
|
||||
};
|
||||
}
|
||||
delete connections[port];
|
||||
}
|
||||
}
|
||||
}();
|
||||
|
||||
RED.app.get("/serialports",function(req,res) {
|
||||
serialp.list(function (err, ports) {
|
||||
res.writeHead(200, {'Content-Type': 'text/plain'});
|
||||
res.write(JSON.stringify(ports));
|
||||
res.end();
|
||||
});
|
||||
});
|
69
nodes/io/30-socketin.html
Normal file
69
nodes/io/30-socketin.html
Normal file
@@ -0,0 +1,69 @@
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
<script type="text/x-red" data-template-name="socket in">
|
||||
<div class="form-row">
|
||||
<label for="node-input-transport"><i class="icon-tasks"></i> Type</label>
|
||||
<select type="text" id="node-input-transport" style="width: 150px;">
|
||||
<option value="http">http listen</option>
|
||||
<option value="tcp">tcp server</option>
|
||||
<!-- <option value="tcpc">tcp client</option> -->
|
||||
<option value="udp">udp socket</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-port"><i class="icon-random"></i> Port</label>
|
||||
<input type="text" id="node-input-port" placeholder="Port">
|
||||
</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">
|
||||
</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: sends the received data as a Buffer object.</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="socket in">
|
||||
<p>Provides a input node for http, tcp or udp sockets. Topic is optional. These are server like sockets.</p>
|
||||
<p>The TCP and UDP sockets produce a <i>BUFFER</i> object msg.payload and NOT a String. If you need a String then use .toString() on msg.payload in your next function block.</p>
|
||||
<p>TCP and UDP sockets also provide <b>msg.fromip</b> of the form ipaddress:port</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('socket in',{
|
||||
category: 'input',
|
||||
color:"Silver",
|
||||
defaults: {
|
||||
name: {value:""},
|
||||
topic: {value:""},
|
||||
port: {value:"",required:true},
|
||||
transport: {value:"tcp",required:true}
|
||||
},
|
||||
inputs:0,
|
||||
outputs:1,
|
||||
icon: "bridge-dash.png",
|
||||
label: function() {
|
||||
return this.name||this.topic||(this.transport+":"+this.port);
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name?"node_label_italic":"";
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
134
nodes/io/30-socketin.js
Normal file
134
nodes/io/30-socketin.js
Normal file
@@ -0,0 +1,134 @@
|
||||
/**
|
||||
* 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");
|
||||
|
||||
function SocketIn(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.port = n.port;
|
||||
this.topic = n.topic;
|
||||
this.trans = (n.transport||n.trans||"").toLowerCase();
|
||||
var node = this;
|
||||
if (this.trans == "http") {
|
||||
var http = require('http');
|
||||
var serv = http.createServer(function (req, res) {
|
||||
//node.log("http "+req.url);
|
||||
var msg = {topic:node.topic,payload:req.url.slice(1)};
|
||||
node.send(msg);
|
||||
res.writeHead(304, {'Content-Type': 'text/plain'});
|
||||
res.end('\n');
|
||||
}).listen(node.port);
|
||||
node.log('http listener at http://127.0.0.1:'+node.port+'/');
|
||||
|
||||
this._close = function() {
|
||||
serv.close();
|
||||
node.log('http listener stopped');
|
||||
}
|
||||
}
|
||||
|
||||
if (this.trans == "tcp") {
|
||||
var net = require('net');
|
||||
var server = net.createServer(function (socket) {
|
||||
var buffer = null;
|
||||
socket.on('data', function (chunk) {
|
||||
if (buffer == null) {
|
||||
buffer = chunk;
|
||||
} else {
|
||||
buffer = Buffer.concat([buffer,chunk]);
|
||||
}
|
||||
});
|
||||
socket.on('end', function() {
|
||||
var msg = {topic:node.topic, payload:buffer, fromip:socket.remoteAddress+':'+socket.remotePort};
|
||||
node.send(msg);
|
||||
});
|
||||
});
|
||||
server.listen(node.port);
|
||||
node.log('tcp listener on port :'+node.port+'/');
|
||||
|
||||
this._close = function() {
|
||||
server.close();
|
||||
node.log('tcp listener stopped');
|
||||
}
|
||||
}
|
||||
|
||||
if (this.trans == "tcpc") {
|
||||
var net = require('net');
|
||||
var client;
|
||||
var to;
|
||||
function setupTcpClient() {
|
||||
node.log('tcpc connecting to port :'+node.port);
|
||||
client = net.connect({port: node.port}, function() {
|
||||
node.log("tcpc connected");
|
||||
});
|
||||
|
||||
client.on('data', function (data) {
|
||||
var msg = {topic:node.topic, payload:data};
|
||||
node.send(msg);
|
||||
});
|
||||
|
||||
client.on('end', function() {
|
||||
node.log("tcpc socket ended");
|
||||
});
|
||||
|
||||
client.on('close', function() {
|
||||
node.log('tcpc socket closed');
|
||||
to = setTimeout(setupTcpClient, 10000); //Try to reconnect
|
||||
});
|
||||
|
||||
client.on('error', function() {
|
||||
node.log('tcpc socket error');
|
||||
to = setTimeout(setupTcpClient, 10000); //Try to reconnect
|
||||
});
|
||||
}
|
||||
setupTcpClient();
|
||||
|
||||
this._close = function() {
|
||||
client.end();
|
||||
//client.destroy();
|
||||
clearTimeout(to);
|
||||
node.log('tcpc stopped client');
|
||||
}
|
||||
setupTcpClient();
|
||||
}
|
||||
|
||||
if (this.trans == "udp") {
|
||||
var dgram = require('dgram');
|
||||
var server = dgram.createSocket('udp4');
|
||||
server.on('listening', function () {
|
||||
var address = server.address();
|
||||
node.log('udp listener at ' + address.address + ":" + address.port);
|
||||
});
|
||||
server.on('message', function (message, remote) {
|
||||
var msg = {topic:node.topic,payload:message,fromip:remote.address+':'+remote.port};
|
||||
node.send(msg);
|
||||
});
|
||||
server.bind(node.port);
|
||||
|
||||
this._close = function() {
|
||||
server.close();
|
||||
node.log('udp listener stopped');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
RED.nodes.registerType("socket in",SocketIn);
|
||||
|
||||
SocketIn.prototype.close = function() {
|
||||
this._close();
|
||||
}
|
||||
|
||||
|
66
nodes/io/30-socketout.html
Normal file
66
nodes/io/30-socketout.html
Normal file
@@ -0,0 +1,66 @@
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
<script type="text/x-red" data-template-name="socket out">
|
||||
<div class="form-row">
|
||||
<label for="node-input-host"><i class="icon-bookmark"></i> Host</label>
|
||||
<input type="text" id="node-input-host" placeholder="localhost" style="width: 40%;" >
|
||||
|
||||
<label for="node-input-port" style="margin-left: 10px; width: 35px;"> Port</label>
|
||||
<input type="text" id="node-input-port" placeholder="Port" style="width: 45px">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-transport"><i class="icon-tasks"></i> Type</label>
|
||||
<select type="text" id="node-input-transport" style="width: 150px;">
|
||||
<option value="http">http</option>
|
||||
<option value="tcp">tcp</option>
|
||||
<option value="udp">udp</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||
<input type="text" id="node-input-name" placeholder="Name">
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="socket out">
|
||||
<p>Provides a choice of http, tcp or udp output connections. All connect, send their <b>msg.payload</b> and disconnect.</p>
|
||||
<p>To use broadcast select udp and set the host to be either the subnet broadcast address required or 255.255.255.255</p>
|
||||
<p>If you need a response from an http request use the httpget node instead.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('socket out',{
|
||||
category: 'output',
|
||||
color:"Silver",
|
||||
defaults: {
|
||||
host: {value:"127.0.0.1",required:true},
|
||||
port: {value:"",required:true},
|
||||
name: {value:""},
|
||||
transport: {value:"tcp",required:true}
|
||||
},
|
||||
inputs:1,
|
||||
outputs:0,
|
||||
icon: "bridge-dash.png",
|
||||
align: "right",
|
||||
label: function() {
|
||||
return this.name||this.topic||(this.transport+":"+this.port);
|
||||
},
|
||||
labelStyle: function() {
|
||||
return (this.name||!this.topic)?"node_label_italic":"";
|
||||
}
|
||||
});
|
||||
</script>
|
63
nodes/io/30-socketout.js
Normal file
63
nodes/io/30-socketout.js
Normal file
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
* 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");
|
||||
|
||||
function SocketOut(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.host = n.host;
|
||||
this.port = n.port * 1;
|
||||
this.name = n.name;
|
||||
this.trans = n.transport||n.trans||"";
|
||||
var node = this;
|
||||
this.on("input", function(msg) {
|
||||
if (msg != null) {
|
||||
if (this.trans == "http") {
|
||||
var http = require("http");
|
||||
http.get(msg.payload, function(res) {
|
||||
node.log("http : response : " + res.statusCode);
|
||||
}).on('error', function(e) {
|
||||
node.error("http : error : " + e.message);
|
||||
});
|
||||
}
|
||||
if (this.trans == "tcp") {
|
||||
var net = require('net');
|
||||
var client = new net.Socket();
|
||||
client.on('error', function (err) {
|
||||
node.error('tcp : '+err);
|
||||
});
|
||||
client.connect(this.port, this.host, function() {
|
||||
client.end(msg.payload);
|
||||
});
|
||||
}
|
||||
if (this.trans == "udp") {
|
||||
var dgram = require('dgram');
|
||||
var sock = dgram.createSocket('udp4'); // only use ipv4 for now
|
||||
sock.bind(this.port); // have to bind before you can enable broadcast...
|
||||
sock.setBroadcast(true); // turn on broadcast
|
||||
var buf = new Buffer(msg.payload);
|
||||
sock.send(buf, 0, buf.length, this.port, this.host, function(err, bytes) {
|
||||
if (err) node.error("udp : "+err);
|
||||
//util.log('[socket out] udp :' +bytes);
|
||||
sock.close();
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
var node = this;
|
||||
}
|
||||
|
||||
RED.nodes.registerType("socket out",SocketOut);
|
79
nodes/io/31-tcpin.html
Normal file
79
nodes/io/31-tcpin.html
Normal file
@@ -0,0 +1,79 @@
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
<script type="text/x-red" data-template-name="tcp in">
|
||||
<div class="form-row">
|
||||
<label for="node-input-host"><i class="icon-bookmark"></i> Host</label>
|
||||
<input type="text" id="node-input-host" placeholder="localhost" style="width: 40%;" >
|
||||
|
||||
<label for="node-input-port" style="margin-left: 10px; width: 35px;"> Port</label>
|
||||
<input type="text" id="node-input-port" placeholder="Port" style="width: 45px">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label> </label>
|
||||
<input type="checkbox" id="node-input-server" placeholder="server" style="display: inline-block; width: auto; vertical-align: top;">
|
||||
<label for="node-input-server" style="width: 70%;">Be a server socket ?</label>
|
||||
</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%;">Base64 encode payload ?</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">
|
||||
</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: sends the received data as a Buffer object (not a String).<br/>If you select server socket the host defaults to localhost.</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="tcp in">
|
||||
<p>Provides a choice of tcp input connections. Can either be a client - or provide a listening socket.</p>
|
||||
<p>The TCP node produces a <i>BUFFER</i> object <b></b>msg.payload</b> and NOT a String. If you need a String then use <i>.toString()</i> on <b>msg.payload</b> in your next function block.</p>
|
||||
<p>It also provides <b>msg.fromip</b> of the form ipaddress:port .</p>
|
||||
<p>You can select Base64 encoding if you want to make it easy to preserve the complete message as a string.</p>
|
||||
<p>In case of disconnection the client trys to reconnect every 10 secs. Topic is optional.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('tcp in',{
|
||||
category: 'input',
|
||||
color:"Silver",
|
||||
defaults: {
|
||||
host: {value:"127.0.0.1",required:true},
|
||||
port: {value:"",required:true,validate:RED.validators.number()},
|
||||
base64: {value:false,required:true},
|
||||
server: {value:false,required:true},
|
||||
topic: {value:""},
|
||||
name: {value:""}
|
||||
},
|
||||
inputs:0,
|
||||
outputs:1,
|
||||
icon: "bridge-dash.png",
|
||||
label: function() {
|
||||
if ((this.host!="") & (this.port!="")) {
|
||||
return this.name||(this.host+":"+this.port);
|
||||
}
|
||||
else { return "tcp in"; }
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name?"node_label_italic":"";
|
||||
}
|
||||
});
|
||||
</script>
|
103
nodes/io/31-tcpin.js
Normal file
103
nodes/io/31-tcpin.js
Normal file
@@ -0,0 +1,103 @@
|
||||
/**
|
||||
* 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 reConnect = RED.settings.socketReconnectTime||10000;
|
||||
var net = require('net');
|
||||
|
||||
function TcpIn(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.host = n.host;
|
||||
this.port = n.port * 1;
|
||||
this.topic = n.topic;
|
||||
this.base64 = n.base64;
|
||||
this.server = n.server;
|
||||
var node = this;
|
||||
|
||||
if (!node.server) {
|
||||
var client;
|
||||
var to;
|
||||
|
||||
function setupTcpClient() {
|
||||
node.log('connecting to port '+node.port);
|
||||
client = net.connect(node.port, node.host, function() {
|
||||
node.log("input connected to "+node.host+":"+node.port);
|
||||
});
|
||||
|
||||
client.on('data', function (data) {
|
||||
var msg;
|
||||
if (node.base64) { msg = { topic:node.topic, payload:new Buffer(data).toString('base64') }; }
|
||||
else { msg = {topic:node.topic, payload:data}; }
|
||||
node.send(msg);
|
||||
});
|
||||
|
||||
client.on('end', function() {
|
||||
node.log("ended");
|
||||
});
|
||||
|
||||
client.on('close', function() {
|
||||
client.destroy();
|
||||
node.log('closed');
|
||||
to = setTimeout(setupTcpClient, reConnect);
|
||||
});
|
||||
|
||||
client.on('error', function(err) {
|
||||
node.log('error : '+err);
|
||||
//to = setTimeout(setupTcpClient, reConnect);
|
||||
});
|
||||
}
|
||||
setupTcpClient();
|
||||
|
||||
this._close = function() {
|
||||
client.end();
|
||||
clearTimeout(to);
|
||||
node.log('input stopped');
|
||||
}
|
||||
}
|
||||
else {
|
||||
var server = net.createServer(function (socket) {
|
||||
var buffer = null;
|
||||
socket.on('data', function (chunk) {
|
||||
//if (buffer == null) {
|
||||
// buffer = chunk;
|
||||
//} else {
|
||||
//buffer = Buffer.concat([buffer,chunk]);
|
||||
var msg = {topic:node.topic, payload:chunk, fromip:socket.remoteAddress+':'+socket.remotePort};
|
||||
node.send(msg);
|
||||
//}
|
||||
});
|
||||
socket.on('end', function() {
|
||||
var msg = {topic:node.topic, payload:buffer, fromip:socket.remoteAddress+':'+socket.remotePort};
|
||||
node.send(msg);
|
||||
});
|
||||
});
|
||||
server.listen(node.port);
|
||||
node.log('socket input on port '+node.port);
|
||||
|
||||
this._close = function() {
|
||||
server.close();
|
||||
node.log('socket input stopped');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
RED.nodes.registerType("tcp in",TcpIn);
|
||||
|
||||
TcpIn.prototype.close = function() {
|
||||
this._close();
|
||||
}
|
||||
|
73
nodes/io/31-tcpout.html
Normal file
73
nodes/io/31-tcpout.html
Normal file
@@ -0,0 +1,73 @@
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
<script type="text/x-red" data-template-name="tcp out">
|
||||
<div class="form-row">
|
||||
<label for="node-input-host"><i class="icon-bookmark"></i> Host</label>
|
||||
<input type="text" id="node-input-host" placeholder="localhost" style="width: 40%;" >
|
||||
|
||||
<label for="node-input-port" style="margin-left: 10px; width: 35px;"> Port</label>
|
||||
<input type="text" id="node-input-port" placeholder="Port" style="width: 45px">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label> </label>
|
||||
<input type="checkbox" id="node-input-beserver" placeholder="server" style="display: inline-block; width: auto; vertical-align: top;">
|
||||
<label for="node-input-beserver" style="width: 70%;">Be a server socket ?</label>
|
||||
</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 message ?</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>
|
||||
<div class="form-tips">Tip: If you select server socket the host defaults to localhost.</div>
|
||||
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="tcp out">
|
||||
<p>Provides a choice of tcp output connections. Can either connect out - or provide a socket connection.</p>
|
||||
<p>Only <b>msg.payload</b> is sent.</p>
|
||||
<p>You can select Base64 decoding if you want to decode a message encoded by the input socket.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('tcp out',{
|
||||
category: 'output',
|
||||
color:"Silver",
|
||||
defaults: {
|
||||
host: {value:"127.0.0.1",required:true},
|
||||
port: {value:"",required:true},
|
||||
beserver: {value:false,required:true},
|
||||
base64: {value:false,required:true},
|
||||
name: {value:""}
|
||||
},
|
||||
inputs:1,
|
||||
outputs:0,
|
||||
icon: "bridge-dash.png",
|
||||
align: "right",
|
||||
label: function() {
|
||||
var lab = this.host+":"+this.port;
|
||||
if (this.server) lab = "tcp out:"+this.port;
|
||||
return this.name||lab;
|
||||
},
|
||||
labelStyle: function() {
|
||||
return (this.name)?"node_label_italic":"";
|
||||
}
|
||||
});
|
||||
</script>
|
98
nodes/io/31-tcpout.js
Normal file
98
nodes/io/31-tcpout.js
Normal file
@@ -0,0 +1,98 @@
|
||||
/**
|
||||
* 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 reConnect = RED.settings.socketReconnectTime||10000;
|
||||
var net = require('net');
|
||||
|
||||
function TcpOut(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.host = n.host;
|
||||
this.port = n.port * 1;
|
||||
this.base64 = n.base64;
|
||||
this.beserver = n.beserver;
|
||||
this.name = n.name;
|
||||
var node = this;
|
||||
|
||||
if (!node.beserver) {
|
||||
var client = new net.Socket();
|
||||
var to;
|
||||
|
||||
function setupTcpClient() {
|
||||
client.connect(node.port, node.host, function() {
|
||||
node.log("output connected to "+node.host+":"+node.port);
|
||||
});
|
||||
|
||||
client.on('error', function (err) {
|
||||
node.error('error : '+err);
|
||||
to = setTimeout(setupTcpClient, reConnect);
|
||||
});
|
||||
|
||||
client.on('end', function (err) {
|
||||
node.log("output disconnected");
|
||||
to = setTimeout(setupTcpClient, reConnect);
|
||||
});
|
||||
|
||||
client.on('close', function() {
|
||||
client.destroy();
|
||||
node.log('closed');
|
||||
to = setTimeout(setupTcpClient, reConnect);
|
||||
});
|
||||
|
||||
node.on("input", function(msg) {
|
||||
if (msg.payload != null) {
|
||||
if (node.base64) { client.write(new Buffer(msg.payload,'base64')); }
|
||||
else { client.write(msg.payload);}
|
||||
}
|
||||
});
|
||||
}
|
||||
setupTcpClient();
|
||||
|
||||
this._close = function() {
|
||||
client.end();
|
||||
clearTimeout(to);
|
||||
node.log('output stopped');
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
var server = net.createServer(function (socket) {
|
||||
socket.on("connect",function() {
|
||||
node.log("Connection from "+socket.remoteAddress);
|
||||
});
|
||||
node.on("input", function(msg) {
|
||||
if (msg.payload != null) {
|
||||
if (node.base64) { socket.write(new Buffer(msg.payload,'base64')); }
|
||||
else { socket.write(msg.payload);}
|
||||
}
|
||||
});
|
||||
});
|
||||
server.listen(node.port);
|
||||
node.log('socket output on port '+node.port);
|
||||
|
||||
this._close = function() {
|
||||
server.close();
|
||||
node.log('output stopped');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RED.nodes.registerType("tcp out",TcpOut);
|
||||
|
||||
TcpOut.prototype.close = function() {
|
||||
this._close();
|
||||
}
|
||||
|
131
nodes/io/32-multicast.html
Normal file
131
nodes/io/32-multicast.html
Normal file
@@ -0,0 +1,131 @@
|
||||
<!--
|
||||
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="multicast in">
|
||||
<div class="form-row">
|
||||
<label for="node-input-group"><i class="icon-tasks"></i> Group</label>
|
||||
<input type="text" id="node-input-group" placeholder="225.0.18.83" style="width: 40%;">
|
||||
<label for="node-input-port" style="margin-left: 10px; width: 35px;"> Port</label>
|
||||
<input type="text" id="node-input-port" placeholder="Port" style="width: 45px">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-iface"><i class="icon-globe"></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%;">Base64 encode 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>
|
||||
<div class="form-tips">Tip: sends the received data as a Buffer object (not a String).<br/>Make sure your firewall will allow the data in.</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="multicast in">
|
||||
<p>A multicast udp input node, that produces a <b>msg.payload</b> containing a <i>BUFFER</i> object and NOT a String.</p>
|
||||
<p>If you need a String then use <i>.toString()</i> on <b>msg.payload</b> in your next function block.</p>
|
||||
<p>It also provides <b>msg.fromip</b> of the form ipaddress:port .</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('multicast in',{
|
||||
category: 'input',
|
||||
color:"Silver",
|
||||
defaults: {
|
||||
name: {value:""},
|
||||
group: {value:"",required:true},
|
||||
host: {value:""},
|
||||
iface: {value:""},
|
||||
port: {value:"",required:true,validate:RED.validators.number()},
|
||||
base64: {value:false,required:true},
|
||||
multicast: {value:"true"}
|
||||
},
|
||||
inputs:0,
|
||||
outputs:1,
|
||||
icon: "bridge-dash.png",
|
||||
label: function() {
|
||||
if ((this.group!="") & (this.port!="")) {
|
||||
return this.name||(this.group+":"+this.port);
|
||||
}
|
||||
else { return "multicast in"; }
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name?"node_label_italic":"";
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- The Output Node -->
|
||||
<script type="text/x-red" data-template-name="multicast out">
|
||||
<div class="form-row">
|
||||
<label for="node-input-group"><i class="icon-tasks"></i> Group</label>
|
||||
<input type="text" id="node-input-group" placeholder="225.0.18.83" style="width: 40%;">
|
||||
<label for="node-input-port" style="margin-left: 10px; width: 35px;"> Port</label>
|
||||
<input type="text" id="node-input-port" placeholder="Port" style="width: 45px">
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<label for="node-input-iface"><i class="icon-globe"></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>
|
||||
|
||||
<script type="text/x-red" data-help-name="multicast out">
|
||||
<p>This node sends <b>msg.payload</b> to the designated multicast group and port.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('multicast out',{
|
||||
category: 'output',
|
||||
color:"Silver",
|
||||
defaults: {
|
||||
name: {value:""},
|
||||
group: {value:"",required:true},
|
||||
host: {value:""},
|
||||
iface: {value:""},
|
||||
port: {value:"",required:true,validate:RED.validators.number()},
|
||||
base64: {value:false,required:true},
|
||||
multicast: {value:"true"}
|
||||
},
|
||||
inputs:1,
|
||||
outputs:0,
|
||||
icon: "bridge-dash.png",
|
||||
align: "right",
|
||||
label: function() {
|
||||
if ((this.group!="") & (this.port!="")) {
|
||||
return this.name||(this.group+":"+this.port);
|
||||
}
|
||||
else { return "multicast out"; }
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name?"node_label_italic":"";
|
||||
}
|
||||
});
|
||||
</script>
|
118
nodes/io/32-multicast.js
Normal file
118
nodes/io/32-multicast.js
Normal file
@@ -0,0 +1,118 @@
|
||||
/**
|
||||
* 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 MCastIn(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.group = n.group;
|
||||
this.port = n.port;
|
||||
this.host = n.host || null;
|
||||
this.base64 = n.base64;
|
||||
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.base64) { msg = { payload:message.toString('base64'), 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) {
|
||||
server.setBroadcast(true)
|
||||
server.setMulticastTTL(128);
|
||||
server.addMembership(node.group,node.iface);
|
||||
node.log("udp multicast group "+node.group);
|
||||
}
|
||||
});
|
||||
|
||||
//server.bind(node.port,node.host);
|
||||
server.bind(node.port,node.host);
|
||||
|
||||
this._close = function() {
|
||||
server.close();
|
||||
node.log('udp listener stopped');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
MCastIn.prototype.close = function() {
|
||||
this._close();
|
||||
}
|
||||
RED.nodes.registerType("multicast in",MCastIn);
|
||||
|
||||
// The Output Node
|
||||
function MCastOut(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.group = n.group;
|
||||
this.port = n.port;
|
||||
this.host = n.host || null;
|
||||
this.base64 = n.base64;
|
||||
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...
|
||||
sock.setBroadcast(true); // turn on broadcast
|
||||
sock.setMulticastTTL(128);
|
||||
sock.addMembership(node.group,node.iface); // Add to the multicast group
|
||||
node.log('udp multicaster ready on '+node.group+":"+node.port);
|
||||
|
||||
node.on("input", function(msg) {
|
||||
if (msg.payload != null) {
|
||||
console.log("MCast:",msg.payload);
|
||||
var message;
|
||||
if (node.base64) {
|
||||
message = new Buffer(msg.payload,'base64');
|
||||
}
|
||||
else {
|
||||
message = new Buffer(msg.payload);
|
||||
}
|
||||
sock.send(message, 0, message.length, node.port, node.group, function(err, bytes) {
|
||||
if (err) node.error("udp : "+err);
|
||||
//util.log('[socket out] udp :' +bytes);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
this._close = function() {
|
||||
sock.close();
|
||||
node.log('udp multicaster stopped');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
RED.nodes.registerType("multicast out",MCastOut);
|
||||
|
||||
MCastOut.prototype.close = function() {
|
||||
this._close();
|
||||
}
|
||||
|
59
nodes/io/90-httpget.html
Normal file
59
nodes/io/90-httpget.html
Normal file
@@ -0,0 +1,59 @@
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
<script type="text/x-red" data-template-name="httpget">
|
||||
<div class="form-row">
|
||||
<label for="node-input-baseurl"><i class="icon-tasks"></i> Base URL</label>
|
||||
<input type="text" id="node-input-baseurl" placeholder="http(s)://url">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-append"><i class="icon-tasks"></i> Append</label>
|
||||
<input type="text" id="node-input-append" placeholder="">
|
||||
</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">The <b>Base URL</b> gets prepended to whatever payload is passed in. Leave blank if you pass in a full url.<br/>The append gets added to the end after any payload.<br/>The output Topic is the same as the input Topic.</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="httpget">
|
||||
<p>Performs an HTTP or HTTPS GET and returns the fetched page.</p>
|
||||
<p>The return code is placed in <b>msg.rc</b>, and the full text of the result is in <b>msg.payload</b>.</p>
|
||||
<p>The <b>msg.payload</b> is added to the base url, and then the optional append is added after.</p>
|
||||
<p>This is mostly suitable for small pages as large results will need a lot of parsing....</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('httpget',{
|
||||
category: 'advanced-function',
|
||||
color:"rgb(231, 231, 174)",
|
||||
defaults: {
|
||||
name: {value:""},
|
||||
baseurl: {value:""},
|
||||
append: {value:""}
|
||||
},
|
||||
inputs:1,
|
||||
outputs:1,
|
||||
icon: "white-globe.png",
|
||||
label: function() {
|
||||
return this.name||this.baseurl||"http(s) get";
|
||||
},
|
||||
labelStyle: function() {
|
||||
return (this.name||!this.baseurl)?"node_label_italic":"";
|
||||
}
|
||||
});
|
||||
</script>
|
52
nodes/io/90-httpget.js
Normal file
52
nodes/io/90-httpget.js
Normal file
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* 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");
|
||||
|
||||
function HttpGet(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.baseurl = n.baseurl || "";
|
||||
this.append = n.append || "";
|
||||
var node = this;
|
||||
if (this.baseurl.substring(0,5) === "https") { var http = require("https"); }
|
||||
else { var http = require("http"); }
|
||||
this.on("input", function(msg) {
|
||||
msg._payload = msg.payload;
|
||||
//util.log("[httpget] "+this.baseurl+msg.payload+this.append);
|
||||
http.get(this.baseurl+msg.payload+this.append, function(res) {
|
||||
node.log("Http response: " + res.statusCode);
|
||||
msg.rc = res.statusCode;
|
||||
msg.payload = "";
|
||||
if ((msg.rc != 200) && (msg.rc != 404)) {
|
||||
node.send(msg);
|
||||
}
|
||||
res.setEncoding('utf8');
|
||||
res.on('data', function(chunk) {
|
||||
msg.payload += chunk;
|
||||
});
|
||||
res.on('end', function() {
|
||||
node.send(msg);
|
||||
});
|
||||
}).on('error', function(e) {
|
||||
//node.error(e);
|
||||
msg.rc = 503;
|
||||
msg.payload = e;
|
||||
node.send(msg);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
RED.nodes.registerType("httpget",HttpGet);
|
225
nodes/io/lib/mqtt.js
Normal file
225
nodes/io/lib/mqtt.js
Normal file
@@ -0,0 +1,225 @@
|
||||
/**
|
||||
* 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 util = require("util");
|
||||
var mqtt = require("mqtt");
|
||||
var events = require("events");
|
||||
|
||||
//var Client = module.exports.Client = function(
|
||||
|
||||
var port = 1883;
|
||||
var host = "localhost";
|
||||
|
||||
function MQTTClient(port,host) {
|
||||
this.port = port||1883;
|
||||
this.host = host||"localhost";
|
||||
this.messageId = 1;
|
||||
this.pendingSubscriptions = {};
|
||||
this.inboundMessages = {};
|
||||
this.lastOutbound = (new Date()).getTime();
|
||||
this.lastInbound = (new Date()).getTime();
|
||||
this.connected = false;
|
||||
|
||||
this._nextMessageId = function() {
|
||||
this.messageId += 1;
|
||||
if (this.messageId > 0xFFFF) {
|
||||
this.messageId = 1;
|
||||
}
|
||||
return this.messageId;
|
||||
}
|
||||
events.EventEmitter.call(this);
|
||||
}
|
||||
util.inherits(MQTTClient, events.EventEmitter);
|
||||
|
||||
MQTTClient.prototype.connect = function(options) {
|
||||
var self = this;
|
||||
options = options||{};
|
||||
self.options = options;
|
||||
self.options.keepalive = options.keepalive||15;
|
||||
self.options.clean = self.options.clean||true;
|
||||
self.options.protocolId = 'MQIsdp';
|
||||
self.options.protocolVersion = 3;
|
||||
|
||||
self.client = mqtt.createConnection(this.port,this.host,function(err,client) {
|
||||
if (err) {
|
||||
self.emit('connectionlost',err);
|
||||
return;
|
||||
}
|
||||
client.on('close',function(e) {
|
||||
clearInterval(self.watchdog);
|
||||
if (self.connected) {
|
||||
self.connected = false;
|
||||
self.emit('connectionlost',e);
|
||||
} else {
|
||||
self.emit('disconnect');
|
||||
}
|
||||
});
|
||||
client.on('error',function(e) {
|
||||
clearInterval(self.watchdog);
|
||||
if (self.connected) {
|
||||
self.connected = false;
|
||||
self.emit('connectionlost',e);
|
||||
}
|
||||
});
|
||||
client.on('connack',function(packet) {
|
||||
if (packet.returnCode == 0) {
|
||||
self.watchdog = setInterval(function(self) {
|
||||
var now = (new Date()).getTime();
|
||||
if (now - self.lastOutbound > self.options.keepalive*500 || now - self.lastInbound > self.options.keepalive*500) {
|
||||
if (self.pingOutstanding) {
|
||||
// DO DISCONNECT
|
||||
} else {
|
||||
self.lastOutbound = (new Date()).getTime();
|
||||
self.lastInbound = (new Date()).getTime();
|
||||
self.pingOutstanding = true;
|
||||
self.client.pingreq();
|
||||
}
|
||||
}
|
||||
|
||||
},self.options.keepalive*500,self);
|
||||
self.lastInbound = (new Date()).getTime()
|
||||
self.connected = true;
|
||||
self.emit('connect');
|
||||
} else {
|
||||
self.connected = false;
|
||||
self.emit('connectionlost');
|
||||
}
|
||||
});
|
||||
client.on('suback',function(packet) {
|
||||
self.lastInbound = (new Date()).getTime()
|
||||
var topic = self.pendingSubscriptions[packet.messageId];
|
||||
self.emit('subscribe',topic,packet.granted[0]);
|
||||
delete self.pendingSubscriptions[packet.messageId];
|
||||
});
|
||||
client.on('unsuback',function(packet) {
|
||||
self.lastInbound = (new Date()).getTime()
|
||||
var topic = self.pendingSubscriptions[packet.messageId];
|
||||
self.emit('unsubscribe',topic,packet.granted[0]);
|
||||
delete self.pendingSubscriptions[packet.messageId];
|
||||
});
|
||||
client.on('publish',function(packet) {
|
||||
self.lastInbound = (new Date()).getTime()
|
||||
if (packet.qos < 2) {
|
||||
var p = packet;
|
||||
self.emit('message',p.topic,p.payload,p.qos,p.retain);
|
||||
} else {
|
||||
self.inboundMessages[packet.messageId] = packet;
|
||||
this.lastOutbound = (new Date()).getTime()
|
||||
self.client.pubrec(packet);
|
||||
}
|
||||
if (packet.qos == 1) {
|
||||
this.lastOutbound = (new Date()).getTime()
|
||||
self.client.puback(packet);
|
||||
}
|
||||
});
|
||||
|
||||
client.on('pubrel',function(packet) {
|
||||
self.lastInbound = (new Date()).getTime()
|
||||
var p = self.inboundMessages[packet.messageId];
|
||||
self.emit('message',p.topic,p.payload,p.qos,p.retain);
|
||||
delete self.inboundMessages[packet.messageId];
|
||||
self.lastOutbound = (new Date()).getTime()
|
||||
self.client.pubcomp(packet);
|
||||
});
|
||||
|
||||
client.on('puback',function(packet) {
|
||||
self.lastInbound = (new Date()).getTime()
|
||||
// outbound qos-1 complete
|
||||
});
|
||||
|
||||
client.on('pubrec',function(packet) {
|
||||
self.lastInbound = (new Date()).getTime()
|
||||
self.lastOutbound = (new Date()).getTime()
|
||||
self.client.pubrel(packet);
|
||||
});
|
||||
client.on('pubcomp',function(packet) {
|
||||
self.lastInbound = (new Date()).getTime()
|
||||
// outbound qos-2 complete
|
||||
});
|
||||
client.on('pingresp',function(packet) {
|
||||
self.lastInbound = (new Date()).getTime()
|
||||
self.pingOutstanding = false;
|
||||
});
|
||||
|
||||
this.lastOutbound = (new Date()).getTime()
|
||||
client.connect(self.options);
|
||||
});
|
||||
}
|
||||
|
||||
MQTTClient.prototype.subscribe = function(topic,qos) {
|
||||
var self = this;
|
||||
if (self.connected) {
|
||||
var options = {
|
||||
subscriptions:[{topic:topic,qos:qos}],
|
||||
messageId: self._nextMessageId()
|
||||
};
|
||||
this.pendingSubscriptions[options.messageId] = topic;
|
||||
this.lastOutbound = (new Date()).getTime()
|
||||
self.client.subscribe(options);
|
||||
}
|
||||
}
|
||||
MQTTClient.prototype.unsubscribe = function(topic) {
|
||||
var self = this;
|
||||
if (self.connected) {
|
||||
var options = {
|
||||
topic:topic,
|
||||
messageId: self._nextMessageId()
|
||||
};
|
||||
this.pendingSubscriptions[options.messageId] = topic;
|
||||
this.lastOutbound = (new Date()).getTime()
|
||||
self.client.unsubscribe(options);
|
||||
}
|
||||
}
|
||||
|
||||
MQTTClient.prototype.publish = function(topic,payload,qos,retain) {
|
||||
var self = this;
|
||||
if (self.connected) {
|
||||
|
||||
if (Buffer.isBuffer(payload)) {
|
||||
payload = payload.toString();
|
||||
} else if (typeof payload === "object") {
|
||||
payload = JSON.stringify(payload);
|
||||
} else if (typeof payload !== "string") {
|
||||
payload = ""+payload;
|
||||
}
|
||||
var options = {
|
||||
topic: topic,
|
||||
payload: payload,
|
||||
qos: qos||0,
|
||||
retain:retain||false
|
||||
};
|
||||
if (options.qos != 0) {
|
||||
options.messageId = self._nextMessageId();
|
||||
}
|
||||
this.lastOutbound = (new Date()).getTime()
|
||||
self.client.publish(options);
|
||||
}
|
||||
}
|
||||
|
||||
MQTTClient.prototype.disconnect = function() {
|
||||
var self = this;
|
||||
if (this.connected) {
|
||||
this.connected = false;
|
||||
this.client.disconnect();
|
||||
}
|
||||
}
|
||||
MQTTClient.prototype.isConnected = function() {
|
||||
return this.connected;
|
||||
}
|
||||
module.exports.createClient = function(port,host) {
|
||||
var mqtt_client = new MQTTClient(port,host);
|
||||
return mqtt_client;
|
||||
}
|
||||
|
119
nodes/io/lib/mqttConnectionPool.js
Normal file
119
nodes/io/lib/mqttConnectionPool.js
Normal file
@@ -0,0 +1,119 @@
|
||||
/**
|
||||
* 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 util = require("util");
|
||||
var mqtt = require("./mqtt");
|
||||
var settings = require("../../../red/red").settings;
|
||||
|
||||
var connections = {};
|
||||
|
||||
function matchTopic(ts,t) {
|
||||
var re = new RegExp("^"+ts.replace(/([\[\]\?\(\)\\\\$\^\*\.|])/g,"\\$1").replace(/\+/g,"[^/]+").replace(/#$/,".*"));
|
||||
return re.test(t);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
get: function(broker,port) {
|
||||
var id = broker+":"+port;
|
||||
if (!connections[id]) {
|
||||
connections[id] = function() {
|
||||
var client = mqtt.createClient(port,broker);
|
||||
var options = {keepalive:15,clientId:'mqtt_' + (1+Math.random()*4294967295).toString(16)};
|
||||
var queue = [];
|
||||
var subscriptions = [];
|
||||
var connecting = false;
|
||||
var obj = {
|
||||
_instances: 0,
|
||||
publish: function(msg) {
|
||||
if (client.isConnected()) {
|
||||
client.publish(msg.topic,msg.payload,msg.qos,msg.retain);
|
||||
} else {
|
||||
if (!connecting) {
|
||||
connecting = true;
|
||||
client.connect(options);
|
||||
}
|
||||
queue.push(msg);
|
||||
}
|
||||
},
|
||||
subscribe: function(topic,qos,callback) {
|
||||
subscriptions.push({topic:topic,qos:qos,callback:callback});
|
||||
client.on('message',function(mtopic,mpayload,mqos,mretain) {
|
||||
if (matchTopic(topic,mtopic)) {
|
||||
callback(mtopic,mpayload,mqos,mretain);
|
||||
}
|
||||
});
|
||||
if (client.isConnected()) {
|
||||
client.subscribe(topic,qos);
|
||||
}
|
||||
},
|
||||
on: function(a,b){
|
||||
client.on(a,b);
|
||||
},
|
||||
once: function(a,b){
|
||||
client.once(a,b);
|
||||
},
|
||||
connect: function() {
|
||||
if (!client.isConnected() && !connecting) {
|
||||
connecting = true;
|
||||
client.connect(options);
|
||||
}
|
||||
},
|
||||
disconnect: function() {
|
||||
this._instances -= 1;
|
||||
if (this._instances == 0) {
|
||||
client.disconnect();
|
||||
client = null;
|
||||
delete connections[id];
|
||||
}
|
||||
}
|
||||
};
|
||||
client.on('connect',function() {
|
||||
|
||||
util.log('[mqtt] connected to broker tcp://'+broker+':'+port);
|
||||
|
||||
connecting = false;
|
||||
for (var s in subscriptions) {
|
||||
var topic = subscriptions[s].topic;
|
||||
var qos = subscriptions[s].qos;
|
||||
var callback = subscriptions[s].callback;
|
||||
client.subscribe(topic,qos);
|
||||
}
|
||||
//console.log("connected - publishing",queue.length,"messages");
|
||||
while(queue.length) {
|
||||
var msg = queue.shift();
|
||||
//console.log(msg);
|
||||
client.publish(msg.topic,msg.payload,msg.qos,msg.retain);
|
||||
}
|
||||
});
|
||||
client.on('connectionlost', function(err) {
|
||||
util.log('[mqtt] connection lost to broker tcp://'+broker+':'+port);
|
||||
setTimeout(function() {
|
||||
if (client) {
|
||||
client.connect(options);
|
||||
}
|
||||
}, settings.mqttReconnectTime||5000);
|
||||
});
|
||||
client.on('disconnect', function() {
|
||||
util.log('[mqtt] disconnected from broker tcp://'+broker+':'+port);
|
||||
});
|
||||
|
||||
return obj
|
||||
}();
|
||||
}
|
||||
connections[id]._instances += 1;
|
||||
return connections[id];
|
||||
}
|
||||
};
|
||||
|
Reference in New Issue
Block a user