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.
- package/.mocharc.yml +10 -0
- package/LICENSE +20 -0
- package/dist/convert_namespace_to_typescript.d.ts +3 -0
- package/dist/convert_namespace_to_typescript.js +158 -0
- package/dist/convert_namespace_to_typescript.js.map +1 -0
- package/dist/convert_to_typescript.d.ts +109 -0
- package/dist/convert_to_typescript.js +879 -0
- package/dist/convert_to_typescript.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/main.d.ts +1 -0
- package/dist/main.js +66 -0
- package/dist/main.js.map +1 -0
- package/dist/official_namespaces.d.ts +23 -0
- package/dist/official_namespaces.js +36 -0
- package/dist/official_namespaces.js.map +1 -0
- package/dist/options.d.ts +4 -0
- package/dist/options.js +3 -0
- package/dist/options.js.map +1 -0
- package/dist/private/cache.d.ts +58 -0
- package/dist/private/cache.js +213 -0
- package/dist/private/cache.js.map +1 -0
- package/dist/private/to_filename.d.ts +1 -0
- package/dist/private/to_filename.js +10 -0
- package/dist/private/to_filename.js.map +1 -0
- package/dist/private/utils.d.ts +24 -0
- package/dist/private/utils.js +261 -0
- package/dist/private/utils.js.map +1 -0
- package/dist/private-stuff.d.ts +4 -0
- package/dist/private-stuff.js +17 -0
- package/dist/private-stuff.js.map +1 -0
- package/dist/walk_through.d.ts +13 -0
- package/dist/walk_through.js +87 -0
- package/dist/walk_through.js.map +1 -0
- package/package.json +58 -0
- package/source/convert_namespace_to_typescript.ts +171 -0
- package/source/convert_to_typescript.ts +1095 -0
- package/source/index.ts +3 -0
- package/source/main.ts +56 -0
- package/source/official_namespaces.ts +35 -0
- package/source/options.ts +4 -0
- package/source/private/cache.ts +228 -0
- package/source/private/to_filename.ts +6 -0
- package/source/private/utils.ts +212 -0
- package/source/private-stuff.ts +6 -0
- package/source/walk_through.ts +73 -0
- package/tsconfig-generated.json +13 -0
package/source/index.ts
ADDED
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,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,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,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
|
+
}
|