mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
Update mqtt node options to include will/cleansession/keepalive
This commit is contained in:
parent
437b2d506b
commit
fa5e37993e
@ -30,8 +30,6 @@
|
||||
<p>MQTT input node. Connects to a broker and subscribes to the specified topic. The topic may contain MQTT wildcards.</p>
|
||||
<p>Outputs an object called <b>msg</b> containing <b>msg.topic, msg.payload, msg.qos</b> and <b>msg.retain</b>.</p>
|
||||
<p><b>msg.payload</b> is usually a string, but can also be a binary buffer.</p>
|
||||
<p>If a secure connection is being used, certificate checking can be disabled to allow connections to brokers using a self signed or non-trusted CA certificate.</p>
|
||||
<p>Compatibility mode allows connections to brokers which do not support the MQTT V3.1.1 standard.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
@ -89,9 +87,6 @@
|
||||
<p>Connects to a MQTT broker and publishes <b>msg.payload</b> either to the <b>msg.topic</b> or to the topic specified in the edit window. The value in the edit window has precedence.</p>
|
||||
<p>Likewise QoS and/or retain values in the edit panel will overwrite any <b>msg.qos</b> and <b>msg.retain</b> properties. If nothing is set they default to <i>0</i> and <i>false</i> respectively.</p>
|
||||
<p>If <b>msg.payload</b> contains an object it will be stringified before being sent.</p>
|
||||
<p>If a secure connection is being used, certificate checking can be disabled to allow connections to brokers using a self signed or non-trusted CA certificate.</p>
|
||||
<p>Compatibility mode allows connections to brokers which do not support the MQTT V3.1.1 standard.</p>
|
||||
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
@ -119,39 +114,77 @@
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-template-name="mqtt-broker">
|
||||
<div class="form-row node-input-broker">
|
||||
<label for="node-config-input-broker"><i class="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; "> <span data-i18n="mqtt.label.port"></span></label>
|
||||
<input type="text" id="node-config-input-port" data-i18n="[placeholder]mqtt.label.port" style="width:45px">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label> </label>
|
||||
<input type="checkbox" id="node-config-input-secureconn" style="display: inline-block; width: auto; vertical-align: top;">
|
||||
<label for="node-config-input-secureconn" style="width: 70%;">Enable secure (SSL/TLS) connection</label>
|
||||
<ul style="background: #fff; min-width: 550px; margin-bottom: 20px;" id="node-config-mqtt-broker-tabs"></ul>
|
||||
</div>
|
||||
<div class="form-row" id="row-disablecertauth">
|
||||
<label> </label>
|
||||
<input type="checkbox" id="node-config-input-disablecertauth" style="display: inline-block; width: auto; vertical-align: top;">
|
||||
<label for="node-config-input-disablecertauth" style="width: 70%;">Disable certificate authentication (secure connections only)</label>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label> </label>
|
||||
<input type="checkbox" id="node-config-input-compatmode" style="display: inline-block; width: auto; vertical-align: top;">
|
||||
<label for="node-config-input-compatmode" style="width: 70%;">Compatibility for brokers not supporting MQTT v3.1.1</label>
|
||||
</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">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<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> <span data-i18n="common.label.password"></span></label>
|
||||
<input type="password" id="node-config-input-password">
|
||||
<div id="node-config-mqtt-broker-tabs-content" style="min-height: 170px;">
|
||||
<div id="mqtt-broker-tab-connection" style="display:none">
|
||||
<div class="form-row node-input-broker">
|
||||
<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; "> <span data-i18n="mqtt.label.port"></span></label>
|
||||
<input type="text" id="node-config-input-port" data-i18n="[placeholder]mqtt.label.port" style="width:45px">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<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.placeholder.clientid">
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<label for="node-config-input-keepalive" style="width: auto"><i class="fa fa-clock-o"></i> <span data-i18n="mqtt.label.keepalive"></span></label>
|
||||
<input type="text" id="node-config-input-keepalive" style="width: 50px">
|
||||
<input type="checkbox" id="node-config-input-cleansession" style="margin-left: 30px; height: 1em;display: inline-block; width: auto; vertical-align: middle;">
|
||||
<label for="node-config-input-cleansession" style="width: auto;" data-i18n="mqtt.label.cleansession"></label>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<input type="checkbox" id="node-config-input-compatmode" style="display: inline-block; width: auto; vertical-align: top;">
|
||||
<label for="node-config-input-compatmode" style="width: auto;" data-i18n="mqtt.label.compatmode"></label>
|
||||
</div>
|
||||
</div>
|
||||
<div id="mqtt-broker-tab-security" style="display:none">
|
||||
<div class="form-row">
|
||||
<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> <span data-i18n="common.label.password"></span></label>
|
||||
<input type="password" id="node-config-input-password">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<input type="checkbox" id="node-config-input-usetls" style="display: inline-block; width: auto; vertical-align: top;">
|
||||
<label for="node-config-input-usetls" style="width: 70%;" data-i18n="mqtt.label.use-tls"></label>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<input type="checkbox" id="node-config-input-verifyservercert" style="display: inline-block; width: auto; vertical-align: top;">
|
||||
<label for="node-config-input-verifyservercert" style="width: 70%;" data-i18n="mqtt.label.verify-server-cert"></label>
|
||||
</div>
|
||||
</div>
|
||||
<div id="mqtt-broker-tab-will" style="display:none">
|
||||
<div class="form-row">
|
||||
<label for="node-config-input-willTopic"><i class="fa fa-tasks"></i> <span data-i18n="common.label.topic"></span></label>
|
||||
<input type="text" id="node-config-input-willTopic" data-i18n="[placeholder]mqtt.placeholder.will-topic">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-config-input-willQos"><i class="fa fa-empire"></i> <span data-i18n="mqtt.label.qos"></span></label>
|
||||
<select id="node-config-input-willQos" style="width:125px !important">
|
||||
<option value="0">0</option>
|
||||
<option value="1">1</option>
|
||||
<option value="2">2</option>
|
||||
</select>
|
||||
<i class="fa fa-history"></i> <span data-i18n="mqtt.retain"></span> <select id="node-config-input-willRetain" style="width:125px !important">
|
||||
<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-config-input-willPayload"><i class="fa fa-envelope"></i> <span data-i18n="common.label.payload"></span></label>
|
||||
<input type="text" id="node-config-input-willPayload" data-i18n="[placeholder]common.label.payload">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
@ -160,11 +193,23 @@
|
||||
defaults: {
|
||||
broker: {value:"",required:true},
|
||||
port: {value:1883,required:true,validate:RED.validators.number()},
|
||||
clientid: { value:"" },
|
||||
secureconn: {value: false},
|
||||
disablecertauth: { value: false},
|
||||
clientid: { value:"", validate: function(v) {
|
||||
if ($("#node-config-input-clientid").length) {
|
||||
// Currently editing the node
|
||||
return $("#node-config-input-cleansession").is(":checked") || v.length > 0;
|
||||
} else {
|
||||
return this.cleansession || v.length > 0;
|
||||
}
|
||||
}},
|
||||
usetls: {value: false},
|
||||
verifyservercert: { value: false},
|
||||
compatmode: { value: true},
|
||||
mqttkeepalive: {value:15}
|
||||
keepalive: {value:15,validate:RED.validators.number()},
|
||||
cleansession: {value: true},
|
||||
willTopic: {value:""},
|
||||
willQos: {value:0},
|
||||
willRetain: {value:false},
|
||||
willPayload: {value:""}
|
||||
},
|
||||
credentials: {
|
||||
user: {type:"text"},
|
||||
@ -175,32 +220,67 @@
|
||||
return (this.clientid?this.clientid+"@":"")+this.broker+":"+this.port;
|
||||
},
|
||||
oneditprepare: function () {
|
||||
if (this.broker && typeof this.secureconn === 'undefined'){
|
||||
this.secureconn = false;
|
||||
var tabs = RED.tabs.create({
|
||||
id: "node-config-mqtt-broker-tabs",
|
||||
onchange: function(tab) {
|
||||
$("#node-config-mqtt-broker-tabs-content").children().hide();
|
||||
$("#" + tab.id).show();
|
||||
}
|
||||
});
|
||||
tabs.addTab({
|
||||
id: "mqtt-broker-tab-connection",
|
||||
label: this._("mqtt.tabs-label.connection")
|
||||
});
|
||||
tabs.addTab({
|
||||
id: "mqtt-broker-tab-security",
|
||||
label: this._("mqtt.tabs-label.security")
|
||||
});
|
||||
tabs.addTab({
|
||||
id: "mqtt-broker-tab-will",
|
||||
label: this._("mqtt.tabs-label.will")
|
||||
});
|
||||
setTimeout(function() { tabs.resize()},0);
|
||||
if (typeof this.usetls === 'undefined'){
|
||||
this.usetls = false;
|
||||
$("#node-config-input-usetls").prop("checked",false);
|
||||
}
|
||||
if (this.broker && typeof this.disablecertauth === 'undefined'){
|
||||
this.disablecertauth = false;
|
||||
if (typeof this.verifyservercert === 'undefined'){
|
||||
this.verifyservercert = true;
|
||||
$("#node-config-input-verifyservercert").prop("checked",true);
|
||||
}
|
||||
if (this.broker && typeof this.compatmode === 'undefined'){
|
||||
if (typeof this.compatmode === 'undefined'){
|
||||
this.compatmode = true;
|
||||
$("#node-config-input-compatmode").prop('checked', true);
|
||||
}
|
||||
if (this.broker && typeof this.mqttkeepalive === 'undefined'){
|
||||
this.mqttkeepalive = 15;
|
||||
if (typeof this.keepalive === 'undefined'){
|
||||
this.keepalive = 15;
|
||||
}
|
||||
|
||||
if (this.secureconn == true) {
|
||||
$("#row-disablecertauth").show();
|
||||
} else {
|
||||
$("#row-disablecertauth").hide();
|
||||
}
|
||||
|
||||
$("#node-config-input-secureconn").on("click",function() {
|
||||
if($(this).is(':checked')) {
|
||||
$("#row-disablecertauth").show();
|
||||
function updateTLSOptions() {
|
||||
if ($("#node-config-input-usetls").is(':checked')) {
|
||||
$("#node-config-input-verifyservercert").prop("disabled", false);
|
||||
$("#node-config-input-verifyservercert").next().css("color","");
|
||||
} else {
|
||||
$("#row-disablecertauth").hide();
|
||||
$("#node-config-input-verifyservercert").prop("disabled", true);
|
||||
$("#node-config-input-verifyservercert").next().css("color","#aaa");
|
||||
}
|
||||
}
|
||||
updateTLSOptions();
|
||||
$("#node-config-input-usetls").on("click",function() {
|
||||
updateTLSOptions();
|
||||
});
|
||||
var node = this;
|
||||
function updateClientId() {
|
||||
if ($("#node-config-input-cleansession").is(":checked")) {
|
||||
$("#node-config-input-clientid").attr("placeholder",node._("mqtt.placeholder.clientid"));
|
||||
} else {
|
||||
$("#node-config-input-clientid").attr("placeholder",node._("mqtt.placeholder.clientid-nonclean"));
|
||||
}
|
||||
$("#node-config-input-clientid").change();
|
||||
}
|
||||
setTimeout(updateClientId,0);
|
||||
$("#node-config-input-cleansession").on("click",function() {
|
||||
updateClientId();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -36,17 +36,17 @@ module.exports = function(RED) {
|
||||
this.broker = n.broker;
|
||||
this.port = n.port;
|
||||
this.clientid = n.clientid;
|
||||
this.secureconn = n.secureconn;
|
||||
this.disablecertauth = n.disablecertauth;
|
||||
this.usetls = n.usetls;
|
||||
this.verifyservercert = n.verifyservercert;
|
||||
this.compatmode = n.compatmode;
|
||||
this.mqttkeepalive = n.mqttkeepalive;
|
||||
this.keepalive = n.keepalive;
|
||||
this.cleansession = n.cleansession;
|
||||
|
||||
// Config node state
|
||||
this.brokerurl = "";
|
||||
this.connected = false;
|
||||
this.connecting = false;
|
||||
this.usecount = 0;
|
||||
this.logdisconnect = true;
|
||||
this.options = {};
|
||||
this.queue = [];
|
||||
this.subscriptions = {};
|
||||
@ -61,22 +61,27 @@ module.exports = function(RED) {
|
||||
|
||||
// If the config node is missing certain options (it was probably deployed prior to an update to the node code),
|
||||
// select/generate sensible options for the new fields
|
||||
if (typeof this.secureconn === 'undefined'){
|
||||
this.secureconn = false;
|
||||
if (typeof this.usetls === 'undefined'){
|
||||
this.usetls = false;
|
||||
}
|
||||
if (typeof this.compatmode === 'undefined'){
|
||||
this.compatmode = true;
|
||||
}
|
||||
if (typeof this.disablecertauth === 'undefined'){
|
||||
this.disablecertauth = false;
|
||||
if (typeof this.verifyservercert === 'undefined'){
|
||||
this.verifyservercert = false;
|
||||
}
|
||||
if (typeof this.mqttkeepalive === 'undefined'){
|
||||
this.mqttkeepalive = 15;
|
||||
if (typeof this.keepalive === 'undefined'){
|
||||
this.keepalive = 15;
|
||||
} else if (typeof this.keepalive === 'string') {
|
||||
this.keepalive = Number(this.keepalive);
|
||||
}
|
||||
if (typeof this.cleansession === 'undefined') {
|
||||
this.cleansession = true;
|
||||
}
|
||||
|
||||
// Create the URL to pass in to the MQTT.js library
|
||||
if (this.brokerurl == "") {
|
||||
if (this.secureconn) {
|
||||
if (this.usetls) {
|
||||
this.brokerurl="mqtts://";
|
||||
} else {
|
||||
this.brokerurl="mqtt://";
|
||||
@ -88,22 +93,32 @@ module.exports = function(RED) {
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.cleansession && !this.clientid) {
|
||||
this.cleansession = true;
|
||||
this.warn(RED._("mqtt.errors.nonclean-missingclientid"));
|
||||
}
|
||||
|
||||
// Build options for passing to the MQTT.js API
|
||||
this.options.clientId = this.clientid || 'mqtt_' + (1+Math.random()*4294967295).toString(16);
|
||||
this.options.username = this.username;
|
||||
this.options.password = this.password;
|
||||
this.options.keepalive = this.mqttkeepalive;
|
||||
this.options.reconnectPeriod = 5000;
|
||||
this.options.keepalive = this.keepalive;
|
||||
this.options.clean = this.clean;
|
||||
this.options.reconnectPeriod = RED.settings.mqttReconnectTime||5000;
|
||||
if (this.compatmode == "true" || this.compatmode === true){
|
||||
this.log('Using compatibility mode for non-MQTT v3.1.1 brokers');
|
||||
this.options.protocolId = 'MQIsdp';
|
||||
this.options.protocolVersion = 3;
|
||||
}
|
||||
if (this.disablecertauth == "true" || this.disablecertauth === true) {
|
||||
this.log(' Warning: Certificate checking is disabled for this connection');
|
||||
this.options.rejectUnauthorized = false;
|
||||
} else {
|
||||
this.options.rejectUnauthorized = true;
|
||||
|
||||
this.options.rejectUnauthorized = (this.verifyservercert == "true" || this.verifyservercert === true)
|
||||
|
||||
if (n.willTopic) {
|
||||
this.options.will = {
|
||||
topic: n.willTopic,
|
||||
payload: n.willPayload || "",
|
||||
qos: Number(n.willQos||0),
|
||||
retain: n.willRetain=="true"|| n.willRetain===true
|
||||
};
|
||||
}
|
||||
|
||||
// Define functions called by MQTT in and out nodes
|
||||
@ -123,12 +138,10 @@ module.exports = function(RED) {
|
||||
if (!node.connected && !node.connecting) {
|
||||
node.connecting = true;
|
||||
node.client = mqtt.connect(node.brokerurl ,node.options);
|
||||
|
||||
// Register successful connect or reconnect handler
|
||||
node.client.on('connect', function () {
|
||||
node.connected = true;
|
||||
node.logdisconnect = true;
|
||||
node.log("Connected to broker: "+(node.clientid?node.clientid+"@":"")+node.brokerurl);
|
||||
node.log(RED._("mqtt.state.connected",{broker:(node.clientid?node.clientid+"@":"")+node.brokerurl}));
|
||||
node.emit('connected');
|
||||
|
||||
// Remove any existing listeners before resubscribing to avoid duplicates in the event of a re-connection
|
||||
@ -156,26 +169,18 @@ module.exports = function(RED) {
|
||||
|
||||
// Register disconnect handlers
|
||||
node.client.on('close', function () {
|
||||
if (node.connected && node.logdisconnect ) {
|
||||
if (node.connected) {
|
||||
node.connected = false;
|
||||
node.logdisconnect = false;
|
||||
node.log("Disconnected from broker: "+(node.clientid?node.clientid+"@":"")+node.brokerurl);
|
||||
node.emit('disconnected');
|
||||
}
|
||||
});
|
||||
|
||||
node.client.on('offline', function () {
|
||||
if (node.connected && node.logdisconnect ) {
|
||||
node.connected = false;
|
||||
node.logdisconnect = false;
|
||||
node.log("Disconnected from broker: "+(node.clientid?node.clientid+"@":"")+node.brokerurl);
|
||||
node.log(RED._("mqtt.state.disconnected",{broker:(node.clientid?node.clientid+"@":"")+node.brokerurl}));
|
||||
node.emit('disconnected');
|
||||
} else if (node.connecting) {
|
||||
node.log(RED._("mqtt.state.connect-failed",{broker:(node.clientid?node.clientid+"@":"")+node.brokerurl}));
|
||||
}
|
||||
});
|
||||
|
||||
// Register connect error handler
|
||||
node.client.on('error', function (error) {
|
||||
node.log("" + error);
|
||||
console.log("ERROR",error);
|
||||
if (node.connecting) {
|
||||
node.client.end();
|
||||
node.connecting = false;
|
||||
|
@ -211,13 +211,30 @@
|
||||
},
|
||||
"mqtt": {
|
||||
"label": {
|
||||
"broker": "Broker",
|
||||
"broker": "Server",
|
||||
"qos": "QoS",
|
||||
"clientid": "Client ID",
|
||||
"port": "Port"
|
||||
"port": "Port",
|
||||
"keepalive": "Keep alive time (s)",
|
||||
"cleansession": "Use clean session",
|
||||
"use-tls": "Enable secure (SSL/TLS) connection",
|
||||
"verify-server-cert":"Verify server certificate",
|
||||
"compatmode": "Use legacy MQTT 3.1 support"
|
||||
},
|
||||
"tabs-label": {
|
||||
"connection": "Connection",
|
||||
"security": "Security",
|
||||
"will": "Will Message"
|
||||
},
|
||||
"placeholder": {
|
||||
"clientid": "Leave blank for auto generated"
|
||||
"clientid": "Leave blank for auto generated",
|
||||
"clientid-nonclean":"Must be set for non-clean sessions",
|
||||
"will-topic": "Leave blank to disable will message"
|
||||
},
|
||||
"state": {
|
||||
"connected": "Connected to broker: __broker__",
|
||||
"disconnected": "Disconnected from broker: __broker__",
|
||||
"connect-failed": "Connection failed to broker: __broker__"
|
||||
},
|
||||
"retain": "Retain",
|
||||
"true": "true",
|
||||
@ -226,7 +243,8 @@
|
||||
"errors": {
|
||||
"not-defined": "topic not defined",
|
||||
"missing-config": "missing broker configuration",
|
||||
"invalid-topic": "Invalid topic specified"
|
||||
"invalid-topic": "Invalid topic specified",
|
||||
"nonclean-missingclientid": "No client ID set, using clean session"
|
||||
}
|
||||
},
|
||||
"httpin": {
|
||||
|
Loading…
Reference in New Issue
Block a user