node-opcua-convert-nodeset-to-javascript 2.51.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.
Files changed (48) hide show
  1. package/.mocharc.yml +10 -0
  2. package/LICENSE +20 -0
  3. package/dist/convert_namespace_to_typescript.d.ts +3 -0
  4. package/dist/convert_namespace_to_typescript.js +158 -0
  5. package/dist/convert_namespace_to_typescript.js.map +1 -0
  6. package/dist/convert_to_typescript.d.ts +109 -0
  7. package/dist/convert_to_typescript.js +879 -0
  8. package/dist/convert_to_typescript.js.map +1 -0
  9. package/dist/index.d.ts +3 -0
  10. package/dist/index.js +16 -0
  11. package/dist/index.js.map +1 -0
  12. package/dist/main.d.ts +1 -0
  13. package/dist/main.js +66 -0
  14. package/dist/main.js.map +1 -0
  15. package/dist/official_namespaces.d.ts +23 -0
  16. package/dist/official_namespaces.js +36 -0
  17. package/dist/official_namespaces.js.map +1 -0
  18. package/dist/options.d.ts +4 -0
  19. package/dist/options.js +3 -0
  20. package/dist/options.js.map +1 -0
  21. package/dist/private/cache.d.ts +58 -0
  22. package/dist/private/cache.js +213 -0
  23. package/dist/private/cache.js.map +1 -0
  24. package/dist/private/to_filename.d.ts +1 -0
  25. package/dist/private/to_filename.js +10 -0
  26. package/dist/private/to_filename.js.map +1 -0
  27. package/dist/private/utils.d.ts +24 -0
  28. package/dist/private/utils.js +261 -0
  29. package/dist/private/utils.js.map +1 -0
  30. package/dist/private-stuff.d.ts +4 -0
  31. package/dist/private-stuff.js +17 -0
  32. package/dist/private-stuff.js.map +1 -0
  33. package/dist/walk_through.d.ts +13 -0
  34. package/dist/walk_through.js +87 -0
  35. package/dist/walk_through.js.map +1 -0
  36. package/package.json +58 -0
  37. package/source/convert_namespace_to_typescript.ts +171 -0
  38. package/source/convert_to_typescript.ts +1095 -0
  39. package/source/index.ts +3 -0
  40. package/source/main.ts +56 -0
  41. package/source/official_namespaces.ts +35 -0
  42. package/source/options.ts +4 -0
  43. package/source/private/cache.ts +228 -0
  44. package/source/private/to_filename.ts +6 -0
  45. package/source/private/utils.ts +212 -0
  46. package/source/private-stuff.ts +6 -0
  47. package/source/walk_through.ts +73 -0
  48. package/tsconfig-generated.json +13 -0
