@uns-kit/core 2.0.69 → 2.0.70
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/README.md +44 -24
- package/dist/uns/handover-manager.d.ts.map +1 -1
- package/dist/uns/handover-manager.js +1 -3
- package/dist/uns/handover-manager.js.map +1 -1
- package/dist/uns/uns-interfaces.d.ts +2 -0
- package/dist/uns/uns-interfaces.d.ts.map +1 -1
- package/dist/uns/uns-interfaces.js.map +1 -1
- package/dist/uns/uns-proxy-process.d.ts +2 -1
- package/dist/uns/uns-proxy-process.d.ts.map +1 -1
- package/dist/uns/uns-proxy-process.js +8 -2
- package/dist/uns/uns-proxy-process.js.map +1 -1
- package/dist/uns-grpc/uns-gateway-server.js +2 -2
- package/dist/uns-grpc/uns-gateway-server.js.map +1 -1
- package/dist/uns-mqtt/mqtt-interfaces.d.ts +2 -0
- package/dist/uns-mqtt/mqtt-interfaces.d.ts.map +1 -1
- package/dist/uns-mqtt/mqtt-interfaces.js.map +1 -1
- package/dist/uns-mqtt/mqtt-proxy.d.ts.map +1 -1
- package/dist/uns-mqtt/mqtt-proxy.js +2 -4
- package/dist/uns-mqtt/mqtt-proxy.js.map +1 -1
- package/dist/uns-mqtt/mqtt-worker.d.ts.map +1 -1
- package/dist/uns-mqtt/mqtt-worker.js +33 -17
- package/dist/uns-mqtt/mqtt-worker.js.map +1 -1
- package/dist/uns-mqtt/throttled-queue.d.ts +13 -2
- package/dist/uns-mqtt/throttled-queue.d.ts.map +1 -1
- package/dist/uns-mqtt/throttled-queue.js +80 -33
- package/dist/uns-mqtt/throttled-queue.js.map +1 -1
- package/dist/uns-mqtt/uns-mqtt-proxy.d.ts +16 -3
- package/dist/uns-mqtt/uns-mqtt-proxy.d.ts.map +1 -1
- package/dist/uns-mqtt/uns-mqtt-proxy.js +104 -23
- package/dist/uns-mqtt/uns-mqtt-proxy.js.map +1 -1
- package/package.json +1 -1
|
@@ -30,15 +30,19 @@ export var MessageMode;
|
|
|
30
30
|
MessageMode["Both"] = "both"; // Send both the original and delta messages
|
|
31
31
|
})(MessageMode || (MessageMode = {}));
|
|
32
32
|
export default class UnsMqttProxy extends UnsProxy {
|
|
33
|
+
static DEFAULT_DRAIN_TIMEOUT_MS = 30_000;
|
|
33
34
|
lastValues = new Map();
|
|
34
35
|
worker;
|
|
35
36
|
pendingEnqueues = new Map();
|
|
37
|
+
pendingPublishCompletions = 0;
|
|
36
38
|
unsParameters;
|
|
37
39
|
processStatusTopic;
|
|
38
40
|
instanceName;
|
|
39
41
|
currentSequenceId = new Map();
|
|
40
42
|
topicBuilder;
|
|
41
43
|
deltaModeDeprecationWarned = false;
|
|
44
|
+
drainWaiters = [];
|
|
45
|
+
workerFailure = null;
|
|
42
46
|
constructor(mqttHost, processName, instanceName, unsParameters, publisherActive = false, subscriberActive = false) {
|
|
43
47
|
super();
|
|
44
48
|
this.instanceName = instanceName;
|
|
@@ -123,6 +127,8 @@ export default class UnsMqttProxy extends UnsProxy {
|
|
|
123
127
|
startQueueWorker(mqttHost, instanceNameWithSuffix, mqttParameters, publisherActive, subscriberActive) {
|
|
124
128
|
const workerData = {
|
|
125
129
|
publishThrottlingDelay: this.unsParameters.publishThrottlingDelay ?? 1,
|
|
130
|
+
publishConcurrency: this.unsParameters.publishConcurrency ?? 1,
|
|
131
|
+
maxPendingPublishes: this.unsParameters.maxPendingPublishes,
|
|
126
132
|
subscribeThrottlingDelay: this.unsParameters.subscribeThrottlingDelay ?? 1,
|
|
127
133
|
persistToDisk: false,
|
|
128
134
|
mqttHost: mqttHost,
|
|
@@ -134,18 +140,30 @@ export default class UnsMqttProxy extends UnsProxy {
|
|
|
134
140
|
};
|
|
135
141
|
this.worker = new Worker(workerScriptPath, { workerData });
|
|
136
142
|
this.worker.on("message", (msg) => {
|
|
137
|
-
if (msg && msg.command === "
|
|
143
|
+
if (msg && msg.command === "enqueueAccepted" && msg.id) {
|
|
138
144
|
const pending = this.pendingEnqueues.get(msg.id);
|
|
139
145
|
if (pending) {
|
|
140
|
-
if (msg.status === "
|
|
146
|
+
if (msg.status === "accepted") {
|
|
147
|
+
this.pendingPublishCompletions += 1;
|
|
141
148
|
pending.resolve();
|
|
142
149
|
}
|
|
143
150
|
else {
|
|
144
151
|
pending.reject(new Error(msg.error));
|
|
145
152
|
}
|
|
146
153
|
this.pendingEnqueues.delete(msg.id);
|
|
154
|
+
this.notifyDrainWaiters();
|
|
147
155
|
}
|
|
148
156
|
}
|
|
157
|
+
else if (msg && msg.command === "publishResult" && msg.id) {
|
|
158
|
+
if (this.pendingPublishCompletions > 0) {
|
|
159
|
+
this.pendingPublishCompletions -= 1;
|
|
160
|
+
}
|
|
161
|
+
if (msg.status === "error") {
|
|
162
|
+
const errorMessage = msg.error ?? `Error publishing to topic ${msg.topic ?? "unknown"}`;
|
|
163
|
+
this.event.emit("error", { code: 0, message: errorMessage });
|
|
164
|
+
}
|
|
165
|
+
this.notifyDrainWaiters();
|
|
166
|
+
}
|
|
149
167
|
else if (msg && msg.command === "input") {
|
|
150
168
|
this.event.emit("input", { topic: msg.topic, message: msg.message.toString(), packet: msg.packet });
|
|
151
169
|
}
|
|
@@ -159,19 +177,13 @@ export default class UnsMqttProxy extends UnsProxy {
|
|
|
159
177
|
this.worker.on("error", (err) => {
|
|
160
178
|
logger.error("Error in worker:", err);
|
|
161
179
|
const reason = err instanceof Error ? err : new Error(String(err));
|
|
162
|
-
|
|
163
|
-
pending.reject(reason);
|
|
164
|
-
}
|
|
165
|
-
this.pendingEnqueues.clear();
|
|
180
|
+
this.failPendingPublishes(reason);
|
|
166
181
|
});
|
|
167
182
|
this.worker.on("exit", (code) => {
|
|
168
183
|
if (code !== 0) {
|
|
169
184
|
logger.error(`Worker exited with code ${code}`);
|
|
170
185
|
const reason = new Error(`MQTT worker exited with code ${code}`);
|
|
171
|
-
|
|
172
|
-
pending.reject(reason);
|
|
173
|
-
}
|
|
174
|
-
this.pendingEnqueues.clear();
|
|
186
|
+
this.failPendingPublishes(reason);
|
|
175
187
|
}
|
|
176
188
|
});
|
|
177
189
|
}
|
|
@@ -181,14 +193,18 @@ export default class UnsMqttProxy extends UnsProxy {
|
|
|
181
193
|
* @param topic - The topic to which the message belongs.
|
|
182
194
|
* @param message - The message to be enqueued.
|
|
183
195
|
* @param options - Optional publish options.
|
|
184
|
-
* @returns A promise that resolves when the message is
|
|
196
|
+
* @returns A promise that resolves when the message is accepted into the worker queue.
|
|
185
197
|
*/
|
|
186
198
|
async enqueueMessageToWorkerQueue(topic, message, options) {
|
|
187
199
|
return new Promise((resolve, reject) => {
|
|
188
|
-
|
|
200
|
+
if (this.workerFailure) {
|
|
201
|
+
reject(this.workerFailure);
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
189
204
|
const id = `${Date.now()}-${Math.random()}`;
|
|
190
205
|
this.pendingEnqueues.set(id, { resolve, reject });
|
|
191
206
|
this.worker.postMessage({ command: "enqueue", id, topic, message, options });
|
|
207
|
+
this.notifyDrainWaiters();
|
|
192
208
|
});
|
|
193
209
|
}
|
|
194
210
|
/**
|
|
@@ -246,13 +262,33 @@ export default class UnsMqttProxy extends UnsProxy {
|
|
|
246
262
|
async setSubscriberPassiveAndDrainQueue() {
|
|
247
263
|
return new Promise(async (resolve) => {
|
|
248
264
|
const mqttWorkerData = await this.setSubscriberPassive();
|
|
249
|
-
|
|
250
|
-
await new Promise((resolve) => setTimeout(resolve, 100)); // Poll every 100ms
|
|
251
|
-
}
|
|
265
|
+
await this.flush();
|
|
252
266
|
logger.info(`${this.instanceNameWithSuffix} - Subscriber set to passive and queue drained.`);
|
|
253
267
|
resolve(mqttWorkerData);
|
|
254
268
|
});
|
|
255
269
|
}
|
|
270
|
+
async drainPublishes(timeoutMs = UnsMqttProxy.DEFAULT_DRAIN_TIMEOUT_MS) {
|
|
271
|
+
if (this.workerFailure) {
|
|
272
|
+
throw this.workerFailure;
|
|
273
|
+
}
|
|
274
|
+
if (this.pendingEnqueues.size === 0 && this.pendingPublishCompletions === 0) {
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
await new Promise((resolve, reject) => {
|
|
278
|
+
const waiter = { resolve, reject, timer: undefined };
|
|
279
|
+
if (Number.isFinite(timeoutMs) && timeoutMs > 0) {
|
|
280
|
+
waiter.timer = setTimeout(() => {
|
|
281
|
+
this.removeDrainWaiter(waiter);
|
|
282
|
+
reject(new Error(`Timed out waiting for MQTT publishes to drain after ${timeoutMs}ms.`));
|
|
283
|
+
}, timeoutMs);
|
|
284
|
+
}
|
|
285
|
+
this.drainWaiters.push(waiter);
|
|
286
|
+
this.notifyDrainWaiters();
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
async flush(timeoutMs = UnsMqttProxy.DEFAULT_DRAIN_TIMEOUT_MS) {
|
|
290
|
+
await this.drainPublishes(timeoutMs);
|
|
291
|
+
}
|
|
256
292
|
/**
|
|
257
293
|
* Processes and publishes MQTT messages based on the selected message mode.
|
|
258
294
|
*
|
|
@@ -348,7 +384,7 @@ export default class UnsMqttProxy extends UnsProxy {
|
|
|
348
384
|
*
|
|
349
385
|
* @param topic - The MQTT topic.
|
|
350
386
|
* @param message - The message to publish.
|
|
351
|
-
* @returns A promise that resolves when
|
|
387
|
+
* @returns A promise that resolves when the message is accepted into the worker queue.
|
|
352
388
|
*/
|
|
353
389
|
publishMessage(topic, message, options) {
|
|
354
390
|
return this.enqueueMessageToWorkerQueue(topic, message, options);
|
|
@@ -488,14 +524,26 @@ export default class UnsMqttProxy extends UnsProxy {
|
|
|
488
524
|
}
|
|
489
525
|
catch (error) {
|
|
490
526
|
logger.error(`${this.instanceNameWithSuffix} - Error publishing message to topic ${msg.topic}${msg.attribute}: ${error.message}`);
|
|
527
|
+
throw error;
|
|
491
528
|
}
|
|
492
529
|
}
|
|
493
530
|
/**
|
|
494
531
|
* Stops the UnsProxy instance and cleans up resources.
|
|
495
532
|
*/
|
|
496
|
-
async stop() {
|
|
497
|
-
super.stop();
|
|
498
|
-
|
|
533
|
+
async stop(options = {}) {
|
|
534
|
+
await super.stop();
|
|
535
|
+
const drain = options.drain ?? true;
|
|
536
|
+
const timeoutMs = options.timeoutMs ?? UnsMqttProxy.DEFAULT_DRAIN_TIMEOUT_MS;
|
|
537
|
+
let drainError = null;
|
|
538
|
+
if (drain) {
|
|
539
|
+
try {
|
|
540
|
+
await this.flush(timeoutMs);
|
|
541
|
+
}
|
|
542
|
+
catch (error) {
|
|
543
|
+
drainError = error instanceof Error ? error : new Error(String(error));
|
|
544
|
+
logger.error(`${this.instanceNameWithSuffix} - Error draining publishes before stop: ${drainError.message}`);
|
|
545
|
+
}
|
|
546
|
+
}
|
|
499
547
|
if (this.worker) {
|
|
500
548
|
try {
|
|
501
549
|
const exitCode = await this.worker.terminate();
|
|
@@ -505,11 +553,44 @@ export default class UnsMqttProxy extends UnsProxy {
|
|
|
505
553
|
logger.error(`${this.instanceNameWithSuffix} - Error terminating worker: ${error.message}`);
|
|
506
554
|
}
|
|
507
555
|
}
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
556
|
+
this.failPendingPublishes(drainError ?? new Error("UnsProxy has been stopped"));
|
|
557
|
+
if (drainError) {
|
|
558
|
+
throw drainError;
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
failPendingPublishes(reason) {
|
|
562
|
+
this.workerFailure = reason;
|
|
563
|
+
for (const pending of this.pendingEnqueues.values()) {
|
|
564
|
+
pending.reject(reason);
|
|
512
565
|
}
|
|
566
|
+
this.pendingEnqueues.clear();
|
|
567
|
+
this.pendingPublishCompletions = 0;
|
|
568
|
+
this.notifyDrainWaiters();
|
|
569
|
+
}
|
|
570
|
+
notifyDrainWaiters() {
|
|
571
|
+
if (this.workerFailure) {
|
|
572
|
+
const waiters = this.drainWaiters.splice(0);
|
|
573
|
+
for (const waiter of waiters) {
|
|
574
|
+
if (waiter.timer) {
|
|
575
|
+
clearTimeout(waiter.timer);
|
|
576
|
+
}
|
|
577
|
+
waiter.reject(this.workerFailure);
|
|
578
|
+
}
|
|
579
|
+
return;
|
|
580
|
+
}
|
|
581
|
+
if (this.pendingEnqueues.size !== 0 || this.pendingPublishCompletions !== 0) {
|
|
582
|
+
return;
|
|
583
|
+
}
|
|
584
|
+
const waiters = this.drainWaiters.splice(0);
|
|
585
|
+
for (const waiter of waiters) {
|
|
586
|
+
if (waiter.timer) {
|
|
587
|
+
clearTimeout(waiter.timer);
|
|
588
|
+
}
|
|
589
|
+
waiter.resolve();
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
removeDrainWaiter(waiterToRemove) {
|
|
593
|
+
this.drainWaiters = this.drainWaiters.filter((waiter) => waiter !== waiterToRemove);
|
|
513
594
|
}
|
|
514
595
|
}
|
|
515
596
|
//# sourceMappingURL=uns-mqtt-proxy.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"uns-mqtt-proxy.js","sourceRoot":"","sources":["../../src/uns-mqtt/uns-mqtt-proxy.ts"],"names":[],"mappings":"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","sourcesContent":["import { readFileSync } from \"fs\";\r\nimport { IClientPublishOptions } from \"mqtt\";\r\nimport * as path from \"path\";\r\nimport { Worker } from \"worker_threads\";\r\nimport { fileURLToPath } from \"url\";\r\nimport { basePath } from \"../base-path.js\";\r\nimport logger from \"../logger.js\";\r\nimport { IMqttPublishRequest, IUnsLifecycleMetadata, IUnsMessage, IUnsPacket, IUnsParameters, IUnsRelationshipEvidenceMetadata, IUnsTableColumnMetadata, UnsAttribute, UnsAttributeSystemRole, UnsEvents, ValueType } from \"../uns/uns-interfaces.js\";\r\nimport { getObjectTypeDescription, type UnsObjectId, type UnsObjectType } from \"../uns/uns-object.js\";\r\nimport type { UnsAsset } from \"../uns/uns-asset.js\";\r\nimport { MeasurementUnit } from \"../uns/uns-measurements.js\";\r\nimport { UnsPacket } from \"../uns/uns-packet.js\";\r\nimport { IMqttParameters, IMqttWorkerData } from \"./mqtt-interfaces.js\";\r\nimport { MqttTopicBuilder } from \"./mqtt-topic-builder.js\";\r\nimport UnsProxy from \"../uns/uns-proxy.js\";\r\nimport { UnsAttributeType } from \"../graphql/schema.js\";\r\nimport { getAttributeDescription } from \"../uns/uns-attributes.js\";\r\nimport { UnsTags } from \"../uns/uns-tags.js\";\r\nimport { UnsTopics } from \"../uns/uns-topics.js\";\r\n\r\nconst packageJsonPath = path.join(basePath, \"package.json\");\r\nconst packageJson = JSON.parse(readFileSync(packageJsonPath, \"utf8\"));\r\n\r\nconst moduleDirectory = path.dirname(fileURLToPath(import.meta.url));\r\nconst packageRoot = path.resolve(moduleDirectory, \"..\", \"..\");\r\nconst workerScriptPath = path.join(packageRoot, \"dist/uns-mqtt/mqtt-worker-init.js\");\r\n\r\nexport enum MessageMode {\r\n Raw = 'raw', // Send only the original message\r\n /**\r\n * @deprecated Producer-side delta calculation loses state across restarts.\r\n * Publish raw cumulative counter values and request delta/rate from Datahub history APIs.\r\n */\r\n Delta = 'delta', // Send only the delta message\r\n /**\r\n * @deprecated Producer-side delta calculation loses state across restarts.\r\n * Publish raw cumulative counter values and request delta/rate from Datahub history APIs.\r\n */\r\n Both = 'both' // Send both the original and delta messages\r\n}\r\n\r\ntype InternalMqttMessage = {\r\n topic: UnsTopics;\r\n attribute: UnsAttribute;\r\n asset: UnsAsset;\r\n assetDescription?: string;\r\n objectType: UnsObjectType;\r\n objectTypeDescription?: string;\r\n objectId: UnsObjectId;\r\n virtualGroup?: string;\r\n description?: string;\r\n tags?: UnsTags[];\r\n attributeNeedsPersistence?: boolean | null;\r\n valueType?: string;\r\n presentationKind?: string;\r\n defaultAggregation?: string;\r\n counterResetPolicy?: string;\r\n tableColumns?: IUnsTableColumnMetadata[];\r\n systemRole?: UnsAttributeSystemRole;\r\n relationshipEvidence?: IUnsRelationshipEvidenceMetadata;\r\n lifecycle?: IUnsLifecycleMetadata;\r\n validityMode?: \"interval\" | \"lifecycle\" | \"static\";\r\n expectedIntervalMs?: number;\r\n lifecycleEndValue?: string;\r\n packet: IUnsPacket;\r\n};\r\n\r\nexport default class UnsMqttProxy extends UnsProxy {\r\n private lastValues: Map<string, { value: ValueType; uom: string; timestamp: Date }> = new Map();\r\n private worker: Worker;\r\n private pendingEnqueues: Map<string, { resolve: () => void; reject: (reason?: any) => void }> = new Map();\r\n private unsParameters: IUnsParameters;\r\n protected processStatusTopic: string;\r\n public instanceName: string;\r\n private currentSequenceId: Map<string, number> = new Map();\r\n private topicBuilder: MqttTopicBuilder;\r\n private deltaModeDeprecationWarned = false;\r\n\r\n constructor(\r\n mqttHost: string,\r\n processName: string,\r\n instanceName: string,\r\n unsParameters?: IUnsParameters,\r\n publisherActive: boolean = false,\r\n subscriberActive: boolean = false\r\n ) {\r\n super();\r\n this.instanceName = instanceName;\r\n // Create the topic builder using packageJson values and the processName.\r\n this.topicBuilder = new MqttTopicBuilder(`uns-infra/${MqttTopicBuilder.sanitizeTopicPart(packageJson.name)}/${MqttTopicBuilder.sanitizeTopicPart(packageJson.version)}/${MqttTopicBuilder.sanitizeTopicPart(processName)}/`);\r\n\r\n // Generate the processStatusTopic using the builder.\r\n this.processStatusTopic = this.topicBuilder.getProcessStatusTopic();\r\n // Derive the instanceStatusTopic by appending the instance name.\r\n this.instanceStatusTopic = this.processStatusTopic + instanceName + \"/\";\r\n\r\n // Concatenate processName with instanceName for the worker identification.\r\n this.instanceNameWithSuffix = `${processName}-${instanceName}`;\r\n \r\n const mqttParameters: IMqttParameters = {\r\n mqttSubToTopics: unsParameters?.mqttSubToTopics ?? [],\r\n username: unsParameters?.username ?? \"\",\r\n password: unsParameters?.password ?? \"\",\r\n mqttSSL: unsParameters?.mqttSSL ?? false,\r\n statusTopic: this.instanceStatusTopic,\r\n rejectUnauthorized: unsParameters?.rejectUnauthorized ?? false,\r\n clientId: unsParameters?.clientId,\r\n hosts: unsParameters?.hosts,\r\n servers: unsParameters?.servers,\r\n port: unsParameters?.port,\r\n protocol: unsParameters?.protocol,\r\n keepalive: unsParameters?.keepalive,\r\n clean: unsParameters?.clean,\r\n connectTimeout: unsParameters?.connectTimeout,\r\n reconnectPeriod: unsParameters?.reconnectPeriod,\r\n reconnectOnConnackError: unsParameters?.reconnectOnConnackError,\r\n resubscribe: unsParameters?.resubscribe,\r\n queueQoSZero: unsParameters?.queueQoSZero,\r\n properties: unsParameters?.properties,\r\n ca: unsParameters?.ca,\r\n cert: unsParameters?.cert,\r\n key: unsParameters?.key,\r\n servername: unsParameters?.servername,\r\n };\r\n this.unsParameters = unsParameters ?? {};\r\n this.startQueueWorker(mqttHost, this.instanceNameWithSuffix, mqttParameters, publisherActive, subscriberActive);\r\n }\r\n\r\n /**\r\n * Resolve object identity from explicit fields or the tail of the topic path.\r\n * Falls back to parsing when not provided for backward compatibility.\r\n */\r\n private resolveObjectIdentity(msg: InternalMqttMessage): { objectType?: UnsObjectType; objectId?: UnsObjectId; asset?: UnsAsset } {\r\n const providedType = msg.objectType;\r\n const providedId = msg.objectId;\r\n const providedAsset = msg.asset;\r\n\r\n const topicParts = msg.topic.split(\"/\").filter((part) => part.length > 0);\r\n const hasObjectTail = topicParts.length >= 2;\r\n const parsedType = hasObjectTail ? topicParts[topicParts.length - 2] as UnsObjectType : undefined;\r\n const parsedId = hasObjectTail ? topicParts[topicParts.length - 1] as UnsObjectId : undefined;\r\n const parsedAsset = hasObjectTail\r\n ? (topicParts.length >= 3 ? topicParts[topicParts.length - 3] as UnsAsset : undefined)\r\n : (topicParts.length >= 1 ? topicParts[topicParts.length - 1] as UnsAsset : undefined);\r\n\r\n const objectType = providedType ?? parsedType;\r\n const objectId = providedId ?? parsedId ?? \"main\";\r\n const asset = providedAsset ?? parsedAsset;\r\n\r\n // If values are provided, trust them; otherwise derive from topic.\r\n if (!providedType || !providedId) {\r\n if (parsedType && parsedId) {\r\n logger.warn(`${this.instanceNameWithSuffix} - objectType/objectId missing; derived from topic tail ${parsedType}/${parsedId}`);\r\n } else {\r\n logger.warn(`${this.instanceNameWithSuffix} - objectType/objectId missing; defaulting objectId to 'main' for topic '${msg.topic}'. Expected topic to end with '<objectType>/<objectId>/'`);\r\n }\r\n }\r\n // Asset is optional; no warning on mismatch to avoid noisy logs when base topics don't carry it.\r\n\r\n msg.objectType = objectType;\r\n msg.objectId = objectId;\r\n msg.asset = asset;\r\n\r\n return { objectType, objectId, asset };\r\n }\r\n\r\n /**\r\n * Ensure the topic ends with a trailing slash for attribute concatenation.\r\n */\r\n private normalizeTopicWithObject(topic: string): string {\r\n return topic.endsWith(\"/\") ? topic : `${topic}/`;\r\n }\r\n\r\n /**\r\n * Starts a worker thread to process the throttled publish queue.\r\n */\r\n private startQueueWorker(\r\n mqttHost: string,\r\n instanceNameWithSuffix: string,\r\n mqttParameters: IMqttParameters,\r\n publisherActive: boolean,\r\n subscriberActive: boolean\r\n ): void {\r\n const workerData: IMqttWorkerData = {\r\n publishThrottlingDelay: this.unsParameters.publishThrottlingDelay ?? 1,\r\n subscribeThrottlingDelay: this.unsParameters.subscribeThrottlingDelay ?? 1,\r\n persistToDisk: false,\r\n mqttHost: mqttHost,\r\n instanceNameWithSuffix: instanceNameWithSuffix,\r\n mqttParameters: mqttParameters,\r\n publisherActive,\r\n subscriberActive,\r\n defaultPublishOptions: this.unsParameters.defaultPublishOptions,\r\n };\r\n\r\n this.worker = new Worker(workerScriptPath, { workerData });\r\n\r\n this.worker.on(\"message\", (msg) => {\r\n if (msg && msg.command === \"enqueueResult\" && msg.id) {\r\n const pending = this.pendingEnqueues.get(msg.id);\r\n if (pending) {\r\n if (msg.status === \"success\" && msg.topic && msg.message) {\r\n pending.resolve();\r\n } else {\r\n pending.reject(new Error(msg.error));\r\n }\r\n this.pendingEnqueues.delete(msg.id);\r\n }\r\n } else if (msg && msg.command === \"input\") {\r\n this.event.emit(\"input\", { topic: msg.topic, message: msg.message.toString(), packet: msg.packet });\r\n } else if (msg && (msg.command === \"handover_subscriber\" || msg.command === \"handover_publisher\")) {\r\n this.event.emit(\"mqttWorker\", { command: msg.command, batchSize: msg.batchSize, referenceHash: msg.referenceHash, instanceName: this.instanceName });\r\n } else if (msg && msg.command === \"mqttProxyStatus\") {\r\n this.event.emit(\"mqttProxyStatus\", { event: msg.event, value: msg.value, uom: msg.uom, statusTopic: msg.statusTopic });\r\n }\r\n });\r\n\r\n this.worker.on(\"error\", (err) => {\r\n logger.error(\"Error in worker:\", err);\r\n const reason = err instanceof Error ? err : new Error(String(err));\r\n for (const pending of this.pendingEnqueues.values()) {\r\n pending.reject(reason);\r\n }\r\n this.pendingEnqueues.clear();\r\n });\r\n\r\n this.worker.on(\"exit\", (code) => {\r\n if (code !== 0) {\r\n logger.error(`Worker exited with code ${code}`);\r\n const reason = new Error(`MQTT worker exited with code ${code}`);\r\n for (const pending of this.pendingEnqueues.values()) {\r\n pending.reject(reason);\r\n }\r\n this.pendingEnqueues.clear();\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Enqueues a message to the worker queue.\r\n *\r\n * @param topic - The topic to which the message belongs.\r\n * @param message - The message to be enqueued.\r\n * @param options - Optional publish options.\r\n * @returns A promise that resolves when the message is successfully enqueued.\r\n */\r\n private async enqueueMessageToWorkerQueue(topic: string, message: string, options?: IClientPublishOptions): Promise<void> {\r\n return new Promise((resolve, reject) => {\r\n // const id: string = String(this.currentSequenceId.get(topic) ?? 0);\r\n const id = `${Date.now()}-${Math.random()}`;\r\n this.pendingEnqueues.set(id, { resolve, reject });\r\n this.worker.postMessage({ command: \"enqueue\", id, topic, message, options });\r\n });\r\n }\r\n\r\n /**\r\n * Sets the publisher active state.\r\n *\r\n * @param batchSize - Optional batch size.\r\n * @param referenceHash - Optional reference hash.\r\n */\r\n public setPublisherActive(batchSize?: number, referenceHash?: string): void {\r\n this.worker.postMessage({ command: \"setPublisherActive\", batchSize, referenceHash });\r\n }\r\n\r\n /**\r\n * Sets the publisher to passive mode.\r\n * @returns A promise that resolves when the publisher is set to passive.\r\n */\r\n public setPublisherPassive(): Promise<UnsEvents[\"mqttWorker\"]> {\r\n this.worker.postMessage({ command: \"setPublisherPassive\"});\r\n return new Promise((resolve) => {\r\n this.event.on(\"mqttWorker\", (msg: UnsEvents[\"mqttWorker\"]) => {\r\n if (msg.command === \"handover_publisher\") {\r\n logger.info(`${this.instanceNameWithSuffix} - Publisher set to passive.`);\r\n resolve(msg);\r\n }\r\n });\r\n });\r\n }\r\n\r\n /**\r\n * Sets the subscriber active state.\r\n *\r\n * @param batchSize - Optional batch size.\r\n * @param referenceHash - Optional reference hash.\r\n */\r\n public setSubscriberActive(batchSize?: number, referenceHash?: string): void {\r\n this.worker.postMessage({ command: \"setSubscriberActive\", batchSize, referenceHash });\r\n }\r\n\r\n /**\r\n * Sets the subscriber to passive mode.\r\n * @returns A promise that resolves when the subscriber is set to passive.\r\n */\r\n public setSubscriberPassive(): Promise<UnsEvents[\"mqttWorker\"]> {\r\n this.worker.postMessage({ command: \"setSubscriberPassive\"});\r\n return new Promise((resolve) => {\r\n this.event.on(\"mqttWorker\", (msg: UnsEvents[\"mqttWorker\"]) => {\r\n if (msg.command === \"handover_subscriber\") {\r\n logger.info(`${this.instanceNameWithSuffix} - Publisher set to passive.`);\r\n resolve(msg);\r\n }\r\n });\r\n });\r\n }\r\n\r\n\r\n /**\r\n * Sets the subscriber to passive mode and allows the publisher to run\r\n * until the queue is empty (all messages are processed).\r\n */\r\n public async setSubscriberPassiveAndDrainQueue(): Promise<UnsEvents[\"mqttWorker\"]> {\r\n return new Promise(async (resolve) => {\r\n const mqttWorkerData = await this.setSubscriberPassive();\r\n while (this.pendingEnqueues.size > 0) {\r\n await new Promise((resolve) => setTimeout(resolve, 100)); // Poll every 100ms\r\n }\r\n logger.info(`${this.instanceNameWithSuffix} - Subscriber set to passive and queue drained.`);\r\n resolve(mqttWorkerData);\r\n });\r\n }\r\n\r\n /**\r\n * Processes and publishes MQTT messages based on the selected message mode.\r\n *\r\n * @param mqttMessage - The MQTT message object.\r\n * @param mode - The message mode. Delta and Both are deprecated because\r\n * producer-side delta calculation loses state across restarts.\r\n */\r\n public async publishMqttMessage(mqttMessage: IMqttPublishRequest | null, mode: MessageMode = MessageMode.Raw) {\r\n if (!mqttMessage) {\r\n logger.error(`${this.instanceNameWithSuffix} - Error publishing mqtt message: mqttMessage must be defined.`);\r\n return;\r\n }\r\n\r\n const attrs = Array.isArray(mqttMessage.attributes)\r\n ? mqttMessage.attributes\r\n : [mqttMessage.attributes];\r\n const { topic, asset, assetDescription, objectType, objectTypeDescription, objectId, virtualGroup: requestVirtualGroup } = mqttMessage;\r\n for (const attrEntry of attrs) {\r\n const attrDescription = attrEntry.description ?? getAttributeDescription(attrEntry.attribute);\r\n const message: IUnsMessage =\r\n \"message\" in attrEntry && attrEntry.message\r\n ? attrEntry.message\r\n : \"data\" in attrEntry && attrEntry.data\r\n ? { data: attrEntry.data, createdAt: attrEntry.createdAt, expiresAt: attrEntry.expiresAt }\r\n : \"table\" in attrEntry && attrEntry.table\r\n ? { table: attrEntry.table, createdAt: attrEntry.createdAt, expiresAt: attrEntry.expiresAt }\r\n : (() => { throw new Error(\"Attribute entry must include exactly one of data/table/message\"); })();\r\n const packet = await UnsPacket.unsPacketFromUnsMessage(message);\r\n const singleMsg: InternalMqttMessage = {\r\n topic,\r\n asset,\r\n assetDescription,\r\n objectType,\r\n objectTypeDescription,\r\n objectId,\r\n virtualGroup: attrEntry.virtualGroup ?? requestVirtualGroup,\r\n attribute: attrEntry.attribute,\r\n description: attrDescription,\r\n tags: attrEntry.tags,\r\n attributeNeedsPersistence: attrEntry.attributeNeedsPersistence,\r\n valueType: attrEntry.valueType,\r\n presentationKind: attrEntry.presentationKind,\r\n defaultAggregation: attrEntry.defaultAggregation,\r\n counterResetPolicy: attrEntry.counterResetPolicy,\r\n tableColumns: attrEntry.tableColumns,\r\n systemRole: attrEntry.systemRole,\r\n relationshipEvidence: attrEntry.relationshipEvidence,\r\n lifecycle: attrEntry.lifecycle,\r\n ...(attrEntry.validityMode ? { validityMode: attrEntry.validityMode } : {}),\r\n ...(attrEntry.expectedIntervalMs ? { expectedIntervalMs: attrEntry.expectedIntervalMs } : {}),\r\n ...(attrEntry.lifecycleEndValue ? { lifecycleEndValue: attrEntry.lifecycleEndValue } : {}),\r\n packet,\r\n };\r\n\r\n // existing single-attribute flow\r\n const baseDescription =\r\n singleMsg.description ??\r\n getAttributeDescription(singleMsg.attribute) ??\r\n singleMsg.attribute;\r\n const mqttMessageWithDesc = { ...singleMsg, description: baseDescription };\r\n\r\n const time = UnsPacket.formatToISO8601(new Date());\r\n if (mode === MessageMode.Delta || mode === MessageMode.Both) {\r\n this.warnDeprecatedDeltaMode(mode);\r\n }\r\n switch (mode) {\r\n case MessageMode.Raw: {\r\n await this.processAndEnqueueMessage(mqttMessageWithDesc, time, false);\r\n break;\r\n }\r\n case MessageMode.Delta: {\r\n const deltaMessage = { ...mqttMessageWithDesc };\r\n deltaMessage.attribute = `${mqttMessageWithDesc.attribute}-delta`;\r\n deltaMessage.description = `${baseDescription ?? \"\"} (delta)`;\r\n await this.processAndEnqueueMessage(deltaMessage, time, true);\r\n break;\r\n }\r\n case MessageMode.Both: {\r\n await this.processAndEnqueueMessage(mqttMessageWithDesc, time, false);\r\n const deltaMessageBoth = { ...mqttMessageWithDesc };\r\n deltaMessageBoth.attribute = `${mqttMessageWithDesc.attribute}-delta`;\r\n deltaMessageBoth.description = `${baseDescription ?? \"\"} (delta)`;\r\n await this.processAndEnqueueMessage(deltaMessageBoth, time, true);\r\n break;\r\n }\r\n }\r\n }\r\n return;\r\n }\r\n\r\n private warnDeprecatedDeltaMode(mode: MessageMode): void {\r\n if (this.deltaModeDeprecationWarned) return;\r\n this.deltaModeDeprecationWarned = true;\r\n logger.warn(\r\n `${this.instanceNameWithSuffix} - MessageMode.${mode} is deprecated: producer-side delta calculation loses previous-value state across service restarts. Publish raw cumulative counter values and request delta/rate from Datahub history APIs.`,\r\n );\r\n }\r\n\r\n /**\r\n * Publishes a message to a specified topic.\r\n *\r\n * @param topic - The MQTT topic.\r\n * @param message - The message to publish.\r\n * @returns A promise that resolves when enqueued.\r\n */\r\n public publishMessage(topic: string, message: string, options?: IClientPublishOptions): Promise<void> {\r\n return this.enqueueMessageToWorkerQueue(topic, message, options);\r\n }\r\n\r\n /**\r\n * Parses an MQTT packet from a JSON string.\r\n *\r\n * @param mqttPacket - The MQTT packet string.\r\n * @returns A parsed IUnsPacket object or null.\r\n */\r\n public parseMqttPacket(mqttPacket: string): IUnsPacket | null {\r\n return UnsPacket.parseMqttPacket(mqttPacket, this.instanceNameWithSuffix);\r\n }\r\n\r\n /**\r\n * Subscribes asynchronously to one or more topics.\r\n *\r\n * @param topics - A topic or list of topics.\r\n */\r\n public subscribeAsync(topics: string | string[]): void {\r\n this.worker.postMessage({ command: \"subscribeAsync\", topics });\r\n }\r\n\r\n /**\r\n * Unsubscribes asynchronously from the given topics.\r\n *\r\n * @param topics - A list of topics.\r\n */\r\n public unsubscribeAsync(topics: string[]): void {\r\n this.worker.postMessage({ command: \"unsubscribeAsync\", topics });\r\n }\r\n\r\n /**\r\n * Processes and enqueues a message to the worker queue, including handling\r\n * sequencing, value differences, and tracking of unique topics.\r\n *\r\n * @param msg - The MQTT message to process.\r\n * @param time - The timestamp.\r\n * @param valueIsCumulative - Whether the value is cumulative.\r\n */\r\n private async processAndEnqueueMessage(msg: InternalMqttMessage, time: string, valueIsCumulative: boolean = false): Promise<void> {\r\n try {\r\n const attributeType =\r\n msg.packet.message.data ? UnsAttributeType.Data :\r\n msg.packet.message.table ? UnsAttributeType.Table : null;\r\n \r\n let dataGroup = \"\";\r\n if (attributeType == UnsAttributeType.Data)\r\n dataGroup = msg.packet.message.data.dataGroup ?? \"\";\r\n if (attributeType == UnsAttributeType.Table)\r\n dataGroup = msg.packet.message.table.dataGroup ?? \"\";\r\n\r\n const { objectType, objectId, asset } = this.resolveObjectIdentity(msg);\r\n const normalizedTopic = this.normalizeTopicWithObject(msg.topic);\r\n msg.topic = normalizedTopic;\r\n const description = msg.description ?? getAttributeDescription(msg.attribute as string) ?? \"\";\r\n const objectTypeDescription = msg.objectTypeDescription ?? (objectType ? getObjectTypeDescription(objectType) : undefined);\r\n\r\n // Runtime validation for validity fields\r\n if (msg.validityMode) {\r\n const validModes = new Set([\"interval\", \"lifecycle\", \"static\"]);\r\n if (!validModes.has(msg.validityMode)) {\r\n logger.warn(`${this.instanceNameWithSuffix} - Invalid validityMode \"${msg.validityMode}\" for attribute \"${msg.attribute}\". Expected: interval | lifecycle | static.`);\r\n }\r\n if (msg.expectedIntervalMs && msg.validityMode !== \"interval\") {\r\n logger.warn(`${this.instanceNameWithSuffix} - expectedIntervalMs is set but validityMode is \"${msg.validityMode}\" (only used with \"interval\") for attribute \"${msg.attribute}\".`);\r\n }\r\n if (msg.lifecycleEndValue && msg.validityMode !== \"lifecycle\") {\r\n logger.warn(`${this.instanceNameWithSuffix} - lifecycleEndValue is set but validityMode is \"${msg.validityMode}\" (only used with \"lifecycle\") for attribute \"${msg.attribute}\".`);\r\n }\r\n if (msg.validityMode === \"interval\" && !msg.expectedIntervalMs) {\r\n logger.debug(`${this.instanceNameWithSuffix} - validityMode \"interval\" without expectedIntervalMs for attribute \"${msg.attribute}\" — controller will use its default.`);\r\n }\r\n }\r\n\r\n this.registerUniqueTopic({\r\n timestamp: time,\r\n topic: msg.topic,\r\n attribute: msg.attribute,\r\n attributeType: attributeType,\r\n description,\r\n tags: msg.tags,\r\n attributeNeedsPersistence: msg.attributeNeedsPersistence,\r\n valueType: msg.valueType,\r\n presentationKind: msg.presentationKind,\r\n defaultAggregation: msg.defaultAggregation,\r\n counterResetPolicy: msg.counterResetPolicy,\r\n tableColumns: msg.tableColumns,\r\n systemRole: msg.systemRole,\r\n relationshipEvidence: msg.relationshipEvidence,\r\n lifecycle: msg.lifecycle,\r\n dataGroup,\r\n virtualGroup: msg.virtualGroup,\r\n asset,\r\n assetDescription: msg.assetDescription,\r\n objectType,\r\n objectTypeDescription,\r\n objectId,\r\n ...(msg.validityMode ? { validityMode: msg.validityMode } : {}),\r\n ...(msg.expectedIntervalMs ? { expectedIntervalMs: msg.expectedIntervalMs } : {}),\r\n ...(msg.lifecycleEndValue ? { lifecycleEndValue: msg.lifecycleEndValue } : {}),\r\n });\r\n\r\n const publishTopic = `${msg.topic}${asset ? `${asset}/` : \"\"}${objectType ? `${objectType}/` : \"\"}${objectId ? `${objectId}/` : \"\"}${msg.attribute}`;\r\n const sequenceId = this.currentSequenceId.get(msg.topic) ?? 0;\r\n this.currentSequenceId.set(msg.topic, sequenceId + 1);\r\n msg.packet.sequenceId = sequenceId;\r\n\r\n if (msg.packet.message.data) {\r\n const newValue = msg.packet.message.data.value;\r\n const newUom: MeasurementUnit = msg.packet.message.data.uom;\r\n const lastValueEntry = this.lastValues.get(publishTopic);\r\n const currentTime = new Date(msg.packet.message.data.time);\r\n\r\n if (lastValueEntry) {\r\n const intervalBetweenMessages = currentTime.getTime() - lastValueEntry.timestamp.getTime();\r\n const lastValue = lastValueEntry.value;\r\n this.lastValues.set(publishTopic, { value: newValue, uom: newUom, timestamp: currentTime });\r\n // Compute the delta and manage cumulative resets\r\n if (valueIsCumulative == true && typeof newValue === \"number\" && typeof lastValue === \"number\") {\r\n // Skip if newValue is 0 (likely a glitch)\r\n if (newValue === 0) {\r\n return; // Don't process or enqueue\r\n }\r\n const delta = newValue - lastValue;\r\n msg.packet.message.data.value = delta < 0 ? newValue : delta;\r\n }\r\n msg.packet.interval = intervalBetweenMessages;\r\n await this.enqueueMessageToWorkerQueue(publishTopic, JSON.stringify(msg.packet));\r\n } else {\r\n this.lastValues.set(publishTopic, { value: newValue, uom: newUom, timestamp: currentTime });\r\n logger.debug(`${this.instanceNameWithSuffix} - Need one more packet to calculate interval on topic ${publishTopic}`);\r\n if (valueIsCumulative === false) {\r\n await this.enqueueMessageToWorkerQueue(publishTopic, JSON.stringify(msg.packet));\r\n } else {\r\n logger.debug(`${this.instanceNameWithSuffix} - Need one more packet to calculate difference on value in data for topic ${publishTopic}`);\r\n }\r\n }\r\n } else if (msg.packet.message.table) {\r\n await this.enqueueMessageToWorkerQueue(publishTopic, JSON.stringify(msg.packet));\r\n } else {\r\n logger.error(`${this.instanceNameWithSuffix} - Error publishing message to topic ${publishTopic}: packet.message must include data or table`);\r\n }\r\n } catch (error: any) {\r\n logger.error(`${this.instanceNameWithSuffix} - Error publishing message to topic ${msg.topic}${msg.attribute}: ${error.message}`);\r\n }\r\n }\r\n\r\n /**\r\n * Stops the UnsProxy instance and cleans up resources.\r\n */\r\n public async stop(): Promise<void> {\r\n super.stop();\r\n // Terminate the worker thread if it exists.\r\n if (this.worker) {\r\n try {\r\n const exitCode = await this.worker.terminate();\r\n logger.info(`${this.instanceNameWithSuffix} - Worker terminated with exit code ${exitCode}`);\r\n } catch (error: any) {\r\n logger.error(`${this.instanceNameWithSuffix} - Error terminating worker: ${error.message}`);\r\n }\r\n }\r\n \r\n // Optionally, handle any pending enqueues.\r\n for (const [id, pending] of this.pendingEnqueues) {\r\n pending.reject(new Error(\"UnsProxy has been stopped\"));\r\n this.pendingEnqueues.delete(id);\r\n }\r\n }\r\n\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"file":"uns-mqtt-proxy.js","sourceRoot":"","sources":["../../src/uns-mqtt/uns-mqtt-proxy.ts"],"names":[],"mappings":"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","sourcesContent":["import { readFileSync } from \"fs\";\r\nimport { IClientPublishOptions } from \"mqtt\";\r\nimport * as path from \"path\";\r\nimport { Worker } from \"worker_threads\";\r\nimport { fileURLToPath } from \"url\";\r\nimport { basePath } from \"../base-path.js\";\r\nimport logger from \"../logger.js\";\r\nimport { IMqttPublishRequest, IUnsLifecycleMetadata, IUnsMessage, IUnsPacket, IUnsParameters, IUnsRelationshipEvidenceMetadata, IUnsTableColumnMetadata, UnsAttribute, UnsAttributeSystemRole, UnsEvents, ValueType } from \"../uns/uns-interfaces.js\";\r\nimport { getObjectTypeDescription, type UnsObjectId, type UnsObjectType } from \"../uns/uns-object.js\";\r\nimport type { UnsAsset } from \"../uns/uns-asset.js\";\r\nimport { MeasurementUnit } from \"../uns/uns-measurements.js\";\r\nimport { UnsPacket } from \"../uns/uns-packet.js\";\r\nimport { IMqttParameters, IMqttWorkerData } from \"./mqtt-interfaces.js\";\r\nimport { MqttTopicBuilder } from \"./mqtt-topic-builder.js\";\r\nimport UnsProxy from \"../uns/uns-proxy.js\";\r\nimport { UnsAttributeType } from \"../graphql/schema.js\";\r\nimport { getAttributeDescription } from \"../uns/uns-attributes.js\";\r\nimport { UnsTags } from \"../uns/uns-tags.js\";\r\nimport { UnsTopics } from \"../uns/uns-topics.js\";\r\n\r\nconst packageJsonPath = path.join(basePath, \"package.json\");\r\nconst packageJson = JSON.parse(readFileSync(packageJsonPath, \"utf8\"));\r\n\r\nconst moduleDirectory = path.dirname(fileURLToPath(import.meta.url));\r\nconst packageRoot = path.resolve(moduleDirectory, \"..\", \"..\");\r\nconst workerScriptPath = path.join(packageRoot, \"dist/uns-mqtt/mqtt-worker-init.js\");\r\n\r\nexport enum MessageMode {\n Raw = 'raw', // Send only the original message\r\n /**\r\n * @deprecated Producer-side delta calculation loses state across restarts.\r\n * Publish raw cumulative counter values and request delta/rate from Datahub history APIs.\r\n */\r\n Delta = 'delta', // Send only the delta message\r\n /**\r\n * @deprecated Producer-side delta calculation loses state across restarts.\r\n * Publish raw cumulative counter values and request delta/rate from Datahub history APIs.\r\n */\r\n Both = 'both' // Send both the original and delta messages\n}\n\nexport interface UnsMqttProxyStopOptions {\n drain?: boolean;\n timeoutMs?: number;\n}\n\r\ntype InternalMqttMessage = {\r\n topic: UnsTopics;\r\n attribute: UnsAttribute;\r\n asset: UnsAsset;\r\n assetDescription?: string;\r\n objectType: UnsObjectType;\r\n objectTypeDescription?: string;\r\n objectId: UnsObjectId;\r\n virtualGroup?: string;\r\n description?: string;\r\n tags?: UnsTags[];\r\n attributeNeedsPersistence?: boolean | null;\r\n valueType?: string;\r\n presentationKind?: string;\r\n defaultAggregation?: string;\r\n counterResetPolicy?: string;\r\n tableColumns?: IUnsTableColumnMetadata[];\r\n systemRole?: UnsAttributeSystemRole;\r\n relationshipEvidence?: IUnsRelationshipEvidenceMetadata;\r\n lifecycle?: IUnsLifecycleMetadata;\r\n validityMode?: \"interval\" | \"lifecycle\" | \"static\";\r\n expectedIntervalMs?: number;\r\n lifecycleEndValue?: string;\r\n packet: IUnsPacket;\r\n};\r\n\r\nexport default class UnsMqttProxy extends UnsProxy {\n public static readonly DEFAULT_DRAIN_TIMEOUT_MS = 30_000;\n private lastValues: Map<string, { value: ValueType; uom: string; timestamp: Date }> = new Map();\n private worker: Worker;\n private pendingEnqueues: Map<string, { resolve: () => void; reject: (reason?: any) => void }> = new Map();\n private pendingPublishCompletions = 0;\n private unsParameters: IUnsParameters;\n protected processStatusTopic: string;\r\n public instanceName: string;\r\n private currentSequenceId: Map<string, number> = new Map();\n private topicBuilder: MqttTopicBuilder;\n private deltaModeDeprecationWarned = false;\n private drainWaiters: Array<{ resolve: () => void; reject: (reason?: any) => void; timer?: NodeJS.Timeout }> = [];\n private workerFailure: Error | null = null;\n\n constructor(\n mqttHost: string,\r\n processName: string,\r\n instanceName: string,\r\n unsParameters?: IUnsParameters,\r\n publisherActive: boolean = false,\r\n subscriberActive: boolean = false\r\n ) {\r\n super();\r\n this.instanceName = instanceName;\r\n // Create the topic builder using packageJson values and the processName.\r\n this.topicBuilder = new MqttTopicBuilder(`uns-infra/${MqttTopicBuilder.sanitizeTopicPart(packageJson.name)}/${MqttTopicBuilder.sanitizeTopicPart(packageJson.version)}/${MqttTopicBuilder.sanitizeTopicPart(processName)}/`);\r\n\r\n // Generate the processStatusTopic using the builder.\r\n this.processStatusTopic = this.topicBuilder.getProcessStatusTopic();\r\n // Derive the instanceStatusTopic by appending the instance name.\r\n this.instanceStatusTopic = this.processStatusTopic + instanceName + \"/\";\r\n\r\n // Concatenate processName with instanceName for the worker identification.\r\n this.instanceNameWithSuffix = `${processName}-${instanceName}`;\r\n \r\n const mqttParameters: IMqttParameters = {\r\n mqttSubToTopics: unsParameters?.mqttSubToTopics ?? [],\r\n username: unsParameters?.username ?? \"\",\r\n password: unsParameters?.password ?? \"\",\r\n mqttSSL: unsParameters?.mqttSSL ?? false,\r\n statusTopic: this.instanceStatusTopic,\r\n rejectUnauthorized: unsParameters?.rejectUnauthorized ?? false,\r\n clientId: unsParameters?.clientId,\r\n hosts: unsParameters?.hosts,\r\n servers: unsParameters?.servers,\r\n port: unsParameters?.port,\r\n protocol: unsParameters?.protocol,\r\n keepalive: unsParameters?.keepalive,\r\n clean: unsParameters?.clean,\r\n connectTimeout: unsParameters?.connectTimeout,\r\n reconnectPeriod: unsParameters?.reconnectPeriod,\r\n reconnectOnConnackError: unsParameters?.reconnectOnConnackError,\r\n resubscribe: unsParameters?.resubscribe,\r\n queueQoSZero: unsParameters?.queueQoSZero,\r\n properties: unsParameters?.properties,\r\n ca: unsParameters?.ca,\r\n cert: unsParameters?.cert,\r\n key: unsParameters?.key,\r\n servername: unsParameters?.servername,\r\n };\r\n this.unsParameters = unsParameters ?? {};\r\n this.startQueueWorker(mqttHost, this.instanceNameWithSuffix, mqttParameters, publisherActive, subscriberActive);\r\n }\r\n\r\n /**\r\n * Resolve object identity from explicit fields or the tail of the topic path.\r\n * Falls back to parsing when not provided for backward compatibility.\r\n */\r\n private resolveObjectIdentity(msg: InternalMqttMessage): { objectType?: UnsObjectType; objectId?: UnsObjectId; asset?: UnsAsset } {\r\n const providedType = msg.objectType;\r\n const providedId = msg.objectId;\r\n const providedAsset = msg.asset;\r\n\r\n const topicParts = msg.topic.split(\"/\").filter((part) => part.length > 0);\r\n const hasObjectTail = topicParts.length >= 2;\r\n const parsedType = hasObjectTail ? topicParts[topicParts.length - 2] as UnsObjectType : undefined;\r\n const parsedId = hasObjectTail ? topicParts[topicParts.length - 1] as UnsObjectId : undefined;\r\n const parsedAsset = hasObjectTail\r\n ? (topicParts.length >= 3 ? topicParts[topicParts.length - 3] as UnsAsset : undefined)\r\n : (topicParts.length >= 1 ? topicParts[topicParts.length - 1] as UnsAsset : undefined);\r\n\r\n const objectType = providedType ?? parsedType;\r\n const objectId = providedId ?? parsedId ?? \"main\";\r\n const asset = providedAsset ?? parsedAsset;\r\n\r\n // If values are provided, trust them; otherwise derive from topic.\r\n if (!providedType || !providedId) {\r\n if (parsedType && parsedId) {\r\n logger.warn(`${this.instanceNameWithSuffix} - objectType/objectId missing; derived from topic tail ${parsedType}/${parsedId}`);\r\n } else {\r\n logger.warn(`${this.instanceNameWithSuffix} - objectType/objectId missing; defaulting objectId to 'main' for topic '${msg.topic}'. Expected topic to end with '<objectType>/<objectId>/'`);\r\n }\r\n }\r\n // Asset is optional; no warning on mismatch to avoid noisy logs when base topics don't carry it.\r\n\r\n msg.objectType = objectType;\r\n msg.objectId = objectId;\r\n msg.asset = asset;\r\n\r\n return { objectType, objectId, asset };\r\n }\r\n\r\n /**\r\n * Ensure the topic ends with a trailing slash for attribute concatenation.\r\n */\r\n private normalizeTopicWithObject(topic: string): string {\r\n return topic.endsWith(\"/\") ? topic : `${topic}/`;\r\n }\r\n\r\n /**\r\n * Starts a worker thread to process the throttled publish queue.\r\n */\r\n private startQueueWorker(\r\n mqttHost: string,\r\n instanceNameWithSuffix: string,\r\n mqttParameters: IMqttParameters,\r\n publisherActive: boolean,\r\n subscriberActive: boolean\r\n ): void {\r\n const workerData: IMqttWorkerData = {\r\n publishThrottlingDelay: this.unsParameters.publishThrottlingDelay ?? 1,\r\n publishConcurrency: this.unsParameters.publishConcurrency ?? 1,\r\n maxPendingPublishes: this.unsParameters.maxPendingPublishes,\r\n subscribeThrottlingDelay: this.unsParameters.subscribeThrottlingDelay ?? 1,\r\n persistToDisk: false,\r\n mqttHost: mqttHost,\r\n instanceNameWithSuffix: instanceNameWithSuffix,\r\n mqttParameters: mqttParameters,\r\n publisherActive,\r\n subscriberActive,\r\n defaultPublishOptions: this.unsParameters.defaultPublishOptions,\r\n };\r\n\r\n this.worker = new Worker(workerScriptPath, { workerData });\n\n this.worker.on(\"message\", (msg) => {\n if (msg && msg.command === \"enqueueAccepted\" && msg.id) {\n const pending = this.pendingEnqueues.get(msg.id);\n if (pending) {\n if (msg.status === \"accepted\") {\n this.pendingPublishCompletions += 1;\n pending.resolve();\n } else {\n pending.reject(new Error(msg.error));\n }\n this.pendingEnqueues.delete(msg.id);\n this.notifyDrainWaiters();\n }\n } else if (msg && msg.command === \"publishResult\" && msg.id) {\n if (this.pendingPublishCompletions > 0) {\n this.pendingPublishCompletions -= 1;\n }\n if (msg.status === \"error\") {\n const errorMessage = msg.error ?? `Error publishing to topic ${msg.topic ?? \"unknown\"}`;\n this.event.emit(\"error\", { code: 0, message: errorMessage });\n }\n this.notifyDrainWaiters();\n } else if (msg && msg.command === \"input\") {\n this.event.emit(\"input\", { topic: msg.topic, message: msg.message.toString(), packet: msg.packet });\n } else if (msg && (msg.command === \"handover_subscriber\" || msg.command === \"handover_publisher\")) {\n this.event.emit(\"mqttWorker\", { command: msg.command, batchSize: msg.batchSize, referenceHash: msg.referenceHash, instanceName: this.instanceName });\n } else if (msg && msg.command === \"mqttProxyStatus\") {\n this.event.emit(\"mqttProxyStatus\", { event: msg.event, value: msg.value, uom: msg.uom, statusTopic: msg.statusTopic });\r\n }\r\n });\r\n\r\n this.worker.on(\"error\", (err) => {\n logger.error(\"Error in worker:\", err);\n const reason = err instanceof Error ? err : new Error(String(err));\n this.failPendingPublishes(reason);\n });\n\n this.worker.on(\"exit\", (code) => {\n if (code !== 0) {\n logger.error(`Worker exited with code ${code}`);\n const reason = new Error(`MQTT worker exited with code ${code}`);\n this.failPendingPublishes(reason);\n }\n });\n }\n\r\n /**\r\n * Enqueues a message to the worker queue.\r\n *\r\n * @param topic - The topic to which the message belongs.\r\n * @param message - The message to be enqueued.\r\n * @param options - Optional publish options.\r\n * @returns A promise that resolves when the message is accepted into the worker queue.\n */\n private async enqueueMessageToWorkerQueue(topic: string, message: string, options?: IClientPublishOptions): Promise<void> {\n return new Promise((resolve, reject) => {\n if (this.workerFailure) {\n reject(this.workerFailure);\n return;\n }\n const id = `${Date.now()}-${Math.random()}`;\n this.pendingEnqueues.set(id, { resolve, reject });\n this.worker.postMessage({ command: \"enqueue\", id, topic, message, options });\n this.notifyDrainWaiters();\n });\n }\n\r\n /**\r\n * Sets the publisher active state.\r\n *\r\n * @param batchSize - Optional batch size.\r\n * @param referenceHash - Optional reference hash.\r\n */\r\n public setPublisherActive(batchSize?: number, referenceHash?: string): void {\r\n this.worker.postMessage({ command: \"setPublisherActive\", batchSize, referenceHash });\r\n }\r\n\r\n /**\r\n * Sets the publisher to passive mode.\r\n * @returns A promise that resolves when the publisher is set to passive.\r\n */\r\n public setPublisherPassive(): Promise<UnsEvents[\"mqttWorker\"]> {\r\n this.worker.postMessage({ command: \"setPublisherPassive\"});\r\n return new Promise((resolve) => {\r\n this.event.on(\"mqttWorker\", (msg: UnsEvents[\"mqttWorker\"]) => {\r\n if (msg.command === \"handover_publisher\") {\r\n logger.info(`${this.instanceNameWithSuffix} - Publisher set to passive.`);\r\n resolve(msg);\r\n }\r\n });\r\n });\r\n }\r\n\r\n /**\r\n * Sets the subscriber active state.\r\n *\r\n * @param batchSize - Optional batch size.\r\n * @param referenceHash - Optional reference hash.\r\n */\r\n public setSubscriberActive(batchSize?: number, referenceHash?: string): void {\r\n this.worker.postMessage({ command: \"setSubscriberActive\", batchSize, referenceHash });\r\n }\r\n\r\n /**\r\n * Sets the subscriber to passive mode.\r\n * @returns A promise that resolves when the subscriber is set to passive.\r\n */\r\n public setSubscriberPassive(): Promise<UnsEvents[\"mqttWorker\"]> {\r\n this.worker.postMessage({ command: \"setSubscriberPassive\"});\r\n return new Promise((resolve) => {\r\n this.event.on(\"mqttWorker\", (msg: UnsEvents[\"mqttWorker\"]) => {\r\n if (msg.command === \"handover_subscriber\") {\r\n logger.info(`${this.instanceNameWithSuffix} - Publisher set to passive.`);\r\n resolve(msg);\r\n }\r\n });\r\n });\r\n }\r\n\r\n\r\n /**\r\n * Sets the subscriber to passive mode and allows the publisher to run\r\n * until the queue is empty (all messages are processed).\r\n */\r\n public async setSubscriberPassiveAndDrainQueue(): Promise<UnsEvents[\"mqttWorker\"]> {\n return new Promise(async (resolve) => {\n const mqttWorkerData = await this.setSubscriberPassive();\n await this.flush();\n logger.info(`${this.instanceNameWithSuffix} - Subscriber set to passive and queue drained.`);\n resolve(mqttWorkerData);\n });\n }\n\n public async drainPublishes(timeoutMs: number = UnsMqttProxy.DEFAULT_DRAIN_TIMEOUT_MS): Promise<void> {\n if (this.workerFailure) {\n throw this.workerFailure;\n }\n if (this.pendingEnqueues.size === 0 && this.pendingPublishCompletions === 0) {\n return;\n }\n await new Promise<void>((resolve, reject) => {\n const waiter = { resolve, reject, timer: undefined as NodeJS.Timeout | undefined };\n if (Number.isFinite(timeoutMs) && timeoutMs > 0) {\n waiter.timer = setTimeout(() => {\n this.removeDrainWaiter(waiter);\n reject(new Error(`Timed out waiting for MQTT publishes to drain after ${timeoutMs}ms.`));\n }, timeoutMs);\n }\n this.drainWaiters.push(waiter);\n this.notifyDrainWaiters();\n });\n }\n\n public async flush(timeoutMs: number = UnsMqttProxy.DEFAULT_DRAIN_TIMEOUT_MS): Promise<void> {\n await this.drainPublishes(timeoutMs);\n }\n\r\n /**\r\n * Processes and publishes MQTT messages based on the selected message mode.\r\n *\r\n * @param mqttMessage - The MQTT message object.\r\n * @param mode - The message mode. Delta and Both are deprecated because\r\n * producer-side delta calculation loses state across restarts.\r\n */\r\n public async publishMqttMessage(mqttMessage: IMqttPublishRequest | null, mode: MessageMode = MessageMode.Raw) {\r\n if (!mqttMessage) {\r\n logger.error(`${this.instanceNameWithSuffix} - Error publishing mqtt message: mqttMessage must be defined.`);\r\n return;\r\n }\r\n\r\n const attrs = Array.isArray(mqttMessage.attributes)\r\n ? mqttMessage.attributes\r\n : [mqttMessage.attributes];\r\n const { topic, asset, assetDescription, objectType, objectTypeDescription, objectId, virtualGroup: requestVirtualGroup } = mqttMessage;\r\n for (const attrEntry of attrs) {\r\n const attrDescription = attrEntry.description ?? getAttributeDescription(attrEntry.attribute);\r\n const message: IUnsMessage =\r\n \"message\" in attrEntry && attrEntry.message\r\n ? attrEntry.message\r\n : \"data\" in attrEntry && attrEntry.data\r\n ? { data: attrEntry.data, createdAt: attrEntry.createdAt, expiresAt: attrEntry.expiresAt }\r\n : \"table\" in attrEntry && attrEntry.table\r\n ? { table: attrEntry.table, createdAt: attrEntry.createdAt, expiresAt: attrEntry.expiresAt }\r\n : (() => { throw new Error(\"Attribute entry must include exactly one of data/table/message\"); })();\r\n const packet = await UnsPacket.unsPacketFromUnsMessage(message);\r\n const singleMsg: InternalMqttMessage = {\r\n topic,\r\n asset,\r\n assetDescription,\r\n objectType,\r\n objectTypeDescription,\r\n objectId,\r\n virtualGroup: attrEntry.virtualGroup ?? requestVirtualGroup,\r\n attribute: attrEntry.attribute,\r\n description: attrDescription,\r\n tags: attrEntry.tags,\r\n attributeNeedsPersistence: attrEntry.attributeNeedsPersistence,\r\n valueType: attrEntry.valueType,\r\n presentationKind: attrEntry.presentationKind,\r\n defaultAggregation: attrEntry.defaultAggregation,\r\n counterResetPolicy: attrEntry.counterResetPolicy,\r\n tableColumns: attrEntry.tableColumns,\r\n systemRole: attrEntry.systemRole,\r\n relationshipEvidence: attrEntry.relationshipEvidence,\r\n lifecycle: attrEntry.lifecycle,\r\n ...(attrEntry.validityMode ? { validityMode: attrEntry.validityMode } : {}),\r\n ...(attrEntry.expectedIntervalMs ? { expectedIntervalMs: attrEntry.expectedIntervalMs } : {}),\r\n ...(attrEntry.lifecycleEndValue ? { lifecycleEndValue: attrEntry.lifecycleEndValue } : {}),\r\n packet,\r\n };\r\n\r\n // existing single-attribute flow\r\n const baseDescription =\r\n singleMsg.description ??\r\n getAttributeDescription(singleMsg.attribute) ??\r\n singleMsg.attribute;\r\n const mqttMessageWithDesc = { ...singleMsg, description: baseDescription };\r\n\r\n const time = UnsPacket.formatToISO8601(new Date());\r\n if (mode === MessageMode.Delta || mode === MessageMode.Both) {\r\n this.warnDeprecatedDeltaMode(mode);\r\n }\r\n switch (mode) {\r\n case MessageMode.Raw: {\r\n await this.processAndEnqueueMessage(mqttMessageWithDesc, time, false);\r\n break;\r\n }\r\n case MessageMode.Delta: {\r\n const deltaMessage = { ...mqttMessageWithDesc };\r\n deltaMessage.attribute = `${mqttMessageWithDesc.attribute}-delta`;\r\n deltaMessage.description = `${baseDescription ?? \"\"} (delta)`;\r\n await this.processAndEnqueueMessage(deltaMessage, time, true);\r\n break;\r\n }\r\n case MessageMode.Both: {\r\n await this.processAndEnqueueMessage(mqttMessageWithDesc, time, false);\r\n const deltaMessageBoth = { ...mqttMessageWithDesc };\r\n deltaMessageBoth.attribute = `${mqttMessageWithDesc.attribute}-delta`;\r\n deltaMessageBoth.description = `${baseDescription ?? \"\"} (delta)`;\r\n await this.processAndEnqueueMessage(deltaMessageBoth, time, true);\r\n break;\r\n }\r\n }\r\n }\r\n return;\r\n }\r\n\r\n private warnDeprecatedDeltaMode(mode: MessageMode): void {\r\n if (this.deltaModeDeprecationWarned) return;\r\n this.deltaModeDeprecationWarned = true;\r\n logger.warn(\r\n `${this.instanceNameWithSuffix} - MessageMode.${mode} is deprecated: producer-side delta calculation loses previous-value state across service restarts. Publish raw cumulative counter values and request delta/rate from Datahub history APIs.`,\r\n );\r\n }\r\n\r\n /**\r\n * Publishes a message to a specified topic.\r\n *\r\n * @param topic - The MQTT topic.\r\n * @param message - The message to publish.\r\n * @returns A promise that resolves when the message is accepted into the worker queue.\r\n */\r\n public publishMessage(topic: string, message: string, options?: IClientPublishOptions): Promise<void> {\r\n return this.enqueueMessageToWorkerQueue(topic, message, options);\r\n }\r\n\r\n /**\r\n * Parses an MQTT packet from a JSON string.\r\n *\r\n * @param mqttPacket - The MQTT packet string.\r\n * @returns A parsed IUnsPacket object or null.\r\n */\r\n public parseMqttPacket(mqttPacket: string): IUnsPacket | null {\r\n return UnsPacket.parseMqttPacket(mqttPacket, this.instanceNameWithSuffix);\r\n }\r\n\r\n /**\r\n * Subscribes asynchronously to one or more topics.\r\n *\r\n * @param topics - A topic or list of topics.\r\n */\r\n public subscribeAsync(topics: string | string[]): void {\r\n this.worker.postMessage({ command: \"subscribeAsync\", topics });\r\n }\r\n\r\n /**\r\n * Unsubscribes asynchronously from the given topics.\r\n *\r\n * @param topics - A list of topics.\r\n */\r\n public unsubscribeAsync(topics: string[]): void {\r\n this.worker.postMessage({ command: \"unsubscribeAsync\", topics });\r\n }\r\n\r\n /**\r\n * Processes and enqueues a message to the worker queue, including handling\r\n * sequencing, value differences, and tracking of unique topics.\r\n *\r\n * @param msg - The MQTT message to process.\r\n * @param time - The timestamp.\r\n * @param valueIsCumulative - Whether the value is cumulative.\r\n */\r\n private async processAndEnqueueMessage(msg: InternalMqttMessage, time: string, valueIsCumulative: boolean = false): Promise<void> {\r\n try {\r\n const attributeType =\r\n msg.packet.message.data ? UnsAttributeType.Data :\r\n msg.packet.message.table ? UnsAttributeType.Table : null;\r\n \r\n let dataGroup = \"\";\r\n if (attributeType == UnsAttributeType.Data)\r\n dataGroup = msg.packet.message.data.dataGroup ?? \"\";\r\n if (attributeType == UnsAttributeType.Table)\r\n dataGroup = msg.packet.message.table.dataGroup ?? \"\";\r\n\r\n const { objectType, objectId, asset } = this.resolveObjectIdentity(msg);\r\n const normalizedTopic = this.normalizeTopicWithObject(msg.topic);\r\n msg.topic = normalizedTopic;\r\n const description = msg.description ?? getAttributeDescription(msg.attribute as string) ?? \"\";\r\n const objectTypeDescription = msg.objectTypeDescription ?? (objectType ? getObjectTypeDescription(objectType) : undefined);\r\n\r\n // Runtime validation for validity fields\r\n if (msg.validityMode) {\r\n const validModes = new Set([\"interval\", \"lifecycle\", \"static\"]);\r\n if (!validModes.has(msg.validityMode)) {\r\n logger.warn(`${this.instanceNameWithSuffix} - Invalid validityMode \"${msg.validityMode}\" for attribute \"${msg.attribute}\". Expected: interval | lifecycle | static.`);\r\n }\r\n if (msg.expectedIntervalMs && msg.validityMode !== \"interval\") {\r\n logger.warn(`${this.instanceNameWithSuffix} - expectedIntervalMs is set but validityMode is \"${msg.validityMode}\" (only used with \"interval\") for attribute \"${msg.attribute}\".`);\r\n }\r\n if (msg.lifecycleEndValue && msg.validityMode !== \"lifecycle\") {\r\n logger.warn(`${this.instanceNameWithSuffix} - lifecycleEndValue is set but validityMode is \"${msg.validityMode}\" (only used with \"lifecycle\") for attribute \"${msg.attribute}\".`);\r\n }\r\n if (msg.validityMode === \"interval\" && !msg.expectedIntervalMs) {\r\n logger.debug(`${this.instanceNameWithSuffix} - validityMode \"interval\" without expectedIntervalMs for attribute \"${msg.attribute}\" — controller will use its default.`);\r\n }\r\n }\r\n\r\n this.registerUniqueTopic({\r\n timestamp: time,\r\n topic: msg.topic,\r\n attribute: msg.attribute,\r\n attributeType: attributeType,\r\n description,\r\n tags: msg.tags,\r\n attributeNeedsPersistence: msg.attributeNeedsPersistence,\r\n valueType: msg.valueType,\r\n presentationKind: msg.presentationKind,\r\n defaultAggregation: msg.defaultAggregation,\r\n counterResetPolicy: msg.counterResetPolicy,\r\n tableColumns: msg.tableColumns,\r\n systemRole: msg.systemRole,\r\n relationshipEvidence: msg.relationshipEvidence,\r\n lifecycle: msg.lifecycle,\r\n dataGroup,\r\n virtualGroup: msg.virtualGroup,\r\n asset,\r\n assetDescription: msg.assetDescription,\r\n objectType,\r\n objectTypeDescription,\r\n objectId,\r\n ...(msg.validityMode ? { validityMode: msg.validityMode } : {}),\r\n ...(msg.expectedIntervalMs ? { expectedIntervalMs: msg.expectedIntervalMs } : {}),\r\n ...(msg.lifecycleEndValue ? { lifecycleEndValue: msg.lifecycleEndValue } : {}),\r\n });\r\n\r\n const publishTopic = `${msg.topic}${asset ? `${asset}/` : \"\"}${objectType ? `${objectType}/` : \"\"}${objectId ? `${objectId}/` : \"\"}${msg.attribute}`;\r\n const sequenceId = this.currentSequenceId.get(msg.topic) ?? 0;\r\n this.currentSequenceId.set(msg.topic, sequenceId + 1);\r\n msg.packet.sequenceId = sequenceId;\r\n\r\n if (msg.packet.message.data) {\r\n const newValue = msg.packet.message.data.value;\r\n const newUom: MeasurementUnit = msg.packet.message.data.uom;\r\n const lastValueEntry = this.lastValues.get(publishTopic);\r\n const currentTime = new Date(msg.packet.message.data.time);\r\n\r\n if (lastValueEntry) {\r\n const intervalBetweenMessages = currentTime.getTime() - lastValueEntry.timestamp.getTime();\r\n const lastValue = lastValueEntry.value;\r\n this.lastValues.set(publishTopic, { value: newValue, uom: newUom, timestamp: currentTime });\r\n // Compute the delta and manage cumulative resets\r\n if (valueIsCumulative == true && typeof newValue === \"number\" && typeof lastValue === \"number\") {\r\n // Skip if newValue is 0 (likely a glitch)\r\n if (newValue === 0) {\r\n return; // Don't process or enqueue\r\n }\r\n const delta = newValue - lastValue;\r\n msg.packet.message.data.value = delta < 0 ? newValue : delta;\r\n }\r\n msg.packet.interval = intervalBetweenMessages;\r\n await this.enqueueMessageToWorkerQueue(publishTopic, JSON.stringify(msg.packet));\r\n } else {\r\n this.lastValues.set(publishTopic, { value: newValue, uom: newUom, timestamp: currentTime });\r\n logger.debug(`${this.instanceNameWithSuffix} - Need one more packet to calculate interval on topic ${publishTopic}`);\r\n if (valueIsCumulative === false) {\r\n await this.enqueueMessageToWorkerQueue(publishTopic, JSON.stringify(msg.packet));\r\n } else {\r\n logger.debug(`${this.instanceNameWithSuffix} - Need one more packet to calculate difference on value in data for topic ${publishTopic}`);\r\n }\r\n }\r\n } else if (msg.packet.message.table) {\r\n await this.enqueueMessageToWorkerQueue(publishTopic, JSON.stringify(msg.packet));\r\n } else {\r\n logger.error(`${this.instanceNameWithSuffix} - Error publishing message to topic ${publishTopic}: packet.message must include data or table`);\r\n }\r\n } catch (error: any) {\r\n logger.error(`${this.instanceNameWithSuffix} - Error publishing message to topic ${msg.topic}${msg.attribute}: ${error.message}`);\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Stops the UnsProxy instance and cleans up resources.\r\n */\r\n public async stop(options: UnsMqttProxyStopOptions = {}): Promise<void> {\n await super.stop();\n const drain = options.drain ?? true;\n const timeoutMs = options.timeoutMs ?? UnsMqttProxy.DEFAULT_DRAIN_TIMEOUT_MS;\n let drainError: Error | null = null;\n\n if (drain) {\n try {\n await this.flush(timeoutMs);\n } catch (error: any) {\n drainError = error instanceof Error ? error : new Error(String(error));\n logger.error(`${this.instanceNameWithSuffix} - Error draining publishes before stop: ${drainError.message}`);\n }\n }\n\n if (this.worker) {\n try {\n const exitCode = await this.worker.terminate();\n logger.info(`${this.instanceNameWithSuffix} - Worker terminated with exit code ${exitCode}`);\n } catch (error: any) {\n logger.error(`${this.instanceNameWithSuffix} - Error terminating worker: ${error.message}`);\n }\n }\n\n this.failPendingPublishes(drainError ?? new Error(\"UnsProxy has been stopped\"));\n\n if (drainError) {\n throw drainError;\n }\n }\n\n private failPendingPublishes(reason: Error): void {\n this.workerFailure = reason;\n for (const pending of this.pendingEnqueues.values()) {\n pending.reject(reason);\n }\n this.pendingEnqueues.clear();\n this.pendingPublishCompletions = 0;\n this.notifyDrainWaiters();\n }\n\n private notifyDrainWaiters(): void {\n if (this.workerFailure) {\n const waiters = this.drainWaiters.splice(0);\n for (const waiter of waiters) {\n if (waiter.timer) {\n clearTimeout(waiter.timer);\n }\n waiter.reject(this.workerFailure);\n }\n return;\n }\n if (this.pendingEnqueues.size !== 0 || this.pendingPublishCompletions !== 0) {\n return;\n }\n const waiters = this.drainWaiters.splice(0);\n for (const waiter of waiters) {\n if (waiter.timer) {\n clearTimeout(waiter.timer);\n }\n waiter.resolve();\n }\n }\n\n private removeDrainWaiter(waiterToRemove: { resolve: () => void; reject: (reason?: any) => void; timer?: NodeJS.Timeout }): void {\n this.drainWaiters = this.drainWaiters.filter((waiter) => waiter !== waiterToRemove);\n }\n\n}\n"]}
|