@uns-kit/core 2.0.19 → 2.0.20
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.
|
@@ -3,6 +3,14 @@ import { UnsEvents } from "../uns/uns-interfaces.js";
|
|
|
3
3
|
import { UnsEventEmitter } from "../uns/uns-event-emitter.js";
|
|
4
4
|
import { IMqttParameters } from "./mqtt-interfaces.js";
|
|
5
5
|
import { MqttWorker } from "./mqtt-worker.js";
|
|
6
|
+
export type MqttStopOptions = {
|
|
7
|
+
silent?: boolean;
|
|
8
|
+
reason?: "retry" | "shutdown";
|
|
9
|
+
};
|
|
10
|
+
type MqttErrorInfo = {
|
|
11
|
+
code: string | number;
|
|
12
|
+
message: string;
|
|
13
|
+
};
|
|
6
14
|
export default class MqttProxy {
|
|
7
15
|
event: UnsEventEmitter<UnsEvents>;
|
|
8
16
|
statusTopic: string;
|
|
@@ -23,6 +31,7 @@ export default class MqttProxy {
|
|
|
23
31
|
isConnected: boolean;
|
|
24
32
|
private rejectUnauthorized;
|
|
25
33
|
private pendingReconnectWait;
|
|
34
|
+
private hasEstablishedConnection;
|
|
26
35
|
constructor(mqttHost: string, instanceName: string, mqttParameters: IMqttParameters, mqttWorker?: MqttWorker);
|
|
27
36
|
private resolveProtocol;
|
|
28
37
|
private resolveDefaultPort;
|
|
@@ -31,11 +40,13 @@ export default class MqttProxy {
|
|
|
31
40
|
publish(topic: string, message: string | Buffer, options?: mqtt.IClientPublishOptions): Promise<void>;
|
|
32
41
|
subscribeAsync(topic: string | string[], options?: mqtt.IClientSubscribeOptions): Promise<mqtt.ISubscriptionGrant[]>;
|
|
33
42
|
unsubscribeAsync(topic: string | string[]): Promise<mqtt.Packet | undefined>;
|
|
34
|
-
stop(): void;
|
|
43
|
+
stop(options?: MqttStopOptions): void;
|
|
35
44
|
private emitStatusUpdates;
|
|
36
45
|
private updatePublishTransformationStats;
|
|
37
46
|
private updateSubscribeTransformationStats;
|
|
38
47
|
private waitForReconnect;
|
|
39
48
|
private emitTransformationStatistics;
|
|
40
49
|
}
|
|
50
|
+
export declare function formatMqttError(error: unknown): MqttErrorInfo;
|
|
51
|
+
export {};
|
|
41
52
|
//# sourceMappingURL=mqtt-proxy.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mqtt-proxy.d.ts","sourceRoot":"","sources":["../../src/uns-mqtt/mqtt-proxy.ts"],"names":[],"mappings":"AAAA,OAAO,IAAoC,MAAM,MAAM,CAAC;AAExD,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAG9C,MAAM,CAAC,OAAO,OAAO,SAAS;IACrB,KAAK,EAAE,eAAe,CAAC,SAAS,CAAC,CAAoC;IACrE,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IAC5B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,eAAe,CAAoB;IAC3C,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,SAAS,CAAO;IACxB,OAAO,CAAC,cAAc,CAAkB;IACxC,OAAO,CAAC,oBAAoB,CAAiC;IAC7D,OAAO,CAAC,2BAA2B,CAA+B;IAClE,OAAO,CAAC,qBAAqB,CAAK;IAClC,OAAO,CAAC,qBAAqB,CAAK;IAClC,OAAO,CAAC,sBAAsB,CAAK;IACnC,OAAO,CAAC,sBAAsB,CAAK;IACnC,OAAO,CAAC,UAAU,CAAa;IACxB,WAAW,UAAS;IAC3B,OAAO,CAAC,kBAAkB,CAAU;IACpC,OAAO,CAAC,oBAAoB,CAA8B;
|
|
1
|
+
{"version":3,"file":"mqtt-proxy.d.ts","sourceRoot":"","sources":["../../src/uns-mqtt/mqtt-proxy.ts"],"names":[],"mappings":"AAAA,OAAO,IAAoC,MAAM,MAAM,CAAC;AAExD,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAG9C,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,GAAG,UAAU,CAAC;CAC/B,CAAC;AAEF,KAAK,aAAa,GAAG;IACnB,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,CAAC,OAAO,OAAO,SAAS;IACrB,KAAK,EAAE,eAAe,CAAC,SAAS,CAAC,CAAoC;IACrE,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IAC5B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,eAAe,CAAoB;IAC3C,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,SAAS,CAAO;IACxB,OAAO,CAAC,cAAc,CAAkB;IACxC,OAAO,CAAC,oBAAoB,CAAiC;IAC7D,OAAO,CAAC,2BAA2B,CAA+B;IAClE,OAAO,CAAC,qBAAqB,CAAK;IAClC,OAAO,CAAC,qBAAqB,CAAK;IAClC,OAAO,CAAC,sBAAsB,CAAK;IACnC,OAAO,CAAC,sBAAsB,CAAK;IACnC,OAAO,CAAC,UAAU,CAAa;IACxB,WAAW,UAAS;IAC3B,OAAO,CAAC,kBAAkB,CAAU;IACpC,OAAO,CAAC,oBAAoB,CAA8B;IAC1D,OAAO,CAAC,wBAAwB,CAAS;gBAE7B,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,cAAc,EAAE,eAAe,EAAE,UAAU,CAAC,EAAE,UAAU;IAY5G,OAAO,CAAC,eAAe;IAIvB,OAAO,CAAC,kBAAkB;IAgB1B,OAAO,CAAC,YAAY;IA0CP,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAyItB,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC;IA8BrG,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC,kBAAkB,EAAE,CAAC;IAIpH,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC;IASlF,IAAI,CAAC,OAAO,GAAE,eAAoB;IAsCzC,OAAO,CAAC,iBAAiB;IAiBzB,OAAO,CAAC,gCAAgC;IAKxC,OAAO,CAAC,kCAAkC;IAK1C,OAAO,CAAC,gBAAgB;YAsCV,4BAA4B;CAwC3C;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,aAAa,CAY7D"}
|
|
@@ -22,6 +22,7 @@ export default class MqttProxy {
|
|
|
22
22
|
isConnected = false;
|
|
23
23
|
rejectUnauthorized;
|
|
24
24
|
pendingReconnectWait = null;
|
|
25
|
+
hasEstablishedConnection = false;
|
|
25
26
|
constructor(mqttHost, instanceName, mqttParameters, mqttWorker) {
|
|
26
27
|
this.mqttSSL = mqttParameters?.mqttSSL ?? false;
|
|
27
28
|
this.rejectUnauthorized = mqttParameters.rejectUnauthorized ?? false;
|
|
@@ -93,7 +94,7 @@ export default class MqttProxy {
|
|
|
93
94
|
return servers.length > 0 ? servers : undefined;
|
|
94
95
|
}
|
|
95
96
|
async start() {
|
|
96
|
-
logger.
|
|
97
|
+
logger.debug(`${this.instanceName} - Connecting to MQTT broker...`);
|
|
97
98
|
return new Promise((resolve, reject) => {
|
|
98
99
|
try {
|
|
99
100
|
const username = this.mqttParameters.username;
|
|
@@ -141,9 +142,10 @@ export default class MqttProxy {
|
|
|
141
142
|
const onConnect = () => {
|
|
142
143
|
try {
|
|
143
144
|
this.mqttClient.stream.setMaxListeners(0);
|
|
145
|
+
this.hasEstablishedConnection = true;
|
|
144
146
|
logger.info(`${this.instanceName} - Connected to MQTT broker at ${this.mqttHost}`);
|
|
145
147
|
if (this.mqttSubToTopics && this.mqttSubToTopics.length > 0) {
|
|
146
|
-
logger.
|
|
148
|
+
logger.debug(`${this.instanceName} - Subscribed to ${this.mqttSubToTopics.length} topics.`);
|
|
147
149
|
this.mqttClient.subscribe(this.mqttSubToTopics, { qos: 0 });
|
|
148
150
|
}
|
|
149
151
|
if (this.statusTopic) {
|
|
@@ -157,7 +159,7 @@ export default class MqttProxy {
|
|
|
157
159
|
resolve();
|
|
158
160
|
}
|
|
159
161
|
catch (error) {
|
|
160
|
-
logger.error(`${this.instanceName} - Error in MQTT connect handler: ${error.message}`);
|
|
162
|
+
logger.error(`${this.instanceName} - Error in MQTT connect handler: ${formatMqttError(error).message}`);
|
|
161
163
|
this.isConnected = false;
|
|
162
164
|
reject(error);
|
|
163
165
|
}
|
|
@@ -178,14 +180,13 @@ export default class MqttProxy {
|
|
|
178
180
|
}
|
|
179
181
|
});
|
|
180
182
|
this.mqttClient.on("error", (error) => {
|
|
181
|
-
|
|
183
|
+
const errorInfo = formatMqttError(error);
|
|
184
|
+
logger.error(`${this.instanceName} - MQTT client error: ${errorInfo.message}`);
|
|
182
185
|
this.isConnected = false;
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
this.event.emit("error", { message: error.message, code: 0 });
|
|
188
|
-
}
|
|
186
|
+
this.event.emit("error", {
|
|
187
|
+
code: typeof errorInfo.code === "number" ? errorInfo.code : 0,
|
|
188
|
+
message: errorInfo.message,
|
|
189
|
+
});
|
|
189
190
|
reject(error);
|
|
190
191
|
});
|
|
191
192
|
this.mqttClient.on("reconnect", () => {
|
|
@@ -209,7 +210,7 @@ export default class MqttProxy {
|
|
|
209
210
|
});
|
|
210
211
|
}
|
|
211
212
|
catch (error) {
|
|
212
|
-
logger.error(`${this.instanceName} - Error starting MQTT proxy: ${error.message}`);
|
|
213
|
+
logger.error(`${this.instanceName} - Error starting MQTT proxy: ${formatMqttError(error).message}`);
|
|
213
214
|
this.isConnected = false;
|
|
214
215
|
reject(error);
|
|
215
216
|
}
|
|
@@ -252,8 +253,12 @@ export default class MqttProxy {
|
|
|
252
253
|
}
|
|
253
254
|
return this.mqttClient.unsubscribeAsync(topics);
|
|
254
255
|
}
|
|
255
|
-
stop() {
|
|
256
|
-
|
|
256
|
+
stop(options = {}) {
|
|
257
|
+
const silent = options.silent === true || options.reason === "retry";
|
|
258
|
+
const shouldLogDisconnect = !silent && this.hasEstablishedConnection;
|
|
259
|
+
if (shouldLogDisconnect) {
|
|
260
|
+
logger.debug(`${this.instanceName} - Disconnecting from MQTT broker...`);
|
|
261
|
+
}
|
|
257
262
|
try {
|
|
258
263
|
if (this.statusUpdateInterval) {
|
|
259
264
|
clearInterval(this.statusUpdateInterval);
|
|
@@ -266,13 +271,23 @@ export default class MqttProxy {
|
|
|
266
271
|
if (this.mqttClient) {
|
|
267
272
|
this.mqttClient.end(false, () => {
|
|
268
273
|
this.isConnected = false;
|
|
269
|
-
|
|
274
|
+
this.pendingReconnectWait = null;
|
|
275
|
+
if (shouldLogDisconnect) {
|
|
276
|
+
logger.debug(`${this.instanceName} - Disconnected from MQTT broker.`);
|
|
277
|
+
}
|
|
270
278
|
});
|
|
271
279
|
}
|
|
280
|
+
else {
|
|
281
|
+
this.isConnected = false;
|
|
282
|
+
this.pendingReconnectWait = null;
|
|
283
|
+
}
|
|
272
284
|
}
|
|
273
285
|
catch (error) {
|
|
274
|
-
|
|
286
|
+
if (!silent) {
|
|
287
|
+
logger.error(`${this.instanceName} - Error during stop: ${formatMqttError(error).message}`);
|
|
288
|
+
}
|
|
275
289
|
this.isConnected = false;
|
|
290
|
+
this.pendingReconnectWait = null;
|
|
276
291
|
}
|
|
277
292
|
}
|
|
278
293
|
emitStatusUpdates() {
|
|
@@ -373,4 +388,66 @@ export default class MqttProxy {
|
|
|
373
388
|
}
|
|
374
389
|
}
|
|
375
390
|
}
|
|
391
|
+
export function formatMqttError(error) {
|
|
392
|
+
const parts = [];
|
|
393
|
+
const codes = [];
|
|
394
|
+
collectMqttErrorParts(error, parts, codes);
|
|
395
|
+
const uniqueParts = Array.from(new Set(parts.map((part) => part.trim()).filter(Boolean)));
|
|
396
|
+
const message = uniqueParts.join("; ") || "Unknown MQTT error";
|
|
397
|
+
return {
|
|
398
|
+
code: codes[0] ?? 0,
|
|
399
|
+
message,
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
function collectMqttErrorParts(error, parts, codes) {
|
|
403
|
+
if (error instanceof AggregateError) {
|
|
404
|
+
if (typeof error.message === "string" && error.message.trim()) {
|
|
405
|
+
parts.push(error.message.trim());
|
|
406
|
+
}
|
|
407
|
+
for (const nested of error.errors) {
|
|
408
|
+
collectMqttErrorParts(nested, parts, codes);
|
|
409
|
+
}
|
|
410
|
+
return;
|
|
411
|
+
}
|
|
412
|
+
if (typeof error === "string") {
|
|
413
|
+
if (error.trim()) {
|
|
414
|
+
parts.push(error.trim());
|
|
415
|
+
}
|
|
416
|
+
return;
|
|
417
|
+
}
|
|
418
|
+
if (!error || typeof error !== "object") {
|
|
419
|
+
return;
|
|
420
|
+
}
|
|
421
|
+
const record = error;
|
|
422
|
+
const code = typeof record.code === "string" || typeof record.code === "number"
|
|
423
|
+
? record.code
|
|
424
|
+
: undefined;
|
|
425
|
+
if (code !== undefined) {
|
|
426
|
+
codes.push(code);
|
|
427
|
+
}
|
|
428
|
+
const message = typeof record.message === "string" && record.message.trim()
|
|
429
|
+
? record.message.trim()
|
|
430
|
+
: undefined;
|
|
431
|
+
const address = typeof record.address === "string" && record.address.trim()
|
|
432
|
+
? record.address.trim()
|
|
433
|
+
: undefined;
|
|
434
|
+
const port = typeof record.port === "number" ? record.port : undefined;
|
|
435
|
+
const endpoint = address || port !== undefined
|
|
436
|
+
? `${address ?? ""}${address && port !== undefined ? ":" : ""}${port ?? ""}`.trim()
|
|
437
|
+
: undefined;
|
|
438
|
+
const detailParts = [
|
|
439
|
+
code !== undefined && !message?.includes(String(code)) ? String(code) : undefined,
|
|
440
|
+
message,
|
|
441
|
+
endpoint && !message?.includes(endpoint) ? endpoint : undefined,
|
|
442
|
+
].filter((part) => typeof part === "string" && part.length > 0);
|
|
443
|
+
if (detailParts.length > 0) {
|
|
444
|
+
parts.push(detailParts.join(" "));
|
|
445
|
+
}
|
|
446
|
+
else if (typeof record.name === "string" && record.name.trim()) {
|
|
447
|
+
parts.push(record.name.trim());
|
|
448
|
+
}
|
|
449
|
+
if (record.cause !== undefined) {
|
|
450
|
+
collectMqttErrorParts(record.cause, parts, codes);
|
|
451
|
+
}
|
|
452
|
+
}
|
|
376
453
|
//# sourceMappingURL=mqtt-proxy.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mqtt-proxy.js","sourceRoot":"","sources":["../../src/uns-mqtt/mqtt-proxy.ts"],"names":[],"mappings":"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","sourcesContent":["import mqtt, { IClientOptions, MqttClient } from \"mqtt\";\nimport logger from \"../logger.js\";\nimport { UnsEvents } from \"../uns/uns-interfaces.js\";\nimport { UnsEventEmitter } from \"../uns/uns-event-emitter.js\";\nimport { IMqttParameters } from \"./mqtt-interfaces.js\";\nimport { MqttWorker } from \"./mqtt-worker.js\";\nimport { DataSizeMeasurements, PhysicalMeasurements } from \"../uns/uns-measurements.js\";\n\nexport default class MqttProxy {\n public event: UnsEventEmitter<UnsEvents> = new UnsEventEmitter<UnsEvents>();\n public statusTopic: string;\n public instanceName: string;\n private mqttHost: string;\n private mqttSubToTopics: string | string[];\n private mqttSSL: boolean;\n private mqttClient: MqttClient;\n private startDate: Date;\n private mqttParameters: IMqttParameters;\n private statusUpdateInterval: ReturnType<typeof setInterval>;\n private transformationStatsInterval: NodeJS.Timeout | null = null;\n private publishedMessageCount = 0;\n private publishedMessageBytes = 0;\n private subscribedMessageCount = 0;\n private subscribedMessageBytes = 0;\n private mqttWorker: MqttWorker;\n public isConnected = false;\n private rejectUnauthorized: boolean;\n private pendingReconnectWait: Promise<void> | null = null;\n\n constructor(mqttHost: string, instanceName: string, mqttParameters: IMqttParameters, mqttWorker?: MqttWorker) {\n this.mqttSSL = mqttParameters?.mqttSSL ?? false;\n this.rejectUnauthorized = mqttParameters.rejectUnauthorized ?? false;\n this.mqttSubToTopics = mqttParameters?.mqttSubToTopics ?? [];\n this.mqttHost = mqttHost;\n this.startDate = new Date();\n this.instanceName = instanceName ?? \"process\";\n this.statusTopic = `${mqttParameters?.statusTopic}`;\n this.mqttParameters = mqttParameters ?? {};\n this.mqttWorker = mqttWorker;\n }\n\n private resolveProtocol(): IMqttParameters[\"protocol\"] {\n return this.mqttParameters.protocol ?? (this.mqttSSL ? \"mqtts\" : \"mqtt\");\n }\n\n private resolveDefaultPort(protocol: IMqttParameters[\"protocol\"]): number {\n switch (protocol) {\n case \"mqtts\":\n case \"ssl\":\n return 8883;\n case \"wss\":\n return 443;\n case \"ws\":\n return 80;\n case \"tcp\":\n case \"mqtt\":\n default:\n return 1883;\n }\n }\n\n private buildServers(defaultProtocol: IMqttParameters[\"protocol\"]): IClientOptions[\"servers\"] | undefined {\n const servers: IClientOptions[\"servers\"] = [];\n const { port } = this.mqttParameters;\n const protocol = this.mqttParameters.protocol ?? defaultProtocol;\n\n if (Array.isArray(this.mqttParameters.servers) && this.mqttParameters.servers.length > 0) {\n for (const server of this.mqttParameters.servers) {\n if (!server?.host) continue;\n const resolvedProtocol = server.protocol ?? protocol;\n const resolvedPort =\n typeof server.port === \"number\"\n ? server.port\n : typeof port === \"number\"\n ? port\n : this.resolveDefaultPort(resolvedProtocol);\n const entry: { host: string; port: number; protocol?: IMqttParameters[\"protocol\"] } = {\n host: server.host,\n port: resolvedPort,\n };\n if (resolvedProtocol) {\n entry.protocol = resolvedProtocol;\n }\n servers.push(entry);\n }\n } else if (Array.isArray(this.mqttParameters.hosts) && this.mqttParameters.hosts.length > 0) {\n for (const host of this.mqttParameters.hosts) {\n if (!host) continue;\n const resolvedPort = typeof port === \"number\" ? port : this.resolveDefaultPort(protocol);\n const entry: { host: string; port: number; protocol?: IMqttParameters[\"protocol\"] } = {\n host,\n port: resolvedPort,\n };\n if (protocol) {\n entry.protocol = protocol;\n }\n servers.push(entry);\n }\n }\n\n return servers.length > 0 ? servers : undefined;\n }\n\n public async start(): Promise<void> {\n logger.info(`${this.instanceName} - Connecting to MQTT broker...`);\n\n return new Promise<void>((resolve, reject) => {\n try {\n const username = this.mqttParameters.username;\n const password = this.mqttParameters.password;\n const clientId = this.mqttParameters.clientId ?? this.instanceName;\n const protocol = this.resolveProtocol();\n\n const options: IClientOptions = {\n username,\n password,\n protocolVersion: 5,\n rejectUnauthorized: this.rejectUnauthorized,\n keepalive: this.mqttParameters.keepalive,\n clean: this.mqttParameters.clean ?? true,\n connectTimeout: this.mqttParameters.connectTimeout,\n reconnectPeriod: this.mqttParameters.reconnectPeriod,\n reconnectOnConnackError: this.mqttParameters.reconnectOnConnackError,\n resubscribe: this.mqttParameters.resubscribe,\n queueQoSZero: this.mqttParameters.queueQoSZero,\n properties: this.mqttParameters.properties,\n ca: this.mqttParameters.ca,\n cert: this.mqttParameters.cert,\n key: this.mqttParameters.key,\n servername: this.mqttParameters.servername,\n \n will: {\n topic: `${this.statusTopic}alive`,\n payload: Buffer.from(\"\"),\n qos: 0,\n retain: true,\n properties: { messageExpiryInterval: 3600 },\n },\n clientId,\n };\n\n const servers = this.buildServers(protocol);\n if (servers) {\n options.servers = servers;\n options.protocol = protocol;\n this.mqttClient = mqtt.connect(options);\n } else {\n options.host = this.mqttHost;\n options.port = this.mqttParameters.port;\n options.protocol = protocol;\n this.mqttClient = mqtt.connect(options);\n }\n\n const onConnect = () => {\n try {\n this.mqttClient.stream.setMaxListeners(0);\n logger.info(`${this.instanceName} - Connected to MQTT broker at ${this.mqttHost}`);\n\n if (this.mqttSubToTopics && this.mqttSubToTopics.length > 0) {\n logger.info(`${this.instanceName} - Subscribed to ${this.mqttSubToTopics.length} topics.`);\n this.mqttClient.subscribe(this.mqttSubToTopics, { qos: 0 });\n }\n\n if (this.statusTopic) {\n this.statusUpdateInterval = setInterval(() => this.emitStatusUpdates(), 10000);\n }\n\n this.transformationStatsInterval = setInterval(() => {\n this.emitTransformationStatistics();\n }, 60000);\n\n this.mqttClient.off(\"connect\", onConnect);\n this.isConnected = true;\n resolve();\n } catch (error) {\n logger.error(`${this.instanceName} - Error in MQTT connect handler: ${error.message}`);\n this.isConnected = false;\n reject(error);\n }\n };\n\n this.mqttClient.on(\"connect\", onConnect);\n\n this.mqttClient.on(\"message\", (topic: string, message: Buffer, packet: mqtt.IPublishPacket) => {\n try {\n logger.debug(`${this.instanceName} - Message received on topic ${topic}`);\n this.event.emit(\"input\", {\n message: message.toString(),\n topic: topic,\n packet: packet,\n });\n this.updateSubscribeTransformationStats(message.length);\n } catch (error) {\n logger.error(`${this.instanceName} - Error in MQTT message handler: ${error.message}`);\n }\n });\n\n this.mqttClient.on(\"error\", (error) => {\n logger.error(`${this.instanceName} - MQTT client error: ${error.message}`);\n this.isConnected = false;\n if (\"code\" in error) {\n this.event.emit(\"error\", { code: error.code, message: error.message });\n } else {\n this.event.emit(\"error\", { message: error.message, code: 0 });\n }\n reject(error);\n });\n\n this.mqttClient.on(\"reconnect\", () => {\n logger.debug(`${this.instanceName} - Attempting to reconnect to MQTT broker...`);\n });\n\n this.mqttClient.on(\"close\", () => {\n logger.debug(`${this.instanceName} - MQTT connection closed.`);\n this.isConnected = false;\n });\n\n this.mqttClient.on(\"offline\", () => {\n logger.debug(`${this.instanceName} - MQTT client is offline.`);\n this.isConnected = false;\n });\n\n this.mqttClient.on(\"end\", () => {\n logger.debug(`${this.instanceName} - MQTT client connection ended.`);\n this.isConnected = false;\n });\n\n this.mqttClient.on(\"disconnect\", (packet) => {\n logger.debug(`${this.instanceName} - MQTT client disconnected. Reason: ${packet?.reasonCode}`);\n this.isConnected = false;\n });\n } catch (error) {\n logger.error(`${this.instanceName} - Error starting MQTT proxy: ${error.message}`);\n this.isConnected = false;\n reject(error);\n }\n });\n }\n\n public async publish(topic: string, message: string | Buffer, options?: mqtt.IClientPublishOptions): Promise<void> {\n this.updatePublishTransformationStats(JSON.stringify(message).length);\n const client = this.mqttClient;\n if (!client) {\n logger.warn(`${this.instanceName} - MQTT client missing; dropping publish to ${topic}`);\n return;\n }\n\n if (!client.connected) {\n // Wait briefly for reconnection before giving up.\n await this.waitForReconnect(client, 5000);\n }\n\n if (!client.connected) {\n logger.warn(`${this.instanceName} - MQTT client still disconnected; dropping publish to ${topic}`);\n return;\n }\n\n return new Promise((resolve, reject) => {\n client.publish(topic, message, options || {}, (err) => {\n if (err) {\n logger.error(`${this.instanceName} - Error publishing to topic ${topic}: ${err.message}`);\n return reject(err);\n }\n logger.debug(`${this.instanceName} - Published message to topic ${topic}`);\n resolve();\n });\n });\n }\n\n public async subscribeAsync(topic: string | string[], options?: mqtt.IClientSubscribeOptions): Promise<mqtt.ISubscriptionGrant[]> {\n return this.mqttClient.subscribeAsync(topic, options);\n }\n\n public async unsubscribeAsync(topic: string | string[]): Promise<mqtt.Packet | undefined> {\n const topics = Array.isArray(topic) ? topic.filter((t) => typeof t === \"string\" && t.length > 0) : [topic].filter((t): t is string => typeof t === \"string\" && t.length > 0);\n if (topics.length === 0) {\n logger.warn(`${this.instanceName} - unsubscribeAsync called with empty topic list; skipping.`);\n return Promise.resolve(undefined);\n }\n return this.mqttClient.unsubscribeAsync(topics);\n }\n\n public stop() {\n logger.info(`${this.instanceName} - Disconnecting from MQTT broker...`);\n try {\n if (this.statusUpdateInterval) {\n clearInterval(this.statusUpdateInterval);\n this.statusUpdateInterval = null;\n }\n if (this.transformationStatsInterval) {\n clearInterval(this.transformationStatsInterval);\n this.transformationStatsInterval = null;\n }\n if (this.mqttClient) {\n this.mqttClient.end(false, () => {\n this.isConnected = false;\n logger.info(`${this.instanceName} - Disconnected from MQTT broker.`);\n });\n }\n } catch (error) {\n logger.error(`${this.instanceName} - Error during stop: ${error.message}`);\n this.isConnected = false;\n }\n }\n\n private emitStatusUpdates() {\n try {\n const uptime = Math.round((new Date().getTime() - this.startDate.getTime()) / 60000);\n this.event.emit(\"mqttProxyStatus\", { event: \"uptime\", value: uptime, uom: PhysicalMeasurements.Minute, statusTopic: this.statusTopic + \"uptime\" });\n this.event.emit(\"mqttProxyStatus\", { event: \"alive\", value: 1, uom: DataSizeMeasurements.Bit, statusTopic: this.statusTopic + \"alive\" });\n\n if (this.mqttWorker !== undefined) {\n const tpValue = this.mqttWorker.getPublisherState() ? 1 : 0;\n this.event.emit(\"mqttProxyStatus\", { event: \"t-publisher-active\", value: tpValue, uom: DataSizeMeasurements.Bit, statusTopic: this.statusTopic + \"t-publisher-active\" });\n const tsValue = this.mqttWorker.getSubscriberState() ? 1 : 0;\n this.event.emit(\"mqttProxyStatus\", { event: \"t-subscriber-active\", value: tsValue, uom: DataSizeMeasurements.Bit, statusTopic: this.statusTopic + \"t-subscriber-active\" });\n }\n } catch (error) {\n logger.error(`${this.instanceName} - Error publishing MQTT status: ${error.message}`);\n }\n }\n\n private updatePublishTransformationStats(messageSizeOut: number): void {\n this.publishedMessageCount += 1;\n this.publishedMessageBytes += messageSizeOut;\n }\n\n private updateSubscribeTransformationStats(messageSizeIn: number): void {\n this.subscribedMessageCount += 1;\n this.subscribedMessageBytes += messageSizeIn;\n }\n\n private waitForReconnect(client: mqtt.MqttClient, timeoutMs: number): Promise<void> {\n if (client.connected) {\n return Promise.resolve();\n }\n\n if (this.pendingReconnectWait) {\n return this.pendingReconnectWait;\n }\n\n this.pendingReconnectWait = new Promise<void>((resolve) => {\n if (client.connected) return resolve();\n\n const onConnect = () => {\n cleanup();\n resolve();\n };\n const onClose = () => {\n // stay waiting; close is expected during reconnect attempts\n };\n const cleanup = () => {\n client.off(\"connect\", onConnect);\n client.off(\"close\", onClose);\n };\n\n client.on(\"connect\", onConnect);\n client.on(\"close\", onClose);\n\n setTimeout(() => {\n cleanup();\n resolve();\n }, timeoutMs).unref?.();\n }).finally(() => {\n this.pendingReconnectWait = null;\n });\n\n return this.pendingReconnectWait;\n }\n\n private async emitTransformationStatistics(): Promise<void> {\n if (this.statusTopic !== \"\") {\n try {\n this.event.emit(\"mqttProxyStatus\", {\n event: \"published-message-count\",\n value: this.publishedMessageCount,\n uom: \"\",\n statusTopic: this.statusTopic + \"published-message-count\",\n });\n this.event.emit(\"mqttProxyStatus\", {\n event: \"published-message-bytes\",\n value: Math.round(this.publishedMessageBytes / 1024),\n uom: DataSizeMeasurements.KiloByte,\n statusTopic: this.statusTopic + \"published-message-bytes\",\n });\n this.event.emit(\"mqttProxyStatus\", {\n event: \"subscribed-message-count\",\n value: this.subscribedMessageCount,\n uom: \"\",\n statusTopic: this.statusTopic + \"subscribed-message-count\",\n });\n this.event.emit(\"mqttProxyStatus\", {\n event: \"subscribed-message-bytes\",\n value: Math.round(this.subscribedMessageBytes / 1024),\n uom: DataSizeMeasurements.KiloByte,\n statusTopic: this.statusTopic + \"subscribed-message-bytes\",\n });\n this.publishedMessageCount = 0;\n this.publishedMessageBytes = 0;\n this.subscribedMessageCount = 0;\n this.subscribedMessageBytes = 0;\n } catch (error: any) {\n this.publishedMessageCount = 0;\n this.publishedMessageBytes = 0;\n this.subscribedMessageCount = 0;\n this.subscribedMessageBytes = 0;\n logger.error(`${this.instanceName} - Error emitting transformation statistics: ${error.message}`);\n }\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"mqtt-proxy.js","sourceRoot":"","sources":["../../src/uns-mqtt/mqtt-proxy.ts"],"names":[],"mappings":"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","sourcesContent":["import mqtt, { IClientOptions, MqttClient } from \"mqtt\";\nimport logger from \"../logger.js\";\nimport { UnsEvents } from \"../uns/uns-interfaces.js\";\nimport { UnsEventEmitter } from \"../uns/uns-event-emitter.js\";\nimport { IMqttParameters } from \"./mqtt-interfaces.js\";\nimport { MqttWorker } from \"./mqtt-worker.js\";\nimport { DataSizeMeasurements, PhysicalMeasurements } from \"../uns/uns-measurements.js\";\n\nexport type MqttStopOptions = {\n silent?: boolean;\n reason?: \"retry\" | \"shutdown\";\n};\n\ntype MqttErrorInfo = {\n code: string | number;\n message: string;\n};\n\nexport default class MqttProxy {\n public event: UnsEventEmitter<UnsEvents> = new UnsEventEmitter<UnsEvents>();\n public statusTopic: string;\n public instanceName: string;\n private mqttHost: string;\n private mqttSubToTopics: string | string[];\n private mqttSSL: boolean;\n private mqttClient: MqttClient;\n private startDate: Date;\n private mqttParameters: IMqttParameters;\n private statusUpdateInterval: ReturnType<typeof setInterval>;\n private transformationStatsInterval: NodeJS.Timeout | null = null;\n private publishedMessageCount = 0;\n private publishedMessageBytes = 0;\n private subscribedMessageCount = 0;\n private subscribedMessageBytes = 0;\n private mqttWorker: MqttWorker;\n public isConnected = false;\n private rejectUnauthorized: boolean;\n private pendingReconnectWait: Promise<void> | null = null;\n private hasEstablishedConnection = false;\n\n constructor(mqttHost: string, instanceName: string, mqttParameters: IMqttParameters, mqttWorker?: MqttWorker) {\n this.mqttSSL = mqttParameters?.mqttSSL ?? false;\n this.rejectUnauthorized = mqttParameters.rejectUnauthorized ?? false;\n this.mqttSubToTopics = mqttParameters?.mqttSubToTopics ?? [];\n this.mqttHost = mqttHost;\n this.startDate = new Date();\n this.instanceName = instanceName ?? \"process\";\n this.statusTopic = `${mqttParameters?.statusTopic}`;\n this.mqttParameters = mqttParameters ?? {};\n this.mqttWorker = mqttWorker;\n }\n\n private resolveProtocol(): IMqttParameters[\"protocol\"] {\n return this.mqttParameters.protocol ?? (this.mqttSSL ? \"mqtts\" : \"mqtt\");\n }\n\n private resolveDefaultPort(protocol: IMqttParameters[\"protocol\"]): number {\n switch (protocol) {\n case \"mqtts\":\n case \"ssl\":\n return 8883;\n case \"wss\":\n return 443;\n case \"ws\":\n return 80;\n case \"tcp\":\n case \"mqtt\":\n default:\n return 1883;\n }\n }\n\n private buildServers(defaultProtocol: IMqttParameters[\"protocol\"]): IClientOptions[\"servers\"] | undefined {\n const servers: IClientOptions[\"servers\"] = [];\n const { port } = this.mqttParameters;\n const protocol = this.mqttParameters.protocol ?? defaultProtocol;\n\n if (Array.isArray(this.mqttParameters.servers) && this.mqttParameters.servers.length > 0) {\n for (const server of this.mqttParameters.servers) {\n if (!server?.host) continue;\n const resolvedProtocol = server.protocol ?? protocol;\n const resolvedPort =\n typeof server.port === \"number\"\n ? server.port\n : typeof port === \"number\"\n ? port\n : this.resolveDefaultPort(resolvedProtocol);\n const entry: { host: string; port: number; protocol?: IMqttParameters[\"protocol\"] } = {\n host: server.host,\n port: resolvedPort,\n };\n if (resolvedProtocol) {\n entry.protocol = resolvedProtocol;\n }\n servers.push(entry);\n }\n } else if (Array.isArray(this.mqttParameters.hosts) && this.mqttParameters.hosts.length > 0) {\n for (const host of this.mqttParameters.hosts) {\n if (!host) continue;\n const resolvedPort = typeof port === \"number\" ? port : this.resolveDefaultPort(protocol);\n const entry: { host: string; port: number; protocol?: IMqttParameters[\"protocol\"] } = {\n host,\n port: resolvedPort,\n };\n if (protocol) {\n entry.protocol = protocol;\n }\n servers.push(entry);\n }\n }\n\n return servers.length > 0 ? servers : undefined;\n }\n\n public async start(): Promise<void> {\n logger.debug(`${this.instanceName} - Connecting to MQTT broker...`);\n\n return new Promise<void>((resolve, reject) => {\n try {\n const username = this.mqttParameters.username;\n const password = this.mqttParameters.password;\n const clientId = this.mqttParameters.clientId ?? this.instanceName;\n const protocol = this.resolveProtocol();\n\n const options: IClientOptions = {\n username,\n password,\n protocolVersion: 5,\n rejectUnauthorized: this.rejectUnauthorized,\n keepalive: this.mqttParameters.keepalive,\n clean: this.mqttParameters.clean ?? true,\n connectTimeout: this.mqttParameters.connectTimeout,\n reconnectPeriod: this.mqttParameters.reconnectPeriod,\n reconnectOnConnackError: this.mqttParameters.reconnectOnConnackError,\n resubscribe: this.mqttParameters.resubscribe,\n queueQoSZero: this.mqttParameters.queueQoSZero,\n properties: this.mqttParameters.properties,\n ca: this.mqttParameters.ca,\n cert: this.mqttParameters.cert,\n key: this.mqttParameters.key,\n servername: this.mqttParameters.servername,\n \n will: {\n topic: `${this.statusTopic}alive`,\n payload: Buffer.from(\"\"),\n qos: 0,\n retain: true,\n properties: { messageExpiryInterval: 3600 },\n },\n clientId,\n };\n\n const servers = this.buildServers(protocol);\n if (servers) {\n options.servers = servers;\n options.protocol = protocol;\n this.mqttClient = mqtt.connect(options);\n } else {\n options.host = this.mqttHost;\n options.port = this.mqttParameters.port;\n options.protocol = protocol;\n this.mqttClient = mqtt.connect(options);\n }\n\n const onConnect = () => {\n try {\n this.mqttClient.stream.setMaxListeners(0);\n this.hasEstablishedConnection = true;\n logger.info(`${this.instanceName} - Connected to MQTT broker at ${this.mqttHost}`);\n\n if (this.mqttSubToTopics && this.mqttSubToTopics.length > 0) {\n logger.debug(`${this.instanceName} - Subscribed to ${this.mqttSubToTopics.length} topics.`);\n this.mqttClient.subscribe(this.mqttSubToTopics, { qos: 0 });\n }\n\n if (this.statusTopic) {\n this.statusUpdateInterval = setInterval(() => this.emitStatusUpdates(), 10000);\n }\n\n this.transformationStatsInterval = setInterval(() => {\n this.emitTransformationStatistics();\n }, 60000);\n\n this.mqttClient.off(\"connect\", onConnect);\n this.isConnected = true;\n resolve();\n } catch (error) {\n logger.error(`${this.instanceName} - Error in MQTT connect handler: ${formatMqttError(error).message}`);\n this.isConnected = false;\n reject(error);\n }\n };\n\n this.mqttClient.on(\"connect\", onConnect);\n\n this.mqttClient.on(\"message\", (topic: string, message: Buffer, packet: mqtt.IPublishPacket) => {\n try {\n logger.debug(`${this.instanceName} - Message received on topic ${topic}`);\n this.event.emit(\"input\", {\n message: message.toString(),\n topic: topic,\n packet: packet,\n });\n this.updateSubscribeTransformationStats(message.length);\n } catch (error) {\n logger.error(`${this.instanceName} - Error in MQTT message handler: ${error.message}`);\n }\n });\n\n this.mqttClient.on(\"error\", (error) => {\n const errorInfo = formatMqttError(error);\n logger.error(`${this.instanceName} - MQTT client error: ${errorInfo.message}`);\n this.isConnected = false;\n this.event.emit(\"error\", {\n code: typeof errorInfo.code === \"number\" ? errorInfo.code : 0,\n message: errorInfo.message,\n });\n reject(error);\n });\n\n this.mqttClient.on(\"reconnect\", () => {\n logger.debug(`${this.instanceName} - Attempting to reconnect to MQTT broker...`);\n });\n\n this.mqttClient.on(\"close\", () => {\n logger.debug(`${this.instanceName} - MQTT connection closed.`);\n this.isConnected = false;\n });\n\n this.mqttClient.on(\"offline\", () => {\n logger.debug(`${this.instanceName} - MQTT client is offline.`);\n this.isConnected = false;\n });\n\n this.mqttClient.on(\"end\", () => {\n logger.debug(`${this.instanceName} - MQTT client connection ended.`);\n this.isConnected = false;\n });\n\n this.mqttClient.on(\"disconnect\", (packet) => {\n logger.debug(`${this.instanceName} - MQTT client disconnected. Reason: ${packet?.reasonCode}`);\n this.isConnected = false;\n });\n } catch (error) {\n logger.error(`${this.instanceName} - Error starting MQTT proxy: ${formatMqttError(error).message}`);\n this.isConnected = false;\n reject(error);\n }\n });\n }\n\n public async publish(topic: string, message: string | Buffer, options?: mqtt.IClientPublishOptions): Promise<void> {\n this.updatePublishTransformationStats(JSON.stringify(message).length);\n const client = this.mqttClient;\n if (!client) {\n logger.warn(`${this.instanceName} - MQTT client missing; dropping publish to ${topic}`);\n return;\n }\n\n if (!client.connected) {\n // Wait briefly for reconnection before giving up.\n await this.waitForReconnect(client, 5000);\n }\n\n if (!client.connected) {\n logger.warn(`${this.instanceName} - MQTT client still disconnected; dropping publish to ${topic}`);\n return;\n }\n\n return new Promise((resolve, reject) => {\n client.publish(topic, message, options || {}, (err) => {\n if (err) {\n logger.error(`${this.instanceName} - Error publishing to topic ${topic}: ${err.message}`);\n return reject(err);\n }\n logger.debug(`${this.instanceName} - Published message to topic ${topic}`);\n resolve();\n });\n });\n }\n\n public async subscribeAsync(topic: string | string[], options?: mqtt.IClientSubscribeOptions): Promise<mqtt.ISubscriptionGrant[]> {\n return this.mqttClient.subscribeAsync(topic, options);\n }\n\n public async unsubscribeAsync(topic: string | string[]): Promise<mqtt.Packet | undefined> {\n const topics = Array.isArray(topic) ? topic.filter((t) => typeof t === \"string\" && t.length > 0) : [topic].filter((t): t is string => typeof t === \"string\" && t.length > 0);\n if (topics.length === 0) {\n logger.warn(`${this.instanceName} - unsubscribeAsync called with empty topic list; skipping.`);\n return Promise.resolve(undefined);\n }\n return this.mqttClient.unsubscribeAsync(topics);\n }\n\n public stop(options: MqttStopOptions = {}) {\n const silent = options.silent === true || options.reason === \"retry\";\n const shouldLogDisconnect = !silent && this.hasEstablishedConnection;\n\n if (shouldLogDisconnect) {\n logger.debug(`${this.instanceName} - Disconnecting from MQTT broker...`);\n }\n\n try {\n if (this.statusUpdateInterval) {\n clearInterval(this.statusUpdateInterval);\n this.statusUpdateInterval = null;\n }\n if (this.transformationStatsInterval) {\n clearInterval(this.transformationStatsInterval);\n this.transformationStatsInterval = null;\n }\n if (this.mqttClient) {\n this.mqttClient.end(false, () => {\n this.isConnected = false;\n this.pendingReconnectWait = null;\n if (shouldLogDisconnect) {\n logger.debug(`${this.instanceName} - Disconnected from MQTT broker.`);\n }\n });\n } else {\n this.isConnected = false;\n this.pendingReconnectWait = null;\n }\n } catch (error) {\n if (!silent) {\n logger.error(`${this.instanceName} - Error during stop: ${formatMqttError(error).message}`);\n }\n this.isConnected = false;\n this.pendingReconnectWait = null;\n }\n }\n\n private emitStatusUpdates() {\n try {\n const uptime = Math.round((new Date().getTime() - this.startDate.getTime()) / 60000);\n this.event.emit(\"mqttProxyStatus\", { event: \"uptime\", value: uptime, uom: PhysicalMeasurements.Minute, statusTopic: this.statusTopic + \"uptime\" });\n this.event.emit(\"mqttProxyStatus\", { event: \"alive\", value: 1, uom: DataSizeMeasurements.Bit, statusTopic: this.statusTopic + \"alive\" });\n\n if (this.mqttWorker !== undefined) {\n const tpValue = this.mqttWorker.getPublisherState() ? 1 : 0;\n this.event.emit(\"mqttProxyStatus\", { event: \"t-publisher-active\", value: tpValue, uom: DataSizeMeasurements.Bit, statusTopic: this.statusTopic + \"t-publisher-active\" });\n const tsValue = this.mqttWorker.getSubscriberState() ? 1 : 0;\n this.event.emit(\"mqttProxyStatus\", { event: \"t-subscriber-active\", value: tsValue, uom: DataSizeMeasurements.Bit, statusTopic: this.statusTopic + \"t-subscriber-active\" });\n }\n } catch (error) {\n logger.error(`${this.instanceName} - Error publishing MQTT status: ${error.message}`);\n }\n }\n\n private updatePublishTransformationStats(messageSizeOut: number): void {\n this.publishedMessageCount += 1;\n this.publishedMessageBytes += messageSizeOut;\n }\n\n private updateSubscribeTransformationStats(messageSizeIn: number): void {\n this.subscribedMessageCount += 1;\n this.subscribedMessageBytes += messageSizeIn;\n }\n\n private waitForReconnect(client: mqtt.MqttClient, timeoutMs: number): Promise<void> {\n if (client.connected) {\n return Promise.resolve();\n }\n\n if (this.pendingReconnectWait) {\n return this.pendingReconnectWait;\n }\n\n this.pendingReconnectWait = new Promise<void>((resolve) => {\n if (client.connected) return resolve();\n\n const onConnect = () => {\n cleanup();\n resolve();\n };\n const onClose = () => {\n // stay waiting; close is expected during reconnect attempts\n };\n const cleanup = () => {\n client.off(\"connect\", onConnect);\n client.off(\"close\", onClose);\n };\n\n client.on(\"connect\", onConnect);\n client.on(\"close\", onClose);\n\n setTimeout(() => {\n cleanup();\n resolve();\n }, timeoutMs).unref?.();\n }).finally(() => {\n this.pendingReconnectWait = null;\n });\n\n return this.pendingReconnectWait;\n }\n\n private async emitTransformationStatistics(): Promise<void> {\n if (this.statusTopic !== \"\") {\n try {\n this.event.emit(\"mqttProxyStatus\", {\n event: \"published-message-count\",\n value: this.publishedMessageCount,\n uom: \"\",\n statusTopic: this.statusTopic + \"published-message-count\",\n });\n this.event.emit(\"mqttProxyStatus\", {\n event: \"published-message-bytes\",\n value: Math.round(this.publishedMessageBytes / 1024),\n uom: DataSizeMeasurements.KiloByte,\n statusTopic: this.statusTopic + \"published-message-bytes\",\n });\n this.event.emit(\"mqttProxyStatus\", {\n event: \"subscribed-message-count\",\n value: this.subscribedMessageCount,\n uom: \"\",\n statusTopic: this.statusTopic + \"subscribed-message-count\",\n });\n this.event.emit(\"mqttProxyStatus\", {\n event: \"subscribed-message-bytes\",\n value: Math.round(this.subscribedMessageBytes / 1024),\n uom: DataSizeMeasurements.KiloByte,\n statusTopic: this.statusTopic + \"subscribed-message-bytes\",\n });\n this.publishedMessageCount = 0;\n this.publishedMessageBytes = 0;\n this.subscribedMessageCount = 0;\n this.subscribedMessageBytes = 0;\n } catch (error: any) {\n this.publishedMessageCount = 0;\n this.publishedMessageBytes = 0;\n this.subscribedMessageCount = 0;\n this.subscribedMessageBytes = 0;\n logger.error(`${this.instanceName} - Error emitting transformation statistics: ${error.message}`);\n }\n }\n }\n}\n\nexport function formatMqttError(error: unknown): MqttErrorInfo {\n const parts: string[] = [];\n const codes: Array<string | number> = [];\n collectMqttErrorParts(error, parts, codes);\n\n const uniqueParts = Array.from(new Set(parts.map((part) => part.trim()).filter(Boolean)));\n const message = uniqueParts.join(\"; \") || \"Unknown MQTT error\";\n\n return {\n code: codes[0] ?? 0,\n message,\n };\n}\n\nfunction collectMqttErrorParts(\n error: unknown,\n parts: string[],\n codes: Array<string | number>,\n): void {\n if (error instanceof AggregateError) {\n if (typeof error.message === \"string\" && error.message.trim()) {\n parts.push(error.message.trim());\n }\n for (const nested of error.errors) {\n collectMqttErrorParts(nested, parts, codes);\n }\n return;\n }\n\n if (typeof error === \"string\") {\n if (error.trim()) {\n parts.push(error.trim());\n }\n return;\n }\n\n if (!error || typeof error !== \"object\") {\n return;\n }\n\n const record = error as {\n message?: unknown;\n name?: unknown;\n code?: unknown;\n address?: unknown;\n port?: unknown;\n cause?: unknown;\n };\n\n const code =\n typeof record.code === \"string\" || typeof record.code === \"number\"\n ? record.code\n : undefined;\n if (code !== undefined) {\n codes.push(code);\n }\n\n const message =\n typeof record.message === \"string\" && record.message.trim()\n ? record.message.trim()\n : undefined;\n const address =\n typeof record.address === \"string\" && record.address.trim()\n ? record.address.trim()\n : undefined;\n const port = typeof record.port === \"number\" ? record.port : undefined;\n const endpoint =\n address || port !== undefined\n ? `${address ?? \"\"}${address && port !== undefined ? \":\" : \"\"}${port ?? \"\"}`.trim()\n : undefined;\n\n const detailParts = [\n code !== undefined && !message?.includes(String(code)) ? String(code) : undefined,\n message,\n endpoint && !message?.includes(endpoint) ? endpoint : undefined,\n ].filter((part): part is string => typeof part === \"string\" && part.length > 0);\n\n if (detailParts.length > 0) {\n parts.push(detailParts.join(\" \"));\n } else if (typeof record.name === \"string\" && record.name.trim()) {\n parts.push(record.name.trim());\n }\n\n if (record.cause !== undefined) {\n collectMqttErrorParts(record.cause, parts, codes);\n }\n}\n"]}
|