node-opcua-address-space 2.59.0 → 2.62.1

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 (82) hide show
  1. package/dist/source/address_space_ts.d.ts +0 -2
  2. package/dist/source/helpers/argument_list.js +12 -1
  3. package/dist/source/helpers/argument_list.js.map +1 -1
  4. package/dist/source/helpers/multiform_func.d.ts +11 -0
  5. package/dist/source/helpers/multiform_func.js +74 -0
  6. package/dist/source/helpers/multiform_func.js.map +1 -0
  7. package/dist/source/loader/load_nodeset2.js +47 -64
  8. package/dist/source/loader/load_nodeset2.js.map +1 -1
  9. package/dist/source/set_namespace_meta_data.js +1 -1
  10. package/dist/src/address_space.js +12 -6
  11. package/dist/src/address_space.js.map +1 -1
  12. package/dist/src/alarms_and_conditions/condition_snapshot.js +3 -3
  13. package/dist/src/alarms_and_conditions/condition_snapshot.js.map +1 -1
  14. package/dist/src/alarms_and_conditions/ua_alarm_condition_impl.js +1 -1
  15. package/dist/src/alarms_and_conditions/ua_alarm_condition_impl.js.map +1 -1
  16. package/dist/src/alarms_and_conditions/ua_condition_impl.js +8 -6
  17. package/dist/src/alarms_and_conditions/ua_condition_impl.js.map +1 -1
  18. package/dist/src/alarms_and_conditions/ua_off_normal_alarm_impl.js +1 -1
  19. package/dist/src/alarms_and_conditions/ua_off_normal_alarm_impl.js.map +1 -1
  20. package/dist/src/base_node_impl.js +2 -0
  21. package/dist/src/base_node_impl.js.map +1 -1
  22. package/dist/src/base_node_private.d.ts +3 -3
  23. package/dist/src/base_node_private.js +198 -25
  24. package/dist/src/base_node_private.js.map +1 -1
  25. package/dist/src/event_data.js +1 -1
  26. package/dist/src/event_data.js.map +1 -1
  27. package/dist/src/namespace_impl.js +5 -5
  28. package/dist/src/namespace_impl.js.map +1 -1
  29. package/dist/src/nodeset_tools/nodeset_to_xml.js +15 -9
  30. package/dist/src/nodeset_tools/nodeset_to_xml.js.map +1 -1
  31. package/dist/src/nodeset_tools/typedictionary_to_xml.js +17 -10
  32. package/dist/src/nodeset_tools/typedictionary_to_xml.js.map +1 -1
  33. package/dist/src/state_machine/ua_shelving_state_machine_ex.js +20 -13
  34. package/dist/src/state_machine/ua_shelving_state_machine_ex.js.map +1 -1
  35. package/dist/src/ua_data_type_impl.d.ts +15 -5
  36. package/dist/src/ua_data_type_impl.js +129 -51
  37. package/dist/src/ua_data_type_impl.js.map +1 -1
  38. package/dist/src/ua_method_impl.js +2 -1
  39. package/dist/src/ua_method_impl.js.map +1 -1
  40. package/dist/src/ua_object_impl.js +2 -1
  41. package/dist/src/ua_object_impl.js.map +1 -1
  42. package/dist/src/ua_object_type_impl.js +1 -0
  43. package/dist/src/ua_object_type_impl.js.map +1 -1
  44. package/dist/src/ua_variable_impl.d.ts +12 -18
  45. package/dist/src/ua_variable_impl.js +287 -215
  46. package/dist/src/ua_variable_impl.js.map +1 -1
  47. package/dist/src/ua_variable_type_impl.d.ts +3 -4
  48. package/dist/src/ua_variable_type_impl.js +61 -52
  49. package/dist/src/ua_variable_type_impl.js.map +1 -1
  50. package/dist/src/ua_view_impl.js +1 -1
  51. package/dist/src/ua_view_impl.js.map +1 -1
  52. package/distHelpers/mock_session.js +1 -1
  53. package/distHelpers/mock_session.js.map +1 -1
  54. package/package.json +35 -35
  55. package/source/address_space_ts.ts +0 -1
  56. package/source/helpers/argument_list.ts +13 -3
  57. package/source/helpers/multiform_func.ts +76 -0
  58. package/source/loader/load_nodeset2.ts +64 -80
  59. package/source/set_namespace_meta_data.ts +1 -1
  60. package/src/address_space.ts +16 -7
  61. package/src/alarms_and_conditions/condition_snapshot.ts +4 -4
  62. package/src/alarms_and_conditions/ua_alarm_condition_impl.ts +2 -2
  63. package/src/alarms_and_conditions/ua_condition_impl.ts +18 -8
  64. package/src/alarms_and_conditions/ua_off_normal_alarm_impl.ts +1 -1
  65. package/src/base_node_impl.ts +3 -1
  66. package/src/base_node_private.ts +282 -36
  67. package/src/event_data.ts +1 -1
  68. package/src/namespace_impl.ts +6 -6
  69. package/src/nodeset_tools/nodeset_to_xml.ts +20 -10
  70. package/src/nodeset_tools/typedictionary_to_xml.ts +17 -7
  71. package/src/state_machine/ua_shelving_state_machine_ex.ts +28 -16
  72. package/src/ua_data_type_impl.ts +168 -61
  73. package/src/ua_method_impl.ts +10 -2
  74. package/src/ua_object_impl.ts +10 -2
  75. package/src/ua_object_type_impl.ts +1 -0
  76. package/src/ua_variable_impl.ts +421 -325
  77. package/src/ua_variable_type_impl.ts +87 -52
  78. package/src/ua_view_impl.ts +1 -1
  79. package/test_helpers/mock_session.ts +1 -1
  80. package/test_helpers/test_fixtures/fixture_simple_statemachine_nodeset2.xml +18 -0
  81. package/test_helpers/test_fixtures/fixuture_nodeset_objects_with_some_methods.xml +9 -1
  82. package/test_helpers/test_fixtures/mini.Node.Set2.xml +22 -1
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.UAVariableImplT = exports.UAVariableImpl = exports.verifyRankAndDimensions = exports.adjust_userAccessLevel = exports.adjust_accessLevel = void 0;
3
+ exports.UAVariableImplT = exports.UAVariableImpl = exports.adjust_userAccessLevel = exports.adjust_accessLevel = void 0;
4
4
  /* eslint-disable max-statements */
5
5
  /* eslint-disable complexity */
6
6
  /**
@@ -10,6 +10,7 @@ exports.UAVariableImplT = exports.UAVariableImpl = exports.verifyRankAndDimensio
10
10
  // tslint:disable:no-console
11
11
  // tslint:disable:max-line-length
12
12
  const chalk = require("chalk");
13
+ const node_opcua_address_space_base_1 = require("node-opcua-address-space-base");
13
14
  const node_opcua_assert_1 = require("node-opcua-assert");
14
15
  const node_opcua_data_model_1 = require("node-opcua-data-model");
15
16
  const node_opcua_data_value_1 = require("node-opcua-data-value");
@@ -24,6 +25,7 @@ const utils = require("node-opcua-utils");
24
25
  const node_opcua_utils_1 = require("node-opcua-utils");
25
26
  const node_opcua_variant_1 = require("node-opcua-variant");
26
27
  const session_context_1 = require("../source/session_context");
28
+ const multiform_func_1 = require("../source/helpers/multiform_func");
27
29
  const base_node_impl_1 = require("./base_node_impl");
28
30
  const base_node_private_1 = require("./base_node_private");
29
31
  const ua_data_type_impl_1 = require("./ua_data_type_impl");
@@ -104,13 +106,13 @@ function validateDataType(addressSpace, dataTypeNodeId, variantDataType, nodeId,
104
106
  }
105
107
  let builtInType;
106
108
  let builtInUADataType;
107
- const destUADataType = addressSpace.findNode(dataTypeNodeId);
109
+ const destUADataType = addressSpace.findDataType(dataTypeNodeId);
108
110
  (0, node_opcua_assert_1.assert)(destUADataType instanceof ua_data_type_impl_1.UADataTypeImpl);
109
111
  if (destUADataType.isAbstract || destUADataType.nodeId.namespace !== 0) {
110
112
  builtInUADataType = destUADataType;
111
113
  }
112
114
  else {
113
- builtInType = node_opcua_variant_1.DataType[addressSpace.findCorrespondingBasicDataType(destUADataType)];
115
+ builtInType = addressSpace.findCorrespondingBasicDataType(destUADataType);
114
116
  builtInUADataType = addressSpace.findDataType(builtInType);
115
117
  }
116
118
  (0, node_opcua_assert_1.assert)(builtInUADataType instanceof ua_data_type_impl_1.UADataTypeImpl);
@@ -121,8 +123,8 @@ function validateDataType(addressSpace, dataTypeNodeId, variantDataType, nodeId,
121
123
  if (destUADataType.isSupertypeOf(enumerationUADataType)) {
122
124
  // istanbul ignore next
123
125
  if (doDebug) {
124
- console.log("destUADataType.", destUADataType.browseName.toString(), destUADataType.nodeId.toString());
125
- console.log("enumerationUADataType.", enumerationUADataType.browseName.toString(), enumerationUADataType.nodeId.toString());
126
+ debugLog("destUADataType.", destUADataType.browseName.toString(), destUADataType.nodeId.toString());
127
+ debugLog("enumerationUADataType.", enumerationUADataType.browseName.toString(), enumerationUADataType.nodeId.toString());
126
128
  }
127
129
  return true;
128
130
  }
@@ -134,45 +136,21 @@ function validateDataType(addressSpace, dataTypeNodeId, variantDataType, nodeId,
134
136
  if (doDebug) {
135
137
  if (dest_isSuperTypeOf_variant) {
136
138
  /* istanbul ignore next*/
