node-opcua-address-space 2.66.1 → 2.67.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/address_space_ts.js.map +1 -1
- package/dist/source/continuation_points/continuation_point_manager.js +3 -0
- package/dist/source/continuation_points/continuation_point_manager.js.map +1 -1
- package/dist/source/loader/make_xml_extension_object_parser.js +28 -9
- package/dist/source/loader/make_xml_extension_object_parser.js.map +1 -1
- package/dist/src/base_node_impl.js +1 -1
- package/dist/src/base_node_impl.js.map +1 -1
- package/dist/src/extension_object_array_node.js +31 -22
- package/dist/src/extension_object_array_node.js.map +1 -1
- package/dist/src/reference_impl.js +1 -1
- package/dist/src/reference_impl.js.map +1 -1
- package/dist/src/ua_variable_impl.d.ts +9 -8
- package/dist/src/ua_variable_impl.js +54 -311
- package/dist/src/ua_variable_impl.js.map +1 -1
- package/dist/src/ua_variable_impl_ext_obj.d.ts +17 -0
- package/dist/src/ua_variable_impl_ext_obj.js +393 -0
- package/dist/src/ua_variable_impl_ext_obj.js.map +1 -0
- package/package.json +36 -36
- package/source/address_space_ts.ts +0 -2
- package/source/continuation_points/continuation_point_manager.ts +8 -6
- package/source/loader/make_xml_extension_object_parser.ts +32 -11
- package/src/base_node_impl.ts +1 -1
- package/src/extension_object_array_node.ts +43 -28
- package/src/reference_impl.ts +1 -1
- package/src/ua_variable_impl.ts +66 -379
- package/src/ua_variable_impl_ext_obj.ts +472 -0
- package/test_helpers/test_fixtures/issue_1132_variable_with_nodeid_value.xml +68 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CloneExtraInfo, ContinuationData, VariableDataValueSetterWithCallback } from "node-opcua-address-space-base";
|
|
1
|
+
import { BindExtensionObjectOptions, CloneExtraInfo, ContinuationData, VariableDataValueSetterWithCallback } from "node-opcua-address-space-base";
|
|
2
2
|
import { QualifiedNameLike, NodeClass, AccessLevelFlag, AttributeIds } from "node-opcua-data-model";
|
|
3
3
|
import { DataValue, DataValueT } from "node-opcua-data-value";
|
|
4
4
|
import { PreciseClock } from "node-opcua-date-time";
|
|
@@ -148,13 +148,8 @@ export declare class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
148
148
|
*/
|
|
149
149
|
checkVariantCompatibility(value: Variant): StatusCode;
|
|
150
150
|
/**
|
|
151
|
-
* @method touchValue
|
|
152
151
|
* touch the source timestamp of a Variable and cascade up the change
|
|
153
152
|
* to the parent variable if any.
|
|
154
|
-
*
|
|
155
|
-
* @param [optionalNow=null] {Object}
|
|
156
|
-
* @param optionalNow.timestamp {Date}
|
|
157
|
-
* @param optionalNow.picoseconds {Number}
|
|
158
153
|
*/
|
|
159
154
|
touchValue(optionalNow?: PreciseClock): void;
|
|
160
155
|
/**
|
|
@@ -290,16 +285,22 @@ export declare class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
290
285
|
getDataTypeNode(): UADataType;
|
|
291
286
|
get dataTypeObj(): UADataType;
|
|
292
287
|
checkExtensionObjectIsCorrect(extObj: ExtensionObject | ExtensionObject[] | null): boolean;
|
|
288
|
+
/**
|
|
289
|
+
* @private
|
|
290
|
+
* install UAVariable to exposed th
|
|
291
|
+
*
|
|
292
|
+
* precondition:
|
|
293
|
+
*/
|
|
294
|
+
installExtensionObjectVariables(): void;
|
|
293
295
|
/**
|
|
294
296
|
* @method bindExtensionObject
|
|
295
297
|
* @return {ExtensionObject}
|
|
296
298
|
*/
|
|
297
|
-
bindExtensionObject(optionalExtensionObject?: ExtensionObject): ExtensionObject | null;
|
|
299
|
+
bindExtensionObject(optionalExtensionObject?: ExtensionObject, options?: BindExtensionObjectOptions): ExtensionObject | null;
|
|
298
300
|
updateExtensionObjectPartial(partialExtensionObject?: {
|
|
299
301
|
[key: string]: any;
|
|
300
302
|
}): ExtensionObject;
|
|
301
303
|
incrementExtensionObjectPartial(path: string | string[]): void;
|
|
302
|
-
constructExtensionObjectFromComponents(): any;
|
|
303
304
|
toString(): string;
|
|
304
305
|
historyRead(context: ISessionContext, historyReadDetails: HistoryReadDetails | ReadRawModifiedDetails | ReadEventDetails | ReadProcessedDetails | ReadAtTimeDetails, indexRange: NumericRange | null, dataEncoding: QualifiedNameLike | null, continuationData: ContinuationData): Promise<HistoryReadResult>;
|
|
305
306
|
historyRead(context: ISessionContext, historyReadDetails: HistoryReadDetails | ReadRawModifiedDetails | ReadEventDetails | ReadProcessedDetails | ReadAtTimeDetails, indexRange: NumericRange | null, dataEncoding: QualifiedNameLike | null, continuationData: ContinuationData, callback: CallbackT<HistoryReadResult>): void;
|
|
@@ -22,7 +22,6 @@ const node_opcua_service_write_1 = require("node-opcua-service-write");
|
|
|
22
22
|
const node_opcua_status_code_1 = require("node-opcua-status-code");
|
|
23
23
|
const node_opcua_types_1 = require("node-opcua-types");
|
|
24
24
|
const utils = require("node-opcua-utils");
|
|
25
|
-
const node_opcua_utils_1 = require("node-opcua-utils");
|
|
26
25
|
const node_opcua_variant_1 = require("node-opcua-variant");
|
|
27
26
|
const session_context_1 = require("../source/session_context");
|
|
28
27
|
const multiform_func_1 = require("../source/helpers/multiform_func");
|
|
@@ -30,6 +29,7 @@ const base_node_impl_1 = require("./base_node_impl");
|
|
|
30
29
|
const base_node_private_1 = require("./base_node_private");
|
|
31
30
|
const ua_data_type_impl_1 = require("./ua_data_type_impl");
|
|
32
31
|
const apply_condition_refresh_1 = require("./apply_condition_refresh");
|
|
32
|
+
const ua_variable_impl_ext_obj_1 = require("./ua_variable_impl_ext_obj");
|
|
33
33
|
const debugLog = (0, node_opcua_debug_1.make_debugLog)(__filename);
|
|
34
34
|
const warningLog = (0, node_opcua_debug_1.make_warningLog)(__filename);
|
|
35
35
|
const doDebug = (0, node_opcua_debug_1.checkDebugFlag)(__filename);
|
|
@@ -478,7 +478,8 @@ class UAVariableImpl extends base_node_impl_1.BaseNodeImpl {
|
|
|
478
478
|
}
|
|
479
479
|
if (this.dataType.namespace === 0 &&
|
|
480
480
|
this.dataType.value === node_opcua_variant_1.DataType.LocalizedText &&
|
|
481
|
-
variant.dataType !== node_opcua_variant_1.DataType.LocalizedText &&
|
|
481
|
+
variant.dataType !== node_opcua_variant_1.DataType.LocalizedText &&
|
|
482
|
+
variant.dataType !== node_opcua_variant_1.DataType.Null) {
|
|
482
483
|
throw new Error("Variant must provide a valid LocalizedText : variant = " +
|
|
483
484
|
variant.toString() +
|
|
484
485
|
" this.dataType= " +
|
|
@@ -547,7 +548,21 @@ class UAVariableImpl extends base_node_impl_1.BaseNodeImpl {
|
|
|
547
548
|
dataValue.sourceTimestamp = now.timestamp;
|
|
548
549
|
dataValue.statusCode = statusCode;
|
|
549
550
|
dataValue.value = variant1;
|
|
550
|
-
|
|
551
|
+
if (dataValue.value.dataType === node_opcua_variant_1.DataType.ExtensionObject) {
|
|
552
|
+
this.$dataValue = dataValue;
|
|
553
|
+
(0, node_opcua_assert_1.assert)(this.checkExtensionObjectIsCorrect(dataValue.value.value));
|
|
554
|
+
// ----------------------------------
|
|
555
|
+
if (this.$extensionObject) {
|
|
556
|
+
// we have an extension object already bound to this node
|
|
557
|
+
// the client is asking us to replace the object entierly by a new one
|
|
558
|
+
const ext = dataValue.value.value;
|
|
559
|
+
(0, ua_variable_impl_ext_obj_1._setExtensionObject)(this, ext);
|
|
560
|
+
return;
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
else {
|
|
564
|
+
this._internal_set_dataValue(dataValue);
|
|
565
|
+
}
|
|
551
566
|
}
|
|
552
567
|
catch (err) {
|
|
553
568
|
errorLog("UAVariable#setValueFromString Error : ", this.browseName.toString(), this.nodeId.toString());
|
|
@@ -730,30 +745,12 @@ class UAVariableImpl extends base_node_impl_1.BaseNodeImpl {
|
|
|
730
745
|
return node_opcua_status_code_1.StatusCodes.Good;
|
|
731
746
|
}
|
|
732
747
|
/**
|
|
733
|
-
* @method touchValue
|
|
734
748
|
* touch the source timestamp of a Variable and cascade up the change
|
|
735
749
|
* to the parent variable if any.
|
|
736
|
-
*
|
|
737
|
-
* @param [optionalNow=null] {Object}
|
|
738
|
-
* @param optionalNow.timestamp {Date}
|
|
739
|
-
* @param optionalNow.picoseconds {Number}
|
|
740
750
|
*/
|
|
741
751
|
touchValue(optionalNow) {
|
|
742
752
|
const now = optionalNow || (0, node_opcua_date_time_1.getCurrentClock)();
|
|
743
|
-
this
|
|
744
|
-
this.$dataValue.sourcePicoseconds = now.picoseconds;
|
|
745
|
-
this.$dataValue.serverTimestamp = now.timestamp;
|
|
746
|
-
this.$dataValue.serverPicoseconds = now.picoseconds;
|
|
747
|
-
this.$dataValue.statusCode = node_opcua_status_code_1.StatusCodes.Good;
|
|
748
|
-
if (this.minimumSamplingInterval === 0) {
|
|
749
|
-
if (this.listenerCount("value_changed") > 0) {
|
|
750
|
-
const clonedDataValue = this.readValue();
|
|
751
|
-
this.emit("value_changed", clonedDataValue);
|
|
752
|
-
}
|
|
753
|
-
}
|
|
754
|
-
if (this.parent && this.parent.nodeClass === node_opcua_data_model_1.NodeClass.Variable) {
|
|
755
|
-
this.parent.touchValue(now);
|
|
756
|
-
}
|
|
753
|
+
(0, ua_variable_impl_ext_obj_1.propagateTouchValueUpward)(this, now);
|
|
757
754
|
}
|
|
758
755
|
/**
|
|
759
756
|
* bind a variable with a get and set functions.
|
|
@@ -972,6 +969,11 @@ class UAVariableImpl extends base_node_impl_1.BaseNodeImpl {
|
|
|
972
969
|
(0, node_opcua_assert_1.assert)(typeof newVariable._timestamped_set_func === "function");
|
|
973
970
|
(0, node_opcua_assert_1.assert)(newVariable.dataType === this.dataType);
|
|
974
971
|
newVariable.$dataValue = this.$dataValue.clone();
|
|
972
|
+
// also bind extension object
|
|
973
|
+
const v = newVariable.$dataValue.value;
|
|
974
|
+
if (v.dataType === node_opcua_variant_1.DataType.ExtensionObject && v.value && v.arrayType === node_opcua_variant_1.VariantArrayType.Scalar) {
|
|
975
|
+
newVariable.bindExtensionObject(newVariable.$dataValue.value.value);
|
|
976
|
+
}
|
|
975
977
|
return newVariable;
|
|
976
978
|
}
|
|
977
979
|
getDataTypeNode() {
|
|
@@ -1026,262 +1028,37 @@ class UAVariableImpl extends base_node_impl_1.BaseNodeImpl {
|
|
|
1026
1028
|
}
|
|
1027
1029
|
}
|
|
1028
1030
|
/**
|
|
1029
|
-
* @
|
|
1030
|
-
*
|
|
1031
|
+
* @private
|
|
1032
|
+
* install UAVariable to exposed th
|
|
1033
|
+
*
|
|
1034
|
+
* precondition:
|
|
1031
1035
|
*/
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
const
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
// bindExtensionObject cannot be performed and shall finish here.
|
|
1040
|
-
return null;
|
|
1041
|
-
}
|
|
1042
|
-
// istanbul ignore next
|
|
1043
|
-
if (doDebug) {
|
|
1044
|
-
debugLog(" ------------------------------ binding ", this.browseName.toString(), this.nodeId.toString());
|
|
1045
|
-
}
|
|
1046
|
-
(0, node_opcua_assert_1.assert)(structure && structure.browseName.toString() === "Structure", "expecting DataType Structure to be in IAddressSpace");
|
|
1047
|
-
const dt = this.getDataTypeNode();
|
|
1048
|
-
if (!dt.isSupertypeOf(structure)) {
|
|
1049
|
-
return null;
|
|
1050
|
-
}
|
|
1051
|
-
// the namespace for the structure browse name elements
|
|
1052
|
-
const structureNamespace = dt.nodeId.namespace;
|
|
1053
|
-
// -------------------- make sure we do not bind a variable twice ....
|
|
1054
|
-
if (this.$extensionObject) {
|
|
1055
|
-
// istanbul ignore next
|
|
1056
|
-
// if (!force && !utils.isNullOrUndefined(optionalExtensionObject)) {
|
|
1057
|
-
// throw new Error(
|
|
1058
|
-
// "bindExtensionObject: unsupported case : $extensionObject already exists on " +
|
|
1059
|
-
// this.browseName.toString() +
|
|
1060
|
-
// " " +
|
|
1061
|
-
// this.nodeId.toString()
|
|
1062
|
-
// );
|
|
1063
|
-
// }
|
|
1064
|
-
// istanbul ignore next
|
|
1065
|
-
if (!this.checkExtensionObjectIsCorrect(this.$extensionObject)) {
|
|
1066
|
-
warningLog("on node : ", this.browseName.toString(), this.nodeId.toString(), "dataType=", this.dataType.toString({ addressSpace: this.addressSpace }));
|
|
1067
|
-
warningLog((_a = this.$extensionObject) === null || _a === void 0 ? void 0 : _a.toString());
|
|
1068
|
-
throw new Error("bindExtensionObject: $extensionObject is incorrect: we are expecting a " +
|
|
1069
|
-
this.dataType.toString({ addressSpace: this.addressSpace }) +
|
|
1070
|
-
" but we got a " +
|
|
1071
|
-
((_b = this.$extensionObject) === null || _b === void 0 ? void 0 : _b.constructor.name));
|
|
1072
|
-
}
|
|
1073
|
-
return this.$extensionObject;
|
|
1074
|
-
// throw new Error("Variable already bound");
|
|
1075
|
-
}
|
|
1076
|
-
this.$extensionObject = optionalExtensionObject;
|
|
1077
|
-
// ------------------------------------------------------------------
|
|
1078
|
-
function prepareVariantValue(dataType, value) {
|
|
1079
|
-
if ((dataType === node_opcua_variant_1.DataType.Int32 || dataType === node_opcua_variant_1.DataType.UInt32) && value && value.key) {
|
|
1080
|
-
value = value.value;
|
|
1081
|
-
}
|
|
1082
|
-
return value;
|
|
1083
|
-
}
|
|
1084
|
-
const bindProperty = (propertyNode, name, extensionObject, dataType) => {
|
|
1085
|
-
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
1086
|
-
const self = this;
|
|
1087
|
-
propertyNode.bindVariable({
|
|
1088
|
-
timestamped_get: () => {
|
|
1089
|
-
const propertyValue = self.$extensionObject[name];
|
|
1090
|
-
if (propertyValue === undefined) {
|
|
1091
|
-
propertyNode.$dataValue.value.dataType = node_opcua_variant_1.DataType.Null;
|
|
1092
|
-
propertyNode.$dataValue.statusCode = node_opcua_status_code_1.StatusCodes.Good;
|
|
1093
|
-
propertyNode.$dataValue.value.value = null;
|
|
1094
|
-
return new node_opcua_data_value_1.DataValue(propertyNode.$dataValue);
|
|
1095
|
-
}
|
|
1096
|
-
const value = prepareVariantValue(dataType, propertyValue);
|
|
1097
|
-
propertyNode.$dataValue.statusCode = node_opcua_status_code_1.StatusCodes.Good;
|
|
1098
|
-
propertyNode.$dataValue.value.dataType = dataType;
|
|
1099
|
-
propertyNode.$dataValue.value.value = value;
|
|
1100
|
-
return new node_opcua_data_value_1.DataValue(propertyNode.$dataValue);
|
|
1101
|
-
},
|
|
1102
|
-
timestamped_set: (dataValue, callback) => {
|
|
1103
|
-
dataValue;
|
|
1104
|
-
callback(null, node_opcua_status_code_1.StatusCodes.BadNotWritable);
|
|
1036
|
+
installExtensionObjectVariables() {
|
|
1037
|
+
(0, ua_variable_impl_ext_obj_1._installExtensionObjectBindingOnProperties)(this, { createMissingProp: true });
|
|
1038
|
+
// now recursively install extension object on children
|
|
1039
|
+
for (const child of this.getComponents()) {
|
|
1040
|
+
if (child.nodeClass === node_opcua_data_model_1.NodeClass.Variable && child instanceof UAVariableImpl) {
|
|
1041
|
+
if (child.isExtensionObject()) {
|
|
1042
|
+
child.installExtensionObjectVariables();
|
|
1105
1043
|
}
|
|
1106
|
-
}, true);
|
|
1107
|
-
};
|
|
1108
|
-
const components = this.getComponents();
|
|
1109
|
-
// ------------------------------------------------------
|
|
1110
|
-
// make sure we have a structure
|
|
1111
|
-
// ------------------------------------------------------
|
|
1112
|
-
const s = this.readValue();
|
|
1113
|
-
// istanbul ignore next
|
|
1114
|
-
if (this.dataTypeObj.isAbstract) {
|
|
1115
|
-
warningLog("Warning the DataType associated with this Variable is abstract ", this.dataTypeObj.browseName.toString());
|
|
1116
|
-
warningLog("You need to provide a extension object yourself ");
|
|
1117
|
-
throw new Error("bindExtensionObject requires a extensionObject as associated dataType is only abstract");
|
|
1118
|
-
}
|
|
1119
|
-
if (s.value && (s.value.dataType === node_opcua_variant_1.DataType.Null || (s.value.dataType === node_opcua_variant_1.DataType.ExtensionObject && !s.value.value))) {
|
|
1120
|
-
// create a structure and bind it
|
|
1121
|
-
extensionObject_ = this.$extensionObject || addressSpace.constructExtensionObject(this.dataType, {});
|
|
1122
|
-
extensionObject_ = new Proxy(extensionObject_, makeHandler(this));
|
|
1123
|
-
this.$extensionObject = extensionObject_;
|
|
1124
|
-
const theValue = new node_opcua_variant_1.Variant({
|
|
1125
|
-
dataType: node_opcua_variant_1.DataType.ExtensionObject,
|
|
1126
|
-
value: this.$extensionObject
|
|
1127
|
-
});
|
|
1128
|
-
this.setValueFromSource(theValue, node_opcua_status_code_1.StatusCodes.Good);
|
|
1129
|
-
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
1130
|
-
const self = this;
|
|
1131
|
-
this.bindVariable({
|
|
1132
|
-
timestamped_get() {
|
|
1133
|
-
self.$dataValue.value.value = self.$extensionObject;
|
|
1134
|
-
const d = new node_opcua_data_value_1.DataValue(self.$dataValue);
|
|
1135
|
-
d.value = new node_opcua_variant_1.Variant(d.value);
|
|
1136
|
-
return d;
|
|
1137
|
-
},
|
|
1138
|
-
timestamped_set(dataValue, callback) {
|
|
1139
|
-
const ext = dataValue.value.value;
|
|
1140
|
-
if (!self.checkExtensionObjectIsCorrect(ext)) {
|
|
1141
|
-
return callback(null, node_opcua_status_code_1.StatusCodes.BadInvalidArgument);
|
|
1142
|
-
}
|
|
1143
|
-
self.$extensionObject = new Proxy(ext, makeHandler(self));
|
|
1144
|
-
self.touchValue();
|
|
1145
|
-
callback(null, node_opcua_status_code_1.StatusCodes.Good);
|
|
1146
|
-
}
|
|
1147
|
-
}, true);
|
|
1148
|
-
}
|
|
1149
|
-
else {
|
|
1150
|
-
// verify that variant has the correct type
|
|
1151
|
-
(0, node_opcua_assert_1.assert)(s.value.dataType === node_opcua_variant_1.DataType.ExtensionObject);
|
|
1152
|
-
this.$extensionObject = s.value.value;
|
|
1153
|
-
(0, node_opcua_assert_1.assert)(this.checkExtensionObjectIsCorrect(this.$extensionObject));
|
|
1154
|
-
(0, node_opcua_assert_1.assert)(s.statusCode.equals(node_opcua_status_code_1.StatusCodes.Good));
|
|
1155
|
-
}
|
|
1156
|
-
// ------------------------------------------------------
|
|
1157
|
-
// now bind each member
|
|
1158
|
-
// ------------------------------------------------------
|
|
1159
|
-
const definition = dt._getDefinition();
|
|
1160
|
-
// istanbul ignore next
|
|
1161
|
-
if (!definition) {
|
|
1162
|
-
throw new Error("xx definition missing in " + dt.toString());
|
|
1163
|
-
}
|
|
1164
|
-
const getOrCreateProperty = (field) => {
|
|
1165
|
-
let property;
|
|
1166
|
-
const selectedComponents = components.filter((f) => f instanceof UAVariableImpl && f.browseName.name.toString() === field.name);
|
|
1167
|
-
if (field.dataType.value === node_opcua_variant_1.DataType.Variant) {
|
|
1168
|
-
warningLog("Warning : variant is not supported in ExtensionObject");
|
|
1169
|
-
}
|
|
1170
|
-
if (selectedComponents.length === 1) {
|
|
1171
|
-
property = selectedComponents[0];
|
|
1172
|
-
/* istanbul ignore next */
|
|
1173
1044
|
}
|
|
1174
|
-
else {
|
|
1175
|
-
debugLog("adding missing array variable", field.name, this.browseName.toString(), this.nodeId.toString());
|
|
1176
|
-
// todo: Handle array appropriately...
|
|
1177
|
-
(0, node_opcua_assert_1.assert)(selectedComponents.length === 0);
|
|
1178
|
-
// create a variable (Note we may use ns=1;s=parentName/0:PropertyName)
|
|
1179
|
-
property = this.namespace.addVariable({
|
|
1180
|
-
browseName: { namespaceIndex: structureNamespace, name: field.name.toString() },
|
|
1181
|
-
componentOf: this,
|
|
1182
|
-
dataType: field.dataType,
|
|
1183
|
-
minimumSamplingInterval: this.minimumSamplingInterval
|
|
1184
|
-
});
|
|
1185
|
-
(0, node_opcua_assert_1.assert)(property.minimumSamplingInterval === this.minimumSamplingInterval);
|
|
1186
|
-
}
|
|
1187
|
-
return property;
|
|
1188
|
-
};
|
|
1189
|
-
for (const field of definition.fields || []) {
|
|
1190
|
-
if (node_opcua_nodeid_1.NodeId.sameNodeId(node_opcua_nodeid_1.NodeId.nullNodeId, field.dataType)) {
|
|
1191
|
-
warningLog("field.dataType is null ! ", field.toString(), node_opcua_nodeid_1.NodeId.nullNodeId.toString());
|
|
1192
|
-
warningLog(" dataType replaced with BaseDataType ");
|
|
1193
|
-
warningLog(definition.toString());
|
|
1194
|
-
field.dataType = this.resolveNodeId("BaseDataType");
|
|
1195
|
-
}
|
|
1196
|
-
const camelCaseName = (0, node_opcua_utils_1.lowerFirstLetter)(field.name);
|
|
1197
|
-
(0, node_opcua_assert_1.assert)(Object.prototype.hasOwnProperty.call(this.$extensionObject, camelCaseName));
|
|
1198
|
-
const propertyNode = getOrCreateProperty(field);
|
|
1199
|
-
propertyNode.$dataValue.statusCode = node_opcua_status_code_1.StatusCodes.Good;
|
|
1200
|
-
propertyNode.touchValue();
|
|
1201
|
-
const basicDataType = addressSpace.findCorrespondingBasicDataType(field.dataType);
|
|
1202
|
-
// istanbul ignore next
|
|
1203
|
-
if (doDebug) {
|
|
1204
|
-
const x = addressSpace.findNode(field.dataType).browseName.toString();
|
|
1205
|
-
debugLog(chalk.cyan("xxx"), " dataType", w(field.dataType.toString(), 8), w(field.name, 35), "valueRank", chalk.cyan(w((0, base_node_private_1.valueRankToString)(field.valueRank), 10)), chalk.green(w(x, 25)), "basicType = ", chalk.yellow(w(basicDataType.toString(), 20)), propertyNode.nodeId.toString(), propertyNode.readValue().statusCode.toString());
|
|
1206
|
-
}
|
|
1207
|
-
if (this.$extensionObject[camelCaseName] !== undefined && basicDataType === node_opcua_variant_1.DataType.ExtensionObject) {
|
|
1208
|
-
(0, node_opcua_assert_1.assert)(this.$extensionObject[camelCaseName] instanceof Object);
|
|
1209
|
-
this.$extensionObject[camelCaseName] = new Proxy(this.$extensionObject[camelCaseName], makeHandler(propertyNode));
|
|
1210
|
-
propertyNode._internal_set_value(new node_opcua_variant_1.Variant({
|
|
1211
|
-
dataType: node_opcua_variant_1.DataType.ExtensionObject,
|
|
1212
|
-
value: this.$extensionObject[camelCaseName]
|
|
1213
|
-
}));
|
|
1214
|
-
propertyNode.bindExtensionObject();
|
|
1215
|
-
propertyNode.$extensionObject = this.$extensionObject[camelCaseName];
|
|
1216
|
-
}
|
|
1217
|
-
else {
|
|
1218
|
-
const prop = this.$extensionObject[camelCaseName];
|
|
1219
|
-
if (prop === undefined) {
|
|
1220
|
-
propertyNode._internal_set_value(new node_opcua_variant_1.Variant({
|
|
1221
|
-
dataType: node_opcua_variant_1.DataType.Null
|
|
1222
|
-
}));
|
|
1223
|
-
}
|
|
1224
|
-
else {
|
|
1225
|
-
const preparedValue = prepareVariantValue(basicDataType, prop);
|
|
1226
|
-
propertyNode._internal_set_value(new node_opcua_variant_1.Variant({
|
|
1227
|
-
dataType: basicDataType,
|
|
1228
|
-
value: preparedValue
|
|
1229
|
-
}));
|
|
1230
|
-
}
|
|
1231
|
-
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
1232
|
-
const self = this;
|
|
1233
|
-
// property.camelCaseName = camelCaseName;
|
|
1234
|
-
propertyNode.setValueFromSource = function (variant) {
|
|
1235
|
-
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
1236
|
-
const inner_this = this;
|
|
1237
|
-
const variant1 = node_opcua_variant_1.Variant.coerce(variant);
|
|
1238
|
-
inner_this.verifyVariantCompatibility(variant1);
|
|
1239
|
-
self.$extensionObject[camelCaseName] = variant1.value;
|
|
1240
|
-
self.touchValue();
|
|
1241
|
-
};
|
|
1242
|
-
}
|
|
1243
|
-
(0, node_opcua_assert_1.assert)(propertyNode.readValue().statusCode.equals(node_opcua_status_code_1.StatusCodes.Good));
|
|
1244
|
-
bindProperty(propertyNode, camelCaseName, this.$extensionObject, basicDataType);
|
|
1245
1045
|
}
|
|
1246
|
-
|
|
1247
|
-
|
|
1046
|
+
}
|
|
1047
|
+
/**
|
|
1048
|
+
* @method bindExtensionObject
|
|
1049
|
+
* @return {ExtensionObject}
|
|
1050
|
+
*/
|
|
1051
|
+
bindExtensionObject(optionalExtensionObject, options) {
|
|
1052
|
+
return (0, ua_variable_impl_ext_obj_1._bindExtensionObject)(this, optionalExtensionObject, options);
|
|
1248
1053
|
}
|
|
1249
1054
|
updateExtensionObjectPartial(partialExtensionObject) {
|
|
1250
|
-
setExtensionObjectValue(this, partialExtensionObject);
|
|
1055
|
+
(0, ua_variable_impl_ext_obj_1.setExtensionObjectValue)(this, partialExtensionObject);
|
|
1251
1056
|
return this.$extensionObject;
|
|
1252
1057
|
}
|
|
1253
1058
|
incrementExtensionObjectPartial(path) {
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
}
|
|
1258
|
-
(0, node_opcua_assert_1.assert)(path instanceof Array);
|
|
1259
|
-
const extensionObject = this.constructExtensionObjectFromComponents();
|
|
1260
|
-
let i;
|
|
1261
|
-
// read partial value
|
|
1262
|
-
const partialData = {};
|
|
1263
|
-
let p = partialData;
|
|
1264
|
-
for (i = 0; i < path.length - 1; i++) {
|
|
1265
|
-
name = path[i];
|
|
1266
|
-
p[name] = {};
|
|
1267
|
-
p = p[name];
|
|
1268
|
-
}
|
|
1269
|
-
name = path[path.length - 1];
|
|
1270
|
-
p[name] = 0;
|
|
1271
|
-
let c1 = partialData;
|
|
1272
|
-
let c2 = extensionObject;
|
|
1273
|
-
for (i = 0; i < path.length - 1; i++) {
|
|
1274
|
-
name = path[i];
|
|
1275
|
-
c1 = partialData[name];
|
|
1276
|
-
c2 = extensionObject[name];
|
|
1277
|
-
}
|
|
1278
|
-
name = path[path.length - 1];
|
|
1279
|
-
c1[name] = c2[name];
|
|
1280
|
-
c1[name] += 1;
|
|
1281
|
-
setExtensionObjectValue(this, partialData);
|
|
1282
|
-
}
|
|
1283
|
-
constructExtensionObjectFromComponents() {
|
|
1284
|
-
return this.readValue().value.value;
|
|
1059
|
+
const extensionObject = this.readValue().value.value;
|
|
1060
|
+
const partialData = (0, ua_variable_impl_ext_obj_1.extractPartialData)(path, extensionObject);
|
|
1061
|
+
(0, ua_variable_impl_ext_obj_1.setExtensionObjectValue)(this, partialData);
|
|
1285
1062
|
}
|
|
1286
1063
|
toString() {
|
|
1287
1064
|
const options = new base_node_private_1.ToStringBuilder();
|
|
@@ -1356,6 +1133,14 @@ class UAVariableImpl extends base_node_impl_1.BaseNodeImpl {
|
|
|
1356
1133
|
warningLog(dataValue.toString());
|
|
1357
1134
|
throw new Error("Invalid Extension Object on nodeId =" + this.nodeId.toString());
|
|
1358
1135
|
}
|
|
1136
|
+
// ----------------------------------
|
|
1137
|
+
// if (this.$extensionObject) {
|
|
1138
|
+
// // we have an extension object already bound to this node
|
|
1139
|
+
// // the client is asking us to replace the object entierly by a new one
|
|
1140
|
+
// const ext = dataValue.value.value;
|
|
1141
|
+
// _setExtensionObject(this, ext);
|
|
1142
|
+
// return;
|
|
1143
|
+
// }
|
|
1359
1144
|
}
|
|
1360
1145
|
// // istanbul ignore next
|
|
1361
1146
|
// if (this.dataType.namespace === 0) {
|
|
@@ -1750,48 +1535,6 @@ function bind_getter(options) {
|
|
|
1750
1535
|
}
|
|
1751
1536
|
}
|
|
1752
1537
|
}
|
|
1753
|
-
function w(str, n) {
|
|
1754
|
-
return (str + " ").substr(0, n);
|
|
1755
|
-
}
|
|
1756
|
-
function _getter(target, key /*, receiver*/) {
|
|
1757
|
-
if (target[key] === undefined) {
|
|
1758
|
-
return undefined;
|
|
1759
|
-
}
|
|
1760
|
-
return target[key];
|
|
1761
|
-
}
|
|
1762
|
-
function _setter(variable, target, key, value /*, receiver*/) {
|
|
1763
|
-
target[key] = value;
|
|
1764
|
-
const child = variable[key];
|
|
1765
|
-
if (child && child.touchValue) {
|
|
1766
|
-
child.touchValue();
|
|
1767
|
-
}
|
|
1768
|
-
return true; // true means the set operation has succeeded
|
|
1769
|
-
}
|
|
1770
|
-
function makeHandler(variable) {
|
|
1771
|
-
const handler = {
|
|
1772
|
-
get: _getter,
|
|
1773
|
-
set: _setter.bind(null, variable)
|
|
1774
|
-
};
|
|
1775
|
-
return handler;
|
|
1776
|
-
}
|
|
1777
|
-
function setExtensionObjectValue(node, partialObject) {
|
|
1778
|
-
const extensionObject = node.$extensionObject;
|
|
1779
|
-
if (!extensionObject) {
|
|
1780
|
-
throw new Error("setExtensionObjectValue node has no extension object " + node.browseName.toString());
|
|
1781
|
-
}
|
|
1782
|
-
function _update_extension_object(extObject, partialObject1) {
|
|
1783
|
-
const keys = Object.keys(partialObject1);
|
|
1784
|
-
for (const prop of keys) {
|
|
1785
|
-
if (extObject[prop] instanceof Object) {
|
|
1786
|
-
_update_extension_object(extObject[prop], partialObject1[prop]);
|
|
1787
|
-
}
|
|
1788
|
-
else {
|
|
1789
|
-
extObject[prop] = partialObject1[prop];
|
|
1790
|
-
}
|
|
1791
|
-
}
|
|
1792
|
-
}
|
|
1793
|
-
_update_extension_object(extensionObject, partialObject);
|
|
1794
|
-
}
|
|
1795
1538
|
class UAVariableImplT extends UAVariableImpl {
|
|
1796
1539
|
}
|
|
1797
1540
|
exports.UAVariableImplT = UAVariableImplT;
|