@machhub-dev/node-red-nodes 1.0.9-test → 1.0.10-test
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.
- package/dist/lib/services/mqtt.service.js +10 -45
- package/dist/nodes/bulk-tag-write.js +14 -15
- package/dist/nodes/tag-read.js +6 -20
- package/dist/nodes/tag-write.js +14 -15
- package/package.json +1 -1
|
@@ -15,11 +15,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
15
15
|
exports.MQTTService = void 0;
|
|
16
16
|
const mqtt_1 = __importDefault(require("mqtt"));
|
|
17
17
|
class MQTTService {
|
|
18
|
+
constructor() {
|
|
19
|
+
this.subscribedTopics = [];
|
|
20
|
+
}
|
|
18
21
|
static getInstance(settings, statusCallback) {
|
|
19
22
|
return __awaiter(this, void 0, void 0, function* () {
|
|
20
23
|
// If we already have an instance, return it
|
|
21
24
|
if (this.instance && this.instance.client && this.instance.client.connected) {
|
|
22
|
-
console.log("Returning existing MQTT instance");
|
|
23
25
|
if (statusCallback) {
|
|
24
26
|
statusCallback({ fill: "green", shape: "dot", text: "MQTT Connected" });
|
|
25
27
|
}
|
|
@@ -39,6 +41,7 @@ class MQTTService {
|
|
|
39
41
|
this.instancePromise = this.createInstance(settings, statusCallback);
|
|
40
42
|
try {
|
|
41
43
|
this.instance = yield this.instancePromise;
|
|
44
|
+
this.instancePromise = null; // Clear so future calls re-evaluate fresh state
|
|
42
45
|
return this.instance;
|
|
43
46
|
}
|
|
44
47
|
catch (error) {
|
|
@@ -106,17 +109,8 @@ class MQTTService {
|
|
|
106
109
|
clientId: settings.clientId,
|
|
107
110
|
username: settings.clientId,
|
|
108
111
|
password: settings.clientSecret,
|
|
109
|
-
reconnectPeriod: 0, // disable MQTT.js auto-reconnect; we manage reconnection via getInstance()
|
|
110
112
|
});
|
|
111
113
|
instance.attachMessageListener();
|
|
112
|
-
// Re-subscribe any topics registered before this connection was established
|
|
113
|
-
for (const sub of MQTTService.subscribedTopics) {
|
|
114
|
-
instance.client.subscribe(sub.topic, { qos: 2 }, (err) => {
|
|
115
|
-
if (err) {
|
|
116
|
-
console.error(`Failed to re-subscribe to topic ${sub.topic}:`, err);
|
|
117
|
-
}
|
|
118
|
-
});
|
|
119
|
-
}
|
|
120
114
|
// console.log("MQTT connection established successfully");
|
|
121
115
|
if (statusCallback) {
|
|
122
116
|
statusCallback({ fill: "green", shape: "dot", text: "MQTT Connected" });
|
|
@@ -134,22 +128,19 @@ class MQTTService {
|
|
|
134
128
|
return instance;
|
|
135
129
|
});
|
|
136
130
|
}
|
|
137
|
-
// Method to reset the instance
|
|
131
|
+
// Method to reset the instance
|
|
138
132
|
static resetInstance() {
|
|
139
|
-
|
|
140
|
-
|
|
133
|
+
if (this.instance && this.instance.client) {
|
|
134
|
+
this.instance.client.end();
|
|
135
|
+
}
|
|
141
136
|
this.instance = null;
|
|
142
137
|
this.instancePromise = null;
|
|
143
138
|
this.stopConnecting = true;
|
|
144
|
-
this.subscribedTopics = [];
|
|
145
|
-
if (inst && inst.client) {
|
|
146
|
-
inst.client.end();
|
|
147
|
-
}
|
|
148
139
|
}
|
|
149
140
|
// Adds a topic and handler to the subscribed list
|
|
150
141
|
addTopicHandler(topic, handler) {
|
|
151
142
|
try {
|
|
152
|
-
|
|
143
|
+
this.subscribedTopics.push({ topic, handler });
|
|
153
144
|
// console.log("New Subscription Handler : ", topic)
|
|
154
145
|
this.client.subscribe(topic, { qos: 2 }, (err) => {
|
|
155
146
|
if (err) {
|
|
@@ -161,23 +152,6 @@ class MQTTService {
|
|
|
161
152
|
console.error(`Failed to subscribe to topic ${topic}:`, e);
|
|
162
153
|
}
|
|
163
154
|
}
|
|
164
|
-
// Removes a topic handler and unsubscribes from the broker if no other handler covers the same topic
|
|
165
|
-
removeTopicHandler(topic, handler) {
|
|
166
|
-
MQTTService.subscribedTopics = MQTTService.subscribedTopics.filter(st => !(st.topic === topic && st.handler === handler));
|
|
167
|
-
const stillSubscribed = MQTTService.subscribedTopics.some(st => st.topic === topic);
|
|
168
|
-
if (!stillSubscribed) {
|
|
169
|
-
try {
|
|
170
|
-
this.client.unsubscribe(topic, (err) => {
|
|
171
|
-
if (err) {
|
|
172
|
-
console.error(`Failed to unsubscribe from topic ${topic}:`, err);
|
|
173
|
-
}
|
|
174
|
-
});
|
|
175
|
-
}
|
|
176
|
-
catch (e) {
|
|
177
|
-
console.error(`Failed to unsubscribe from topic ${topic}:`, e);
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
155
|
// Publishes a message to a specific topic
|
|
182
156
|
publish(topic, message) {
|
|
183
157
|
try {
|
|
@@ -202,7 +176,7 @@ class MQTTService {
|
|
|
202
176
|
}
|
|
203
177
|
attachMessageListener() {
|
|
204
178
|
this.client.on('message', (topic, message, packet) => {
|
|
205
|
-
for (const subscribedTopic of
|
|
179
|
+
for (const subscribedTopic of this.subscribedTopics) {
|
|
206
180
|
if (this.matchesTopic(subscribedTopic.topic, topic)) {
|
|
207
181
|
const parsedMessage = this.parseMessage(message, topic);
|
|
208
182
|
subscribedTopic.handler(parsedMessage, packet.retain);
|
|
@@ -210,14 +184,6 @@ class MQTTService {
|
|
|
210
184
|
}
|
|
211
185
|
}
|
|
212
186
|
});
|
|
213
|
-
// When the broker closes the connection (e.g. session expired), self-reset so the
|
|
214
|
-
// next getInstance() call creates a fresh client with an empty in-flight store.
|
|
215
|
-
this.client.on('close', () => {
|
|
216
|
-
if (MQTTService.instance === this) {
|
|
217
|
-
MQTTService.instance = null;
|
|
218
|
-
MQTTService.instancePromise = null;
|
|
219
|
-
}
|
|
220
|
-
});
|
|
221
187
|
}
|
|
222
188
|
// Matches MQTT topic patterns with wildcards (+ for single level, # for multi-level)
|
|
223
189
|
matchesTopic(pattern, topic) {
|
|
@@ -266,4 +232,3 @@ class MQTTService {
|
|
|
266
232
|
exports.MQTTService = MQTTService;
|
|
267
233
|
MQTTService.instancePromise = null;
|
|
268
234
|
MQTTService.stopConnecting = false;
|
|
269
|
-
MQTTService.subscribedTopics = [];
|
|
@@ -56,6 +56,7 @@ function default_1(RED) {
|
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
58
|
node.on('close', () => {
|
|
59
|
+
mqtt_service_1.MQTTService.resetInstance();
|
|
59
60
|
mqttService = null;
|
|
60
61
|
initializationPromise = null;
|
|
61
62
|
});
|
|
@@ -63,13 +64,18 @@ function default_1(RED) {
|
|
|
63
64
|
return __awaiter(this, void 0, void 0, function* () {
|
|
64
65
|
try {
|
|
65
66
|
node.status({ fill: "orange", shape: "dot", text: "Sending Payload" });
|
|
66
|
-
//
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
}
|
|
67
|
+
// Wait for initialization if still in progress
|
|
68
|
+
if (isInitializing && initializationPromise) {
|
|
69
|
+
yield initializationPromise;
|
|
70
|
+
}
|
|
71
|
+
// Check if mqttService is initialized
|
|
72
|
+
if (!mqttService) {
|
|
73
|
+
node.status({ fill: "red", shape: "dot", text: "MQTT service not initialized" });
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
70
76
|
Object.keys(msg.payload).forEach(function (key) {
|
|
71
77
|
try {
|
|
72
|
-
|
|
78
|
+
mqttService.publish(key, msg.payload[key]);
|
|
73
79
|
}
|
|
74
80
|
catch (error) {
|
|
75
81
|
node.status({ fill: "red", shape: "dot", text: "Failed to publish to '" + key + "': " + error.toString() });
|
|
@@ -88,16 +94,9 @@ function default_1(RED) {
|
|
|
88
94
|
isInitializing = true;
|
|
89
95
|
node.status({ fill: "yellow", shape: "dot", text: "Connecting..." });
|
|
90
96
|
// Use MACHHUB config to get MQTT service with status callback
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
node.status(status);
|
|
95
|
-
});
|
|
96
|
-
// console.log("MQTT Service obtained client:", mqttService.client);
|
|
97
|
-
if (mqttService.client) {
|
|
98
|
-
break;
|
|
99
|
-
}
|
|
100
|
-
}
|
|
97
|
+
mqttService = yield mqtt_service_1.MQTTService.getInstance(machhubConfig, (status) => {
|
|
98
|
+
node.status(status);
|
|
99
|
+
});
|
|
101
100
|
node.status({ fill: "green", shape: "dot", text: "Ready to publish" });
|
|
102
101
|
}
|
|
103
102
|
catch (error) {
|
package/dist/nodes/tag-read.js
CHANGED
|
@@ -61,36 +61,22 @@ function default_1(RED) {
|
|
|
61
61
|
isRetained: false,
|
|
62
62
|
payload: undefined
|
|
63
63
|
};
|
|
64
|
-
let mqttService = null;
|
|
65
|
-
let topicHandler = null;
|
|
66
64
|
node.on('close', function () {
|
|
67
|
-
|
|
68
|
-
mqttService.removeTopicHandler(node.selectedTag, topicHandler);
|
|
69
|
-
}
|
|
70
|
-
mqttService = null;
|
|
71
|
-
topicHandler = null;
|
|
65
|
+
mqtt_service_1.MQTTService.resetInstance();
|
|
72
66
|
});
|
|
73
67
|
(() => __awaiter(this, void 0, void 0, function* () {
|
|
74
68
|
try {
|
|
75
69
|
node.status({ fill: "yellow", shape: "dot", text: "Connecting..." });
|
|
76
70
|
// Use MACHHUB config from machhub.env.json to get MQTT service with status callback
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
});
|
|
82
|
-
// console.log("MQTT Service obtained client:", mqttService.client);
|
|
83
|
-
if (mqttService.client) {
|
|
84
|
-
break;
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
topicHandler = (message, isRetained) => {
|
|
71
|
+
const mqttService = yield mqtt_service_1.MQTTService.getInstance(machhubConfig, (status) => {
|
|
72
|
+
node.status(status);
|
|
73
|
+
});
|
|
74
|
+
mqttService.addTopicHandler(node.selectedTag, (message, isRetained) => {
|
|
88
75
|
msg.payload = message;
|
|
89
76
|
msg.isRetained = isRetained;
|
|
90
77
|
node.send(msg);
|
|
91
78
|
node.status({ fill: "green", shape: "dot", text: "Payload Received" });
|
|
92
|
-
};
|
|
93
|
-
mqttService.addTopicHandler(node.selectedTag, topicHandler);
|
|
79
|
+
});
|
|
94
80
|
node.status({ fill: "green", shape: "dot", text: "MQTT Listening" });
|
|
95
81
|
}
|
|
96
82
|
catch (error) {
|
package/dist/nodes/tag-write.js
CHANGED
|
@@ -58,17 +58,23 @@ function default_1(RED) {
|
|
|
58
58
|
}
|
|
59
59
|
}
|
|
60
60
|
node.on('close', () => {
|
|
61
|
+
mqtt_service_1.MQTTService.resetInstance();
|
|
61
62
|
mqttService = null;
|
|
62
63
|
initializationPromise = null;
|
|
63
64
|
});
|
|
64
65
|
node.on('input', (msg) => __awaiter(this, void 0, void 0, function* () {
|
|
65
66
|
try {
|
|
66
67
|
node.status({ fill: "orange", shape: "dot", text: "Sending Payload" });
|
|
67
|
-
//
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
}
|
|
71
|
-
|
|
68
|
+
// Wait for initialization if still in progress
|
|
69
|
+
if (isInitializing && initializationPromise) {
|
|
70
|
+
yield initializationPromise;
|
|
71
|
+
}
|
|
72
|
+
// Check if mqttService is initialized
|
|
73
|
+
if (!mqttService) {
|
|
74
|
+
node.status({ fill: "red", shape: "dot", text: "MQTT service not initialized" });
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
yield mqttService.publish(node.selectedTag, msg.payload);
|
|
72
78
|
node.status({ fill: "green", shape: "dot", text: "Payload Sent" });
|
|
73
79
|
}
|
|
74
80
|
catch (err) {
|
|
@@ -80,16 +86,9 @@ function default_1(RED) {
|
|
|
80
86
|
try {
|
|
81
87
|
isInitializing = true;
|
|
82
88
|
node.status({ fill: "yellow", shape: "dot", text: "Connecting..." });
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
node.status(status);
|
|
87
|
-
});
|
|
88
|
-
// console.log("MQTT Service obtained client:", mqttService.client);
|
|
89
|
-
if (mqttService.client) {
|
|
90
|
-
break;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
89
|
+
mqttService = yield mqtt_service_1.MQTTService.getInstance(machhubConfig, (status) => {
|
|
90
|
+
node.status(status);
|
|
91
|
+
});
|
|
93
92
|
node.status({ fill: "green", shape: "dot", text: "Ready to publish" });
|
|
94
93
|
}
|
|
95
94
|
catch (error) {
|