137
- console.log(chalk.green(" ---------- Type match !!! "), " on ", nodeId.toString());
139
+ debugLog(chalk.green(" ---------- Type match !!! "), " on ", nodeId.toString());
138
140
  }
139
141
  else {
140
142
  /* istanbul ignore next*/
141
- console.log(chalk.red(" ---------- Type mismatch "), " on ", nodeId.toString());
143
+ debugLog(chalk.red(" ---------- Type mismatch "), " on ", nodeId.toString());
142
144
  }
143
- console.log(chalk.cyan(" Variable data Type is = "), destUADataType.browseName.toString());
144
- console.log(chalk.cyan(" which matches basic Type = "), builtInUADataType.browseName.toString());
145
- console.log(chalk.yellow(" Actual dataType = "), variantUADataType.browseName.toString());
145
+ debugLog(chalk.cyan(" Variable data Type is = "), destUADataType.browseName.toString());
146
+ debugLog(chalk.cyan(" which matches basic Type = "), builtInUADataType.browseName.toString());
147
+ debugLog(chalk.yellow(" Actual dataType = "), variantUADataType.browseName.toString());
146
148
  }
147
149
  return dest_isSuperTypeOf_variant;
148
150
  }
149
- function verifyRankAndDimensions(options) {
150
- // evaluate valueRank arrayDimensions is specified but valueRank is null
151
- if (options.arrayDimensions && options.valueRank === undefined) {
152
- options.valueRank = options.arrayDimensions.length;
153
- }
154
- options.valueRank = options.valueRank === undefined ? -1 : options.valueRank || 0; // UInt32
155
- (0, node_opcua_assert_1.assert)(typeof options.valueRank === "number");
156
- options.arrayDimensions = options.arrayDimensions || null;
157
- (0, node_opcua_assert_1.assert)(options.arrayDimensions === null || Array.isArray(options.arrayDimensions));
158
- if (options.arrayDimensions && options.valueRank <= 0) {
159
- throw new Error("[CONFORMANCE] arrayDimensions must be null if valueRank <=0");
160
- }
161
- // specify default arrayDimension if not provided
162
- if (options.valueRank > 0 && !options.arrayDimensions) {
163
- options.arrayDimensions = new Array(options.valueRank).fill(0);
164
- }
165
- if (!options.arrayDimensions && options.valueRank > 0) {
166
- throw new Error("[CONFORMANCE] arrayDimension must be specified if valueRank >0 " + options.valueRank);
167
- }
168
- if (options.valueRank > 0 && options.arrayDimensions.length !== options.valueRank) {
169
- throw new Error("[CONFORMANCE] when valueRank> 0, arrayDimensions must have valueRank elements, this.valueRank =" +
170
- options.valueRank +
171
- " whereas arrayDimensions.length =" +
172
- options.arrayDimensions.length);
173
- }
151
+ function default_func(dataValue1, callback1) {
152
+ return _default_writable_timestamped_set_func.call(this, dataValue1, callback1);
174
153
  }
175
- exports.verifyRankAndDimensions = verifyRankAndDimensions;
176
154
  /**
177
155
  * A OPCUA Variable Node
178
156
  *
@@ -203,16 +181,15 @@ class UAVariableImpl extends base_node_impl_1.BaseNodeImpl {
203
181
  constructor(options) {
204
182
  super(options);
205
183
  this.nodeClass = node_opcua_data_model_1.NodeClass.Variable;
206
- verifyRankAndDimensions(options);
184
+ (0, node_opcua_variant_1.verifyRankAndDimensions)(options);
207
185
  this.valueRank = options.valueRank;
208
186
  this.arrayDimensions = options.arrayDimensions;
209
187
  this.dataType = this.resolveNodeId(options.dataType); // DataType (NodeId)
210
188
  this.accessLevel = adjust_accessLevel(options.accessLevel);
211
189
  this.userAccessLevel = adjust_userAccessLevel(options.userAccessLevel, this.accessLevel);
212
190
  this.minimumSamplingInterval = adjust_samplingInterval(options.minimumSamplingInterval || 0);
213
- this.historizing = !!options.historizing; // coerced to boolean
214
- this._dataValue = new node_opcua_data_value_1.DataValue({ statusCode: node_opcua_status_code_1.StatusCodes.UncertainInitialValue, value: {} });
215
- // xx options.value = options.value || { dataType: DataType.Null };
191
+ this.historizing = !!options.historizing; // coerced to boolean"
192
+ this.$dataValue = new node_opcua_data_value_1.DataValue({ statusCode: node_opcua_status_code_1.StatusCodes.UncertainInitialValue, value: { dataType: node_opcua_variant_1.DataType.Null } });
216
193
  if (options.value) {
217
194
  this.bindVariable(options.value);
218
195
  }
@@ -301,10 +278,17 @@ class UAVariableImpl extends base_node_impl_1.BaseNodeImpl {
301
278
  }
302
279
  if (this._timestamped_get_func) {
303
280
  if (this._timestamped_get_func.length === 0) {
304
- this._dataValue = this._timestamped_get_func();
281
+ const dataValueOrPromise = this._timestamped_get_func();
282
+ if (!Object.prototype.hasOwnProperty.call(dataValueOrPromise, "then")) {
283
+ this.$dataValue = dataValueOrPromise;
284
+ this.verifyVariantCompatibility(this.$dataValue.value);
285
+ }
286
+ else {
287
+ errorLog("Unsupported: _timestamped_get_func returns a Promise !");
288
+ }
305
289
  }
306
290
  }
307
- let dataValue = this._dataValue;
291
+ let dataValue = this.$dataValue;
308
292
  if (isGoodish(dataValue.statusCode)) {
309
293
  // note : extractRange will clone the dataValue
310
294
  dataValue = (0, node_opcua_data_value_1.extractRange)(dataValue, indexRange);
@@ -342,6 +326,9 @@ class UAVariableImpl extends base_node_impl_1.BaseNodeImpl {
342
326
  return dataTypeNode._getEnumerationInfo();
343
327
  }
344
328
  asyncRefresh(...args) {
329
+ if (isGoodish(this.$dataValue.statusCode)) {
330
+ this.verifyVariantCompatibility(this.$dataValue.value);
331
+ }
345
332
  const oldestDate = args[0];
346
333
  (0, node_opcua_assert_1.assert)(oldestDate instanceof Date);
347
334
  const callback = args[1];
@@ -358,21 +345,31 @@ class UAVariableImpl extends base_node_impl_1.BaseNodeImpl {
358
345
  return callback(null, dataValue);
359
346
  }
360
347
  }
361
- if (this._dataValue.serverTimestamp && oldestDate.getTime() <= this._dataValue.serverTimestamp.getTime()) {
348
+ if (this.$dataValue.serverTimestamp && oldestDate.getTime() <= this.$dataValue.serverTimestamp.getTime()) {
362
349
  const dataValue = this.readValue();
363
350
  dataValue.serverTimestamp = oldestDate;
364
351
  dataValue.serverPicoseconds = 0;
365
352
  return callback(null, dataValue);
366
353
  }
367
- this.refreshFunc.call(this, (err, dataValue) => {
368
- if (err || !dataValue) {
369
- dataValue = { statusCode: node_opcua_status_code_1.StatusCodes.BadNoDataAvailable };
370
- }
371
- if (dataValue !== this._dataValue) {
372
- this._internal_set_dataValue(coerceDataValue(dataValue), null);
373
- }
374
- callback(err, this._dataValue);
375
- });
354
+ try {
355
+ this.refreshFunc.call(this, (err, dataValue) => {
356
+ if (err || !dataValue) {
357
+ errorLog("-------------- refresh call failed", this.browseName.toString(), this.nodeId.toString(), err === null || err === void 0 ? void 0 : err.message);
358
+ dataValue = { statusCode: node_opcua_status_code_1.StatusCodes.BadNoDataAvailable };
359
+ }
360
+ if (dataValue !== this.$dataValue) {
361
+ this._internal_set_dataValue(coerceDataValue(dataValue), null);
362
+ }
363
+ callback(err, this.$dataValue);
364
+ });
365
+ }
366
+ catch (err) {
367
+ errorLog("-------------- refresh call failed 2", this.browseName.toString(), this.nodeId.toString());
368
+ errorLog(err);
369
+ const dataValue = new node_opcua_data_value_1.DataValue({ statusCode: node_opcua_status_code_1.StatusCodes.BadInternalError });
370
+ this._internal_set_dataValue(dataValue, null);
371
+ callback(err, this.$dataValue);
372
+ }
376
373
  }
377
374
  readEnumValue() {
378
375
  const value = this.readValue().value.value;
@@ -441,10 +438,80 @@ class UAVariableImpl extends base_node_impl_1.BaseNodeImpl {
441
438
  return base_node_impl_1.BaseNodeImpl.prototype.readAttribute.call(this, context, attributeId);
442
439
  }
443
440
  }
444
- adjustVariant(variant) {
441
+ getBasicDataType() {
442
+ if (this._basicDataType) {
443
+ return this._basicDataType;
444
+ }
445
+ if (this.dataType.namespace === 0 && this.dataType.value === 0) {
446
+ return node_opcua_variant_1.DataType.Null;
447
+ }
445
448
  const addressSpace = this.addressSpace;
446
- const dataTypeNodeId = addressSpace.findCorrespondingBasicDataType(this.dataType);
447
- return (0, node_opcua_variant_1.adjustVariant)(variant, this.valueRank, dataTypeNodeId);
449
+ const dataTypeNode = addressSpace.findDataType(this.dataType);
450
+ const basicDataType = dataTypeNode ? dataTypeNode.getBasicDataType() : node_opcua_variant_1.DataType.Null;
451
+ // const basicDataType = addressSpace.findCorrespondingBasicDataType(this.dataType);
452
+ this._basicDataType = basicDataType;
453
+ return basicDataType;
454
+ }
455
+ adjustVariant(variant) {
456
+ return (0, node_opcua_variant_1.adjustVariant)(variant, this.valueRank, this.getBasicDataType());
457
+ }
458
+ verifyVariantCompatibility(variant) {
459
+ var _a;
460
+ try {
461
+ // istanbul ignore next
462
+ if (Object.prototype.hasOwnProperty.call(variant, "value")) {
463
+ if (variant.dataType === null || variant.dataType === undefined) {
464
+ throw new Error("Variant must provide a valid dataType : variant = " +
465
+ variant.toString() +
466
+ " this.dataType= " +
467
+ this.dataType.toString());
468
+ }
469
+ if (variant.dataType === node_opcua_variant_1.DataType.Boolean &&
470
+ (this.dataType.namespace !== 0 || this.dataType.value !== node_opcua_variant_1.DataType.Boolean)) {
471
+ throw new Error("Variant must provide a valid Boolean : variant = " +
472
+ variant.toString() +
473
+ " this.dataType= " +
474
+ this.dataType.toString());
475
+ }
476
+ if (this.dataType.namespace === 0 &&
477
+ this.dataType.value === node_opcua_variant_1.DataType.LocalizedText &&
478
+ variant.dataType !== node_opcua_variant_1.DataType.LocalizedText) {
479
+ throw new Error("Variant must provide a valid LocalizedText : variant = " +
480
+ variant.toString() +
481
+ " this.dataType= " +
482
+ this.dataType.toString());
483
+ }
484
+ }
485
+ const basicType = this.getBasicDataType();
486
+ if (basicType !== node_opcua_variant_1.DataType.Null &&
487
+ basicType !== node_opcua_variant_1.DataType.Variant &&
488
+ variant.dataType !== node_opcua_variant_1.DataType.Null &&
489
+ variant.dataType !== basicType) {
490
+ const message = "UAVariable.setValueFromSource " +
491
+ this.browseName.toString() +
492
+ " nodeId:" +
493
+ this.nodeId.toString() +
494
+ " dataType:" +
495
+ this.dataType.toString() +
496
+ ":\n" +
497
+ "the provided variant must have the expected dataType!\n" +
498
+ " - the expected dataType is " +
499
+ chalk.cyan(node_opcua_variant_1.DataType[basicType]) +
500
+ "\n" +
501
+ " - the actual dataType is " +
502
+ chalk.magenta(node_opcua_variant_1.DataType[variant.dataType]) +
503
+ "\n" +
504
+ " - " +
505
+ variant.toString();
506
+ throw new Error(message);
507
+ }
508
+ }
509
+ catch (err) {
510
+ errorLog("UAVariable ", (_a = err) === null || _a === void 0 ? void 0 : _a.message, this.browseName.toString(), " nodeId=", this.nodeId.toString());
511
+ errorLog(err.message);
512
+ errorLog(err.stack);
513
+ throw err;
514
+ }
448
515
  }
449
516
  /**
450
517
  * setValueFromSource is used to let the device sets the variable values
@@ -458,32 +525,27 @@ class UAVariableImpl extends base_node_impl_1.BaseNodeImpl {
458
525
  * @param [sourceTimestamp= Now]
459
526
  */
460
527
  setValueFromSource(variant, statusCode, sourceTimestamp) {
461
- statusCode = statusCode || node_opcua_status_code_1.StatusCodes.Good;
462
- // istanbul ignore next
463
- if (Object.prototype.hasOwnProperty.call(variant, "value")) {
464
- if (variant.dataType === null || variant.dataType === undefined) {
465
- throw new Error("Variant must provide a valid dataType" + variant.toString());
466
- }
467
- if (variant.dataType === node_opcua_variant_1.DataType.Boolean &&
468
- (this.dataType.namespace !== 0 || this.dataType.value !== node_opcua_variant_1.DataType.Boolean)) {
469
- throw new Error("Variant must provide a valid Boolean" + variant.toString());
470
- }
471
- if (this.dataType.namespace === 0 &&
472
- this.dataType.value === node_opcua_variant_1.DataType.LocalizedText &&
473
- variant.dataType !== node_opcua_variant_1.DataType.LocalizedText) {
474
- throw new Error("Variant must provide a valid LocalizedText" + variant.toString());
475
- }
528
+ var _a;
529
+ try {
530
+ statusCode = statusCode || node_opcua_status_code_1.StatusCodes.Good;
531
+ const variant1 = node_opcua_variant_1.Variant.coerce(variant);
532
+ this.verifyVariantCompatibility(variant1);
533
+ const now = (0, node_opcua_date_time_1.coerceClock)(sourceTimestamp, 0);
534
+ const dataValue = new node_opcua_data_value_1.DataValue(null);
535
+ dataValue.serverPicoseconds = now.picoseconds;
536
+ dataValue.serverTimestamp = now.timestamp;
537
+ dataValue.sourcePicoseconds = now.picoseconds;
538
+ dataValue.sourceTimestamp = now.timestamp;
539
+ dataValue.statusCode = statusCode;
540
+ dataValue.value = variant1;
541
+ this._internal_set_dataValue(dataValue);
542
+ }
543
+ catch (err) {
544
+ errorLog("UAVariable#setValueFromString Error : ", this.browseName.toString(), this.nodeId.toString());
545
+ errorLog(err.message);
546
+ errorLog((_a = this.parent) === null || _a === void 0 ? void 0 : _a.toString());
547
+ throw err;
476
548
  }
477
- const variant1 = node_opcua_variant_1.Variant.coerce(variant);
478
- const now = (0, node_opcua_date_time_1.coerceClock)(sourceTimestamp, 0);
479
- const dataValue = new node_opcua_data_value_1.DataValue(null);
480
- dataValue.serverPicoseconds = now.picoseconds;
481
- dataValue.serverTimestamp = now.timestamp;
482
- dataValue.sourcePicoseconds = now.picoseconds;
483
- dataValue.sourceTimestamp = now.timestamp;
484
- dataValue.statusCode = statusCode;
485
- dataValue.value = variant1;
486
- this._internal_set_dataValue(dataValue);
487
549
  }
488
550
  writeValue(context, dataValue, ...args) {
489
551
  context = context || session_context_1.SessionContext.defaultContext;
@@ -536,49 +598,43 @@ class UAVariableImpl extends base_node_impl_1.BaseNodeImpl {
536
598
  if (statusCode.isNot(node_opcua_status_code_1.StatusCodes.Good)) {
537
599
  return callback(null, statusCode);
538
600
  }
539
- function default_func(dataValue1, indexRange1, callback1) {
540
- // xx assert(!indexRange,"indexRange Not Implemented");
541
- return _default_writable_timestamped_set_func.call(this, dataValue1, callback1);
542
- }
543
- const write_func = (this._timestamped_set_func || default_func);
601
+ const write_func = this._timestamped_set_func || default_func;
544
602
  if (!write_func) {
545
603
  warningLog(" warning " + this.nodeId.toString() + " " + this.browseName.toString() + " has no setter. \n");
546
604
  warningLog("Please make sure to bind the variable or to pass a valid value: new Variant({}) during construction time");
547
605
  return callback(null, node_opcua_status_code_1.StatusCodes.BadNotWritable);
548
606
  }
549
607
  (0, node_opcua_assert_1.assert)(write_func);
550
- write_func.call(this, dataValue, indexRange, (err, statusCode1, correctedDataValue) => {
608
+ write_func.call(this, dataValue, (err, statusCode1) => {
551
609
  if (!err) {
552
- correctedDataValue = correctedDataValue || dataValue;
553
- (0, node_opcua_assert_1.assert)(correctedDataValue instanceof node_opcua_data_value_1.DataValue);
554
- // xx assert(correctedDataValue.serverTimestamp);
610
+ dataValue && this.verifyVariantCompatibility(dataValue.value);
555
611
  if (indexRange && !indexRange.isEmpty()) {
556
612
  if (!indexRange.isValid()) {
557
613
  return callback(null, node_opcua_status_code_1.StatusCodes.BadIndexRangeInvalid);
558
614
  }
559
- const newArrayOrMatrix = correctedDataValue.value.value;
560
- if (correctedDataValue.value.arrayType === node_opcua_variant_1.VariantArrayType.Array) {
561
- if (this._dataValue.value.arrayType !== node_opcua_variant_1.VariantArrayType.Array) {
615
+ const newArrayOrMatrix = dataValue.value.value;
616
+ if (dataValue.value.arrayType === node_opcua_variant_1.VariantArrayType.Array) {
617
+ if (this.$dataValue.value.arrayType !== node_opcua_variant_1.VariantArrayType.Array) {
562
618
  return callback(null, node_opcua_status_code_1.StatusCodes.BadTypeMismatch);
563
619
  }
564
620
  // check that destination data is also an array
565
- (0, node_opcua_assert_1.assert)(check_valid_array(this._dataValue.value.dataType, this._dataValue.value.value));
566
- const destArr = this._dataValue.value.value;
621
+ (0, node_opcua_assert_1.assert)(check_valid_array(this.$dataValue.value.dataType, this.$dataValue.value.value));
622
+ const destArr = this.$dataValue.value.value;
567
623
  const result = indexRange.set_values(destArr, newArrayOrMatrix);
568
624
  if (result.statusCode.isNot(node_opcua_status_code_1.StatusCodes.Good)) {
569
625
  return callback(null, result.statusCode);
570
626
  }
571
- correctedDataValue.value.value = result.array;
627
+ dataValue.value.value = result.array;
572
628
  // scrap original array so we detect range
573
- this._dataValue.value.value = null;
629
+ this.$dataValue.value.value = null;
574
630
  }
575
- else if (correctedDataValue.value.arrayType === node_opcua_variant_1.VariantArrayType.Matrix) {
576
- const dimensions = this._dataValue.value.dimensions;
577
- if (this._dataValue.value.arrayType !== node_opcua_variant_1.VariantArrayType.Matrix || !dimensions) {
631
+ else if (dataValue.value.arrayType === node_opcua_variant_1.VariantArrayType.Matrix) {
632
+ const dimensions = this.$dataValue.value.dimensions;
633
+ if (this.$dataValue.value.arrayType !== node_opcua_variant_1.VariantArrayType.Matrix || !dimensions) {
578
634
  // not a matrix !
579
635
  return callback(null, node_opcua_status_code_1.StatusCodes.BadTypeMismatch);
580
636
  }
581
- const matrix = this._dataValue.value.value;
637
+ const matrix = this.$dataValue.value.value;
582
638
  const result = indexRange.set_values_matrix({
583
639
  matrix,
584
640
  dimensions
@@ -586,17 +642,17 @@ class UAVariableImpl extends base_node_impl_1.BaseNodeImpl {
586
642
  if (result.statusCode.isNot(node_opcua_status_code_1.StatusCodes.Good)) {
587
643
  return callback(null, result.statusCode);
588
644
  }
589
- correctedDataValue.value.dimensions = this._dataValue.value.dimensions;
590
- correctedDataValue.value.value = result.matrix;
645
+ dataValue.value.dimensions = this.$dataValue.value.dimensions;
646
+ dataValue.value.value = result.matrix;
591
647
  // scrap original array so we detect range
592
- this._dataValue.value.value = null;
648
+ this.$dataValue.value.value = null;
593
649
  }
594
650
  else {
595
651
  return callback(null, node_opcua_status_code_1.StatusCodes.BadTypeMismatch);
596
652
  }
597
653
  }
598
654
  try {
599
- this._internal_set_dataValue(correctedDataValue, indexRange);
655
+ this._internal_set_dataValue(dataValue, indexRange);
600
656
  }
601
657
  catch (err) {
602
658
  if (err instanceof Error) {
@@ -605,7 +661,7 @@ class UAVariableImpl extends base_node_impl_1.BaseNodeImpl {
605
661
  return callback(null, node_opcua_status_code_1.StatusCodes.BadInternalError);
606
662
  }
607
663
  }
608
- callback(err, statusCode1);
664
+ callback(err || null, statusCode1);
609
665
  });
610
666
  }
611
667
  writeAttribute(context, writeValueOptions, callback) {
@@ -656,6 +712,12 @@ class UAVariableImpl extends base_node_impl_1.BaseNodeImpl {
656
712
  if (!this._validate_DataType(value.dataType)) {
657
713
  return node_opcua_status_code_1.StatusCodes.BadTypeMismatch;
658
714
  }
715
+ try {
716
+ this.verifyVariantCompatibility(value);
717
+ }
718
+ catch (err) {
719
+ return node_opcua_status_code_1.StatusCodes.BadTypeMismatch;
720
+ }
659
721
  return node_opcua_status_code_1.StatusCodes.Good;
660
722
  }
661
723
  /**
@@ -669,11 +731,11 @@ class UAVariableImpl extends base_node_impl_1.BaseNodeImpl {
669
731
  */
670
732
  touchValue(optionalNow) {
671
733
  const now = optionalNow || (0, node_opcua_date_time_1.getCurrentClock)();
672
- this._dataValue.sourceTimestamp = now.timestamp;
673
- this._dataValue.sourcePicoseconds = now.picoseconds;
674
- this._dataValue.serverTimestamp = now.timestamp;
675
- this._dataValue.serverPicoseconds = now.picoseconds;
676
- this._dataValue.statusCode = node_opcua_status_code_1.StatusCodes.Good;
734
+ this.$dataValue.sourceTimestamp = now.timestamp;
735
+ this.$dataValue.sourcePicoseconds = now.picoseconds;
736
+ this.$dataValue.serverTimestamp = now.timestamp;
737
+ this.$dataValue.serverPicoseconds = now.picoseconds;
738
+ this.$dataValue.statusCode = node_opcua_status_code_1.StatusCodes.Good;
677
739
  if (this.minimumSamplingInterval === 0) {
678
740
  if (this.listenerCount("value_changed") > 0) {
679
741
  const clonedDataValue = this.readValue();
@@ -826,8 +888,9 @@ class UAVariableImpl extends base_node_impl_1.BaseNodeImpl {
826
888
  this._historyRead = _historyRead;
827
889
  (0, node_opcua_assert_1.assert)(this._historyRead.length === 6);
828
890
  }
891
+ // post conditions
829
892
  (0, node_opcua_assert_1.assert)(typeof this._timestamped_set_func === "function");
830
- (0, node_opcua_assert_1.assert)(this._timestamped_set_func.length === 3);
893
+ (0, node_opcua_assert_1.assert)(this._timestamped_set_func.length === 2, "expecting 2 parameters");
831
894
  }
832
895
  readValueAsync(context, callback) {
833
896
  if (!context) {
@@ -841,7 +904,7 @@ class UAVariableImpl extends base_node_impl_1.BaseNodeImpl {
841
904
  return;
842
905
  }
843
906
  const readImmediate = (innerCallback) => {
844
- (0, node_opcua_assert_1.assert)(this._dataValue instanceof node_opcua_data_value_1.DataValue);
907
+ (0, node_opcua_assert_1.assert)(this.$dataValue instanceof node_opcua_data_value_1.DataValue);
845
908
  const dataValue = this.readValue();
846
909
  innerCallback(null, dataValue);
847
910
  };
@@ -895,11 +958,11 @@ class UAVariableImpl extends base_node_impl_1.BaseNodeImpl {
895
958
  // check this eventNotifier: this.eventNotifier,
896
959
  // check this symbolicName: this.symbolicName,
897
960
  accessLevel: this.accessLevel, arrayDimensions: this.arrayDimensions, dataType: this.dataType, historizing: this.historizing, minimumSamplingInterval: this.minimumSamplingInterval, userAccessLevel: this.userAccessLevel, valueRank: this.valueRank });
898
- const newVariable = base_node_private_1._clone.call(this, UAVariableImpl, options, optionalFilter, extraInfo);
961
+ const newVariable = base_node_private_1._clone.call(this, UAVariableImpl, options, optionalFilter || node_opcua_address_space_base_1.defaultCloneFilter, extraInfo || node_opcua_address_space_base_1.defaultCloneExtraInfo);
899
962
  newVariable.bindVariable();
900
963
  (0, node_opcua_assert_1.assert)(typeof newVariable._timestamped_set_func === "function");
901
964
  (0, node_opcua_assert_1.assert)(newVariable.dataType === this.dataType);
902
- newVariable._dataValue = this._dataValue.clone();
965
+ newVariable.$dataValue = this.$dataValue.clone();
903
966
  return newVariable;
904
967
  }
905
968
  getDataTypeNode() {
@@ -919,8 +982,9 @@ class UAVariableImpl extends base_node_impl_1.BaseNodeImpl {
919
982
  return true;
920
983
  }
921
984
  const addressSpace = this.addressSpace;
985
+ // istanbul ignore next
922
986
  if (!(extObj && extObj.constructor)) {
923
- console.log(extObj);
987
+ errorLog(extObj);
924
988
  throw new Error("expecting an valid extension object");
925
989
  }
926
990
  const dataType = addressSpace.findDataType(this.dataType);
@@ -948,7 +1012,7 @@ class UAVariableImpl extends base_node_impl_1.BaseNodeImpl {
948
1012
  }
949
1013
  }
950
1014
  catch (err) {
951
- console.log(err);
1015
+ errorLog(err);
952
1016
  return false;
953
1017
  }
954
1018
  }
@@ -957,7 +1021,7 @@ class UAVariableImpl extends base_node_impl_1.BaseNodeImpl {
957
1021
  * @return {ExtensionObject}
958
1022
  */
959
1023
  bindExtensionObject(optionalExtensionObject) {
960
- var _a, _b, _c;
1024
+ var _a, _b;
961
1025
  const addressSpace = this.addressSpace;
962
1026
  const structure = addressSpace.findDataType("Structure");
963
1027
  let extensionObject_;
@@ -968,7 +1032,7 @@ class UAVariableImpl extends base_node_impl_1.BaseNodeImpl {
968
1032
  }
969
1033
  // istanbul ignore next
970
1034
  if (doDebug) {
971
- console.log(" ------------------------------ binding ", this.browseName.toString(), this.nodeId.toString());
1035
+ debugLog(" ------------------------------ binding ", this.browseName.toString(), this.nodeId.toString());
972
1036
  }
973
1037
  (0, node_opcua_assert_1.assert)(structure && structure.browseName.toString() === "Structure", "expecting DataType Structure to be in IAddressSpace");
974
1038
  const dt = this.getDataTypeNode();
@@ -990,8 +1054,8 @@ class UAVariableImpl extends base_node_impl_1.BaseNodeImpl {
990
1054
  // }
991
1055
  // istanbul ignore next
992
1056
  if (!this.checkExtensionObjectIsCorrect(this.$extensionObject)) {
993
- console.log("on node : ", this.browseName.toString(), this.nodeId.toString(), "dataType=", this.dataType.toString({ addressSpace: this.addressSpace }));
994
- console.log((_a = this.$extensionObject) === null || _a === void 0 ? void 0 : _a.toString());
1057
+ warningLog("on node : ", this.browseName.toString(), this.nodeId.toString(), "dataType=", this.dataType.toString({ addressSpace: this.addressSpace }));
1058
+ warningLog((_a = this.$extensionObject) === null || _a === void 0 ? void 0 : _a.toString());
995
1059
  throw new Error("bindExtensionObject: $extensionObject is incorrect: we are expecting a " +
996
1060
  this.dataType.toString({ addressSpace: this.addressSpace }) +
997
1061
  " but we got a " +
@@ -1003,38 +1067,28 @@ class UAVariableImpl extends base_node_impl_1.BaseNodeImpl {
1003
1067
  this.$extensionObject = optionalExtensionObject;
1004
1068
  // ------------------------------------------------------------------
1005
1069
  function prepareVariantValue(dataType, value) {
1006
- if (typeof dataType === "string") {
1007
- dataType = node_opcua_variant_1.DataType[dataType];
1008
- }
1009
1070
  if ((dataType === node_opcua_variant_1.DataType.Int32 || dataType === node_opcua_variant_1.DataType.UInt32) && value && value.key) {
1010
1071
  value = value.value;
1011
1072
  }
1012
1073
  return value;
1013
1074
  }
1014
- const bindProperty = (propertyNode, name, extensionObject, dataTypeNodeId) => {
1015
- const dataTypeAsString = node_opcua_variant_1.DataType[dataTypeNodeId];
1016
- /*
1017
- property.setValueFromSource(new Variant({
1018
- dataType: dataType,
1019
- value: prepareVariantValue(dataType, this.$extensionObject[name])
1020
- }));
1021
- */
1022
- (0, node_opcua_assert_1.assert)(propertyNode.readValue().statusCode.equals(node_opcua_status_code_1.StatusCodes.Good));
1075
+ const bindProperty = (propertyNode, name, extensionObject, dataType) => {
1023
1076
  // eslint-disable-next-line @typescript-eslint/no-this-alias
1024
1077
  const self = this;
1025
1078
  propertyNode.bindVariable({
1026
1079
  timestamped_get: () => {
1027
- const prop = self.$extensionObject[name];
1028
- if (prop === undefined) {
1029
- propertyNode._dataValue.value.dataType = node_opcua_variant_1.DataType.Null;
1030
- propertyNode._dataValue.statusCode = node_opcua_status_code_1.StatusCodes.Good;
1031
- propertyNode._dataValue.value.value = null;
1032
- return new node_opcua_data_value_1.DataValue(propertyNode._dataValue);
1080
+ const propertyValue = self.$extensionObject[name];
1081
+ if (propertyValue === undefined) {
1082
+ propertyNode.$dataValue.value.dataType = node_opcua_variant_1.DataType.Null;
1083
+ propertyNode.$dataValue.statusCode = node_opcua_status_code_1.StatusCodes.Good;
1084
+ propertyNode.$dataValue.value.value = null;
1085
+ return new node_opcua_data_value_1.DataValue(propertyNode.$dataValue);
1033
1086
  }
1034
- const value = prepareVariantValue(dataTypeNodeId, prop);
1035
- propertyNode._dataValue.statusCode = node_opcua_status_code_1.StatusCodes.Good;
1036
- propertyNode._dataValue.value.value = value;
1037
- return new node_opcua_data_value_1.DataValue(propertyNode._dataValue);
1087
+ const value = prepareVariantValue(dataType, propertyValue);
1088
+ propertyNode.$dataValue.statusCode = node_opcua_status_code_1.StatusCodes.Good;
1089
+ propertyNode.$dataValue.value.dataType = dataType;
1090
+ propertyNode.$dataValue.value.value = value;
1091
+ return new node_opcua_data_value_1.DataValue(propertyNode.$dataValue);
1038
1092
  },
1039
1093
  timestamped_set: (dataValue, callback) => {
1040
1094
  dataValue;
@@ -1049,8 +1103,8 @@ class UAVariableImpl extends base_node_impl_1.BaseNodeImpl {
1049
1103
  const s = this.readValue();
1050
1104
  // istanbul ignore next
1051
1105
  if (this.dataTypeObj.isAbstract) {
1052
- console.log("Warning the DataType associated with this Variable is abstract ", this.dataTypeObj.browseName.toString());
1053
- console.log("You need to provide a extension object yourself ");
1106
+ warningLog("Warning the DataType associated with this Variable is abstract ", this.dataTypeObj.browseName.toString());
1107
+ warningLog("You need to provide a extension object yourself ");
1054
1108
  throw new Error("bindExtensionObject requires a extensionObject as associated dataType is only abstract");
1055
1109
  }
1056
1110
  if (s.value && (s.value.dataType === node_opcua_variant_1.DataType.Null || (s.value.dataType === node_opcua_variant_1.DataType.ExtensionObject && !s.value.value))) {
@@ -1067,8 +1121,8 @@ class UAVariableImpl extends base_node_impl_1.BaseNodeImpl {
1067
1121
  const self = this;
1068
1122
  this.bindVariable({
1069
1123
  timestamped_get() {
1070
- self._dataValue.value.value = self.$extensionObject;
1071
- const d = new node_opcua_data_value_1.DataValue(self._dataValue);
1124
+ self.$dataValue.value.value = self.$extensionObject;
1125
+ const d = new node_opcua_data_value_1.DataValue(self.$dataValue);
1072
1126
  d.value = new node_opcua_variant_1.Variant(d.value);
1073
1127
  return d;
1074
1128
  },
@@ -1090,26 +1144,28 @@ class UAVariableImpl extends base_node_impl_1.BaseNodeImpl {
1090
1144
  (0, node_opcua_assert_1.assert)(this.checkExtensionObjectIsCorrect(this.$extensionObject));
1091
1145
  (0, node_opcua_assert_1.assert)(s.statusCode.equals(node_opcua_status_code_1.StatusCodes.Good));
1092
1146
  }
1093
- let property;
1094
- let camelCaseName;
1095
1147
  // ------------------------------------------------------
1096
1148
  // now bind each member
1097
1149
  // ------------------------------------------------------
1098
- const definition = dt._getDefinition(false);
1150
+ const definition = dt._getDefinition();
1099
1151
  // istanbul ignore next
1100
1152
  if (!definition) {
1101
1153
  throw new Error("xx definition missing in " + dt.toString());
1102
1154
  }
1103
- for (const field of definition.fields || []) {
1104
- camelCaseName = (0, node_opcua_utils_1.lowerFirstLetter)(field.name);
1105
- const component = components.filter((f) => f.browseName.name.toString() === field.name);
1106
- if (component.length === 1) {
1107
- property = component[0];
1155
+ const getOrCreateProperty = (field) => {
1156
+ let property;
1157
+ const selectedComponents = components.filter((f) => f instanceof UAVariableImpl && f.browseName.name.toString() === field.name);
1158
+ if (field.dataType.value === node_opcua_variant_1.DataType.Variant) {
1159
+ warningLog("Warning : variant is not supported in ExtensionObject");
1160
+ }
1161
+ if (selectedComponents.length === 1) {
1162
+ property = selectedComponents[0];
1108
1163
  /* istanbul ignore next */
1109
1164
  }
1110
1165
  else {
1166
+ debugLog("adding missing array variable", field.name, this.browseName.toString(), this.nodeId.toString());
1111
1167
  // todo: Handle array appropriately...
1112
- (0, node_opcua_assert_1.assert)(component.length === 0);
1168
+ (0, node_opcua_assert_1.assert)(selectedComponents.length === 0);
1113
1169
  // create a variable (Note we may use ns=1;s=parentName/0:PropertyName)
1114
1170
  property = this.namespace.addVariable({
1115
1171
  browseName: { namespaceIndex: structureNamespace, name: field.name.toString() },
@@ -1119,62 +1175,64 @@ class UAVariableImpl extends base_node_impl_1.BaseNodeImpl {
1119
1175
  });
1120
1176
  (0, node_opcua_assert_1.assert)(property.minimumSamplingInterval === this.minimumSamplingInterval);
1121
1177
  }
1122
- property._dataValue.statusCode = node_opcua_status_code_1.StatusCodes.Good;
1123
- property.touchValue();
1178
+ return property;
1179
+ };
1180
+ for (const field of definition.fields || []) {
1124
1181
  if (node_opcua_nodeid_1.NodeId.sameNodeId(node_opcua_nodeid_1.NodeId.nullNodeId, field.dataType)) {
1125
- debugLog("field.dataType is null ! " + field.name + " " + ((_c = field.description) === null || _c === void 0 ? void 0 : _c.text));
1126
- debugLog(" dataType replaced with BaseDataType ");
1182
+ warningLog("field.dataType is null ! ", field.toString(), node_opcua_nodeid_1.NodeId.nullNodeId.toString());
1183
+ warningLog(" dataType replaced with BaseDataType ");
1184
+ warningLog(definition.toString());
1127
1185
  field.dataType = this.resolveNodeId("BaseDataType");
1128
1186
  }
1129
- const dataTypeNodeId = addressSpace.findCorrespondingBasicDataType(field.dataType);
1187
+ const camelCaseName = (0, node_opcua_utils_1.lowerFirstLetter)(field.name);
1130
1188
  (0, node_opcua_assert_1.assert)(Object.prototype.hasOwnProperty.call(this.$extensionObject, camelCaseName));
1189
+ const propertyNode = getOrCreateProperty(field);
1190
+ propertyNode.$dataValue.statusCode = node_opcua_status_code_1.StatusCodes.Good;
1191
+ propertyNode.touchValue();
1192
+ const basicDataType = addressSpace.findCorrespondingBasicDataType(field.dataType);
1131
1193
  // istanbul ignore next
1132
1194
  if (doDebug) {
1133
1195
  const x = addressSpace.findNode(field.dataType).browseName.toString();
1134
- const basicType = addressSpace.findCorrespondingBasicDataType(field.dataType);
1135
- debugLog(chalk.cyan("xxx"), " dataType", w(field.dataType.toString(), 8), w(field.name, 35), "valueRank", chalk.cyan(w((0, base_node_private_1.valueRankToString)(field.valueRank), 10)), chalk.green(w(x, 25)), "basicType = ", chalk.yellow(w(basicType.toString(), 20)), property.nodeId.toString(), property.readValue().statusCode.toString());
1196
+ debugLog(chalk.cyan("xxx"), " dataType", w(field.dataType.toString(), 8), w(field.name, 35), "valueRank", chalk.cyan(w((0, base_node_private_1.valueRankToString)(field.valueRank), 10)), chalk.green(w(x, 25)), "basicType = ", chalk.yellow(w(basicDataType.toString(), 20)), propertyNode.nodeId.toString(), propertyNode.readValue().statusCode.toString());
1136
1197
  }
1137
- if (this.$extensionObject[camelCaseName] !== undefined && dataTypeNodeId === node_opcua_variant_1.DataType.ExtensionObject) {
1198
+ if (this.$extensionObject[camelCaseName] !== undefined && basicDataType === node_opcua_variant_1.DataType.ExtensionObject) {
1138
1199
  (0, node_opcua_assert_1.assert)(this.$extensionObject[camelCaseName] instanceof Object);
1139
- this.$extensionObject[camelCaseName] = new Proxy(this.$extensionObject[camelCaseName], makeHandler(property));
1140
- property._dataValue.value = new node_opcua_variant_1.Variant({
1200
+ this.$extensionObject[camelCaseName] = new Proxy(this.$extensionObject[camelCaseName], makeHandler(propertyNode));
1201
+ propertyNode._internal_set_value(new node_opcua_variant_1.Variant({
1141
1202
  dataType: node_opcua_variant_1.DataType.ExtensionObject,
1142
1203
  value: this.$extensionObject[camelCaseName]
1143
- });
1144
- property.bindExtensionObject();
1145
- property.$extensionObject = this.$extensionObject[camelCaseName];
1204
+ }));
1205
+ propertyNode.bindExtensionObject();
1206
+ propertyNode.$extensionObject = this.$extensionObject[camelCaseName];
1146
1207
  }
1147
1208
  else {
1148
- const dataTypeAsString = node_opcua_variant_1.DataType[dataTypeNodeId];
1149
- (0, node_opcua_assert_1.assert)(typeof dataTypeAsString === "string");
1150
1209
  const prop = this.$extensionObject[camelCaseName];
1151
1210
  if (prop === undefined) {
1152
- property._dataValue.value = new node_opcua_variant_1.Variant({
1211
+ propertyNode._internal_set_value(new node_opcua_variant_1.Variant({
1153
1212
  dataType: node_opcua_variant_1.DataType.Null
1154
- });
1213
+ }));
1155
1214
  }
1156
1215
  else {
1157
- const preparedValue = prepareVariantValue(dataTypeNodeId, prop);
1158
- property._dataValue.value = new node_opcua_variant_1.Variant({
1159
- dataType: dataTypeAsString,
1216
+ const preparedValue = prepareVariantValue(basicDataType, prop);
1217
+ propertyNode._internal_set_value(new node_opcua_variant_1.Variant({
1218
+ dataType: basicDataType,
1160
1219
  value: preparedValue
1161
- });
1220
+ }));
1162
1221
  }
1163
1222
  // eslint-disable-next-line @typescript-eslint/no-this-alias
1164
1223
  const self = this;
1165
- property.camelCaseName = camelCaseName;
1166
- property.setValueFromSource = function (variant) {
1224
+ // property.camelCaseName = camelCaseName;
1225
+ propertyNode.setValueFromSource = function (variant) {
1167
1226
  // eslint-disable-next-line @typescript-eslint/no-this-alias
1168
1227
  const inner_this = this;
1169
- variant = node_opcua_variant_1.Variant.coerce(variant);
1170
- // xx console.log("PropertySetValueFromSource this", inner_this.nodeId.toString(), inner_this.browseName.toString(), variant.toString(), inner_this.dataType.toString());
1171
- // xx assert(variant.dataType === this.dataType);
1172
- self.$extensionObject[inner_this.camelCaseName] = variant.value;
1228
+ const variant1 = node_opcua_variant_1.Variant.coerce(variant);
1229
+ inner_this.verifyVariantCompatibility(variant1);
1230
+ self.$extensionObject[camelCaseName] = variant1.value;
1173
1231
  self.touchValue();
1174
1232
  };
1175
1233
  }
1176
- (0, node_opcua_assert_1.assert)(property.readValue().statusCode.equals(node_opcua_status_code_1.StatusCodes.Good));
1177
- bindProperty(property, camelCaseName, this.$extensionObject, dataTypeNodeId);
1234
+ (0, node_opcua_assert_1.assert)(propertyNode.readValue().statusCode.equals(node_opcua_status_code_1.StatusCodes.Good));
1235
+ bindProperty(propertyNode, camelCaseName, this.$extensionObject, basicDataType);
1178
1236
  }
1179
1237
  (0, node_opcua_assert_1.assert)(this.$extensionObject instanceof Object);
1180
1238
  return this.$extensionObject;
@@ -1211,7 +1269,6 @@ class UAVariableImpl extends base_node_impl_1.BaseNodeImpl {
1211
1269
  name = path[path.length - 1];
1212
1270
  c1[name] = c2[name];
1213
1271
  c1[name] += 1;
1214
- // xx console.log(partialData);
1215
1272
  setExtensionObjectValue(this, partialData);
1216
1273
  }
1217
1274
  constructExtensionObjectFromComponents() {
@@ -1261,10 +1318,16 @@ class UAVariableImpl extends base_node_impl_1.BaseNodeImpl {
1261
1318
  _validate_DataType(variantDataType) {
1262
1319
  return validateDataType(this.addressSpace, this.dataType, variantDataType, this.nodeId, /* allow Nulls */ false);
1263
1320
  }
1321
+ _internal_set_value(value) {
1322
+ if (value.dataType !== node_opcua_variant_1.DataType.Null) {
1323
+ this.verifyVariantCompatibility(value);
1324
+ }
1325
+ this.$dataValue.value = value;
1326
+ }
1264
1327
  _internal_set_dataValue(dataValue, indexRange) {
1265
1328
  (0, node_opcua_assert_1.assert)(dataValue, "expecting a dataValue");
1266
1329
  (0, node_opcua_assert_1.assert)(dataValue instanceof node_opcua_data_value_1.DataValue, "expecting dataValue to be a DataValue");
1267
- (0, node_opcua_assert_1.assert)(dataValue !== this._dataValue, "expecting dataValue to be different from previous DataValue instance");
1330
+ (0, node_opcua_assert_1.assert)(dataValue !== this.$dataValue, "expecting dataValue to be different from previous DataValue instance");
1268
1331
  if (dataValue.value.arrayType === node_opcua_variant_1.VariantArrayType.Matrix) {
1269
1332
  if (!dataValue.value.dimensions) {
1270
1333
  throw new Error("missing dimensions: a Matrix Variant needs a dimension");
@@ -1283,23 +1346,26 @@ class UAVariableImpl extends base_node_impl_1.BaseNodeImpl {
1283
1346
  // istanbul ignore next
1284
1347
  if (this.dataType.namespace === 0) {
1285
1348
  if (this.dataType.value === node_opcua_variant_1.DataType.LocalizedText && dataValue.value.dataType !== node_opcua_variant_1.DataType.LocalizedText) {
1286
- throw new Error("Invalid dataValue provided (expecting a LocalizedText) but got " + dataValue.toString());
1349
+ const message = "Invalid dataValue provided (expecting a LocalizedText) but got " + dataValue.toString();
1350
+ errorLog(message);
1351
+ throw new Error(message);
1287
1352
  }
1288
1353
  }
1289
- const old_dataValue = this._dataValue;
1290
- this._dataValue = dataValue;
1291
- this._dataValue.statusCode = this._dataValue.statusCode || node_opcua_status_code_1.StatusCodes.Good;
1354
+ this.verifyVariantCompatibility(dataValue.value);
1355
+ const old_dataValue = this.$dataValue;
1356
+ this.$dataValue = dataValue;
1357
+ this.$dataValue.statusCode = this.$dataValue.statusCode || node_opcua_status_code_1.StatusCodes.Good;
1292
1358
  // repair missing timestamps
1293
1359
  if (!dataValue.serverTimestamp) {
1294
- this._dataValue.serverTimestamp = old_dataValue.serverTimestamp;
1295
- this._dataValue.serverPicoseconds = old_dataValue.serverPicoseconds;
1360
+ this.$dataValue.serverTimestamp = old_dataValue.serverTimestamp;
1361
+ this.$dataValue.serverPicoseconds = old_dataValue.serverPicoseconds;
1296
1362
  }
1297
1363
  if (!dataValue.sourceTimestamp) {
1298
- this._dataValue.sourceTimestamp = old_dataValue.sourceTimestamp;
1299
- this._dataValue.sourcePicoseconds = old_dataValue.sourcePicoseconds;
1364
+ this.$dataValue.sourceTimestamp = old_dataValue.sourceTimestamp;
1365
+ this.$dataValue.sourcePicoseconds = old_dataValue.sourcePicoseconds;
1300
1366
  }
1301
1367
  if (!(0, node_opcua_data_value_1.sameDataValue)(old_dataValue, dataValue)) {
1302
- this.emit("value_changed", this._dataValue, indexRange);
1368
+ this.emit("value_changed", this.$dataValue, indexRange);
1303
1369
  }
1304
1370
  }
1305
1371
  _conditionRefresh(_cache) {
@@ -1467,7 +1533,7 @@ function _calculateEffectiveUserAccessLevelFromPermission(node, context, userAcc
1467
1533
  function adjustVariant2(variant) {
1468
1534
  // convert Variant( Scalar|ByteString) => Variant(Array|ByteArray)
1469
1535
  const addressSpace = this.addressSpace;
1470
- const basicType = addressSpace.findCorrespondingBasicDataType(this.dataType);
1536
+ const basicType = this.getBasicDataType();
1471
1537
  variant = (0, node_opcua_variant_1.adjustVariant)(variant, this.valueRank, basicType);
1472
1538
  return variant;
1473
1539
  }
@@ -1476,7 +1542,6 @@ function _not_writable_timestamped_set_func(dataValue, callback) {
1476
1542
  callback(null, node_opcua_status_code_1.StatusCodes.BadNotWritable, null);
1477
1543
  }
1478
1544
  function _default_writable_timestamped_set_func(dataValue, callback) {
1479
- /* jshint validthis: true */
1480
1545
  (0, node_opcua_assert_1.assert)(dataValue instanceof node_opcua_data_value_1.DataValue);
1481
1546
  callback(null, node_opcua_status_code_1.StatusCodes.Good, dataValue);
1482
1547
  }
@@ -1511,7 +1576,7 @@ function _Variable_bind_with_async_refresh(options) {
1511
1576
  (0, node_opcua_assert_1.assert)(!this.refreshFunc);
1512
1577
  this.refreshFunc = options.refreshFunc;
1513
1578
  // assert(this.readValue().statusCode === StatusCodes.BadNodeIdUnknown);
1514
- this._dataValue.statusCode = node_opcua_status_code_1.StatusCodes.UncertainInitialValue;
1579
+ this.$dataValue.statusCode = node_opcua_status_code_1.StatusCodes.UncertainInitialValue;
1515
1580
  // TO DO : REVISIT THIS ASSUMPTION
1516
1581
  if (false && this.minimumSamplingInterval === 0) {
1517
1582
  // when a getter /timestamped_getter or async_getter is provided
@@ -1530,13 +1595,17 @@ function _Variable_bind_with_timestamped_get(options) {
1530
1595
  const async_refresh_func = (callback) => {
1531
1596
  Promise.resolve(this._timestamped_get_func.call(this))
1532
1597
  .then((dataValue) => callback(null, dataValue))
1533
- .catch((err) => callback(err));
1598
+ .catch((err) => {
1599
+ errorLog("asyncRefresh error: Variable is ", this.nodeId.toString(), this.browseName.toString());
1600
+ callback(err);
1601
+ });
1534
1602
  };
1603
+ const pThis = this;
1535
1604
  if (options.timestamped_get.length === 0) {
1536
1605
  const timestamped_get = options.timestamped_get;
1537
1606
  // sync version | Promise version
1538
1607
  this._timestamped_get_func = timestamped_get;
1539
- const dataValue_verify = timestamped_get.call(this);
1608
+ const dataValue_verify = timestamped_get.call(pThis);
1540
1609
  // dataValue_verify should be a DataValue or a Promise
1541
1610
  /* istanbul ignore next */
1542
1611
  if (!(dataValue_verify instanceof node_opcua_data_value_1.DataValue) && typeof dataValue_verify.then !== "function") {
@@ -1575,16 +1644,14 @@ function _Variable_bind_with_simple_get(options) {
1575
1644
  return new node_opcua_data_value_1.DataValue({ statusCode: value });
1576
1645
  }
1577
1646
  else {
1578
- if (!this._dataValue || !isGoodish(this._dataValue.statusCode) || !(0, node_opcua_variant_1.sameVariant)(this._dataValue.value, value)) {
1647
+ if (!this.$dataValue || !isGoodish(this.$dataValue.statusCode) || !(0, node_opcua_variant_1.sameVariant)(this.$dataValue.value, value)) {
1579
1648
  this.setValueFromSource(value, node_opcua_status_code_1.StatusCodes.Good);
1580
1649
  }
1581
- else {
1582
- // XX console.log("YYYYYYYYYYYYYYYYYYYYYYYYYY",this.browseName.toString());
1583
- }
1584
- return this._dataValue;
1650
+ return this.$dataValue;
1585
1651
  }
1586
1652
  };
1587
1653
  _Variable_bind_with_timestamped_get.call(this, {
1654
+ get: undefined,
1588
1655
  timestamped_get: timestamped_get_func_from__Variable_bind_with_simple_get
1589
1656
  });
1590
1657
  }
@@ -1596,12 +1663,13 @@ function _Variable_bind_with_simple_set(options) {
1596
1663
  (0, node_opcua_assert_1.assert)(!this._set_func);
1597
1664
  this._set_func = turn_sync_to_async(options.set, 1);
1598
1665
  (0, node_opcua_assert_1.assert)(this._set_func.length === 2, " set function must have 2 arguments ( variant, callback)");
1599
- this._timestamped_set_func = (timestamped_value, indexRange, callback) => {
1666
+ this._timestamped_set_func = (timestamped_value, callback) => {
1600
1667
  (0, node_opcua_assert_1.assert)(timestamped_value instanceof node_opcua_data_value_1.DataValue);
1601
1668
  this._set_func(timestamped_value.value, (err, statusCode) => {
1669
+ // istanbul ignore next
1602
1670
  if (!err && !statusCode) {
1603
- console.log(chalk.red("UAVariable Binding Error _set_func must return a StatusCode, check the bindVariable parameters"));
1604
- console.log(chalk.yellow("StatusCode.Good is assumed"));
1671
+ errorLog(chalk.red("UAVariable Binding Error _set_func must return a StatusCode, check the bindVariable parameters"));
1672
+ errorLog(chalk.yellow("StatusCode.Good is assumed"));
1605
1673
  return callback(err, node_opcua_status_code_1.StatusCodes.Good, timestamped_value);
1606
1674
  }
1607
1675
  callback(err, statusCode, timestamped_value);
@@ -1609,14 +1677,10 @@ function _Variable_bind_with_simple_set(options) {
1609
1677
  };
1610
1678
  }
1611
1679
  function _Variable_bind_with_timestamped_set(options) {
1612
- (0, node_opcua_assert_1.assert)(this instanceof UAVariableImpl);
1613
1680
  (0, node_opcua_assert_1.assert)(typeof options.timestamped_set === "function");
1614
1681
  (0, node_opcua_assert_1.assert)(options.timestamped_set.length === 2, "timestamped_set must have 2 parameters timestamped_set: function(dataValue,callback){}");
1615
1682
  (0, node_opcua_assert_1.assert)(!options.set, "should not specify set when timestamped_set_func exists ");
1616
- this._timestamped_set_func = (dataValue, indexRange, callback) => {
1617
- // xx assert(!indexRange,"indexRange Not Implemented");
1618
- return options.timestamped_set.call(this, dataValue, callback);
1619
- };
1683
+ this._timestamped_set_func = (0, multiform_func_1.convertToCallbackFunction1)(options.timestamped_set);
1620
1684
  }
1621
1685
  function bind_setter(options) {
1622
1686
  if (typeof options.set === "function") {
@@ -1626,17 +1690,22 @@ function bind_setter(options) {
1626
1690
  else if (typeof options.timestamped_set === "function") {
1627
1691
  // variation 2
1628
1692
  (0, node_opcua_assert_1.assert)(typeof options.timestamped_get === "function", "timestamped_set must be used with timestamped_get ");
1629
- _Variable_bind_with_timestamped_set.call(this, options);
1693
+ _Variable_bind_with_timestamped_set.call(this, {
1694
+ set: undefined,
1695
+ timestamped_set: options.timestamped_set
1696
+ });
1630
1697
  }
1631
1698
  else if (typeof options.timestamped_get === "function") {
1632
1699
  // timestamped_get is specified but timestamped_set is not
1633
1700
  // => Value is read-only
1634
1701
  _Variable_bind_with_timestamped_set.call(this, {
1702
+ set: undefined,
1635
1703
  timestamped_set: _not_writable_timestamped_set_func
1636
1704
  });
1637
1705
  }
1638
1706
  else {
1639
1707
  _Variable_bind_with_timestamped_set.call(this, {
1708
+ set: undefined,
1640
1709
  timestamped_set: _default_writable_timestamped_set_func
1641
1710
  });
1642
1711
  }
@@ -1648,7 +1717,10 @@ function bind_getter(options) {
1648
1717
  }
1649
1718
  else if (typeof options.timestamped_get === "function") {
1650
1719
  // variation 2
1651
- _Variable_bind_with_timestamped_get.call(this, options);
1720
+ _Variable_bind_with_timestamped_get.call(this, {
1721
+ get: undefined,
1722
+ timestamped_get: options.timestamped_get
1723
+ });
1652
1724
  }
1653
1725
  else if (typeof options.refreshFunc === "function") {
1654
1726
  // variation 3