node-opcua-address-space-base 2.98.2 → 2.100.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/clone_helper.d.ts +20 -0
- package/dist/clone_helper.js +270 -0
- package/dist/clone_helper.js.map +1 -0
- package/dist/clone_options.d.ts +3 -7
- package/dist/clone_options.js +4 -16
- package/dist/clone_options.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/ua_variable.d.ts +2 -2
- package/package.json +15 -13
- package/source/clone_helper.ts +343 -0
- package/source/clone_options.ts +5 -19
- package/source/index.ts +1 -0
- package/source/ua_variable.ts +2 -2
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { UAObject } from "./ua_object";
|
|
2
|
+
import { UAVariable } from "./ua_variable";
|
|
3
|
+
import { UAMethod } from "./ua_method";
|
|
4
|
+
import { UAObjectType } from "./ua_object_type";
|
|
5
|
+
import { UAVariableType } from "./ua_variable_type";
|
|
6
|
+
export declare class CloneHelper {
|
|
7
|
+
level: number;
|
|
8
|
+
private readonly mapOrgToClone;
|
|
9
|
+
pad(): string;
|
|
10
|
+
registerClonedObject<TO extends UAObject | UAVariable | UAMethod | UAObjectType | UAVariableType, TC extends UAObject | UAVariable | UAMethod>(clonedNode: TC, originalNode: TO): void;
|
|
11
|
+
getCloned(originalNode: UAVariableType | UAObjectType): UAObject | UAVariable | UAMethod | null;
|
|
12
|
+
}
|
|
13
|
+
export declare function reconstructNonHierarchicalReferences(extraInfo: CloneHelper): void;
|
|
14
|
+
/**
|
|
15
|
+
* recreate functional group types according to type definition
|
|
16
|
+
*
|
|
17
|
+
* @method reconstructFunctionalGroupType
|
|
18
|
+
* @param baseType
|
|
19
|
+
*/
|
|
20
|
+
export declare function reconstructFunctionalGroupType(extraInfo: CloneHelper): void;
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.reconstructFunctionalGroupType = exports.reconstructNonHierarchicalReferences = exports.CloneHelper = void 0;
|
|
4
|
+
const node_opcua_assert_1 = require("node-opcua-assert");
|
|
5
|
+
const node_opcua_debug_1 = require("node-opcua-debug");
|
|
6
|
+
const node_opcua_data_model_1 = require("node-opcua-data-model");
|
|
7
|
+
const node_opcua_nodeid_1 = require("node-opcua-nodeid");
|
|
8
|
+
const node_opcua_constants_1 = require("node-opcua-constants");
|
|
9
|
+
const debugLog = (0, node_opcua_debug_1.make_debugLog)("CLONE");
|
|
10
|
+
const doDebug = (0, node_opcua_debug_1.checkDebugFlag)("CLONE");
|
|
11
|
+
const warningLog = (0, node_opcua_debug_1.make_warningLog)("CLONE");
|
|
12
|
+
//
|
|
13
|
+
// case 1:
|
|
14
|
+
// /-----------------------------\
|
|
15
|
+
// | AcknowledgeableConditionType |
|
|
16
|
+
// \-----------------------------/
|
|
17
|
+
// ^ |
|
|
18
|
+
// | +---------------------|- (EnabledState) (shadow element)
|
|
19
|
+
// |
|
|
20
|
+
// /-----------------------------\
|
|
21
|
+
// | AlarmConditionType |
|
|
22
|
+
// \-----------------------------/
|
|
23
|
+
// |
|
|
24
|
+
// +-------------------------------|- EnabledState <
|
|
25
|
+
//
|
|
26
|
+
// find also child object with the same browse name that are
|
|
27
|
+
// overridden in the SuperType
|
|
28
|
+
// case 2:
|
|
29
|
+
//
|
|
30
|
+
// /-----------------------------\
|
|
31
|
+
// | MyDeviceType |
|
|
32
|
+
// \-----------------------------/
|
|
33
|
+
// ^ |
|
|
34
|
+
// | | +----------+
|
|
35
|
+
// | +-------| Folder1 |
|
|
36
|
+
// | +----------+
|
|
37
|
+
// | |
|
|
38
|
+
// | +--------------|- (EnabledState) (shadow element)
|
|
39
|
+
// |
|
|
40
|
+
// /-----------------------------\
|
|
41
|
+
// | MyDeriveDeviceType |
|
|
42
|
+
// \-----------------------------/
|
|
43
|
+
// |
|
|
44
|
+
// | | +----------+
|
|
45
|
+
// | +-------| Folder1 |
|
|
46
|
+
// | +----------+
|
|
47
|
+
// | |
|
|
48
|
+
// | +--------------|- (EnabledState)
|
|
49
|
+
//
|
|
50
|
+
// find also child object with the same browse name that are
|
|
51
|
+
function _get_parent_type_and_path(originalObject) {
|
|
52
|
+
if (originalObject.nodeClass === node_opcua_data_model_1.NodeClass.Method) {
|
|
53
|
+
return { parentType: null, path: [] };
|
|
54
|
+
}
|
|
55
|
+
const addressSpace = originalObject.addressSpace;
|
|
56
|
+
const parents = originalObject.findReferencesEx("HasChild", node_opcua_data_model_1.BrowseDirection.Inverse);
|
|
57
|
+
// istanbul ignore next
|
|
58
|
+
if (parents.length > 1) {
|
|
59
|
+
warningLog(" object ", originalObject.browseName.toString(), " has more than one parent !");
|
|
60
|
+
warningLog(originalObject.toString());
|
|
61
|
+
warningLog(" parents : ");
|
|
62
|
+
for (const parent of parents) {
|
|
63
|
+
warningLog(" ", parent.toString(), addressSpace.findNode(parent.nodeId).browseName.toString());
|
|
64
|
+
}
|
|
65
|
+
return { parentType: null, path: [] };
|
|
66
|
+
}
|
|
67
|
+
(0, node_opcua_assert_1.assert)(parents.length === 0 || parents.length === 1);
|
|
68
|
+
if (parents.length === 0) {
|
|
69
|
+
return { parentType: null, path: [] };
|
|
70
|
+
}
|
|
71
|
+
const theParent = addressSpace.findNode(parents[0].nodeId);
|
|
72
|
+
if (theParent && (theParent.nodeClass === node_opcua_data_model_1.NodeClass.VariableType || theParent.nodeClass === node_opcua_data_model_1.NodeClass.ObjectType)) {
|
|
73
|
+
return { parentType: theParent, path: [originalObject.browseName] };
|
|
74
|
+
}
|
|
75
|
+
// walk up
|
|
76
|
+
const { parentType, path } = _get_parent_type_and_path(theParent);
|
|
77
|
+
return { parentType, path: [...path, originalObject.browseName] };
|
|
78
|
+
}
|
|
79
|
+
function followPath(node, path) {
|
|
80
|
+
let current = node;
|
|
81
|
+
for (const qn of path) {
|
|
82
|
+
const ref = current
|
|
83
|
+
.findReferencesExAsObject("HierarchicalReferences", node_opcua_data_model_1.BrowseDirection.Forward)
|
|
84
|
+
.find((r) => r.browseName.toString() === qn.toString());
|
|
85
|
+
if (!ref) {
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
current = ref;
|
|
89
|
+
}
|
|
90
|
+
return current;
|
|
91
|
+
}
|
|
92
|
+
class CloneHelper {
|
|
93
|
+
constructor() {
|
|
94
|
+
this.level = 0;
|
|
95
|
+
this.mapOrgToClone = new Map();
|
|
96
|
+
}
|
|
97
|
+
pad() {
|
|
98
|
+
return " ".padEnd(this.level * 2, " ");
|
|
99
|
+
}
|
|
100
|
+
registerClonedObject(clonedNode, originalNode) {
|
|
101
|
+
this.mapOrgToClone.set(originalNode.nodeId.toString(), {
|
|
102
|
+
cloned: clonedNode,
|
|
103
|
+
original: originalNode
|
|
104
|
+
});
|
|
105
|
+
//
|
|
106
|
+
const { parentType, path } = _get_parent_type_and_path(originalNode);
|
|
107
|
+
if (parentType) {
|
|
108
|
+
let base = parentType.subtypeOfObj;
|
|
109
|
+
while (base) {
|
|
110
|
+
const shadowChild = followPath(base, path);
|
|
111
|
+
if (shadowChild) {
|
|
112
|
+
this.mapOrgToClone.set(shadowChild.nodeId.toString(), {
|
|
113
|
+
cloned: clonedNode,
|
|
114
|
+
original: shadowChild
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
base = base.subtypeOfObj;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
}
|
|
122
|
+
// find subTypeOf
|
|
123
|
+
}
|
|
124
|
+
getCloned(originalNode) {
|
|
125
|
+
const info = this.mapOrgToClone.get(originalNode.nodeId.toString());
|
|
126
|
+
if (info) {
|
|
127
|
+
return info.cloned;
|
|
128
|
+
}
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
exports.CloneHelper = CloneHelper;
|
|
133
|
+
const hasTypeDefinitionNodeId = (0, node_opcua_nodeid_1.makeNodeId)(node_opcua_constants_1.ReferenceTypeIds.HasTypeDefinition);
|
|
134
|
+
const hasModellingRuleNodeId = (0, node_opcua_nodeid_1.makeNodeId)(node_opcua_constants_1.ReferenceTypeIds.HasModellingRule);
|
|
135
|
+
/**
|
|
136
|
+
* remove unwanted reference such as HasTypeDefinition and HasModellingRule
|
|
137
|
+
* from the list
|
|
138
|
+
*/
|
|
139
|
+
function _remove_unwanted_ref(references) {
|
|
140
|
+
// filter out HasTypeDefinition (i=40) , HasModellingRule (i=37);
|
|
141
|
+
references = references.filter((reference) => !(0, node_opcua_nodeid_1.sameNodeId)(reference.referenceType, hasTypeDefinitionNodeId) &&
|
|
142
|
+
!(0, node_opcua_nodeid_1.sameNodeId)(reference.referenceType, hasModellingRuleNodeId));
|
|
143
|
+
return references;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
*
|
|
147
|
+
*/
|
|
148
|
+
function findNonHierarchicalReferences(originalObject) {
|
|
149
|
+
// todo: MEMOIZE this method
|
|
150
|
+
const addressSpace = originalObject.addressSpace;
|
|
151
|
+
// we need to explore the non hierarchical references backwards
|
|
152
|
+
let references = originalObject.findReferencesEx("NonHierarchicalReferences", node_opcua_data_model_1.BrowseDirection.Inverse);
|
|
153
|
+
references = [].concat(references, originalObject.findReferencesEx("HasEventSource", node_opcua_data_model_1.BrowseDirection.Inverse));
|
|
154
|
+
const { parentType, path } = _get_parent_type_and_path(originalObject);
|
|
155
|
+
if (parentType && parentType.subtypeOfObj) {
|
|
156
|
+
// parent is a ObjectType or VariableType and is not a root type
|
|
157
|
+
(0, node_opcua_assert_1.assert)(parentType.nodeClass === node_opcua_data_model_1.NodeClass.VariableType || parentType.nodeClass === node_opcua_data_model_1.NodeClass.ObjectType);
|
|
158
|
+
// let investigate the same child base child
|
|
159
|
+
const child = followPath(parentType.subtypeOfObj, path);
|
|
160
|
+
if (child) {
|
|
161
|
+
const baseRef = findNonHierarchicalReferences(child);
|
|
162
|
+
references = [].concat(references, baseRef);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
// perform some cleanup
|
|
166
|
+
references = _remove_unwanted_ref(references);
|
|
167
|
+
return references;
|
|
168
|
+
}
|
|
169
|
+
function reconstructNonHierarchicalReferences(extraInfo) {
|
|
170
|
+
const extraInfo_ = extraInfo;
|
|
171
|
+
const findImplementedObject = (ref) => extraInfo_.mapOrgToClone.get(ref.nodeId.toString()) || null;
|
|
172
|
+
// navigate through original objects to find those that are being references by node that
|
|
173
|
+
// have been cloned .
|
|
174
|
+
// this could be node organized by some FunctionalGroup
|
|
175
|
+
for (const { original, cloned } of extraInfo_.mapOrgToClone.values()) {
|
|
176
|
+
apply(original, cloned);
|
|
177
|
+
}
|
|
178
|
+
function apply(original, cloned) {
|
|
179
|
+
const addressSpace = original.addressSpace;
|
|
180
|
+
// find NonHierarchical References on original object
|
|
181
|
+
const originalNonHierarchical = findNonHierarchicalReferences(original);
|
|
182
|
+
if (originalNonHierarchical.length === 0) {
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
// istanbul ignore next
|
|
186
|
+
if (doDebug) {
|
|
187
|
+
debugLog(" investigation ", original.browseName.toString(), cloned.nodeClass.toString(), original.nodeClass.toString(), original.nodeId.toString(), cloned.nodeId.toString());
|
|
188
|
+
}
|
|
189
|
+
for (const ref of originalNonHierarchical) {
|
|
190
|
+
const info = findImplementedObject(ref);
|
|
191
|
+
// if the object pointed by this reference is also cloned ...
|
|
192
|
+
if (info) {
|
|
193
|
+
const originalDest = info.original;
|
|
194
|
+
const cloneDest = info.cloned;
|
|
195
|
+
// istanbul ignore next
|
|
196
|
+
if (doDebug) {
|
|
197
|
+
debugLog(" adding reference ", ref.referenceType, addressSpace.findNode(ref.referenceType).browseName.toString(), " from cloned ", cloned.nodeId.toString(), cloned.browseName.toString(), " to cloned ", cloneDest.nodeId.toString(), cloneDest.browseName.toString());
|
|
198
|
+
}
|
|
199
|
+
// restore reference
|
|
200
|
+
cloned.addReference({
|
|
201
|
+
isForward: false,
|
|
202
|
+
nodeId: cloneDest.nodeId,
|
|
203
|
+
referenceType: ref.referenceType
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
// // restore reference
|
|
208
|
+
// cloned.addReference({
|
|
209
|
+
// isForward: false,
|
|
210
|
+
// nodeId: ref.nodeId,
|
|
211
|
+
// referenceType: ref.referenceType
|
|
212
|
+
// });
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
exports.reconstructNonHierarchicalReferences = reconstructNonHierarchicalReferences;
|
|
218
|
+
/**
|
|
219
|
+
* recreate functional group types according to type definition
|
|
220
|
+
*
|
|
221
|
+
* @method reconstructFunctionalGroupType
|
|
222
|
+
* @param baseType
|
|
223
|
+
*/
|
|
224
|
+
/* @example:
|
|
225
|
+
*
|
|
226
|
+
* MyDeviceType
|
|
227
|
+
* |
|
|
228
|
+
* +----------|- ParameterSet(BaseObjectType)
|
|
229
|
+
* | |
|
|
230
|
+
* | +-----------------|- Parameter1
|
|
231
|
+
* | ^
|
|
232
|
+
* +----------|- Config(FunctionalGroupType) |
|
|
233
|
+
* | |
|
|
234
|
+
* +-------- Organizes---+
|
|
235
|
+
*/
|
|
236
|
+
function reconstructFunctionalGroupType(extraInfo) {
|
|
237
|
+
const extraInfo_ = extraInfo;
|
|
238
|
+
// navigate through original objects to find those that are being organized by some FunctionalGroup
|
|
239
|
+
for (const { original, cloned } of extraInfo_.mapOrgToClone.values()) {
|
|
240
|
+
const organizedByArray = original.findReferencesEx("Organizes", node_opcua_data_model_1.BrowseDirection.Inverse);
|
|
241
|
+
for (const ref of organizedByArray) {
|
|
242
|
+
const info = extraInfo_.mapOrgToClone.get(ref.nodeId.toString());
|
|
243
|
+
if (!info)
|
|
244
|
+
continue;
|
|
245
|
+
const folder = info.original;
|
|
246
|
+
if (folder.nodeClass !== node_opcua_data_model_1.NodeClass.Object)
|
|
247
|
+
continue;
|
|
248
|
+
if (!folder.typeDefinitionObj)
|
|
249
|
+
continue;
|
|
250
|
+
(0, node_opcua_assert_1.assert)(folder.typeDefinitionObj.browseName.name.toString() === "FunctionalGroupType");
|
|
251
|
+
// now create the same reference with the instantiated function group
|
|
252
|
+
const destFolder = info.cloned;
|
|
253
|
+
(0, node_opcua_assert_1.assert)(ref.referenceType);
|
|
254
|
+
// may be we should check that the referenceType is a subtype of Organizes
|
|
255
|
+
const alreadyExist = destFolder
|
|
256
|
+
.findReferences(ref.referenceType, !ref.isForward)
|
|
257
|
+
.find((r) => r.nodeId === cloned.nodeId);
|
|
258
|
+
if (alreadyExist) {
|
|
259
|
+
continue;
|
|
260
|
+
}
|
|
261
|
+
destFolder.addReference({
|
|
262
|
+
isForward: !ref.isForward,
|
|
263
|
+
nodeId: cloned.nodeId,
|
|
264
|
+
referenceType: ref.referenceType
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
exports.reconstructFunctionalGroupType = reconstructFunctionalGroupType;
|
|
270
|
+
//# sourceMappingURL=clone_helper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clone_helper.js","sourceRoot":"","sources":["../source/clone_helper.ts"],"names":[],"mappings":"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"}
|
package/dist/clone_options.d.ts
CHANGED
|
@@ -16,13 +16,10 @@ export declare const defaultCloneFilter: CloneFilter;
|
|
|
16
16
|
export interface CloneExtraInfo {
|
|
17
17
|
level: number;
|
|
18
18
|
pad(): string;
|
|
19
|
-
registerClonedObject(
|
|
20
|
-
getCloned(
|
|
19
|
+
registerClonedObject(clonedNode: BaseNode, originalNode: BaseNode): void;
|
|
20
|
+
getCloned(originalObject: BaseNode): BaseNode | null;
|
|
21
21
|
}
|
|
22
|
-
|
|
23
|
-
_cloned: Map<BaseNode, BaseNode>;
|
|
24
|
-
}
|
|
25
|
-
export declare const defaultCloneExtraInfo: CloneExtraInfoEx;
|
|
22
|
+
export declare const makeDefaultCloneExtraInfo: () => CloneExtraInfo;
|
|
26
23
|
export interface CloneOptions {
|
|
27
24
|
namespace: INamespace;
|
|
28
25
|
references?: UAReference[];
|
|
@@ -46,4 +43,3 @@ export interface CloneOptions {
|
|
|
46
43
|
copyAlsoModellingRules?: boolean;
|
|
47
44
|
ignoreChildren?: boolean;
|
|
48
45
|
}
|
|
49
|
-
export {};
|
package/dist/clone_options.js
CHANGED
|
@@ -1,25 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.makeDefaultCloneExtraInfo = exports.defaultCloneFilter = void 0;
|
|
4
|
+
const clone_helper_1 = require("./clone_helper");
|
|
4
5
|
exports.defaultCloneFilter = {
|
|
5
6
|
shouldKeep: () => true,
|
|
6
7
|
filterFor(node) {
|
|
7
8
|
return this;
|
|
8
9
|
}
|
|
9
10
|
};
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
_cloned: new Map(),
|
|
13
|
-
pad() {
|
|
14
|
-
return " ".padEnd(this.level * 2);
|
|
15
|
-
},
|
|
16
|
-
registerClonedObject(_clonedObject, _originalObject) {
|
|
17
|
-
if (this.getCloned(_originalObject))
|
|
18
|
-
throw new Error("cloned object is already registered.");
|
|
19
|
-
this._cloned.set(_originalObject, _clonedObject);
|
|
20
|
-
},
|
|
21
|
-
getCloned(node) {
|
|
22
|
-
return this._cloned.get(node) || null;
|
|
23
|
-
}
|
|
24
|
-
};
|
|
11
|
+
const makeDefaultCloneExtraInfo = () => new clone_helper_1.CloneHelper();
|
|
12
|
+
exports.makeDefaultCloneExtraInfo = makeDefaultCloneExtraInfo;
|
|
25
13
|
//# sourceMappingURL=clone_options.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clone_options.js","sourceRoot":"","sources":["../source/clone_options.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"clone_options.js","sourceRoot":"","sources":["../source/clone_options.ts"],"names":[],"mappings":";;;AAWA,iDAA6C;AAMhC,QAAA,kBAAkB,GAAgB;IAC3C,UAAU,EAAE,GAAG,EAAE,CAAC,IAAI;IACtB,SAAS,CAAC,IAAc;QACpB,OAAO,IAAI,CAAC;IAChB,CAAC;CACJ,CAAC;AAUK,MAAM,yBAAyB,GAAG,GAAmB,EAAE,CAAG,IAAI,0BAAW,EAAE,CAAC;AAAtE,QAAA,yBAAyB,6BAA6C"}
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -37,4 +37,5 @@ __exportStar(require("./ua_variable_t"), exports);
|
|
|
37
37
|
__exportStar(require("./ua_variable_type"), exports);
|
|
38
38
|
__exportStar(require("./ua_variable"), exports);
|
|
39
39
|
__exportStar(require("./ua_view"), exports);
|
|
40
|
+
__exportStar(require("./clone_helper"), exports);
|
|
40
41
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../source/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,kDAAgC;AAChC,8CAA4B;AAC5B,kDAAgC;AAChC,kDAAgC;AAChC,uDAAqC;AACrC,yDAAuC;AACvC,iDAA+B;AAC/B,wDAAsC;AACtC,8CAA4B;AAC5B,oDAAkC;AAClC,iDAA+B;AAC/B,8DAA4C;AAC5C,kDAAgC;AAChC,8CAA4B;AAC5B,mDAAiC;AACjC,8CAA4B;AAC5B,gDAA8B;AAC9B,sDAAoC;AACpC,iDAA+B;AAC/B,kDAAgC;AAChC,qDAAmC;AACnC,gDAA8B;AAC9B,4CAA0B"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../source/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,kDAAgC;AAChC,8CAA4B;AAC5B,kDAAgC;AAChC,kDAAgC;AAChC,uDAAqC;AACrC,yDAAuC;AACvC,iDAA+B;AAC/B,wDAAsC;AACtC,8CAA4B;AAC5B,oDAAkC;AAClC,iDAA+B;AAC/B,8DAA4C;AAC5C,kDAAgC;AAChC,8CAA4B;AAC5B,mDAAiC;AACjC,8CAA4B;AAC5B,gDAA8B;AAC9B,sDAAoC;AACpC,iDAA+B;AAC/B,kDAAgC;AAChC,qDAAmC;AACnC,gDAA8B;AAC9B,4CAA0B;AAC1B,iDAA+B"}
|
package/dist/ua_variable.d.ts
CHANGED
|
@@ -217,8 +217,8 @@ export interface UAVariable extends BaseNode, VariableAttributes, IPropertyAndCo
|
|
|
217
217
|
writeValue(context: ISessionContext, dataValue: DataValue, indexRange: string | NumericRange | null, callback: StatusCodeCallback): void;
|
|
218
218
|
writeValue(context: ISessionContext, dataValue: DataValue, callback: StatusCodeCallback): void;
|
|
219
219
|
writeValue(context: ISessionContext, dataValue: DataValue, indexRange?: string | NumericRange | null): Promise<StatusCode>;
|
|
220
|
-
asyncRefresh(oldestDate:
|
|
221
|
-
asyncRefresh(oldestDate:
|
|
220
|
+
asyncRefresh(oldestDate: PreciseClock, callback: CallbackT<DataValue>): void;
|
|
221
|
+
asyncRefresh(oldestDate: PreciseClock): Promise<DataValue>;
|
|
222
222
|
/**
|
|
223
223
|
* write a variable attribute (callback version)
|
|
224
224
|
* @param context
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "node-opcua-address-space-base",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.100.0",
|
|
4
4
|
"description": "pure nodejs OPCUA SDK - module address-space-base",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -13,22 +13,24 @@
|
|
|
13
13
|
"lint": "eslint source",
|
|
14
14
|
"format": "prettier --write source",
|
|
15
15
|
"clean": "npx rimraf node_modules dist *.tsbuildinfo",
|
|
16
|
-
"
|
|
16
|
+
"mocha:version": "mocha --version"
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"node-opcua-
|
|
19
|
+
"node-opcua-assert": "2.98.1",
|
|
20
|
+
"node-opcua-basic-types": "2.99.0",
|
|
20
21
|
"node-opcua-constants": "2.98.1",
|
|
21
22
|
"node-opcua-crypto": "^2.1.2",
|
|
22
|
-
"node-opcua-data-model": "2.
|
|
23
|
-
"node-opcua-data-value": "2.
|
|
24
|
-
"node-opcua-date-time": "2.
|
|
25
|
-
"node-opcua-
|
|
26
|
-
"node-opcua-
|
|
27
|
-
"node-opcua-
|
|
28
|
-
"node-opcua-
|
|
23
|
+
"node-opcua-data-model": "2.99.0",
|
|
24
|
+
"node-opcua-data-value": "2.99.0",
|
|
25
|
+
"node-opcua-date-time": "2.99.0",
|
|
26
|
+
"node-opcua-debug": "2.99.0",
|
|
27
|
+
"node-opcua-extension-object": "2.99.0",
|
|
28
|
+
"node-opcua-nodeid": "2.99.0",
|
|
29
|
+
"node-opcua-numeric-range": "2.99.0",
|
|
30
|
+
"node-opcua-schemas": "2.99.0",
|
|
29
31
|
"node-opcua-status-code": "2.98.1",
|
|
30
|
-
"node-opcua-types": "2.
|
|
31
|
-
"node-opcua-variant": "2.
|
|
32
|
+
"node-opcua-types": "2.99.0",
|
|
33
|
+
"node-opcua-variant": "2.99.0"
|
|
32
34
|
},
|
|
33
35
|
"author": "Etienne Rossignon",
|
|
34
36
|
"license": "MIT",
|
|
@@ -45,7 +47,7 @@
|
|
|
45
47
|
"internet of things"
|
|
46
48
|
],
|
|
47
49
|
"homepage": "http://node-opcua.github.io/",
|
|
48
|
-
"gitHead": "
|
|
50
|
+
"gitHead": "e143ff72418bb3db8c0a2cb8d4b7e54a90521a73",
|
|
49
51
|
"files": [
|
|
50
52
|
"dist",
|
|
51
53
|
"source"
|
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
import { assert } from "node-opcua-assert";
|
|
2
|
+
import { checkDebugFlag, make_debugLog, make_warningLog } from "node-opcua-debug";
|
|
3
|
+
import { BrowseDirection, NodeClass, QualifiedName } from "node-opcua-data-model";
|
|
4
|
+
import { UAObject } from "./ua_object";
|
|
5
|
+
import { UAVariable } from "./ua_variable";
|
|
6
|
+
import { UAMethod } from "./ua_method";
|
|
7
|
+
import { UAObjectType } from "./ua_object_type";
|
|
8
|
+
import { UAVariableType } from "./ua_variable_type";
|
|
9
|
+
import { BaseNode } from "./base_node";
|
|
10
|
+
import { makeNodeId, sameNodeId } from "node-opcua-nodeid";
|
|
11
|
+
import { ReferenceTypeIds } from "node-opcua-constants";
|
|
12
|
+
import { UAReference } from "./ua_reference";
|
|
13
|
+
import { IAddressSpace } from "./address_space";
|
|
14
|
+
|
|
15
|
+
const debugLog = make_debugLog("CLONE");
|
|
16
|
+
const doDebug = checkDebugFlag("CLONE");
|
|
17
|
+
const warningLog = make_warningLog("CLONE");
|
|
18
|
+
|
|
19
|
+
type UAConcrete = UAVariable | UAObject | UAMethod;
|
|
20
|
+
|
|
21
|
+
//
|
|
22
|
+
// case 1:
|
|
23
|
+
// /-----------------------------\
|
|
24
|
+
// | AcknowledgeableConditionType |
|
|
25
|
+
// \-----------------------------/
|
|
26
|
+
// ^ |
|
|
27
|
+
// | +---------------------|- (EnabledState) (shadow element)
|
|
28
|
+
// |
|
|
29
|
+
// /-----------------------------\
|
|
30
|
+
// | AlarmConditionType |
|
|
31
|
+
// \-----------------------------/
|
|
32
|
+
// |
|
|
33
|
+
// +-------------------------------|- EnabledState <
|
|
34
|
+
//
|
|
35
|
+
// find also child object with the same browse name that are
|
|
36
|
+
// overridden in the SuperType
|
|
37
|
+
|
|
38
|
+
// case 2:
|
|
39
|
+
//
|
|
40
|
+
// /-----------------------------\
|
|
41
|
+
// | MyDeviceType |
|
|
42
|
+
// \-----------------------------/
|
|
43
|
+
// ^ |
|
|
44
|
+
// | | +----------+
|
|
45
|
+
// | +-------| Folder1 |
|
|
46
|
+
// | +----------+
|
|
47
|
+
// | |
|
|
48
|
+
// | +--------------|- (EnabledState) (shadow element)
|
|
49
|
+
// |
|
|
50
|
+
// /-----------------------------\
|
|
51
|
+
// | MyDeriveDeviceType |
|
|
52
|
+
// \-----------------------------/
|
|
53
|
+
// |
|
|
54
|
+
// | | +----------+
|
|
55
|
+
// | +-------| Folder1 |
|
|
56
|
+
// | +----------+
|
|
57
|
+
// | |
|
|
58
|
+
// | +--------------|- (EnabledState)
|
|
59
|
+
//
|
|
60
|
+
// find also child object with the same browse name that are
|
|
61
|
+
|
|
62
|
+
function _get_parent_type_and_path(originalObject: BaseNode): {
|
|
63
|
+
parentType: null | UAVariableType | UAObjectType;
|
|
64
|
+
path: QualifiedName[];
|
|
65
|
+
} {
|
|
66
|
+
if (originalObject.nodeClass === NodeClass.Method) {
|
|
67
|
+
return { parentType: null, path: [] };
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const addressSpace = originalObject.addressSpace;
|
|
71
|
+
|
|
72
|
+
const parents = originalObject.findReferencesEx("HasChild", BrowseDirection.Inverse);
|
|
73
|
+
// istanbul ignore next
|
|
74
|
+
if (parents.length > 1) {
|
|
75
|
+
warningLog(" object ", originalObject.browseName.toString(), " has more than one parent !");
|
|
76
|
+
warningLog(originalObject.toString());
|
|
77
|
+
warningLog(" parents : ");
|
|
78
|
+
for (const parent of parents) {
|
|
79
|
+
warningLog(" ", parent.toString(), addressSpace.findNode(parent.nodeId)!.browseName.toString());
|
|
80
|
+
}
|
|
81
|
+
return { parentType: null, path: [] };
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
assert(parents.length === 0 || parents.length === 1);
|
|
85
|
+
if (parents.length === 0) {
|
|
86
|
+
return { parentType: null, path: [] };
|
|
87
|
+
}
|
|
88
|
+
const theParent = addressSpace.findNode(parents[0]!.nodeId)!;
|
|
89
|
+
if (theParent && (theParent.nodeClass === NodeClass.VariableType || theParent.nodeClass === NodeClass.ObjectType)) {
|
|
90
|
+
return { parentType: theParent as UAVariableType | UAObjectType, path: [originalObject.browseName] };
|
|
91
|
+
}
|
|
92
|
+
// walk up
|
|
93
|
+
const { parentType, path } = _get_parent_type_and_path(theParent!);
|
|
94
|
+
return { parentType, path: [...path, originalObject.browseName] };
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
interface CloneInfo {
|
|
98
|
+
cloned: UAObject | UAVariable | UAMethod;
|
|
99
|
+
original: UAObject | UAVariable | UAMethod | UAVariableType | UAObjectType;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function followPath(node: BaseNode, path: QualifiedName[]): UAConcrete | null {
|
|
103
|
+
let current = node;
|
|
104
|
+
for (const qn of path) {
|
|
105
|
+
const ref = current
|
|
106
|
+
.findReferencesExAsObject("HierarchicalReferences", BrowseDirection.Forward)
|
|
107
|
+
.find((r) => r.browseName.toString() === qn.toString());
|
|
108
|
+
if (!ref) {
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
current = ref;
|
|
112
|
+
}
|
|
113
|
+
return current as UAConcrete;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export class CloneHelper {
|
|
117
|
+
public level = 0;
|
|
118
|
+
private readonly mapOrgToClone: Map<string, CloneInfo> = new Map();
|
|
119
|
+
|
|
120
|
+
public pad(): string {
|
|
121
|
+
return " ".padEnd(this.level * 2, " ");
|
|
122
|
+
}
|
|
123
|
+
public registerClonedObject<
|
|
124
|
+
TO extends UAObject | UAVariable | UAMethod | UAObjectType | UAVariableType,
|
|
125
|
+
TC extends UAObject | UAVariable | UAMethod
|
|
126
|
+
>(clonedNode: TC, originalNode: TO) {
|
|
127
|
+
this.mapOrgToClone.set(originalNode.nodeId.toString(), {
|
|
128
|
+
cloned: clonedNode,
|
|
129
|
+
original: originalNode
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
//
|
|
133
|
+
const { parentType, path } = _get_parent_type_and_path(originalNode);
|
|
134
|
+
|
|
135
|
+
if (parentType) {
|
|
136
|
+
let base = parentType.subtypeOfObj;
|
|
137
|
+
while (base) {
|
|
138
|
+
const shadowChild = followPath(base, path);
|
|
139
|
+
if (shadowChild) {
|
|
140
|
+
this.mapOrgToClone.set(shadowChild.nodeId.toString(), {
|
|
141
|
+
cloned: clonedNode,
|
|
142
|
+
original: shadowChild
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
base = base.subtypeOfObj;
|
|
146
|
+
}
|
|
147
|
+
} else {
|
|
148
|
+
}
|
|
149
|
+
// find subTypeOf
|
|
150
|
+
}
|
|
151
|
+
public getCloned(originalNode: UAVariableType | UAObjectType): UAObject | UAVariable | UAMethod | null {
|
|
152
|
+
const info = this.mapOrgToClone.get(originalNode.nodeId.toString());
|
|
153
|
+
if (info) {
|
|
154
|
+
return info.cloned;
|
|
155
|
+
}
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const hasTypeDefinitionNodeId = makeNodeId(ReferenceTypeIds.HasTypeDefinition);
|
|
161
|
+
const hasModellingRuleNodeId = makeNodeId(ReferenceTypeIds.HasModellingRule);
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* remove unwanted reference such as HasTypeDefinition and HasModellingRule
|
|
165
|
+
* from the list
|
|
166
|
+
*/
|
|
167
|
+
function _remove_unwanted_ref(references: UAReference[]): UAReference[] {
|
|
168
|
+
// filter out HasTypeDefinition (i=40) , HasModellingRule (i=37);
|
|
169
|
+
references = references.filter(
|
|
170
|
+
(reference: UAReference) =>
|
|
171
|
+
!sameNodeId(reference.referenceType, hasTypeDefinitionNodeId) &&
|
|
172
|
+
!sameNodeId(reference.referenceType, hasModellingRuleNodeId)
|
|
173
|
+
);
|
|
174
|
+
return references;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
*
|
|
179
|
+
*/
|
|
180
|
+
function findNonHierarchicalReferences(originalObject: BaseNode): UAReference[] {
|
|
181
|
+
// todo: MEMOIZE this method
|
|
182
|
+
const addressSpace: IAddressSpace = originalObject.addressSpace;
|
|
183
|
+
|
|
184
|
+
// we need to explore the non hierarchical references backwards
|
|
185
|
+
let references = originalObject.findReferencesEx("NonHierarchicalReferences", BrowseDirection.Inverse);
|
|
186
|
+
|
|
187
|
+
references = ([] as UAReference[]).concat(
|
|
188
|
+
references,
|
|
189
|
+
originalObject.findReferencesEx("HasEventSource", BrowseDirection.Inverse)
|
|
190
|
+
);
|
|
191
|
+
|
|
192
|
+
const { parentType, path } = _get_parent_type_and_path(originalObject);
|
|
193
|
+
|
|
194
|
+
if (parentType && parentType.subtypeOfObj) {
|
|
195
|
+
// parent is a ObjectType or VariableType and is not a root type
|
|
196
|
+
assert(parentType.nodeClass === NodeClass.VariableType || parentType.nodeClass === NodeClass.ObjectType);
|
|
197
|
+
|
|
198
|
+
// let investigate the same child base child
|
|
199
|
+
const child = followPath(parentType.subtypeOfObj, path);
|
|
200
|
+
if (child) {
|
|
201
|
+
const baseRef = findNonHierarchicalReferences(child);
|
|
202
|
+
references = ([] as UAReference[]).concat(references, baseRef);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
// perform some cleanup
|
|
206
|
+
references = _remove_unwanted_ref(references);
|
|
207
|
+
|
|
208
|
+
return references;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
export function reconstructNonHierarchicalReferences(extraInfo: CloneHelper): void {
|
|
212
|
+
const extraInfo_ = extraInfo as unknown as { mapOrgToClone: Map<string, CloneInfo> };
|
|
213
|
+
|
|
214
|
+
const findImplementedObject = (ref: UAReference): CloneInfo | null =>
|
|
215
|
+
extraInfo_.mapOrgToClone.get(ref.nodeId.toString()) || null;
|
|
216
|
+
|
|
217
|
+
// navigate through original objects to find those that are being references by node that
|
|
218
|
+
// have been cloned .
|
|
219
|
+
// this could be node organized by some FunctionalGroup
|
|
220
|
+
|
|
221
|
+
for (const { original, cloned } of extraInfo_.mapOrgToClone.values()) {
|
|
222
|
+
apply(original, cloned);
|
|
223
|
+
}
|
|
224
|
+
function apply(original: BaseNode, cloned: BaseNode) {
|
|
225
|
+
const addressSpace = original.addressSpace;
|
|
226
|
+
// find NonHierarchical References on original object
|
|
227
|
+
const originalNonHierarchical = findNonHierarchicalReferences(original);
|
|
228
|
+
|
|
229
|
+
if (originalNonHierarchical.length === 0) {
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// istanbul ignore next
|
|
234
|
+
if (doDebug) {
|
|
235
|
+
debugLog(
|
|
236
|
+
" investigation ",
|
|
237
|
+
original.browseName.toString(),
|
|
238
|
+
cloned.nodeClass.toString(),
|
|
239
|
+
original.nodeClass.toString(),
|
|
240
|
+
original.nodeId.toString(),
|
|
241
|
+
cloned.nodeId.toString()
|
|
242
|
+
);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
for (const ref of originalNonHierarchical) {
|
|
246
|
+
const info = findImplementedObject(ref);
|
|
247
|
+
|
|
248
|
+
// if the object pointed by this reference is also cloned ...
|
|
249
|
+
if (info) {
|
|
250
|
+
const originalDest = info.original;
|
|
251
|
+
const cloneDest = info.cloned;
|
|
252
|
+
|
|
253
|
+
// istanbul ignore next
|
|
254
|
+
if (doDebug) {
|
|
255
|
+
debugLog(
|
|
256
|
+
" adding reference ",
|
|
257
|
+
ref.referenceType,
|
|
258
|
+
addressSpace.findNode(ref.referenceType)!.browseName.toString(),
|
|
259
|
+
" from cloned ",
|
|
260
|
+
cloned.nodeId.toString(),
|
|
261
|
+
cloned.browseName.toString(),
|
|
262
|
+
" to cloned ",
|
|
263
|
+
cloneDest.nodeId.toString(),
|
|
264
|
+
cloneDest.browseName.toString()
|
|
265
|
+
);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// restore reference
|
|
269
|
+
cloned.addReference({
|
|
270
|
+
isForward: false,
|
|
271
|
+
nodeId: cloneDest.nodeId,
|
|
272
|
+
referenceType: ref.referenceType
|
|
273
|
+
});
|
|
274
|
+
} else {
|
|
275
|
+
// // restore reference
|
|
276
|
+
// cloned.addReference({
|
|
277
|
+
// isForward: false,
|
|
278
|
+
// nodeId: ref.nodeId,
|
|
279
|
+
// referenceType: ref.referenceType
|
|
280
|
+
// });
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* recreate functional group types according to type definition
|
|
288
|
+
*
|
|
289
|
+
* @method reconstructFunctionalGroupType
|
|
290
|
+
* @param baseType
|
|
291
|
+
*/
|
|
292
|
+
|
|
293
|
+
/* @example:
|
|
294
|
+
*
|
|
295
|
+
* MyDeviceType
|
|
296
|
+
* |
|
|
297
|
+
* +----------|- ParameterSet(BaseObjectType)
|
|
298
|
+
* | |
|
|
299
|
+
* | +-----------------|- Parameter1
|
|
300
|
+
* | ^
|
|
301
|
+
* +----------|- Config(FunctionalGroupType) |
|
|
302
|
+
* | |
|
|
303
|
+
* +-------- Organizes---+
|
|
304
|
+
*/
|
|
305
|
+
export function reconstructFunctionalGroupType(extraInfo: CloneHelper) {
|
|
306
|
+
const extraInfo_ = extraInfo as unknown as { mapOrgToClone: Map<string, CloneInfo> };
|
|
307
|
+
|
|
308
|
+
// navigate through original objects to find those that are being organized by some FunctionalGroup
|
|
309
|
+
for (const { original, cloned } of extraInfo_.mapOrgToClone.values()) {
|
|
310
|
+
const organizedByArray = original.findReferencesEx("Organizes", BrowseDirection.Inverse);
|
|
311
|
+
|
|
312
|
+
for (const ref of organizedByArray) {
|
|
313
|
+
const info = extraInfo_.mapOrgToClone.get(ref.nodeId.toString());
|
|
314
|
+
if (!info) continue;
|
|
315
|
+
|
|
316
|
+
const folder = info.original;
|
|
317
|
+
if (folder.nodeClass !== NodeClass.Object) continue;
|
|
318
|
+
|
|
319
|
+
if (!folder.typeDefinitionObj) continue;
|
|
320
|
+
|
|
321
|
+
assert(folder.typeDefinitionObj.browseName.name!.toString() === "FunctionalGroupType");
|
|
322
|
+
|
|
323
|
+
// now create the same reference with the instantiated function group
|
|
324
|
+
const destFolder = info.cloned as BaseNode;
|
|
325
|
+
|
|
326
|
+
assert(ref.referenceType);
|
|
327
|
+
|
|
328
|
+
// may be we should check that the referenceType is a subtype of Organizes
|
|
329
|
+
const alreadyExist = destFolder
|
|
330
|
+
.findReferences(ref.referenceType, !ref.isForward)
|
|
331
|
+
.find((r) => r.nodeId === cloned.nodeId);
|
|
332
|
+
if (alreadyExist) {
|
|
333
|
+
continue;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
destFolder.addReference({
|
|
337
|
+
isForward: !ref.isForward,
|
|
338
|
+
nodeId: cloned.nodeId,
|
|
339
|
+
referenceType: ref.referenceType
|
|
340
|
+
});
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
}
|
package/source/clone_options.ts
CHANGED
|
@@ -9,6 +9,7 @@ import { UAObject } from "./ua_object";
|
|
|
9
9
|
import { UAObjectType } from "./ua_object_type";
|
|
10
10
|
import { UAReference } from "./ua_reference";
|
|
11
11
|
import { UAVariable } from "./ua_variable";
|
|
12
|
+
import { CloneHelper } from "./clone_helper";
|
|
12
13
|
|
|
13
14
|
export interface CloneFilter {
|
|
14
15
|
shouldKeep(node: BaseNode): boolean;
|
|
@@ -25,26 +26,11 @@ export interface CloneExtraInfo {
|
|
|
25
26
|
/* */
|
|
26
27
|
level: number;
|
|
27
28
|
pad(): string;
|
|
28
|
-
registerClonedObject(
|
|
29
|
-
getCloned(
|
|
29
|
+
registerClonedObject(clonedNode: BaseNode, originalNode: BaseNode): void;
|
|
30
|
+
getCloned(originalObject: BaseNode): BaseNode | null;
|
|
30
31
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
}
|
|
34
|
-
export const defaultCloneExtraInfo: CloneExtraInfoEx = {
|
|
35
|
-
level: 0,
|
|
36
|
-
_cloned: new Map<BaseNode, BaseNode>(),
|
|
37
|
-
pad(this: CloneExtraInfo) {
|
|
38
|
-
return " ".padEnd(this.level * 2);
|
|
39
|
-
},
|
|
40
|
-
registerClonedObject(_clonedObject: BaseNode, _originalObject: BaseNode): void {
|
|
41
|
-
if(this.getCloned(_originalObject)) throw new Error("cloned object is already registered.");
|
|
42
|
-
this._cloned.set(_originalObject, _clonedObject);
|
|
43
|
-
},
|
|
44
|
-
getCloned(node: BaseNode): BaseNode | null {
|
|
45
|
-
return this._cloned.get(node) || null;
|
|
46
|
-
}
|
|
47
|
-
};
|
|
32
|
+
|
|
33
|
+
export const makeDefaultCloneExtraInfo = (): CloneExtraInfo => new CloneHelper();
|
|
48
34
|
|
|
49
35
|
export interface CloneOptions /* extends ConstructNodeIdOptions */ {
|
|
50
36
|
namespace: INamespace;
|
package/source/index.ts
CHANGED
package/source/ua_variable.ts
CHANGED
|
@@ -281,9 +281,9 @@ export interface UAVariable extends BaseNode, VariableAttributes, IPropertyAndCo
|
|
|
281
281
|
|
|
282
282
|
writeValue(context: ISessionContext, dataValue: DataValue, indexRange?: string | NumericRange | null): Promise<StatusCode>;
|
|
283
283
|
|
|
284
|
-
asyncRefresh(oldestDate:
|
|
284
|
+
asyncRefresh(oldestDate: PreciseClock, callback: CallbackT<DataValue>): void;
|
|
285
285
|
|
|
286
|
-
asyncRefresh(oldestDate:
|
|
286
|
+
asyncRefresh(oldestDate: PreciseClock): Promise<DataValue>;
|
|
287
287
|
|
|
288
288
|
/**
|
|
289
289
|
* write a variable attribute (callback version)
|