node-opcua-server 2.91.1 → 2.92.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/base_server.js +6 -6
- package/dist/base_server.js.map +1 -1
- package/dist/monitored_item.d.ts +9 -3
- package/dist/monitored_item.js +66 -17
- package/dist/monitored_item.js.map +1 -1
- package/dist/opcua_server.d.ts +1 -1
- package/dist/opcua_server.js +86 -86
- package/dist/opcua_server.js.map +1 -1
- package/dist/sampling_func.d.ts +1 -1
- package/dist/server_capabilities.d.ts +1 -1
- package/dist/server_engine.d.ts +3 -3
- package/dist/server_publish_engine.js +22 -22
- package/dist/server_publish_engine.js.map +1 -1
- package/dist/server_session.d.ts +1 -1
- package/dist/server_subscription.d.ts +4 -4
- package/dist/server_subscription.js +24 -24
- package/dist/server_subscription.js.map +1 -1
- package/dist/user_manager.d.ts +3 -3
- package/package.json +33 -33
- package/source/monitored_item.ts +63 -14
package/source/monitored_item.ts
CHANGED
|
@@ -50,7 +50,7 @@ import {
|
|
|
50
50
|
SimpleAttributeOperand,
|
|
51
51
|
SubscriptionDiagnosticsDataType
|
|
52
52
|
} from "node-opcua-types";
|
|
53
|
-
import { sameVariant, Variant } from "node-opcua-variant";
|
|
53
|
+
import { sameVariant, Variant, VariantArrayType } from "node-opcua-variant";
|
|
54
54
|
|
|
55
55
|
import { appendToTimer, removeFromTimer } from "./node_sampler";
|
|
56
56
|
import { validateFilter } from "./validate_filter";
|
|
@@ -250,10 +250,26 @@ function apply_dataChange_filter(this: MonitoredItem, newDataValue: DataValue, o
|
|
|
250
250
|
}
|
|
251
251
|
}
|
|
252
252
|
|
|
253
|
+
function safeGuardRegiter(monitoredItem: any) {
|
|
254
|
+
(monitoredItem as any)._$safeGuard = monitoredItem.oldDataValue.toString();
|
|
255
|
+
}
|
|
256
|
+
function safeGuardVerify(monitoredItem: MonitoredItem) {
|
|
257
|
+
if ((monitoredItem as any)._$safeGuard) {
|
|
258
|
+
const verif = monitoredItem.oldDataValue?.toString() || "";
|
|
259
|
+
if (verif !== (monitoredItem as any)._$safeGuard) {
|
|
260
|
+
console.log(verif, (monitoredItem as any)._$safeGuard);
|
|
261
|
+
throw new Error("Internal error: DataValue has been altereed !!!");
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
253
265
|
function apply_filter(this: MonitoredItem, newDataValue: DataValue) {
|
|
254
266
|
if (!this.oldDataValue) {
|
|
255
267
|
return true; // keep
|
|
256
268
|
}
|
|
269
|
+
|
|
270
|
+
// istanbul ignore next
|
|
271
|
+
doDebug && safeGuardVerify(this);
|
|
272
|
+
|
|
257
273
|
if (this.filter instanceof DataChangeFilter) {
|
|
258
274
|
return apply_dataChange_filter.call(this, newDataValue, this.oldDataValue);
|
|
259
275
|
} else {
|
|
@@ -547,12 +563,21 @@ export class MonitoredItem extends EventEmitter {
|
|
|
547
563
|
* therefore recordValue must clone the dataValue to make sure it retains a snapshot
|
|
548
564
|
* of the contain at the time recordValue was called.
|
|
549
565
|
*
|
|
566
|
+
* return true if the value has been recorded, false if not.
|
|
567
|
+
*
|
|
568
|
+
* Value will not be recorded :
|
|
569
|
+
* * if the range do not overlap
|
|
570
|
+
* * is !skipChangeTest and value is equal to previous value
|
|
571
|
+
*
|
|
550
572
|
*/
|
|
551
|
-
|
|
573
|
+
// eslint-disable-next-line complexity, max-statements
|
|
574
|
+
public recordValue(dataValue: DataValue, skipChangeTest: boolean, indexRange?: NumericRange): boolean {
|
|
552
575
|
|
|
553
576
|
if (!this.itemToMonitor) {
|
|
554
577
|
// we must have a valid itemToMonitor(have this monitoredItem been disposed already ?)
|
|
555
|
-
|
|
578
|
+
// istanbul ignore next
|
|
579
|
+
doDebug && debugLog("recordValue => Rejected", this.node?.browseName.toString(), " because no itemToMonitor");
|
|
580
|
+
return false;
|
|
556
581
|
}
|
|
557
582
|
|
|
558
583
|
assert(dataValue !== this.oldDataValue, "recordValue expects different dataValue to be provided");
|
|
@@ -576,7 +601,9 @@ export class MonitoredItem extends EventEmitter {
|
|
|
576
601
|
// we just ignore changes that do not fall within our range
|
|
577
602
|
// ( unless semantic bit has changed )
|
|
578
603
|
if (!NumericRange.overlap(indexRange as NumericalRange0, this.itemToMonitor.indexRange)) {
|
|
579
|
-
|
|
604
|
+
// istanbul ignore next
|
|
605
|
+
doDebug && debugLog("recordValue => Rejected", this.node?.browseName.toString(), " because no range not overlap");
|
|
606
|
+
return false; // no overlap !
|
|
580
607
|
}
|
|
581
608
|
}
|
|
582
609
|
|
|
@@ -603,7 +630,10 @@ export class MonitoredItem extends EventEmitter {
|
|
|
603
630
|
debugLog("_enqueue_value => because hasSemanticChanged");
|
|
604
631
|
setSemanticChangeBit(dataValue);
|
|
605
632
|
this._semantic_version = (this.node as UAVariable).semantic_version;
|
|
606
|
-
|
|
633
|
+
this._enqueue_value(dataValue);
|
|
634
|
+
// istanbul ignore next
|
|
635
|
+
doDebug && debugLog("recordValue => OK ", this.node?.browseName.toString(), " because hasSemanticChanged");
|
|
636
|
+
return true;
|
|
607
637
|
}
|
|
608
638
|
|
|
609
639
|
const useIndexRange = this.itemToMonitor.indexRange && !this.itemToMonitor.indexRange.isEmpty();
|
|
@@ -611,12 +641,21 @@ export class MonitoredItem extends EventEmitter {
|
|
|
611
641
|
if (!skipChangeTest) {
|
|
612
642
|
const hasChanged = !sameDataValue(dataValue, this.oldDataValue!);
|
|
613
643
|
if (!hasChanged) {
|
|
614
|
-
|
|
644
|
+
// istanbul ignore next
|
|
645
|
+
doDebug && debugLog("recordValue => Rejected ", this.node?.browseName.toString(), " because !skipChangeTest && sameDataValue");
|
|
646
|
+
return false;
|
|
615
647
|
}
|
|
616
648
|
}
|
|
617
649
|
|
|
618
650
|
if (!apply_filter.call(this, dataValue)) {
|
|
619
|
-
|
|
651
|
+
// istanbul ignore next
|
|
652
|
+
if (doDebug) {
|
|
653
|
+
debugLog("recordValue => Rejected ", this.node?.browseName.toString(), " because apply_filter");
|
|
654
|
+
debugLog("current Value =>", this.oldDataValue?.toString());
|
|
655
|
+
debugLog("propoped Value =>", dataValue?.toString());
|
|
656
|
+
debugLog("propoped Value =>", dataValue == this.oldDataValue, dataValue.value === this.oldDataValue?.value);
|
|
657
|
+
}
|
|
658
|
+
return false;
|
|
620
659
|
}
|
|
621
660
|
|
|
622
661
|
if (useIndexRange) {
|
|
@@ -631,18 +670,20 @@ export class MonitoredItem extends EventEmitter {
|
|
|
631
670
|
}
|
|
632
671
|
|
|
633
672
|
if (sameVariant(dataValue.value, this.oldDataValue!.value)) {
|
|
634
|
-
|
|
673
|
+
// istanbul ignore next
|
|
674
|
+
doDebug && debugLog("recordValue => Rejected ", this.node?.browseName.toString(), " because useIndexRange && sameVariant");
|
|
675
|
+
return false;
|
|
635
676
|
}
|
|
636
677
|
}
|
|
637
678
|
|
|
638
679
|
// processTriggerItems
|
|
639
680
|
this.triggerLinkedItems();
|
|
640
681
|
|
|
641
|
-
if (doDebug) {
|
|
642
|
-
debugLog("RECORD VALUE ", this.node?.nodeId.toString());
|
|
643
|
-
}
|
|
644
682
|
// store last value
|
|
645
683
|
this._enqueue_value(dataValue);
|
|
684
|
+
// istanbul ignore next
|
|
685
|
+
doDebug && debugLog("recordValue => OK ", this.node?.browseName.toString());
|
|
686
|
+
return true;
|
|
646
687
|
}
|
|
647
688
|
|
|
648
689
|
public hasLinkItem(linkedMonitoredItemId: number): boolean {
|
|
@@ -995,6 +1036,8 @@ export class MonitoredItem extends EventEmitter {
|
|
|
995
1036
|
} else {
|
|
996
1037
|
const o = this.oldDataValue;
|
|
997
1038
|
this.oldDataValue = new DataValue({ statusCode: StatusCodes.BadDataUnavailable });
|
|
1039
|
+
// istanbul ignore next
|
|
1040
|
+
if (doDebug) { safeGuardRegiter(this); }
|
|
998
1041
|
callback(null, o);
|
|
999
1042
|
}
|
|
1000
1043
|
|
|
@@ -1058,18 +1101,18 @@ export class MonitoredItem extends EventEmitter {
|
|
|
1058
1101
|
// initiate first read
|
|
1059
1102
|
if (recordInitialValue) {
|
|
1060
1103
|
this.__acquireInitialValue(sessionContext, (err: Error | null, dataValue?: DataValue) => {
|
|
1061
|
-
if(err) {
|
|
1104
|
+
if (err) {
|
|
1062
1105
|
warningLog(err.message);
|
|
1063
1106
|
}
|
|
1064
1107
|
if (!err && dataValue) {
|
|
1065
|
-
this.recordValue(dataValue, true);
|
|
1108
|
+
this.recordValue(dataValue.clone(), true);
|
|
1066
1109
|
}
|
|
1067
1110
|
});
|
|
1068
1111
|
}
|
|
1069
1112
|
} else {
|
|
1070
1113
|
if (recordInitialValue) {
|
|
1071
1114
|
this.__acquireInitialValue(sessionContext, (err: Error | null, dataValue?: DataValue) => {
|
|
1072
|
-
if(err) {
|
|
1115
|
+
if (err) {
|
|
1073
1116
|
warningLog(err.message);
|
|
1074
1117
|
}
|
|
1075
1118
|
if (!err && dataValue) {
|
|
@@ -1239,10 +1282,16 @@ export class MonitoredItem extends EventEmitter {
|
|
|
1239
1282
|
// istanbul ignore next
|
|
1240
1283
|
if (doDebug) {
|
|
1241
1284
|
debugLog("MonitoredItem#_enqueue_value", this.node!.nodeId.toString());
|
|
1285
|
+
safeGuardVerify(this);
|
|
1242
1286
|
}
|
|
1243
1287
|
this.oldDataValue = dataValue;
|
|
1288
|
+
|
|
1289
|
+
// istanbul ignore next
|
|
1290
|
+
if (doDebug) { safeGuardRegiter(this); }
|
|
1291
|
+
|
|
1244
1292
|
const notification = this._makeDataChangeNotification(dataValue);
|
|
1245
1293
|
this._enqueue_notification(notification);
|
|
1294
|
+
|
|
1246
1295
|
}
|
|
1247
1296
|
|
|
1248
1297
|
private _makeEventFieldList(eventFields: any[]): EventFieldList {
|