node-opcua-address-space 2.99.0 → 2.100.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.
@@ -12,7 +12,7 @@ import {
12
12
  BindExtensionObjectOptions,
13
13
  CloneExtraInfo,
14
14
  ContinuationData,
15
- defaultCloneExtraInfo,
15
+ makeDefaultCloneExtraInfo,
16
16
  defaultCloneFilter,
17
17
  GetFunc,
18
18
  SetFunc,
@@ -101,8 +101,6 @@ const warningLog = make_warningLog(__filename);
101
101
  const doDebug = checkDebugFlag(__filename);
102
102
  const errorLog = make_errorLog(__filename);
103
103
 
104
-
105
-
106
104
  export function adjust_accessLevel(accessLevel: string | number | null): AccessLevelFlag {
107
105
  accessLevel = utils.isNullOrUndefined(accessLevel) ? "CurrentRead | CurrentWrite" : accessLevel;
108
106
  accessLevel = makeAccessLevelFlag(accessLevel);
@@ -138,8 +136,7 @@ function is_StatusCode(v: any): boolean {
138
136
  return (
139
137
  v &&
140
138
  v.constructor &&
141
- (
142
- v instanceof StatusCode ||
139
+ (v instanceof StatusCode ||
143
140
  v.constructor.name === "ConstantStatusCode" ||
144
141
  v.constructor.name === "StatusCode" ||
145
142
  v.constructor.name === "ModifiableStatusCode")
@@ -165,13 +162,13 @@ function _dataType_toUADataType(addressSpace: IAddressSpace, dataType: DataType)
165
162
  return dataTypeNode as UADataType;
166
163
  }
167
164
  /*=
168
- *
169
- * @param addressSpace
170
- * @param dataTypeNodeId : the nodeId matching the dataType of the destination variable.
171
- * @param variantDataType: the dataType of the variant to write to the destination variable
172
- * @param nodeId
173
- * @return {boolean} true if the variant dataType is compatible with the Variable DataType
174
- */
165
+ *
166
+ * @param addressSpace
167
+ * @param dataTypeNodeId : the nodeId matching the dataType of the destination variable.
168
+ * @param variantDataType: the dataType of the variant to write to the destination variable
169
+ * @param nodeId
170
+ * @return {boolean} true if the variant dataType is compatible with the Variable DataType
171
+ */
175
172
  function validateDataType(
176
173
  addressSpace: IAddressSpace,
177
174
  dataTypeNodeId: NodeId,
@@ -365,18 +362,13 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
365
362
 
366
363
  this.semantic_version = 0;
367
364
  }
368
- private checkAccessLevelPrivate(
369
- _context: ISessionContext,
370
- accessLevel: AccessLevelFlag): boolean {
365
+ private checkAccessLevelPrivate(_context: ISessionContext, accessLevel: AccessLevelFlag): boolean {
371
366
  if (this.userAccessLevel === undefined) {
372
367
  return true;
373
368
  }
374
369
  return (this.userAccessLevel & accessLevel) === accessLevel;
375
370
  }
376
- private checkPermissionPrivate(
377
- context: ISessionContext,
378
- permission: PermissionType,
379
- ): boolean {
371
+ private checkPermissionPrivate(context: ISessionContext, permission: PermissionType): boolean {
380
372
  if (!context) return true;
381
373
  assert(context instanceof SessionContext);
382
374
  if (context.checkPermission) {
@@ -393,7 +385,8 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
393
385
  private checkPermissionAndAccessLevelPrivate(
394
386
  context: ISessionContext,
395
387
  permission: PermissionType,
396
- accessLevel: AccessLevelFlag): boolean {
388
+ accessLevel: AccessLevelFlag
389
+ ): boolean {
397
390
  if (!this.checkPermissionPrivate(context, permission)) {
398
391
  return false;
399
392
  }
@@ -446,7 +439,7 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
446
439
 
447
440
  /**
448
441
  *
449
- *
442
+ *
450
443
  * from OPC.UA.Spec 1.02 part 4
451
444
  * 5.10.2.4 StatusCodes
452
445
  * Table 51 defines values for the operation level statusCode contained in the DataValue structure of
@@ -526,10 +519,10 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
526
519
  ) {
527
520
  debugLog(
528
521
  chalk.red(" Warning: UAVariable#readValue ") +
529
- chalk.cyan(this.browseName.toString()) +
530
- " (" +
531
- chalk.yellow(this.nodeId.toString()) +
532
- ") exists but dataValue has not been defined"
522
+ chalk.cyan(this.browseName.toString()) +
523
+ " (" +
524
+ chalk.yellow(this.nodeId.toString()) +
525
+ ") exists but dataValue has not been defined"
533
526
  );
534
527
  }
535
528
  return dataValue;
@@ -541,7 +534,7 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
541
534
 
542
535
  /**
543
536
  * return true if the DataType is of type Extension object
544
- * this is not taking into account the valueRank of the variable
537
+ * this is not taking into account the valueRank of the variable
545
538
  */
546
539
  public isExtensionObject(): boolean {
547
540
  // DataType must be one of Structure
@@ -564,23 +557,30 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
564
557
  return dataTypeNode._getEnumerationInfo();
565
558
  }
566
559
 
567
- public asyncRefresh(oldestDate: Date, callback: CallbackT<DataValue>): void;
568
- public asyncRefresh(oldestDate: Date): Promise<DataValue>;
560
+ public asyncRefresh(oldestDate: PreciseClock, callback: CallbackT<DataValue>): void;
561
+ public asyncRefresh(oldestDate: PreciseClock): Promise<DataValue>;
569
562
  public asyncRefresh(...args: any[]): any {
570
563
  if (this.$dataValue.statusCode.isGoodish()) {
571
564
  this.verifyVariantCompatibility(this.$dataValue.value);
572
565
  }
573
566
 
574
- const oldestDate = args[0] as Date;
575
- assert(oldestDate instanceof Date);
567
+ const oldestDate = args[0] as PreciseClock;
576
568
  const callback = args[1] as CallbackT<DataValue>;
577
569
 
570
+ const lessOrEqual = (a: PreciseClock, b: PreciseClock) => {
571
+ return (
572
+ a.timestamp.getTime() < b.timestamp.getTime() ||
573
+ (a.timestamp.getTime() === b.timestamp.getTime() && a.picoseconds <= b.picoseconds)
574
+ );
575
+ };
576
+
578
577
  if (!this.refreshFunc) {
579
578
  // no refresh func
580
579
  const dataValue = this.readValue();
581
- dataValue.serverTimestamp = oldestDate;
582
- dataValue.serverPicoseconds = 0;
583
- if (oldestDate.getTime() <= dataValue.serverTimestamp!.getTime()) {
580
+ dataValue.serverTimestamp = oldestDate.timestamp;
581
+ dataValue.serverPicoseconds = oldestDate.picoseconds;
582
+ const serverClock = coerceClock(dataValue.serverTimestamp, dataValue.serverPicoseconds);
583
+ if (lessOrEqual(oldestDate, serverClock)) {
584
584
  return callback(null, dataValue);
585
585
  } else {
586
586
  // fake
@@ -588,10 +588,14 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
588
588
  }
589
589
  }
590
590
 
591
- if (this.$dataValue.serverTimestamp && oldestDate.getTime() <= this.$dataValue.serverTimestamp!.getTime()) {
591
+ const c1 = this.$dataValue.serverTimestamp
592
+ ? coerceClock(this.$dataValue.serverTimestamp, this.$dataValue.serverPicoseconds)
593
+ : null;
594
+
595
+ if (this.$dataValue.serverTimestamp && lessOrEqual(oldestDate, c1!)) {
592
596
  const dataValue = this.readValue().clone();
593
- dataValue.serverTimestamp = oldestDate;
594
- dataValue.serverPicoseconds = 0;
597
+ dataValue.serverTimestamp = oldestDate.timestamp;
598
+ dataValue.serverPicoseconds = oldestDate.picoseconds;
595
599
  return callback(null, dataValue);
596
600
  }
597
601
  try {
@@ -736,9 +740,9 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
736
740
  if (variant.dataType === null || variant.dataType === undefined) {
737
741
  throw new Error(
738
742
  "Variant must provide a valid dataType : variant = " +
739
- variant.toString() +
740
- " this.dataType= " +
741
- this.dataType.toString()
743
+ variant.toString() +
744
+ " this.dataType= " +
745
+ this.dataType.toString()
742
746
  );
743
747
  }
744
748
  if (
@@ -747,9 +751,9 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
747
751
  ) {
748
752
  throw new Error(
749
753
  "Variant must provide a valid Boolean : variant = " +
750
- variant.toString() +
751
- " this.dataType= " +
752
- this.dataType.toString()
754
+ variant.toString() +
755
+ " this.dataType= " +
756
+ this.dataType.toString()
753
757
  );
754
758
  }
755
759
  if (
@@ -760,9 +764,9 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
760
764
  ) {
761
765
  throw new Error(
762
766
  "Variant must provide a valid LocalizedText : variant = " +
763
- variant.toString() +
764
- " this.dataType= " +
765
- this.dataType.toString()
767
+ variant.toString() +
768
+ " this.dataType= " +
769
+ this.dataType.toString()
766
770
  );
767
771
  }
768
772
  }
@@ -922,7 +926,6 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
922
926
  return new DataValue({ statusCode: StatusCodes.BadUserAccessDenied });
923
927
  }
924
928
 
925
-
926
929
  if (!this.isUserWritable(context)) {
927
930
  return callback!(null, StatusCodes.BadWriteNotSupported);
928
931
  }
@@ -1259,7 +1262,6 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
1259
1262
  public readValueAsync(context: ISessionContext | null, callback: CallbackT<DataValue>): void;
1260
1263
  public readValueAsync(context: ISessionContext | null): Promise<DataValue>;
1261
1264
  public readValueAsync(context: ISessionContext | null, callback?: CallbackT<DataValue>): any {
1262
-
1263
1265
  assert(typeof callback === "function");
1264
1266
 
1265
1267
  context = context || SessionContext.defaultContext;
@@ -1272,7 +1274,9 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
1272
1274
  return;
1273
1275
  }
1274
1276
 
1275
- if (this.isDisposed()) { return callback!(null, new DataValue({ statusCode: StatusCodes.BadNodeIdUnknown })); }
1277
+ if (this.isDisposed()) {
1278
+ return callback!(null, new DataValue({ statusCode: StatusCodes.BadNodeIdUnknown }));
1279
+ }
1276
1280
 
1277
1281
  const readImmediate = (innerCallback: (err: Error | null, dataValue: DataValue) => void) => {
1278
1282
  assert(this.$dataValue instanceof DataValue);
@@ -1298,7 +1302,8 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
1298
1302
  innerCallback(null, dataValue);
1299
1303
  };
1300
1304
  } else {
1301
- func = typeof this.refreshFunc === "function" ? this.asyncRefresh.bind(this, new Date()) : readImmediate;
1305
+ const clock = getCurrentClock();
1306
+ func = typeof this.refreshFunc === "function" ? this.asyncRefresh.bind(this, clock) : readImmediate;
1302
1307
  }
1303
1308
 
1304
1309
  const satisfy_callbacks = (err: Error | null, dataValue?: DataValue) => {
@@ -1308,7 +1313,6 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
1308
1313
  const n = callbacks.length;
1309
1314
  for (const callback1 of callbacks) {
1310
1315
  callback1.call(this, err, dataValue);
1311
-
1312
1316
  }
1313
1317
  };
1314
1318
 
@@ -1349,12 +1353,12 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
1349
1353
  valueRank: this.valueRank
1350
1354
  };
1351
1355
 
1352
- const newVariable = _clone.call(
1356
+ const newVariable = _clone(
1353
1357
  this,
1354
1358
  UAVariableImpl,
1355
1359
  options,
1356
1360
  optionalFilter || defaultCloneFilter,
1357
- extraInfo || defaultCloneExtraInfo
1361
+ extraInfo || makeDefaultCloneExtraInfo()
1358
1362
  ) as UAVariableImpl;
1359
1363
 
1360
1364
  newVariable.bindVariable();
@@ -1513,10 +1517,16 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
1513
1517
  optionalExtensionObject?: ExtensionObject | ExtensionObject[],
1514
1518
  options?: BindExtensionObjectOptions
1515
1519
  ): ExtensionObject | ExtensionObject[] | null {
1516
-
1517
1520
  // coerce to ExtensionObject[] when this.valueRank === 1
1518
- if (optionalExtensionObject && this.valueRank === 1 && !Array.isArray(optionalExtensionObject) && optionalExtensionObject instanceof ExtensionObject) {
1519
- warningLog("bindExtensionObject: coerce to ExtensionObject[] when valueRank === 1 and value is a scalar extension object");
1521
+ if (
1522
+ optionalExtensionObject &&
1523
+ this.valueRank === 1 &&
1524
+ !Array.isArray(optionalExtensionObject) &&
1525
+ optionalExtensionObject instanceof ExtensionObject
1526
+ ) {
1527
+ warningLog(
1528
+ "bindExtensionObject: coerce to ExtensionObject[] when valueRank === 1 and value is a scalar extension object"
1529
+ );
1520
1530
  optionalExtensionObject = [optionalExtensionObject];
1521
1531
  }
1522
1532
 
@@ -1539,7 +1549,7 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
1539
1549
  } else if (this.valueRank > 1) {
1540
1550
  return _bindExtensionObjectArrayOrMatrix(this, undefined, options);
1541
1551
  }
1542
- // unsupported case ...
1552
+ // unsupported case ...
1543
1553
  return null;
1544
1554
  }
1545
1555
 
@@ -1648,7 +1658,6 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
1648
1658
  continuationData: ContinuationData,
1649
1659
  callback: CallbackT<HistoryReadResult>
1650
1660
  ): void {
1651
-
1652
1661
  if (!this.checkPermissionPrivate(context, PermissionType.ReadHistory)) {
1653
1662
  const result = new HistoryReadResult({
1654
1663
  statusCode: StatusCodes.BadUserAccessDenied
@@ -1733,7 +1742,8 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
1733
1742
  const nbElements = dataValue.value.dimensions.reduce((acc, x) => acc * x, 1);
1734
1743
  if (dataValue.value.value.length !== 0 && dataValue.value.value.length !== nbElements) {
1735
1744
  throw new Error(
1736
- `Internal Error: matrix dimension doesn't match the number of element in the array : ${dataValue.toString()} "\n expecting ${nbElements} elements but got ${dataValue.value.value.length
1745
+ `Internal Error: matrix dimension doesn't match the number of element in the array : ${dataValue.toString()} "\n expecting ${nbElements} elements but got ${
1746
+ dataValue.value.value.length
1737
1747
  }`
1738
1748
  );
1739
1749
  }
@@ -1757,7 +1767,6 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
1757
1767
  * @private
1758
1768
  */
1759
1769
  public _inner_replace_dataValue(dataValue: DataValue, indexRange?: NumericRange | null) {
1760
-
1761
1770
  assert(this.$dataValue.value instanceof Variant);
1762
1771
  const old_dataValue = this.$dataValue.clone();
1763
1772
 
@@ -1775,12 +1784,16 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
1775
1784
  this.$dataValue.serverPicoseconds = dataValue.serverPicoseconds;
1776
1785
  this.$dataValue.sourceTimestamp = dataValue.sourceTimestamp;
1777
1786
  this.$dataValue.sourcePicoseconds = dataValue.sourcePicoseconds;
1778
-
1779
- } else if (this._basicDataType === DataType.ExtensionObject && this.valueRank === -1 && this.$set_ExtensionObject && dataValue.value.arrayType === VariantArrayType.Scalar) {
1780
- // the entire extension object is changed.
1787
+ } else if (
1788
+ this._basicDataType === DataType.ExtensionObject &&
1789
+ this.valueRank === -1 &&
1790
+ this.$set_ExtensionObject &&
1791
+ dataValue.value.arrayType === VariantArrayType.Scalar
1792
+ ) {
1793
+ // the entire extension object is changed.
1781
1794
  this.$dataValue.statusCode = this.$dataValue.statusCode || StatusCodes.Good;
1782
1795
  const preciseClock = coerceClock(this.$dataValue.sourceTimestamp, this.$dataValue.sourcePicoseconds);
1783
- this.$set_ExtensionObject(dataValue.value.value, preciseClock, new Set())
1796
+ this.$set_ExtensionObject(dataValue.value.value, preciseClock, new Set());
1784
1797
  } else {
1785
1798
  this.$dataValue = dataValue;
1786
1799
  this.$dataValue.statusCode = this.$dataValue.statusCode || StatusCodes.Good;
@@ -1924,8 +1937,7 @@ export interface UAVariableImplExtArray {
1924
1937
  $$extensionObjectArray: ExtensionObject[];
1925
1938
  $$indexPropertyName: string;
1926
1939
  }
1927
- export interface UAVariableImpl extends UAVariableImplExtArray {
1928
- }
1940
+ export interface UAVariableImpl extends UAVariableImplExtArray {}
1929
1941
  function check_valid_array(dataType: DataType, array: any): boolean {
1930
1942
  if (Array.isArray(array)) {
1931
1943
  return true;
@@ -2110,7 +2122,7 @@ function _Variable_bind_with_timestamped_get(
2110
2122
  errorLog(
2111
2123
  chalk.red(" Bind variable error: "),
2112
2124
  " the timestamped_get function must return a DataValue or a Promise<DataValue>" +
2113
- "\n value_check.constructor.name ",
2125
+ "\n value_check.constructor.name ",
2114
2126
  dataValue_verify ? dataValue_verify.constructor.name : "null"
2115
2127
  );
2116
2128
 
@@ -2154,7 +2166,11 @@ function _Variable_bind_with_simple_get(this: UAVariableImpl, options: GetterOpt
2154
2166
  if (is_StatusCode(value)) {
2155
2167
  return new DataValue({ statusCode: value as StatusCode });
2156
2168
  } else {
2157
- if (!this.$dataValue || !this.$dataValue.statusCode.isGoodish() || !sameVariant(this.$dataValue.value, value as Variant)) {
2169
+ if (
2170
+ !this.$dataValue ||
2171
+ !this.$dataValue.statusCode.isGoodish() ||
2172
+ !sameVariant(this.$dataValue.value, value as Variant)
2173
+ ) {
2158
2174
  this._inner_replace_dataValue(new DataValue({ value }));
2159
2175
  }
2160
2176
  return this.$dataValue;
@@ -2304,4 +2320,4 @@ export interface UAVariableImplT<T, DT extends DataType> extends UAVariableImpl,
2304
2320
  writeValue(context: ISessionContext, dataValue: DataValueT<T, DT>, callback: StatusCodeCallback): void;
2305
2321
  writeValue(context: ISessionContext, dataValue: DataValueT<T, DT>, indexRange?: NumericRange | null): Promise<StatusCode>;
2306
2322
  }
2307
- export class UAVariableImplT<T, DT extends DataType> extends UAVariableImpl { }
2323
+ export class UAVariableImplT<T, DT extends DataType> extends UAVariableImpl {}