node-red-contrib-aedes 0.15.1 → 1.2.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.
@@ -0,0 +1,110 @@
1
+ <script type="text/x-red" data-help-name="aedes broker">
2
+ <p>Ein eingebetteter MQTT-Broker basierend auf <a href="https://github.com/moscajs/aedes">Aedes</a>.
3
+ Ermöglicht MQTT-in- und MQTT-out-Nodes die Kommunikation ohne einen externen Broker wie Mosquitto.</p>
4
+
5
+ <h3>Ausgänge</h3>
6
+ <ol class="node-ports">
7
+ <li>Ereignisse
8
+ <dl class="message-properties">
9
+ <dt>topic <span class="property-type">string</span></dt>
10
+ <dd>Der Name des Ereignisses (siehe Tabelle unten).</dd>
11
+ <dt>payload <span class="property-type">object</span></dt>
12
+ <dd>Ereignisspezifische Daten mit Client-Informationen und ggf. Fehler- oder Abonnement-Details.</dd>
13
+ </dl>
14
+ </li>
15
+ <li>Publish
16
+ <dl class="message-properties">
17
+ <dt>topic <span class="property-type">string</span></dt>
18
+ <dd>immer <code>"publish"</code>.</dd>
19
+ <dt>payload.packet <span class="property-type">object</span></dt>
20
+ <dd>Das MQTT-Paket mit den Eigenschaften <code>topic</code>, <code>payload</code>, <code>qos</code> und <code>retain</code>.</dd>
21
+ <dt>payload.client <span class="property-type">object | null</span></dt>
22
+ <dd>Der Client, der die Nachricht gesendet hat, oder <code>null</code> bei Broker-eigenen Nachrichten.</dd>
23
+ </dl>
24
+ </li>
25
+ </ol>
26
+ <p><strong>Hinweis:</strong> Der Publish-Ausgang ist nur aktiv, wenn er mit einem anderen Node verbunden ist.
27
+ Dies vermeidet unnötige Verarbeitung, wenn Publish-Nachrichten nicht benötigt werden.</p>
28
+
29
+ <h3>Details</h3>
30
+ <p>Dieser Node startet einen MQTT-Broker innerhalb des Node-RED-Prozesses. MQTT-Clients,
31
+ einschließlich der integrierten MQTT-in- und MQTT-out-Nodes, können sich über den
32
+ konfigurierten Port (Standard <code>1883</code>) verbinden.</p>
33
+
34
+ <h4>Verbindung</h4>
35
+ <p>Konfigurieren Sie den MQTT-TCP-Port und den optionalen WebSocket-Zugang. WebSocket-Verbindungen
36
+ können auf zwei Arten bereitgestellt werden:</p>
37
+ <ul>
38
+ <li><b>Port</b> &ndash; ein eigenständiger WebSocket-Server auf einem separaten Port.</li>
39
+ <li><b>Pfad</b> &ndash; nutzt den Node-RED-HTTP-Server unter einem URL-Pfad
40
+ (relativ zu <code>httpNodeRoot</code>).</li>
41
+ </ul>
42
+ <p>Aktivieren Sie <i>SSL/TLS</i> um Verbindungen abzusichern. Zertifikate können
43
+ direkt hochgeladen oder als lokale Dateipfade auf dem Server angegeben werden.</p>
44
+
45
+ <h4>Persistenz</h4>
46
+ <p>Standardmäßig werden Nachrichten und Abonnements im Speicher gehalten und gehen
47
+ bei einem Neustart verloren. Wählen Sie <i>MongoDB</i> um Daten über Neustarts
48
+ hinweg zu persistieren.</p>
49
+
50
+ <h4>Sicherheit</h4>
51
+ <p>Legen Sie einen Benutzernamen und ein Passwort fest, um eine Client-Authentifizierung
52
+ zu erzwingen. Lassen Sie beide Felder leer, um anonyme Verbindungen zu erlauben.
53
+ Es wird nur ein einzelnes Zugangsdatenpaar unterstützt.</p>
54
+
55
+ <h4>Ereignis-Topics</h4>
56
+ <p>Der erste Ausgang sendet folgende Ereignisse:</p>
57
+ <table>
58
+ <thead>
59
+ <tr><th>Topic</th><th>Payload</th><th>Beschreibung</th></tr>
60
+ </thead>
61
+ <tbody>
62
+ <tr>
63
+ <td><code>client</code></td>
64
+ <td><code>{ client }</code></td>
65
+ <td>Ein neuer Client hat sich verbunden (vor der Authentifizierung).</td>
66
+ </tr>
67
+ <tr>
68
+ <td><code>clientReady</code></td>
69
+ <td><code>{ client }</code></td>
70
+ <td>Ein Client hat sich verbunden, ist authentifiziert und bereit.</td>
71
+ </tr>
72
+ <tr>
73
+ <td><code>clientDisconnect</code></td>
74
+ <td><code>{ client }</code></td>
75
+ <td>Ein Client hat sich ordnungsgemäß getrennt.</td>
76
+ </tr>
77
+ <tr>
78
+ <td><code>clientError</code></td>
79
+ <td><code>{ client, err }</code></td>
80
+ <td>Bei einer Client-Verbindung ist ein Fehler aufgetreten.</td>
81
+ </tr>
82
+ <tr>
83
+ <td><code>connectionError</code></td>
84
+ <td><code>{ client, err }</code></td>
85
+ <td>Ein Fehler auf Verbindungsebene ist aufgetreten.</td>
86
+ </tr>
87
+ <tr>
88
+ <td><code>keepaliveTimeout</code></td>
89
+ <td><code>{ client }</code></td>
90
+ <td>Ein Client wurde wegen Keepalive-Timeout getrennt.</td>
91
+ </tr>
92
+ <tr>
93
+ <td><code>subscribe</code></td>
94
+ <td><code>{ topic, qos, client }</code></td>
95
+ <td>Ein Client hat ein Topic abonniert. Pro Abonnement wird eine Nachricht gesendet.</td>
96
+ </tr>
97
+ <tr>
98
+ <td><code>unsubscribe</code></td>
99
+ <td><code>{ topic, client }</code></td>
100
+ <td>Ein Client hat ein Topic-Abonnement beendet. Pro Abmeldung wird eine Nachricht gesendet.</td>
101
+ </tr>
102
+ </tbody>
103
+ </table>
104
+
105
+ <h3>Referenzen</h3>
106
+ <ul>
107
+ <li><a href="https://github.com/moscajs/aedes">Aedes</a> - die zugrunde liegende MQTT-Broker-Bibliothek</li>
108
+ <li><a href="https://github.com/martin-doyle/node-red-contrib-aedes">node-red-contrib-aedes</a> - GitHub-Repository</li>
109
+ </ul>
110
+ </script>
@@ -0,0 +1,54 @@
1
+ {
2
+ "aedes-mqtt-broker": {
3
+ "status": {
4
+ "connected": "verbunden __count__",
5
+ "connected_plural": "verbunden __count__",
6
+ "disconnected": "getrennt",
7
+ "error": "Fehler",
8
+ "init-failed": "Initialisierung fehlgeschlagen"
9
+ },
10
+ "error": {
11
+ "port-in-use": "Fehler: Port __port__ wird bereits verwendet",
12
+ "server-error": "Fehler beim Erstellen des Servers auf Port __port__: __error__",
13
+ "init-failed": "Aedes Broker konnte nicht initialisiert werden: __error__"
14
+ },
15
+ "label": {
16
+ "mqtt_port": "MQTT-Port",
17
+ "mqtt_ws_bind": "WS-Bindung",
18
+ "mqtt_ws_port": "WS-Port",
19
+ "mqtt_ws_path": "WS-Pfad",
20
+ "use-tls": "Sichere Verbindung (SSL/TLS) aktivieren",
21
+ "use-local-files": "Lokale Dateien verwenden",
22
+ "tls-config": "TLS-Konfiguration",
23
+ "upload": "Hochladen",
24
+ "cert": "Zertifikat",
25
+ "key": "Privater Schlüssel",
26
+ "ca": "CA-Zertifikat",
27
+ "persistence_bind": "Persistenz",
28
+ "persistence_memory": "Speicher",
29
+ "persistence_mongodb": "MongoDB",
30
+ "persistence_level": "LevelDB",
31
+ "dburl": "DB-URL",
32
+ "persist_to_file": "Zustand über Neustarts hinweg speichern"
33
+ },
34
+ "tip": {
35
+ "persist_to_file": "Speichert Retained Messages und Subscriptions als JSON-Datei im Node-RED userDir. Wird beim Herunterfahren und alle 60 s geschrieben. QoS 1/2 In-Flight-Nachrichten werden nicht gespeichert. Wird automatisch deaktiviert, wenn userDir nicht beschreibbar ist."
36
+ },
37
+ "placeholder": {
38
+ "mqtt_port": "MQTT-Port eingeben",
39
+ "mqtt_ws_port": "WebSocket-Port eingeben. Leer lassen um WebSocket zu deaktivieren",
40
+ "mqtt_ws_path": "WebSocket-Pfad eingeben. Leer lassen um WebSocket zu deaktivieren",
41
+ "cert": "Pfad zum Zertifikat (PEM-Format)",
42
+ "key": "Pfad zum privaten Schlüssel (PEM-Format)",
43
+ "ca": "Pfad zum CA-Zertifikat (PEM-Format)",
44
+ "dburl": "mongodb://localhost:27017/mqtt",
45
+ "username": "Leer lassen um Authentifizierung zu deaktivieren",
46
+ "password": "Leer lassen um Authentifizierung zu deaktivieren"
47
+ },
48
+ "tabs-label": {
49
+ "connection": "Verbindung",
50
+ "persistence": "Persistenz",
51
+ "security": "Sicherheit"
52
+ }
53
+ }
54
+ }
@@ -1,18 +1,109 @@
1
1
  <script type="text/x-red" data-help-name="aedes broker">
