node-opcua-server 2.91.0 → 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.
@@ -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
- public recordValue(dataValue: DataValue, skipChangeTest: boolean, indexRange?: NumericRange): void {
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
- return;
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
- return; // no overlap !
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
- return this._enqueue_value(dataValue);
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
- return;
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
- return;
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
- return;
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 {