@@ -0,0 +1,3 @@
1
+ export * from "./convert_to_typescript";
2
+ export * from "./convert_namespace_to_typescript";
3
+ export * from "./walk_through";
package/source/main.ts ADDED
@@ -0,0 +1,56 @@
1
+ import * as path from "path";
2
+ import { AddressSpace, PseudoSession } from "node-opcua-address-space";
3
+ import { generateAddressSpace } from "node-opcua-address-space/nodeJS";
4
+ import { nodesets } from "node-opcua-nodesets";
5
+ import { convertNamespaceTypeToTypescript } from "./convert_namespace_to_typescript";
6
+
7
+ async function main() {
8
+ const addressSpace = AddressSpace.create();
9
+ await generateAddressSpace(addressSpace, [
10
+ nodesets.standard,
11
+ nodesets.di,
12
+ nodesets.adi,
13
+ nodesets.autoId,
14
+ nodesets.machineVision,
15
+ nodesets.commercialKitchenEquipment,
16
+ nodesets.gds,
17
+ nodesets.robotics,
18
+ nodesets.machinery,
19
+ nodesets.ia,
20
+ nodesets.machineTool,
21
+ nodesets.cnc
22
+ ]);
23
+
24
+
25
+ const nsUA = 0;
26
+ const nsDI = addressSpace.getNamespaceIndex("http://opcfoundation.org/UA/DI/");
27
+ const nsADI = addressSpace.getNamespaceIndex("http://opcfoundation.org/UA/ADI/");
28
+ const nsMachineVision = addressSpace.getNamespaceIndex("http://opcfoundation.org/UA/MachineVision");
29
+ const nsAutoId = addressSpace.getNamespaceIndex("http://opcfoundation.org/UA/AutoID/");
30
+ const nsGds = addressSpace.getNamespaceIndex("http://opcfoundation.org/UA/GDS/");
31
+ const nsRobotics = addressSpace.getNamespaceIndex("http://opcfoundation.org/UA/Robotics/");
32
+ const nsMachinery = addressSpace.getNamespaceIndex("http://opcfoundation.org/UA/Machinery/");
33
+ const nsIA = addressSpace.getNamespaceIndex("http://opcfoundation.org/UA/IA/");
34
+ const nsMachineTool = addressSpace.getNamespaceIndex("http://opcfoundation.org/UA/MachineTool/");
35
+ const ncCNC = addressSpace.getNamespaceIndex("http://opcfoundation.org/UA/CNC");
36
+ const nsCommercialKitchenEquipment = addressSpace.getNamespaceIndex("http://opcfoundation.org/UA/CommercialKitchenEquipment/");
37
+
38
+ const session = new PseudoSession(addressSpace);
39
+ const options = {
40
+ baseFolder: path.join(__dirname, "../../"),
41
+ prefix: "node-opcua-nodeset-"
42
+ };
43
+ await convertNamespaceTypeToTypescript(session, nsUA, options);
44
+ await convertNamespaceTypeToTypescript(session, nsDI, options);
45
+ await convertNamespaceTypeToTypescript(session, nsADI, options);
46
+ await convertNamespaceTypeToTypescript(session, nsMachineVision, options);
47
+ await convertNamespaceTypeToTypescript(session, nsAutoId, options);
48
+ await convertNamespaceTypeToTypescript(session, nsGds, options);
49
+ await convertNamespaceTypeToTypescript(session, nsRobotics, options);
50
+ await convertNamespaceTypeToTypescript(session, nsMachinery, options);
51
+ await convertNamespaceTypeToTypescript(session, nsIA, options);
52
+ await convertNamespaceTypeToTypescript(session, nsMachineTool, options);
53
+ await convertNamespaceTypeToTypescript(session, ncCNC, options);
54
+ await convertNamespaceTypeToTypescript(session, nsCommercialKitchenEquipment, options);
55
+ }
56
+ main();
@@ -0,0 +1,35 @@
1
+
2
+
3
+ export const officialNamespaces = {
4
+ "standard": {
5
+ location: "node-opcua-ua-types-ua"
6
+ },
7
+ "di": {
8
+ location: "node-opcua-nodeset-di"
9
+ },
10
+ "adi": {
11
+ location: "node-opcua-nodeset-adi"
12
+ },
13
+ "autoId": {
14
+ location: "node-opcua-nodeset-auto-id"
15
+ },
16
+ "machineVision": {
17
+ location: "node-opcua-nodeset-machine-vision"
18
+ },
19
+ "commercialKitchenEquipment": {
20
+ location: "node-opcua-nodeset-commercial-kitchen-equipment"
21
+
22
+ },
23
+ "gds": {
24
+ location: "node-opcua-types-gds"
25
+ }
26
+ };
27
+ /*
28
+ nodesets.standard,
29
+ nodesets.di,
30
+ nodesets.adi,
31
+ nodesets.autoId,
32
+ nodesets.machineVision,
33
+ nodesets.commercialKitchenEquipment,
34
+ nodesets.gds
35
+ */
@@ -0,0 +1,4 @@
1
+ export interface Options {
2
+ baseFolder: string;
3
+ prefix: string;
4
+ }
@@ -0,0 +1,228 @@
1
+ import * as path from "path";
2
+ import assert from "node-opcua-assert";
3
+ import { AttributeIds, NodeClass, QualifiedName } from "node-opcua-data-model";
4
+ import { NodeId, resolveNodeId } from "node-opcua-nodeid";
5
+ import { IBasicSession } from "node-opcua-pseudo-session";
6
+ import { DataTypeDefinition, EnumDefinition } from "node-opcua-types";
7
+ import { kebabCase } from "case-anything";
8
+ import { Options } from "../options";
9
+ import { getBrowseName, getDefinition } from "./utils";
10
+
11
+ export interface Import {
12
+ name: string;
13
+ module: string;
14
+ namespace: number;
15
+ }
16
+ interface CacheInterfaceNamespace {
17
+ namespaceUri: string;
18
+ sourceFolder: string;
19
+ module: string;
20
+ symbols: { [key: string]: number };
21
+ }
22
+ interface CacheInterface {
23
+ namespace: CacheInterfaceNamespace[];
24
+ requestedSymbols: RequestedSymbol;
25
+ }
26
+ export interface RequestedSubSymbol {
27
+ subSymbols: { [key: string]: number };
28
+ }
29
+ interface RequestedSymbol {
30
+ namespace: {
31
+ symbols: { [key: string]: RequestedSubSymbol };
32
+ }[];
33
+ }
34
+
35
+ export class Cache implements CacheInterface {
36
+ namespace: CacheInterfaceNamespace[] = [];
37
+ requestedSymbols: RequestedSymbol = { namespace: [] };
38
+ requestedBasicTypes: { [key: string]: number } = {};
39
+ imports: { [key: string]: { [key: string]: number } } = {};
40
+ public constructor() {
41
+ this.imports = {
42
+ "node-opcua-address-space-base": {
43
+ UAObject: 1,
44
+ UAVariable: 1,
45
+ UAVariableT: 1,
46
+ UAMethod: 1,
47
+ UADataType: 1,
48
+ UAProperty: 1,
49
+ },
50
+ "node-opcua-variant": {
51
+ DataType: 1,
52
+ Variant: 1
53
+ },
54
+ "node-opcua-data-model": {
55
+ LocalizedText: 1,
56
+ QualifiedName: 1,
57
+ DiagnosticInfo: 1
58
+ },
59
+ "node-opcua-data-access": {
60
+ EUInformation: 1
61
+ },
62
+ "node-opcua-nodeid": {
63
+ NodeId: 1,
64
+ ExpandedNodeId: 1
65
+ },
66
+ "node-opcua-status-code": {
67
+ StatusCode: 1,
68
+ StatusCodes: 1
69
+ },
70
+ "node-opcua-basic-types": {
71
+ Int64: 1,
72
+ UInt64: 1,
73
+ UInt32: 1,
74
+ Int32: 1,
75
+ UInt16: 1,
76
+ Int16: 1,
77
+ Byte: 1,
78
+ SByte: 1,
79
+ UAString: 1,
80
+ DateTime: 1,
81
+ Guid: 1
82
+ },
83
+ "node-opcua-data-value": {
84
+ DataValue: 1
85
+ },
86
+ "node-opcua-types": {
87
+ EnumValueType: 1
88
+ }
89
+ };
90
+ }
91
+ resetRequire(): void {
92
+ this.requestedSymbols = { namespace: [] };
93
+ this.requestedBasicTypes = {};
94
+ }
95
+
96
+ referenceBasicType(basicType: string): string {
97
+ this.requestedBasicTypes[basicType] = (this.requestedBasicTypes[basicType] || 0) + 1;
98
+ return basicType;
99
+ }
100
+
101
+ _reference(namespaceIndex: number, typeName: string, mainTypeName?: string): void {
102
+ if (namespaceIndex <= 0 && this.imports["node-opcua-address-space-base"][typeName]) {
103
+ this.referenceBasicType(typeName);
104
+ return;
105
+ }
106
+ {
107
+ const sourceFolder = this.namespace[namespaceIndex]?.sourceFolder;
108
+ if (!sourceFolder) {
109
+ throw new Error("Cannot find namespace " + namespaceIndex);
110
+ }
111
+ }
112
+ const symbols = (this.namespace[namespaceIndex].symbols = this.namespace[namespaceIndex].symbols || {});
113
+ symbols[typeName] = (symbols[typeName] || 0) + 1;
114
+
115
+ const ns = this.requestedSymbols.namespace[namespaceIndex] || { symbols: {} };
116
+ this.requestedSymbols.namespace[namespaceIndex] = ns;
117
+
118
+ ns.symbols = ns.symbols || {};
119
+
120
+ if (!mainTypeName) {
121
+ mainTypeName = typeName;
122
+ }
123
+ const subs = (ns.symbols[mainTypeName] = ns.symbols[mainTypeName] || { subSymbols: {} });
124
+ subs.subSymbols[typeName] = (subs.subSymbols[typeName] || 0) + 1;
125
+ }
126
+
127
+ ensureImported(i: Import): void {
128
+ if (i.namespace < 0) {
129
+ this.referenceBasicType(i.name);
130
+ } else {
131
+ this._reference(i.namespace, i.name, i.module);
132
+ }
133
+ }
134
+ }
135
+
136
+
137
+ function getSourceFolderForNamespace(browseName: QualifiedName, options: Options, cache: Cache2) {
138
+ const ns = browseName.namespaceIndex;
139
+ const n = cache.namespaceArray[ns].split("/").filter((s: string) => s.length !== 0);
140
+ const nn = n[n.length - 1];
141
+ const module = options.prefix + kebabCase(nn);
142
+ const namespaceFolder = path.join(options.baseFolder, module);
143
+ const sourceFolder = path.join(namespaceFolder);
144
+ return { sourceFolder, module };
145
+ }
146
+
147
+ export async function referenceExtensionObject(session: IBasicSession, extensionObjectDataType: NodeId): Promise<Import> {
148
+ const browseName = await getBrowseName(session, extensionObjectDataType);
149
+ const definition = await getDefinition(session, extensionObjectDataType);
150
+ const dataTypeNameImport = makeTypeNameNew(NodeClass.DataType, definition, browseName);
151
+ return dataTypeNameImport;
152
+ }
153
+
154
+ export class Cache2 extends Cache {
155
+ public namespaceArray: string[] = [];
156
+ }
157
+
158
+ export async function constructCache(session: IBasicSession, options: Options): Promise<Cache2> {
159
+ const cache = new Cache2();
160
+
161
+ cache.namespaceArray = cache.namespaceArray.length
162
+ ? cache.namespaceArray
163
+ : (
164
+ await session.read({
165
+ nodeId: resolveNodeId("Server_NamespaceArray"),
166
+ attributeId: AttributeIds.Value
167
+ })
168
+ ).value.value;
169
+
170
+ for (let namespaceIndex = 0; namespaceIndex < cache.namespaceArray.length; namespaceIndex++) {
171
+ const namespaceUri = cache.namespaceArray[namespaceIndex];
172
+ const { sourceFolder, module } = getSourceFolderForNamespace(
173
+ new QualifiedName({ name: namespaceUri, namespaceIndex }),
174
+ options,
175
+ cache
176
+ );
177
+ cache.namespace.push({
178
+ namespaceUri,
179
+ sourceFolder,
180
+ module,
181
+ symbols: {}
182
+ });
183
+ }
184
+ return cache;
185
+ }
186
+
187
+ function makeBasicTypeImport(name: string): Import {
188
+ return { name, module: "BasicType", namespace: -1 };
189
+ }
190
+ export function makeTypeNameNew(nodeClass: NodeClass, definition: DataTypeDefinition | null, browseName: QualifiedName, suffix?: string): Import {
191
+ assert(browseName && !!browseName.name, "expecting a class name here");
192
+
193
+ const typeName = browseName.name!.toString();
194
+ if (typeName === "EUInformation") {
195
+ return makeBasicTypeImport("EUInformation");
196
+ } else if (typeName === "Enumeration") {
197
+ return makeBasicTypeImport("Enumeration");
198
+ } else if (typeName === "BaseObjectType") {
199
+ return makeBasicTypeImport("UAObject");
200
+ } else if (typeName === "BaseVariableType") {
201
+ return makeBasicTypeImport("UAVariableT");
202
+ } else if (typeName === "BaseDataType") {
203
+ return makeBasicTypeImport("UADataType");
204
+ } else {
205
+ let name = "";
206
+ switch (nodeClass) {
207
+ case NodeClass.Method:
208
+ return makeBasicTypeImport("UAMethod");
209
+ case NodeClass.Variable:
210
+ case NodeClass.Object:
211
+ case NodeClass.VariableType:
212
+ case NodeClass.ObjectType:
213
+ name = `UA${typeName.replace(/Type$/, "")}` + (suffix || "");
214
+ break;
215
+ case NodeClass.DataType:
216
+ if (definition instanceof EnumDefinition) {
217
+ name = `Enum${typeName.replace(/(DataType|Enumeration|Type)$/, "")}`;
218
+ } else {
219
+ name = `DT${typeName.replace(/(DataType|Enumeration|Type)$/, "")}`;
220
+ }
221
+ break;
222
+ }
223
+ if (name === "") {
224
+ throw new Error("Internal Error " + NodeClass[nodeClass] + " " + typeName + "browseName = " + browseName.toString());
225
+ }
226
+ return { name, module: name, namespace: browseName.namespaceIndex };
227
+ }
228
+ }
@@ -0,0 +1,6 @@
1
+ import { snakeCase } from "case-anything";
2
+
3
+ export function toFilename(str: string): string {
4
+ str = str.replace(/^DT/,"dt_").replace(/^UA/,"ua_").replace(/^Enum/,"enum_");
5
+ return snakeCase(str);
6
+ }
@@ -0,0 +1,212 @@
1
+ import { AttributeIds, BrowseDirection, LocalizedText, NodeClass, NodeClassMask, QualifiedName } from "node-opcua-data-model";
2
+ import { NodeId, resolveNodeId } from "node-opcua-nodeid";
3
+ import { IBasicSession } from "node-opcua-pseudo-session";
4
+ import { BrowseResult, DataTypeDefinition, ReferenceDescription, StructureDefinition } from "node-opcua-types";
5
+ import { ModellingRuleType } from "node-opcua-address-space-base";
6
+ import { DataType } from "node-opcua-variant";
7
+ import { StatusCodes } from "node-opcua-status-code";
8
+
9
+ export async function getDefinition(session: IBasicSession, nodeId: NodeId): Promise<DataTypeDefinition | null> {
10
+ const dataValue = await session.read({ nodeId, attributeId: AttributeIds.DataTypeDefinition });
11
+ return (dataValue.value.value as DataTypeDefinition) || null;
12
+ }
13
+ export async function getBrowseName(session: IBasicSession, nodeId: NodeId): Promise<QualifiedName> {
14
+ const dataValue = await session.read({ nodeId, attributeId: AttributeIds.BrowseName });
15
+ return dataValue.value.value as QualifiedName;
16
+ }
17
+ export async function getDataTypeNodeId(session: IBasicSession, nodeId: NodeId): Promise<NodeId | null> {
18
+ const dataValue = await session.read({ nodeId, attributeId: AttributeIds.DataType });
19
+ return (dataValue.value.value as NodeId) || null;
20
+ }
21
+ export async function getIsAbstract(session: IBasicSession, nodeId: NodeId): Promise<boolean> {
22
+ const dataValue = await session.read({ nodeId, attributeId: AttributeIds.IsAbstract });
23
+ return dataValue.value.value as boolean;
24
+ }
25
+ export async function getDescription(session: IBasicSession, nodeId: NodeId): Promise<LocalizedText> {
26
+ const dataValue = await session.read({ nodeId, attributeId: AttributeIds.Description });
27
+ return dataValue.value.value as LocalizedText;
28
+ }
29
+
30
+ export async function getNodeClass(session: IBasicSession, nodeId: NodeId): Promise<NodeClass> {
31
+ const dataValue = await session.read({ nodeId, attributeId: AttributeIds.NodeClass });
32
+ return dataValue.value.value as NodeClass;
33
+ }
34
+ export async function getChildren(session: IBasicSession, nodeId: NodeId): Promise<ReferenceDescription[]> {
35
+ const browseResult = await session.browse({
36
+ browseDirection: BrowseDirection.Forward,
37
+ includeSubtypes: true,
38
+ nodeClassMask: NodeClassMask.Method | NodeClassMask.Object | NodeClass.Variable,
39
+ nodeId,
40
+ referenceTypeId: resolveNodeId("HasChild"),
41
+ resultMask: 0xffff
42
+ });
43
+ return browseResult.references || [];
44
+ }
45
+ export async function getFolderElements(session: IBasicSession, nodeId: NodeId): Promise<ReferenceDescription[]> {
46
+ const browseResult = await session.browse({
47
+ browseDirection: BrowseDirection.Forward,
48
+ includeSubtypes: true,
49
+ nodeClassMask: NodeClassMask.Method | NodeClassMask.Object | NodeClass.Variable,
50
+ nodeId,
51
+ referenceTypeId: resolveNodeId("Organizes"),
52
+ resultMask: 0xffff
53
+ });
54
+ return browseResult.references || [];
55
+ }
56
+
57
+ export async function getModellingRule(session: IBasicSession, nodeId: NodeId): Promise<ModellingRuleType | null> {
58
+ const browseResult = await session.browse({
59
+ browseDirection: BrowseDirection.Forward,
60
+ includeSubtypes: true,
61
+ nodeClassMask: NodeClassMask.Method | NodeClassMask.Object | NodeClass.Variable,
62
+ nodeId,
63
+ referenceTypeId: resolveNodeId("HasModellingRule"),
64
+ resultMask: 0xffff
65
+ });
66
+ if (!browseResult.references || browseResult.references.length === 0) {
67
+ return null;
68
+ /*
69
+ console.log(nodeId.toString());
70
+ const browseName = await getBrowseName(session, nodeId);
71
+ throw new Error("No modelling rule for " + nodeId.toString() + " " + browseName.toString());
72
+ */
73
+ }
74
+ return browseResult.references[0].browseName.name! as ModellingRuleType;
75
+ }
76
+ export async function isExtensionObject(session: IBasicSession, nodeId: NodeId): Promise<boolean> {
77
+ if (nodeId.namespace === 0 && nodeId.value === 22) {
78
+ return true;
79
+ }
80
+ if (nodeId.namespace === 0 && nodeId.value <= 25) {
81
+ return false;
82
+ }
83
+ const r = await getSubtypeNodeIdIfAny(session, nodeId);
84
+ return await isExtensionObject(session, r!.nodeId);
85
+ }
86
+
87
+ export async function extractBasicDataType(session: IBasicSession, dataTypeNodeId: NodeId): Promise<DataType> {
88
+ if (dataTypeNodeId.namespace === 0 && dataTypeNodeId.value <= 25) {
89
+ return dataTypeNodeId.value as DataType;
90
+ }
91
+ const r = await getSubtypeNodeIdIfAny(session, dataTypeNodeId);
92
+ return await extractBasicDataType(session, r!.nodeId);
93
+ }
94
+
95
+ export async function getSubtypeNodeIdIfAny(session: IBasicSession, nodeId: NodeId): Promise<ReferenceDescription | null> {
96
+ if (nodeId.isEmpty()) {
97
+ return null;
98
+ }
99
+ const browseResult = await session.browse({
100
+ browseDirection: BrowseDirection.Inverse,
101
+ includeSubtypes: true,
102
+ nodeClassMask: 0, // NodeClassMask.ObjectType| NodeClass.VariableType,
103
+ nodeId,
104
+ referenceTypeId: resolveNodeId("HasSubtype"),
105
+ resultMask: 0xffff
106
+ });
107
+ if (!browseResult.references || browseResult.references.length === 0) {
108
+ return null;
109
+ }
110
+ return browseResult.references[0];
111
+ }
112
+ export async function getSubtypeNodeId(session: IBasicSession, nodeId: NodeId): Promise<ReferenceDescription> {
113
+ const r = await getSubtypeNodeIdIfAny(session, nodeId);
114
+ if (!r) {
115
+ throw new Error("No Subtype");
116
+ }
117
+ return r;
118
+ }
119
+
120
+ export async function getTypeDefOrBaseType(session: IBasicSession, nodeId: NodeId): Promise<ReferenceDescription> {
121
+ let browseResult: BrowseResult = await session.browse({
122
+ browseDirection: BrowseDirection.Forward,
123
+ includeSubtypes: true,
124
+ nodeClassMask: 0,
125
+ nodeId,
126
+ referenceTypeId: resolveNodeId("HasTypeDefinition"),
127
+ resultMask: 0xffff
128
+ });
129
+
130
+ if (!browseResult.references || browseResult.references.length === 0) {
131
+ browseResult = await session.browse({
132
+ browseDirection: BrowseDirection.Inverse,
133
+ includeSubtypes: true,
134
+ nodeClassMask: 0,
135
+ nodeId,
136
+ referenceTypeId: resolveNodeId("HasSubtype"),
137
+ resultMask: 0xffff
138
+ });
139
+ }
140
+ if (!browseResult.references || browseResult.references.length === 0) {
141
+ // console.log("cannot find type definition / subtype for " + nodeId.toString());
142
+ return new ReferenceDescription({});
143
+ }
144
+ return browseResult.references[0];
145
+ }
146
+ export async function getTypeDefinition(session: IBasicSession, nodeId: NodeId): Promise<ReferenceDescription> {
147
+ const browseResult = await session.browse({
148
+ browseDirection: BrowseDirection.Forward,
149
+ includeSubtypes: true,
150
+ nodeClassMask: 0,
151
+ nodeId,
152
+ referenceTypeId: resolveNodeId("HasTypeDefinition"),
153
+ resultMask: 0xffff
154
+ });
155
+ if (!browseResult.references || browseResult.references.length === 0) {
156
+ console.log(nodeId.toString());
157
+ throw new Error("No subtype");
158
+ }
159
+ return browseResult.references[0];
160
+ }
161
+
162
+ // see also client-proxy
163
+ export async function convertNodeIdToDataTypeAsync(session: IBasicSession, dataTypeId: NodeId): Promise<DataType> {
164
+ const nodeToRead = {
165
+ attributeId: AttributeIds.BrowseName,
166
+ nodeId: dataTypeId
167
+ };
168
+
169
+ const dataValue = await session.read(nodeToRead);
170
+
171
+ let dataType: DataType;
172
+ // istanbul ignore next
173
+ if (dataValue.statusCode !== StatusCodes.Good) {
174
+ return (dataType = DataType.Null);
175
+ }
176
+
177
+ const dataTypeName = dataValue.value.value;
178
+
179
+ if (dataTypeId.namespace === 0 && DataType[dataTypeId.value as number]) {
180
+ dataType = dataTypeId.value as DataType;
181
+ return dataType;
182
+ }
183
+
184
+ /// example => Duration (i=290) => Double (i=11)
185
+ // read subTypeOf
186
+ const nodeToBrowse = {
187
+ browseDirection: BrowseDirection.Inverse,
188
+ nodeId: dataTypeId,
189
+ referenceTypeId: resolveNodeId("HasSubtype"),
190
+ resultMask: 0xff
191
+ };
192
+ // tslint:disable:no-shadowed-variable
193
+ const browseResult = await session.browse(nodeToBrowse);
194
+
195
+ const references = browseResult!.references;
196
+
197
+ if (!references || references.length !== 1) {
198
+ throw new Error("cannot find SuperType of " + dataTypeName.toString());
199
+ }
200
+ const nodeId = references[0].nodeId;
201
+ return convertNodeIdToDataTypeAsync(session, nodeId);
202
+ }
203
+
204
+ export async function getChildrenOrFolderElements(session: IBasicSession, nodeId: NodeId): Promise<ReferenceDescription[]> {
205
+ const c1 = await getChildren(session, nodeId);
206
+ const c2 = await getFolderElements(session, nodeId);
207
+ return (<ReferenceDescription[]>[]).concat(c1, c2);
208
+ }
209
+ export async function getValueRank(session: IBasicSession, nodeId: NodeId): Promise<number> {
210
+ const valueRankDataValue = await session.read({ nodeId, attributeId: AttributeIds.ValueRank });
211
+ return valueRankDataValue.value.value;
212
+ }
@@ -0,0 +1,6 @@
1
+ export * from "./index";
2
+ export * from "./options";
3
+ export * from "./private/cache";
4
+ export * from "./private/utils";
5
+
6
+
@@ -0,0 +1,73 @@
1
+ import { AttributeIds, BrowseDirection, NodeClass, QualifiedName } from "node-opcua-data-model";
2
+ import { ExpandedNodeId, NodeId, resolveNodeId } from "node-opcua-nodeid";
3
+ import { IBasicSession } from "node-opcua-pseudo-session";
4
+ import { ReferenceDescription } from "node-opcua-types";
5
+
6
+ export interface ReferenceDescriptionEx extends ReferenceDescription {
7
+ parent: ReferenceDescriptionEx;
8
+ }
9
+ export interface NodeVisitor {
10
+ visit(reference: ReferenceDescriptionEx, level: number): Promise<void>;
11
+ }
12
+ async function _walkThroughTypes(
13
+ session: IBasicSession,
14
+ nodeId: NodeId,
15
+ visitor?: NodeVisitor,
16
+ level?: number,
17
+ parent?: ReferenceDescription
18
+ ): Promise<void> {
19
+ level = level || 0;
20
+
21
+ if (!parent) {
22
+ const dataValues = await session.read([
23
+ { nodeId, attributeId: AttributeIds.BrowseName },
24
+ { nodeId, attributeId: AttributeIds.NodeClass }
25
+ ]);
26
+ const browseName = dataValues[0].value.value as QualifiedName;
27
+ const nodeClass = dataValues[1].value.value as NodeClass;
28
+ parent = new ReferenceDescription({
29
+ isForward: true,
30
+ nodeId: nodeId as ExpandedNodeId,
31
+ browseName,
32
+ nodeClass,
33
+ referenceTypeId: resolveNodeId("HasSubtype")
34
+ // typeDefinition,
35
+ });
36
+ }
37
+ const browseResult = await session.browse({
38
+ browseDirection: BrowseDirection.Forward,
39
+ nodeId,
40
+ includeSubtypes: true,
41
+ referenceTypeId: resolveNodeId("HasSubtype"),
42
+ resultMask: 0xff
43
+ });
44
+ for (const reference of browseResult.references || []) {
45
+ if (visitor) {
46
+ const r = reference as ReferenceDescriptionEx;
47
+ r.parent = parent as ReferenceDescriptionEx;
48
+ await visitor.visit(r, level);
49
+ }
50
+ await _walkThroughTypes(session, reference.nodeId, visitor, level + 1, reference);
51
+ }
52
+ }
53
+
54
+ export async function walkThroughReferenceTypes(session: IBasicSession, nodeVisitor?: NodeVisitor): Promise<void> {
55
+ const baseReferenceTypeNodeId = resolveNodeId("References");
56
+ await _walkThroughTypes(session, baseReferenceTypeNodeId, nodeVisitor);
57
+ }
58
+ export async function walkThroughDataTypes(session: IBasicSession, nodeVisitor?: NodeVisitor): Promise<void> {
59
+ const baseDataTypeTypeNodeId = resolveNodeId("BaseDataType");
60
+ await _walkThroughTypes(session, baseDataTypeTypeNodeId, nodeVisitor);
61
+ }
62
+ export async function walkThroughInterfaceTypes(session: IBasicSession, nodeVisitor?: NodeVisitor): Promise<void> {
63
+ const baseInterfaceTypeNodeId = resolveNodeId("BaseInterfaceType");
64
+ await _walkThroughTypes(session, baseInterfaceTypeNodeId, nodeVisitor);
65
+ }
66
+ export async function walkThroughObjectTypes(session: IBasicSession, nodeVisitor?: NodeVisitor): Promise<void> {
67
+ const baseObjectType = resolveNodeId("BaseObjectType");
68
+ await _walkThroughTypes(session, baseObjectType, nodeVisitor);
69
+ }
70
+ export async function walkThroughVariableTypes(session: IBasicSession, nodeVisitor?: NodeVisitor): Promise<void> {
71
+ const baseObjectType = resolveNodeId("BaseVariableType");
72
+ await _walkThroughTypes(session, baseObjectType, nodeVisitor);
73
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "extends": "../tsconfig.json",
3
+ "compilerOptions": {
4
+ "rootDir": "./tmp",
5
+ "outDir": "./dist-tmp",
6
+ "composite": true,
7
+ "incremental": true
8
+ },
9
+ "references": [
10
+ ],
11
+ "exclude": ["node_modules", "dist", "test", "source/*"],
12
+ "include": ["./tmp/node-opcua-nodeset*/index.d.ts"]
13
+ }