mirror of
https://github.com/node-red/node-red.git
synced 2025-03-01 10:36:34 +00:00
NLS Core nodes
NLS exec node NLS function/temple/delay nodes NLS function/template/delay/trigger/comment nodes NLS io nodes (mqtt/httpin/websocket/watch/serial) NLS messages.json for tcpin NLS io nodes (tcpin & udp half) NLS io nodes (udp) NLS logic nodes (switch/change) NLS logic (range) and parsers (csv&html) nodes NLS parser nodes (json/xml) NLS test case update for logic/parsers NLS analysis and hardware nodes NLS storage nodes (file/redisout/mongodb) and test NLS storage node (tail) NLS social nodes (feedparse/email/irc) NLS socal node (twitter half change) NLS social node (twitter) and core node (unknown)
This commit is contained in:
committed by
Nick O'Leary
parent
c105b2df37
commit
2fe859b111
@@ -16,16 +16,16 @@
|
||||
|
||||
<script type="text/x-red" data-template-name="mqtt in">
|
||||
<div class="form-row">
|
||||
<label for="node-input-broker"><i class="fa fa-globe"></i> Broker</label>
|
||||
<label for="node-input-broker"><i class="fa fa-globe"></i> <span data-i18n="mqtt.label.broker"></span></label>
|
||||
<input type="text" id="node-input-broker">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-topic"><i class="fa fa-tasks"></i> Topic</label>
|
||||
<input type="text" id="node-input-topic" placeholder="Topic">
|
||||
<label for="node-input-topic"><i class="fa fa-tasks"></i> <span data-i18n="common.label.topic"></span></label>
|
||||
<input type="text" id="node-input-topic" data-i18n="[placeholder]common.label.topicph">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||
<input type="text" id="node-input-name" placeholder="Name">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
|
||||
<input type="text" id="node-input-name" data-i18n="[placeholder]common.label.nameph">
|
||||
</div>
|
||||
</script>
|
||||
|
||||
@@ -58,32 +58,32 @@
|
||||
|
||||
<script type="text/x-red" data-template-name="mqtt out">
|
||||
<div class="form-row">
|
||||
<label for="node-input-broker"><i class="fa fa-globe"></i> Broker</label>
|
||||
<label for="node-input-broker"><i class="fa fa-globe"></i> <span data-i18n="mqtt.label.broker"></span></label>
|
||||
<input type="text" id="node-input-broker">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-topic"><i class="fa fa-tasks"></i> Topic</label>
|
||||
<input type="text" id="node-input-topic" placeholder="Topic">
|
||||
<label for="node-input-topic"><i class="fa fa-tasks"></i> <span data-i18n="common.label.topic"></span></label>
|
||||
<input type="text" id="node-input-topic" data-i18n="[placeholder]common.label.topicph">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-qos"><i class="fa fa-empire"></i> QoS</label>
|
||||
<label for="node-input-qos"><i class="fa fa-empire"></i> <span data-i18n="mqtt.label.qos"></span></label>
|
||||
<select id="node-input-qos" style="width:125px !important">
|
||||
<option value=""></option>
|
||||
<option value="0">0</option>
|
||||
<option value="1">1</option>
|
||||
<option value="2">2</option>
|
||||
</select>
|
||||
<i class="fa fa-history"></i> Retain <select id="node-input-retain" style="width:125px !important">
|
||||
<i class="fa fa-history"></i> <span data-i18n="mqtt.retain"></span> <select id="node-input-retain" style="width:125px !important">
|
||||
<option value=""></option>
|
||||
<option value="false">false</option>
|
||||
<option value="true">true</option>
|
||||
<option value="false" data-i18n="mqtt.false"></option>
|
||||
<option value="true" data-i18n="mqtt.true"></option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||
<input type="text" id="node-input-name" placeholder="Name">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
|
||||
<input type="text" id="node-input-name" data-i18n="[placeholder]common.label.nameph">
|
||||
</div>
|
||||
<div class="form-tips">Tip: Leave topic, qos or retain blank if you want to set them via msg properties.</div>
|
||||
<div class="form-tips"><span data-i18n="mqtt.tip"></span></div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="mqtt out">
|
||||
@@ -118,21 +118,21 @@
|
||||
|
||||
<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="fa fa-globe"></i> Broker</label>
|
||||
<label for="node-config-input-broker"><i class="fa fa-globe"></i> <span data-i18n="mqtt.label.broker"></span></label>
|
||||
<input class="input-append-left" type="text" id="node-config-input-broker" placeholder="localhost" 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">
|
||||
<label for="node-config-input-port" style="margin-left: 10px; width: 35px; "> <span data-i18n="mqtt.port"></span></label>
|
||||
<input type="text" id="node-config-input-port" data-i18n="[placeholder]mqtt.portph" style="width:45px">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-config-input-clientid"><i class="fa fa-tag"></i> Client ID</label>
|
||||
<input type="text" id="node-config-input-clientid" placeholder="Leave blank for auto generated">
|
||||
<label for="node-config-input-clientid"><i class="fa fa-tag"></i> <span data-i18n="mqtt.label.clientid"></span></label>
|
||||
<input type="text" id="node-config-input-clientid" data-i18n="[placeholder]mqtt.label.clientidph">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-config-input-user"><i class="fa fa-user"></i> Username</label>
|
||||
<label for="node-config-input-user"><i class="fa fa-user"></i> <span data-i18n="common.label.username"></span></label>
|
||||
<input type="text" id="node-config-input-user">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-config-input-password"><i class="fa fa-lock"></i> Password</label>
|
||||
<label for="node-config-input-password"><i class="fa fa-lock"></i> <span data-i18n="common.label.password"></span></label>
|
||||
<input type="password" id="node-config-input-password">
|
||||
</div>
|
||||
</script>
|
||||
|
@@ -42,7 +42,7 @@ module.exports = function(RED) {
|
||||
this.broker = n.broker;
|
||||
this.brokerConfig = RED.nodes.getNode(this.broker);
|
||||
if (this.brokerConfig) {
|
||||
this.status({fill:"red",shape:"ring",text:"disconnected"});
|
||||
this.status({fill:"red",shape:"ring",text:RED._("common.status.disconnected")});
|
||||
this.client = connectionPool.get(this.brokerConfig.broker,this.brokerConfig.port,this.brokerConfig.clientid,this.brokerConfig.username,this.brokerConfig.password);
|
||||
var node = this;
|
||||
if (this.topic) {
|
||||
@@ -55,22 +55,22 @@ module.exports = function(RED) {
|
||||
node.send(msg);
|
||||
}, this.id);
|
||||
this.client.on("connectionlost",function() {
|
||||
node.status({fill:"red",shape:"ring",text:"disconnected"});
|
||||
node.status({fill:"red",shape:"ring",text:RED._("common.status.disconnected")});
|
||||
});
|
||||
this.client.on("connect",function() {
|
||||
node.status({fill:"green",shape:"dot",text:"connected"});
|
||||
node.status({fill:"green",shape:"dot",text:RED._("common.status.connected")});
|
||||
});
|
||||
if (this.client.isConnected()) {
|
||||
node.status({fill:"green",shape:"dot",text:"connected"});
|
||||
node.status({fill:"green",shape:"dot",text:RED._("common.status.connected")});
|
||||
} else {
|
||||
this.client.connect();
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.error("topic not defined");
|
||||
this.error(RED._("mqtt.errors.not-defined"));
|
||||
}
|
||||
} else {
|
||||
this.error("missing broker configuration");
|
||||
this.error(RED._("mqtt.errors.missing-config"));
|
||||
}
|
||||
this.on('close', function() {
|
||||
if (this.client) {
|
||||
@@ -90,7 +90,7 @@ module.exports = function(RED) {
|
||||
this.brokerConfig = RED.nodes.getNode(this.broker);
|
||||
|
||||
if (this.brokerConfig) {
|
||||
this.status({fill:"red",shape:"ring",text:"disconnected"});
|
||||
this.status({fill:"red",shape:"ring",text:RED._("common.status.disconnected")});
|
||||
this.client = connectionPool.get(this.brokerConfig.broker,this.brokerConfig.port,this.brokerConfig.clientid,this.brokerConfig.username,this.brokerConfig.password);
|
||||
var node = this;
|
||||
this.on("input",function(msg) {
|
||||
@@ -110,22 +110,22 @@ module.exports = function(RED) {
|
||||
if (msg.hasOwnProperty("topic") && (typeof msg.topic === "string") && (msg.topic !== "")) { // topic must exist
|
||||
this.client.publish(msg); // send the message
|
||||
}
|
||||
else { node.warn("Invalid topic specified"); }
|
||||
else { node.warn(RED._("mqtt.errors.invalid-topic")); }
|
||||
}
|
||||
});
|
||||
this.client.on("connectionlost",function() {
|
||||
node.status({fill:"red",shape:"ring",text:"disconnected"});
|
||||
node.status({fill:"red",shape:"ring",text:RED._("common.status.disconnected")});
|
||||
});
|
||||
this.client.on("connect",function() {
|
||||
node.status({fill:"green",shape:"dot",text:"connected"});
|
||||
node.status({fill:"green",shape:"dot",text:RED._("common.status.connected")});
|
||||
});
|
||||
if (this.client.isConnected()) {
|
||||
node.status({fill:"green",shape:"dot",text:"connected"});
|
||||
node.status({fill:"green",shape:"dot",text:RED._("common.status.connected")});
|
||||
} else {
|
||||
this.client.connect();
|
||||
}
|
||||
} else {
|
||||
this.error("missing broker configuration");
|
||||
this.error(RED._("mqtt.errors.missing-config"));
|
||||
}
|
||||
this.on('close', function() {
|
||||
if (this.client) {
|
||||
|
@@ -16,7 +16,7 @@
|
||||
|
||||
<script type="text/x-red" data-template-name="http in">
|
||||
<div class="form-row">
|
||||
<label for="node-input-method"><i class="fa fa-tasks"></i> Method</label>
|
||||
<label for="node-input-method"><i class="fa fa-tasks"></i> <span data-i18n="httpin.label.method"></span></label>
|
||||
<select type="text" id="node-input-method" style="width:72%;">
|
||||
<option value="get">GET</option>
|
||||
<option value="post">POST</option>
|
||||
@@ -25,18 +25,18 @@
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-url"><i class="fa fa-globe"></i> url</label>
|
||||
<input type="text" id="node-input-url" placeholder="/url">
|
||||
<label for="node-input-url"><i class="fa fa-globe"></i> <span data-i18n="httpin.label.url"></span></label>
|
||||
<input type="text" id="node-input-url" data-i18n="[placeholder]httpin.label.urlph">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||
<input type="text" id="node-input-name" placeholder="Name">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
|
||||
<input type="text" id="node-input-name" data-i18n="[placeholder]common.label.nameph">
|
||||
</div>
|
||||
<div class="form-row row-swagger-doc">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Doc</label>
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="httpin.label.doc"></span></label>
|
||||
<input type="text" id="node-input-swaggerDoc">
|
||||
</div>
|
||||
<div id="node-input-tip" class="form-tips">The url will be relative to <code><span id="node-input-path"></span></code>.</div>
|
||||
<div id="node-input-tip" class="form-tips"><span data-i18n="httpin.in-tip"></span><code><span id="node-input-path"></span></code>.</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="http in">
|
||||
@@ -67,10 +67,10 @@
|
||||
|
||||
<script type="text/x-red" data-template-name="http response">
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||
<input type="text" id="node-input-name" placeholder="Name">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
|
||||
<input type="text" id="node-input-name" data-i18n="[placeholder]common.label.nameph">
|
||||
</div>
|
||||
<div class="form-tips">The messages sent to this node <b>must</b> originate from an <i>http input</i> node</div>
|
||||
<div class="form-tips"><span data-i18n="[html]httpin.res-tip"></span></div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="http response">
|
||||
@@ -86,45 +86,45 @@
|
||||
|
||||
<script type="text/x-red" data-template-name="http request">
|
||||
<div class="form-row">
|
||||
<label for="node-input-method"><i class="fa fa-tasks"></i> Method</label>
|
||||
<label for="node-input-method"><i class="fa fa-tasks"></i> <span data-i18n="httpin.label.method"></span></label>
|
||||
<select type="text" id="node-input-method" style="width:72%;">
|
||||
<option value="GET">GET</option>
|
||||
<option value="POST">POST</option>
|
||||
<option value="PUT">PUT</option>
|
||||
<option value="DELETE">DELETE</option>
|
||||
<option value="use">- set by msg.method -</option>
|
||||
<option value="use" data-i18n="httpin.setby"></option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-url"><i class="fa fa-globe"></i> URL</label>
|
||||
<input type="text" id="node-input-url" placeholder="http://">
|
||||
<label for="node-input-url"><i class="fa fa-globe"></i> <span data-i18n="httpin.label.url"></span></label>
|
||||
<input type="text" id="node-input-url" data-i18n="[placeholder]httpin.label.httpph">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label> </label>
|
||||
<input type="checkbox" id="node-input-useAuth" style="display: inline-block; width: auto; vertical-align: top;">
|
||||
<label for="node-input-useAuth" style="width: 70%;">Use basic authentication ?</label>
|
||||
<label for="node-input-useAuth" style="width: 70%;"><span data-i18n="httpin.basicauth"></span></label>
|
||||
</div>
|
||||
<div class="form-row node-input-useAuth-row">
|
||||
<label for="node-input-user"><i class="fa fa-user"></i> Username</label>
|
||||
<label for="node-input-user"><i class="fa fa-user"></i> <span data-i18n="common.label.username"></span></label>
|
||||
<input type="text" id="node-input-user">
|
||||
</div>
|
||||
<div class="form-row node-input-useAuth-row">
|
||||
<label for="node-input-password"><i class="fa fa-lock"></i> Password</label>
|
||||
<label for="node-input-password"><i class="fa fa-lock"></i> <span data-i18n="common.label.password"></span></label>
|
||||
<input type="password" id="node-input-password">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-ret"><i class="fa fa-arrow-left"></i> Return</label>
|
||||
<label for="node-input-ret"><i class="fa fa-arrow-left"></i> <span data-i18n="httpin.label.return"></span></label>
|
||||
<select type="text" id="node-input-ret" style="width:72%;">
|
||||
<option value="txt">a UTF-8 string</option>
|
||||
<option value="bin">a binary buffer</option>
|
||||
<option value="obj">a parsed JSON object</option>
|
||||
<option value="txt" data-i18n="httpin.utf8"></option>
|
||||
<option value="bin" data-i18n="httpin.binary"></option>
|
||||
<option value="obj" data-i18n="httpin.json"></option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||
<input type="text" id="node-input-name" placeholder="Name">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
|
||||
<input type="text" id="node-input-name" data-i18n="[placeholder]common.label.nameph">
|
||||
</div>
|
||||
<div class="form-tips" id="tip-json" hidden>Tip: If the JSON parse fails the fetched string is returned as-is.</div>
|
||||
<div class="form-tips" id="tip-json" hidden><span data-i18n="httpin.req-tip"></span></div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="http request">
|
||||
@@ -241,7 +241,7 @@
|
||||
outputs:1,
|
||||
icon: "white-globe.png",
|
||||
label: function() {
|
||||
return this.name||"http request";
|
||||
return this.name||this._("httpin.httpreq");
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name?"node_label_italic":"";
|
||||
|
@@ -137,7 +137,7 @@ module.exports = function(RED) {
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.warn("Cannot create http-in node when httpNodeRoot set to false");
|
||||
this.warn(RED._("httpin.errors.not-created"));
|
||||
}
|
||||
}
|
||||
RED.nodes.registerType("http in",HTTPIn);
|
||||
@@ -172,7 +172,7 @@ module.exports = function(RED) {
|
||||
msg.res.send(statusCode,msg.payload);
|
||||
}
|
||||
} else {
|
||||
node.warn("No response object");
|
||||
node.warn(RED._("httpin.errors.no-response"));
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -195,16 +195,16 @@ module.exports = function(RED) {
|
||||
|
||||
this.on("input",function(msg) {
|
||||
var preRequestTimestamp = process.hrtime();
|
||||
node.status({fill:"blue",shape:"dot",text:"requesting"});
|
||||
node.status({fill:"blue",shape:"dot",text:RED._("common.status.requesting")});
|
||||
var url = nodeUrl || msg.url;
|
||||
if (msg.url && nodeUrl && (nodeUrl !== msg.url)) { // revert change below when warning is finally removed
|
||||
node.warn("Warning: msg properties can no longer override set node properties. See bit.ly/nr-override-msg-props");
|
||||
node.warn(RED._("httpin.errors.not-overridden"));
|
||||
}
|
||||
if (isTemplatedUrl) {
|
||||
url = mustache.render(nodeUrl,msg);
|
||||
}
|
||||
if (!url) {
|
||||
node.error("No url specified",msg);
|
||||
node.error(RED._("httpin.errors.no-url"),msg);
|
||||
return;
|
||||
}
|
||||
// url must start http:// or https:// so assume http:// if not set
|
||||
@@ -214,7 +214,7 @@ module.exports = function(RED) {
|
||||
|
||||
var method = nodeMethod.toUpperCase() || "GET";
|
||||
if (msg.method && n.method && (n.method !== "use")) { // warn if override option not set
|
||||
node.warn("Warning: msg properties can no longer override fixed node properties. Use explicit override option. See bit.ly/nr-override-msg-props");
|
||||
node.warn(RED._("httpin.errors.not-overridden"));
|
||||
}
|
||||
if (msg.method && n.method && (n.method === "use")) {
|
||||
method = msg.method.toUpperCase(); // use the msg parameter
|
||||
@@ -312,7 +312,7 @@ module.exports = function(RED) {
|
||||
}
|
||||
else if (node.ret === "obj") {
|
||||
try { msg.payload = JSON.parse(msg.payload); }
|
||||
catch(e) { node.warn("JSON parse error"); }
|
||||
catch(e) { node.warn(RED._("httpin.errors.json-error")); }
|
||||
}
|
||||
node.send(msg);
|
||||
node.status({});
|
||||
|
@@ -1,279 +1,277 @@
|
||||
<!--
|
||||
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/javascript">
|
||||
function ws_oneditprepare() {
|
||||
$("#websocket-client-row").hide();
|
||||
$("#node-input-mode").change(function(){
|
||||
if( $("#node-input-mode").val() === 'client') {
|
||||
$("#websocket-server-row").hide();
|
||||
$("#websocket-client-row").show();
|
||||
}
|
||||
else {
|
||||
$("#websocket-server-row").show();
|
||||
$("#websocket-client-row").hide();
|
||||
}
|
||||
});
|
||||
|
||||
if(this.client) {
|
||||
$("#node-input-mode").val('client').change();
|
||||
}
|
||||
else {
|
||||
$("#node-input-mode").val('server').change();
|
||||
}
|
||||
}
|
||||
|
||||
function ws_oneditsave() {
|
||||
if($("#node-input-mode").val() === 'client') {
|
||||
$("#node-input-server").append('<option value="">Dummy</option>');
|
||||
$("#node-input-server").val('');
|
||||
}
|
||||
else {
|
||||
$("#node-input-client").append('<option value="">Dummy</option>');
|
||||
$("#node-input-client").val('');
|
||||
}
|
||||
}
|
||||
|
||||
function ws_label() {
|
||||
var nodeid = (this.client)?this.client:this.server;
|
||||
var wsNode = RED.nodes.node(nodeid);
|
||||
return this.name||(wsNode?"[ws] "+wsNode.label():"websocket");
|
||||
}
|
||||
|
||||
function ws_validateserver() {
|
||||
if($("#node-input-mode").val() === 'client' || (this.client && !this.server)) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return RED.nodes.node(this.server) != null;
|
||||
}
|
||||
}
|
||||
|
||||
function ws_validateclient() {
|
||||
if($("#node-input-mode").val() === 'client' || (this.client && !this.server)) {
|
||||
return RED.nodes.node(this.client) != null;
|
||||
}
|
||||
else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<!-- WebSocket Input Node -->
|
||||
<script type="text/x-red" data-template-name="websocket in">
|
||||
<div class="form-row">
|
||||
<label for="node-input-mode"><i class="fa fa-dot-circle-o"></i> Type</label>
|
||||
<select id="node-input-mode">
|
||||
<option value="server">Listen on</option>
|
||||
<option value="client">Connect to</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-row" id="websocket-server-row">
|
||||
<label for="node-input-server"><i class="fa fa-bookmark"></i> Path</label>
|
||||
<input type="text" id="node-input-server">
|
||||
</div>
|
||||
<div class="form-row" id="websocket-client-row">
|
||||
<label for="node-input-client"><i class="fa fa-bookmark"></i> URL</label>
|
||||
<input type="text" id="node-input-client">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||
<input type="text" id="node-input-name" placeholder="Name">
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="websocket in">
|
||||
<p>WebSocket input node.</p>
|
||||
<p>By default, the data received from the WebSocket will be in <b>msg.payload</b>.
|
||||
The socket can be configured to expect a properly formed JSON string, in which
|
||||
case it will parse the JSON and send on the resulting object as the entire message.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('websocket in',{
|
||||
category: 'input',
|
||||
defaults: {
|
||||
name: {value:""},
|
||||
server: {type:"websocket-listener", validate: ws_validateserver},
|
||||
client: {type:"websocket-client", validate: ws_validateclient}
|
||||
},
|
||||
color:"rgb(215, 215, 160)",
|
||||
inputs:0,
|
||||
outputs:1,
|
||||
icon: "white-globe.png",
|
||||
labelStyle: function() {
|
||||
return this.name?"node_label_italic":"";
|
||||
},
|
||||
label: ws_label,
|
||||
oneditsave: ws_oneditsave,
|
||||
oneditprepare: ws_oneditprepare
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- WebSocket out Node -->
|
||||
<script type="text/x-red" data-template-name="websocket out">
|
||||
<div class="form-row">
|
||||
<label for="node-input-mode"><i class="fa fa-dot-circle-o"></i> Type</label>
|
||||
<select id="node-input-mode">
|
||||
<option value="server">Listen on</option>
|
||||
<option value="client">Connect to</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-row" id="websocket-server-row">
|
||||
<label for="node-input-server"><i class="fa fa-bookmark"></i> Path</label>
|
||||
<input type="text" id="node-input-server">
|
||||
</div>
|
||||
<div class="form-row" id="websocket-client-row">
|
||||
<label for="node-input-client"><i class="fa fa-bookmark"></i> URL</label>
|
||||
<input type="text" id="node-input-client">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||
<input type="text" id="node-input-name" placeholder="Name">
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="websocket out">
|
||||
<p>WebSocket out node.</p>
|
||||
<p>By default, <b>msg.payload</b> will be sent over the WebSocket. The socket
|
||||
can be configured to encode the entire message object as a JSON string and send that
|
||||
over the WebSocket.</p>
|
||||
|
||||
<p>If the message arriving at this node started at a WebSocket In node, the message
|
||||
will be sent back to the client that triggered the flow. Otherwise, the message
|
||||
will be broadcast to all connected clients.</p>
|
||||
<p>If you want to broadcast a message that started at a WebSocket In node, you
|
||||
should delete the <b>msg._session</b> property within the flow</p>.
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('websocket out',{
|
||||
category: 'output',
|
||||
defaults: {
|
||||
name: {value:""},
|
||||
server: {type:"websocket-listener", validate: ws_validateserver},
|
||||
client: {type:"websocket-client", validate: ws_validateclient}
|
||||
},
|
||||
color:"rgb(215, 215, 160)",
|
||||
inputs:1,
|
||||
outputs:0,
|
||||
icon: "white-globe.png",
|
||||
align: "right",
|
||||
labelStyle: function() {
|
||||
return this.name?"node_label_italic":"";
|
||||
},
|
||||
label: ws_label,
|
||||
oneditsave: ws_oneditsave,
|
||||
oneditprepare: ws_oneditprepare
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- WebSocket Server configuration node -->
|
||||
<script type="text/x-red" data-template-name="websocket-listener">
|
||||
<div class="form-row">
|
||||
<label for="node-config-input-path"><i class="fa fa-bookmark"></i> Path</label>
|
||||
<input type="text" id="node-config-input-path" placeholder="/ws/example">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-config-input-wholemsg"> </label>
|
||||
<select type="text" id="node-config-input-wholemsg" style="width: 70%;">
|
||||
<option value="false">Send/Receive payload</option>
|
||||
<option value="true">Send/Receive entire message</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-tips">
|
||||
By default, <code>payload</code> will contain the data to be sent over, or received from a websocket.
|
||||
The listener can be configured to send or receive the entire message object as a JSON formatted string.
|
||||
<p id="node-config-ws-tip">This path will be relative to <code><span id="node-config-ws-path"></span></code>.</p>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="websocket-listener">
|
||||
<p>This configuration node creates a WebSocket Server using the specified path</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('websocket-listener',{
|
||||
category: 'config',
|
||||
defaults: {
|
||||
path: {value:"",required:true,validate:RED.validators.regex(/^((?!\/debug\/ws).)*$/) },
|
||||
wholemsg: {value:"false"}
|
||||
},
|
||||
inputs:0,
|
||||
outputs:0,
|
||||
label: function() {
|
||||
var root = RED.settings.httpNodeRoot;
|
||||
if (root.slice(-1) != "/") {
|
||||
root = root+"/";
|
||||
}
|
||||
if (this.path.charAt(0) == "/") {
|
||||
root += this.path.slice(1);
|
||||
} else {
|
||||
root += this.path;
|
||||
}
|
||||
return root;
|
||||
},
|
||||
oneditprepare: function() {
|
||||
var root = RED.settings.httpNodeRoot;
|
||||
if (root.slice(-1) == "/") {
|
||||
root = root.slice(0,-1);
|
||||
}
|
||||
if (root == "") {
|
||||
$("#node-config-ws-tip").hide();
|
||||
} else {
|
||||
$("#node-config-ws-path").html(root);
|
||||
$("#node-config-ws-tip").show();
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- WebSocket Client configuration node -->
|
||||
<script type="text/x-red" data-template-name="websocket-client">
|
||||
<div class="form-row">
|
||||
<label for="node-config-input-path"><i class="fa fa-bookmark"></i> URL</label>
|
||||
<input type="text" id="node-config-input-path" placeholder="ws://example.com/ws">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-config-input-wholemsg"> </label>
|
||||
<select type="text" id="node-config-input-wholemsg" style="width: 70%;">
|
||||
<option value="false">Send/Receive payload</option>
|
||||
<option value="true">Send/Receive entire message</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-tips">
|
||||
<p>URL should use ws:// or wss:// scheme and point to an existing websocket listener.</p>
|
||||
By default, <code>payload</code> will contain the data to be sent over, or received from a websocket.
|
||||
The client can be configured to send or receive the entire message object as a JSON formatted string.
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="websocket-client">
|
||||
<p>This configuration node connects a WebSocket client to the specified URL.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('websocket-client',{
|
||||
category: 'config',
|
||||
defaults: {
|
||||
path: {value:"",required:true,validate:RED.validators.regex(/^((?!\/debug\/ws).)*$/) },
|
||||
wholemsg: {value:"false"}
|
||||
},
|
||||
inputs:0,
|
||||
outputs:0,
|
||||
label: function() {
|
||||
return this.path;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<!--
|
||||
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/javascript">
|
||||
function ws_oneditprepare() {
|
||||
$("#websocket-client-row").hide();
|
||||
$("#node-input-mode").change(function(){
|
||||
if( $("#node-input-mode").val() === 'client') {
|
||||
$("#websocket-server-row").hide();
|
||||
$("#websocket-client-row").show();
|
||||
}
|
||||
else {
|
||||
$("#websocket-server-row").show();
|
||||
$("#websocket-client-row").hide();
|
||||
}
|
||||
});
|
||||
|
||||
if(this.client) {
|
||||
$("#node-input-mode").val('client').change();
|
||||
}
|
||||
else {
|
||||
$("#node-input-mode").val('server').change();
|
||||
}
|
||||
}
|
||||
|
||||
function ws_oneditsave() {
|
||||
if($("#node-input-mode").val() === 'client') {
|
||||
$("#node-input-server").append('<option value="">Dummy</option>');
|
||||
$("#node-input-server").val('');
|
||||
}
|
||||
else {
|
||||
$("#node-input-client").append('<option value="">Dummy</option>');
|
||||
$("#node-input-client").val('');
|
||||
}
|
||||
}
|
||||
|
||||
function ws_label() {
|
||||
var nodeid = (this.client)?this.client:this.server;
|
||||
var wsNode = RED.nodes.node(nodeid);
|
||||
return this.name||(wsNode?"[ws] "+wsNode.label():"websocket");
|
||||
}
|
||||
|
||||
function ws_validateserver() {
|
||||
if($("#node-input-mode").val() === 'client' || (this.client && !this.server)) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return RED.nodes.node(this.server) != null;
|
||||
}
|
||||
}
|
||||
|
||||
function ws_validateclient() {
|
||||
if($("#node-input-mode").val() === 'client' || (this.client && !this.server)) {
|
||||
return RED.nodes.node(this.client) != null;
|
||||
}
|
||||
else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<!-- WebSocket Input Node -->
|
||||
<script type="text/x-red" data-template-name="websocket in">
|
||||
<div class="form-row">
|
||||
<label for="node-input-mode"><i class="fa fa-dot-circle-o"></i> <span data-i18n="websocket.label.type"></span></label>
|
||||
<select id="node-input-mode">
|
||||
<option value="server" data-i18n="websocket.listenon"></option>
|
||||
<option value="client" data-i18n="websocket.connectto"></option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-row" id="websocket-server-row">
|
||||
<label for="node-input-server"><i class="fa fa-bookmark"></i> <span data-i18n="websocket.label.path"></span></label>
|
||||
<input type="text" id="node-input-server">
|
||||
</div>
|
||||
<div class="form-row" id="websocket-client-row">
|
||||
<label for="node-input-client"><i class="fa fa-bookmark"></i> <span data-i18n="websocket.label.url"></span></label>
|
||||
<input type="text" id="node-input-client">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
|
||||
<input type="text" id="node-input-name" data-i18n="[placeholder]common.label.nameph">
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="websocket in">
|
||||
<p>WebSocket input node.</p>
|
||||
<p>By default, the data received from the WebSocket will be in <b>msg.payload</b>.
|
||||
The socket can be configured to expect a properly formed JSON string, in which
|
||||
case it will parse the JSON and send on the resulting object as the entire message.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('websocket in',{
|
||||
category: 'input',
|
||||
defaults: {
|
||||
name: {value:""},
|
||||
server: {type:"websocket-listener", validate: ws_validateserver},
|
||||
client: {type:"websocket-client", validate: ws_validateclient}
|
||||
},
|
||||
color:"rgb(215, 215, 160)",
|
||||
inputs:0,
|
||||
outputs:1,
|
||||
icon: "white-globe.png",
|
||||
labelStyle: function() {
|
||||
return this.name?"node_label_italic":"";
|
||||
},
|
||||
label: ws_label,
|
||||
oneditsave: ws_oneditsave,
|
||||
oneditprepare: ws_oneditprepare
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- WebSocket out Node -->
|
||||
<script type="text/x-red" data-template-name="websocket out">
|
||||
<div class="form-row">
|
||||
<label for="node-input-mode"><i class="fa fa-dot-circle-o"></i> <span data-i18n="websocket.label.type"></span></label>
|
||||
<select id="node-input-mode">
|
||||
<option value="server" data-i18n="websocket.listenon"></option>
|
||||
<option value="client" data-i18n="websocket.connectto"></option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-row" id="websocket-server-row">
|
||||
<label for="node-input-server"><i class="fa fa-bookmark"></i> <span data-i18n="websocket.label.path"></span></label>
|
||||
<input type="text" id="node-input-server">
|
||||
</div>
|
||||
<div class="form-row" id="websocket-client-row">
|
||||
<label for="node-input-client"><i class="fa fa-bookmark"></i> <span data-i18n="websocket.label.url"></span></label>
|
||||
<input type="text" id="node-input-client">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
|
||||
<input type="text" id="node-input-name" data-i18n="[placeholder]common.label.nameph">
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="websocket out">
|
||||
<p>WebSocket out node.</p>
|
||||
<p>By default, <b>msg.payload</b> will be sent over the WebSocket. The socket
|
||||
can be configured to encode the entire message object as a JSON string and send that
|
||||
over the WebSocket.</p>
|
||||
|
||||
<p>If the message arriving at this node started at a WebSocket In node, the message
|
||||
will be sent back to the client that triggered the flow. Otherwise, the message
|
||||
will be broadcast to all connected clients.</p>
|
||||
<p>If you want to broadcast a message that started at a WebSocket In node, you
|
||||
should delete the <b>msg._session</b> property within the flow</p>.
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('websocket out',{
|
||||
category: 'output',
|
||||
defaults: {
|
||||
name: {value:""},
|
||||
server: {type:"websocket-listener", validate: ws_validateserver},
|
||||
client: {type:"websocket-client", validate: ws_validateclient}
|
||||
},
|
||||
color:"rgb(215, 215, 160)",
|
||||
inputs:1,
|
||||
outputs:0,
|
||||
icon: "white-globe.png",
|
||||
align: "right",
|
||||
labelStyle: function() {
|
||||
return this.name?"node_label_italic":"";
|
||||
},
|
||||
label: ws_label,
|
||||
oneditsave: ws_oneditsave,
|
||||
oneditprepare: ws_oneditprepare
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- WebSocket Server configuration node -->
|
||||
<script type="text/x-red" data-template-name="websocket-listener">
|
||||
<div class="form-row">
|
||||
<label for="node-config-input-path"><i class="fa fa-bookmark"></i> <span data-i18n="websocket.label.path"></span></label>
|
||||
<input type="text" id="node-config-input-path" data-i18n="[placeholder]websocket.label.pathph">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-config-input-wholemsg"> </label>
|
||||
<select type="text" id="node-config-input-wholemsg" style="width: 70%;">
|
||||
<option value="false" data-i18n="websocket.payload"></option>
|
||||
<option value="true" data-i18n="websocket.message"></option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-tips">
|
||||
<span data-i18n="[html]websocket.path-tip1"></span>
|
||||
<p id="node-config-ws-tip"><span data-i18n="[html]websocket.path-tip2"></span><code><span id="node-config-ws-path"></span></code>.</p>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="websocket-listener">
|
||||
<p>This configuration node creates a WebSocket Server using the specified path</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('websocket-listener',{
|
||||
category: 'config',
|
||||
defaults: {
|
||||
path: {value:"",required:true,validate:RED.validators.regex(/^((?!\/debug\/ws).)*$/) },
|
||||
wholemsg: {value:"false"}
|
||||
},
|
||||
inputs:0,
|
||||
outputs:0,
|
||||
label: function() {
|
||||
var root = RED.settings.httpNodeRoot;
|
||||
if (root.slice(-1) != "/") {
|
||||
root = root+"/";
|
||||
}
|
||||
if (this.path.charAt(0) == "/") {
|
||||
root += this.path.slice(1);
|
||||
} else {
|
||||
root += this.path;
|
||||
}
|
||||
return root;
|
||||
},
|
||||
oneditprepare: function() {
|
||||
var root = RED.settings.httpNodeRoot;
|
||||
if (root.slice(-1) == "/") {
|
||||
root = root.slice(0,-1);
|
||||
}
|
||||
if (root == "") {
|
||||
$("#node-config-ws-tip").hide();
|
||||
} else {
|
||||
$("#node-config-ws-path").html(root);
|
||||
$("#node-config-ws-tip").show();
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- WebSocket Client configuration node -->
|
||||
<script type="text/x-red" data-template-name="websocket-client">
|
||||
<div class="form-row">
|
||||
<label for="node-config-input-path"><i class="fa fa-bookmark"></i> <span data-i18n="websocket.label.url"></span></label>
|
||||
<input type="text" id="node-config-input-path" data-i18n="[placeholder]websocket.label.urlph">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-config-input-wholemsg"> </label>
|
||||
<select type="text" id="node-config-input-wholemsg" style="width: 70%;">
|
||||
<option value="false" data-i18n="websocket.payload"></option>
|
||||
<option value="true" data-i18n="websocket.message"></option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-tips">
|
||||
<p><span data-i18n="[html]websocket.url-tip1"></span></p>
|
||||
<span data-i18n="[html]websocket.url-tip2"></span>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="websocket-client">
|
||||
<p>This configuration node connects a WebSocket client to the specified URL.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('websocket-client',{
|
||||
category: 'config',
|
||||
defaults: {
|
||||
path: {value:"",required:true,validate:RED.validators.regex(/^((?!\/debug\/ws).)*$/) },
|
||||
wholemsg: {value:"false"}
|
||||
},
|
||||
inputs:0,
|
||||
outputs:0,
|
||||
label: function() {
|
||||
return this.path;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
@@ -1,232 +1,234 @@
|
||||
/**
|
||||
* Copyright 2013,2015 IBM Corp.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
module.exports = function(RED) {
|
||||
"use strict";
|
||||
var ws = require("ws");
|
||||
var inspect = require("sys").inspect;
|
||||
|
||||
// A node red node that sets up a local websocket server
|
||||
function WebSocketListenerNode(n) {
|
||||
// Create a RED node
|
||||
RED.nodes.createNode(this,n);
|
||||
var node = this;
|
||||
|
||||
// Store local copies of the node configuration (as defined in the .html)
|
||||
node.path = n.path;
|
||||
node.wholemsg = (n.wholemsg === "true");
|
||||
|
||||
node._inputNodes = []; // collection of nodes that want to receive events
|
||||
node._clients = {};
|
||||
// match absolute url
|
||||
node.isServer = !/^ws{1,2}:\/\//i.test(node.path);
|
||||
node.closing = false;
|
||||
|
||||
function startconn() { // Connect to remote endpoint
|
||||
var socket = new ws(node.path);
|
||||
node.server = socket; // keep for closing
|
||||
handleConnection(socket);
|
||||
}
|
||||
|
||||
function handleConnection(/*socket*/socket) {
|
||||
var id = (1+Math.random()*4294967295).toString(16);
|
||||
if (node.isServer) { node._clients[id] = socket; node.emit('opened',Object.keys(node._clients).length); }
|
||||
socket.on('open',function() {
|
||||
if (!node.isServer) { node.emit('opened',''); }
|
||||
});
|
||||
socket.on('close',function() {
|
||||
if (node.isServer) { delete node._clients[id]; node.emit('opened',Object.keys(node._clients).length); }
|
||||
else { node.emit('closed'); }
|
||||
if (!node.closing && !node.isServer) {
|
||||
node.tout = setTimeout(function(){ startconn(); }, 3000); // try to reconnect every 3 secs... bit fast ?
|
||||
}
|
||||
});
|
||||
socket.on('message',function(data,flags){
|
||||
node.handleEvent(id,socket,'message',data,flags);
|
||||
});
|
||||
socket.on('error', function(err) {
|
||||
node.emit('erro');
|
||||
if (!node.closing && !node.isServer) {
|
||||
node.tout = setTimeout(function(){ startconn(); }, 3000); // try to reconnect every 3 secs... bit fast ?
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (node.isServer) {
|
||||
var path = RED.settings.httpNodeRoot || "/";
|
||||
path = path + (path.slice(-1) == "/" ? "":"/") + (node.path.charAt(0) == "/" ? node.path.substring(1) : node.path);
|
||||
|
||||
// Workaround https://github.com/einaros/ws/pull/253
|
||||
// Listen for 'newListener' events from RED.server
|
||||
node._serverListeners = {};
|
||||
|
||||
var storeListener = function(/*String*/event,/*function*/listener){
|
||||
if(event == "error" || event == "upgrade" || event == "listening"){
|
||||
node._serverListeners[event] = listener;
|
||||
}
|
||||
}
|
||||
|
||||
RED.server.addListener('newListener',storeListener);
|
||||
|
||||
// Create a WebSocket Server
|
||||
node.server = new ws.Server({server:RED.server,path:path});
|
||||
|
||||
// Workaround https://github.com/einaros/ws/pull/253
|
||||
// Stop listening for new listener events
|
||||
RED.server.removeListener('newListener',storeListener);
|
||||
|
||||
node.server.on('connection', handleConnection);
|
||||
}
|
||||
else {
|
||||
node.closing = false;
|
||||
startconn(); // start outbound connection
|
||||
}
|
||||
|
||||
node.on("close", function() {
|
||||
// Workaround https://github.com/einaros/ws/pull/253
|
||||
// Remove listeners from RED.server
|
||||
if (node.isServer) {
|
||||
var listener = null;
|
||||
for (var event in node._serverListeners) {
|
||||
if (node._serverListeners.hasOwnProperty(event)) {
|
||||
listener = node._serverListeners[event];
|
||||
if (typeof listener === "function") {
|
||||
RED.server.removeListener(event,listener);
|
||||
}
|
||||
}
|
||||
}
|
||||
node._serverListeners = {};
|
||||
node.server.close();
|
||||
node._inputNodes = [];
|
||||
}
|
||||
else {
|
||||
node.closing = true;
|
||||
node.server.close();
|
||||
if (node.tout) { clearTimeout(tout); }
|
||||
}
|
||||
});
|
||||
}
|
||||
RED.nodes.registerType("websocket-listener",WebSocketListenerNode);
|
||||
RED.nodes.registerType("websocket-client",WebSocketListenerNode);
|
||||
|
||||
WebSocketListenerNode.prototype.registerInputNode = function(/*Node*/handler) {
|
||||
this._inputNodes.push(handler);
|
||||
}
|
||||
|
||||
WebSocketListenerNode.prototype.handleEvent = function(id,/*socket*/socket,/*String*/event,/*Object*/data,/*Object*/flags){
|
||||
var msg;
|
||||
if (this.wholemsg) {
|
||||
try {
|
||||
msg = JSON.parse(data);
|
||||
}
|
||||
catch(err) {
|
||||
msg = { payload:data };
|
||||
}
|
||||
} else {
|
||||
msg = {
|
||||
payload:data
|
||||
};
|
||||
}
|
||||
msg._session = {type:"websocket",id:id};
|
||||
for (var i = 0; i < this._inputNodes.length; i++) {
|
||||
this._inputNodes[i].send(msg);
|
||||
}
|
||||
}
|
||||
|
||||
WebSocketListenerNode.prototype.broadcast = function(data) {
|
||||
try {
|
||||
if(this.isServer) {
|
||||
for (var i = 0; i < this.server.clients.length; i++) {
|
||||
this.server.clients[i].send(data);
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.server.send(data);
|
||||
}
|
||||
}
|
||||
catch(e) { // swallow any errors
|
||||
this.warn("ws:"+i+" : "+e);
|
||||
}
|
||||
}
|
||||
|
||||
WebSocketListenerNode.prototype.reply = function(id,data) {
|
||||
var session = this._clients[id];
|
||||
if (session) {
|
||||
try {
|
||||
session.send(data);
|
||||
}
|
||||
catch(e) { // swallow any errors
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function WebSocketInNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.server = (n.client)?n.client:n.server;
|
||||
var node = this;
|
||||
this.serverConfig = RED.nodes.getNode(this.server);
|
||||
if (this.serverConfig) {
|
||||
this.serverConfig.registerInputNode(this);
|
||||
this.serverConfig.on('opened', function(n) { node.status({fill:"green",shape:"dot",text:"connected "+n}); });
|
||||
this.serverConfig.on('erro', function() { node.status({fill:"red",shape:"ring",text:"error"}); });
|
||||
this.serverConfig.on('closed', function() { node.status({fill:"red",shape:"ring",text:"disconnected"}); });
|
||||
} else {
|
||||
this.error("Missing server configuration");
|
||||
}
|
||||
}
|
||||
RED.nodes.registerType("websocket in",WebSocketInNode);
|
||||
|
||||
function WebSocketOutNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
var node = this;
|
||||
this.server = (n.client)?n.client:n.server;
|
||||
this.serverConfig = RED.nodes.getNode(this.server);
|
||||
if (!this.serverConfig) {
|
||||
this.error("Missing server configuration");
|
||||
}
|
||||
else {
|
||||
this.serverConfig.on('opened', function(n) { node.status({fill:"green",shape:"dot",text:"connected "+n}); });
|
||||
this.serverConfig.on('erro', function() { node.status({fill:"red",shape:"ring",text:"error"}); });
|
||||
this.serverConfig.on('closed', function() { node.status({fill:"red",shape:"ring",text:"disconnected"}); });
|
||||
}
|
||||
this.on("input", function(msg) {
|
||||
var payload;
|
||||
if (this.serverConfig.wholemsg) {
|
||||
delete msg._session;
|
||||
payload = JSON.stringify(msg);
|
||||
} else if (msg.hasOwnProperty("payload")) {
|
||||
if (!Buffer.isBuffer(msg.payload)) { // if it's not a buffer make sure it's a string.
|
||||
payload = RED.util.ensureString(msg.payload);
|
||||
}
|
||||
else {
|
||||
payload = msg.payload;
|
||||
}
|
||||
}
|
||||
if (payload) {
|
||||
if (msg._session && msg._session.type == "websocket") {
|
||||
node.serverConfig.reply(msg._session.id,payload);
|
||||
} else {
|
||||
node.serverConfig.broadcast(payload,function(error){
|
||||
if (!!error) {
|
||||
node.warn("An error occurred while sending:" + inspect(error));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
RED.nodes.registerType("websocket out",WebSocketOutNode);
|
||||
}
|
||||
/**
|
||||
* Copyright 2013,2015 IBM Corp.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
module.exports = function(RED) {
|
||||
"use strict";
|
||||
var ws = require("ws");
|
||||
var inspect = require("sys").inspect;
|
||||
|
||||
// A node red node that sets up a local websocket server
|
||||
function WebSocketListenerNode(n) {
|
||||
// Create a RED node
|
||||
RED.nodes.createNode(this,n);
|
||||
var node = this;
|
||||
|
||||
// Store local copies of the node configuration (as defined in the .html)
|
||||
node.path = n.path;
|
||||
node.wholemsg = (n.wholemsg === "true");
|
||||
|
||||
node._inputNodes = []; // collection of nodes that want to receive events
|
||||
node._clients = {};
|
||||
// match absolute url
|
||||
node.isServer = !/^ws{1,2}:\/\//i.test(node.path);
|
||||
node.closing = false;
|
||||
|
||||
function startconn() { // Connect to remote endpoint
|
||||
var socket = new ws(node.path);
|
||||
node.server = socket; // keep for closing
|
||||
handleConnection(socket);
|
||||
}
|
||||
|
||||
function handleConnection(/*socket*/socket) {
|
||||
var id = (1+Math.random()*4294967295).toString(16);
|
||||
if (node.isServer) { node._clients[id] = socket; node.emit('opened',Object.keys(node._clients).length); }
|
||||
socket.on('open',function() {
|
||||
if (!node.isServer) { node.emit('opened',''); }
|
||||
});
|
||||
socket.on('close',function() {
|
||||
if (node.isServer) { delete node._clients[id]; node.emit('opened',Object.keys(node._clients).length); }
|
||||
else { node.emit('closed'); }
|
||||
if (!node.closing && !node.isServer) {
|
||||
node.tout = setTimeout(function(){ startconn(); }, 3000); // try to reconnect every 3 secs... bit fast ?
|
||||
}
|
||||
});
|
||||
socket.on('message',function(data,flags){
|
||||
node.handleEvent(id,socket,'message',data,flags);
|
||||
});
|
||||
socket.on('error', function(err) {
|
||||
node.emit('erro');
|
||||
if (!node.closing && !node.isServer) {
|
||||
node.tout = setTimeout(function(){ startconn(); }, 3000); // try to reconnect every 3 secs... bit fast ?
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (node.isServer) {
|
||||
var path = RED.settings.httpNodeRoot || "/";
|
||||
path = path + (path.slice(-1) == "/" ? "":"/") + (node.path.charAt(0) == "/" ? node.path.substring(1) : node.path);
|
||||
|
||||
// Workaround https://github.com/einaros/ws/pull/253
|
||||
// Listen for 'newListener' events from RED.server
|
||||
node._serverListeners = {};
|
||||
|
||||
var storeListener = function(/*String*/event,/*function*/listener){
|
||||
if(event == "error" || event == "upgrade" || event == "listening"){
|
||||
node._serverListeners[event] = listener;
|
||||
}
|
||||
}
|
||||
|
||||
RED.server.addListener('newListener',storeListener);
|
||||
|
||||
// Create a WebSocket Server
|
||||
node.server = new ws.Server({server:RED.server,path:path});
|
||||
|
||||
// Workaround https://github.com/einaros/ws/pull/253
|
||||
// Stop listening for new listener events
|
||||
RED.server.removeListener('newListener',storeListener);
|
||||
|
||||
node.server.on('connection', handleConnection);
|
||||
}
|
||||
else {
|
||||
node.closing = false;
|
||||
startconn(); // start outbound connection
|
||||
}
|
||||
|
||||
node.on("close", function() {
|
||||
// Workaround https://github.com/einaros/ws/pull/253
|
||||
// Remove listeners from RED.server
|
||||
if (node.isServer) {
|
||||
var listener = null;
|
||||
for (var event in node._serverListeners) {
|
||||
if (node._serverListeners.hasOwnProperty(event)) {
|
||||
listener = node._serverListeners[event];
|
||||
if (typeof listener === "function") {
|
||||
RED.server.removeListener(event,listener);
|
||||
}
|
||||
}
|
||||
}
|
||||
node._serverListeners = {};
|
||||
node.server.close();
|
||||
node._inputNodes = [];
|
||||
}
|
||||
else {
|
||||
node.closing = true;
|
||||
node.server.close();
|
||||
if (node.tout) { clearTimeout(tout); }
|
||||
}
|
||||
});
|
||||
}
|
||||
RED.nodes.registerType("websocket-listener",WebSocketListenerNode);
|
||||
RED.nodes.registerType("websocket-client",WebSocketListenerNode);
|
||||
|
||||
WebSocketListenerNode.prototype.registerInputNode = function(/*Node*/handler) {
|
||||
this._inputNodes.push(handler);
|
||||
}
|
||||
|
||||
WebSocketListenerNode.prototype.handleEvent = function(id,/*socket*/socket,/*String*/event,/*Object*/data,/*Object*/flags){
|
||||
var msg;
|
||||
if (this.wholemsg) {
|
||||
try {
|
||||
msg = JSON.parse(data);
|
||||
}
|
||||
catch(err) {
|
||||
msg = { payload:data };
|
||||
}
|
||||
} else {
|
||||
msg = {
|
||||
payload:data
|
||||
};
|
||||
}
|
||||
msg._session = {type:"websocket",id:id};
|
||||
for (var i = 0; i < this._inputNodes.length; i++) {
|
||||
this._inputNodes[i].send(msg);
|
||||
}
|
||||
}
|
||||
|
||||
WebSocketListenerNode.prototype.broadcast = function(data) {
|
||||
try {
|
||||
if(this.isServer) {
|
||||
for (var i = 0; i < this.server.clients.length; i++) {
|
||||
this.server.clients[i].send(data);
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.server.send(data);
|
||||
}
|
||||
}
|
||||
catch(e) { // swallow any errors
|
||||
this.warn("ws:"+i+" : "+e);
|
||||
}
|
||||
}
|
||||
|
||||
WebSocketListenerNode.prototype.reply = function(id,data) {
|
||||
var session = this._clients[id];
|
||||
if (session) {
|
||||
try {
|
||||
session.send(data);
|
||||
}
|
||||
catch(e) { // swallow any errors
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function WebSocketInNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.server = (n.client)?n.client:n.server;
|
||||
var node = this;
|
||||
this.serverConfig = RED.nodes.getNode(this.server);
|
||||
if (this.serverConfig) {
|
||||
this.serverConfig.registerInputNode(this);
|
||||
// TODO: nls
|
||||
this.serverConfig.on('opened', function(n) { node.status({fill:"green",shape:"dot",text:"connected "+n}); });
|
||||
this.serverConfig.on('erro', function() { node.status({fill:"red",shape:"ring",text:"error"}); });
|
||||
this.serverConfig.on('closed', function() { node.status({fill:"red",shape:"ring",text:"disconnected"}); });
|
||||
} else {
|
||||
this.error(RED._("websocket.errors.missing-conf"));
|
||||
}
|
||||
}
|
||||
RED.nodes.registerType("websocket in",WebSocketInNode);
|
||||
|
||||
function WebSocketOutNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
var node = this;
|
||||
this.server = (n.client)?n.client:n.server;
|
||||
this.serverConfig = RED.nodes.getNode(this.server);
|
||||
if (!this.serverConfig) {
|
||||
this.error(RED._("websocket.errors.missing-conf"));
|
||||
}
|
||||
else {
|
||||
// TODO: nls
|
||||
this.serverConfig.on('opened', function(n) { node.status({fill:"green",shape:"dot",text:"connected "+n}); });
|
||||
this.serverConfig.on('erro', function() { node.status({fill:"red",shape:"ring",text:"error"}); });
|
||||
this.serverConfig.on('closed', function() { node.status({fill:"red",shape:"ring",text:"disconnected"}); });
|
||||
}
|
||||
this.on("input", function(msg) {
|
||||
var payload;
|
||||
if (this.serverConfig.wholemsg) {
|
||||
delete msg._session;
|
||||
payload = JSON.stringify(msg);
|
||||
} else if (msg.hasOwnProperty("payload")) {
|
||||
if (!Buffer.isBuffer(msg.payload)) { // if it's not a buffer make sure it's a string.
|
||||
payload = RED.util.ensureString(msg.payload);
|
||||
}
|
||||
else {
|
||||
payload = msg.payload;
|
||||
}
|
||||
}
|
||||
if (payload) {
|
||||
if (msg._session && msg._session.type == "websocket") {
|
||||
node.serverConfig.reply(msg._session.id,payload);
|
||||
} else {
|
||||
node.serverConfig.broadcast(payload,function(error){
|
||||
if (!!error) {
|
||||
node.warn(RED._("websocket.errors.send-error")+inspect(error));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
RED.nodes.registerType("websocket out",WebSocketOutNode);
|
||||
}
|
||||
|
@@ -16,14 +16,14 @@
|
||||
|
||||
<script type="text/x-red" data-template-name="watch">
|
||||
<div class="form-row node-input-filename">
|
||||
<label for="node-input-files"><i class="fa fa-file"></i> File(s)</label>
|
||||
<input type="text" id="node-input-files" placeholder="File(s) or Directory">
|
||||
<label for="node-input-files"><i class="fa fa-file"></i> <span data-i18n="watch.label.files"></span></label>
|
||||
<input type="text" id="node-input-files" data-i18n="[placeholder]watch.label.filesph">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||
<input type="text" id="node-input-name" placeholder="Name">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
|
||||
<input type="text" id="node-input-name" data-i18n="[placeholder]common.label.nameph">
|
||||
</div>
|
||||
<div id="node-input-tip" class="form-tips">On Windows you must use double back-slashes \\ in any directory names.</div>
|
||||
<div id="node-input-tip" class="form-tips"><span data-i18n="watch.tip"></span></div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="watch">
|
||||
|
@@ -16,43 +16,43 @@
|
||||
|
||||
<script type="text/x-red" data-template-name="tcp in">
|
||||
<div class="form-row">
|
||||
<label for="node-input-server"><i class="fa fa-dot-circle-o"></i> Type</label>
|
||||
<label for="node-input-server"><i class="fa fa-dot-circle-o"></i> <span data-i18n="tcpin.label.type"></span></label>
|
||||
<select id="node-input-server" style="width:120px; margin-right:5px;">
|
||||
<option value="server">Listen on</option>
|
||||
<option value="client">Connect to</option>
|
||||
<option value="server" data-i18n="tcpin.listen"></option>
|
||||
<option value="client" data-i18n="tcpin.connect"></option>
|
||||
</select>
|
||||
port <input type="text" id="node-input-port" style="width: 50px">
|
||||
<span data-i18n="tcpin.label.port"></span> <input type="text" id="node-input-port" style="width: 50px">
|
||||
</div>
|
||||
<div class="form-row hidden" id="node-input-host-row" style="padding-left: 110px;">
|
||||
at host <input type="text" id="node-input-host" placeholder="localhost" style="width: 60%;">
|
||||
<span data-i18n="tcpin.label.host"></span> <input type="text" id="node-input-host" placeholder="localhost" style="width: 60%;">
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<label><i class="fa fa-sign-out"></i> Output</label>
|
||||
a
|
||||
<label><i class="fa fa-sign-out"></i> <span data-i18n="tcpin.label.output"></span></label>
|
||||
<span data-i18n="tcpin.label.a"></span>
|
||||
<select id="node-input-datamode" style="width:110px;">
|
||||
<option value="stream">stream of</option>
|
||||
<option value="single">single</option>
|
||||
<option value="stream" data-i18n="tcpin.stream"></option>
|
||||
<option value="single" data-i18n="tcpin.single"></option>
|
||||
</select>
|
||||
<select id="node-input-datatype" style="width:140px;">
|
||||
<option value="buffer">Buffer</option>
|
||||
<option value="utf8">String</option>
|
||||
<option value="base64">Base64 String</option>
|
||||
<option value="buffer" data-i18n="tcpin.buffer"></option>
|
||||
<option value="utf8" data-i18n="tcpin.string"></option>
|
||||
<option value="base64" data-i18n="tcpin.base64"></option>
|
||||
</select>
|
||||
payload<span id="node-input-datamode-plural">s</span>
|
||||
<span data-i18n="tcpin.label.payload"></span>
|
||||
</div>
|
||||
|
||||
<div id="node-row-newline" class="form-row hidden" style="padding-left: 110px;">
|
||||
delimited by <input type="text" id="node-input-newline" style="width: 110px;">
|
||||
<span data-i18n="tcpin.label.delimited"></span> <input type="text" id="node-input-newline" style="width: 110px;">
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<label for="node-input-topic"><i class="fa fa-tasks"></i> Topic</label>
|
||||
<input type="text" id="node-input-topic" placeholder="Topic">
|
||||
<label for="node-input-topic"><i class="fa fa-tasks"></i> <span data-i18n="common.label.topic"></span></label>
|
||||
<input type="text" id="node-input-topic" data-i18n="[placeholder]common.label.topicph">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||
<input type="text" id="node-input-name" placeholder="Name">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
|
||||
<input type="text" id="node-input-name" data-i18n="[placeholder]common.label.nameph">
|
||||
</div>
|
||||
</script>
|
||||
|
||||
@@ -96,14 +96,12 @@
|
||||
var datamode = $("#node-input-datamode option:selected").val();
|
||||
var datatype = $("#node-input-datatype option:selected").val();
|
||||
if (datamode == "stream") {
|
||||
$("#node-input-datamode-plural").show();
|
||||
if (datatype == "utf8") {
|
||||
$("#node-row-newline").show();
|
||||
} else {
|
||||
$("#node-row-newline").hide();
|
||||
}
|
||||
} else {
|
||||
$("#node-input-datamode-plural").hide();
|
||||
$("#node-row-newline").hide();
|
||||
}
|
||||
};
|
||||
@@ -118,41 +116,41 @@
|
||||
|
||||
<script type="text/x-red" data-template-name="tcp out">
|
||||
<div class="form-row">
|
||||
<label for="node-input-beserver"><i class="fa fa-dot-circle-o"></i> Type</label>
|
||||
<label for="node-input-beserver"><i class="fa fa-dot-circle-o"></i> <span data-i18n="tcpin.label.type"></span></label>
|
||||
<select id="node-input-beserver" style="width:150px; margin-right:5px;">
|
||||
<option value="server">Listen on</option>
|
||||
<option value="client">Connect to</option>
|
||||
<option value="reply">Reply to TCP</option>
|
||||
<option value="server" data-i18n="tcpin.listen"></option>
|
||||
<option value="client" data-i18n="tcpin.connect"></option>
|
||||
<option value="reply" data-i18n="tcpin.reply"></option>
|
||||
</select>
|
||||
<span id="node-input-port-row">port <input type="text" id="node-input-port" style="width: 50px"></span>
|
||||
<span id="node-input-port-row"><span data-i18n="tcpin.label.port"></span> <input type="text" id="node-input-port" style="width: 50px"></span>
|
||||
</div>
|
||||
|
||||
<div class="form-row hidden" id="node-input-host-row" style="padding-left: 110px;">
|
||||
at host <input type="text" id="node-input-host" placeholder="localhost" style="width: 60%;">
|
||||
<span data-i18n="tcpin.label.host"></span> <input type="text" id="node-input-host" placeholder="localhost" style="width: 60%;">
|
||||
</div>
|
||||
|
||||
<div class="form-row hidden" id="node-input-end-row">
|
||||
<label> </label>
|
||||
<input type="checkbox" id="node-input-end" style="display: inline-block; width: auto; vertical-align: top;">
|
||||
<label for="node-input-end" style="width: 70%;">Close connection after each message is sent ?</label>
|
||||
<label for="node-input-end" style="width: 70%;"><span data-i18n="tcpin.label.close-connection"></span></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>
|
||||
<label for="node-input-base64" style="width: 70%;"><span data-i18n="tcpin.label.decode-base64"></span></label>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||
<input type="text" id="node-input-name" placeholder="Name">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
|
||||
<input type="text" id="node-input-name" data-i18n="[placeholder]common.label.nameph">
|
||||
</div>
|
||||
|
||||
<div class="form-tips hidden" id="fin-tip">
|
||||
<b>Note:</b> Closing the connection after each message is generally not a good thing - but is useful to indicate an end-of-file for example.
|
||||
<span data-i18n="[html]tcpin.out-tip1"></span>
|
||||
</div>
|
||||
<div class="form-tips hidden" id="fin-tip2">
|
||||
<b>Note:</b> Closing the connection after each message is generally not a good thing - but is useful to indicate an end-of-file for example. The receiving client will need to reconnect.
|
||||
<span data-i18n="[html]tcpin.out-tip2"></span>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
@@ -223,27 +221,26 @@
|
||||
|
||||
<script type="text/x-red" data-template-name="tcp request">
|
||||
<div class="form-row">
|
||||
<label for="node-input-server"><i class="fa fa-globe"></i> Server</label>
|
||||
<label for="node-input-server"><i class="fa fa-globe"></i> <span data-i18n="tcpin.label.server"></span></label>
|
||||
<input type="text" id="node-input-server" placeholder="ip.address" style="width:45%">
|
||||
port <input type="text" id="node-input-port" placeholder="number" style="width:60px">
|
||||
port <input type="text" id="node-input-port" data-i18n="[placeholder]tcpin.label.numberph" style="width:60px">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-out"><i class="fa fa-sign-out"></i> Return</label>
|
||||
<label for="node-input-out"><i class="fa fa-sign-out"></i> <span data-i18n="tcpin.label.return"></span></label>
|
||||
<select type="text" id="node-input-out" style="width:56%;">
|
||||
<option value="time">after a fixed timeout of</option>
|
||||
<option value="char">when character received is</option>
|
||||
<option value="count">a fixed number of characters</option>
|
||||
<option value="sit">never. Keep connection open</option>
|
||||
<option value="time" data-i18n="tcpin.timeout"></option>
|
||||
<option value="char" data-i18n="tcpin.character"></option>
|
||||
<option value="count" data-i18n="tcpin.number"></option>
|
||||
<option value="sit" data-i18n="tcpin.never"></option>
|
||||
</select>
|
||||
<input type="text" id="node-input-splitc" style="width:50px;">
|
||||
<span id="node-units"></span>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||
<input type="text" id="node-input-name" placeholder="Name">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
|
||||
<input type="text" id="node-input-name" data-i18n="[placeholder]common.label.nameph">
|
||||
</div>
|
||||
<div class="form-tips"><b>Tip:</b> Outputs a binary <b>Buffer</b>, so you may want to .toString() it.</br/>
|
||||
<b>Tip:</b> Leave host and port blank if you want to overide with msg.host and msg.port properties.</div>
|
||||
<div class="form-tips"><span data-i18n="[html]tcpin.req-tip"></span></div>
|
||||
<script>
|
||||
var previous = null;
|
||||
$("#node-input-out").on('focus', function () { previous = this.value; }).change(function() {
|
||||
|
@@ -43,14 +43,14 @@ module.exports = function(RED) {
|
||||
var reconnectTimeout;
|
||||
var end = false;
|
||||
var setupTcpClient = function() {
|
||||
node.log("connecting to "+node.host+":"+node.port);
|
||||
node.status({fill:"grey",shape:"dot",text:"connecting"});
|
||||
node.log(RED._("tcpin.errors.connecting-to")+" "+node.host+":"+node.port);
|
||||
node.status({fill:"grey",shape:"dot",text:RED._("common.status.connecting")});
|
||||
var id = (1+Math.random()*4294967295).toString(16);
|
||||
client = net.connect(node.port, node.host, function() {
|
||||
buffer = (node.datatype == 'buffer')? new Buffer(0):"";
|
||||
node.connected = true;
|
||||
node.log("connected to "+node.host+":"+node.port);
|
||||
node.status({fill:"green",shape:"dot",text:"connected"});
|
||||
node.log(RED._("tcpin.errors.connected-to")+" "+node.host+":"+node.port);
|
||||
node.status({fill:"green",shape:"dot",text:RED._("common.status.connected")});
|
||||
});
|
||||
connectionPool[id] = client;
|
||||
|
||||
@@ -96,14 +96,14 @@ module.exports = function(RED) {
|
||||
client.on('close', function() {
|
||||
delete connectionPool[id];
|
||||
node.connected = false;
|
||||
node.status({fill:"red",shape:"ring",text:"disconnected"});
|
||||
node.status({fill:"red",shape:"ring",text:RED._("common.status.disconnected")});
|
||||
if (!node.closing) {
|
||||
if (end) { // if we were asked to close then try to reconnect once very quick.
|
||||
end = false;
|
||||
reconnectTimeout = setTimeout(setupTcpClient, 20);
|
||||
}
|
||||
else {
|
||||
node.log("connection lost to "+node.host+":"+node.port);
|
||||
node.log(RED._("tcpin.errors.connection-lost")+" "+node.host+":"+node.port);
|
||||
reconnectTimeout = setTimeout(setupTcpClient, reconnectTime);
|
||||
}
|
||||
} else {
|
||||
@@ -128,7 +128,7 @@ module.exports = function(RED) {
|
||||
if (socketTimeout !== null) { socket.setTimeout(socketTimeout); }
|
||||
var id = (1+Math.random()*4294967295).toString(16);
|
||||
connectionPool[id] = socket;
|
||||
node.status({text:++count+" connections"});
|
||||
node.status({text:++count+" "+RED._("common.status.connections")});
|
||||
|
||||
var buffer = (node.datatype == 'buffer')? new Buffer(0):"";
|
||||
socket.on('data', function (data) {
|
||||
@@ -170,12 +170,12 @@ module.exports = function(RED) {
|
||||
}
|
||||
});
|
||||
socket.on('timeout', function() {
|
||||
node.log('timeout closed socket port '+node.port);
|
||||
node.log(RED._("tcpin.errors.timeout")+' '+node.port);
|
||||
socket.end();
|
||||
});
|
||||
socket.on('close', function() {
|
||||
delete connectionPool[id];
|
||||
node.status({text:--count+" connections"});
|
||||
node.status({text:--count+" "+RED._("common.status.connections")});
|
||||
});
|
||||
socket.on('error',function(err) {
|
||||
node.log(err);
|
||||
@@ -183,15 +183,15 @@ module.exports = function(RED) {
|
||||
});
|
||||
server.on('error', function(err) {
|
||||
if (err) {
|
||||
node.error('unable to listen on port '+node.port+' : '+err);
|
||||
node.error(RED._("tcpin.errors.cannot-listen")+' '+node.port+' : '+err);
|
||||
}
|
||||
});
|
||||
|
||||
server.listen(node.port, function(err) {
|
||||
if (err) {
|
||||
node.error('unable to listen on port '+node.port+' : '+err);
|
||||
node.error(RED._("tcpin.errors.cannot-listen")+' '+node.port+' : '+err);
|
||||
} else {
|
||||
node.log('listening on port '+node.port);
|
||||
node.log(RED._("tcpin.errors.listening-port")+' '+node.port);
|
||||
node.on('close', function() {
|
||||
for (var c in connectionPool) {
|
||||
if (connectionPool.hasOwnProperty(c)) {
|
||||
@@ -201,7 +201,7 @@ module.exports = function(RED) {
|
||||
}
|
||||
node.closing = true;
|
||||
server.close();
|
||||
node.log('stopped listening on port '+node.port);
|
||||
node.log(RED._("tcpin.errors.stopped-listening")+' '+node.port);
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -228,20 +228,20 @@ module.exports = function(RED) {
|
||||
var end = false;
|
||||
|
||||
var setupTcpClient = function() {
|
||||
node.log("connecting to "+node.host+":"+node.port);
|
||||
node.status({fill:"grey",shape:"dot",text:"connecting"});
|
||||
node.log(RED._("tcpin.errors.connecting-to")+" "+node.host+":"+node.port);
|
||||
node.status({fill:"grey",shape:"dot",text:RED._("common.status.connecting")});
|
||||
client = net.connect(node.port, node.host, function() {
|
||||
node.connected = true;
|
||||
node.log("connected to "+node.host+":"+node.port);
|
||||
node.status({fill:"green",shape:"dot",text:"connected"});
|
||||
node.log(RED._("tcpin.errors.connected-to")+" "+node.host+":"+node.port);
|
||||
node.status({fill:"green",shape:"dot",text:RED._("common.status.connected")});
|
||||
});
|
||||
client.on('error', function (err) {
|
||||
node.log(err);
|
||||
node.log(RED._("tcpin.errors.error")+' : '+err);
|
||||
});
|
||||
client.on('end', function (err) {
|
||||
});
|
||||
client.on('close', function() {
|
||||
node.status({fill:"red",shape:"ring",text:"disconnected"});
|
||||
node.status({fill:"red",shape:"ring",text:RED._("common.status.disconnected")});
|
||||
node.connected = false;
|
||||
client.destroy();
|
||||
if (!node.closing) {
|
||||
@@ -250,7 +250,7 @@ module.exports = function(RED) {
|
||||
reconnectTimeout = setTimeout(setupTcpClient,20);
|
||||
}
|
||||
else {
|
||||
node.log("connection lost to "+node.host+":"+node.port);
|
||||
node.log(RED._("tcpin.errors.connection-lost")+" "+node.host+":"+node.port);
|
||||
reconnectTimeout = setTimeout(setupTcpClient,reconnectTime);
|
||||
}
|
||||
} else {
|
||||
@@ -301,26 +301,26 @@ module.exports = function(RED) {
|
||||
});
|
||||
} else {
|
||||
var connectedSockets = [];
|
||||
node.status({text:"0 connections"});
|
||||
node.status({text:"0 "+RED._("common.status.connections")});
|
||||
var server = net.createServer(function (socket) {
|
||||
if (socketTimeout !== null) { socket.setTimeout(socketTimeout); }
|
||||
var remoteDetails = socket.remoteAddress+":"+socket.remotePort;
|
||||
node.log("connection from "+remoteDetails);
|
||||
node.log(RED._("tcpin.errors.connection-from")+" "+remoteDetails);
|
||||
connectedSockets.push(socket);
|
||||
node.status({text:connectedSockets.length+" connections"});
|
||||
node.status({text:connectedSockets.length+" "+RED._("common.status.connections")});
|
||||
socket.on('timeout', function() {
|
||||
node.log('timeout closed socket port '+node.port);
|
||||
node.log(RED._("tcpin.errors.timeout")+' '+node.port);
|
||||
socket.end();
|
||||
});
|
||||
socket.on('close',function() {
|
||||
node.log("connection closed from "+remoteDetails);
|
||||
node.log(RED._("tcpin.errors.connection-closed")+" "+remoteDetails);
|
||||
connectedSockets.splice(connectedSockets.indexOf(socket),1);
|
||||
node.status({text:connectedSockets.length+" connections"});
|
||||
node.status({text:connectedSockets.length+" "+RED._("common.status.connections")});
|
||||
});
|
||||
socket.on('error',function() {
|
||||
node.log("socket error from "+remoteDetails);
|
||||
node.log(RED._("tcpin.errors.socket-error")+" "+remoteDetails);
|
||||
connectedSockets.splice(connectedSockets.indexOf(socket),1);
|
||||
node.status({text:connectedSockets.length+" connections"});
|
||||
node.status({text:connectedSockets.length+" "+RED._("common.status.connections")});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -343,15 +343,15 @@ module.exports = function(RED) {
|
||||
|
||||
server.on('error', function(err) {
|
||||
if (err) {
|
||||
node.error('unable to listen on port '+node.port+' : '+err);
|
||||
node.error(RED._("tcpin.errors.cannot-listen")+' '+node.port+' : '+err);
|
||||
}
|
||||
});
|
||||
|
||||
server.listen(node.port, function(err) {
|
||||
if (err) {
|
||||
node.error('unable to listen on port '+node.port+' : '+err);
|
||||
node.error(RED._("tcpin.errors.cannot-listen")+' '+node.port+' : '+err);
|
||||
} else {
|
||||
node.log('listening on port '+node.port);
|
||||
node.log(RED._("tcpin.errors.listening-port")+' '+node.port);
|
||||
node.on('close', function() {
|
||||
for (var c in connectedSockets) {
|
||||
if (connectedSockets.hasOwnProperty(c)) {
|
||||
@@ -360,7 +360,7 @@ module.exports = function(RED) {
|
||||
}
|
||||
}
|
||||
server.close();
|
||||
node.log('stopped listening on port '+node.port);
|
||||
node.log(RED._("tcpin.errors.stopped-listening")+' '+node.port);
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -401,18 +401,17 @@ module.exports = function(RED) {
|
||||
|
||||
if (host && port) {
|
||||
client.connect(port, host, function() {
|
||||
//node.log('client connected');
|
||||
node.status({fill:"green",shape:"dot",text:"connected"});
|
||||
//node.log(RED._("tcpin.errors.client-connected"));
|
||||
node.status({fill:"green",shape:"dot",text:RED._("common.status.connected")});
|
||||
node.connected = true;
|
||||
client.write(msg.payload);
|
||||
});
|
||||
}
|
||||
else {
|
||||
node.warn("Host and/or port not set");
|
||||
node.warn(RED._("tcpin.errors.no-host"));
|
||||
}
|
||||
|
||||
client.on('data', function(data) {
|
||||
//node.log("data:"+ data.length+":"+ data);
|
||||
if (node.out == "sit") { // if we are staying connected just send the buffer
|
||||
node.send({"payload": data});
|
||||
}
|
||||
@@ -477,18 +476,17 @@ module.exports = function(RED) {
|
||||
});
|
||||
|
||||
client.on('error', function() {
|
||||
node.error('connect failed',msg);
|
||||
node.status({fill:"red",shape:"ring",text:"error"});
|
||||
node.error(RED._("tcpin.errors.connect-fail"),msg);
|
||||
node.status({fill:"red",shape:"ring",text:RED._("common.status.error")});
|
||||
if (client) { client.end(); }
|
||||
});
|
||||
|
||||
client.on('timeout',function() {
|
||||
node.warn('connect timeout');
|
||||
node.warn(RED._("tcpin.errors.timeout"));
|
||||
if (client) {
|
||||
client.end();
|
||||
setTimeout(function() {
|
||||
client.connect(port, host, function() {
|
||||
//node.log('client connected');
|
||||
node.connected = true;
|
||||
client.write(msg.payload);
|
||||
});
|
||||
|
@@ -17,54 +17,41 @@
|
||||
<!-- The Input Node -->
|
||||
<script type="text/x-red" data-template-name="udp in">
|
||||
<div class="form-row">
|
||||
<label for="node-input-port"><i class="fa fa-sign-in"></i> Listen for</label>
|
||||
<label for="node-input-port"><i class="fa fa-sign-in"></i> <span data-i18n="udp.label.listen"></span></label>
|
||||
<select id="node-input-multicast" style='width:62%'>
|
||||
<option value="false">udp messages</option>
|
||||
<option value="true">multicast messages</option>
|
||||
<option value="false" data-i18n="udp.udpmsgs"></option>
|
||||
<option value="true" data-i18n="udp.mcmsgs"></option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-row node-input-group">
|
||||
<label for="node-input-group"><i class="fa fa-list"></i> Group</label>
|
||||
<label for="node-input-group"><i class="fa fa-list"></i> <span data-i18n="udp.label.group"></span></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="fa fa-random"></i> Interface</label>
|
||||
<input type="text" id="node-input-iface" placeholder="(optional) ip address of eth0">
|
||||
<label for="node-input-iface"><i class="fa fa-random"></i> <span data-i18n="udp.label.interface"></span></label>
|
||||
<input type="text" id="node-input-iface" data-i18n="[placeholder]udp.label.interfaceph">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-port"><i class="fa fa-sign-in"></i> on Port</label>
|
||||
<input type="text" id="node-input-port" placeholder="Port" style="width: 80px">
|
||||
using <select id="node-input-ipv" style="width:80px">
|
||||
<label for="node-input-port"><i class="fa fa-sign-in"></i> <span data-i18n="udp.label.onport"></span></label>
|
||||
<input type="text" id="node-input-port" data-i18n="[placeholder]udp.label.onportph" style="width: 80px">
|
||||
<span data-i18n="udp.label.using"></span> <select id="node-input-ipv" style="width:80px">
|
||||
<option value="udp4">ipv4</option>
|
||||
<option value="udp6">ipv6</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-datatype"><i class="fa fa-sign-out"></i> Output</label>
|
||||
<label for="node-input-datatype"><i class="fa fa-sign-out"></i> <span data-i18n="udp.label.output"></span></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>
|
||||
<option value="buffer" data-i18n="udp.buffer"></option>
|
||||
<option value="utf8" data-i18n="udp.string"></option>
|
||||
<option value="base64" data-i18n="udp.base64"></option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||
<input type="text" id="node-input-name" placeholder="Name">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
|
||||
<input type="text" id="node-input-name" data-i18n="[placeholder]common.label.nameph">
|
||||
</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>
|
||||
<div class="form-tips"><span data-i18n="udp.in-tip"></span></div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="udp in">
|
||||
@@ -97,6 +84,20 @@
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name?"node_label_italic":"";
|
||||
},
|
||||
oneditprepare: function() {
|
||||
$("#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();
|
||||
}
|
||||
});
|
||||
$("#node-input-multicast").change();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@@ -105,62 +106,44 @@
|
||||
<!-- The Output Node -->
|
||||
<script type="text/x-red" data-template-name="udp out">
|
||||
<div class="form-row">
|
||||
<label for="node-input-port"><i class="fa fa-envelope"></i> Send a</label>
|
||||
<label for="node-input-port"><i class="fa fa-envelope"></i> <span data-i18n="udp.label.send"></span></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>
|
||||
<option value="false" data-i18n="udp.udpmsg"></option>
|
||||
<option value="broad" data-i18n="udp.bcmsg"></option>
|
||||
<option value="multi" data-i18n="udp.mcmsg"></option>
|
||||
</select>
|
||||
to port <input type="text" id="node-input-port" placeholder="port" style="width: 70px">
|
||||
<span data-i18n="udp.label.toport"></span> <input type="text" id="node-input-port" data-i18n="[placeholder]udp.label.toportph" style="width: 70px">
|
||||
</div>
|
||||
<div class="form-row node-input-addr">
|
||||
<label for="node-input-addr" id="node-input-addr-label"><i class="fa fa-list"></i> Address</label>
|
||||
<input type="text" id="node-input-addr" placeholder="destination ip" style="width: 50%;">
|
||||
<label for="node-input-addr" id="node-input-addr-label"><i class="fa fa-list"></i> <span data-i18n="udp.label.address"></span></label>
|
||||
<input type="text" id="node-input-addr" data-i18n="[placeholder]udp.label.addressph" style="width: 50%;">
|
||||
<select id="node-input-ipv" style="width:70px">
|
||||
<option value="udp4">ipv4</option>
|
||||
<option value="udp6">ipv6</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-row node-input-iface">
|
||||
<label for="node-input-iface"><i class="fa fa-random"></i> Interface</label>
|
||||
<input type="text" id="node-input-iface" placeholder="(optional) ip address of eth0">
|
||||
<label for="node-input-iface"><i class="fa fa-random"></i> <span data-i18n="udp.label.interface"></span></label>
|
||||
<input type="text" id="node-input-iface" data-i18n="[placeholder]udp.label.interfaceph">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-outport-type"> </label>
|
||||
<select id="node-input-outport-type">
|
||||
<option id="node-input-outport-type-random" value="random">use random local port</option>
|
||||
<option value="fixed">bind to local port</option>
|
||||
<option id="node-input-outport-type-random" value="random" data-i18n="udp.bindrandom"></option>
|
||||
<option value="fixed" data-i18n="udp.bindlocal"></option>
|
||||
</select>
|
||||
<input type="text" id="node-input-outport" style="width: 70px;" placeholder="port">
|
||||
<input type="text" id="node-input-outport" style="width: 70px;" data-i18n="[placeholder]udp.label.outportph">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label> </label>
|
||||
<input type="checkbox" id="node-input-base64" style="display: inline-block; width: auto; vertical-align: top;">
|
||||
<label for="node-input-base64" style="width: 70%;">Decode Base64 encoded payload ?</label>
|
||||
<label for="node-input-base64" style="width: 70%;"><span data-i18n="udp.label.decode-base64"></span></label>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||
<input type="text" id="node-input-name" placeholder="Name">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
|
||||
<input type="text" id="node-input-name" data-i18n="[placeholder]common.label.nameph">
|
||||
</div>
|
||||
<div class="form-tips">Tip: leave address and port blank if you want to set using <b>msg.ip</b> and <b>msg.port</b>.</div>
|
||||
<script>
|
||||
$("#node-input-multicast").change(function() {
|
||||
var id = $("#node-input-multicast option:selected").val();
|
||||
if (id !== "multi") {
|
||||
$(".node-input-iface").hide();
|
||||
$("#node-input-addr-label").html('<i class="fa fa-list"></i> Address');
|
||||
$("#node-input-addr")[0].placeholder = 'destination ip';
|
||||
}
|
||||
else {
|
||||
$(".node-input-iface").show();
|
||||
$("#node-input-addr-label").html('<i class="fa fa-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>
|
||||
<div class="form-tips"><span data-i18n="[html]udp.out-tip"></span></div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="udp out">
|
||||
@@ -195,6 +178,12 @@
|
||||
return this.name?"node_label_italic":"";
|
||||
},
|
||||
oneditprepare: function() {
|
||||
var addresslabel = this._("udp.label.address");
|
||||
var addressph = this._("udp.label.addressph");
|
||||
var grouplabel = this._("udp.label.group");
|
||||
var bindrandom = this._("udp.bindrandom");
|
||||
var bindtarget = this._("udp.bindtarget");
|
||||
|
||||
var type = this.outport==""?"random":"fixed";
|
||||
$("#node-input-outport-type option").filter(function() {
|
||||
return $(this).val() == type;
|
||||
@@ -208,15 +197,30 @@
|
||||
$("#node-input-outport").show();
|
||||
}
|
||||
});
|
||||
|
||||
$("#node-input-outport-type").change();
|
||||
|
||||
$("#node-input-multicast").change(function() {
|
||||
var id = $("#node-input-multicast option:selected").val();
|
||||
if (id === "multi") {
|
||||
$(".node-input-iface").show();
|
||||
$("#node-input-addr-label").html('<i class="fa fa-list"></i> ' + grouplabel);
|
||||
$("#node-input-addr")[0].placeholder = '225.0.18.83';
|
||||
}
|
||||
else if (id === "broad") {
|
||||
$(".node-input-iface").hide();
|
||||
$("#node-input-addr-label").html('<i class="fa fa-list"></i> ' + addresslabel);
|
||||
$("#node-input-addr")[0].placeholder = '255.255.255.255';
|
||||
}
|
||||
else {
|
||||
$(".node-input-iface").hide();
|
||||
$("#node-input-addr-label").html('<i class="fa fa-list"></i> ' + addresslabel);
|
||||
$("#node-input-addr")[0].placeholder = addressph;
|
||||
}
|
||||
var type = $(this).children("option:selected").val();
|
||||
if (type == "false") {
|
||||
$("#node-input-outport-type-random").html("bind to random local port");
|
||||
$("#node-input-outport-type-random").html(bindrandom);
|
||||
} else {
|
||||
$("#node-input-outport-type-random").html("bind to target port");
|
||||
$("#node-input-outport-type-random").html(bindtarget);
|
||||
}
|
||||
});
|
||||
$("#node-input-multicast").change();
|
||||
|
@@ -33,9 +33,9 @@ module.exports = function(RED) {
|
||||
|
||||
server.on("error", function (err) {
|
||||
if ((err.code == "EACCES") && (node.port < 1024)) {
|
||||
node.error("UDP access error, you may need root access for ports below 1024");
|
||||
node.error(RED._("udp.errors.access-error"));
|
||||
} else {
|
||||
node.error("UDP error : "+err.code);
|
||||
node.error(RED._("udp.errors.udp-error")+" : "+err.code);
|
||||
}
|
||||
server.close();
|
||||
});
|
||||
@@ -54,20 +54,20 @@ module.exports = function(RED) {
|
||||
|
||||
server.on('listening', function () {
|
||||
var address = server.address();
|
||||
node.log('udp listener at ' + address.address + ":" + address.port);
|
||||
node.log(RED._("udp.errors.listener-at") + ' ' + address.address + ":" + address.port);
|
||||
if (node.multicast == "true") {
|
||||
server.setBroadcast(true);
|
||||
try {
|
||||
server.setMulticastTTL(128);
|
||||
server.addMembership(node.group,node.iface);
|
||||
node.log("udp multicast group "+node.group);
|
||||
node.log(RED._("udp.errors.mc-group")+" "+node.group);
|
||||
} catch (e) {
|
||||
if (e.errno == "EINVAL") {
|
||||
node.error("Bad Multicast Address");
|
||||
node.error(RED._("udp.errors.bad-mcaddress"));
|
||||
} else if (e.errno == "ENODEV") {
|
||||
node.error("Must be ip address of the required interface");
|
||||
node.error(RED._("udp.errors.interface"));
|
||||
} else {
|
||||
node.error("Error :"+e.errno);
|
||||
node.error(RED._("udp.errors.error")+" :"+e.errno);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -76,7 +76,7 @@ module.exports = function(RED) {
|
||||
node.on("close", function() {
|
||||
try {
|
||||
server.close();
|
||||
node.log('udp listener stopped');
|
||||
node.log(RED._("udp.errors.listener-stopped"));
|
||||
} catch (err) {
|
||||
node.error(err);
|
||||
}
|
||||
@@ -118,25 +118,25 @@ module.exports = function(RED) {
|
||||
try {
|
||||
sock.setMulticastTTL(128);
|
||||
sock.addMembership(node.addr,node.iface); // Add to the multicast group
|
||||
node.log('udp multicast ready : '+node.outport+' -> '+node.addr+":"+node.port);
|
||||
node.log(RED._("udp.errors.mc-ready")+' : '+node.outport+' -> '+node.addr+":"+node.port);
|
||||
} catch (e) {
|
||||
if (e.errno == "EINVAL") {
|
||||
node.error("Bad Multicast Address");
|
||||
node.error(RED._("udp.errors.bad-mcaddress"));
|
||||
} else if (e.errno == "ENODEV") {
|
||||
node.error("Must be ip address of the required interface");
|
||||
node.error(RED._("udp.errors.interface"));
|
||||
} else {
|
||||
node.error("Error :"+e.errno);
|
||||
node.error(RED._("udp.errors.error")+" :"+e.errno);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
node.log('udp broadcast ready : '+node.outport+' -> '+node.addr+":"+node.port);
|
||||
node.log(RED._("udp.errors.bc-ready")+' : '+node.outport+' -> '+node.addr+":"+node.port);
|
||||
}
|
||||
});
|
||||
} else if (node.outport != "") {
|
||||
sock.bind(node.outport);
|
||||
node.log('udp ready : '+node.outport+' -> '+node.addr+":"+node.port);
|
||||
node.log(RED._("udp.errors.ready")+' : '+node.outport+' -> '+node.addr+":"+node.port);
|
||||
} else {
|
||||
node.log('udp ready : '+node.addr+":"+node.port);
|
||||
node.log(RED._("udp.errors.ready")+' : '+node.addr+":"+node.port);
|
||||
}
|
||||
|
||||
node.on("input", function(msg) {
|
||||
@@ -144,11 +144,11 @@ module.exports = function(RED) {
|
||||
var add = node.addr || msg.ip || "";
|
||||
var por = node.port || msg.port || 0;
|
||||
if (add == "") {
|
||||
node.warn("udp: ip address not set");
|
||||
node.warn(RED._("udp.errors.ip-notset"));
|
||||
} else if (por == 0) {
|
||||
node.warn("udp: port not set");
|
||||
node.warn(RED._("udp.errors.port-notset"));
|
||||
} else if (isNaN(por) || (por < 1) || (por > 65535)) {
|
||||
node.warn("udp: port number not valid");
|
||||
node.warn(RED._("udp.errors.port-invalid"));
|
||||
} else {
|
||||
var message;
|
||||
if (node.base64) {
|
||||
@@ -171,7 +171,7 @@ module.exports = function(RED) {
|
||||
node.on("close", function() {
|
||||
try {
|
||||
sock.close();
|
||||
node.log('udp output stopped');
|
||||
node.log(RED._("udp.errors.output-stopped"));
|
||||
} catch (err) {
|
||||
node.error(err);
|
||||
}
|
||||
|
Reference in New Issue
Block a user