node-opcua-address-space 2.56.2 → 2.60.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/LICENSE +20 -20
- 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/loader/load_nodeset2.js +76 -67
- package/dist/source/loader/load_nodeset2.js.map +1 -1
- package/dist/source/session_context.js +2 -2
- package/dist/source/session_context.js.map +1 -1
- package/dist/source/set_namespace_meta_data.js +1 -1
- package/dist/src/address_space.d.ts +2 -3
- package/dist/src/address_space.js +9 -6
- package/dist/src/address_space.js.map +1 -1
- package/dist/src/address_space_private.d.ts +2 -3
- 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_private.js +2 -2
- 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.d.ts +2 -2
- package/dist/src/namespace_impl.js +9 -9
- package/dist/src/namespace_impl.js.map +1 -1
- package/dist/src/nodeset_tools/nodeset_to_xml.js +16 -10
- 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 +5 -0
- package/dist/src/ua_method_impl.js.map +1 -1
- package/dist/src/ua_variable_impl.d.ts +6 -6
- package/dist/src/ua_variable_impl.js +236 -188
- 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 +13 -18
- package/dist/src/ua_variable_type_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/generate.js +1 -1
- package/nodeJS.d.ts +1 -1
- package/package.json +36 -36
- package/source/address_space_ts.ts +0 -1
- package/source/helpers/argument_list.ts +13 -3
- package/source/loader/load_nodeset2.ts +99 -79
- package/source/session_context.ts +1 -1
- package/source/set_namespace_meta_data.ts +1 -1
- package/source_nodejs/index.ts +1 -1
- package/src/address_space.ts +21 -14
- package/src/address_space_private.ts +3 -3
- 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_private.ts +6 -2
- package/src/event_data.ts +1 -1
- package/src/namespace_impl.ts +9 -9
- package/src/nodeset_tools/nodeset_to_xml.ts +22 -12
- 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 +11 -5
- package/src/ua_variable_impl.ts +290 -218
- package/src/ua_variable_type_impl.ts +9 -15
- package/testHelpers.d.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/dataType_in_separateNamespace.xml +150 -150
- package/test_helpers/test_fixtures/dataType_in_separateNamespace_basic.xml +57 -57
- package/test_helpers/test_fixtures/dataType_in_separateNamespace_mix.xml +135 -135
- package/test_helpers/test_fixtures/dataType_withEnumeration.xml +82 -82
- package/test_helpers/test_fixtures/dataType_with_isOptionSet.xml +194 -194
- package/test_helpers/test_fixtures/dataType_with_union.xml +1 -1
- package/test_helpers/test_fixtures/fixture_empty_nodeset2.xml +106 -106
- package/test_helpers/test_fixtures/fixture_simple_statemachine_nodeset2.xml +1312 -1303
- package/test_helpers/test_fixtures/fixuture_nodeset_objects_with_some_methods.xml +362 -362
- package/test_helpers/test_fixtures/issue_846.xml +3172 -3172
- package/test_helpers/test_fixtures/issue_899_variable_with_nodeid_value.xml +32 -32
- package/test_helpers/test_fixtures/mini.Node.Set2.xml +14 -0
- package/test_helpers/test_fixtures/mini.nodeset.withVariousVariables.xml +194 -194
- package/test_helpers/test_fixtures/minimalist_nodeset_with_models.xml +8 -8
- package/test_helpers/test_fixtures/minimalist_nodeset_with_models_more_complex.xml +16 -16
- package/test_helpers/test_fixtures/nodeset_with_analog_items.xml +45 -45
- package/dist/source/interfaces/alarms_and_conditions/ua_condition_base_i.d.ts +0 -23
- package/dist/source/interfaces/alarms_and_conditions/ua_condition_base_i.js +0 -3
- package/dist/source/interfaces/alarms_and_conditions/ua_condition_base_i.js.map +0 -1
- package/dist/source/interfaces/data_access/ua_discrete_item.d.ts +0 -6
- package/dist/source/interfaces/data_access/ua_discrete_item.js +0 -3
- package/dist/source/interfaces/data_access/ua_discrete_item.js.map +0 -1
- package/dist/source/interfaces/data_access/ua_multistate_discrete.d.ts +0 -25
- package/dist/source/interfaces/data_access/ua_multistate_discrete.js +0 -3
- package/dist/source/interfaces/data_access/ua_multistate_discrete.js.map +0 -1
- package/dist/source/interfaces/data_access/ua_multistate_value_discrete.d.ts +0 -27
- package/dist/source/interfaces/data_access/ua_multistate_value_discrete.js +0 -3
- package/dist/source/interfaces/data_access/ua_multistate_value_discrete.js.map +0 -1
- package/dist/source/interfaces/data_access/ua_two_state_discrete.d.ts +0 -17
- package/dist/source/interfaces/data_access/ua_two_state_discrete.js +0 -3
- package/dist/source/interfaces/data_access/ua_two_state_discrete.js.map +0 -1
- package/dist/source/interfaces/data_access/ua_y_array_item.d.ts +0 -19
- package/dist/source/interfaces/data_access/ua_y_array_item.js +0 -3
- package/dist/source/interfaces/data_access/ua_y_array_item.js.map +0 -1
- package/dist/source/interfaces/state_machine/exclusive_limit_state_machine.d.ts +0 -11
- package/dist/source/interfaces/state_machine/exclusive_limit_state_machine.js +0 -3
- package/dist/source/interfaces/state_machine/exclusive_limit_state_machine.js.map +0 -1
- package/dist/source/interfaces/state_machine/finite_state_machine.d.ts +0 -70
- package/dist/source/interfaces/state_machine/finite_state_machine.js +0 -3
- package/dist/source/interfaces/state_machine/finite_state_machine.js.map +0 -1
- package/dist/source/interfaces/state_machine/program_finite_state_machine.d.ts +0 -74
- package/dist/source/interfaces/state_machine/program_finite_state_machine.js +0 -3
- package/dist/source/interfaces/state_machine/program_finite_state_machine.js.map +0 -1
- package/dist/source/interfaces/state_machine/state_machine.d.ts +0 -342
- package/dist/source/interfaces/state_machine/state_machine.js +0 -3
- package/dist/source/interfaces/state_machine/state_machine.js.map +0 -1
- package/dist/source/interfaces/state_machine/ua_finite_state_variable.d.ts +0 -18
- package/dist/source/interfaces/state_machine/ua_finite_state_variable.js +0 -3
- package/dist/source/interfaces/state_machine/ua_finite_state_variable.js.map +0 -1
- package/dist/source/interfaces/state_machine/ua_state_variable.d.ts +0 -29
- package/dist/source/interfaces/state_machine/ua_state_variable.js +0 -3
- package/dist/source/interfaces/state_machine/ua_state_variable.js.map +0 -1
- package/dist/source/interfaces/state_machine/ua_two_state_variable.d.ts +0 -26
- package/dist/source/interfaces/state_machine/ua_two_state_variable.js +0 -3
- package/dist/source/interfaces/state_machine/ua_two_state_variable.js.map +0 -1
- package/dist/source/interfaces/subscription_diagnostics_variable.d.ts +0 -41
- package/dist/source/interfaces/subscription_diagnostics_variable.js +0 -3
- package/dist/source/interfaces/subscription_diagnostics_variable.js.map +0 -1
- package/dist/src/alarms_and_conditions/base_event_type.d.ts +0 -26
- package/dist/src/alarms_and_conditions/base_event_type.js +0 -41
- package/dist/src/alarms_and_conditions/base_event_type.js.map +0 -1
- package/dist/src/alarms_and_conditions/shelving_state_machine.d.ts +0 -22
- package/dist/src/alarms_and_conditions/shelving_state_machine.js +0 -241
- package/dist/src/alarms_and_conditions/shelving_state_machine.js.map +0 -1
- package/dist/src/alarms_and_conditions/trip_alarm.d.ts +0 -16
- package/dist/src/alarms_and_conditions/trip_alarm.js +0 -21
- package/dist/src/alarms_and_conditions/trip_alarm.js.map +0 -1
- package/dist/src/alarms_and_conditions/ua_acknowledgeable_condition_base.d.ts +0 -54
- package/dist/src/alarms_and_conditions/ua_acknowledgeable_condition_base.js +0 -255
- package/dist/src/alarms_and_conditions/ua_acknowledgeable_condition_base.js.map +0 -1
- package/dist/src/alarms_and_conditions/ua_alarm_condition_base.d.ts +0 -138
- package/dist/src/alarms_and_conditions/ua_alarm_condition_base.js +0 -460
- package/dist/src/alarms_and_conditions/ua_alarm_condition_base.js.map +0 -1
- package/dist/src/alarms_and_conditions/ua_certificate_expiration_alarm.d.ts +0 -35
- package/dist/src/alarms_and_conditions/ua_certificate_expiration_alarm.js +0 -32
- package/dist/src/alarms_and_conditions/ua_certificate_expiration_alarm.js.map +0 -1
- package/dist/src/alarms_and_conditions/ua_condition_base.d.ts +0 -191
- package/dist/src/alarms_and_conditions/ua_condition_base.js +0 -1029
- package/dist/src/alarms_and_conditions/ua_condition_base.js.map +0 -1
- package/dist/src/alarms_and_conditions/ua_discrete_alarm.d.ts +0 -11
- package/dist/src/alarms_and_conditions/ua_discrete_alarm.js +0 -58
- package/dist/src/alarms_and_conditions/ua_discrete_alarm.js.map +0 -1
- package/dist/src/alarms_and_conditions/ua_exclusive_deviation_alarm.d.ts +0 -24
- package/dist/src/alarms_and_conditions/ua_exclusive_deviation_alarm.js +0 -59
- package/dist/src/alarms_and_conditions/ua_exclusive_deviation_alarm.js.map +0 -1
- package/dist/src/alarms_and_conditions/ua_exclusive_level_alarm.d.ts +0 -14
- package/dist/src/alarms_and_conditions/ua_exclusive_level_alarm.js +0 -17
- package/dist/src/alarms_and_conditions/ua_exclusive_level_alarm.js.map +0 -1
- package/dist/src/alarms_and_conditions/ua_exclusive_limit_alarm.d.ts +0 -22
- package/dist/src/alarms_and_conditions/ua_exclusive_limit_alarm.js +0 -87
- package/dist/src/alarms_and_conditions/ua_exclusive_limit_alarm.js.map +0 -1
- package/dist/src/alarms_and_conditions/ua_exclusive_rate_of_change_alarm.d.ts +0 -6
- package/dist/src/alarms_and_conditions/ua_exclusive_rate_of_change_alarm.js +0 -11
- package/dist/src/alarms_and_conditions/ua_exclusive_rate_of_change_alarm.js.map +0 -1
- package/dist/src/alarms_and_conditions/ua_limit_alarm.d.ts +0 -76
- package/dist/src/alarms_and_conditions/ua_limit_alarm.js +0 -237
- package/dist/src/alarms_and_conditions/ua_limit_alarm.js.map +0 -1
- package/dist/src/alarms_and_conditions/ua_non_exclusive_deviation_alarm.d.ts +0 -27
- package/dist/src/alarms_and_conditions/ua_non_exclusive_deviation_alarm.js +0 -62
- package/dist/src/alarms_and_conditions/ua_non_exclusive_deviation_alarm.js.map +0 -1
- package/dist/src/alarms_and_conditions/ua_non_exclusive_limit_alarm.d.ts +0 -49
- package/dist/src/alarms_and_conditions/ua_non_exclusive_limit_alarm.js +0 -176
- package/dist/src/alarms_and_conditions/ua_non_exclusive_limit_alarm.js.map +0 -1
- package/dist/src/alarms_and_conditions/ua_off_normal_alarm.d.ts +0 -47
- package/dist/src/alarms_and_conditions/ua_off_normal_alarm.js +0 -151
- package/dist/src/alarms_and_conditions/ua_off_normal_alarm.js.map +0 -1
- package/dist/src/alarms_and_conditions/ua_system_off_normal_alarm.d.ts +0 -16
- package/dist/src/alarms_and_conditions/ua_system_off_normal_alarm.js +0 -18
- package/dist/src/alarms_and_conditions/ua_system_off_normal_alarm.js.map +0 -1
- package/dist/src/base_node.d.ts +0 -289
- package/dist/src/base_node.js +0 -1345
- package/dist/src/base_node.js.map +0 -1
- package/dist/src/data_access/ua_analog_item.d.ts +0 -13
- package/dist/src/data_access/ua_analog_item.js +0 -37
- package/dist/src/data_access/ua_analog_item.js.map +0 -1
- package/dist/src/data_access/ua_data_item.d.ts +0 -16
- package/dist/src/data_access/ua_data_item.js +0 -66
- package/dist/src/data_access/ua_data_item.js.map +0 -1
- package/dist/src/data_access/ua_multistate_discrete.d.ts +0 -24
- package/dist/src/data_access/ua_multistate_discrete.js +0 -132
- package/dist/src/data_access/ua_multistate_discrete.js.map +0 -1
- package/dist/src/namespace.d.ts +0 -472
- package/dist/src/namespace.js +0 -1751
- package/dist/src/namespace.js.map +0 -1
- package/dist/src/reference.d.ts +0 -43
- package/dist/src/reference.js +0 -138
- package/dist/src/reference.js.map +0 -1
- package/dist/src/session_context.d.ts +0 -4
- package/dist/src/session_context.js +0 -9
- package/dist/src/session_context.js.map +0 -1
- package/dist/src/ua_data_type.d.ts +0 -83
- package/dist/src/ua_data_type.js +0 -289
- package/dist/src/ua_data_type.js.map +0 -1
- package/dist/src/ua_method.d.ts +0 -41
- package/dist/src/ua_method.js +0 -202
- package/dist/src/ua_method.js.map +0 -1
- package/dist/src/ua_object.d.ts +0 -28
- package/dist/src/ua_object.js +0 -153
- package/dist/src/ua_object.js.map +0 -1
- package/dist/src/ua_object_type.d.ts +0 -49
- package/dist/src/ua_object_type.js +0 -123
- package/dist/src/ua_object_type.js.map +0 -1
- package/dist/src/ua_reference_type.d.ts +0 -42
- package/dist/src/ua_reference_type.js +0 -138
- package/dist/src/ua_reference_type.js.map +0 -1
- package/dist/src/ua_variable.d.ts +0 -339
- package/dist/src/ua_variable.js +0 -1706
- package/dist/src/ua_variable.js.map +0 -1
- package/dist/src/ua_variable_type.d.ts +0 -57
- package/dist/src/ua_variable_type.js +0 -530
- package/dist/src/ua_variable_type.js.map +0 -1
- package/dist/src/ua_view.d.ts +0 -16
- package/dist/src/ua_view.js +0 -42
- package/dist/src/ua_view.js.map +0 -1
package/src/ua_variable_impl.ts
CHANGED
|
@@ -37,11 +37,20 @@ import {
|
|
|
37
37
|
ReadProcessedDetails,
|
|
38
38
|
ReadRawModifiedDetails,
|
|
39
39
|
StructureDefinition,
|
|
40
|
+
StructureField,
|
|
40
41
|
WriteValueOptions
|
|
41
42
|
} from "node-opcua-types";
|
|
42
43
|
import * as utils from "node-opcua-utils";
|
|
43
44
|
import { lowerFirstLetter } from "node-opcua-utils";
|
|
44
|
-
import {
|
|
45
|
+
import {
|
|
46
|
+
Variant,
|
|
47
|
+
VariantLike,
|
|
48
|
+
DataType,
|
|
49
|
+
sameVariant,
|
|
50
|
+
VariantArrayType,
|
|
51
|
+
adjustVariant,
|
|
52
|
+
verifyRankAndDimensions
|
|
53
|
+
} from "node-opcua-variant";
|
|
45
54
|
import { StatusCodeCallback } from "node-opcua-status-code";
|
|
46
55
|
import {
|
|
47
56
|
IAddressSpace,
|
|
@@ -162,16 +171,16 @@ function validateDataType(
|
|
|
162
171
|
if (variantDataType === DataType.Null && !allowNulls) {
|
|
163
172
|
return false;
|
|
164
173
|
}
|
|
165
|
-
let builtInType:
|
|
174
|
+
let builtInType: DataType;
|
|
166
175
|
let builtInUADataType: UADataType;
|
|
167
176
|
|
|
168
|
-
const destUADataType = addressSpace.
|
|
177
|
+
const destUADataType = addressSpace.findDataType(dataTypeNodeId)!;
|
|
169
178
|
assert(destUADataType instanceof UADataTypeImpl);
|
|
170
179
|
|
|
171
180
|
if (destUADataType.isAbstract || destUADataType.nodeId.namespace !== 0) {
|
|
172
181
|
builtInUADataType = destUADataType;
|
|
173
182
|
} else {
|
|
174
|
-
builtInType =
|
|
183
|
+
builtInType = addressSpace.findCorrespondingBasicDataType(destUADataType);
|
|
175
184
|
builtInUADataType = addressSpace.findDataType(builtInType)!;
|
|
176
185
|
}
|
|
177
186
|
assert(builtInUADataType instanceof UADataTypeImpl);
|
|
@@ -183,8 +192,8 @@ function validateDataType(
|
|
|
183
192
|
if (destUADataType.isSupertypeOf(enumerationUADataType)) {
|
|
184
193
|
// istanbul ignore next
|
|
185
194
|
if (doDebug) {
|
|
186
|
-
|
|
187
|
-
|
|
195
|
+
debugLog("destUADataType.", destUADataType.browseName.toString(), destUADataType.nodeId.toString());
|
|
196
|
+
debugLog(
|
|
188
197
|
"enumerationUADataType.",
|
|
189
198
|
enumerationUADataType.browseName.toString(),
|
|
190
199
|
enumerationUADataType.nodeId.toString()
|
|
@@ -203,14 +212,14 @@ function validateDataType(
|
|
|
203
212
|
if (doDebug) {
|
|
204
213
|
if (dest_isSuperTypeOf_variant) {
|
|
205
214
|
/* istanbul ignore next*/
|
|
206
|
-
|
|
215
|
+
debugLog(chalk.green(" ---------- Type match !!! "), " on ", nodeId.toString());
|
|
207
216
|
} else {
|
|
208
217
|
/* istanbul ignore next*/
|
|
209
|
-
|
|
218
|
+
debugLog(chalk.red(" ---------- Type mismatch "), " on ", nodeId.toString());
|
|
210
219
|
}
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
220
|
+
debugLog(chalk.cyan(" Variable data Type is = "), destUADataType.browseName.toString());
|
|
221
|
+
debugLog(chalk.cyan(" which matches basic Type = "), builtInUADataType.browseName.toString());
|
|
222
|
+
debugLog(chalk.yellow(" Actual dataType = "), variantUADataType.browseName.toString());
|
|
214
223
|
}
|
|
215
224
|
|
|
216
225
|
return dest_isSuperTypeOf_variant;
|
|
@@ -227,37 +236,6 @@ interface UAVariableOptions extends InternalBaseNodeOptions {
|
|
|
227
236
|
historizing?: number;
|
|
228
237
|
}
|
|
229
238
|
|
|
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
239
|
type TimestampGetFunction1 = () => DataValue | Promise<DataValue>;
|
|
262
240
|
type TimestampGetFunction2 = (callback: (err: Error | null, dataValue?: DataValue) => void) => void;
|
|
263
241
|
type TimestampGetFunction = TimestampGetFunction1 | TimestampGetFunction2;
|
|
@@ -299,7 +277,9 @@ type TimestampSetFunction = TimestampSetFunction1 | TimestampSetFunction2;
|
|
|
299
277
|
*/
|
|
300
278
|
export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
301
279
|
public readonly nodeClass = NodeClass.Variable;
|
|
280
|
+
|
|
302
281
|
public dataType: NodeId;
|
|
282
|
+
private _basicDataType?: DataType;
|
|
303
283
|
|
|
304
284
|
public $extensionObject?: any;
|
|
305
285
|
|
|
@@ -307,9 +287,9 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
307
287
|
public varHistorian?: IVariableHistorian;
|
|
308
288
|
|
|
309
289
|
/**
|
|
310
|
-
* @internal
|
|
290
|
+
* @internal @private
|
|
311
291
|
*/
|
|
312
|
-
public
|
|
292
|
+
public $dataValue: DataValue;
|
|
313
293
|
public accessLevel: number;
|
|
314
294
|
public userAccessLevel?: number;
|
|
315
295
|
public valueRank: number;
|
|
@@ -346,11 +326,9 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
346
326
|
|
|
347
327
|
this.minimumSamplingInterval = adjust_samplingInterval(options.minimumSamplingInterval || 0);
|
|
348
328
|
|
|
349
|
-
this.historizing = !!options.historizing; // coerced to boolean
|
|
350
|
-
|
|
351
|
-
this._dataValue = new DataValue({ statusCode: StatusCodes.UncertainInitialValue, value: {} });
|
|
329
|
+
this.historizing = !!options.historizing; // coerced to boolean"
|
|
352
330
|
|
|
353
|
-
|
|
331
|
+
this.$dataValue = new DataValue({ statusCode: StatusCodes.UncertainInitialValue, value: { dataType: DataType.Null } });
|
|
354
332
|
|
|
355
333
|
if (options.value) {
|
|
356
334
|
this.bindVariable(options.value);
|
|
@@ -453,11 +431,12 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
453
431
|
|
|
454
432
|
if (this._timestamped_get_func) {
|
|
455
433
|
if (this._timestamped_get_func.length === 0) {
|
|
456
|
-
this
|
|
434
|
+
this.$dataValue = (this._timestamped_get_func as TimestampGetFunction1)() as DataValue;
|
|
435
|
+
this.verifyVariantCompatibility(this.$dataValue.value);
|
|
457
436
|
}
|
|
458
437
|
}
|
|
459
438
|
|
|
460
|
-
let dataValue = this
|
|
439
|
+
let dataValue = this.$dataValue;
|
|
461
440
|
|
|
462
441
|
if (isGoodish(dataValue.statusCode)) {
|
|
463
442
|
// note : extractRange will clone the dataValue
|
|
@@ -507,6 +486,8 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
507
486
|
public asyncRefresh(oldestDate: Date, callback: DataValueCallback): void;
|
|
508
487
|
public asyncRefresh(oldestDate: Date): Promise<DataValue>;
|
|
509
488
|
public asyncRefresh(...args: any[]): any {
|
|
489
|
+
this.verifyVariantCompatibility(this.$dataValue.value);
|
|
490
|
+
|
|
510
491
|
const oldestDate = args[0] as Date;
|
|
511
492
|
assert(oldestDate instanceof Date);
|
|
512
493
|
const callback = args[1] as DataValueCallback;
|
|
@@ -524,22 +505,36 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
524
505
|
}
|
|
525
506
|
}
|
|
526
507
|
|
|
527
|
-
if (this.
|
|
508
|
+
if (this.$dataValue.serverTimestamp && oldestDate.getTime() <= this.$dataValue.serverTimestamp!.getTime()) {
|
|
528
509
|
const dataValue = this.readValue();
|
|
529
510
|
dataValue.serverTimestamp = oldestDate;
|
|
530
511
|
dataValue.serverPicoseconds = 0;
|
|
531
512
|
return callback(null, dataValue);
|
|
532
513
|
}
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
514
|
+
|
|
515
|
+
try {
|
|
516
|
+
this.refreshFunc.call(this, (err: Error | null, dataValue?: DataValueLike) => {
|
|
517
|
+
if (err || !dataValue) {
|
|
518
|
+
errorLog(
|
|
519
|
+
"-------------- refresh call failed",
|
|
520
|
+
this.browseName.toString(),
|
|
521
|
+
this.nodeId.toString(),
|
|
522
|
+
err?.message
|
|
523
|
+
);
|
|
524
|
+
dataValue = { statusCode: StatusCodes.BadNoDataAvailable };
|
|
525
|
+
}
|
|
526
|
+
if (dataValue !== this.$dataValue) {
|
|
527
|
+
this._internal_set_dataValue(coerceDataValue(dataValue), null);
|
|
528
|
+
}
|
|
529
|
+
callback(err, this.$dataValue);
|
|
530
|
+
});
|
|
531
|
+
} catch (err) {
|
|
532
|
+
errorLog("-------------- refresh call failed 2", this.browseName.toString(), this.nodeId.toString());
|
|
533
|
+
errorLog(err);
|
|
534
|
+
const dataValue = new DataValue({ statusCode: StatusCodes.BadInternalError });
|
|
535
|
+
this._internal_set_dataValue(dataValue, null);
|
|
536
|
+
callback(err as Error, this.$dataValue);
|
|
537
|
+
}
|
|
543
538
|
}
|
|
544
539
|
|
|
545
540
|
public readEnumValue(): IEnumItem {
|
|
@@ -629,10 +624,76 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
629
624
|
}
|
|
630
625
|
}
|
|
631
626
|
|
|
632
|
-
public
|
|
627
|
+
public getBasicDataType(): DataType {
|
|
628
|
+
if (this._basicDataType) {
|
|
629
|
+
return this._basicDataType;
|
|
630
|
+
}
|
|
631
|
+
if (this.dataType.namespace === 0 && this.dataType.value === 0) {
|
|
632
|
+
return DataType.Null;
|
|
633
|
+
}
|
|
633
634
|
const addressSpace = this.addressSpace;
|
|
634
|
-
const
|
|
635
|
-
|
|
635
|
+
const dataTypeNode = addressSpace.findDataType(this.dataType)!;
|
|
636
|
+
const basicDataType = dataTypeNode ? dataTypeNode.getBasicDataType() : DataType.Null;
|
|
637
|
+
// const basicDataType = addressSpace.findCorrespondingBasicDataType(this.dataType);
|
|
638
|
+
this._basicDataType = basicDataType;
|
|
639
|
+
return basicDataType;
|
|
640
|
+
}
|
|
641
|
+
public adjustVariant(variant: Variant): Variant {
|
|
642
|
+
return adjustVariant(variant, this.valueRank, this.getBasicDataType());
|
|
643
|
+
}
|
|
644
|
+
public verifyVariantCompatibility(variant: Variant): void {
|
|
645
|
+
try {
|
|
646
|
+
// istanbul ignore next
|
|
647
|
+
if (Object.prototype.hasOwnProperty.call(variant, "value")) {
|
|
648
|
+
if (variant.dataType === null || variant.dataType === undefined) {
|
|
649
|
+
throw new Error("Variant must provide a valid dataType" + variant.toString());
|
|
650
|
+
}
|
|
651
|
+
if (
|
|
652
|
+
variant.dataType === DataType.Boolean &&
|
|
653
|
+
(this.dataType.namespace !== 0 || this.dataType.value !== DataType.Boolean)
|
|
654
|
+
) {
|
|
655
|
+
throw new Error("Variant must provide a valid Boolean" + variant.toString());
|
|
656
|
+
}
|
|
657
|
+
if (
|
|
658
|
+
this.dataType.namespace === 0 &&
|
|
659
|
+
this.dataType.value === DataType.LocalizedText &&
|
|
660
|
+
variant.dataType !== DataType.LocalizedText
|
|
661
|
+
) {
|
|
662
|
+
throw new Error("Variant must provide a valid LocalizedText" + variant.toString());
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
const basicType = this.getBasicDataType();
|
|
666
|
+
if (
|
|
667
|
+
basicType !== DataType.Null &&
|
|
668
|
+
basicType !== DataType.Variant &&
|
|
669
|
+
variant.dataType !== DataType.Null &&
|
|
670
|
+
variant.dataType !== basicType
|
|
671
|
+
) {
|
|
672
|
+
const message =
|
|
673
|
+
"UAVariable.setValueFromSource " +
|
|
674
|
+
this.browseName.toString() +
|
|
675
|
+
" nodeId:" +
|
|
676
|
+
this.nodeId.toString() +
|
|
677
|
+
" dataType:" +
|
|
678
|
+
this.dataType.toString() +
|
|
679
|
+
":\n" +
|
|
680
|
+
"the provided variant must have the expected dataType!\n" +
|
|
681
|
+
" - the expected dataType is " +
|
|
682
|
+
chalk.cyan(DataType[basicType]) +
|
|
683
|
+
"\n" +
|
|
684
|
+
" - the actual dataType is " +
|
|
685
|
+
chalk.magenta(DataType[variant.dataType]) +
|
|
686
|
+
"\n" +
|
|
687
|
+
" - " +
|
|
688
|
+
variant.toString();
|
|
689
|
+
throw new Error(message);
|
|
690
|
+
}
|
|
691
|
+
} catch (err) {
|
|
692
|
+
errorLog("UAVariable ", (err as Error)?.message, this.browseName.toString(), this.nodeId.toString());
|
|
693
|
+
errorLog((err as Error).message);
|
|
694
|
+
errorLog((err as Error).stack);
|
|
695
|
+
throw err;
|
|
696
|
+
}
|
|
636
697
|
}
|
|
637
698
|
/**
|
|
638
699
|
* setValueFromSource is used to let the device sets the variable values
|
|
@@ -646,39 +707,24 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
646
707
|
* @param [sourceTimestamp= Now]
|
|
647
708
|
*/
|
|
648
709
|
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
|
-
throw new Error("Variant must provide a valid LocalizedText" + variant.toString());
|
|
667
|
-
}
|
|
710
|
+
try {
|
|
711
|
+
statusCode = statusCode || StatusCodes.Good;
|
|
712
|
+
const variant1 = Variant.coerce(variant);
|
|
713
|
+
this.verifyVariantCompatibility(variant1);
|
|
714
|
+
const now = coerceClock(sourceTimestamp, 0);
|
|
715
|
+
|
|
716
|
+
const dataValue = new DataValue(null);
|
|
717
|
+
dataValue.serverPicoseconds = now.picoseconds;
|
|
718
|
+
dataValue.serverTimestamp = now.timestamp;
|
|
719
|
+
dataValue.sourcePicoseconds = now.picoseconds;
|
|
720
|
+
dataValue.sourceTimestamp = now.timestamp;
|
|
721
|
+
dataValue.statusCode = statusCode;
|
|
722
|
+
dataValue.value = variant1;
|
|
723
|
+
this._internal_set_dataValue(dataValue);
|
|
724
|
+
} catch (err) {
|
|
725
|
+
errorLog("UAVariable#setValueFromString Error : ", this.browseName.toString(), this.nodeId.toString());
|
|
726
|
+
throw err;
|
|
668
727
|
}
|
|
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
728
|
}
|
|
683
729
|
|
|
684
730
|
public writeValue(
|
|
@@ -775,6 +821,7 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
775
821
|
if (!err) {
|
|
776
822
|
correctedDataValue = correctedDataValue || dataValue;
|
|
777
823
|
assert(correctedDataValue instanceof DataValue);
|
|
824
|
+
correctedDataValue && this.verifyVariantCompatibility(correctedDataValue.value);
|
|
778
825
|
// xx assert(correctedDataValue.serverTimestamp);
|
|
779
826
|
|
|
780
827
|
if (indexRange && !indexRange.isEmpty()) {
|
|
@@ -785,12 +832,12 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
785
832
|
const newArrayOrMatrix = correctedDataValue.value.value;
|
|
786
833
|
|
|
787
834
|
if (correctedDataValue.value.arrayType === VariantArrayType.Array) {
|
|
788
|
-
if (this.
|
|
835
|
+
if (this.$dataValue.value.arrayType !== VariantArrayType.Array) {
|
|
789
836
|
return callback(null, StatusCodes.BadTypeMismatch);
|
|
790
837
|
}
|
|
791
838
|
// check that destination data is also an array
|
|
792
|
-
assert(check_valid_array(this.
|
|
793
|
-
const destArr = this.
|
|
839
|
+
assert(check_valid_array(this.$dataValue.value.dataType, this.$dataValue.value.value));
|
|
840
|
+
const destArr = this.$dataValue.value.value;
|
|
794
841
|
const result = indexRange.set_values(destArr, newArrayOrMatrix);
|
|
795
842
|
|
|
796
843
|
if (result.statusCode.isNot(StatusCodes.Good)) {
|
|
@@ -799,14 +846,14 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
799
846
|
correctedDataValue.value.value = result.array;
|
|
800
847
|
|
|
801
848
|
// scrap original array so we detect range
|
|
802
|
-
this.
|
|
849
|
+
this.$dataValue.value.value = null;
|
|
803
850
|
} else if (correctedDataValue.value.arrayType === VariantArrayType.Matrix) {
|
|
804
|
-
const dimensions = this.
|
|
805
|
-
if (this.
|
|
851
|
+
const dimensions = this.$dataValue.value.dimensions;
|
|
852
|
+
if (this.$dataValue.value.arrayType !== VariantArrayType.Matrix || !dimensions) {
|
|
806
853
|
// not a matrix !
|
|
807
854
|
return callback!(null, StatusCodes.BadTypeMismatch);
|
|
808
855
|
}
|
|
809
|
-
const matrix = this.
|
|
856
|
+
const matrix = this.$dataValue.value.value;
|
|
810
857
|
const result = indexRange.set_values_matrix(
|
|
811
858
|
{
|
|
812
859
|
matrix,
|
|
@@ -817,11 +864,11 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
817
864
|
if (result.statusCode.isNot(StatusCodes.Good)) {
|
|
818
865
|
return callback!(null, result.statusCode);
|
|
819
866
|
}
|
|
820
|
-
correctedDataValue.value.dimensions = this.
|
|
867
|
+
correctedDataValue.value.dimensions = this.$dataValue.value.dimensions;
|
|
821
868
|
correctedDataValue.value.value = result.matrix;
|
|
822
869
|
|
|
823
870
|
// scrap original array so we detect range
|
|
824
|
-
this.
|
|
871
|
+
this.$dataValue.value.value = null;
|
|
825
872
|
} else {
|
|
826
873
|
return callback!(null, StatusCodes.BadTypeMismatch);
|
|
827
874
|
}
|
|
@@ -903,6 +950,11 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
903
950
|
if (!this._validate_DataType(value.dataType)) {
|
|
904
951
|
return StatusCodes.BadTypeMismatch;
|
|
905
952
|
}
|
|
953
|
+
try {
|
|
954
|
+
this.verifyVariantCompatibility(value);
|
|
955
|
+
} catch(err) {
|
|
956
|
+
return StatusCodes.BadTypeMismatch;
|
|
957
|
+
}
|
|
906
958
|
return StatusCodes.Good;
|
|
907
959
|
}
|
|
908
960
|
|
|
@@ -917,12 +969,12 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
917
969
|
*/
|
|
918
970
|
public touchValue(optionalNow?: PreciseClock): void {
|
|
919
971
|
const now = optionalNow || getCurrentClock();
|
|
920
|
-
this.
|
|
921
|
-
this.
|
|
922
|
-
this.
|
|
923
|
-
this.
|
|
972
|
+
this.$dataValue.sourceTimestamp = now.timestamp;
|
|
973
|
+
this.$dataValue.sourcePicoseconds = now.picoseconds;
|
|
974
|
+
this.$dataValue.serverTimestamp = now.timestamp;
|
|
975
|
+
this.$dataValue.serverPicoseconds = now.picoseconds;
|
|
924
976
|
|
|
925
|
-
this.
|
|
977
|
+
this.$dataValue.statusCode = StatusCodes.Good;
|
|
926
978
|
|
|
927
979
|
if (this.minimumSamplingInterval === 0) {
|
|
928
980
|
if (this.listenerCount("value_changed") > 0) {
|
|
@@ -1106,7 +1158,7 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
1106
1158
|
}
|
|
1107
1159
|
|
|
1108
1160
|
const readImmediate = (innerCallback: (err: Error | null, dataValue: DataValue) => void) => {
|
|
1109
|
-
assert(this
|
|
1161
|
+
assert(this.$dataValue instanceof DataValue);
|
|
1110
1162
|
const dataValue = this.readValue();
|
|
1111
1163
|
innerCallback(null, dataValue);
|
|
1112
1164
|
};
|
|
@@ -1181,7 +1233,7 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
1181
1233
|
assert(typeof newVariable._timestamped_set_func === "function");
|
|
1182
1234
|
|
|
1183
1235
|
assert(newVariable.dataType === this.dataType);
|
|
1184
|
-
newVariable
|
|
1236
|
+
newVariable.$dataValue = this.$dataValue.clone();
|
|
1185
1237
|
return newVariable;
|
|
1186
1238
|
}
|
|
1187
1239
|
|
|
@@ -1204,8 +1256,10 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
1204
1256
|
return true;
|
|
1205
1257
|
}
|
|
1206
1258
|
const addressSpace = this.addressSpace;
|
|
1259
|
+
|
|
1260
|
+
// istanbul ignore next
|
|
1207
1261
|
if (!(extObj && extObj.constructor)) {
|
|
1208
|
-
|
|
1262
|
+
errorLog(extObj);
|
|
1209
1263
|
throw new Error("expecting an valid extension object");
|
|
1210
1264
|
}
|
|
1211
1265
|
const dataType = addressSpace.findDataType(this.dataType);
|
|
@@ -1231,7 +1285,7 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
1231
1285
|
return extObj.constructor.name === Constructor.name;
|
|
1232
1286
|
}
|
|
1233
1287
|
} catch (err) {
|
|
1234
|
-
|
|
1288
|
+
errorLog(err);
|
|
1235
1289
|
return false;
|
|
1236
1290
|
}
|
|
1237
1291
|
}
|
|
@@ -1252,7 +1306,7 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
1252
1306
|
|
|
1253
1307
|
// istanbul ignore next
|
|
1254
1308
|
if (doDebug) {
|
|
1255
|
-
|
|
1309
|
+
debugLog(" ------------------------------ binding ", this.browseName.toString(), this.nodeId.toString());
|
|
1256
1310
|
}
|
|
1257
1311
|
assert(structure && structure.browseName.toString() === "Structure", "expecting DataType Structure to be in IAddressSpace");
|
|
1258
1312
|
|
|
@@ -1277,14 +1331,14 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
1277
1331
|
// }
|
|
1278
1332
|
// istanbul ignore next
|
|
1279
1333
|
if (!this.checkExtensionObjectIsCorrect(this.$extensionObject!)) {
|
|
1280
|
-
|
|
1334
|
+
warningLog(
|
|
1281
1335
|
"on node : ",
|
|
1282
1336
|
this.browseName.toString(),
|
|
1283
1337
|
this.nodeId.toString(),
|
|
1284
1338
|
"dataType=",
|
|
1285
1339
|
this.dataType.toString({ addressSpace: this.addressSpace })
|
|
1286
1340
|
);
|
|
1287
|
-
|
|
1341
|
+
warningLog(this.$extensionObject?.toString());
|
|
1288
1342
|
throw new Error(
|
|
1289
1343
|
"bindExtensionObject: $extensionObject is incorrect: we are expecting a " +
|
|
1290
1344
|
this.dataType.toString({ addressSpace: this.addressSpace }) +
|
|
@@ -1299,45 +1353,33 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
1299
1353
|
|
|
1300
1354
|
// ------------------------------------------------------------------
|
|
1301
1355
|
|
|
1302
|
-
function prepareVariantValue(dataType: DataType
|
|
1303
|
-
if (typeof dataType === "string") {
|
|
1304
|
-
dataType = (DataType as any)[dataType];
|
|
1305
|
-
}
|
|
1356
|
+
function prepareVariantValue(dataType: DataType, value: VariantLike): VariantLike {
|
|
1306
1357
|
if ((dataType === DataType.Int32 || dataType === DataType.UInt32) && value && (value as any).key) {
|
|
1307
1358
|
value = value.value;
|
|
1308
1359
|
}
|
|
1309
1360
|
return value;
|
|
1310
1361
|
}
|
|
1311
1362
|
|
|
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));
|
|
1363
|
+
const bindProperty = (propertyNode: UAVariableImpl, name: string, extensionObject: ExtensionObject, dataType: DataType) => {
|
|
1323
1364
|
|
|
1324
1365
|
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
1325
1366
|
const self = this;
|
|
1326
1367
|
propertyNode.bindVariable(
|
|
1327
1368
|
{
|
|
1328
1369
|
timestamped_get: () => {
|
|
1329
|
-
const
|
|
1370
|
+
const propertyValue = self.$extensionObject[name];
|
|
1330
1371
|
|
|
1331
|
-
if (
|
|
1332
|
-
propertyNode.
|
|
1333
|
-
propertyNode.
|
|
1334
|
-
propertyNode.
|
|
1335
|
-
return new DataValue(propertyNode
|
|
1372
|
+
if (propertyValue === undefined) {
|
|
1373
|
+
propertyNode.$dataValue.value.dataType = DataType.Null;
|
|
1374
|
+
propertyNode.$dataValue.statusCode = StatusCodes.Good;
|
|
1375
|
+
propertyNode.$dataValue.value.value = null;
|
|
1376
|
+
return new DataValue(propertyNode.$dataValue);
|
|
1336
1377
|
}
|
|
1337
|
-
const value = prepareVariantValue(
|
|
1338
|
-
propertyNode.
|
|
1339
|
-
propertyNode.
|
|
1340
|
-
|
|
1378
|
+
const value = prepareVariantValue(dataType, propertyValue);
|
|
1379
|
+
propertyNode.$dataValue.statusCode = StatusCodes.Good;
|
|
1380
|
+
propertyNode.$dataValue.value.dataType = dataType;
|
|
1381
|
+
propertyNode.$dataValue.value.value = value;
|
|
1382
|
+
return new DataValue(propertyNode.$dataValue);
|
|
1341
1383
|
},
|
|
1342
1384
|
timestamped_set: (dataValue: DataValue, callback: CallbackT<StatusCode>) => {
|
|
1343
1385
|
dataValue;
|
|
@@ -1355,8 +1397,8 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
1355
1397
|
const s = this.readValue();
|
|
1356
1398
|
// istanbul ignore next
|
|
1357
1399
|
if (this.dataTypeObj.isAbstract) {
|
|
1358
|
-
|
|
1359
|
-
|
|
1400
|
+
warningLog("Warning the DataType associated with this Variable is abstract ", this.dataTypeObj.browseName.toString());
|
|
1401
|
+
warningLog("You need to provide a extension object yourself ");
|
|
1360
1402
|
throw new Error("bindExtensionObject requires a extensionObject as associated dataType is only abstract");
|
|
1361
1403
|
}
|
|
1362
1404
|
if (s.value && (s.value.dataType === DataType.Null || (s.value.dataType === DataType.ExtensionObject && !s.value.value))) {
|
|
@@ -1376,8 +1418,8 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
1376
1418
|
this.bindVariable(
|
|
1377
1419
|
{
|
|
1378
1420
|
timestamped_get() {
|
|
1379
|
-
self.
|
|
1380
|
-
const d = new DataValue(self
|
|
1421
|
+
self.$dataValue.value.value = self.$extensionObject;
|
|
1422
|
+
const d = new DataValue(self.$dataValue);
|
|
1381
1423
|
d.value = new Variant(d.value);
|
|
1382
1424
|
return d;
|
|
1383
1425
|
},
|
|
@@ -1386,7 +1428,6 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
1386
1428
|
if (!self.checkExtensionObjectIsCorrect(ext)) {
|
|
1387
1429
|
return callback(null, StatusCodes.BadInvalidArgument);
|
|
1388
1430
|
}
|
|
1389
|
-
|
|
1390
1431
|
self.$extensionObject = new Proxy(ext, makeHandler(self));
|
|
1391
1432
|
self.touchValue();
|
|
1392
1433
|
callback(null, StatusCodes.Good);
|
|
@@ -1402,51 +1443,66 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
1402
1443
|
assert(s.statusCode.equals(StatusCodes.Good));
|
|
1403
1444
|
}
|
|
1404
1445
|
|
|
1405
|
-
let property: any;
|
|
1406
|
-
let camelCaseName: any;
|
|
1407
1446
|
// ------------------------------------------------------
|
|
1408
1447
|
// now bind each member
|
|
1409
1448
|
// ------------------------------------------------------
|
|
1410
|
-
const definition = dt._getDefinition(
|
|
1449
|
+
const definition = dt._getDefinition() as StructureDefinition | null;
|
|
1411
1450
|
|
|
1412
1451
|
// istanbul ignore next
|
|
1413
1452
|
if (!definition) {
|
|
1414
1453
|
throw new Error("xx definition missing in " + dt.toString());
|
|
1415
1454
|
}
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1455
|
+
|
|
1456
|
+
const getOrCreateProperty = (field: StructureField): UAVariableImpl => {
|
|
1457
|
+
let property: UAVariableImpl;
|
|
1458
|
+
const selectedComponents = components.filter(
|
|
1459
|
+
(f) => f instanceof UAVariableImpl && f.browseName.name!.toString() === field.name
|
|
1460
|
+
);
|
|
1461
|
+
|
|
1462
|
+
if (field.dataType.value === DataType.Variant) {
|
|
1463
|
+
warningLog("Warning : variant is not supported in ExtensionObject");
|
|
1464
|
+
}
|
|
1465
|
+
if (selectedComponents.length === 1) {
|
|
1466
|
+
property = selectedComponents[0] as UAVariableImpl;
|
|
1421
1467
|
/* istanbul ignore next */
|
|
1422
1468
|
} else {
|
|
1469
|
+
debugLog("adding missing array variable", field.name, this.browseName.toString(), this.nodeId.toString());
|
|
1423
1470
|
// todo: Handle array appropriately...
|
|
1424
|
-
assert(
|
|
1471
|
+
assert(selectedComponents.length === 0);
|
|
1425
1472
|
// create a variable (Note we may use ns=1;s=parentName/0:PropertyName)
|
|
1426
1473
|
property = this.namespace.addVariable({
|
|
1427
1474
|
browseName: { namespaceIndex: structureNamespace, name: field.name!.toString() },
|
|
1428
1475
|
componentOf: this,
|
|
1429
1476
|
dataType: field.dataType,
|
|
1430
1477
|
minimumSamplingInterval: this.minimumSamplingInterval
|
|
1431
|
-
});
|
|
1478
|
+
}) as UAVariableImpl;
|
|
1432
1479
|
assert(property.minimumSamplingInterval === this.minimumSamplingInterval);
|
|
1433
1480
|
}
|
|
1481
|
+
return property;
|
|
1482
|
+
};
|
|
1434
1483
|
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1484
|
+
for (const field of definition.fields || []) {
|
|
1485
|
+
|
|
1438
1486
|
if (NodeId.sameNodeId(NodeId.nullNodeId, field.dataType)) {
|
|
1439
|
-
|
|
1440
|
-
|
|
1487
|
+
warningLog("field.dataType is null ! ", field.toString(), NodeId.nullNodeId.toString());
|
|
1488
|
+
warningLog(" dataType replaced with BaseDataType ");
|
|
1489
|
+
warningLog(definition.toString());
|
|
1441
1490
|
field.dataType = this.resolveNodeId("BaseDataType");
|
|
1442
1491
|
}
|
|
1443
|
-
|
|
1492
|
+
|
|
1493
|
+
const camelCaseName = lowerFirstLetter(field.name!);
|
|
1444
1494
|
assert(Object.prototype.hasOwnProperty.call(this.$extensionObject, camelCaseName));
|
|
1445
1495
|
|
|
1496
|
+
const propertyNode = getOrCreateProperty(field);
|
|
1497
|
+
|
|
1498
|
+
propertyNode.$dataValue.statusCode = StatusCodes.Good;
|
|
1499
|
+
propertyNode.touchValue();
|
|
1500
|
+
|
|
1501
|
+
const basicDataType = addressSpace.findCorrespondingBasicDataType(field.dataType);
|
|
1502
|
+
|
|
1446
1503
|
// istanbul ignore next
|
|
1447
1504
|
if (doDebug) {
|
|
1448
1505
|
const x = addressSpace.findNode(field.dataType)!.browseName.toString();
|
|
1449
|
-
const basicType = addressSpace.findCorrespondingBasicDataType(field.dataType);
|
|
1450
1506
|
debugLog(
|
|
1451
1507
|
chalk.cyan("xxx"),
|
|
1452
1508
|
" dataType",
|
|
@@ -1456,52 +1512,56 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
1456
1512
|
chalk.cyan(w(valueRankToString(field.valueRank), 10)),
|
|
1457
1513
|
chalk.green(w(x, 25)),
|
|
1458
1514
|
"basicType = ",
|
|
1459
|
-
chalk.yellow(w(
|
|
1460
|
-
|
|
1461
|
-
|
|
1515
|
+
chalk.yellow(w(basicDataType.toString(), 20)),
|
|
1516
|
+
propertyNode.nodeId.toString(),
|
|
1517
|
+
propertyNode.readValue().statusCode.toString()
|
|
1462
1518
|
);
|
|
1463
1519
|
}
|
|
1464
|
-
if (this.$extensionObject[camelCaseName] !== undefined &&
|
|
1520
|
+
if (this.$extensionObject[camelCaseName] !== undefined && basicDataType === DataType.ExtensionObject) {
|
|
1465
1521
|
assert(this.$extensionObject[camelCaseName] instanceof Object);
|
|
1466
|
-
this.$extensionObject[camelCaseName] = new Proxy(this.$extensionObject[camelCaseName], makeHandler(
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1522
|
+
this.$extensionObject[camelCaseName] = new Proxy(this.$extensionObject[camelCaseName], makeHandler(propertyNode));
|
|
1523
|
+
|
|
1524
|
+
propertyNode._internal_set_value(
|
|
1525
|
+
new Variant({
|
|
1526
|
+
dataType: DataType.ExtensionObject,
|
|
1527
|
+
value: this.$extensionObject[camelCaseName]
|
|
1528
|
+
})
|
|
1529
|
+
);
|
|
1530
|
+
|
|
1531
|
+
propertyNode.bindExtensionObject();
|
|
1532
|
+
propertyNode.$extensionObject = this.$extensionObject[camelCaseName];
|
|
1473
1533
|
} else {
|
|
1474
|
-
const dataTypeAsString = DataType[dataTypeNodeId];
|
|
1475
|
-
assert(typeof dataTypeAsString === "string");
|
|
1476
1534
|
const prop = this.$extensionObject[camelCaseName];
|
|
1477
|
-
|
|
1478
1535
|
if (prop === undefined) {
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1536
|
+
propertyNode._internal_set_value(
|
|
1537
|
+
new Variant({
|
|
1538
|
+
dataType: DataType.Null
|
|
1539
|
+
})
|
|
1540
|
+
);
|
|
1482
1541
|
} else {
|
|
1483
|
-
const preparedValue = prepareVariantValue(
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1542
|
+
const preparedValue = prepareVariantValue(basicDataType, prop);
|
|
1543
|
+
propertyNode._internal_set_value(
|
|
1544
|
+
new Variant({
|
|
1545
|
+
dataType: basicDataType,
|
|
1546
|
+
value: preparedValue
|
|
1547
|
+
})
|
|
1548
|
+
);
|
|
1488
1549
|
}
|
|
1489
1550
|
|
|
1490
1551
|
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
1491
1552
|
const self = this;
|
|
1492
|
-
property.camelCaseName = camelCaseName;
|
|
1493
|
-
|
|
1553
|
+
// property.camelCaseName = camelCaseName;
|
|
1554
|
+
propertyNode.setValueFromSource = function (this: UAVariableImpl, variant: VariantLike) {
|
|
1494
1555
|
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
1495
1556
|
const inner_this = this;
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
self.$extensionObject[inner_this.camelCaseName] = variant.value;
|
|
1557
|
+
const variant1 = Variant.coerce(variant);
|
|
1558
|
+
inner_this.verifyVariantCompatibility(variant1);
|
|
1559
|
+
self.$extensionObject[camelCaseName] = variant1.value;
|
|
1500
1560
|
self.touchValue();
|
|
1501
1561
|
};
|
|
1502
1562
|
}
|
|
1503
|
-
assert(
|
|
1504
|
-
bindProperty(
|
|
1563
|
+
assert(propertyNode.readValue().statusCode.equals(StatusCodes.Good));
|
|
1564
|
+
bindProperty(propertyNode, camelCaseName, this.$extensionObject, basicDataType);
|
|
1505
1565
|
}
|
|
1506
1566
|
assert(this.$extensionObject instanceof Object);
|
|
1507
1567
|
return this.$extensionObject;
|
|
@@ -1543,7 +1603,6 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
1543
1603
|
c1[name] = c2[name];
|
|
1544
1604
|
c1[name] += 1;
|
|
1545
1605
|
|
|
1546
|
-
// xx console.log(partialData);
|
|
1547
1606
|
setExtensionObjectValue(this, partialData);
|
|
1548
1607
|
}
|
|
1549
1608
|
|
|
@@ -1687,10 +1746,16 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
1687
1746
|
return validateDataType(this.addressSpace, this.dataType, variantDataType, this.nodeId, /* allow Nulls */ false);
|
|
1688
1747
|
}
|
|
1689
1748
|
|
|
1749
|
+
public _internal_set_value(value: Variant): void {
|
|
1750
|
+
if (value.dataType !== DataType.Null) {
|
|
1751
|
+
this.verifyVariantCompatibility(value);
|
|
1752
|
+
}
|
|
1753
|
+
this.$dataValue.value = value;
|
|
1754
|
+
}
|
|
1690
1755
|
public _internal_set_dataValue(dataValue: DataValue, indexRange?: NumericRange | null): void {
|
|
1691
1756
|
assert(dataValue, "expecting a dataValue");
|
|
1692
1757
|
assert(dataValue instanceof DataValue, "expecting dataValue to be a DataValue");
|
|
1693
|
-
assert(dataValue !== this
|
|
1758
|
+
assert(dataValue !== this.$dataValue, "expecting dataValue to be different from previous DataValue instance");
|
|
1694
1759
|
|
|
1695
1760
|
if (dataValue.value.arrayType === VariantArrayType.Matrix) {
|
|
1696
1761
|
if (!dataValue.value.dimensions) {
|
|
@@ -1714,27 +1779,31 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
1714
1779
|
// istanbul ignore next
|
|
1715
1780
|
if (this.dataType.namespace === 0) {
|
|
1716
1781
|
if (this.dataType.value === DataType.LocalizedText && dataValue.value.dataType !== DataType.LocalizedText) {
|
|
1717
|
-
|
|
1782
|
+
const message = "Invalid dataValue provided (expecting a LocalizedText) but got " + dataValue.toString();
|
|
1783
|
+
errorLog(message);
|
|
1784
|
+
throw new Error(message);
|
|
1718
1785
|
}
|
|
1719
1786
|
}
|
|
1720
1787
|
|
|
1721
|
-
|
|
1788
|
+
this.verifyVariantCompatibility(dataValue.value);
|
|
1722
1789
|
|
|
1723
|
-
|
|
1724
|
-
|
|
1790
|
+
const old_dataValue = this.$dataValue;
|
|
1791
|
+
|
|
1792
|
+
this.$dataValue = dataValue;
|
|
1793
|
+
this.$dataValue.statusCode = this.$dataValue.statusCode || StatusCodes.Good;
|
|
1725
1794
|
|
|
1726
1795
|
// repair missing timestamps
|
|
1727
1796
|
if (!dataValue.serverTimestamp) {
|
|
1728
|
-
this.
|
|
1729
|
-
this.
|
|
1797
|
+
this.$dataValue.serverTimestamp = old_dataValue.serverTimestamp;
|
|
1798
|
+
this.$dataValue.serverPicoseconds = old_dataValue.serverPicoseconds;
|
|
1730
1799
|
}
|
|
1731
1800
|
if (!dataValue.sourceTimestamp) {
|
|
1732
|
-
this.
|
|
1733
|
-
this.
|
|
1801
|
+
this.$dataValue.sourceTimestamp = old_dataValue.sourceTimestamp;
|
|
1802
|
+
this.$dataValue.sourcePicoseconds = old_dataValue.sourcePicoseconds;
|
|
1734
1803
|
}
|
|
1735
1804
|
|
|
1736
1805
|
if (!sameDataValue(old_dataValue, dataValue)) {
|
|
1737
|
-
this.emit("value_changed", this
|
|
1806
|
+
this.emit("value_changed", this.$dataValue, indexRange);
|
|
1738
1807
|
}
|
|
1739
1808
|
}
|
|
1740
1809
|
|
|
@@ -1930,10 +1999,10 @@ function _calculateEffectiveUserAccessLevelFromPermission(
|
|
|
1930
1999
|
}
|
|
1931
2000
|
}
|
|
1932
2001
|
|
|
1933
|
-
function adjustVariant2(this:
|
|
2002
|
+
function adjustVariant2(this: UAVariableImpl, variant: Variant): Variant {
|
|
1934
2003
|
// convert Variant( Scalar|ByteString) => Variant(Array|ByteArray)
|
|
1935
2004
|
const addressSpace = this.addressSpace;
|
|
1936
|
-
const basicType =
|
|
2005
|
+
const basicType = this.getBasicDataType();
|
|
1937
2006
|
variant = adjustVariant(variant, this.valueRank, basicType);
|
|
1938
2007
|
return variant;
|
|
1939
2008
|
}
|
|
@@ -1992,7 +2061,7 @@ function _Variable_bind_with_async_refresh(this: UAVariableImpl, options: any) {
|
|
|
1992
2061
|
this.refreshFunc = options.refreshFunc;
|
|
1993
2062
|
|
|
1994
2063
|
// assert(this.readValue().statusCode === StatusCodes.BadNodeIdUnknown);
|
|
1995
|
-
this.
|
|
2064
|
+
this.$dataValue.statusCode = StatusCodes.UncertainInitialValue;
|
|
1996
2065
|
|
|
1997
2066
|
// TO DO : REVISIT THIS ASSUMPTION
|
|
1998
2067
|
if (false && this.minimumSamplingInterval === 0) {
|
|
@@ -2014,7 +2083,10 @@ function _Variable_bind_with_timestamped_get(this: UAVariableImpl, options: any)
|
|
|
2014
2083
|
const async_refresh_func = (callback: (err: Error | null, dataValue?: DataValue) => void) => {
|
|
2015
2084
|
Promise.resolve((this._timestamped_get_func! as TimestampGetFunction1).call(this))
|
|
2016
2085
|
.then((dataValue) => callback(null, dataValue))
|
|
2017
|
-
.catch((err) =>
|
|
2086
|
+
.catch((err) => {
|
|
2087
|
+
errorLog("asyncRefresh error: Variable is ", this.nodeId.toString(), this.browseName.toString());
|
|
2088
|
+
callback(err as Error);
|
|
2089
|
+
});
|
|
2018
2090
|
};
|
|
2019
2091
|
|
|
2020
2092
|
if (options.timestamped_get.length === 0) {
|
|
@@ -2045,11 +2117,11 @@ function _Variable_bind_with_timestamped_get(this: UAVariableImpl, options: any)
|
|
|
2045
2117
|
}
|
|
2046
2118
|
|
|
2047
2119
|
// variation 1
|
|
2048
|
-
function _Variable_bind_with_simple_get(this: UAVariableImpl, options:
|
|
2120
|
+
function _Variable_bind_with_simple_get(this: UAVariableImpl, options: GetterOptions) {
|
|
2049
2121
|
/* jshint validthis: true */
|
|
2050
2122
|
assert(this instanceof UAVariableImpl);
|
|
2051
2123
|
assert(typeof options.get === "function", "should specify get function");
|
|
2052
|
-
assert(options.get
|
|
2124
|
+
assert(options.get!.length === 0, "get function should not have arguments");
|
|
2053
2125
|
assert(!options.timestamped_get, "should not specify a timestamped_get function when get is specified");
|
|
2054
2126
|
assert(!this._timestamped_get_func);
|
|
2055
2127
|
assert(!this._get_func);
|
|
@@ -2073,12 +2145,10 @@ function _Variable_bind_with_simple_get(this: UAVariableImpl, options: any) {
|
|
|
2073
2145
|
if (is_StatusCode(value)) {
|
|
2074
2146
|
return new DataValue({ statusCode: value });
|
|
2075
2147
|
} else {
|
|
2076
|
-
if (!this
|
|
2148
|
+
if (!this.$dataValue || !isGoodish(this.$dataValue.statusCode) || !sameVariant(this.$dataValue.value, value)) {
|
|
2077
2149
|
this.setValueFromSource(value, StatusCodes.Good);
|
|
2078
|
-
}
|
|
2079
|
-
|
|
2080
|
-
}
|
|
2081
|
-
return this._dataValue;
|
|
2150
|
+
}
|
|
2151
|
+
return this.$dataValue;
|
|
2082
2152
|
}
|
|
2083
2153
|
};
|
|
2084
2154
|
|
|
@@ -2105,11 +2175,13 @@ function _Variable_bind_with_simple_set(this: UAVariableImpl, options: any) {
|
|
|
2105
2175
|
) => {
|
|
2106
2176
|
assert(timestamped_value instanceof DataValue);
|
|
2107
2177
|
this._set_func(timestamped_value.value, (err: Error | null, statusCode: StatusCode) => {
|
|
2178
|
+
|
|
2179
|
+
// istanbul ignore next
|
|
2108
2180
|
if (!err && !statusCode) {
|
|
2109
|
-
|
|
2181
|
+
errorLog(
|
|
2110
2182
|
chalk.red("UAVariable Binding Error _set_func must return a StatusCode, check the bindVariable parameters")
|
|
2111
2183
|
);
|
|
2112
|
-
|
|
2184
|
+
errorLog(chalk.yellow("StatusCode.Good is assumed"));
|
|
2113
2185
|
return callback(err, StatusCodes.Good, timestamped_value);
|
|
2114
2186
|
}
|
|
2115
2187
|
callback(err, statusCode, timestamped_value);
|