2
- <p>MQTT broker based on Barebone MQTT broker Aedes. You can use MQTT-in and MQTT-out nodes without an external broker like Mosquitto.</p>
2
+ <p>An embedded MQTT broker based on <a href="https://github.com/moscajs/aedes">Aedes</a>.
3
+ Allows MQTT-in and MQTT-out nodes to communicate without an external broker like Mosquitto.</p>
4
+
3
5
  <h3>Outputs</h3>
4
- <dl class="message-properties">
5
- <dt>topic <span class="property-type">string</span></dt>
6
- <dd>the topic of the event.</dd>
7
- <dt>payload 1<span class="property-type">object</span></dt>
8
- <dd>the content of all events from the broker except publish.</dd>
9
- <dt>payload 2<span class="property-type">object</span></dt>
10
- <dd>the content of the publish events from the broker.</dd>
6
+ <ol class="node-ports">
7
+ <li>Events
8
+ <dl class="message-properties">
9
+ <dt>topic <span class="property-type">string</span></dt>
10
+ <dd>the name of the event (see table below).</dd>
11
+ <dt>payload <span class="property-type">object</span></dt>
12
+ <dd>event-specific data containing client information and, where applicable, error or subscription details.</dd>
13
+ </dl>
14
+ </li>
15
+ <li>Publish
16
+ <dl class="message-properties">
17
+ <dt>topic <span class="property-type">string</span></dt>
18
+ <dd>always <code>"publish"</code>.</dd>
19
+ <dt>payload.packet <span class="property-type">object</span></dt>
20
+ <dd>the MQTT packet with <code>topic</code>, <code>payload</code>, <code>qos</code>, and <code>retain</code> properties.</dd>
21
+ <dt>payload.client <span class="property-type">object | null</span></dt>
22
+ <dd>the client that published the message, or <code>null</code> for broker-originated messages.</dd>
23
+ </dl>
24
+ </li>
25
+ </ol>
26
+ <p><strong>Note:</strong> The publish output is only active when it is wired to another node.
27
+ This avoids unnecessary processing when publish messages are not needed.</p>
11
28
 
