node-red-contrib-aedes 0.15.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -9,7 +9,7 @@ jobs:
9
9
 
10
10
  strategy:
11
11
  matrix:
12
- node-version: [20.x, 22.x]
12
+ node-version: [22.x, 24.x]
13
13
  node-red: [3.x, 4.x]
14
14
 
15
15
  steps:
package/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # node-red-contrib-aedes Changelog
2
2
 
3
+ ## Feb 15, 2026, Version 1.1.0
4
+ ### Notable changes
5
+ - Improved help documentation
6
+ - Improved UI
7
+ - Added German locale (de)
8
+
9
+ ## Feb 14, 2026, Version 1.0.0
10
+ ### Notable changes
11
+ - Update aedes to version 1.0.0
12
+
3
13
  ## Jul 22, 2025, Version 0.15.0
4
14
  ### Notable changes
5
15
  - TLS configuration with local filess
package/README.md CHANGED
@@ -30,7 +30,7 @@ Just put this node on Node-RED and hit the deploy button. The MQTT Broker will r
30
30
  - Standard TCP Support
31
31
  - WebSocket Support via port or path
32
32
  - SSL / TLS
33
- - Message Persistence (In-memory, LevelDB or MongoDB)
33
+ - Message Persistence (In-memory or MongoDB)
34
34
 
