node-opcua-address-space 2.60.0 → 2.62.2

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.
Files changed (41) hide show
  1. package/dist/source/helpers/multiform_func.d.ts +11 -0
  2. package/dist/source/helpers/multiform_func.js +74 -0
  3. package/dist/source/helpers/multiform_func.js.map +1 -0
  4. package/dist/src/address_space.js +4 -1
  5. package/dist/src/address_space.js.map +1 -1
  6. package/dist/src/alarms_and_conditions/ua_limit_alarm_impl.d.ts +0 -1
  7. package/dist/src/alarms_and_conditions/ua_limit_alarm_impl.js +23 -5
  8. package/dist/src/alarms_and_conditions/ua_limit_alarm_impl.js.map +1 -1
  9. package/dist/src/base_node_impl.js +2 -0
  10. package/dist/src/base_node_impl.js.map +1 -1
  11. package/dist/src/base_node_private.d.ts +3 -3
  12. package/dist/src/base_node_private.js +196 -23
  13. package/dist/src/base_node_private.js.map +1 -1
  14. package/dist/src/ua_method_impl.js +2 -1
  15. package/dist/src/ua_method_impl.js.map +1 -1
  16. package/dist/src/ua_object_impl.js +2 -1
  17. package/dist/src/ua_object_impl.js.map +1 -1
  18. package/dist/src/ua_object_type_impl.js +1 -0
  19. package/dist/src/ua_object_type_impl.js.map +1 -1
  20. package/dist/src/ua_variable_impl.d.ts +6 -12
  21. package/dist/src/ua_variable_impl.js +61 -37
  22. package/dist/src/ua_variable_impl.js.map +1 -1
  23. package/dist/src/ua_variable_type_impl.js +48 -34
  24. package/dist/src/ua_variable_type_impl.js.map +1 -1
  25. package/dist/src/ua_view_impl.js +1 -1
  26. package/dist/src/ua_view_impl.js.map +1 -1
  27. package/package.json +30 -30
  28. package/source/helpers/multiform_func.ts +76 -0
  29. package/src/address_space.ts +11 -8
  30. package/src/alarms_and_conditions/ua_limit_alarm_impl.ts +29 -9
  31. package/src/base_node_impl.ts +3 -1
  32. package/src/base_node_private.ts +276 -34
  33. package/src/ua_method_impl.ts +10 -2
  34. package/src/ua_object_impl.ts +10 -2
  35. package/src/ua_object_type_impl.ts +1 -0
  36. package/src/ua_variable_impl.ts +156 -132
  37. package/src/ua_variable_type_impl.ts +80 -39
  38. package/src/ua_view_impl.ts +1 -1
  39. package/test_helpers/test_fixtures/fixture_simple_statemachine_nodeset2.xml +9 -0
  40. package/test_helpers/test_fixtures/fixuture_nodeset_objects_with_some_methods.xml +9 -1
  41. package/test_helpers/test_fixtures/mini.Node.Set2.xml +8 -1
@@ -8,7 +8,19 @@
8
8
  // tslint:disable:max-line-length
9
9
  import * as chalk from "chalk";
10
10
 
11
- import { ContinuationData, GetFunc, SetFunc } from "node-opcua-address-space-base";
11
+ import {
12
+ CloneExtraInfo,
13
+ ContinuationData,
14
+ defaultCloneExtraInfo,
15
+ defaultCloneFilter,
16
+ GetFunc,
17
+ SetFunc,
18
+ VariableDataValueGetterCallback,
19
+ VariableDataValueGetterPromise,
20
+ VariableDataValueGetterSync,
21
+ VariableDataValueSetterWithCallback,
22
+ VariableDataValueSetterWithPromise
23
+ } from "node-opcua-address-space-base";
12
24
  import { assert } from "node-opcua-assert";