12
- </dl>
13
29
  <h3>Details</h3>
30
+ <p>This node starts an MQTT broker inside the Node-RED process. MQTT clients,
31
+ including the built-in MQTT-in and MQTT-out nodes, can connect to it on the
32
+ configured port (default <code>1883</code>).</p>
33
+
34
+ <h4>Connection</h4>
35
+ <p>Configure the MQTT TCP port and optional WebSocket access. WebSocket
36
+ connections can be exposed in two ways:</p>
37
+ <ul>
38
+ <li><b>Port</b> &ndash; a standalone WebSocket server on a separate port.</li>
39
+ <li><b>Path</b> &ndash; shares the Node-RED HTTP server under a URL path
40
+ (relative to <code>httpNodeRoot</code>).</li>
41
+ </ul>
42
+ <p>Enable <i>SSL/TLS</i> to secure connections. Certificates can be uploaded
43
+ directly or referenced as local file paths on the server.</p>
44
+
45
+ <h4>Persistence</h4>
46
+ <p>By default messages and subscriptions are stored in memory and lost on
47
+ restart. Select <i>MongoDB</i> to persist data across restarts.</p>
48
+
49
+ <h4>Security</h4>
50
+ <p>Set a username and password to require client authentication.
51
+ Leave both fields blank to allow anonymous connections.
52
+ Only a single set of credentials is supported.</p>
53
+
54
+ <h4>Event Topics</h4>
55
+ <p>The first output emits the following events:</p>
56
+ <table>
57
+ <thead>
58
+ <tr><th>topic</th><th>payload</th><th>Description</th></tr>
59
+ </thead>
60
+ <tbody>
61
+ <tr>
62
+ <td><code>client</code></td>
63
+ <td><code>{ client }</code></td>
64
+ <td>A new client has connected (before authentication).</td>
65
+ </tr>
66
+ <tr>
67
+ <td><code>clientReady</code></td>
68
+ <td><code>{ client }</code></td>
69
+ <td>A client has connected and is authenticated and ready.</td>
70
+ </tr>
71
+ <tr>
72
+ <td><code>clientDisconnect</code></td>
73
+ <td><code>{ client }</code></td>
74
+ <td>A client has gracefully disconnected.</td>
75
+ </tr>
76
+ <tr>
77
+ <td><code>clientError</code></td>
78
+ <td><code>{ client, err }</code></td>
79
+ <td>An error occurred on a client connection.</td>
80
+ </tr>
81
+ <tr>
82
+ <td><code>connectionError</code></td>
83
+ <td><code>{ client, err }</code></td>
84
+ <td>A connection-level error occurred.</td>
85
+ </tr>
86
+ <tr>
87
+ <td><code>keepaliveTimeout</code></td>
88
+ <td><code>{ client }</code></td>
89
+ <td>A client has been disconnected due to keepalive timeout.</td>
90
+ </tr>
91
+ <tr>
92
+ <td><code>subscribe</code></td>
93
+ <td><code>{ topic, qos, client }</code></td>
94
+ <td>A client has subscribed to a topic. One message is sent per subscription.</td>
95
+ </tr>
96
+ <tr>
97
+ <td><code>unsubscribe</code></td>
98
+ <td><code>{ topic, client }</code></td>
99
+ <td>A client has unsubscribed from a topic. One message is sent per unsubscription.</td>
100
+ </tr>
101
+ </tbody>
102
+ </table>
103
+
14
104
  <h3>References</h3>