35
35
  For more information see [Aedes](https://github.com/moscajs/aedes/blob/master/README.md#features).
36
36
 
@@ -41,6 +41,26 @@ When your Node-RED server address is `https://yourserver/`, you can set the WebS
41
41
 
42
42
  You can also bind the WebSocket to the root `"/"` path and having `wss://yourserver/` WebSocket listening at port `443` (or `ws://yourserver/` at port `80`).
43
43
 
44
+ ## Version Compatibility
45
+
46
+ The current version is based on **Aedes version 1.0**, which introduces several breaking changes. If your environment requires Aedes version 0.51, you can switch to version 0.15.x of this package.
47
+
48
+ To install the compatible version using the `version-11` dist-tag:
49
+ ```sh
50
+ npm install node-red-contrib-aedes@version-15
51
+ ```
52
+
53
+ The current version and version 0.15.x require **Node.js >= 20** and **Node-RED >= 3.0**.
54
+
55
+ If you are running an older Node.js version (e.g. on locked-down or legacy hardware), please use version **0.11.x** of this package.
56
+
57
+ To install the compatible version using the `version-11` dist-tag:
58
+ ```sh
59
+ npm install node-red-contrib-aedes@version-11
60
+ ```
61
+
62
+ For more details, see [issue #85](https://github.com/martin-doyle/node-red-contrib-aedes/issues/85).
63
+
44
64
  ## License
45
-
65
+
46
66
  Licensed under [MIT](./LICENSE).
package/aedes.html CHANGED
@@ -25,27 +25,28 @@
25
25
  <div id="node-config-aedes-broker-tabs-content" style="min-height:150px;">
26
26
  <div id="aedes-broker-tab-connection" style="display:none">
27
27
  <div class="form-row">
28
- <label for="node-input-mqtt_port"><i class="fa fa-globe"></i> <span
28
+ <label for="node-input-mqtt_port"><i class="fa fa-plug"></i> <span
29
29
  data-i18n="aedes-mqtt-broker.label.mqtt_port"></span></label>
30
30
  <input type="text" id="node-input-mqtt_port"
31
31
  data-i18n="[placeholder]aedes-mqtt-broker.placeholder.mqtt_port">
32
32
  </div>
33
33
  <div class="form-row">
34
- <label for="node-input-mqtt_ws_bind"><i class="fa fa-globe"></i> WS bind</label>
35
- <select id="node-input-mqtt_ws_bind" type="text" style="width:30%" text-center>
34
+ <label for="node-input-mqtt_ws_bind"><i class="fa fa-exchange"></i> <span
35
+ data-i18n="aedes-mqtt-broker.label.mqtt_ws_bind"></span></label>
36
+ <select id="node-input-mqtt_ws_bind" type="text" style="width:30%; text-align:center;">
36
37
  <option value="path" default>path</option>
37
38
  <option value="port">port</option>
38
39
  </select>
39
40
  </div>
40
41
  <div class="form-row" id="node-input-mqtt_ws_path-label">
41
- <label for="node-input-mqtt_ws_path"><i class="fa fa-globe"></i> <span
42
- data-i18n="aedes-mqtt-broker.label.mqtt_ws_path"></label>
42
+ <label for="node-input-mqtt_ws_path"><i class="fa fa-link"></i> <span
43
+ data-i18n="aedes-mqtt-broker.label.mqtt_ws_path"></span></label>
43
44
  <input type="text" id="node-input-mqtt_ws_path"
44
45
  data-i18n="[placeholder]aedes-mqtt-broker.placeholder.mqtt_ws_path">
45
46
  </div>
46
47
  <div class="form-row" id="node-input-mqtt_ws_port-label">
47
- <label for="node-input-mqtt_ws_port"><i class="fa fa-globe"></i> <span
48
- data-i18n="aedes-mqtt-broker.label.mqtt_ws_port"></label>
48
+ <label for="node-input-mqtt_ws_port"><i class="fa fa-plug"></i> <span
49
+ data-i18n="aedes-mqtt-broker.label.mqtt_ws_port"></span></label>
49
50
  <input type="text" id="node-input-mqtt_ws_port"
50
51
  data-i18n="[placeholder]aedes-mqtt-broker.placeholder.mqtt_ws_port">
51
52
  </div>
@@ -58,7 +59,7 @@
58
59
  <input type="checkbox" id="node-input-uselocalfiles"
59
60
  style="display: inline-block; width: auto; vertical-align: top;">
60
61
  <label for="node-input-uselocalfiles" style="width: 70%;"><span
61
- data-i18n="aedes-mqtt-broker.label.use-local-files"></label>
62
+ data-i18n="aedes-mqtt-broker.label.use-local-files"></span></label>
62
63
  </div>
63
64
 
64
65
  <div class="form-row">
@@ -122,17 +123,17 @@
122
123
  </div>
123
124
  <div id="aedes-broker-tab-persistence" style="display:none">
124
125
  <div class="form-row">
125
- <label for="node-input-persistence_bind"><i class="fa fa-globe"></i> <span
126
- data-i18n="aedes-mqtt-broker.label.persistence_bind"></label>
127
- <select id="node-input-persistence_bind" type="text" style="width:30%" text-center>
126
+ <label for="node-input-persistence_bind"><i class="fa fa-hdd-o"></i> <span
127
+ data-i18n="aedes-mqtt-broker.label.persistence_bind"></span></label>
128
+ <select id="node-input-persistence_bind" type="text" style="width:30%; text-align:center;">
128
129
  <option value="memory" data-i18n="aedes-mqtt-broker.label.persistence_memory" default></option>
129
130
  <option value="mongodb" data-i18n="aedes-mqtt-broker.label.persistence_mongodb"></option>
130
131
  <!-- <option value="level" data-i18n="aedes-mqtt-broker.label.persistence_level"></option> -->
131
132
  </select>
132
133
  </div>
133
- <div class="form-row" id="node-row-dburl" class="hide">
134
+ <div class="form-row hide" id="node-row-dburl">
134
135
  <label for="node-input-dburl"><i class="fa fa-database"></i> <span
135
- data-i18n="aedes-mqtt-broker.label.dburl"></label>
136
+ data-i18n="aedes-mqtt-broker.label.dburl"></span></label>
136
137
  <input type="text" id="node-input-dburl" data-i18n="[placeholder]aedes-mqtt-broker.placeholder.dburl">
137
138
  </div>
138
139
  </div>
@@ -157,9 +158,16 @@
157
158
  category: 'network',
158
159
  defaults: {
159
160
  name: { value: '' },
160
- mqtt_port: { value: 1883, validate: RED.validators.number() },
161
+ mqtt_port: { value: 1883, validate: function (v) {
162
+ var n = parseInt(v, 10);
163
+ return !isNaN(n) && n >= 1 && n <= 65535;
164
+ }},
161
165
  mqtt_ws_bind: { value: 'port', required: true },
162
- mqtt_ws_port: { value: null, required: false, validate: RED.validators.number(true) },
166
+ mqtt_ws_port: { value: null, required: false, validate: function (v) {
167
+ if (v === '' || v === null || v === undefined) return true;
168
+ var n = parseInt(v, 10);
169
+ return !isNaN(n) && n >= 1 && n <= 65535;
170
+ }},
163
171
  mqtt_ws_path: { value: '', required: false },
164
172
  cert: {
165
173
  value: '',
@@ -331,7 +339,7 @@
331
339
  $('#tls-button-key-clear').on('click', function () {
332
340
  clearNameData('key');
333
341
  });
334
- $("#tls-config-button-ca-clear").on("click", function() {
342
+ $("#tls-button-ca-clear").on("click", function() {
335
343
  clearNameData("ca");
336
344
  });
337
345
 
@@ -360,9 +368,11 @@
360
368
  $('#node-input-tls').val('');
361
369
  }
362
370
  if ($("#node-input-uselocalfiles").is(':checked')) {
363
- clearNameData("ca");
364
- clearNameData("cert");
365
- clearNameData("key");
371
+ ['ca', 'cert', 'key'].forEach(function (prop) {
372
+ $('#tls-' + prop + 'name').text('');
373
+ $('#node-input-' + prop + 'data').val('');
374
+ $('#node-input-' + prop + 'name').val('');
375
+ });
366
376
  } else {
367
377
  $("#node-input-ca").val("");
368
378
  $("#node-input-cert").val("");
package/aedes.js CHANGED
@@ -19,13 +19,13 @@ module.exports = function (RED) {
19
19
  const MongoPersistence = require('aedes-persistence-mongodb');
20
20
  // const { Level } = require('level');
21
21
  // const LevelPersistence = require('aedes-persistence-level');
22
- const aedes = require('aedes');
22
+ // aedes is ESM-only in v1 -- dynamically imported in initializeBroker()
23
23
  const fs = require('fs');
24
24
  const net = require('net');
25
25
  const tls = require('tls');
26
26
  const http = require('http');
27
27
  const https = require('https');
28
- const ws = require('websocket-stream');
28
+ const { WebSocketServer, createWebSocketStream } = require('ws');
29
29
 
30
30
  let serverUpgradeAdded = false;
31
31
  const listenerNodes = {};
@@ -51,131 +51,53 @@ module.exports = function (RED) {
51
51
  }
52
52
  }
53
53
 
54
- function AedesBrokerNode (config) {
55
- RED.nodes.createNode(this, config);
56
- this.mqtt_port = parseInt(config.mqtt_port, 10);
57
- this.mqtt_ws_port = parseInt(config.mqtt_ws_port, 10);
58
- this.mqtt_ws_path = '' + config.mqtt_ws_path;
59
- this.mqtt_ws_bind = config.mqtt_ws_bind;
60
- this.usetls = config.usetls;
61
-
62
- const certPath = config.cert ? config.cert.trim() : '';
63
- const keyPath = config.key ? config.key.trim() : '';
64
- const caPath = config.ca ? config.ca.trim() : '';
65
-
66
- this.uselocalfiles = config.uselocalfiles;
67
- this.dburl = config.dburl;
68
-
69
- if (this.mqtt_ws_bind === 'path') {
70
- this.mqtt_ws_port = 0;
71
- } else {
72
- this.mqtt_ws_path = '';
73
- }
74
-
75
- if (certPath.length > 0 || keyPath.length > 0 || caPath.length > 0) {
76
- if ((certPath.length > 0) !== (keyPath.length > 0)) {
77
- this.valid = false;
78
- this.error(RED._('tls.error.missing-file'));
79
- return;
80
- }
81
- try {
82
- if (certPath) {
83
- this.cert = fs.readFileSync(certPath);
84
- }
85
- if (keyPath) {
86
- this.key = fs.readFileSync(keyPath);
87
- }
88
- if (caPath) {
89
- this.ca = fs.readFileSync(caPath);
90
- }
91
- } catch (err) {
92
- this.valid = false;
93
- this.error(err.toString());
94
- return;
95
- }
96
- } else {
97
- if (this.credentials) {
98
- this.cert = this.credentials.certdata || '';
99
- this.key = this.credentials.keydata || '';
100
- this.ca = this.credentials.cadata || '';
101
- }
102
- }
103
- if (this.credentials) {
104
- this.username = this.credentials.username;
105
- this.password = this.credentials.password;
106
- }
54
+ async function initializeBroker (node, config, aedesSettings, serverOptions) {
55
+ const { Aedes } = await import('aedes');
56
+ const broker = await Aedes.createBroker(aedesSettings);
57
+ if (node._closing) { broker.close(); return; }
58
+ node._broker = broker;
107
59
 
108
- if (typeof this.usetls === 'undefined') {
109
- this.usetls = false;
110
- }
111
-
112
- const node = this;
113
-
114
- const aedesSettings = {};
115
- const serverOptions = {};
116
-
117
- if (config.persistence_bind === 'mongodb' && config.dburl) {
118
- aedesSettings.persistence = MongoPersistence({
119
- url: config.dburl
120
- });
121
- node.log('Start persistence to MongeDB');
122
- /*
123
- } else if (config.persistence_bind === 'level') {
124
- aedesSettings.persistence = LevelPersistence(new Level('leveldb'));
125
- node.log('Start persistence to LevelDB');
126
- */
127
- }
128
-
129
- if (this.cert && this.key && this.usetls) {
130
- serverOptions.cert = this.cert;
131
- serverOptions.key = this.key;
132
- serverOptions.ca = this.ca;
133
- }
134
-
135
- const broker = aedes.createBroker(aedesSettings);
136
60
  let server;
137
- if (this.usetls) {
61
+ if (node.usetls) {
138
62
  server = tls.createServer(serverOptions, broker.handle);
139
63
  } else {
140
64
  server = net.createServer(broker.handle);
141
65
  }
66
+ node._server = server;
142
67
 
143
- let wss = null;
144
- let httpServer = null;
145
-
146
- if (this.mqtt_ws_port) {
68
+ if (node.mqtt_ws_port) {
147
69
  // Awkward check since http or ws do not fire an error event in case the port is in use
148
70
  const testServer = net.createServer();
149
71
  testServer.once('error', function (err) {
150
72
  if (err.code === 'EADDRINUSE') {
151
73
  node.error(
152
- 'Error: Port ' + config.mqtt_ws_port + ' is already in use'
74
+ RED._('aedes-mqtt-broker.error.port-in-use', { port: config.mqtt_ws_port })
153
75
  );
154
76
  } else {
155
77
  node.error(
156
- 'Error creating net server on port ' +
157
- config.mqtt_ws_port +
158
- ', ' +
159
- err.toString()
78
+ RED._('aedes-mqtt-broker.error.server-error', { port: config.mqtt_ws_port, error: err.toString() })
160
79
  );
161
80
  }
81
+ node.status({ fill: 'red', shape: 'ring', text: 'aedes-mqtt-broker.status.error' });
162
82
  });
163
83
  testServer.once('listening', function () {
164
84
  testServer.close();
165
85
  });
166
86
 
167
87
  testServer.once('close', function () {
88
+ let httpServer;
168
89
  if (node.usetls) {
169
90
  httpServer = https.createServer(serverOptions);
170
91
  } else {
171
92
  httpServer = http.createServer();
172
93
  }
173
- wss = ws.createServer(
174
- {
175
- server: httpServer
176
- },
177
- broker.handle
178
- );
94
+ node._httpServer = httpServer;
95
+ const wss = new WebSocketServer({ server: httpServer });
96
+ wss.on('connection', function (websocket, req) {
97
+ const stream = createWebSocketStream(websocket);
98
+ broker.handle(stream, req);
99
+ });
100
+ node._wss = wss;
179
101
  httpServer.listen(config.mqtt_ws_port, function () {
180
102
  node.log(
181
103
  'Binding aedes mqtt server on ws port: ' + config.mqtt_ws_port
@@ -187,7 +109,7 @@ module.exports = function (RED) {
187
109
  });
188
110
  }
189
111
 
190
- if (this.mqtt_ws_path !== '') {
112
+ if (node.mqtt_ws_path !== '') {
191
113
  if (!serverUpgradeAdded) {
192
114
  RED.server.on('upgrade', handleServerUpgrade);
193
115
  serverUpgradeAdded = true;
@@ -206,46 +128,44 @@ module.exports = function (RED) {
206
128
  node.error(
207
129
  RED._('websocket.errors.duplicate-path', { path: node.mqtt_ws_path })
208
130
  );
209
- return;
210
- }
211
- listenerNodes[node.fullPath] = node;
212
- const serverOptions_ = {
213
- noServer: true
214
- };
215
- if (RED.settings.webSocketNodeVerifyClient) {
216
- serverOptions_.verifyClient = RED.settings.webSocketNodeVerifyClient;
217
- }
218
-
219
- node.server = ws.createServer(
220
- {
131
+ } else {
132
+ listenerNodes[node.fullPath] = node;
133
+ const serverOptions_ = {
221
134
  noServer: true
222
- },
223
- broker.handle
224
- );
135
+ };
136
+ if (RED.settings.webSocketNodeVerifyClient) {
137
+ serverOptions_.verifyClient = RED.settings.webSocketNodeVerifyClient;
138
+ }
225
139
 
226
- node.log('Binding aedes mqtt server on ws path: ' + node.fullPath);
140
+ node.server = new WebSocketServer(serverOptions_);
141
+ node.server.on('connection', function (websocket, req) {
142
+ const stream = createWebSocketStream(websocket);
143
+ broker.handle(stream, req);
144
+ });
145
+
146
+ node.log('Binding aedes mqtt server on ws path: ' + node.fullPath);
147
+ }
227
148
  }
228
149
 
229
150
  server.once('error', function (err) {
230
151
  if (err.code === 'EADDRINUSE') {
231
- node.error('Error: Port ' + config.mqtt_port + ' is already in use');
232
- node.status({
233
- fill: 'red',
234
- shape: 'ring',
235
- text: 'node-red:common.status.disconnected'
236
- });
152
+ node.error(
153
+ RED._('aedes-mqtt-broker.error.port-in-use', { port: config.mqtt_port })
154
+ );
237
155
  } else {
238
- node.error('Error: Port ' + config.mqtt_port + ' ' + err.toString());
239
- node.status({
240
- fill: 'red',
241
- shape: 'ring',
242
- text: 'node-red:common.status.disconnected'
243
- });
156
+ node.error(
157
+ RED._('aedes-mqtt-broker.error.server-error', { port: config.mqtt_port, error: err.toString() })
158
+ );
244
159
  }
160
+ node.status({
161
+ fill: 'red',
162
+ shape: 'ring',
163
+ text: 'aedes-mqtt-broker.status.error'
164
+ });
245
165
  });
246
166
 
247
- if (this.mqtt_port) {
248
- server.listen(this.mqtt_port, function () {
167
+ if (node.mqtt_port) {
168
+ server.listen(node.mqtt_port, function () {
249
169
  node.log('Binding aedes mqtt server on port: ' + config.mqtt_port);
250
170
  node.status({
251
171
  fill: 'green',
@@ -255,7 +175,7 @@ module.exports = function (RED) {
255
175
  });
256
176
  }
257
177
 
258
- if (this.credentials && this.username && this.password) {
178
+ if (node.credentials && node.username && node.password) {
259
179
  broker.authenticate = function (client, username, password, callback) {
260
180
  const authorized =
261
181
  username === node.username &&
@@ -365,31 +285,25 @@ module.exports = function (RED) {
365
285
  });
366
286
  });
367
287
 
368
- broker.on('subscribe', function (subscription, client) {
369
- const msg = {
370
- topic: 'subscribe',
371
- payload: {
372
- topic: subscription.topic,
373
- qos: subscription.qos,
374
- client
375
- }
376
- };
377
- node.send([msg, null]);
288
+ broker.on('subscribe', function (subscriptions, client) {
289
+ for (const subscription of subscriptions) {
290
+ node.send([{
291
+ topic: 'subscribe',
292
+ payload: { topic: subscription.topic, qos: subscription.qos, client }
293
+ }, null]);
294
+ }
378
295
  });
379
296
 
380
- broker.on('unsubscribe', function (subscription, client) {
381
- const msg = {
382
- topic: 'unsubscribe',
383
- payload: {
384
- topic: subscription.topic,
385
- qos: subscription.qos,
386
- client
387
- }
388
- };
389
- node.send([msg, null]);
297
+ broker.on('unsubscribe', function (unsubscriptions, client) {
298
+ for (const topic of unsubscriptions) {
299
+ node.send([{
300
+ topic: 'unsubscribe',
301
+ payload: { topic, client }
302
+ }, null]);
303
+ }
390
304
  });
391
305
 
392
- if (this.wires && this.wires[1] && this.wires[1].length > 0) {
306
+ if (node.wires && node.wires[1] && node.wires[1].length > 0) {
393
307
  node.log('Publish output wired. Enable broker publish event messages.');
394
308
  broker.on('publish', function (packet, client) {
395
309
  const msg = {
@@ -406,49 +320,143 @@ module.exports = function (RED) {
406
320
  broker.on('closed', function () {
407
321
  node.debug('Closed event');
408
322
  });
323
+ }
409
324
 
410
- this.on('close', function (done) {
411
- process.nextTick(function onCloseDelayed () {
412
- function wsClose () {
413
- if (wss) {
414
- node.log(
415
- 'Unbinding aedes mqtt server from ws port: ' + config.mqtt_ws_port
416
- );
417
- wss.close(function () {
418
- node.debug('after wss.close(): ');
419
- httpServer.close(function () {
420
- node.debug('after httpServer.close(): ');
421
- done();
422
- });
423
- });
424
- } else {
425
- done();
426
- }
427
- }
325
+ function AedesBrokerNode (config) {
326
+ RED.nodes.createNode(this, config);
327
+ this.mqtt_port = parseInt(config.mqtt_port, 10);
328
+ this.mqtt_ws_port = parseInt(config.mqtt_ws_port, 10);
329
+ this.mqtt_ws_path = '' + config.mqtt_ws_path;
330
+ this.mqtt_ws_bind = config.mqtt_ws_bind;
331
+ this.usetls = config.usetls;
428
332
 
429
- function brokerClose () {
430
- broker.close(function () {
431
- node.log(
432
- 'Unbinding aedes mqtt server from port: ' + config.mqtt_port
433
- );
434
- server.close(function () {
435
- node.debug('after server.close(): ');
436
- if (node.mqtt_ws_path !== '') {
437
- node.log(
438
- 'Unbinding aedes mqtt server from ws path: ' + node.fullPath
439
- );
440
- delete listenerNodes[node.fullPath];
441
- node.server.close(function () {
442
- wsClose();
443
- });
444
- } else {
445
- wsClose();
446
- }
447
- });
448
- });
333
+ const certPath = config.cert ? config.cert.trim() : '';
334
+ const keyPath = config.key ? config.key.trim() : '';
335
+ const caPath = config.ca ? config.ca.trim() : '';
336
+
337
+ this.uselocalfiles = config.uselocalfiles;
338
+ this.dburl = config.dburl;
339
+
340
+ if (this.mqtt_ws_bind === 'path') {
341
+ this.mqtt_ws_port = 0;
342
+ } else {
343
+ this.mqtt_ws_path = '';
344
+ }
345
+
346
+ if (certPath.length > 0 || keyPath.length > 0 || caPath.length > 0) {
347
+ if ((certPath.length > 0) !== (keyPath.length > 0)) {
348
+ this.valid = false;
349
+ this.error(RED._('tls.error.missing-file'));
350
+ return;
351
+ }
352
+ try {
353
+ if (certPath) {
354
+ this.cert = fs.readFileSync(certPath);
355
+ }
356
+ if (keyPath) {
357
+ this.key = fs.readFileSync(keyPath);
449
358
  }
450
- brokerClose();
359
+ if (caPath) {
360
+ this.ca = fs.readFileSync(caPath);
361
+ }
362
+ } catch (err) {
363
+ this.valid = false;
364
+ this.error(err.toString());
365
+ return;
366
+ }
367
+ } else {
368
+ if (this.credentials) {
369
+ this.cert = this.credentials.certdata || '';
370
+ this.key = this.credentials.keydata || '';
371
+ this.ca = this.credentials.cadata || '';
372
+ }
373
+ }
374
+ if (this.credentials) {
375
+ this.username = this.credentials.username;
376
+ this.password = this.credentials.password;
377
+ }
378
+
379
+ if (typeof this.usetls === 'undefined') {
380
+ this.usetls = false;
381
+ }
382
+
383
+ const node = this;
384
+
385
+ const aedesSettings = {};
386
+ const serverOptions = {};
387
+
388
+ if (config.persistence_bind === 'mongodb' && config.dburl) {
389
+ aedesSettings.persistence = MongoPersistence({
390
+ url: config.dburl
451
391
  });
392
+ node.log('Start persistence to MongoDB');
393
+ /*
394
+ } else if (config.persistence_bind === 'level') {
395
+ aedesSettings.persistence = LevelPersistence(new Level('leveldb'));
396
+ node.log('Start persistence to LevelDB');
397
+ */
398
+ }
399
+
400
+ if (this.cert && this.key && this.usetls) {
401
+ serverOptions.cert = this.cert;
402
+ serverOptions.key = this.key;
403
+ serverOptions.ca = this.ca;
404
+ }
405
+
406
+ node._closing = false;
407
+ node._broker = null;
408
+ node._server = null;
409
+ node._wss = null;
410
+ node._httpServer = null;
411
+
412
+ node._initPromise = initializeBroker(node, config, aedesSettings, serverOptions);
413
+ node._initPromise.catch(function (err) {
414
+ node.error(RED._('aedes-mqtt-broker.error.init-failed', { error: err.toString() }));
415
+ node.status({ fill: 'red', shape: 'ring', text: 'aedes-mqtt-broker.status.init-failed' });
416
+ });
417
+
418
+ this.on('close', async function (removed, done) {
419
+ node._closing = true;
420
+ if (removed) {
421
+ node.debug('Node removed or disabled');
422
+ } else {
423
+ node.debug('Node restarting');
424
+ }
425
+ try {
426
+ await node._initPromise;
427
+ closeBroker(node, done);
428
+ } catch (e) {
429
+ done();
430
+ }
431
+ });
432
+ }
433
+
434
+ function closeBroker (node, done) {
435
+ process.nextTick(function () {
436
+ function wsClose () {
437
+ if (node._wss) {
438
+ node._wss.close(function () {
439
+ if (node._httpServer) {
440
+ node._httpServer.close(function () { done(); });
441
+ } else { done(); }
442
+ });
443
+ } else { done(); }
444
+ }
445
+ function serverClose () {
446
+ if (node._server) {
447
+ node._server.close(function () {
448
+ if (node.mqtt_ws_path !== '' && node.fullPath) {
449
+ delete listenerNodes[node.fullPath];
450
+ if (node.server) {
451
+ node.server.close(function () { wsClose(); });
452
+ } else { wsClose(); }
453
+ } else { wsClose(); }
454
+ });
455
+ } else { wsClose(); }
456
+ }
457
+ if (node._broker) {
458
+ node._broker.close(function () { serverClose(); });
459
+ } else { serverClose(); }
452
460
  });
453
461
  }
454
462