node-opcua-address-space 2.83.0 → 2.85.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/continuation_points/continuation_point_manager.js +6 -1
- package/dist/source/continuation_points/continuation_point_manager.js.map +1 -1
- package/dist/source/loader/ensure_datatype_extracted.js +1 -1
- package/dist/source/loader/ensure_datatype_extracted.js.map +1 -1
- package/dist/source/loader/load_nodeset2.js +1 -1
- package/dist/source/loader/load_nodeset2.js.map +1 -1
- package/dist/source/pseudo_session.d.ts +15 -1
- package/dist/source/pseudo_session.js +86 -37
- package/dist/source/pseudo_session.js.map +1 -1
- package/dist/src/address_space.d.ts +0 -4
- package/dist/src/address_space.js +4 -13
- package/dist/src/address_space.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/base_node_private.js +13 -7
- package/dist/src/base_node_private.js.map +1 -1
- package/dist/src/namespace_impl.js +1 -0
- package/dist/src/namespace_impl.js.map +1 -1
- package/dist/src/nodeset_tools/construct_namespace_dependency.js +7 -0
- package/dist/src/nodeset_tools/construct_namespace_dependency.js.map +1 -1
- package/dist/src/nodeset_tools/nodeset_to_xml.js +33 -36
- package/dist/src/nodeset_tools/nodeset_to_xml.js.map +1 -1
- package/dist/src/tool_isSupertypeOf.d.ts +1 -0
- package/dist/src/tool_isSupertypeOf.js +7 -1
- package/dist/src/tool_isSupertypeOf.js.map +1 -1
- package/dist/src/ua_reference_type_impl.d.ts +1 -1
- package/dist/src/ua_variable_impl.js +1 -1
- package/dist/src/ua_variable_impl.js.map +1 -1
- package/package.json +35 -35
- package/source/continuation_points/continuation_point_manager.ts +6 -2
- package/source/loader/ensure_datatype_extracted.ts +1 -1
- package/source/loader/load_nodeset2.ts +1 -1
- package/source/pseudo_session.ts +120 -46
- package/src/address_space.ts +4 -16
- package/src/base_node_impl.ts +8 -3
- package/src/base_node_private.ts +23 -17
- package/src/namespace_impl.ts +6 -3
- package/src/nodeset_tools/construct_namespace_dependency.ts +9 -0
- package/src/nodeset_tools/nodeset_to_xml.ts +45 -44
- package/src/tool_isSupertypeOf.ts +5 -0
- package/src/ua_variable_impl.ts +1 -1
package/source/pseudo_session.ts
CHANGED
|
@@ -32,6 +32,96 @@ import { callMethodHelper } from "./helpers/call_helpers";
|
|
|
32
32
|
import { SessionContext } from "./session_context";
|
|
33
33
|
|
|
34
34
|
const errorLog = make_errorLog("PseudoSession");
|
|
35
|
+
|
|
36
|
+
function coerceBrowseDescription(browseDescription: BrowseDescriptionLike): BrowseDescription {
|
|
37
|
+
if (typeof browseDescription === "string") {
|
|
38
|
+
return coerceBrowseDescription({
|
|
39
|
+
nodeId: resolveNodeId(browseDescription)
|
|
40
|
+
});
|
|
41
|
+
} else if (browseDescription instanceof BrowseDescription) {
|
|
42
|
+
return browseDescription;
|
|
43
|
+
} else {
|
|
44
|
+
return new BrowseDescription(browseDescription);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
export interface InnerBrowseEngine {
|
|
48
|
+
requestedMaxReferencesPerNode: number;
|
|
49
|
+
maxBrowseContinuationPoints: number;
|
|
50
|
+
continuationPointManager: ContinuationPointManager;
|
|
51
|
+
context: ISessionContext;
|
|
52
|
+
browseAll: (nodesToBrowse: BrowseDescriptionOptions[], callack: ResponseCallback<BrowseResult[]>) => void;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function innerBrowse(
|
|
56
|
+
engine: InnerBrowseEngine,
|
|
57
|
+
nodesToBrowse: BrowseDescriptionOptions[],
|
|
58
|
+
callback?: ResponseCallback<BrowseResult[]>
|
|
59
|
+
): void {
|
|
60
|
+
engine.browseAll(nodesToBrowse, (err, results) => {
|
|
61
|
+
if (err || !results) {
|
|
62
|
+
return callback!(err);
|
|
63
|
+
}
|
|
64
|
+
// handle continuation points
|
|
65
|
+
results = results.map((result: BrowseResult, index) => {
|
|
66
|
+
assert(!result.continuationPoint);
|
|
67
|
+
// istanbul ignore next
|
|
68
|
+
if (!engine.continuationPointManager) {
|
|
69
|
+
return new BrowseResult({ statusCode: StatusCodes.BadNoContinuationPoints });
|
|
70
|
+
}
|
|
71
|
+
if (index === 0) {
|
|
72
|
+
// clear previous continuation points
|
|
73
|
+
engine.continuationPointManager.clearContinuationPoints();
|
|
74
|
+
}
|
|
75
|
+
if (engine.continuationPointManager.hasReachedMaximum(engine.maxBrowseContinuationPoints)) {
|
|
76
|
+
return new BrowseResult({ statusCode: StatusCodes.BadNoContinuationPoints });
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const truncatedResult = engine.continuationPointManager.registerReferences(
|
|
80
|
+
engine.requestedMaxReferencesPerNode,
|
|
81
|
+
result.references || [],
|
|
82
|
+
{ continuationPoint: null, index }
|
|
83
|
+
);
|
|
84
|
+
let { statusCode } = truncatedResult;
|
|
85
|
+
const { continuationPoint, values } = truncatedResult;
|
|
86
|
+
assert(statusCode === StatusCodes.Good || statusCode === StatusCodes.GoodNoData);
|
|
87
|
+
statusCode = result.statusCode;
|
|
88
|
+
return new BrowseResult({
|
|
89
|
+
statusCode,
|
|
90
|
+
continuationPoint,
|
|
91
|
+
references: values
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
callback!(null, results);
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export interface InnerBrowseNextEngine {
|
|
99
|
+
continuationPointManager: ContinuationPointManager;
|
|
100
|
+
}
|
|
101
|
+
export function innerBrowseNext(
|
|
102
|
+
engine: InnerBrowseNextEngine,
|
|
103
|
+
continuationPoints: Buffer[],
|
|
104
|
+
releaseContinuationPoints: boolean,
|
|
105
|
+
callback?: ResponseCallback<BrowseResult[]>
|
|
106
|
+
): void {
|
|
107
|
+
const results = continuationPoints
|
|
108
|
+
.map((continuationPoint: ContinuationPoint, index: number) => {
|
|
109
|
+
return engine.continuationPointManager.getNextReferences(0, {
|
|
110
|
+
continuationPoint,
|
|
111
|
+
index,
|
|
112
|
+
releaseContinuationPoints
|
|
113
|
+
});
|
|
114
|
+
})
|
|
115
|
+
.map(
|
|
116
|
+
(r) =>
|
|
117
|
+
new BrowseResult({
|
|
118
|
+
statusCode: r.statusCode,
|
|
119
|
+
continuationPoint: r.continuationPoint,
|
|
120
|
+
references: r.values
|
|
121
|
+
})
|
|
122
|
+
);
|
|
123
|
+
callback!(null, results);
|
|
124
|
+
}
|
|
35
125
|
/**
|
|
36
126
|
* Pseudo session is an helper object that exposes the same async methods
|
|
37
127
|
* than the ClientSession. It can be used on a server address space.
|
|
@@ -44,6 +134,7 @@ const errorLog = make_errorLog("PseudoSession");
|
|
|
44
134
|
*/
|
|
45
135
|
export class PseudoSession implements IBasicSession {
|
|
46
136
|
public requestedMaxReferencesPerNode = 0;
|
|
137
|
+
public maxBrowseContinuationPoints = 0; // 0=no limits
|
|
47
138
|
private _sessionId: NodeId = new NodeId(NodeIdType.GUID, randomGuid());
|
|
48
139
|
private readonly addressSpace: IAddressSpace;
|
|
49
140
|
private readonly continuationPointManager: ContinuationPointManager;
|
|
@@ -63,40 +154,36 @@ export class PseudoSession implements IBasicSession {
|
|
|
63
154
|
public browse(nodeToBrowse: BrowseDescriptionLike): Promise<BrowseResult>;
|
|
64
155
|
public browse(nodesToBrowse: BrowseDescriptionLike[]): Promise<BrowseResult[]>;
|
|
65
156
|
public browse(nodesToBrowse: BrowseDescriptionLike | BrowseDescriptionLike[], callback?: ResponseCallback<any>): any {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
}
|
|
71
|
-
|
|
157
|
+
const isArray = Array.isArray(nodesToBrowse);
|
|
158
|
+
if (!isArray) {
|
|
159
|
+
return this.browse([nodesToBrowse as BrowseDescriptionLike], (err, results) => {
|
|
160
|
+
return callback!(err, results ? results[0] : undefined);
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
const browseAll = (nodesToBrowse: BrowseDescriptionOptions[], callack: ResponseCallback<BrowseResult[]>) => {
|
|
164
|
+
const results: BrowseResult[] = [];
|
|
72
165
|
for (const browseDescription of nodesToBrowse as BrowseDescriptionOptions[]) {
|
|
73
166
|
browseDescription.referenceTypeId = resolveNodeId(browseDescription.referenceTypeId!);
|
|
74
|
-
const _browseDescription =
|
|
75
|
-
browseDescription instanceof BrowseDescription ? browseDescription : new BrowseDescription(browseDescription);
|
|
167
|
+
const _browseDescription = coerceBrowseDescription(browseDescription);
|
|
76
168
|
const nodeId = resolveNodeId(_browseDescription.nodeId);
|
|
77
169
|
const r = this.addressSpace.browseSingleNode(nodeId, _browseDescription, this.context);
|
|
78
170
|
results.push(r);
|
|
79
171
|
}
|
|
172
|
+
callack(null, results);
|
|
173
|
+
};
|
|
80
174
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
this.
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
return new BrowseResult({
|
|
94
|
-
statusCode,
|
|
95
|
-
continuationPoint,
|
|
96
|
-
references: values
|
|
97
|
-
});
|
|
98
|
-
});
|
|
99
|
-
callback!(null, isArray ? results : results[0]);
|
|
175
|
+
setImmediate(() => {
|
|
176
|
+
innerBrowse(
|
|
177
|
+
{
|
|
178
|
+
browseAll,
|
|
179
|
+
context: this.context,
|
|
180
|
+
continuationPointManager: this.continuationPointManager,
|
|
181
|
+
requestedMaxReferencesPerNode: this.requestedMaxReferencesPerNode,
|
|
182
|
+
maxBrowseContinuationPoints: this.maxBrowseContinuationPoints
|
|
183
|
+
},
|
|
184
|
+
nodesToBrowse as BrowseDescriptionOptions[],
|
|
185
|
+
callback
|
|
186
|
+
);
|
|
100
187
|
});
|
|
101
188
|
}
|
|
102
189
|
|
|
@@ -175,25 +262,12 @@ export class PseudoSession implements IBasicSession {
|
|
|
175
262
|
callback!(null, _results![0]);
|
|
176
263
|
});
|
|
177
264
|
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
releaseContinuationPoints
|
|
185
|
-
});
|
|
186
|
-
})
|
|
187
|
-
.map(
|
|
188
|
-
(r) =>
|
|
189
|
-
new BrowseResult({
|
|
190
|
-
statusCode: r.statusCode,
|
|
191
|
-
continuationPoint: r.continuationPoint,
|
|
192
|
-
references: r.values
|
|
193
|
-
})
|
|
194
|
-
);
|
|
195
|
-
|
|
196
|
-
callback!(null, results);
|
|
265
|
+
innerBrowseNext(
|
|
266
|
+
{ continuationPointManager: this.continuationPointManager },
|
|
267
|
+
continuationPoints,
|
|
268
|
+
releaseContinuationPoints,
|
|
269
|
+
callback
|
|
270
|
+
);
|
|
197
271
|
});
|
|
198
272
|
}
|
|
199
273
|
|
package/src/address_space.ts
CHANGED
|
@@ -123,7 +123,6 @@ function isNodeIdString(str: unknown): boolean {
|
|
|
123
123
|
return str.substring(0, 2) === "i=" || str.substring(0, 3) === "ns=";
|
|
124
124
|
}
|
|
125
125
|
|
|
126
|
-
|
|
127
126
|
/**
|
|
128
127
|
* `AddressSpace` is a collection of UA nodes.
|
|
129
128
|
*
|
|
@@ -423,7 +422,9 @@ export class AddressSpace implements AddressSpacePrivate {
|
|
|
423
422
|
// +-> Structure
|
|
424
423
|
// +-> Node
|
|
425
424
|
// +-> ObjectNode
|
|
426
|
-
if (dataType instanceof
|
|
425
|
+
if (dataType instanceof UADataTypeImpl) {
|
|
426
|
+
return this.findDataType(dataType.nodeId);
|
|
427
|
+
} else if (dataType instanceof NodeId) {
|
|
427
428
|
return _find_by_node_id<UADataType>(this, dataType!, namespaceIndex);
|
|
428
429
|
}
|
|
429
430
|
if (typeof dataType === "number") {
|
|
@@ -1346,29 +1347,16 @@ export class AddressSpace implements AddressSpacePrivate {
|
|
|
1346
1347
|
_nodeId = (_nodeId as any).nodeId as NodeId;
|
|
1347
1348
|
}
|
|
1348
1349
|
_nodeId = resolveNodeId(_nodeId);
|
|
1349
|
-
/* istanbul ignore next */
|
|
1350
|
-
if (!(_nodeId instanceof NodeId) || _nodeId.isEmpty()) {
|
|
1351
|
-
// tslint:disable:no-console
|
|
1352
|
-
console.log("xx =>", JSON.stringify(params, null, " "));
|
|
1353
|
-
throw new Error(" Invalid reference nodeId " + _nodeId.toString());
|
|
1354
|
-
}
|
|
1355
1350
|
params.nodeId = _nodeId;
|
|
1356
1351
|
}
|
|
1357
1352
|
return new ReferenceImpl(params);
|
|
1358
1353
|
}
|
|
1359
1354
|
|
|
1360
|
-
/**
|
|
1361
|
-
*
|
|
1362
|
-
* @param references
|
|
1363
|
-
*/
|
|
1364
1355
|
public normalizeReferenceTypes(references: AddReferenceOpts[] | ReferenceImpl[] | null): UAReference[] {
|
|
1365
1356
|
if (!references || references.length === 0) {
|
|
1366
1357
|
return [];
|
|
1367
1358
|
}
|
|
1368
|
-
|
|
1369
|
-
assert(Array.isArray(references));
|
|
1370
|
-
|
|
1371
|
-
return (references as any).map((el: UAReference | AddReferenceOpts) => this.normalizeReferenceType(el));
|
|
1359
|
+
return references.map((el) => this.normalizeReferenceType(el));
|
|
1372
1360
|
}
|
|
1373
1361
|
|
|
1374
1362
|
// -- Historical Node -----------------------------------------------------------------------------------------
|
package/src/base_node_impl.ts
CHANGED
|
@@ -237,7 +237,13 @@ export class BaseNodeImpl extends EventEmitter implements BaseNode {
|
|
|
237
237
|
_cache.typeDefinitionObj = nodeId ? (this.addressSpace.findNode(nodeId) as UAObjectType | UAVariableType) : null;
|
|
238
238
|
}
|
|
239
239
|
if (!_cache.typeDefinitionObj) {
|
|
240
|
-
warningLog(
|
|
240
|
+
warningLog(
|
|
241
|
+
this.nodeClass,
|
|
242
|
+
"cannot find typeDefinitionObj ",
|
|
243
|
+
this.browseName.toString(),
|
|
244
|
+
this.nodeId.toString(),
|
|
245
|
+
NodeClass[this.nodeClass]
|
|
246
|
+
);
|
|
241
247
|
}
|
|
242
248
|
return _cache.typeDefinitionObj as UAObjectType | UAVariableType;
|
|
243
249
|
}
|
|
@@ -390,7 +396,6 @@ export class BaseNodeImpl extends EventEmitter implements BaseNode {
|
|
|
390
396
|
return results;
|
|
391
397
|
}
|
|
392
398
|
|
|
393
|
-
|
|
394
399
|
public findReferences_no_cache(referenceTypeNode: UAReferenceType, isForward = true): UAReference[] {
|
|
395
400
|
const _private = BaseNode_getPrivate(this);
|
|
396
401
|
const result: UAReference[] = [];
|
|
@@ -500,7 +505,7 @@ export class BaseNodeImpl extends EventEmitter implements BaseNode {
|
|
|
500
505
|
// _cache._notifiers = this.findReferencesAsObject("HasNotifier", true);
|
|
501
506
|
// }
|
|
502
507
|
// return _cache._notifiers;
|
|
503
|
-
return
|
|
508
|
+
return this.findReferencesAsObject("HasNotifier", true);
|
|
504
509
|
}
|
|
505
510
|
|
|
506
511
|
/**
|
package/src/base_node_private.ts
CHANGED
|
@@ -40,6 +40,7 @@ import { UANamespace_process_modelling_rule } from "./namespace_private";
|
|
|
40
40
|
import { ReferenceImpl } from "./reference_impl";
|
|
41
41
|
import { BaseNodeImpl, getReferenceType } from "./base_node_impl";
|
|
42
42
|
import { AddressSpacePrivate } from "./address_space_private";
|
|
43
|
+
import { wipeMemorizedStuff } from "./tool_isSupertypeOf";
|
|
43
44
|
|
|
44
45
|
// eslint-disable-next-line prefer-const
|
|
45
46
|
let doTrace = checkDebugFlag("INSTANTIATE");
|
|
@@ -126,6 +127,7 @@ export function BaseNode_clearCache(node: BaseNode): void {
|
|
|
126
127
|
if (_private && _private._cache) {
|
|
127
128
|
_private._cache = {};
|
|
128
129
|
}
|
|
130
|
+
wipeMemorizedStuff(node);
|
|
129
131
|
}
|
|
130
132
|
const hasTypeDefinition_ReferenceTypeNodeId = resolveNodeId("HasTypeDefinition");
|
|
131
133
|
|
|
@@ -681,6 +683,10 @@ function _cloneInterface(
|
|
|
681
683
|
|
|
682
684
|
extraInfo = extraInfo || defaultExtraInfo;
|
|
683
685
|
const addressSpace = node.addressSpace;
|
|
686
|
+
|
|
687
|
+
if (node.nodeClass !== NodeClass.Object && node.nodeClass !== NodeClass.Variable) {
|
|
688
|
+
return;
|
|
689
|
+
}
|
|
684
690
|
const typeDefinitionNode = node.typeDefinitionObj;
|
|
685
691
|
if (!typeDefinitionNode) {
|
|
686
692
|
return;
|
|
@@ -813,25 +819,25 @@ export function _clone<T extends UAObject | UAVariable | UAMethod>(
|
|
|
813
819
|
const browseNameMap = new Set<string>();
|
|
814
820
|
_clone_children_references(this, cloneObj, options.copyAlsoModellingRules, newFilter!, extraInfo, browseNameMap);
|
|
815
821
|
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
822
|
+
if (this.nodeClass === NodeClass.Object || this.nodeClass === NodeClass.Variable) {
|
|
823
|
+
let typeDefinitionNode: UAVariableType | UAObjectType | null = this.typeDefinitionObj;
|
|
824
|
+
while (typeDefinitionNode) {
|
|
825
|
+
doTrace &&
|
|
826
|
+
traceLog(
|
|
827
|
+
extraInfo?.pad(),
|
|
828
|
+
chalk.blueBright("---------------------- Exploring ", typeDefinitionNode.browseName.toString())
|
|
829
|
+
);
|
|
830
|
+
_clone_children_references(
|
|
831
|
+
typeDefinitionNode,
|
|
832
|
+
cloneObj,
|
|
833
|
+
options.copyAlsoModellingRules,
|
|
834
|
+
newFilter,
|
|
835
|
+
extraInfo,
|
|
836
|
+
browseNameMap
|
|
823
837
|
);
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
cloneObj,
|
|
827
|
-
options.copyAlsoModellingRules,
|
|
828
|
-
newFilter,
|
|
829
|
-
extraInfo,
|
|
830
|
-
browseNameMap
|
|
831
|
-
);
|
|
832
|
-
typeDefinitionNode = typeDefinitionNode.subtypeOfObj;
|
|
838
|
+
typeDefinitionNode = typeDefinitionNode.subtypeOfObj;
|
|
839
|
+
}
|
|
833
840
|
}
|
|
834
|
-
|
|
835
841
|
_clone_non_hierarchical_references(this, cloneObj, options.copyAlsoModellingRules, newFilter, extraInfo, browseNameMap);
|
|
836
842
|
}
|
|
837
843
|
cloneObj.propagate_back_references();
|
package/src/namespace_impl.ts
CHANGED
|
@@ -10,7 +10,7 @@ import { AxisScaleEnumeration } from "node-opcua-data-access";
|
|
|
10
10
|
import { AccessRestrictionsFlag, coerceLocalizedText, QualifiedNameLike } from "node-opcua-data-model";
|
|
11
11
|
import { QualifiedName } from "node-opcua-data-model";
|
|
12
12
|
import { BrowseDirection } from "node-opcua-data-model";
|
|
13
|
-
import {
|
|
13
|
+
import { NodeClass } from "node-opcua-data-model";
|
|
14
14
|
import { dumpIf, make_errorLog } from "node-opcua-debug";
|
|
15
15
|
import { NodeIdLike, NodeIdType, resolveNodeId } from "node-opcua-nodeid";
|
|
16
16
|
import { NodeId } from "node-opcua-nodeid";
|
|
@@ -124,7 +124,7 @@ import { UAReferenceTypeImpl } from "./ua_reference_type_impl";
|
|
|
124
124
|
import { UAViewImpl } from "./ua_view_impl";
|
|
125
125
|
import { UAStateMachineImpl, UATransitionImpl } from "./state_machine/finite_state_machine";
|
|
126
126
|
import { _addMultiStateValueDiscrete } from "./data_access/ua_multistate_value_discrete_impl";
|
|
127
|
-
|
|
127
|
+
|
|
128
128
|
|
|
129
129
|
function _makeHashKey(nodeId: NodeId): string | number {
|
|
130
130
|
switch (nodeId.identifierType) {
|
|
@@ -615,7 +615,7 @@ export class NamespaceImpl implements NamespacePrivate {
|
|
|
615
615
|
assert(!Object.prototype.hasOwnProperty.call(options, "nodeClass"));
|
|
616
616
|
assert(Object.prototype.hasOwnProperty.call(options, "browseName"), "must provide a browseName");
|
|
617
617
|
|
|
618
|
-
const options1 = options as
|
|
618
|
+
const options1 = options as unknown as { nodeClass: NodeClass; references: AddReferenceOpts[]; subtypeOf: UADataType };
|
|
619
619
|
options1.nodeClass = NodeClass.DataType;
|
|
620
620
|
options1.references = options.references || [];
|
|
621
621
|
|
|
@@ -638,6 +638,9 @@ export class NamespaceImpl implements NamespacePrivate {
|
|
|
638
638
|
});
|
|
639
639
|
}
|
|
640
640
|
const node = this.internalCreateNode(options) as UADataType;
|
|
641
|
+
|
|
642
|
+
node.propagate_back_references();
|
|
643
|
+
|
|
641
644
|
return node;
|
|
642
645
|
}
|
|
643
646
|
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { INamespace, UADataType, UAVariable, UAVariableType } from "node-opcua-address-space-base";
|
|
2
2
|
import { NodeClass } from "node-opcua-data-model";
|
|
3
3
|
import { StructureField } from "node-opcua-types";
|
|
4
|
+
import { make_warningLog } from "node-opcua-debug";
|
|
4
5
|
import { NamespacePrivate } from "../namespace_private";
|
|
5
6
|
import { BaseNodeImpl, getReferenceType } from "../base_node_impl";
|
|
6
7
|
|
|
8
|
+
const warningLog = make_warningLog(__filename);
|
|
9
|
+
|
|
7
10
|
function _constructNamespaceDependency(
|
|
8
11
|
namespace: INamespace,
|
|
9
12
|
dependency: INamespace[],
|
|
@@ -43,6 +46,12 @@ function _constructNamespaceDependency(
|
|
|
43
46
|
if (_visitedDataType.has(dataType.toString())) {
|
|
44
47
|
return;
|
|
45
48
|
}
|
|
49
|
+
// istanbul ignore next
|
|
50
|
+
if (dataTypeNode.nodeClass !== NodeClass.DataType) {
|
|
51
|
+
warningLog("exploreDataTypes! ignoring ",dataTypeNode.toString());
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
|
|
46
55
|
const namespaceIndex = dataType.namespace;
|
|
47
56
|
consider(namespaceIndex);
|
|
48
57
|
if (dataTypeNode.isStructure()) {
|
|
@@ -35,7 +35,6 @@ import { AttributeIds, Int64, minOPCUADate, StatusCode, StatusCodes } from "node
|
|
|
35
35
|
import { BrowseDescription, EnumDefinition, StructureDefinition, StructureType } from "node-opcua-types";
|
|
36
36
|
|
|
37
37
|
import { ITranslationTable, XmlWriter } from "../../source/xml_writer";
|
|
38
|
-
import { NamespacePrivate } from "../namespace_private";
|
|
39
38
|
import { ReferenceImpl } from "../reference_impl";
|
|
40
39
|
import { BaseNodeImpl, getReferenceType } from "../base_node_impl";
|
|
41
40
|
import { UAReferenceTypeImpl } from "../ua_reference_type_impl";
|
|
@@ -50,7 +49,11 @@ import { SessionContext } from "../index_current";
|
|
|
50
49
|
|
|
51
50
|
import { DefinitionMap2, TypeInfo } from "../../source/loader/make_xml_extension_object_parser";
|
|
52
51
|
import { makeDefinitionMap } from "../../source/loader/decode_xml_extension_object";
|
|
53
|
-
import {
|
|
52
|
+
import {
|
|
53
|
+
constructNamespaceDependency,
|
|
54
|
+
constructNamespacePriorityTable,
|
|
55
|
+
hasHigherPriorityThan
|
|
56
|
+
} from "./construct_namespace_dependency";
|
|
54
57
|
|
|
55
58
|
// tslint:disable:no-var-requires
|
|
56
59
|
const XMLWriter = require("xml-writer");
|
|
@@ -247,6 +250,10 @@ function findXsdNamespaceUri(xw: XmlWriter, nodeId: NodeId): string {
|
|
|
247
250
|
if (namespace === "http://opcfoundation.org/UA/") {
|
|
248
251
|
return "http://opcfoundation.org/UA/2008/02/Types.xsd";
|
|
249
252
|
}
|
|
253
|
+
// istanbul ignore next
|
|
254
|
+
if (!namespace) {
|
|
255
|
+
return "";
|
|
256
|
+
}
|
|
250
257
|
return namespace.replace(/\/$/, "") + "/Types.xsd";
|
|
251
258
|
}
|
|
252
259
|
|
|
@@ -628,37 +635,37 @@ function _dumpValue(xw: XmlWriter, node: UAVariable | UAVariableType, value: Var
|
|
|
628
635
|
if (isExtensionObject) {
|
|
629
636
|
const encodeXml = _dumpVariantExtensionObjectValue2.bind(null, xw, dataTypeNode);
|
|
630
637
|
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
638
|
+
switch (value.arrayType) {
|
|
639
|
+
case VariantArrayType.Matrix:
|
|
640
|
+
case VariantArrayType.Array:
|
|
641
|
+
startElementEx(xw, uax, `ListOf${baseDataTypeName}`, "http://opcfoundation.org/UA/2008/02/Types.xsd");
|
|
642
|
+
value.value.forEach(encodeXml);
|
|
643
|
+
restoreDefaultNamespace(xw);
|
|
644
|
+
xw.endElement();
|
|
645
|
+
break;
|
|
646
|
+
case VariantArrayType.Scalar:
|
|
647
|
+
encodeXml(value.value);
|
|
648
|
+
break;
|
|
649
|
+
default:
|
|
650
|
+
errorLog(node.toString());
|
|
651
|
+
errorLog("_dumpValue : unsupported arrayType: ", value.arrayType);
|
|
642
652
|
}
|
|
643
653
|
} else {
|
|
644
654
|
const encodeXml = _dumpVariantValue.bind(null, xw, value.dataType, node);
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
errorLog(node.toString());
|
|
660
|
-
errorLog("_dumpValue : unsupported case , Matrix");
|
|
661
|
-
// xx throw new Error("Unsupported case");
|
|
655
|
+
switch (value.arrayType) {
|
|
656
|
+
case VariantArrayType.Matrix:
|
|
657
|
+
case VariantArrayType.Array:
|
|
658
|
+
startElementEx(xw, uax, `ListOf${dataTypeName}`, "http://opcfoundation.org/UA/2008/02/Types.xsd");
|
|
659
|
+
value.value.forEach(encodeXml);
|
|
660
|
+
restoreDefaultNamespace(xw);
|
|
661
|
+
xw.endElement();
|
|
662
|
+
break;
|
|
663
|
+
case VariantArrayType.Scalar:
|
|
664
|
+
encodeXml(value.value);
|
|
665
|
+
break;
|
|
666
|
+
default:
|
|
667
|
+
errorLog(node.toString());
|
|
668
|
+
errorLog("_dumpValue : unsupported arrayType: ", value.arrayType);
|
|
662
669
|
}
|
|
663
670
|
}
|
|
664
671
|
|
|
@@ -675,7 +682,6 @@ function _dumpArrayDimensionsAttribute(xw: XmlWriter, node: UAVariableType | UAV
|
|
|
675
682
|
}
|
|
676
683
|
|
|
677
684
|
function visitUANode(node: BaseNode, data: DumpData, forward: boolean) {
|
|
678
|
-
|
|
679
685
|
const addressSpace = node.addressSpace;
|
|
680
686
|
|
|
681
687
|
// visit references
|
|
@@ -800,7 +806,7 @@ function dumpCommonAttributes(xw: XmlWriter, node: BaseNode) {
|
|
|
800
806
|
}
|
|
801
807
|
}
|
|
802
808
|
if (Object.prototype.hasOwnProperty.call(node, "minimumSamplingInterval")) {
|
|
803
|
-
const minimumSamplingInterval =(node as UAVariable).minimumSamplingInterval;
|
|
809
|
+
const minimumSamplingInterval = (node as UAVariable).minimumSamplingInterval;
|
|
804
810
|
if (minimumSamplingInterval > 0) {
|
|
805
811
|
xw.writeAttribute("MinimumSamplingInterval", minimumSamplingInterval);
|
|
806
812
|
}
|
|
@@ -1030,11 +1036,11 @@ function dumpUAVariableType(xw: XmlWriter, node: UAVariableType) {
|
|
|
1030
1036
|
// throw new Error(" cannot find datatype " + node.dataType);
|
|
1031
1037
|
console.log(
|
|
1032
1038
|
" cannot find datatype " +
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1039
|
+
node.dataType +
|
|
1040
|
+
" for node " +
|
|
1041
|
+
node.browseName.toString() +
|
|
1042
|
+
" id =" +
|
|
1043
|
+
node.nodeId.toString()
|
|
1038
1044
|
);
|
|
1039
1045
|
} else {
|
|
1040
1046
|
const dataTypeName = b(xw, resolveDataTypeName(addressSpace, dataTypeNode.nodeId));
|
|
@@ -1063,6 +1069,7 @@ function dumpUAObject(xw: XmlWriter, node: UAObject) {
|
|
|
1063
1069
|
_dumpUAObject(xw, node);
|
|
1064
1070
|
xw.writeComment("Object - " + b(xw, node.browseName) + " }}}} ");
|
|
1065
1071
|
}
|
|
1072
|
+
|
|
1066
1073
|
function _dumpUAObject(xw: XmlWriter, node: UAObject) {
|
|
1067
1074
|
assert(node.nodeClass === NodeClass.Object);
|
|
1068
1075
|
xw.visitedNode = xw.visitedNode || {};
|
|
@@ -1101,9 +1108,7 @@ function dumpElementInFolder(xw: XmlWriter, node: BaseNodeImpl) {
|
|
|
1101
1108
|
|
|
1102
1109
|
function dumpAggregates(xw: XmlWriter, node: BaseNode) {
|
|
1103
1110
|
// Xx xw.writeComment("Aggregates {{ ");
|
|
1104
|
-
const aggregates = node
|
|
1105
|
-
.getAggregates()
|
|
1106
|
-
.sort(sortByBrowseName);
|
|
1111
|
+
const aggregates = node.getAggregates().sort(sortByBrowseName);
|
|
1107
1112
|
// const aggregates = node.findReferencesExAsObject("Aggregates", BrowseDirection.Forward);
|
|
1108
1113
|
|
|
1109
1114
|
for (const aggregate of aggregates.sort(sortByNodeId)) {
|
|
@@ -1242,7 +1247,6 @@ function writeAliases(xw: XmlWriter, aliases: Record<string, NodeIdString>) {
|
|
|
1242
1247
|
xw.endElement();
|
|
1243
1248
|
}
|
|
1244
1249
|
|
|
1245
|
-
|
|
1246
1250
|
export function constructNamespaceTranslationTable(dependency: INamespace[]): ITranslationTable {
|
|
1247
1251
|
const translationTable: ITranslationTable = {};
|
|
1248
1252
|
for (let i = 0; i < dependency.length; i++) {
|
|
@@ -1329,8 +1333,6 @@ function makeTypeXsd(namespaceUri: string): string {
|
|
|
1329
1333
|
|
|
1330
1334
|
// eslint-disable-next-line max-statements
|
|
1331
1335
|
NamespaceImpl.prototype.toNodeset2XML = function (this: NamespaceImpl) {
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
1336
|
const namespaceArrayNode = this.addressSpace.findNode(VariableIds.Server_NamespaceArray);
|
|
1335
1337
|
const namespaceArray: string[] = namespaceArrayNode
|
|
1336
1338
|
? namespaceArrayNode.readAttribute(null, AttributeIds.Value).value.value
|
|
@@ -1343,7 +1345,6 @@ NamespaceImpl.prototype.toNodeset2XML = function (this: NamespaceImpl) {
|
|
|
1343
1345
|
const translationTable = constructNamespaceTranslationTable(dependency);
|
|
1344
1346
|
xw.translationTable = translationTable;
|
|
1345
1347
|
|
|
1346
|
-
|
|
1347
1348
|
xw.startDocument({ encoding: "utf-8", version: "1.0" });
|
|
1348
1349
|
xw.startElement("UANodeSet");
|
|
1349
1350
|
|
|
@@ -60,6 +60,11 @@ function _slow_isSupertypeOf<T extends UAType>(this: T, Class: typeof BaseNodeIm
|
|
|
60
60
|
|
|
61
61
|
export type MemberFuncValue<T, P, R> = (this: T, param: P) => R;
|
|
62
62
|
|
|
63
|
+
export function wipeMemorizedStuff(node: any) {
|
|
64
|
+
if (!node.__cache) {
|
|
65
|
+
node.__cache = undefined;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
63
68
|
// http://jsperf.com/underscore-js-memoize-refactor-test
|
|
64
69
|
// http://addyosmani.com/blog/faster-javascript-memoization/
|
|
65
70
|
function wrap_memoize<T, P, R>(
|
package/src/ua_variable_impl.ts
CHANGED
|
@@ -1388,7 +1388,7 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
1388
1388
|
return false;
|
|
1389
1389
|
}
|
|
1390
1390
|
return checkExtensionObjectIsCorrectScalar.call(this, extObj);
|
|
1391
|
-
} else if (this.valueRank
|
|
1391
|
+
} else if (this.valueRank >= 1) {
|
|
1392
1392
|
/** array */
|
|
1393
1393
|
if (!(extObj instanceof Array)) {
|
|
1394
1394
|
// let's coerce this scalar into an 1-element array if it is a valid extension object
|