13
25
  import {
14
26
  isValidDataEncoding,
@@ -56,7 +68,6 @@ import {
56
68
  IAddressSpace,
57
69
  BindVariableOptions,
58
70
  ContinuationPoint,
59
- DataValueCallback,
60
71
  IVariableHistorian,
61
72
  TimestampGetFunc,
62
73
  TimestampSetFunc,
@@ -65,7 +76,6 @@ import {
65
76
  UAVariableType,
66
77
  CloneOptions,
67
78
  CloneFilter,
68
- CloneExtraInfo,
69
79
  ISessionContext,
70
80
  BaseNode,
71
81
  UAVariableT
@@ -73,6 +83,7 @@ import {
73
83
  import { UAHistoricalDataConfiguration } from "node-opcua-nodeset-ua";
74
84
 
75
85
  import { SessionContext } from "../source/session_context";
86
+ import { convertToCallbackFunction1 } from "../source/helpers/multiform_func";
76
87
  import { BaseNodeImpl, InternalBaseNodeOptions } from "./base_node_impl";
77
88
  import { _clone, ToStringBuilder, UAVariable_toString, valueRankToString } from "./base_node_private";
78
89
  import { EnumerationInfo, IEnumItem, UADataTypeImpl } from "./ua_data_type_impl";
@@ -225,6 +236,10 @@ function validateDataType(
225
236
  return dest_isSuperTypeOf_variant;
226
237
  }
227
238
 
239
+ function default_func(this: UAVariable, dataValue1: DataValue, callback1: CallbackT<StatusCode>) {
240
+ return _default_writable_timestamped_set_func.call(this, dataValue1, callback1);
241
+ }
242
+
228
243
  interface UAVariableOptions extends InternalBaseNodeOptions {
229
244
  value?: any;
230
245
  dataType: NodeId | string;
@@ -236,19 +251,6 @@ interface UAVariableOptions extends InternalBaseNodeOptions {
236
251
  historizing?: number;
237
252
  }
238
253
 
239
- type TimestampGetFunction1 = () => DataValue | Promise<DataValue>;
240
- type TimestampGetFunction2 = (callback: (err: Error | null, dataValue?: DataValue) => void) => void;
241
- type TimestampGetFunction = TimestampGetFunction1 | TimestampGetFunction2;
242
-
243
- type TimestampSetFunction1 = (this: UAVariable, dataValue: DataValue, indexRange: NumericRange) => void | Promise<void>;
244
- type TimestampSetFunction2 = (
245
- this: UAVariable,
246
- dataValue: DataValue,
247
- indexRange: NumericRange,
248
- callback: (err: Error | null, StatusCode: StatusCode) => void
249
- ) => void;
250
- type TimestampSetFunction = TimestampSetFunction1 | TimestampSetFunction2;
251
-
252
254
  /**
253
255
  * A OPCUA Variable Node
254
256
  *
@@ -298,11 +300,11 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
298
300
  public semantic_version: number;
299
301
  public arrayDimensions: null | number[];
300
302
 
301
- public _timestamped_get_func?: TimestampGetFunction | null;
302
- public _timestamped_set_func?: TimestampSetFunction | null;
303
+ public _timestamped_get_func?: TimestampGetFunc | null;
304
+ public _timestamped_set_func?: VariableDataValueSetterWithCallback | null;
303
305
  public _get_func: any;
304
306
  public _set_func: any;
305
- public refreshFunc?: (callback: DataValueCallback) => void;
307
+ public refreshFunc?: (callback: CallbackT<DataValue>) => void;
306
308
  public __waiting_callbacks?: any[];
307
309
 
308
310
  get typeDefinitionObj(): UAVariableType {
@@ -431,8 +433,13 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
431
433
 
432
434
  if (this._timestamped_get_func) {
433
435
  if (this._timestamped_get_func.length === 0) {
434
- this.$dataValue = (this._timestamped_get_func as TimestampGetFunction1)() as DataValue;
435
- this.verifyVariantCompatibility(this.$dataValue.value);
436
+ const dataValueOrPromise = (this._timestamped_get_func as VariableDataValueGetterSync)();
437
+ if (!Object.prototype.hasOwnProperty.call(dataValueOrPromise, "then")) {
438
+ this.$dataValue = dataValueOrPromise as DataValue;
439
+ this.verifyVariantCompatibility(this.$dataValue.value);
440
+ } else {
441
+ errorLog("Unsupported: _timestamped_get_func returns a Promise !");
442
+ }
436
443
  }
437
444
  }
438
445
 
@@ -483,14 +490,16 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
483
490
  return dataTypeNode._getEnumerationInfo();
484
491
  }
485
492
 
486
- public asyncRefresh(oldestDate: Date, callback: DataValueCallback): void;
493
+ public asyncRefresh(oldestDate: Date, callback: CallbackT<DataValue>): void;
487
494
  public asyncRefresh(oldestDate: Date): Promise<DataValue>;
488
495
  public asyncRefresh(...args: any[]): any {
489
- this.verifyVariantCompatibility(this.$dataValue.value);
496
+ if (isGoodish(this.$dataValue.statusCode)) {
497
+ this.verifyVariantCompatibility(this.$dataValue.value);
498
+ }
490
499
 
491
500
  const oldestDate = args[0] as Date;
492
501
  assert(oldestDate instanceof Date);
493
- const callback = args[1] as DataValueCallback;
502
+ const callback = args[1] as CallbackT<DataValue>;
494
503
 
495
504
  if (!this.refreshFunc) {
496
505
  // no refresh func
@@ -511,7 +520,7 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
511
520
  dataValue.serverPicoseconds = 0;
512
521
  return callback(null, dataValue);
513
522
  }
514
-
523
+
515
524
  try {
516
525
  this.refreshFunc.call(this, (err: Error | null, dataValue?: DataValueLike) => {
517
526
  if (err || !dataValue) {
@@ -646,20 +655,35 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
646
655
  // istanbul ignore next
647
656
  if (Object.prototype.hasOwnProperty.call(variant, "value")) {
648
657
  if (variant.dataType === null || variant.dataType === undefined) {
649
- throw new Error("Variant must provide a valid dataType" + variant.toString());
658
+ throw new Error(
659
+ "Variant must provide a valid dataType : variant = " +
660
+ variant.toString() +
661
+ " this.dataType= " +
662
+ this.dataType.toString()
663
+ );
650
664
  }
651
665
  if (
652
666
  variant.dataType === DataType.Boolean &&
653
667
  (this.dataType.namespace !== 0 || this.dataType.value !== DataType.Boolean)
654
668
  ) {
655
- throw new Error("Variant must provide a valid Boolean" + variant.toString());
669
+ throw new Error(
670
+ "Variant must provide a valid Boolean : variant = " +
671
+ variant.toString() +
672
+ " this.dataType= " +
673
+ this.dataType.toString()
674
+ );
656
675
  }
657
676
  if (
658
677
  this.dataType.namespace === 0 &&
659
678
  this.dataType.value === DataType.LocalizedText &&
660
679
  variant.dataType !== DataType.LocalizedText
661
680
  ) {
662
- throw new Error("Variant must provide a valid LocalizedText" + variant.toString());
681
+ throw new Error(
682
+ "Variant must provide a valid LocalizedText : variant = " +
683
+ variant.toString() +
684
+ " this.dataType= " +
685
+ this.dataType.toString()
686
+ );
663
687
  }
664
688
  }
665
689
  const basicType = this.getBasicDataType();
@@ -689,7 +713,7 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
689
713
  throw new Error(message);
690
714
  }
691
715
  } catch (err) {
692
- errorLog("UAVariable ", (err as Error)?.message, this.browseName.toString(), this.nodeId.toString());
716
+ errorLog("UAVariable ", (err as Error)?.message, this.browseName.toString(), " nodeId=", this.nodeId.toString());
693
717
  errorLog((err as Error).message);
694
718
  errorLog((err as Error).stack);
695
719
  throw err;
@@ -723,6 +747,8 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
723
747
  this._internal_set_dataValue(dataValue);
724
748
  } catch (err) {
725
749
  errorLog("UAVariable#setValueFromString Error : ", this.browseName.toString(), this.nodeId.toString());
750
+ errorLog((err as Error).message);
751
+ errorLog(this.parent?.toString());
726
752
  throw err;
727
753
  }
728
754
  }
@@ -795,16 +821,7 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
795
821
  return callback!(null, statusCode);
796
822
  }
797
823
 
798
- function default_func(
799
- this: UAVariable,
800
- dataValue1: DataValue,
801
- indexRange1: NumericRange,
802
- callback1: (err: Error | null, statusCode: StatusCode, dataValue?: DataValue | null | undefined) => void
803
- ) {
804
- // xx assert(!indexRange,"indexRange Not Implemented");
805
- return _default_writable_timestamped_set_func.call(this, dataValue1, callback1);
806
- }
807
- const write_func = (this._timestamped_set_func || default_func) as any;
824
+ const write_func = this._timestamped_set_func || default_func;
808
825
 
809
826
  if (!write_func) {
810
827
  warningLog(" warning " + this.nodeId.toString() + " " + this.browseName.toString() + " has no setter. \n");
@@ -813,78 +830,70 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
813
830
  }
814
831
  assert(write_func);
815
832
 
816
- write_func.call(
817
- this,
818
- dataValue,
819
- indexRange,
820
- (err: Error | null, statusCode1?: StatusCode, correctedDataValue?: DataValue) => {
821
- if (!err) {
822
- correctedDataValue = correctedDataValue || dataValue;
823
- assert(correctedDataValue instanceof DataValue);
824
- correctedDataValue && this.verifyVariantCompatibility(correctedDataValue.value);
825
- // xx assert(correctedDataValue.serverTimestamp);
826
-
827
- if (indexRange && !indexRange.isEmpty()) {
828
- if (!indexRange.isValid()) {
829
- return callback!(null, StatusCodes.BadIndexRangeInvalid);
833
+ write_func.call(this, dataValue, (err?: Error | null, statusCode1?: StatusCode) => {
834
+ if (!err) {
835
+ dataValue && this.verifyVariantCompatibility(dataValue.value);
836
+
837
+ if (indexRange && !indexRange.isEmpty()) {
838
+ if (!indexRange.isValid()) {
839
+ return callback!(null, StatusCodes.BadIndexRangeInvalid);
840
+ }
841
+
842
+ const newArrayOrMatrix = dataValue.value.value;
843
+
844
+ if (dataValue.value.arrayType === VariantArrayType.Array) {
845
+ if (this.$dataValue.value.arrayType !== VariantArrayType.Array) {
846
+ return callback(null, StatusCodes.BadTypeMismatch);
830
847
  }
848
+ // check that destination data is also an array
849
+ assert(check_valid_array(this.$dataValue.value.dataType, this.$dataValue.value.value));
850
+ const destArr = this.$dataValue.value.value;
851
+ const result = indexRange.set_values(destArr, newArrayOrMatrix);
831
852
 
832
- const newArrayOrMatrix = correctedDataValue.value.value;
833
-
834
- if (correctedDataValue.value.arrayType === VariantArrayType.Array) {
835
- if (this.$dataValue.value.arrayType !== VariantArrayType.Array) {
836
- return callback(null, StatusCodes.BadTypeMismatch);
837
- }
838
- // check that destination data is also an array
839
- assert(check_valid_array(this.$dataValue.value.dataType, this.$dataValue.value.value));
840
- const destArr = this.$dataValue.value.value;
841
- const result = indexRange.set_values(destArr, newArrayOrMatrix);
842
-
843
- if (result.statusCode.isNot(StatusCodes.Good)) {
844
- return callback!(null, result.statusCode);
845
- }
846
- correctedDataValue.value.value = result.array;
847
-
848
- // scrap original array so we detect range
849
- this.$dataValue.value.value = null;
850
- } else if (correctedDataValue.value.arrayType === VariantArrayType.Matrix) {
851
- const dimensions = this.$dataValue.value.dimensions;
852
- if (this.$dataValue.value.arrayType !== VariantArrayType.Matrix || !dimensions) {
853
- // not a matrix !
854
- return callback!(null, StatusCodes.BadTypeMismatch);
855
- }
856
- const matrix = this.$dataValue.value.value;
857
- const result = indexRange.set_values_matrix(
858
- {
859
- matrix,
860
- dimensions
861
- },
862
- newArrayOrMatrix
863
- );
864
- if (result.statusCode.isNot(StatusCodes.Good)) {
865
- return callback!(null, result.statusCode);
866
- }
867
- correctedDataValue.value.dimensions = this.$dataValue.value.dimensions;
868
- correctedDataValue.value.value = result.matrix;
869
-
870
- // scrap original array so we detect range
871
- this.$dataValue.value.value = null;
872
- } else {
853
+ if (result.statusCode.isNot(StatusCodes.Good)) {
854
+ return callback!(null, result.statusCode);
855
+ }
856
+ dataValue.value.value = result.array;
857
+
858
+ // scrap original array so we detect range
859
+ this.$dataValue.value.value = null;
860
+ } else if (dataValue.value.arrayType === VariantArrayType.Matrix) {
861
+ const dimensions = this.$dataValue.value.dimensions;
862
+ if (this.$dataValue.value.arrayType !== VariantArrayType.Matrix || !dimensions) {
863
+ // not a matrix !
873
864
  return callback!(null, StatusCodes.BadTypeMismatch);
874
865
  }
875
- }
876
- try {
877
- this._internal_set_dataValue(correctedDataValue, indexRange);
878
- } catch (err) {
879
- if (err instanceof Error) {
880
- warningLog(err.message);
866
+ const matrix = this.$dataValue.value.value;
867
+ const result = indexRange.set_values_matrix(
868
+ {
869
+ matrix,
870
+ dimensions
871
+ },
872
+ newArrayOrMatrix
873
+ );
874
+ if (result.statusCode.isNot(StatusCodes.Good)) {
875
+ return callback!(null, result.statusCode);
881
876
  }
882
- return callback!(null, StatusCodes.BadInternalError);
877
+ dataValue.value.dimensions = this.$dataValue.value.dimensions;
878
+ dataValue.value.value = result.matrix;
879
+
880
+ // scrap original array so we detect range
881
+ this.$dataValue.value.value = null;
882
+ } else {
883
+ return callback!(null, StatusCodes.BadTypeMismatch);
884
+ }
885
+ }
886
+ try {
887
+ this._internal_set_dataValue(dataValue, indexRange);
888
+ } catch (err) {
889
+ if (err instanceof Error) {
890
+ warningLog(err.message);
883
891
  }
892
+ return callback!(null, StatusCodes.BadInternalError);
884
893
  }
885
- callback!(err, statusCode1);
886
894
  }
887
- );
895
+ callback!(err || null, statusCode1);
896
+ });
888
897
  }
889
898
 
890
899
  public writeAttribute(context: ISessionContext | null, writeValue: WriteValueOptions, callback: StatusCodeCallback): void;
@@ -952,7 +961,7 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
952
961
  }
953
962
  try {
954
963
  this.verifyVariantCompatibility(value);
955
- } catch(err) {
964
+ } catch (err) {
956
965
  return StatusCodes.BadTypeMismatch;
957
966
  }
958
967
  return StatusCodes.Good;
@@ -1122,6 +1131,7 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
1122
1131
 
1123
1132
  assert(typeof this._timestamped_set_func !== "function", "UAVariable already bound");
1124
1133
  assert(typeof this._timestamped_get_func !== "function", "UAVariable already bound");
1134
+
1125
1135
  bind_getter.call(this, options);
1126
1136
  bind_setter.call(this, options);
1127
1137
 
@@ -1133,9 +1143,9 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
1133
1143
  this._historyRead = _historyRead;
1134
1144
  assert(this._historyRead.length === 6);
1135
1145
  }
1136
-
1146
+ // post conditions
1137
1147
  assert(typeof this._timestamped_set_func === "function");
1138
- assert(this._timestamped_set_func!.length === 3);
1148
+ assert(this._timestamped_set_func!.length === 2, "expecting 2 parameters");
1139
1149
  }
1140
1150
 
1141
1151
  /**
@@ -1226,7 +1236,13 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
1226
1236
  valueRank: this.valueRank
1227
1237
  };
1228
1238
 
1229
- const newVariable = _clone.call(this, UAVariableImpl, options, optionalFilter, extraInfo) as UAVariableImpl;
1239
+ const newVariable = _clone.call(
1240
+ this,
1241
+ UAVariableImpl,
1242
+ options,
1243
+ optionalFilter || defaultCloneFilter,
1244
+ extraInfo || defaultCloneExtraInfo
1245
+ ) as UAVariableImpl;
1230
1246
 
1231
1247
  newVariable.bindVariable();
1232
1248
 
@@ -1361,7 +1377,6 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
1361
1377
  }
1362
1378
 
1363
1379
  const bindProperty = (propertyNode: UAVariableImpl, name: string, extensionObject: ExtensionObject, dataType: DataType) => {
1364
-
1365
1380
  // eslint-disable-next-line @typescript-eslint/no-this-alias
1366
1381
  const self = this;
1367
1382
  propertyNode.bindVariable(
@@ -1379,7 +1394,7 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
1379
1394
  propertyNode.$dataValue.statusCode = StatusCodes.Good;
1380
1395
  propertyNode.$dataValue.value.dataType = dataType;
1381
1396
  propertyNode.$dataValue.value.value = value;
1382
- return new DataValue(propertyNode.$dataValue);
1397
+ return new DataValue(propertyNode.$dataValue);
1383
1398
  },
1384
1399
  timestamped_set: (dataValue: DataValue, callback: CallbackT<StatusCode>) => {
1385
1400
  dataValue;
@@ -1482,7 +1497,6 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
1482
1497
  };
1483
1498
 
1484
1499
  for (const field of definition.fields || []) {
1485
-
1486
1500
  if (NodeId.sameNodeId(NodeId.nullNodeId, field.dataType)) {
1487
1501
  warningLog("field.dataType is null ! ", field.toString(), NodeId.nullNodeId.toString());
1488
1502
  warningLog(" dataType replaced with BaseDataType ");
@@ -2019,7 +2033,6 @@ function _default_writable_timestamped_set_func(
2019
2033
  dataValue: DataValue,
2020
2034
  callback: (err: Error | null, statusCode: StatusCode, dataValue?: DataValue | null) => void
2021
2035
  ) {
2022
- /* jshint validthis: true */
2023
2036
  assert(dataValue instanceof DataValue);
2024
2037
  callback(null, StatusCodes.Good, dataValue);
2025
2038
  }
@@ -2073,7 +2086,13 @@ function _Variable_bind_with_async_refresh(this: UAVariableImpl, options: any) {
2073
2086
  }
2074
2087
 
2075
2088
  // variation 2
2076
- function _Variable_bind_with_timestamped_get(this: UAVariableImpl, options: any) {
2089
+ function _Variable_bind_with_timestamped_get(
2090
+ this: UAVariableImpl,
2091
+ options: {
2092
+ get: undefined;
2093
+ timestamped_get: TimestampGetFunc;
2094
+ }
2095
+ ) {
2077
2096
  /* jshint validthis: true */
2078
2097
  assert(this instanceof UAVariableImpl);
2079
2098
  assert(typeof options.timestamped_get === "function");
@@ -2081,20 +2100,20 @@ function _Variable_bind_with_timestamped_get(this: UAVariableImpl, options: any)
2081
2100
  assert(!this._timestamped_get_func);
2082
2101
 
2083
2102
  const async_refresh_func = (callback: (err: Error | null, dataValue?: DataValue) => void) => {
2084
- Promise.resolve((this._timestamped_get_func! as TimestampGetFunction1).call(this))
2103
+ Promise.resolve((this._timestamped_get_func! as VariableDataValueGetterSync).call(this))
2085
2104
  .then((dataValue) => callback(null, dataValue))
2086
2105
  .catch((err) => {
2087
2106
  errorLog("asyncRefresh error: Variable is ", this.nodeId.toString(), this.browseName.toString());
2088
2107
  callback(err as Error);
2089
2108
  });
2090
2109
  };
2091
-
2110
+ const pThis = this as UAVariable;
2092
2111
  if (options.timestamped_get.length === 0) {
2093
- const timestamped_get = options.timestamped_get as TimestampGetFunction1;
2112
+ const timestamped_get = options.timestamped_get as (this: UAVariable) => DataValue | Promise<DataValue>;
2094
2113
  // sync version | Promise version
2095
2114
  this._timestamped_get_func = timestamped_get;
2096
2115
 
2097
- const dataValue_verify = timestamped_get!.call(this);
2116
+ const dataValue_verify = timestamped_get.call(pThis);
2098
2117
  // dataValue_verify should be a DataValue or a Promise
2099
2118
  /* istanbul ignore next */
2100
2119
  if (!(dataValue_verify instanceof DataValue) && typeof dataValue_verify.then !== "function") {
@@ -2147,12 +2166,13 @@ function _Variable_bind_with_simple_get(this: UAVariableImpl, options: GetterOpt
2147
2166
  } else {
2148
2167
  if (!this.$dataValue || !isGoodish(this.$dataValue.statusCode) || !sameVariant(this.$dataValue.value, value)) {
2149
2168
  this.setValueFromSource(value, StatusCodes.Good);
2150
- }
2169
+ }
2151
2170
  return this.$dataValue;
2152
2171
  }
2153
2172
  };
2154
2173
 
2155
2174
  _Variable_bind_with_timestamped_get.call(this, {
2175
+ get: undefined,
2156
2176
  timestamped_get: timestamped_get_func_from__Variable_bind_with_simple_get
2157
2177
  });
2158
2178
  }
@@ -2170,12 +2190,10 @@ function _Variable_bind_with_simple_set(this: UAVariableImpl, options: any) {
2170
2190
 
2171
2191
  this._timestamped_set_func = (
2172
2192
  timestamped_value: DataValue,
2173
- indexRange: NumericRange,
2174
2193
  callback: (err: Error | null, statusCode: StatusCode, dataValue: DataValue) => void
2175
2194
  ) => {
2176
2195
  assert(timestamped_value instanceof DataValue);
2177
2196
  this._set_func(timestamped_value.value, (err: Error | null, statusCode: StatusCode) => {
2178
-
2179
2197
  // istanbul ignore next
2180
2198
  if (!err && !statusCode) {
2181
2199
  errorLog(
@@ -2189,22 +2207,20 @@ function _Variable_bind_with_simple_set(this: UAVariableImpl, options: any) {
2189
2207
  };
2190
2208
  }
2191
2209
 
2192
- function _Variable_bind_with_timestamped_set(this: UAVariableImpl, options: any) {
2193
- assert(this instanceof UAVariableImpl);
2210
+ function _Variable_bind_with_timestamped_set(
2211
+ this: UAVariableImpl,
2212
+ options: {
2213
+ timestamped_set: TimestampSetFunc;
2214
+ set: undefined;
2215
+ }
2216
+ ) {
2194
2217
  assert(typeof options.timestamped_set === "function");
2195
2218
  assert(
2196
2219
  options.timestamped_set.length === 2,
2197
2220
  "timestamped_set must have 2 parameters timestamped_set: function(dataValue,callback){}"
2198
2221
  );
2199
2222
  assert(!options.set, "should not specify set when timestamped_set_func exists ");
2200
- this._timestamped_set_func = (
2201
- dataValue: DataValue,
2202
- indexRange: NumericRange,
2203
- callback: (err: Error | null, statusCode: StatusCode, dataValue: DataValue) => void
2204
- ) => {
2205
- // xx assert(!indexRange,"indexRange Not Implemented");
2206
- return options.timestamped_set.call(this, dataValue, callback);
2207
- };
2223
+ this._timestamped_set_func = convertToCallbackFunction1<StatusCode, DataValue, UAVariable>(options.timestamped_set);
2208
2224
  }
2209
2225
 
2210
2226
  interface SetterOptions {
@@ -2219,15 +2235,20 @@ function bind_setter(this: UAVariableImpl, options: SetterOptions) {
2219
2235
  } else if (typeof options.timestamped_set === "function") {
2220
2236
  // variation 2
2221
2237
  assert(typeof options.timestamped_get === "function", "timestamped_set must be used with timestamped_get ");
2222
- _Variable_bind_with_timestamped_set.call(this, options);
2238
+ _Variable_bind_with_timestamped_set.call(this, {
2239
+ set: undefined,
2240
+ timestamped_set: options.timestamped_set
2241
+ });
2223
2242
  } else if (typeof options.timestamped_get === "function") {
2224
2243
  // timestamped_get is specified but timestamped_set is not
2225
2244
  // => Value is read-only
2226
2245
  _Variable_bind_with_timestamped_set.call(this, {
2246
+ set: undefined,
2227
2247
  timestamped_set: _not_writable_timestamped_set_func
2228
2248
  });
2229
2249
  } else {
2230
2250
  _Variable_bind_with_timestamped_set.call(this, {
2251
+ set: undefined,
2231
2252
  timestamped_set: _default_writable_timestamped_set_func
2232
2253
  });
2233
2254
  }
@@ -2236,7 +2257,7 @@ function bind_setter(this: UAVariableImpl, options: SetterOptions) {
2236
2257
  interface GetterOptions {
2237
2258
  get?: GetFunc;
2238
2259
  timestamped_get?: TimestampGetFunc;
2239
- refreshFunc?: any;
2260
+ refreshFunc?: (callback: CallbackT<DataValue>) => void;
2240
2261
  dataType?: DataType | string;
2241
2262
  value?: any;
2242
2263
  }
@@ -2246,7 +2267,10 @@ function bind_getter(this: UAVariableImpl, options: GetterOptions) {
2246
2267
  _Variable_bind_with_simple_get.call(this, options);
2247
2268
  } else if (typeof options.timestamped_get === "function") {
2248
2269
  // variation 2
2249
- _Variable_bind_with_timestamped_get.call(this, options);
2270
+ _Variable_bind_with_timestamped_get.call(this, {
2271
+ get: undefined,
2272
+ timestamped_get: options.timestamped_get
2273
+ });
2250
2274
  } else if (typeof options.refreshFunc === "function") {
2251
2275
  // variation 3
2252
2276
  _Variable_bind_with_async_refresh.call(this, options);