node-opcua-address-space 2.57.0 → 2.61.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/source/address_space_ts.d.ts +0 -2
- package/dist/source/helpers/argument_list.js +12 -1
- package/dist/source/helpers/argument_list.js.map +1 -1
- package/dist/source/helpers/multiform_func.d.ts +11 -0
- package/dist/source/helpers/multiform_func.js +74 -0
- package/dist/source/helpers/multiform_func.js.map +1 -0
- package/dist/source/loader/load_nodeset2.js +47 -64
- package/dist/source/loader/load_nodeset2.js.map +1 -1
- package/dist/source/set_namespace_meta_data.js +1 -1
- package/dist/src/address_space.js +12 -6
- package/dist/src/address_space.js.map +1 -1
- package/dist/src/alarms_and_conditions/condition_snapshot.js +3 -3
- package/dist/src/alarms_and_conditions/condition_snapshot.js.map +1 -1
- package/dist/src/alarms_and_conditions/ua_acknowledgeable_condition_impl.js +2 -1
- package/dist/src/alarms_and_conditions/ua_acknowledgeable_condition_impl.js.map +1 -1
- package/dist/src/alarms_and_conditions/ua_alarm_condition_impl.js +1 -1
- package/dist/src/alarms_and_conditions/ua_alarm_condition_impl.js.map +1 -1
- package/dist/src/alarms_and_conditions/ua_condition_impl.js +8 -6
- package/dist/src/alarms_and_conditions/ua_condition_impl.js.map +1 -1
- package/dist/src/alarms_and_conditions/ua_off_normal_alarm_impl.js +1 -1
- package/dist/src/alarms_and_conditions/ua_off_normal_alarm_impl.js.map +1 -1
- package/dist/src/base_node_impl.js +2 -0
- package/dist/src/base_node_impl.js.map +1 -1
- package/dist/src/base_node_private.d.ts +3 -3
- package/dist/src/base_node_private.js +198 -25
- package/dist/src/base_node_private.js.map +1 -1
- package/dist/src/event_data.js +1 -1
- package/dist/src/event_data.js.map +1 -1
- package/dist/src/namespace_impl.js +5 -5
- package/dist/src/namespace_impl.js.map +1 -1
- package/dist/src/nodeset_tools/nodeset_to_xml.js +15 -9
- package/dist/src/nodeset_tools/nodeset_to_xml.js.map +1 -1
- package/dist/src/nodeset_tools/typedictionary_to_xml.js +17 -10
- package/dist/src/nodeset_tools/typedictionary_to_xml.js.map +1 -1
- package/dist/src/reference_impl.js +1 -1
- package/dist/src/reference_impl.js.map +1 -1
- package/dist/src/state_machine/ua_shelving_state_machine_ex.js +20 -13
- package/dist/src/state_machine/ua_shelving_state_machine_ex.js.map +1 -1
- package/dist/src/ua_data_type_impl.d.ts +15 -5
- package/dist/src/ua_data_type_impl.js +129 -51
- package/dist/src/ua_data_type_impl.js.map +1 -1
- package/dist/src/ua_method_impl.d.ts +3 -2
- package/dist/src/ua_method_impl.js +7 -1
- package/dist/src/ua_method_impl.js.map +1 -1
- package/dist/src/ua_object_impl.js +2 -1
- package/dist/src/ua_object_impl.js.map +1 -1
- package/dist/src/ua_variable_impl.d.ts +12 -18
- package/dist/src/ua_variable_impl.js +285 -215
- package/dist/src/ua_variable_impl.js.map +1 -1
- package/dist/src/ua_variable_type_impl.d.ts +3 -4
- package/dist/src/ua_variable_type_impl.js +60 -52
- package/dist/src/ua_variable_type_impl.js.map +1 -1
- package/dist/src/ua_view_impl.js +1 -1
- package/dist/src/ua_view_impl.js.map +1 -1
- package/distHelpers/add_event_generator_object.js.map +1 -1
- package/distHelpers/mock_session.js +1 -1
- package/distHelpers/mock_session.js.map +1 -1
- package/package.json +35 -35
- package/source/address_space_ts.ts +0 -1
- package/source/helpers/argument_list.ts +13 -3
- package/source/helpers/multiform_func.ts +76 -0
- package/source/loader/load_nodeset2.ts +64 -80
- package/source/set_namespace_meta_data.ts +1 -1
- package/src/address_space.ts +16 -7
- package/src/alarms_and_conditions/condition_snapshot.ts +4 -4
- package/src/alarms_and_conditions/ua_acknowledgeable_condition_impl.ts +7 -6
- package/src/alarms_and_conditions/ua_alarm_condition_impl.ts +2 -2
- package/src/alarms_and_conditions/ua_condition_impl.ts +29 -15
- package/src/alarms_and_conditions/ua_off_normal_alarm_impl.ts +1 -1
- package/src/base_node_impl.ts +3 -1
- package/src/base_node_private.ts +282 -36
- package/src/event_data.ts +1 -1
- package/src/namespace_impl.ts +6 -6
- package/src/nodeset_tools/nodeset_to_xml.ts +20 -10
- package/src/nodeset_tools/typedictionary_to_xml.ts +17 -7
- package/src/reference_impl.ts +3 -3
- package/src/state_machine/ua_shelving_state_machine_ex.ts +32 -19
- package/src/ua_data_type_impl.ts +168 -61
- package/src/ua_method_impl.ts +21 -7
- package/src/ua_object_impl.ts +10 -2
- package/src/ua_variable_impl.ts +419 -325
- package/src/ua_variable_type_impl.ts +86 -52
- package/src/ua_view_impl.ts +1 -1
- package/test_helpers/add_event_generator_object.ts +4 -3
- package/test_helpers/mock_session.ts +1 -1
- package/test_helpers/test_fixtures/fixture_simple_statemachine_nodeset2.xml +18 -0
- package/test_helpers/test_fixtures/fixuture_nodeset_objects_with_some_methods.xml +9 -1
- package/test_helpers/test_fixtures/mini.Node.Set2.xml +22 -1
package/src/ua_variable_impl.ts
CHANGED
|
@@ -8,7 +8,19 @@
|
|
|
8
8
|
// tslint:disable:max-line-length
|
|
9
9
|
import * as chalk from "chalk";
|
|
10
10
|
|
|
11
|
-
import {
|
|
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,
|
|
@@ -37,17 +49,25 @@ import {
|
|
|
37
49
|
ReadProcessedDetails,
|
|
38
50
|
ReadRawModifiedDetails,
|
|
39
51
|
StructureDefinition,
|
|
52
|
+
StructureField,
|
|
40
53
|
WriteValueOptions
|
|
41
54
|
} from "node-opcua-types";
|
|
42
55
|
import * as utils from "node-opcua-utils";
|
|
43
56
|
import { lowerFirstLetter } from "node-opcua-utils";
|
|
44
|
-
import {
|
|
57
|
+
import {
|
|
58
|
+
Variant,
|
|
59
|
+
VariantLike,
|
|
60
|
+
DataType,
|
|
61
|
+
sameVariant,
|
|
62
|
+
VariantArrayType,
|
|
63
|
+
adjustVariant,
|
|
64
|
+
verifyRankAndDimensions
|
|
65
|
+
} from "node-opcua-variant";
|
|
45
66
|
import { StatusCodeCallback } from "node-opcua-status-code";
|
|
46
67
|
import {
|
|
47
68
|
IAddressSpace,
|
|
48
69
|
BindVariableOptions,
|
|
49
70
|
ContinuationPoint,
|
|
50
|
-
DataValueCallback,
|
|
51
71
|
IVariableHistorian,
|
|
52
72
|
TimestampGetFunc,
|
|
53
73
|
TimestampSetFunc,
|
|
@@ -56,7 +76,6 @@ import {
|
|
|
56
76
|
UAVariableType,
|
|
57
77
|
CloneOptions,
|
|
58
78
|
CloneFilter,
|
|
59
|
-
CloneExtraInfo,
|
|
60
79
|
ISessionContext,
|
|
61
80
|
BaseNode,
|
|
62
81
|
UAVariableT
|
|
@@ -64,6 +83,7 @@ import {
|
|
|
64
83
|
import { UAHistoricalDataConfiguration } from "node-opcua-nodeset-ua";
|
|
65
84
|
|
|
66
85
|
import { SessionContext } from "../source/session_context";
|
|
86
|
+
import { convertToCallbackFunction1 } from "../source/helpers/multiform_func";
|
|
67
87
|
import { BaseNodeImpl, InternalBaseNodeOptions } from "./base_node_impl";
|
|
68
88
|
import { _clone, ToStringBuilder, UAVariable_toString, valueRankToString } from "./base_node_private";
|
|
69
89
|
import { EnumerationInfo, IEnumItem, UADataTypeImpl } from "./ua_data_type_impl";
|
|
@@ -162,16 +182,16 @@ function validateDataType(
|
|
|
162
182
|
if (variantDataType === DataType.Null && !allowNulls) {
|
|
163
183
|
return false;
|
|
164
184
|
}
|
|
165
|
-
let builtInType:
|
|
185
|
+
let builtInType: DataType;
|
|
166
186
|
let builtInUADataType: UADataType;
|
|
167
187
|
|
|
168
|
-
const destUADataType = addressSpace.
|
|
188
|
+
const destUADataType = addressSpace.findDataType(dataTypeNodeId)!;
|
|
169
189
|
assert(destUADataType instanceof UADataTypeImpl);
|
|
170
190
|
|
|
171
191
|
if (destUADataType.isAbstract || destUADataType.nodeId.namespace !== 0) {
|
|
172
192
|
builtInUADataType = destUADataType;
|
|
173
193
|
} else {
|
|
174
|
-
builtInType =
|
|
194
|
+
builtInType = addressSpace.findCorrespondingBasicDataType(destUADataType);
|
|
175
195
|
builtInUADataType = addressSpace.findDataType(builtInType)!;
|
|
176
196
|
}
|
|
177
197
|
assert(builtInUADataType instanceof UADataTypeImpl);
|
|
@@ -183,8 +203,8 @@ function validateDataType(
|
|
|
183
203
|
if (destUADataType.isSupertypeOf(enumerationUADataType)) {
|
|
184
204
|
// istanbul ignore next
|
|
185
205
|
if (doDebug) {
|
|
186
|
-
|
|
187
|
-
|
|
206
|
+
debugLog("destUADataType.", destUADataType.browseName.toString(), destUADataType.nodeId.toString());
|
|
207
|
+
debugLog(
|
|
188
208
|
"enumerationUADataType.",
|
|
189
209
|
enumerationUADataType.browseName.toString(),
|
|
190
210
|
enumerationUADataType.nodeId.toString()
|
|
@@ -203,19 +223,23 @@ function validateDataType(
|
|
|
203
223
|
if (doDebug) {
|
|
204
224
|
if (dest_isSuperTypeOf_variant) {
|
|
205
225
|
/* istanbul ignore next*/
|
|
206
|
-
|
|
226
|
+
debugLog(chalk.green(" ---------- Type match !!! "), " on ", nodeId.toString());
|
|
207
227
|
} else {
|
|
208
228
|
/* istanbul ignore next*/
|
|
209
|
-
|
|
229
|
+
debugLog(chalk.red(" ---------- Type mismatch "), " on ", nodeId.toString());
|
|
210
230
|
}
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
231
|
+
debugLog(chalk.cyan(" Variable data Type is = "), destUADataType.browseName.toString());
|
|
232
|
+
debugLog(chalk.cyan(" which matches basic Type = "), builtInUADataType.browseName.toString());
|
|
233
|
+
debugLog(chalk.yellow(" Actual dataType = "), variantUADataType.browseName.toString());
|
|
214
234
|
}
|
|
215
235
|
|
|
216
236
|
return dest_isSuperTypeOf_variant;
|
|
217
237
|
}
|
|
218
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
|
+
|
|
219
243
|
interface UAVariableOptions extends InternalBaseNodeOptions {
|
|
220
244
|
value?: any;
|
|
221
245
|
dataType: NodeId | string;
|
|
@@ -227,50 +251,6 @@ interface UAVariableOptions extends InternalBaseNodeOptions {
|
|
|
227
251
|
historizing?: number;
|
|
228
252
|
}
|
|
229
253
|
|
|
230
|
-
export function verifyRankAndDimensions(options: { valueRank?: number; arrayDimensions?: number[] | null }): void {
|
|
231
|
-
// evaluate valueRank arrayDimensions is specified but valueRank is null
|
|
232
|
-
if (options.arrayDimensions && options.valueRank === undefined) {
|
|
233
|
-
options.valueRank = options.arrayDimensions.length;
|
|
234
|
-
}
|
|
235
|
-
options.valueRank = options.valueRank === undefined ? -1 : options.valueRank || 0; // UInt32
|
|
236
|
-
assert(typeof options.valueRank === "number");
|
|
237
|
-
|
|
238
|
-
options.arrayDimensions = options.arrayDimensions || null;
|
|
239
|
-
assert(options.arrayDimensions === null || Array.isArray(options.arrayDimensions));
|
|
240
|
-
|
|
241
|
-
if (options.arrayDimensions && options.valueRank <= 0) {
|
|
242
|
-
throw new Error("[CONFORMANCE] arrayDimensions must be null if valueRank <=0");
|
|
243
|
-
}
|
|
244
|
-
// specify default arrayDimension if not provided
|
|
245
|
-
if (options.valueRank > 0 && !options.arrayDimensions) {
|
|
246
|
-
options.arrayDimensions = new Array(options.valueRank).fill(0);
|
|
247
|
-
}
|
|
248
|
-
if (!options.arrayDimensions && options.valueRank > 0) {
|
|
249
|
-
throw new Error("[CONFORMANCE] arrayDimension must be specified if valueRank >0 " + options.valueRank);
|
|
250
|
-
}
|
|
251
|
-
if (options.valueRank > 0 && options.arrayDimensions!.length !== options.valueRank) {
|
|
252
|
-
throw new Error(
|
|
253
|
-
"[CONFORMANCE] when valueRank> 0, arrayDimensions must have valueRank elements, this.valueRank =" +
|
|
254
|
-
options.valueRank +
|
|
255
|
-
" whereas arrayDimensions.length =" +
|
|
256
|
-
options.arrayDimensions!.length
|
|
257
|
-
);
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
type TimestampGetFunction1 = () => DataValue | Promise<DataValue>;
|
|
262
|
-
type TimestampGetFunction2 = (callback: (err: Error | null, dataValue?: DataValue) => void) => void;
|
|
263
|
-
type TimestampGetFunction = TimestampGetFunction1 | TimestampGetFunction2;
|
|
264
|
-
|
|
265
|
-
type TimestampSetFunction1 = (this: UAVariable, dataValue: DataValue, indexRange: NumericRange) => void | Promise<void>;
|
|
266
|
-
type TimestampSetFunction2 = (
|
|
267
|
-
this: UAVariable,
|
|
268
|
-
dataValue: DataValue,
|
|
269
|
-
indexRange: NumericRange,
|
|
270
|
-
callback: (err: Error | null, StatusCode: StatusCode) => void
|
|
271
|
-
) => void;
|
|
272
|
-
type TimestampSetFunction = TimestampSetFunction1 | TimestampSetFunction2;
|
|
273
|
-
|
|
274
254
|
/**
|
|
275
255
|
* A OPCUA Variable Node
|
|
276
256
|
*
|
|
@@ -299,7 +279,9 @@ type TimestampSetFunction = TimestampSetFunction1 | TimestampSetFunction2;
|
|
|
299
279
|
*/
|
|
300
280
|
export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
301
281
|
public readonly nodeClass = NodeClass.Variable;
|
|
282
|
+
|
|
302
283
|
public dataType: NodeId;
|
|
284
|
+
private _basicDataType?: DataType;
|
|
303
285
|
|
|
304
286
|
public $extensionObject?: any;
|
|
305
287
|
|
|
@@ -307,9 +289,9 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
307
289
|
public varHistorian?: IVariableHistorian;
|
|
308
290
|
|
|
309
291
|
/**
|
|
310
|
-
* @internal
|
|
292
|
+
* @internal @private
|
|
311
293
|
*/
|
|
312
|
-
public
|
|
294
|
+
public $dataValue: DataValue;
|
|
313
295
|
public accessLevel: number;
|
|
314
296
|
public userAccessLevel?: number;
|
|
315
297
|
public valueRank: number;
|
|
@@ -318,11 +300,11 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
318
300
|
public semantic_version: number;
|
|
319
301
|
public arrayDimensions: null | number[];
|
|
320
302
|
|
|
321
|
-
public _timestamped_get_func?:
|
|
322
|
-
public _timestamped_set_func?:
|
|
303
|
+
public _timestamped_get_func?: TimestampGetFunc | null;
|
|
304
|
+
public _timestamped_set_func?: VariableDataValueSetterWithCallback | null;
|
|
323
305
|
public _get_func: any;
|
|
324
306
|
public _set_func: any;
|
|
325
|
-
public refreshFunc?: (callback:
|
|
307
|
+
public refreshFunc?: (callback: CallbackT<DataValue>) => void;
|
|
326
308
|
public __waiting_callbacks?: any[];
|
|
327
309
|
|
|
328
310
|
get typeDefinitionObj(): UAVariableType {
|
|
@@ -346,11 +328,9 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
346
328
|
|
|
347
329
|
this.minimumSamplingInterval = adjust_samplingInterval(options.minimumSamplingInterval || 0);
|
|
348
330
|
|
|
349
|
-
this.historizing = !!options.historizing; // coerced to boolean
|
|
331
|
+
this.historizing = !!options.historizing; // coerced to boolean"
|
|
350
332
|
|
|
351
|
-
this
|
|
352
|
-
|
|
353
|
-
// xx options.value = options.value || { dataType: DataType.Null };
|
|
333
|
+
this.$dataValue = new DataValue({ statusCode: StatusCodes.UncertainInitialValue, value: { dataType: DataType.Null } });
|
|
354
334
|
|
|
355
335
|
if (options.value) {
|
|
356
336
|
this.bindVariable(options.value);
|
|
@@ -453,11 +433,17 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
453
433
|
|
|
454
434
|
if (this._timestamped_get_func) {
|
|
455
435
|
if (this._timestamped_get_func.length === 0) {
|
|
456
|
-
|
|
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
|
+
}
|
|
457
443
|
}
|
|
458
444
|
}
|
|
459
445
|
|
|
460
|
-
let dataValue = this
|
|
446
|
+
let dataValue = this.$dataValue;
|
|
461
447
|
|
|
462
448
|
if (isGoodish(dataValue.statusCode)) {
|
|
463
449
|
// note : extractRange will clone the dataValue
|
|
@@ -504,12 +490,14 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
504
490
|
return dataTypeNode._getEnumerationInfo();
|
|
505
491
|
}
|
|
506
492
|
|
|
507
|
-
public asyncRefresh(oldestDate: Date, callback:
|
|
493
|
+
public asyncRefresh(oldestDate: Date, callback: CallbackT<DataValue>): void;
|
|
508
494
|
public asyncRefresh(oldestDate: Date): Promise<DataValue>;
|
|
509
495
|
public asyncRefresh(...args: any[]): any {
|
|
496
|
+
this.verifyVariantCompatibility(this.$dataValue.value);
|
|
497
|
+
|
|
510
498
|
const oldestDate = args[0] as Date;
|
|
511
499
|
assert(oldestDate instanceof Date);
|
|
512
|
-
const callback = args[1] as
|
|
500
|
+
const callback = args[1] as CallbackT<DataValue>;
|
|
513
501
|
|
|
514
502
|
if (!this.refreshFunc) {
|
|
515
503
|
// no refresh func
|
|
@@ -524,22 +512,36 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
524
512
|
}
|
|
525
513
|
}
|
|
526
514
|
|
|
527
|
-
if (this.
|
|
515
|
+
if (this.$dataValue.serverTimestamp && oldestDate.getTime() <= this.$dataValue.serverTimestamp!.getTime()) {
|
|
528
516
|
const dataValue = this.readValue();
|
|
529
517
|
dataValue.serverTimestamp = oldestDate;
|
|
530
518
|
dataValue.serverPicoseconds = 0;
|
|
531
519
|
return callback(null, dataValue);
|
|
532
520
|
}
|
|
533
521
|
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
522
|
+
try {
|
|
523
|
+
this.refreshFunc.call(this, (err: Error | null, dataValue?: DataValueLike) => {
|
|
524
|
+
if (err || !dataValue) {
|
|
525
|
+
errorLog(
|
|
526
|
+
"-------------- refresh call failed",
|
|
527
|
+
this.browseName.toString(),
|
|
528
|
+
this.nodeId.toString(),
|
|
529
|
+
err?.message
|
|
530
|
+
);
|
|
531
|
+
dataValue = { statusCode: StatusCodes.BadNoDataAvailable };
|
|
532
|
+
}
|
|
533
|
+
if (dataValue !== this.$dataValue) {
|
|
534
|
+
this._internal_set_dataValue(coerceDataValue(dataValue), null);
|
|
535
|
+
}
|
|
536
|
+
callback(err, this.$dataValue);
|
|
537
|
+
});
|
|
538
|
+
} catch (err) {
|
|
539
|
+
errorLog("-------------- refresh call failed 2", this.browseName.toString(), this.nodeId.toString());
|
|
540
|
+
errorLog(err);
|
|
541
|
+
const dataValue = new DataValue({ statusCode: StatusCodes.BadInternalError });
|
|
542
|
+
this._internal_set_dataValue(dataValue, null);
|
|
543
|
+
callback(err as Error, this.$dataValue);
|
|
544
|
+
}
|
|
543
545
|
}
|
|
544
546
|
|
|
545
547
|
public readEnumValue(): IEnumItem {
|
|
@@ -629,10 +631,91 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
629
631
|
}
|
|
630
632
|
}
|
|
631
633
|
|
|
632
|
-
public
|
|
634
|
+
public getBasicDataType(): DataType {
|
|
635
|
+
if (this._basicDataType) {
|
|
636
|
+
return this._basicDataType;
|
|
637
|
+
}
|
|
638
|
+
if (this.dataType.namespace === 0 && this.dataType.value === 0) {
|
|
639
|
+
return DataType.Null;
|
|
640
|
+
}
|
|
633
641
|
const addressSpace = this.addressSpace;
|
|
634
|
-
const
|
|
635
|
-
|
|
642
|
+
const dataTypeNode = addressSpace.findDataType(this.dataType)!;
|
|
643
|
+
const basicDataType = dataTypeNode ? dataTypeNode.getBasicDataType() : DataType.Null;
|
|
644
|
+
// const basicDataType = addressSpace.findCorrespondingBasicDataType(this.dataType);
|
|
645
|
+
this._basicDataType = basicDataType;
|
|
646
|
+
return basicDataType;
|
|
647
|
+
}
|
|
648
|
+
public adjustVariant(variant: Variant): Variant {
|
|
649
|
+
return adjustVariant(variant, this.valueRank, this.getBasicDataType());
|
|
650
|
+
}
|
|
651
|
+
public verifyVariantCompatibility(variant: Variant): void {
|
|
652
|
+
try {
|
|
653
|
+
// istanbul ignore next
|
|
654
|
+
if (Object.prototype.hasOwnProperty.call(variant, "value")) {
|
|
655
|
+
if (variant.dataType === null || variant.dataType === undefined) {
|
|
656
|
+
throw new Error(
|
|
657
|
+
"Variant must provide a valid dataType : variant = " +
|
|
658
|
+
variant.toString() +
|
|
659
|
+
" this.dataType= " +
|
|
660
|
+
this.dataType.toString()
|
|
661
|
+
);
|
|
662
|
+
}
|
|
663
|
+
if (
|
|
664
|
+
variant.dataType === DataType.Boolean &&
|
|
665
|
+
(this.dataType.namespace !== 0 || this.dataType.value !== DataType.Boolean)
|
|
666
|
+
) {
|
|
667
|
+
throw new Error(
|
|
668
|
+
"Variant must provide a valid Boolean : variant = " +
|
|
669
|
+
variant.toString() +
|
|
670
|
+
" this.dataType= " +
|
|
671
|
+
this.dataType.toString()
|
|
672
|
+
);
|
|
673
|
+
}
|
|
674
|
+
if (
|
|
675
|
+
this.dataType.namespace === 0 &&
|
|
676
|
+
this.dataType.value === DataType.LocalizedText &&
|
|
677
|
+
variant.dataType !== DataType.LocalizedText
|
|
678
|
+
) {
|
|
679
|
+
throw new Error(
|
|
680
|
+
"Variant must provide a valid LocalizedText : variant = " +
|
|
681
|
+
variant.toString() +
|
|
682
|
+
" this.dataType= " +
|
|
683
|
+
this.dataType.toString()
|
|
684
|
+
);
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
const basicType = this.getBasicDataType();
|
|
688
|
+
if (
|
|
689
|
+
basicType !== DataType.Null &&
|
|
690
|
+
basicType !== DataType.Variant &&
|
|
691
|
+
variant.dataType !== DataType.Null &&
|
|
692
|
+
variant.dataType !== basicType
|
|
693
|
+
) {
|
|
694
|
+
const message =
|
|
695
|
+
"UAVariable.setValueFromSource " +
|
|
696
|
+
this.browseName.toString() +
|
|
697
|
+
" nodeId:" +
|
|
698
|
+
this.nodeId.toString() +
|
|
699
|
+
" dataType:" +
|
|
700
|
+
this.dataType.toString() +
|
|
701
|
+
":\n" +
|
|
702
|
+
"the provided variant must have the expected dataType!\n" +
|
|
703
|
+
" - the expected dataType is " +
|
|
704
|
+
chalk.cyan(DataType[basicType]) +
|
|
705
|
+
"\n" +
|
|
706
|
+
" - the actual dataType is " +
|
|
707
|
+
chalk.magenta(DataType[variant.dataType]) +
|
|
708
|
+
"\n" +
|
|
709
|
+
" - " +
|
|
710
|
+
variant.toString();
|
|
711
|
+
throw new Error(message);
|
|
712
|
+
}
|
|
713
|
+
} catch (err) {
|
|
714
|
+
errorLog("UAVariable ", (err as Error)?.message, this.browseName.toString(), " nodeId=", this.nodeId.toString());
|
|
715
|
+
errorLog((err as Error).message);
|
|
716
|
+
errorLog((err as Error).stack);
|
|
717
|
+
throw err;
|
|
718
|
+
}
|
|
636
719
|
}
|
|
637
720
|
/**
|
|
638
721
|
* setValueFromSource is used to let the device sets the variable values
|
|
@@ -646,39 +729,26 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
646
729
|
* @param [sourceTimestamp= Now]
|
|
647
730
|
*/
|
|
648
731
|
public setValueFromSource(variant: VariantLike, statusCode?: StatusCode, sourceTimestamp?: Date): void {
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
)
|
|
666
|
-
|
|
667
|
-
|
|
732
|
+
try {
|
|
733
|
+
statusCode = statusCode || StatusCodes.Good;
|
|
734
|
+
const variant1 = Variant.coerce(variant);
|
|
735
|
+
this.verifyVariantCompatibility(variant1);
|
|
736
|
+
const now = coerceClock(sourceTimestamp, 0);
|
|
737
|
+
|
|
738
|
+
const dataValue = new DataValue(null);
|
|
739
|
+
dataValue.serverPicoseconds = now.picoseconds;
|
|
740
|
+
dataValue.serverTimestamp = now.timestamp;
|
|
741
|
+
dataValue.sourcePicoseconds = now.picoseconds;
|
|
742
|
+
dataValue.sourceTimestamp = now.timestamp;
|
|
743
|
+
dataValue.statusCode = statusCode;
|
|
744
|
+
dataValue.value = variant1;
|
|
745
|
+
this._internal_set_dataValue(dataValue);
|
|
746
|
+
} catch (err) {
|
|
747
|
+
errorLog("UAVariable#setValueFromString Error : ", this.browseName.toString(), this.nodeId.toString());
|
|
748
|
+
errorLog((err as Error).message);
|
|
749
|
+
errorLog(this.parent?.toString());
|
|
750
|
+
throw err;
|
|
668
751
|
}
|
|
669
|
-
|
|
670
|
-
const variant1 = Variant.coerce(variant);
|
|
671
|
-
|
|
672
|
-
const now = coerceClock(sourceTimestamp, 0);
|
|
673
|
-
|
|
674
|
-
const dataValue = new DataValue(null);
|
|
675
|
-
dataValue.serverPicoseconds = now.picoseconds;
|
|
676
|
-
dataValue.serverTimestamp = now.timestamp;
|
|
677
|
-
dataValue.sourcePicoseconds = now.picoseconds;
|
|
678
|
-
dataValue.sourceTimestamp = now.timestamp;
|
|
679
|
-
dataValue.statusCode = statusCode;
|
|
680
|
-
dataValue.value = variant1;
|
|
681
|
-
this._internal_set_dataValue(dataValue);
|
|
682
752
|
}
|
|
683
753
|
|
|
684
754
|
public writeValue(
|
|
@@ -749,16 +819,7 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
749
819
|
return callback!(null, statusCode);
|
|
750
820
|
}
|
|
751
821
|
|
|
752
|
-
|
|
753
|
-
this: UAVariable,
|
|
754
|
-
dataValue1: DataValue,
|
|
755
|
-
indexRange1: NumericRange,
|
|
756
|
-
callback1: (err: Error | null, statusCode: StatusCode, dataValue?: DataValue | null | undefined) => void
|
|
757
|
-
) {
|
|
758
|
-
// xx assert(!indexRange,"indexRange Not Implemented");
|
|
759
|
-
return _default_writable_timestamped_set_func.call(this, dataValue1, callback1);
|
|
760
|
-
}
|
|
761
|
-
const write_func = (this._timestamped_set_func || default_func) as any;
|
|
822
|
+
const write_func = this._timestamped_set_func || default_func;
|
|
762
823
|
|
|
763
824
|
if (!write_func) {
|
|
764
825
|
warningLog(" warning " + this.nodeId.toString() + " " + this.browseName.toString() + " has no setter. \n");
|
|
@@ -767,77 +828,70 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
767
828
|
}
|
|
768
829
|
assert(write_func);
|
|
769
830
|
|
|
770
|
-
write_func.call(
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
831
|
+
write_func.call(this, dataValue, (err?: Error | null, statusCode1?: StatusCode) => {
|
|
832
|
+
if (!err) {
|
|
833
|
+
dataValue && this.verifyVariantCompatibility(dataValue.value);
|
|
834
|
+
|
|
835
|
+
if (indexRange && !indexRange.isEmpty()) {
|
|
836
|
+
if (!indexRange.isValid()) {
|
|
837
|
+
return callback!(null, StatusCodes.BadIndexRangeInvalid);
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
const newArrayOrMatrix = dataValue.value.value;
|
|
841
|
+
|
|
842
|
+
if (dataValue.value.arrayType === VariantArrayType.Array) {
|
|
843
|
+
if (this.$dataValue.value.arrayType !== VariantArrayType.Array) {
|
|
844
|
+
return callback(null, StatusCodes.BadTypeMismatch);
|
|
783
845
|
}
|
|
846
|
+
// check that destination data is also an array
|
|
847
|
+
assert(check_valid_array(this.$dataValue.value.dataType, this.$dataValue.value.value));
|
|
848
|
+
const destArr = this.$dataValue.value.value;
|
|
849
|
+
const result = indexRange.set_values(destArr, newArrayOrMatrix);
|
|
784
850
|
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
if (result.statusCode.isNot(StatusCodes.Good)) {
|
|
797
|
-
return callback!(null, result.statusCode);
|
|
798
|
-
}
|
|
799
|
-
correctedDataValue.value.value = result.array;
|
|
800
|
-
|
|
801
|
-
// scrap original array so we detect range
|
|
802
|
-
this._dataValue.value.value = null;
|
|
803
|
-
} else if (correctedDataValue.value.arrayType === VariantArrayType.Matrix) {
|
|
804
|
-
const dimensions = this._dataValue.value.dimensions;
|
|
805
|
-
if (this._dataValue.value.arrayType !== VariantArrayType.Matrix || !dimensions) {
|
|
806
|
-
// not a matrix !
|
|
807
|
-
return callback!(null, StatusCodes.BadTypeMismatch);
|
|
808
|
-
}
|
|
809
|
-
const matrix = this._dataValue.value.value;
|
|
810
|
-
const result = indexRange.set_values_matrix(
|
|
811
|
-
{
|
|
812
|
-
matrix,
|
|
813
|
-
dimensions
|
|
814
|
-
},
|
|
815
|
-
newArrayOrMatrix
|
|
816
|
-
);
|
|
817
|
-
if (result.statusCode.isNot(StatusCodes.Good)) {
|
|
818
|
-
return callback!(null, result.statusCode);
|
|
819
|
-
}
|
|
820
|
-
correctedDataValue.value.dimensions = this._dataValue.value.dimensions;
|
|
821
|
-
correctedDataValue.value.value = result.matrix;
|
|
822
|
-
|
|
823
|
-
// scrap original array so we detect range
|
|
824
|
-
this._dataValue.value.value = null;
|
|
825
|
-
} else {
|
|
851
|
+
if (result.statusCode.isNot(StatusCodes.Good)) {
|
|
852
|
+
return callback!(null, result.statusCode);
|
|
853
|
+
}
|
|
854
|
+
dataValue.value.value = result.array;
|
|
855
|
+
|
|
856
|
+
// scrap original array so we detect range
|
|
857
|
+
this.$dataValue.value.value = null;
|
|
858
|
+
} else if (dataValue.value.arrayType === VariantArrayType.Matrix) {
|
|
859
|
+
const dimensions = this.$dataValue.value.dimensions;
|
|
860
|
+
if (this.$dataValue.value.arrayType !== VariantArrayType.Matrix || !dimensions) {
|
|
861
|
+
// not a matrix !
|
|
826
862
|
return callback!(null, StatusCodes.BadTypeMismatch);
|
|
827
863
|
}
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
864
|
+
const matrix = this.$dataValue.value.value;
|
|
865
|
+
const result = indexRange.set_values_matrix(
|
|
866
|
+
{
|
|
867
|
+
matrix,
|
|
868
|
+
dimensions
|
|
869
|
+
},
|
|
870
|
+
newArrayOrMatrix
|
|
871
|
+
);
|
|
872
|
+
if (result.statusCode.isNot(StatusCodes.Good)) {
|
|
873
|
+
return callback!(null, result.statusCode);
|
|
834
874
|
}
|
|
835
|
-
|
|
875
|
+
dataValue.value.dimensions = this.$dataValue.value.dimensions;
|
|
876
|
+
dataValue.value.value = result.matrix;
|
|
877
|
+
|
|
878
|
+
// scrap original array so we detect range
|
|
879
|
+
this.$dataValue.value.value = null;
|
|
880
|
+
} else {
|
|
881
|
+
return callback!(null, StatusCodes.BadTypeMismatch);
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
try {
|
|
885
|
+
this._internal_set_dataValue(dataValue, indexRange);
|
|
886
|
+
} catch (err) {
|
|
887
|
+
if (err instanceof Error) {
|
|
888
|
+
warningLog(err.message);
|
|
836
889
|
}
|
|
890
|
+
return callback!(null, StatusCodes.BadInternalError);
|
|
837
891
|
}
|
|
838
|
-
callback!(err, statusCode1);
|
|
839
892
|
}
|
|
840
|
-
|
|
893
|
+
callback!(err || null, statusCode1);
|
|
894
|
+
});
|
|
841
895
|
}
|
|
842
896
|
|
|
843
897
|
public writeAttribute(context: ISessionContext | null, writeValue: WriteValueOptions, callback: StatusCodeCallback): void;
|
|
@@ -903,6 +957,11 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
903
957
|
if (!this._validate_DataType(value.dataType)) {
|
|
904
958
|
return StatusCodes.BadTypeMismatch;
|
|
905
959
|
}
|
|
960
|
+
try {
|
|
961
|
+
this.verifyVariantCompatibility(value);
|
|
962
|
+
} catch (err) {
|
|
963
|
+
return StatusCodes.BadTypeMismatch;
|
|
964
|
+
}
|
|
906
965
|
return StatusCodes.Good;
|
|
907
966
|
}
|
|
908
967
|
|
|
@@ -917,12 +976,12 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
917
976
|
*/
|
|
918
977
|
public touchValue(optionalNow?: PreciseClock): void {
|
|
919
978
|
const now = optionalNow || getCurrentClock();
|
|
920
|
-
this.
|
|
921
|
-
this.
|
|
922
|
-
this.
|
|
923
|
-
this.
|
|
979
|
+
this.$dataValue.sourceTimestamp = now.timestamp;
|
|
980
|
+
this.$dataValue.sourcePicoseconds = now.picoseconds;
|
|
981
|
+
this.$dataValue.serverTimestamp = now.timestamp;
|
|
982
|
+
this.$dataValue.serverPicoseconds = now.picoseconds;
|
|
924
983
|
|
|
925
|
-
this.
|
|
984
|
+
this.$dataValue.statusCode = StatusCodes.Good;
|
|
926
985
|
|
|
927
986
|
if (this.minimumSamplingInterval === 0) {
|
|
928
987
|
if (this.listenerCount("value_changed") > 0) {
|
|
@@ -1070,6 +1129,7 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
1070
1129
|
|
|
1071
1130
|
assert(typeof this._timestamped_set_func !== "function", "UAVariable already bound");
|
|
1072
1131
|
assert(typeof this._timestamped_get_func !== "function", "UAVariable already bound");
|
|
1132
|
+
|
|
1073
1133
|
bind_getter.call(this, options);
|
|
1074
1134
|
bind_setter.call(this, options);
|
|
1075
1135
|
|
|
@@ -1081,9 +1141,9 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
1081
1141
|
this._historyRead = _historyRead;
|
|
1082
1142
|
assert(this._historyRead.length === 6);
|
|
1083
1143
|
}
|
|
1084
|
-
|
|
1144
|
+
// post conditions
|
|
1085
1145
|
assert(typeof this._timestamped_set_func === "function");
|
|
1086
|
-
assert(this._timestamped_set_func!.length ===
|
|
1146
|
+
assert(this._timestamped_set_func!.length === 2, "expecting 2 parameters");
|
|
1087
1147
|
}
|
|
1088
1148
|
|
|
1089
1149
|
/**
|
|
@@ -1106,7 +1166,7 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
1106
1166
|
}
|
|
1107
1167
|
|
|
1108
1168
|
const readImmediate = (innerCallback: (err: Error | null, dataValue: DataValue) => void) => {
|
|
1109
|
-
assert(this
|
|
1169
|
+
assert(this.$dataValue instanceof DataValue);
|
|
1110
1170
|
const dataValue = this.readValue();
|
|
1111
1171
|
innerCallback(null, dataValue);
|
|
1112
1172
|
};
|
|
@@ -1174,14 +1234,20 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
1174
1234
|
valueRank: this.valueRank
|
|
1175
1235
|
};
|
|
1176
1236
|
|
|
1177
|
-
const newVariable = _clone.call(
|
|
1237
|
+
const newVariable = _clone.call(
|
|
1238
|
+
this,
|
|
1239
|
+
UAVariableImpl,
|
|
1240
|
+
options,
|
|
1241
|
+
optionalFilter || defaultCloneFilter,
|
|
1242
|
+
extraInfo || defaultCloneExtraInfo
|
|
1243
|
+
) as UAVariableImpl;
|
|
1178
1244
|
|
|
1179
1245
|
newVariable.bindVariable();
|
|
1180
1246
|
|
|
1181
1247
|
assert(typeof newVariable._timestamped_set_func === "function");
|
|
1182
1248
|
|
|
1183
1249
|
assert(newVariable.dataType === this.dataType);
|
|
1184
|
-
newVariable
|
|
1250
|
+
newVariable.$dataValue = this.$dataValue.clone();
|
|
1185
1251
|
return newVariable;
|
|
1186
1252
|
}
|
|
1187
1253
|
|
|
@@ -1204,8 +1270,10 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
1204
1270
|
return true;
|
|
1205
1271
|
}
|
|
1206
1272
|
const addressSpace = this.addressSpace;
|
|
1273
|
+
|
|
1274
|
+
// istanbul ignore next
|
|
1207
1275
|
if (!(extObj && extObj.constructor)) {
|
|
1208
|
-
|
|
1276
|
+
errorLog(extObj);
|
|
1209
1277
|
throw new Error("expecting an valid extension object");
|
|
1210
1278
|
}
|
|
1211
1279
|
const dataType = addressSpace.findDataType(this.dataType);
|
|
@@ -1231,7 +1299,7 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
1231
1299
|
return extObj.constructor.name === Constructor.name;
|
|
1232
1300
|
}
|
|
1233
1301
|
} catch (err) {
|
|
1234
|
-
|
|
1302
|
+
errorLog(err);
|
|
1235
1303
|
return false;
|
|
1236
1304
|
}
|
|
1237
1305
|
}
|
|
@@ -1252,7 +1320,7 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
1252
1320
|
|
|
1253
1321
|
// istanbul ignore next
|
|
1254
1322
|
if (doDebug) {
|
|
1255
|
-
|
|
1323
|
+
debugLog(" ------------------------------ binding ", this.browseName.toString(), this.nodeId.toString());
|
|
1256
1324
|
}
|
|
1257
1325
|
assert(structure && structure.browseName.toString() === "Structure", "expecting DataType Structure to be in IAddressSpace");
|
|
1258
1326
|
|
|
@@ -1277,14 +1345,14 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
1277
1345
|
// }
|
|
1278
1346
|
// istanbul ignore next
|
|
1279
1347
|
if (!this.checkExtensionObjectIsCorrect(this.$extensionObject!)) {
|
|
1280
|
-
|
|
1348
|
+
warningLog(
|
|
1281
1349
|
"on node : ",
|
|
1282
1350
|
this.browseName.toString(),
|
|
1283
1351
|
this.nodeId.toString(),
|
|
1284
1352
|
"dataType=",
|
|
1285
1353
|
this.dataType.toString({ addressSpace: this.addressSpace })
|
|
1286
1354
|
);
|
|
1287
|
-
|
|
1355
|
+
warningLog(this.$extensionObject?.toString());
|
|
1288
1356
|
throw new Error(
|
|
1289
1357
|
"bindExtensionObject: $extensionObject is incorrect: we are expecting a " +
|
|
1290
1358
|
this.dataType.toString({ addressSpace: this.addressSpace }) +
|
|
@@ -1299,45 +1367,32 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
1299
1367
|
|
|
1300
1368
|
// ------------------------------------------------------------------
|
|
1301
1369
|
|
|
1302
|
-
function prepareVariantValue(dataType: DataType
|
|
1303
|
-
if (typeof dataType === "string") {
|
|
1304
|
-
dataType = (DataType as any)[dataType];
|
|
1305
|
-
}
|
|
1370
|
+
function prepareVariantValue(dataType: DataType, value: VariantLike): VariantLike {
|
|
1306
1371
|
if ((dataType === DataType.Int32 || dataType === DataType.UInt32) && value && (value as any).key) {
|
|
1307
1372
|
value = value.value;
|
|
1308
1373
|
}
|
|
1309
1374
|
return value;
|
|
1310
1375
|
}
|
|
1311
1376
|
|
|
1312
|
-
const bindProperty = (propertyNode: UAVariableImpl, name:
|
|
1313
|
-
const dataTypeAsString = DataType[dataTypeNodeId];
|
|
1314
|
-
|
|
1315
|
-
/*
|
|
1316
|
-
property.setValueFromSource(new Variant({
|
|
1317
|
-
dataType: dataType,
|
|
1318
|
-
value: prepareVariantValue(dataType, this.$extensionObject[name])
|
|
1319
|
-
}));
|
|
1320
|
-
*/
|
|
1321
|
-
|
|
1322
|
-
assert(propertyNode.readValue().statusCode.equals(StatusCodes.Good));
|
|
1323
|
-
|
|
1377
|
+
const bindProperty = (propertyNode: UAVariableImpl, name: string, extensionObject: ExtensionObject, dataType: DataType) => {
|
|
1324
1378
|
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
1325
1379
|
const self = this;
|
|
1326
1380
|
propertyNode.bindVariable(
|
|
1327
1381
|
{
|
|
1328
1382
|
timestamped_get: () => {
|
|
1329
|
-
const
|
|
1383
|
+
const propertyValue = self.$extensionObject[name];
|
|
1330
1384
|
|
|
1331
|
-
if (
|
|
1332
|
-
propertyNode.
|
|
1333
|
-
propertyNode.
|
|
1334
|
-
propertyNode.
|
|
1335
|
-
return new DataValue(propertyNode
|
|
1385
|
+
if (propertyValue === undefined) {
|
|
1386
|
+
propertyNode.$dataValue.value.dataType = DataType.Null;
|
|
1387
|
+
propertyNode.$dataValue.statusCode = StatusCodes.Good;
|
|
1388
|
+
propertyNode.$dataValue.value.value = null;
|
|
1389
|
+
return new DataValue(propertyNode.$dataValue);
|
|
1336
1390
|
}
|
|
1337
|
-
const value = prepareVariantValue(
|
|
1338
|
-
propertyNode.
|
|
1339
|
-
propertyNode.
|
|
1340
|
-
|
|
1391
|
+
const value = prepareVariantValue(dataType, propertyValue);
|
|
1392
|
+
propertyNode.$dataValue.statusCode = StatusCodes.Good;
|
|
1393
|
+
propertyNode.$dataValue.value.dataType = dataType;
|
|
1394
|
+
propertyNode.$dataValue.value.value = value;
|
|
1395
|
+
return new DataValue(propertyNode.$dataValue);
|
|
1341
1396
|
},
|
|
1342
1397
|
timestamped_set: (dataValue: DataValue, callback: CallbackT<StatusCode>) => {
|
|
1343
1398
|
dataValue;
|
|
@@ -1355,8 +1410,8 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
1355
1410
|
const s = this.readValue();
|
|
1356
1411
|
// istanbul ignore next
|
|
1357
1412
|
if (this.dataTypeObj.isAbstract) {
|
|
1358
|
-
|
|
1359
|
-
|
|
1413
|
+
warningLog("Warning the DataType associated with this Variable is abstract ", this.dataTypeObj.browseName.toString());
|
|
1414
|
+
warningLog("You need to provide a extension object yourself ");
|
|
1360
1415
|
throw new Error("bindExtensionObject requires a extensionObject as associated dataType is only abstract");
|
|
1361
1416
|
}
|
|
1362
1417
|
if (s.value && (s.value.dataType === DataType.Null || (s.value.dataType === DataType.ExtensionObject && !s.value.value))) {
|
|
@@ -1376,8 +1431,8 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
1376
1431
|
this.bindVariable(
|
|
1377
1432
|
{
|
|
1378
1433
|
timestamped_get() {
|
|
1379
|
-
self.
|
|
1380
|
-
const d = new DataValue(self
|
|
1434
|
+
self.$dataValue.value.value = self.$extensionObject;
|
|
1435
|
+
const d = new DataValue(self.$dataValue);
|
|
1381
1436
|
d.value = new Variant(d.value);
|
|
1382
1437
|
return d;
|
|
1383
1438
|
},
|
|
@@ -1386,7 +1441,6 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
1386
1441
|
if (!self.checkExtensionObjectIsCorrect(ext)) {
|
|
1387
1442
|
return callback(null, StatusCodes.BadInvalidArgument);
|
|
1388
1443
|
}
|
|
1389
|
-
|
|
1390
1444
|
self.$extensionObject = new Proxy(ext, makeHandler(self));
|
|
1391
1445
|
self.touchValue();
|
|
1392
1446
|
callback(null, StatusCodes.Good);
|
|
@@ -1402,51 +1456,65 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
1402
1456
|
assert(s.statusCode.equals(StatusCodes.Good));
|
|
1403
1457
|
}
|
|
1404
1458
|
|
|
1405
|
-
let property: any;
|
|
1406
|
-
let camelCaseName: any;
|
|
1407
1459
|
// ------------------------------------------------------
|
|
1408
1460
|
// now bind each member
|
|
1409
1461
|
// ------------------------------------------------------
|
|
1410
|
-
const definition = dt._getDefinition(
|
|
1462
|
+
const definition = dt._getDefinition() as StructureDefinition | null;
|
|
1411
1463
|
|
|
1412
1464
|
// istanbul ignore next
|
|
1413
1465
|
if (!definition) {
|
|
1414
1466
|
throw new Error("xx definition missing in " + dt.toString());
|
|
1415
1467
|
}
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1468
|
+
|
|
1469
|
+
const getOrCreateProperty = (field: StructureField): UAVariableImpl => {
|
|
1470
|
+
let property: UAVariableImpl;
|
|
1471
|
+
const selectedComponents = components.filter(
|
|
1472
|
+
(f) => f instanceof UAVariableImpl && f.browseName.name!.toString() === field.name
|
|
1473
|
+
);
|
|
1474
|
+
|
|
1475
|
+
if (field.dataType.value === DataType.Variant) {
|
|
1476
|
+
warningLog("Warning : variant is not supported in ExtensionObject");
|
|
1477
|
+
}
|
|
1478
|
+
if (selectedComponents.length === 1) {
|
|
1479
|
+
property = selectedComponents[0] as UAVariableImpl;
|
|
1421
1480
|
/* istanbul ignore next */
|
|
1422
1481
|
} else {
|
|
1482
|
+
debugLog("adding missing array variable", field.name, this.browseName.toString(), this.nodeId.toString());
|
|
1423
1483
|
// todo: Handle array appropriately...
|
|
1424
|
-
assert(
|
|
1484
|
+
assert(selectedComponents.length === 0);
|
|
1425
1485
|
// create a variable (Note we may use ns=1;s=parentName/0:PropertyName)
|
|
1426
1486
|
property = this.namespace.addVariable({
|
|
1427
1487
|
browseName: { namespaceIndex: structureNamespace, name: field.name!.toString() },
|
|
1428
1488
|
componentOf: this,
|
|
1429
1489
|
dataType: field.dataType,
|
|
1430
1490
|
minimumSamplingInterval: this.minimumSamplingInterval
|
|
1431
|
-
});
|
|
1491
|
+
}) as UAVariableImpl;
|
|
1432
1492
|
assert(property.minimumSamplingInterval === this.minimumSamplingInterval);
|
|
1433
1493
|
}
|
|
1494
|
+
return property;
|
|
1495
|
+
};
|
|
1434
1496
|
|
|
1435
|
-
|
|
1436
|
-
property.touchValue();
|
|
1437
|
-
|
|
1497
|
+
for (const field of definition.fields || []) {
|
|
1438
1498
|
if (NodeId.sameNodeId(NodeId.nullNodeId, field.dataType)) {
|
|
1439
|
-
|
|
1440
|
-
|
|
1499
|
+
warningLog("field.dataType is null ! ", field.toString(), NodeId.nullNodeId.toString());
|
|
1500
|
+
warningLog(" dataType replaced with BaseDataType ");
|
|
1501
|
+
warningLog(definition.toString());
|
|
1441
1502
|
field.dataType = this.resolveNodeId("BaseDataType");
|
|
1442
1503
|
}
|
|
1443
|
-
|
|
1504
|
+
|
|
1505
|
+
const camelCaseName = lowerFirstLetter(field.name!);
|
|
1444
1506
|
assert(Object.prototype.hasOwnProperty.call(this.$extensionObject, camelCaseName));
|
|
1445
1507
|
|
|
1508
|
+
const propertyNode = getOrCreateProperty(field);
|
|
1509
|
+
|
|
1510
|
+
propertyNode.$dataValue.statusCode = StatusCodes.Good;
|
|
1511
|
+
propertyNode.touchValue();
|
|
1512
|
+
|
|
1513
|
+
const basicDataType = addressSpace.findCorrespondingBasicDataType(field.dataType);
|
|
1514
|
+
|
|
1446
1515
|
// istanbul ignore next
|
|
1447
1516
|
if (doDebug) {
|
|
1448
1517
|
const x = addressSpace.findNode(field.dataType)!.browseName.toString();
|
|
1449
|
-
const basicType = addressSpace.findCorrespondingBasicDataType(field.dataType);
|
|
1450
1518
|
debugLog(
|
|
1451
1519
|
chalk.cyan("xxx"),
|
|
1452
1520
|
" dataType",
|
|
@@ -1456,52 +1524,56 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
1456
1524
|
chalk.cyan(w(valueRankToString(field.valueRank), 10)),
|
|
1457
1525
|
chalk.green(w(x, 25)),
|
|
1458
1526
|
"basicType = ",
|
|
1459
|
-
chalk.yellow(w(
|
|
1460
|
-
|
|
1461
|
-
|
|
1527
|
+
chalk.yellow(w(basicDataType.toString(), 20)),
|
|
1528
|
+
propertyNode.nodeId.toString(),
|
|
1529
|
+
propertyNode.readValue().statusCode.toString()
|
|
1462
1530
|
);
|
|
1463
1531
|
}
|
|
1464
|
-
if (this.$extensionObject[camelCaseName] !== undefined &&
|
|
1532
|
+
if (this.$extensionObject[camelCaseName] !== undefined && basicDataType === DataType.ExtensionObject) {
|
|
1465
1533
|
assert(this.$extensionObject[camelCaseName] instanceof Object);
|
|
1466
|
-
this.$extensionObject[camelCaseName] = new Proxy(this.$extensionObject[camelCaseName], makeHandler(
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1534
|
+
this.$extensionObject[camelCaseName] = new Proxy(this.$extensionObject[camelCaseName], makeHandler(propertyNode));
|
|
1535
|
+
|
|
1536
|
+
propertyNode._internal_set_value(
|
|
1537
|
+
new Variant({
|
|
1538
|
+
dataType: DataType.ExtensionObject,
|
|
1539
|
+
value: this.$extensionObject[camelCaseName]
|
|
1540
|
+
})
|
|
1541
|
+
);
|
|
1542
|
+
|
|
1543
|
+
propertyNode.bindExtensionObject();
|
|
1544
|
+
propertyNode.$extensionObject = this.$extensionObject[camelCaseName];
|
|
1473
1545
|
} else {
|
|
1474
|
-
const dataTypeAsString = DataType[dataTypeNodeId];
|
|
1475
|
-
assert(typeof dataTypeAsString === "string");
|
|
1476
1546
|
const prop = this.$extensionObject[camelCaseName];
|
|
1477
|
-
|
|
1478
1547
|
if (prop === undefined) {
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1548
|
+
propertyNode._internal_set_value(
|
|
1549
|
+
new Variant({
|
|
1550
|
+
dataType: DataType.Null
|
|
1551
|
+
})
|
|
1552
|
+
);
|
|
1482
1553
|
} else {
|
|
1483
|
-
const preparedValue = prepareVariantValue(
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1554
|
+
const preparedValue = prepareVariantValue(basicDataType, prop);
|
|
1555
|
+
propertyNode._internal_set_value(
|
|
1556
|
+
new Variant({
|
|
1557
|
+
dataType: basicDataType,
|
|
1558
|
+
value: preparedValue
|
|
1559
|
+
})
|
|
1560
|
+
);
|
|
1488
1561
|
}
|
|
1489
1562
|
|
|
1490
1563
|
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
1491
1564
|
const self = this;
|
|
1492
|
-
property.camelCaseName = camelCaseName;
|
|
1493
|
-
|
|
1565
|
+
// property.camelCaseName = camelCaseName;
|
|
1566
|
+
propertyNode.setValueFromSource = function (this: UAVariableImpl, variant: VariantLike) {
|
|
1494
1567
|
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
1495
1568
|
const inner_this = this;
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
self.$extensionObject[inner_this.camelCaseName] = variant.value;
|
|
1569
|
+
const variant1 = Variant.coerce(variant);
|
|
1570
|
+
inner_this.verifyVariantCompatibility(variant1);
|
|
1571
|
+
self.$extensionObject[camelCaseName] = variant1.value;
|
|
1500
1572
|
self.touchValue();
|
|
1501
1573
|
};
|
|
1502
1574
|
}
|
|
1503
|
-
assert(
|
|
1504
|
-
bindProperty(
|
|
1575
|
+
assert(propertyNode.readValue().statusCode.equals(StatusCodes.Good));
|
|
1576
|
+
bindProperty(propertyNode, camelCaseName, this.$extensionObject, basicDataType);
|
|
1505
1577
|
}
|
|
1506
1578
|
assert(this.$extensionObject instanceof Object);
|
|
1507
1579
|
return this.$extensionObject;
|
|
@@ -1543,7 +1615,6 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
1543
1615
|
c1[name] = c2[name];
|
|
1544
1616
|
c1[name] += 1;
|
|
1545
1617
|
|
|
1546
|
-
// xx console.log(partialData);
|
|
1547
1618
|
setExtensionObjectValue(this, partialData);
|
|
1548
1619
|
}
|
|
1549
1620
|
|
|
@@ -1687,10 +1758,16 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
1687
1758
|
return validateDataType(this.addressSpace, this.dataType, variantDataType, this.nodeId, /* allow Nulls */ false);
|
|
1688
1759
|
}
|
|
1689
1760
|
|
|
1761
|
+
public _internal_set_value(value: Variant): void {
|
|
1762
|
+
if (value.dataType !== DataType.Null) {
|
|
1763
|
+
this.verifyVariantCompatibility(value);
|
|
1764
|
+
}
|
|
1765
|
+
this.$dataValue.value = value;
|
|
1766
|
+
}
|
|
1690
1767
|
public _internal_set_dataValue(dataValue: DataValue, indexRange?: NumericRange | null): void {
|
|
1691
1768
|
assert(dataValue, "expecting a dataValue");
|
|
1692
1769
|
assert(dataValue instanceof DataValue, "expecting dataValue to be a DataValue");
|
|
1693
|
-
assert(dataValue !== this
|
|
1770
|
+
assert(dataValue !== this.$dataValue, "expecting dataValue to be different from previous DataValue instance");
|
|
1694
1771
|
|
|
1695
1772
|
if (dataValue.value.arrayType === VariantArrayType.Matrix) {
|
|
1696
1773
|
if (!dataValue.value.dimensions) {
|
|
@@ -1714,27 +1791,31 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
1714
1791
|
// istanbul ignore next
|
|
1715
1792
|
if (this.dataType.namespace === 0) {
|
|
1716
1793
|
if (this.dataType.value === DataType.LocalizedText && dataValue.value.dataType !== DataType.LocalizedText) {
|
|
1717
|
-
|
|
1794
|
+
const message = "Invalid dataValue provided (expecting a LocalizedText) but got " + dataValue.toString();
|
|
1795
|
+
errorLog(message);
|
|
1796
|
+
throw new Error(message);
|
|
1718
1797
|
}
|
|
1719
1798
|
}
|
|
1720
1799
|
|
|
1721
|
-
|
|
1800
|
+
this.verifyVariantCompatibility(dataValue.value);
|
|
1722
1801
|
|
|
1723
|
-
|
|
1724
|
-
|
|
1802
|
+
const old_dataValue = this.$dataValue;
|
|
1803
|
+
|
|
1804
|
+
this.$dataValue = dataValue;
|
|
1805
|
+
this.$dataValue.statusCode = this.$dataValue.statusCode || StatusCodes.Good;
|
|
1725
1806
|
|
|
1726
1807
|
// repair missing timestamps
|
|
1727
1808
|
if (!dataValue.serverTimestamp) {
|
|
1728
|
-
this.
|
|
1729
|
-
this.
|
|
1809
|
+
this.$dataValue.serverTimestamp = old_dataValue.serverTimestamp;
|
|
1810
|
+
this.$dataValue.serverPicoseconds = old_dataValue.serverPicoseconds;
|
|
1730
1811
|
}
|
|
1731
1812
|
if (!dataValue.sourceTimestamp) {
|
|
1732
|
-
this.
|
|
1733
|
-
this.
|
|
1813
|
+
this.$dataValue.sourceTimestamp = old_dataValue.sourceTimestamp;
|
|
1814
|
+
this.$dataValue.sourcePicoseconds = old_dataValue.sourcePicoseconds;
|
|
1734
1815
|
}
|
|
1735
1816
|
|
|
1736
1817
|
if (!sameDataValue(old_dataValue, dataValue)) {
|
|
1737
|
-
this.emit("value_changed", this
|
|
1818
|
+
this.emit("value_changed", this.$dataValue, indexRange);
|
|
1738
1819
|
}
|
|
1739
1820
|
}
|
|
1740
1821
|
|
|
@@ -1930,10 +2011,10 @@ function _calculateEffectiveUserAccessLevelFromPermission(
|
|
|
1930
2011
|
}
|
|
1931
2012
|
}
|
|
1932
2013
|
|
|
1933
|
-
function adjustVariant2(this:
|
|
2014
|
+
function adjustVariant2(this: UAVariableImpl, variant: Variant): Variant {
|
|
1934
2015
|
// convert Variant( Scalar|ByteString) => Variant(Array|ByteArray)
|
|
1935
2016
|
const addressSpace = this.addressSpace;
|
|
1936
|
-
const basicType =
|
|
2017
|
+
const basicType = this.getBasicDataType();
|
|
1937
2018
|
variant = adjustVariant(variant, this.valueRank, basicType);
|
|
1938
2019
|
return variant;
|
|
1939
2020
|
}
|
|
@@ -1950,7 +2031,6 @@ function _default_writable_timestamped_set_func(
|
|
|
1950
2031
|
dataValue: DataValue,
|
|
1951
2032
|
callback: (err: Error | null, statusCode: StatusCode, dataValue?: DataValue | null) => void
|
|
1952
2033
|
) {
|
|
1953
|
-
/* jshint validthis: true */
|
|
1954
2034
|
assert(dataValue instanceof DataValue);
|
|
1955
2035
|
callback(null, StatusCodes.Good, dataValue);
|
|
1956
2036
|
}
|
|
@@ -1992,7 +2072,7 @@ function _Variable_bind_with_async_refresh(this: UAVariableImpl, options: any) {
|
|
|
1992
2072
|
this.refreshFunc = options.refreshFunc;
|
|
1993
2073
|
|
|
1994
2074
|
// assert(this.readValue().statusCode === StatusCodes.BadNodeIdUnknown);
|
|
1995
|
-
this.
|
|
2075
|
+
this.$dataValue.statusCode = StatusCodes.UncertainInitialValue;
|
|
1996
2076
|
|
|
1997
2077
|
// TO DO : REVISIT THIS ASSUMPTION
|
|
1998
2078
|
if (false && this.minimumSamplingInterval === 0) {
|
|
@@ -2004,7 +2084,13 @@ function _Variable_bind_with_async_refresh(this: UAVariableImpl, options: any) {
|
|
|
2004
2084
|
}
|
|
2005
2085
|
|
|
2006
2086
|
// variation 2
|
|
2007
|
-
function _Variable_bind_with_timestamped_get(
|
|
2087
|
+
function _Variable_bind_with_timestamped_get(
|
|
2088
|
+
this: UAVariableImpl,
|
|
2089
|
+
options: {
|
|
2090
|
+
get: undefined;
|
|
2091
|
+
timestamped_get: TimestampGetFunc;
|
|
2092
|
+
}
|
|
2093
|
+
) {
|
|
2008
2094
|
/* jshint validthis: true */
|
|
2009
2095
|
assert(this instanceof UAVariableImpl);
|
|
2010
2096
|
assert(typeof options.timestamped_get === "function");
|
|
@@ -2012,17 +2098,20 @@ function _Variable_bind_with_timestamped_get(this: UAVariableImpl, options: any)
|
|
|
2012
2098
|
assert(!this._timestamped_get_func);
|
|
2013
2099
|
|
|
2014
2100
|
const async_refresh_func = (callback: (err: Error | null, dataValue?: DataValue) => void) => {
|
|
2015
|
-
Promise.resolve((this._timestamped_get_func! as
|
|
2101
|
+
Promise.resolve((this._timestamped_get_func! as VariableDataValueGetterSync).call(this))
|
|
2016
2102
|
.then((dataValue) => callback(null, dataValue))
|
|
2017
|
-
.catch((err) =>
|
|
2103
|
+
.catch((err) => {
|
|
2104
|
+
errorLog("asyncRefresh error: Variable is ", this.nodeId.toString(), this.browseName.toString());
|
|
2105
|
+
callback(err as Error);
|
|
2106
|
+
});
|
|
2018
2107
|
};
|
|
2019
|
-
|
|
2108
|
+
const pThis = this as UAVariable;
|
|
2020
2109
|
if (options.timestamped_get.length === 0) {
|
|
2021
|
-
const timestamped_get = options.timestamped_get as
|
|
2110
|
+
const timestamped_get = options.timestamped_get as (this: UAVariable) => DataValue | Promise<DataValue>;
|
|
2022
2111
|
// sync version | Promise version
|
|
2023
2112
|
this._timestamped_get_func = timestamped_get;
|
|
2024
2113
|
|
|
2025
|
-
const dataValue_verify = timestamped_get
|
|
2114
|
+
const dataValue_verify = timestamped_get.call(pThis);
|
|
2026
2115
|
// dataValue_verify should be a DataValue or a Promise
|
|
2027
2116
|
/* istanbul ignore next */
|
|
2028
2117
|
if (!(dataValue_verify instanceof DataValue) && typeof dataValue_verify.then !== "function") {
|
|
@@ -2045,11 +2134,11 @@ function _Variable_bind_with_timestamped_get(this: UAVariableImpl, options: any)
|
|
|
2045
2134
|
}
|
|
2046
2135
|
|
|
2047
2136
|
// variation 1
|
|
2048
|
-
function _Variable_bind_with_simple_get(this: UAVariableImpl, options:
|
|
2137
|
+
function _Variable_bind_with_simple_get(this: UAVariableImpl, options: GetterOptions) {
|
|
2049
2138
|
/* jshint validthis: true */
|
|
2050
2139
|
assert(this instanceof UAVariableImpl);
|
|
2051
2140
|
assert(typeof options.get === "function", "should specify get function");
|
|
2052
|
-
assert(options.get
|
|
2141
|
+
assert(options.get!.length === 0, "get function should not have arguments");
|
|
2053
2142
|
assert(!options.timestamped_get, "should not specify a timestamped_get function when get is specified");
|
|
2054
2143
|
assert(!this._timestamped_get_func);
|
|
2055
2144
|
assert(!this._get_func);
|
|
@@ -2073,16 +2162,15 @@ function _Variable_bind_with_simple_get(this: UAVariableImpl, options: any) {
|
|
|
2073
2162
|
if (is_StatusCode(value)) {
|
|
2074
2163
|
return new DataValue({ statusCode: value });
|
|
2075
2164
|
} else {
|
|
2076
|
-
if (!this
|
|
2165
|
+
if (!this.$dataValue || !isGoodish(this.$dataValue.statusCode) || !sameVariant(this.$dataValue.value, value)) {
|
|
2077
2166
|
this.setValueFromSource(value, StatusCodes.Good);
|
|
2078
|
-
} else {
|
|
2079
|
-
// XX console.log("YYYYYYYYYYYYYYYYYYYYYYYYYY",this.browseName.toString());
|
|
2080
2167
|
}
|
|
2081
|
-
return this
|
|
2168
|
+
return this.$dataValue;
|
|
2082
2169
|
}
|
|
2083
2170
|
};
|
|
2084
2171
|
|
|
2085
2172
|
_Variable_bind_with_timestamped_get.call(this, {
|
|
2173
|
+
get: undefined,
|
|
2086
2174
|
timestamped_get: timestamped_get_func_from__Variable_bind_with_simple_get
|
|
2087
2175
|
});
|
|
2088
2176
|
}
|
|
@@ -2100,16 +2188,16 @@ function _Variable_bind_with_simple_set(this: UAVariableImpl, options: any) {
|
|
|
2100
2188
|
|
|
2101
2189
|
this._timestamped_set_func = (
|
|
2102
2190
|
timestamped_value: DataValue,
|
|
2103
|
-
indexRange: NumericRange,
|
|
2104
2191
|
callback: (err: Error | null, statusCode: StatusCode, dataValue: DataValue) => void
|
|
2105
2192
|
) => {
|
|
2106
2193
|
assert(timestamped_value instanceof DataValue);
|
|
2107
2194
|
this._set_func(timestamped_value.value, (err: Error | null, statusCode: StatusCode) => {
|
|
2195
|
+
// istanbul ignore next
|
|
2108
2196
|
if (!err && !statusCode) {
|
|
2109
|
-
|
|
2197
|
+
errorLog(
|
|
2110
2198
|
chalk.red("UAVariable Binding Error _set_func must return a StatusCode, check the bindVariable parameters")
|
|
2111
2199
|
);
|
|
2112
|
-
|
|
2200
|
+
errorLog(chalk.yellow("StatusCode.Good is assumed"));
|
|
2113
2201
|
return callback(err, StatusCodes.Good, timestamped_value);
|
|
2114
2202
|
}
|
|
2115
2203
|
callback(err, statusCode, timestamped_value);
|
|
@@ -2117,22 +2205,20 @@ function _Variable_bind_with_simple_set(this: UAVariableImpl, options: any) {
|
|
|
2117
2205
|
};
|
|
2118
2206
|
}
|
|
2119
2207
|
|
|
2120
|
-
function _Variable_bind_with_timestamped_set(
|
|
2121
|
-
|
|
2208
|
+
function _Variable_bind_with_timestamped_set(
|
|
2209
|
+
this: UAVariableImpl,
|
|
2210
|
+
options: {
|
|
2211
|
+
timestamped_set: TimestampSetFunc;
|
|
2212
|
+
set: undefined;
|
|
2213
|
+
}
|
|
2214
|
+
) {
|
|
2122
2215
|
assert(typeof options.timestamped_set === "function");
|
|
2123
2216
|
assert(
|
|
2124
2217
|
options.timestamped_set.length === 2,
|
|
2125
2218
|
"timestamped_set must have 2 parameters timestamped_set: function(dataValue,callback){}"
|
|
2126
2219
|
);
|
|
2127
2220
|
assert(!options.set, "should not specify set when timestamped_set_func exists ");
|
|
2128
|
-
this._timestamped_set_func = (
|
|
2129
|
-
dataValue: DataValue,
|
|
2130
|
-
indexRange: NumericRange,
|
|
2131
|
-
callback: (err: Error | null, statusCode: StatusCode, dataValue: DataValue) => void
|
|
2132
|
-
) => {
|
|
2133
|
-
// xx assert(!indexRange,"indexRange Not Implemented");
|
|
2134
|
-
return options.timestamped_set.call(this, dataValue, callback);
|
|
2135
|
-
};
|
|
2221
|
+
this._timestamped_set_func = convertToCallbackFunction1<StatusCode, DataValue, UAVariable>(options.timestamped_set);
|
|
2136
2222
|
}
|
|
2137
2223
|
|
|
2138
2224
|
interface SetterOptions {
|
|
@@ -2147,15 +2233,20 @@ function bind_setter(this: UAVariableImpl, options: SetterOptions) {
|
|
|
2147
2233
|
} else if (typeof options.timestamped_set === "function") {
|
|
2148
2234
|
// variation 2
|
|
2149
2235
|
assert(typeof options.timestamped_get === "function", "timestamped_set must be used with timestamped_get ");
|
|
2150
|
-
_Variable_bind_with_timestamped_set.call(this,
|
|
2236
|
+
_Variable_bind_with_timestamped_set.call(this, {
|
|
2237
|
+
set: undefined,
|
|
2238
|
+
timestamped_set: options.timestamped_set
|
|
2239
|
+
});
|
|
2151
2240
|
} else if (typeof options.timestamped_get === "function") {
|
|
2152
2241
|
// timestamped_get is specified but timestamped_set is not
|
|
2153
2242
|
// => Value is read-only
|
|
2154
2243
|
_Variable_bind_with_timestamped_set.call(this, {
|
|
2244
|
+
set: undefined,
|
|
2155
2245
|
timestamped_set: _not_writable_timestamped_set_func
|
|
2156
2246
|
});
|
|
2157
2247
|
} else {
|
|
2158
2248
|
_Variable_bind_with_timestamped_set.call(this, {
|
|
2249
|
+
set: undefined,
|
|
2159
2250
|
timestamped_set: _default_writable_timestamped_set_func
|
|
2160
2251
|
});
|
|
2161
2252
|
}
|
|
@@ -2164,7 +2255,7 @@ function bind_setter(this: UAVariableImpl, options: SetterOptions) {
|
|
|
2164
2255
|
interface GetterOptions {
|
|
2165
2256
|
get?: GetFunc;
|
|
2166
2257
|
timestamped_get?: TimestampGetFunc;
|
|
2167
|
-
refreshFunc?:
|
|
2258
|
+
refreshFunc?: (callback: CallbackT<DataValue>) => void;
|
|
2168
2259
|
dataType?: DataType | string;
|
|
2169
2260
|
value?: any;
|
|
2170
2261
|
}
|
|
@@ -2174,7 +2265,10 @@ function bind_getter(this: UAVariableImpl, options: GetterOptions) {
|
|
|
2174
2265
|
_Variable_bind_with_simple_get.call(this, options);
|
|
2175
2266
|
} else if (typeof options.timestamped_get === "function") {
|
|
2176
2267
|
// variation 2
|
|
2177
|
-
_Variable_bind_with_timestamped_get.call(this,
|
|
2268
|
+
_Variable_bind_with_timestamped_get.call(this, {
|
|
2269
|
+
get: undefined,
|
|
2270
|
+
timestamped_get: options.timestamped_get
|
|
2271
|
+
});
|
|
2178
2272
|
} else if (typeof options.refreshFunc === "function") {
|
|
2179
2273
|
// variation 3
|
|
2180
2274
|
_Variable_bind_with_async_refresh.call(this, options);
|