15
- <ul>
16
- <li><a href="https://github.com/moscajs/aedes">Aedes</a> - Barebone MQTT broker that can run on any stream server, the node way</li>
17
- </ul>
105
+ <ul>
106
+ <li><a href="https://github.com/moscajs/aedes">Aedes</a> - the underlying MQTT broker library</li>
107
+ <li><a href="https://github.com/martin-doyle/node-red-contrib-aedes">node-red-contrib-aedes</a> - GitHub repository</li>
108
+ </ul>
18
109
  </script>
@@ -2,10 +2,19 @@
2
2
  "aedes-mqtt-broker": {
3
3
  "status": {
4
4
  "connected": "connected __count__",
5
- "connected_plural": "connected __count__"
5
+ "connected_plural": "connected __count__",
6
+ "disconnected": "disconnected",
7
+ "error": "error",
8
+ "init-failed": "initialization failed"
9
+ },
10
+ "error": {
11
+ "port-in-use": "Error: Port __port__ is already in use",
12
+ "server-error": "Error creating server on port __port__: __error__",
13
+ "init-failed": "Failed to initialize Aedes broker: __error__"
6
14
  },
7
15
  "label": {
8
16
  "mqtt_port": "MQTT port",
17
+ "mqtt_ws_bind": "WS bind",
9
18
  "mqtt_ws_port": "WS port",
10
19
  "mqtt_ws_path": "WS path",
11
20
  "use-tls": "Enable secure (SSL/TLS) connection",
@@ -19,7 +28,11 @@
19
28
  "persistence_memory": "Memory",
20
29
  "persistence_mongodb": "MongoDB",
21
30
  "persistence_level": "LevelDB",
22
- "dburl": "DB Url"
31
+ "dburl": "DB Url",
32
+ "persist_to_file": "Persist state across restarts"
33
+ },
34
+ "tip": {
35
+ "persist_to_file": "Saves retained messages and subscriptions as a JSON file in the Node-RED userDir. Written on shutdown and every 60 s. QoS 1/2 in-flight messages are not persisted. Disabled automatically if userDir is not writable."
23
36
  },
24
37
  "placeholder": {
25
38
  "mqtt_port": "Enter MQTT port",
package/package.json CHANGED
@@ -1,15 +1,17 @@
1
1
  {
2
2
  "name": "node-red-contrib-aedes",
3
- "version": "0.15.1",
3
+ "version": "1.2.0",
4
4
  "description": "Node Red MQTT broker node based on aedes.js",
5
5
  "dependencies": {
6
- "aedes": "^0.51.3",
6
+ "aedes": "^1.0.0",
7
7
  "aedes-persistence-mongodb": "^9.3.0",
8
- "websocket-stream": "^5.5.2"
8
+ "ws": "^8.18.0"
9
9
  },
10
10
  "devDependencies": {
11
11
  "mqtt": "^5.13.1",
12
- "node-red-node-test-helper": "^0.3.3"
12
+ "node-red-node-test-helper": "^0.3.3",
13
+ "semistandard": "^17.0.0",
14
+ "snazzy": "^9.0.0"
13
15
  },
14
16
  "scripts": {
15
17
  "patch": "npm --no-git-tag-version version patch",
@@ -4,6 +4,7 @@ const helper = require('node-red-node-test-helper');
4
4
  const aedesNode = require('../aedes.js');
5
5
  const mqtt = require('mqtt');
6
6
  const should = require('should');
7
+ const { logError } = require('./test-utils');
7
8
 
8
9
  helper.init(require.resolve('node-red'));
9
10
 
@@ -34,20 +35,7 @@ describe('Aedes Broker Last Will tests', function () {
34
35
  done();
35
36
  });
36
37
  } catch (n) {
37
- // Check if AggregateError
38
- console.log(
39
- n instanceof AggregateError
40
- );
41
-
42
- // Print the message of the error
43
- console.log(n.message);
44
-
45
- // Print the name of the error
46
- console.log(n.name);
47
-
48
- // Print all the errors that this
49
- // error comprises
50
- console.log(n.errors);
38
+ logError(n);
51
39
  done();
52
40
  }
53
41
  });
@@ -70,40 +58,29 @@ describe('Aedes Broker Last Will tests', function () {
70
58
  }
71
59
  ];
72
60
  helper.load([aedesNode], flow, function () {
73
- const client1 = mqtt.connect('mqtt://localhost:1883', {
74
- clientId: 'client1',
75
- will: { topic: 'testLastWill', payload: 'last will' }
76
- });
77
- client1.on('error', function (n) {
78
- console.log(
79
- n instanceof AggregateError
80
- );
81
-
82
- // Print the message of the error
83
- console.log(n.message);
84
-
85
- // Print the name of the error
86
- console.log(n.name);
87
-
88
- // Print all the errors that this
89
- // error comprises
90
- console.log(n.errors);
91
- });
92
- client1.on('connect', function () {
93
- // console.log('External client1 connected');
94
- });
95
- const n2 = helper.getNode('n2');
96
- n2.on('input', function (msg) {
97
- // console.log('Broker received message topic: ' + msg.topic + ', clientid: ' + msg.payload.client.id);
98
- if (msg.topic === 'clientReady') {
99
- // console.log('Topic: ' + msg.payload.client.will.topic);
100
- // console.log('Payload: ' + msg.payload.client.will.payload.toString());
101
- should(msg.payload.client.will.topic).equal('testLastWill');
102
- should(msg.payload.client.will.payload.toString()).equal('last will');
103
- client1.end(function () {
104
- done();
105
- });
106
- }
61
+ const n1 = helper.getNode('n1');
62
+ n1._initPromise.then(function () {
63
+ const client1 = mqtt.connect('mqtt://localhost:1883', {
64
+ clientId: 'client1',
65
+ will: { topic: 'testLastWill', payload: 'last will' }
66
+ });
67
+ client1.on('error', logError);
68
+ client1.on('connect', function () {
69
+ // console.log('External client1 connected');
70
+ });
71
+ const n2 = helper.getNode('n2');
72
+ n2.on('input', function (msg) {
73
+ // console.log('Broker received message topic: ' + msg.topic + ', clientid: ' + msg.payload.client.id);
74
+ if (msg.topic === 'clientReady') {
75
+ // console.log('Topic: ' + msg.payload.client.will.topic);
76
+ // console.log('Payload: ' + msg.payload.client.will.payload.toString());
77
+ should(msg.payload.client.will.topic).equal('testLastWill');
78
+ should(msg.payload.client.will.payload.toString()).equal('last will');
79
+ client1.end(function () {
80
+ done();
81
+ });
82
+ }
83
+ });
107
84
  });
108
85
  });
109
86
  });