node-opcua-address-space-for-conformance-testing 2.167.0 → 2.169.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/address_space_for_conformance_testing.d.ts +6 -2
- package/dist/address_space_for_conformance_testing.js +27 -1306
- package/dist/address_space_for_conformance_testing.js.map +1 -1
- package/dist/conformance_testing/access_right_variables.d.ts +5 -0
- package/dist/conformance_testing/access_right_variables.js +45 -0
- package/dist/conformance_testing/access_right_variables.js.map +1 -0
- package/dist/conformance_testing/analog_data_items.d.ts +5 -0
- package/dist/conformance_testing/analog_data_items.js +117 -0
- package/dist/conformance_testing/analog_data_items.js.map +1 -0
- package/dist/conformance_testing/discrete_variables.d.ts +4 -0
- package/dist/conformance_testing/discrete_variables.js +111 -0
- package/dist/conformance_testing/discrete_variables.js.map +1 -0
- package/dist/conformance_testing/enumeration_variable.d.ts +5 -0
- package/dist/conformance_testing/enumeration_variable.js +24 -0
- package/dist/conformance_testing/enumeration_variable.js.map +1 -0
- package/dist/conformance_testing/helpers.d.ts +13 -0
- package/dist/conformance_testing/helpers.js +204 -0
- package/dist/conformance_testing/helpers.js.map +1 -0
- package/dist/conformance_testing/mass_variables.d.ts +5 -0
- package/dist/conformance_testing/mass_variables.js +31 -0
- package/dist/conformance_testing/mass_variables.js.map +1 -0
- package/dist/conformance_testing/node_with_references.d.ts +5 -0
- package/dist/conformance_testing/node_with_references.js +119 -0
- package/dist/conformance_testing/node_with_references.js.map +1 -0
- package/dist/conformance_testing/object_with_methods.d.ts +5 -0
- package/dist/conformance_testing/object_with_methods.js +85 -0
- package/dist/conformance_testing/object_with_methods.js.map +1 -0
- package/dist/conformance_testing/path_and_large_arrays.d.ts +6 -0
- package/dist/conformance_testing/path_and_large_arrays.js +33 -0
- package/dist/conformance_testing/path_and_large_arrays.js.map +1 -0
- package/dist/conformance_testing/sample_view.d.ts +5 -0
- package/dist/conformance_testing/sample_view.js +25 -0
- package/dist/conformance_testing/sample_view.js.map +1 -0
- package/dist/conformance_testing/simulation_variables.d.ts +5 -0
- package/dist/conformance_testing/simulation_variables.js +113 -0
- package/dist/conformance_testing/simulation_variables.js.map +1 -0
- package/dist/conformance_testing/static_variables.d.ts +2 -0
- package/dist/conformance_testing/static_variables.js +70 -0
- package/dist/conformance_testing/static_variables.js.map +1 -0
- package/dist/conformance_testing/trigger_nodes.d.ts +5 -0
- package/dist/conformance_testing/trigger_nodes.js +41 -0
- package/dist/conformance_testing/trigger_nodes.js.map +1 -0
- package/dist/conformance_testing/type_defaults.d.ts +54 -0
- package/dist/conformance_testing/type_defaults.js +96 -0
- package/dist/conformance_testing/type_defaults.js.map +1 -0
- package/package.json +12 -12
- package/src/address_space_for_conformance_testing.ts +34 -1494
- package/src/conformance_testing/access_right_variables.ts +55 -0
- package/src/conformance_testing/analog_data_items.ts +136 -0
- package/src/conformance_testing/discrete_variables.ts +131 -0
- package/src/conformance_testing/enumeration_variable.ts +27 -0
- package/src/conformance_testing/helpers.ts +226 -0
- package/src/conformance_testing/mass_variables.ts +42 -0
- package/src/conformance_testing/node_with_references.ts +130 -0
- package/src/conformance_testing/object_with_methods.ts +93 -0
- package/src/conformance_testing/path_and_large_arrays.ts +35 -0
- package/src/conformance_testing/sample_view.ts +28 -0
- package/src/conformance_testing/simulation_variables.ts +129 -0
- package/src/conformance_testing/static_variables.ts +71 -0
- package/src/conformance_testing/trigger_nodes.ts +49 -0
- package/src/conformance_testing/type_defaults.ts +60 -0
|
@@ -1,1488 +1,28 @@
|
|
|
1
|
-
// tslint:disable: no-console
|
|
2
|
-
// tslint:disable: object-literal-sort-keys
|
|
3
|
-
// tslint:disable: no-shadowed-variable
|
|
4
1
|
/**
|
|
5
2
|
* @module opcua.server.simulation
|
|
6
3
|
*
|
|
4
|
+
* Builds the conformance-testing address space by delegating to focused sub-modules.
|
|
7
5
|
*/
|
|
8
|
-
|
|
9
|
-
import path from "path";
|
|
10
|
-
import fs from "fs";
|
|
11
|
-
|
|
12
|
-
import { assert } from "node-opcua-assert";
|
|
13
|
-
import { coerceNodeId, makeNodeId, NodeIdLike } from "node-opcua-nodeid";
|
|
14
|
-
import { StatusCodes } from "node-opcua-status-code";
|
|
15
|
-
import { AddressSpace, Namespace, UAObject, UAVariable } from "node-opcua-address-space";
|
|
16
|
-
import { AccessLevelFlag, makeAccessLevelFlag } from "node-opcua-data-model";
|
|
17
|
-
import { Variant, DataType, VariantArrayType, buildVariantArray } from "node-opcua-variant";
|
|
18
|
-
import { findBuiltInType } from "node-opcua-factory";
|
|
19
|
-
import { DataValue } from "node-opcua-data-value";
|
|
20
|
-
import { emptyGuid, isValidBoolean, isValidUInt16, randomString } from "node-opcua-basic-types";
|
|
21
|
-
import * as ec from "node-opcua-basic-types";
|
|
22
|
-
import { QualifiedName, LocalizedText } from "node-opcua-data-model";
|
|
23
|
-
import { standardUnits } from "node-opcua-data-access";
|
|
6
|
+
import type { AddressSpace, UAObject } from "node-opcua-address-space";
|
|
24
7
|
import { add_eventGeneratorObject } from "node-opcua-address-space/testHelpers";
|
|
25
|
-
import { UInt64, Int64 } from "node-opcua-basic-types";
|
|
26
|
-
import { make_debugLog, make_errorLog, make_warningLog } from "node-opcua-debug";
|
|
27
|
-
|
|
28
|
-
const debugLog = make_debugLog(__filename);
|
|
29
|
-
const errorLog = make_errorLog(__filename);
|
|
30
|
-
const warningLog = make_warningLog(__filename);
|
|
31
|
-
|
|
32
|
-
interface RangeOptions {
|
|
33
|
-
low: number;
|
|
34
|
-
high: number;
|
|
35
|
-
}
|
|
36
|
-
function defaultValidator(/*value*/) {
|
|
37
|
-
return true;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
function getValidatorFuncForType(dataType: DataType): any {
|
|
41
|
-
const f = (ec as any)["isValid" + dataType];
|
|
42
|
-
return f || defaultValidator;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
function getRandomFuncForType(dataType: DataType): () => any {
|
|
46
|
-
const dataTypeName = DataType[dataType];
|
|
47
|
-
const f = (ec as any)["random" + dataTypeName];
|
|
48
|
-
|
|
49
|
-
if (f) {
|
|
50
|
-
return f;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
switch (dataTypeName) {
|
|
54
|
-
case "Variant":
|
|
55
|
-
return () => {
|
|
56
|
-
return new Variant();
|
|
57
|
-
};
|
|
58
|
-
case "QualifiedName":
|
|
59
|
-
return () => {
|
|
60
|
-
return new QualifiedName({ name: randomString() });
|
|
61
|
-
};
|
|
62
|
-
case "LocalizedText":
|
|
63
|
-
return () => {
|
|
64
|
-
return new LocalizedText({ text: randomString() });
|
|
65
|
-
};
|
|
66
|
-
case "XmlElement":
|
|
67
|
-
return () => {
|
|
68
|
-
const element = randomString();
|
|
69
|
-
const content = randomString();
|
|
70
|
-
return "<" + element + ">" + content + "</" + element + ">";
|
|
71
|
-
};
|
|
72
|
-
default:
|
|
73
|
-
// c8 ignore next
|
|
74
|
-
throw new Error("Cannot find random" + dataTypeName + "() func anywhere");
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
function _findDataType(dataTypeName: string): DataType {
|
|
79
|
-
const builtInDataTypeName = findBuiltInType(dataTypeName);
|
|
80
|
-
const dataType = (DataType as any)[builtInDataTypeName.name];
|
|
81
|
-
// c8 ignore next
|
|
82
|
-
if (!dataType) {
|
|
83
|
-
throw new Error(" dataType " + dataTypeName + " must exists");
|
|
84
|
-
}
|
|
85
|
-
return dataType;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
function validate_value_or_array(isArray: boolean, variantValue: any, validatorFunc: any) {
|
|
89
|
-
assert(typeof validatorFunc === "function");
|
|
90
|
-
let i: number;
|
|
91
|
-
let value: any;
|
|
92
|
-
if (isArray) {
|
|
93
|
-
const n = Math.min(10, variantValue.length);
|
|
94
|
-
|
|
95
|
-
for (i = 0; i < n; i++) {
|
|
96
|
-
value = variantValue[i];
|
|
97
|
-
// c8 ignore next
|
|
98
|
-
if (!validatorFunc(value)) {
|
|
99
|
-
throw new Error("default value must be valid for dataType " + variantValue + " at index " + i + " got " + value);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
} else {
|
|
103
|
-
// scalar
|
|
104
|
-
// c8 ignore next
|
|
105
|
-
if (!validatorFunc(variantValue)) {
|
|
106
|
-
throw new Error("default value must be valid for dataType " + variantValue);
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
function makeVariant(dataTypeName: string, arrayType: VariantArrayType, dimensions: number[] | null, current_value: any) {
|
|
112
|
-
const dataType = _findDataType(dataTypeName);
|
|
113
|
-
|
|
114
|
-
const validatorFunc = getValidatorFuncForType(dataType);
|
|
115
|
-
|
|
116
|
-
const isArray = arrayType === VariantArrayType.Array || arrayType === VariantArrayType.Matrix;
|
|
117
|
-
validate_value_or_array(isArray, current_value, validatorFunc);
|
|
118
|
-
|
|
119
|
-
const variant = new Variant({
|
|
120
|
-
dataType,
|
|
121
|
-
arrayType,
|
|
122
|
-
dimensions,
|
|
123
|
-
value: current_value
|
|
124
|
-
});
|
|
125
|
-
return variant;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
// eslint-disable-next-line max-params
|
|
129
|
-
function _add_variable(
|
|
130
|
-
namespace: Namespace,
|
|
131
|
-
parent: UAObject,
|
|
132
|
-
varName: string,
|
|
133
|
-
dataTypeName: string,
|
|
134
|
-
current_value: any,
|
|
135
|
-
valueRank: number,
|
|
136
|
-
arrayDimensions: number[] | null,
|
|
137
|
-
extra_name: string
|
|
138
|
-
): UAVariable {
|
|
139
|
-
assert(typeof extra_name === "string");
|
|
140
|
-
|
|
141
|
-
const arrayType = valueRank <= 0 ? VariantArrayType.Scalar : valueRank === 1 ? VariantArrayType.Array : VariantArrayType.Matrix;
|
|
142
|
-
|
|
143
|
-
const variant = makeVariant(dataTypeName, arrayType, arrayDimensions, current_value);
|
|
144
|
-
|
|
145
|
-
const name = varName + extra_name;
|
|
146
|
-
|
|
147
|
-
const nodeId = parent.nodeId.toString() + "_" + varName + extra_name;
|
|
148
|
-
|
|
149
|
-
const placeholder = {
|
|
150
|
-
variant
|
|
151
|
-
};
|
|
152
|
-
|
|
153
|
-
const variable = namespace.addVariable({
|
|
154
|
-
browseName: name,
|
|
155
|
-
componentOf: parent,
|
|
156
|
-
dataType: varName,
|
|
157
|
-
description: { locale: "en", text: name },
|
|
158
|
-
nodeId,
|
|
159
|
-
valueRank,
|
|
160
|
-
arrayDimensions,
|
|
161
|
-
accessLevel: makeAccessLevelFlag("CurrentRead | CurrentWrite"),
|
|
162
|
-
userAccessLevel: makeAccessLevelFlag("CurrentRead | CurrentWrite"),
|
|
163
|
-
value: variant
|
|
164
|
-
});
|
|
165
|
-
(variable as any)._backdoor_placeholder = placeholder;
|
|
166
|
-
return variable;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
function add_scalar_variable(
|
|
170
|
-
namespace: Namespace,
|
|
171
|
-
parent: UAObject,
|
|
172
|
-
name: string,
|
|
173
|
-
realType: any,
|
|
174
|
-
default_value: any,
|
|
175
|
-
extra_name: string
|
|
176
|
-
) {
|
|
177
|
-
assert(typeof extra_name === "string");
|
|
178
|
-
const initialValue = typeof default_value === "function" ? default_value() : default_value;
|
|
179
|
-
const variable = _add_variable(namespace, parent, name, realType, initialValue, -1, null, extra_name);
|
|
180
|
-
assert(variable.valueRank === -1);
|
|
181
|
-
// tslint:disable-next-line: no-bitwise
|
|
182
|
-
assert(variable.accessLevel === AccessLevelFlag.CurrentRead + AccessLevelFlag.CurrentWrite);
|
|
183
|
-
// tslint:disable-next-line: no-bitwise
|
|
184
|
-
assert(variable.userAccessLevel === AccessLevelFlag.CurrentRead + AccessLevelFlag.CurrentWrite);
|
|
185
|
-
assert(variable.historizing === false);
|
|
186
|
-
return variable;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
function add_array_variable(
|
|
190
|
-
namespace: Namespace,
|
|
191
|
-
parent: UAObject,
|
|
192
|
-
dataTypeName: string,
|
|
193
|
-
default_value: any,
|
|
194
|
-
realTypeName: string,
|
|
195
|
-
arrayLength: number,
|
|
196
|
-
extra_name: string
|
|
197
|
-
): void {
|
|
198
|
-
assert(typeof dataTypeName === "string");
|
|
199
|
-
assert(typeof realTypeName === "string");
|
|
200
|
-
|
|
201
|
-
// c8 ignore next
|
|
202
|
-
if (!(DataType as any)[realTypeName]) {
|
|
203
|
-
warningLog("dataTypeName", dataTypeName);
|
|
204
|
-
warningLog("realTypeName", realTypeName);
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
assert((DataType as any)[realTypeName], " expecting a valid real type");
|
|
208
|
-
arrayLength = arrayLength || 10;
|
|
209
|
-
|
|
210
|
-
const local_defaultValue = typeof default_value === "function" ? default_value() : default_value;
|
|
211
|
-
|
|
212
|
-
const current_value = buildVariantArray((DataType as any)[realTypeName], arrayLength, local_defaultValue);
|
|
213
|
-
|
|
214
|
-
const variable = _add_variable(namespace, parent, dataTypeName, realTypeName, current_value, 1, null, extra_name);
|
|
215
|
-
|
|
216
|
-
assert(variable.valueRank === 1);
|
|
217
|
-
assert(variable.accessLevel === AccessLevelFlag.CurrentRead + AccessLevelFlag.CurrentWrite);
|
|
218
|
-
assert(variable.userAccessLevel === AccessLevelFlag.CurrentRead + AccessLevelFlag.CurrentWrite);
|
|
219
|
-
assert(variable.historizing === false);
|
|
220
|
-
}
|
|
221
|
-
// eslint-disable-next-line max-params
|
|
222
|
-
function add_multi_dimensional_array_variable(
|
|
223
|
-
namespace: Namespace,
|
|
224
|
-
parent: UAObject,
|
|
225
|
-
dataTypeName: string,
|
|
226
|
-
default_value: any,
|
|
227
|
-
realTypeName: string,
|
|
228
|
-
nbRows: number,
|
|
229
|
-
nbCols: number,
|
|
230
|
-
extra_name: string
|
|
231
|
-
): void {
|
|
232
|
-
assert(typeof dataTypeName === "string");
|
|
233
|
-
assert(typeof realTypeName === "string");
|
|
234
|
-
|
|
235
|
-
// c8 ignore next
|
|
236
|
-
if (!(DataType as any)[realTypeName]) {
|
|
237
|
-
debugLog("dataTypeName", dataTypeName);
|
|
238
|
-
debugLog("realTypeName", realTypeName);
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
assert((DataType as any)[realTypeName], " expecting a valid real type");
|
|
242
|
-
|
|
243
|
-
nbRows = nbRows || 6;
|
|
244
|
-
nbCols = nbCols || 2;
|
|
245
|
-
|
|
246
|
-
const local_defaultValue = typeof default_value === "function" ? default_value() : default_value;
|
|
247
|
-
|
|
248
|
-
const current_value = buildVariantArray((DataType as any)[realTypeName], nbRows * nbCols, local_defaultValue);
|
|
249
|
-
|
|
250
|
-
const variable = _add_variable(namespace, parent, dataTypeName, realTypeName, current_value, 2, [nbRows, nbCols], extra_name);
|
|
251
|
-
|
|
252
|
-
assert(variable.valueRank === 2);
|
|
253
|
-
|
|
254
|
-
assert(variable.accessLevel === AccessLevelFlag.CurrentRead + AccessLevelFlag.CurrentWrite);
|
|
255
|
-
assert(variable.userAccessLevel === AccessLevelFlag.CurrentRead + AccessLevelFlag.CurrentWrite);
|
|
256
|
-
assert(variable.historizing === false);
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
function add_mass_variables_of_type(
|
|
260
|
-
namespace: Namespace,
|
|
261
|
-
parent: UAObject,
|
|
262
|
-
dataTypeName: string,
|
|
263
|
-
default_value: any,
|
|
264
|
-
realType: string
|
|
265
|
-
): void {
|
|
266
|
-
// Mass Mass_Boolean -> Mass_Boolean_Boolean_00 ...
|
|
267
|
-
const nodeName = "Scalar_Mass_" + dataTypeName;
|
|
268
|
-
|
|
269
|
-
const scalarMass_Type = namespace.addObject({
|
|
270
|
-
browseName: nodeName,
|
|
271
|
-
description: "This folder will contain 100 items per supported data-type.",
|
|
272
|
-
nodeId: "s=" + nodeName,
|
|
273
|
-
organizedBy: parent
|
|
274
|
-
});
|
|
275
|
-
for (let i = 0; i <= 99; i++) {
|
|
276
|
-
const extra_name = "_" + i.toString().padStart(2, "0");
|
|
277
|
-
const local_defaultValue = typeof default_value === "function" ? default_value() : default_value;
|
|
278
|
-
_add_variable(namespace, scalarMass_Type, dataTypeName, realType, local_defaultValue, -1, null, extra_name);
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
function add_mass_variables(namespace: Namespace, scalarFolder: UAObject): void {
|
|
283
|
-
const scalarMass = namespace.addFolder(scalarFolder, {
|
|
284
|
-
browseName: "Scalar_Mass",
|
|
285
|
-
description: "This folder will contain 100 items per supported data-type.",
|
|
286
|
-
nodeId: "s=Scalar_Mass"
|
|
287
|
-
});
|
|
288
|
-
|
|
289
|
-
typeAndDefaultValue.forEach((e) => {
|
|
290
|
-
const dataType = e.type;
|
|
291
|
-
const realType = e.realType || dataType;
|
|
292
|
-
add_mass_variables_of_type(namespace, scalarMass, dataType, e.defaultValue, realType);
|
|
293
|
-
});
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
const typeAndDefaultValue = [
|
|
297
|
-
{ type: "Boolean", defaultValue: false },
|
|
298
|
-
{ type: "ByteString", defaultValue: Buffer.from("OPCUA") },
|
|
299
|
-
{ type: "DateTime", defaultValue: ec.getMinOPCUADate() },
|
|
300
|
-
{ type: "Double", defaultValue: 0.0 },
|
|
301
|
-
{ type: "Float", defaultValue: 0.0 },
|
|
302
|
-
{ type: "Guid", defaultValue: emptyGuid },
|
|
303
|
-
{ type: "SByte", defaultValue: 0 },
|
|
304
|
-
{ type: "Int16", defaultValue: 0 },
|
|
305
|
-
{ type: "Int32", defaultValue: 0 },
|
|
306
|
-
{
|
|
307
|
-
type: "NodeId",
|
|
308
|
-
defaultValue() {
|
|
309
|
-
return coerceNodeId("ns=" + 3 + ";g=00000000-0000-0000-0000-000000000023");
|
|
310
|
-
}
|
|
311
|
-
},
|
|
312
|
-
{ type: "String", defaultValue: "OPCUA" },
|
|
313
|
-
{ type: "Byte", defaultValue: 0 },
|
|
314
|
-
{ type: "UInt16", defaultValue: 0 },
|
|
315
|
-
{ type: "UInt32", defaultValue: 0 },
|
|
316
|
-
{ type: "Duration", realType: "Double", defaultValue: 0.0 },
|
|
317
|
-
{ type: "Number", realType: "UInt16", defaultValue: 0 }, // Number is abstract
|
|
318
|
-
{ type: "Integer", realType: "Int64", defaultValue: 0 }, // because Integer is abstract , we choose Int32
|
|
319
|
-
{ type: "UInteger", realType: "UInt64", defaultValue: 0 },
|
|
320
|
-
{
|
|
321
|
-
type: "UtcTime",
|
|
322
|
-
realType: "DateTime",
|
|
323
|
-
defaultValue() {
|
|
324
|
-
return new Date();
|
|
325
|
-
}
|
|
326
|
-
},
|
|
327
|
-
// xx { type: "Int64", defaultValue: 0},
|
|
328
|
-
{ type: "LocaleId", realType: "String", defaultValue: "" },
|
|
329
|
-
{
|
|
330
|
-
type: "LocalizedText",
|
|
331
|
-
defaultValue() {
|
|
332
|
-
return new LocalizedText({});
|
|
333
|
-
}
|
|
334
|
-
},
|
|
335
|
-
|
|
336
|
-
{
|
|
337
|
-
type: "QualifiedName",
|
|
338
|
-
defaultValue() {
|
|
339
|
-
return new QualifiedName();
|
|
340
|
-
}
|
|
341
|
-
},
|
|
342
|
-
{ type: "UInt64", defaultValue: [0, 0] },
|
|
343
|
-
{ type: "Int64", defaultValue: [0, 0] },
|
|
344
|
-
// xx {type: "Variant", realType: "Variant", defaultValue: {} },
|
|
345
|
-
{ type: "XmlElement", defaultValue: "<string1>OPCUA</string1>" },
|
|
346
|
-
{ type: "ImageBMP", realType: "ByteString", defaultValue: null },
|
|
347
|
-
{ type: "ImageGIF", realType: "ByteString", defaultValue: null },
|
|
348
|
-
{ type: "ImageJPG", realType: "ByteString", defaultValue: null },
|
|
349
|
-
{ type: "ImagePNG", realType: "ByteString", defaultValue: null }
|
|
350
|
-
// {type: "Enumeration", realType: "UInt32" , defaultValue:0}
|
|
351
|
-
];
|
|
352
|
-
|
|
353
|
-
function add_simulation_variables(namespace: Namespace, scalarFolder: UAObject): void {
|
|
354
|
-
let values_to_change: any[] = [];
|
|
355
|
-
|
|
356
|
-
function add_simulation_variable(parent: UAObject, dataTypeName: string, defaultValue: any, realTypeName: string): UAVariable {
|
|
357
|
-
// the type of the default value
|
|
358
|
-
realTypeName = realTypeName || dataTypeName;
|
|
359
|
-
|
|
360
|
-
const dataType = _findDataType(realTypeName);
|
|
361
|
-
const randomFunc = getRandomFuncForType(dataType);
|
|
362
|
-
|
|
363
|
-
// c8 ignore next
|
|
364
|
-
if (typeof randomFunc !== "function") {
|
|
365
|
-
throw new Error("a random function must exist for basicType " + dataTypeName);
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
const variable = _add_variable(namespace, parent, dataTypeName, realTypeName, defaultValue, -1, null, "");
|
|
369
|
-
|
|
370
|
-
const value_to_change = {
|
|
371
|
-
dataType,
|
|
372
|
-
randomFunc,
|
|
373
|
-
variable
|
|
374
|
-
};
|
|
375
|
-
|
|
376
|
-
values_to_change.push(value_to_change);
|
|
377
|
-
|
|
378
|
-
return variable;
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
const simulation = namespace.addObject({
|
|
382
|
-
browseName: "Scalar_Simulation",
|
|
383
|
-
description: "This folder will contain one item per supported data-type.",
|
|
384
|
-
nodeId: "s=Scalar_Simulation",
|
|
385
|
-
organizedBy: scalarFolder
|
|
386
|
-
});
|
|
387
|
-
|
|
388
|
-
// add simulation variables
|
|
389
|
-
typeAndDefaultValue.forEach((e) => {
|
|
390
|
-
const dataType = e.type;
|
|
391
|
-
const defaultValue = typeof e.defaultValue === "function" ? e.defaultValue() : e.defaultValue;
|
|
392
|
-
const realType = e.realType || dataType;
|
|
393
|
-
add_simulation_variable(simulation, dataType, defaultValue, realType);
|
|
394
|
-
});
|
|
395
|
-
|
|
396
|
-
// add management nodes
|
|
397
|
-
let interval = 2000;
|
|
398
|
-
let enabled = true;
|
|
399
|
-
let timer: NodeJS.Timeout | undefined;
|
|
400
|
-
|
|
401
|
-
function change_randomly() {
|
|
402
|
-
values_to_change.forEach((element) => {
|
|
403
|
-
const variant = element.variable._backdoor_placeholder.variant;
|
|
404
|
-
variant.value = element.randomFunc();
|
|
405
|
-
element.variable.setValueFromSource(variant);
|
|
406
|
-
});
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
function delete_Timer() {
|
|
410
|
-
// delete previous timer if any
|
|
411
|
-
if (timer) {
|
|
412
|
-
clearInterval(timer);
|
|
413
|
-
timer = undefined;
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
function install_Timer() {
|
|
418
|
-
delete_Timer();
|
|
419
|
-
assert(!timer);
|
|
420
|
-
if (enabled) {
|
|
421
|
-
timer = setInterval(() => {
|
|
422
|
-
change_randomly();
|
|
423
|
-
}, interval);
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
function tearDown_Timer() {
|
|
428
|
-
delete_Timer();
|
|
429
|
-
values_to_change = [];
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
const intervalVariable = namespace.addVariable({
|
|
433
|
-
browseName: "Interval",
|
|
434
|
-
componentOf: simulation,
|
|
435
|
-
dataType: "UInt16",
|
|
436
|
-
description: { locale: "en", text: "The rate (in msec) of change for all Simulated items." },
|
|
437
|
-
nodeId: "s=Scalar_Simulation_Interval",
|
|
438
|
-
value: new Variant({
|
|
439
|
-
arrayType: VariantArrayType.Scalar,
|
|
440
|
-
dataType: DataType.UInt16,
|
|
441
|
-
value: interval
|
|
442
|
-
})
|
|
443
|
-
});
|
|
444
|
-
|
|
445
|
-
intervalVariable.on("value_changed", (dataValue /*,indexRange*/) => {
|
|
446
|
-
const variant = dataValue.value;
|
|
447
|
-
assert(variant instanceof Variant);
|
|
448
|
-
assert(isValidUInt16(variant.value), " value must be valid for dataType");
|
|
449
|
-
interval = variant.value;
|
|
450
|
-
install_Timer();
|
|
451
|
-
});
|
|
452
|
-
|
|
453
|
-
const enabledVariable = namespace.addVariable({
|
|
454
|
-
componentOf: simulation,
|
|
455
|
-
browseName: "Enabled",
|
|
456
|
-
description: { locale: "en", text: "Enabled" },
|
|
457
|
-
nodeId: "s=Scalar_Simulation_Enabled",
|
|
458
|
-
dataType: "Boolean",
|
|
459
|
-
value: new Variant({
|
|
460
|
-
dataType: DataType.Boolean,
|
|
461
|
-
arrayType: VariantArrayType.Scalar,
|
|
462
|
-
value: enabled
|
|
463
|
-
})
|
|
464
|
-
});
|
|
465
|
-
|
|
466
|
-
enabledVariable.on("value_changed", (dataValue /*,indexRange*/) => {
|
|
467
|
-
const variant = dataValue.value;
|
|
468
|
-
assert(variant instanceof Variant);
|
|
469
|
-
assert(isValidBoolean(variant.value), " value must be valid for dataType");
|
|
470
|
-
enabled = variant.value;
|
|
471
|
-
install_Timer();
|
|
472
|
-
});
|
|
473
|
-
install_Timer();
|
|
474
|
-
|
|
475
|
-
const addressSpace = namespace.addressSpace;
|
|
476
|
-
(addressSpace as any).registerShutdownTask(tearDown_Timer);
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
async function add_static_variables(namespace: Namespace, scalarFolder: UAObject): Promise<void> {
|
|
480
|
-
const staticScalarFolder = namespace.addObject({
|
|
481
|
-
organizedBy: scalarFolder,
|
|
482
|
-
browseName: "Scalars",
|
|
483
|
-
description: "This folder will contain one item per supported data-type.",
|
|
484
|
-
nodeId: "s=Static_Scalar"
|
|
485
|
-
});
|
|
486
|
-
|
|
487
|
-
// add statics scalar Variables
|
|
488
|
-
typeAndDefaultValue.forEach((e) => {
|
|
489
|
-
const dataType = e.type;
|
|
490
|
-
const realType = e.realType || dataType;
|
|
491
|
-
const defaultValue = typeof e.defaultValue === "function" ? e.defaultValue() : e.defaultValue;
|
|
492
|
-
add_scalar_variable(namespace, staticScalarFolder, dataType, realType, defaultValue, "");
|
|
493
|
-
});
|
|
494
|
-
|
|
495
|
-
function setImage2(imageType: any, filename: string) {
|
|
496
|
-
const fullPath = path.join(__dirname, "../data", filename);
|
|
497
|
-
const imageNode = namespace.findNode("s=Static_Scalar_Image" + imageType) as UAVariable;
|
|
498
|
-
|
|
499
|
-
const options = {
|
|
500
|
-
refreshFunc: (callback: (err: Error | null, dataValue: DataValue) => void) => {
|
|
501
|
-
fs.readFile(fullPath, (err, data) => {
|
|
502
|
-
if (err) {
|
|
503
|
-
return callback(
|
|
504
|
-
null,
|
|
505
|
-
new DataValue({
|
|
506
|
-
statusCode: StatusCodes.BadDataUnavailable,
|
|
507
|
-
value: { dataType: "ByteString", value: null }
|
|
508
|
-
})
|
|
509
|
-
);
|
|
510
|
-
}
|
|
511
|
-
assert(data instanceof Buffer);
|
|
512
|
-
callback(null, new DataValue({ value: { dataType: "ByteString", value: data } }));
|
|
513
|
-
});
|
|
514
|
-
}
|
|
515
|
-
};
|
|
516
|
-
|
|
517
|
-
imageNode.bindVariable(options, /*overwrite=*/ true);
|
|
518
|
-
}
|
|
519
|
-
setImage2;
|
|
520
|
-
|
|
521
|
-
async function setImage(imageType: string, filename: string): Promise<void> {
|
|
522
|
-
const fullPath = path.join(__dirname, "../data", filename);
|
|
523
|
-
const imageNode = namespace.findNode("s=Static_Scalar_Image" + imageType) as UAVariable;
|
|
524
|
-
try {
|
|
525
|
-
const data = await fs.promises.readFile(fullPath);
|
|
526
|
-
imageNode.setValueFromSource(new Variant({ dataType: DataType.ByteString, value: data }));
|
|
527
|
-
} catch (err) {
|
|
528
|
-
errorLog("cannot load file =", fullPath);
|
|
529
|
-
}
|
|
530
|
-
}
|
|
531
|
-
|
|
532
|
-
await setImage("BMP", "image.bmp");
|
|
533
|
-
await setImage("PNG", "tux.png");
|
|
534
|
-
await setImage("GIF", "gif-anime.gif");
|
|
535
|
-
await setImage("JPG", "tiger.jpg");
|
|
536
|
-
|
|
537
|
-
// add static Array Variables
|
|
538
|
-
const staticArraysFolders = namespace.addObject({
|
|
539
|
-
organizedBy: scalarFolder,
|
|
540
|
-
browseName: "Arrays",
|
|
541
|
-
description:
|
|
542
|
-
"Single dimension, suggested size of 10-elements per array. Unsupported types will be missing from the address-space.",
|
|
543
|
-
nodeId: "s=Static_Array"
|
|
544
|
-
});
|
|
545
|
-
// add static Array
|
|
546
|
-
typeAndDefaultValue.forEach((e) => {
|
|
547
|
-
const dataType = e.type;
|
|
548
|
-
const realType = e.realType || dataType;
|
|
549
|
-
add_array_variable(namespace, staticArraysFolders, dataType, e.defaultValue, realType, 10, "");
|
|
550
|
-
});
|
|
551
|
-
|
|
552
|
-
// add static MultiDimension Array Variables
|
|
553
|
-
const staticMultiDimensionalArrays = namespace.addObject({
|
|
554
|
-
organizedBy: scalarFolder,
|
|
555
|
-
browseName: "Multi-Dimensional Arrays",
|
|
556
|
-
description:
|
|
557
|
-
"Single dimension, suggested size of 10-elements per array. Unsupported types will be missing from the address-space.",
|
|
558
|
-
nodeId: "s=Static_MultiDimensional_Array"
|
|
559
|
-
});
|
|
560
|
-
// add static Array
|
|
561
|
-
typeAndDefaultValue.forEach((e) => {
|
|
562
|
-
const dataType = e.type;
|
|
563
|
-
const realType = e.realType || dataType;
|
|
564
|
-
add_multi_dimensional_array_variable(namespace, staticMultiDimensionalArrays, dataType, e.defaultValue, realType, 2, 3, "");
|
|
565
|
-
});
|
|
566
|
-
}
|
|
567
|
-
|
|
568
|
-
function add_access_right_variables(namespace: Namespace, parentFolder: UAObject): void {
|
|
569
|
-
const accessRight_Folder = namespace.addFolder(parentFolder, {
|
|
570
|
-
browseName: "AccessRight",
|
|
571
|
-
description: "Folder containing various nodes with different access right behavior",
|
|
572
|
-
nodeId: "s=AccessRight"
|
|
573
|
-
});
|
|
574
|
-
|
|
575
|
-
const accessLevel_All_Folder = namespace.addFolder(accessRight_Folder, {
|
|
576
|
-
browseName: "AccessLevel",
|
|
577
|
-
description: "Various node with different access right behavior",
|
|
578
|
-
nodeId: "s=AccessLevel"
|
|
579
|
-
});
|
|
580
|
-
|
|
581
|
-
let name = "AccessLevel_CurrentRead";
|
|
582
|
-
namespace.addVariable({
|
|
583
|
-
componentOf: accessLevel_All_Folder,
|
|
584
|
-
browseName: name,
|
|
585
|
-
description: { locale: "en", text: name },
|
|
586
|
-
nodeId: "s=" + name,
|
|
587
|
-
dataType: "Int32",
|
|
588
|
-
valueRank: -1,
|
|
589
|
-
|
|
590
|
-
accessLevel: makeAccessLevelFlag("CurrentRead"),
|
|
591
|
-
userAccessLevel: makeAccessLevelFlag("CurrentRead"),
|
|
592
|
-
|
|
593
|
-
value: new Variant({
|
|
594
|
-
dataType: DataType.Int32,
|
|
595
|
-
arrayType: VariantArrayType.Scalar,
|
|
596
|
-
value: 36
|
|
597
|
-
})
|
|
598
|
-
});
|
|
599
|
-
|
|
600
|
-
name = "AccessLevel_CurrentWrite";
|
|
601
|
-
namespace.addVariable({
|
|
602
|
-
componentOf: accessLevel_All_Folder,
|
|
603
|
-
browseName: name,
|
|
604
|
-
description: { locale: "en", text: name },
|
|
605
|
-
nodeId: "s=" + name,
|
|
606
|
-
dataType: "Int32",
|
|
607
|
-
valueRank: -1,
|
|
608
|
-
accessLevel: makeAccessLevelFlag("CurrentWrite"),
|
|
609
|
-
userAccessLevel: makeAccessLevelFlag("CurrentWrite"),
|
|
610
|
-
value: {}
|
|
611
|
-
});
|
|
612
|
-
|
|
613
|
-
name = "AccessLevel_CurrentRead_NotUser";
|
|
614
|
-
namespace.addVariable({
|
|
615
|
-
componentOf: accessLevel_All_Folder,
|
|
616
|
-
browseName: name,
|
|
617
|
-
description: { locale: "en", text: name },
|
|
618
|
-
nodeId: "s=" + name,
|
|
619
|
-
dataType: "Int32",
|
|
620
|
-
valueRank: -1,
|
|
621
|
-
|
|
622
|
-
accessLevel: makeAccessLevelFlag("CurrentRead"),
|
|
623
|
-
userAccessLevel: makeAccessLevelFlag(""),
|
|
624
|
-
|
|
625
|
-
value: new Variant({
|
|
626
|
-
dataType: DataType.Int32,
|
|
627
|
-
arrayType: VariantArrayType.Scalar,
|
|
628
|
-
value: 36
|
|
629
|
-
})
|
|
630
|
-
});
|
|
631
|
-
|
|
632
|
-
name = "AccessLevel_CurrentWrite_NotUser";
|
|
633
|
-
namespace.addVariable({
|
|
634
|
-
componentOf: accessLevel_All_Folder,
|
|
635
|
-
browseName: name,
|
|
636
|
-
description: { locale: "en", text: name },
|
|
637
|
-
nodeId: "s=" + name,
|
|
638
|
-
dataType: "Int32",
|
|
639
|
-
valueRank: -1,
|
|
640
|
-
|
|
641
|
-
accessLevel: makeAccessLevelFlag("CurrentWrite | CurrentRead"),
|
|
642
|
-
userAccessLevel: makeAccessLevelFlag("CurrentRead"),
|
|
643
|
-
|
|
644
|
-
value: new Variant({
|
|
645
|
-
dataType: DataType.Int32,
|
|
646
|
-
arrayType: VariantArrayType.Scalar,
|
|
647
|
-
value: 36
|
|
648
|
-
})
|
|
649
|
-
});
|
|
650
|
-
|
|
651
|
-
name = "AccessLevel_CurrentRead_NotCurrentWrite";
|
|
652
|
-
namespace.addVariable({
|
|
653
|
-
componentOf: accessLevel_All_Folder,
|
|
654
|
-
browseName: name,
|
|
655
|
-
description: { locale: "en", text: name },
|
|
656
|
-
nodeId: "s=" + name,
|
|
657
|
-
dataType: "Int32",
|
|
658
|
-
valueRank: -1,
|
|
659
|
-
|
|
660
|
-
accessLevel: makeAccessLevelFlag("CurrentRead"),
|
|
661
|
-
userAccessLevel: makeAccessLevelFlag("CurrentRead"),
|
|
662
|
-
|
|
663
|
-
value: new Variant({
|
|
664
|
-
dataType: DataType.Int32,
|
|
665
|
-
arrayType: VariantArrayType.Scalar,
|
|
666
|
-
value: 36
|
|
667
|
-
})
|
|
668
|
-
});
|
|
669
|
-
|
|
670
|
-
name = "AccessLevel_CurrentWrite_NotCurrentRead";
|
|
671
|
-
namespace.addVariable({
|
|
672
|
-
componentOf: accessLevel_All_Folder,
|
|
673
|
-
browseName: name,
|
|
674
|
-
description: { locale: "en", text: name },
|
|
675
|
-
nodeId: "s=" + name,
|
|
676
|
-
dataType: "Int32",
|
|
677
|
-
valueRank: -1,
|
|
678
|
-
|
|
679
|
-
accessLevel: makeAccessLevelFlag("CurrentWrite"),
|
|
680
|
-
userAccessLevel: makeAccessLevelFlag("CurrentWrite"),
|
|
681
|
-
|
|
682
|
-
value: new Variant({
|
|
683
|
-
dataType: DataType.Int32,
|
|
684
|
-
arrayType: VariantArrayType.Scalar,
|
|
685
|
-
value: 36
|
|
686
|
-
})
|
|
687
|
-
});
|
|
688
|
-
|
|
689
|
-
name = "AccessLevel_DeniedAll";
|
|
690
|
-
namespace.addVariable({
|
|
691
|
-
componentOf: accessLevel_All_Folder,
|
|
692
|
-
browseName: name,
|
|
693
|
-
description: { locale: "en", text: name },
|
|
694
|
-
nodeId: "s=" + name,
|
|
695
|
-
dataType: "Int32",
|
|
696
|
-
valueRank: -1,
|
|
697
|
-
|
|
698
|
-
accessLevel: makeAccessLevelFlag(""),
|
|
699
|
-
userAccessLevel: makeAccessLevelFlag(""),
|
|
700
|
-
|
|
701
|
-
value: new Variant({
|
|
702
|
-
dataType: DataType.Int32,
|
|
703
|
-
arrayType: VariantArrayType.Scalar,
|
|
704
|
-
value: 36
|
|
705
|
-
})
|
|
706
|
-
});
|
|
707
|
-
}
|
|
708
|
-
|
|
709
|
-
function add_node_with_references(namespace: Namespace, simulation_folder: UAObject): void {
|
|
710
|
-
const parent = simulation_folder;
|
|
711
|
-
const referenceFolder = namespace.addObject({
|
|
712
|
-
browseName: "References",
|
|
713
|
-
nodeId: "s=Demo.CTT.References",
|
|
714
|
-
organizedBy: parent,
|
|
715
|
-
typeDefinition: "FolderType"
|
|
716
|
-
});
|
|
717
|
-
|
|
718
|
-
(() => {
|
|
719
|
-
const has3ForwardReferences1 = namespace.addObject({
|
|
720
|
-
browseName: "Has3ForwardReferences1",
|
|
721
|
-
nodeId: "s=Demo.CTT.References.Has3ForwardReferences1",
|
|
722
|
-
componentOf: referenceFolder,
|
|
723
|
-
typeDefinition: "FolderType"
|
|
724
|
-
});
|
|
725
|
-
const referenceNode1 = namespace.addVariable({
|
|
726
|
-
browseName: "ReferenceNode1",
|
|
727
|
-
componentOf: has3ForwardReferences1,
|
|
728
|
-
dataType: "UInt32"
|
|
729
|
-
});
|
|
730
|
-
referenceNode1;
|
|
731
|
-
const referenceNode2 = namespace.addVariable({
|
|
732
|
-
browseName: "ReferenceNode2",
|
|
733
|
-
componentOf: has3ForwardReferences1,
|
|
734
|
-
dataType: "UInt32"
|
|
735
|
-
});
|
|
736
|
-
referenceNode2;
|
|
737
|
-
const referenceNode3 = namespace.addVariable({
|
|
738
|
-
browseName: "ReferenceNode3",
|
|
739
|
-
componentOf: has3ForwardReferences1,
|
|
740
|
-
dataType: "UInt32"
|
|
741
|
-
});
|
|
742
|
-
referenceNode3;
|
|
743
|
-
})();
|
|
744
|
-
|
|
745
|
-
(() => {
|
|
746
|
-
const has3ForwardReferences2 = namespace.addObject({
|
|
747
|
-
browseName: "Has3ForwardReferences2",
|
|
748
|
-
nodeId: "s=Demo.CTT.References.Has3ForwardReferences2",
|
|
749
|
-
componentOf: referenceFolder,
|
|
750
|
-
typeDefinition: "FolderType"
|
|
751
|
-
});
|
|
752
|
-
has3ForwardReferences2;
|
|
753
|
-
const baseDataVariable = namespace.addVariable({
|
|
754
|
-
browseName: "BaseDataVariable",
|
|
755
|
-
componentOf: has3ForwardReferences2,
|
|
756
|
-
dataType: "UInt32"
|
|
757
|
-
});
|
|
758
|
-
baseDataVariable;
|
|
759
|
-
namespace.addMethod(has3ForwardReferences2, {
|
|
760
|
-
browseName: "Method1"
|
|
761
|
-
});
|
|
762
|
-
namespace.addMethod(has3ForwardReferences2, {
|
|
763
|
-
browseName: "Method2"
|
|
764
|
-
});
|
|
765
|
-
namespace.addMethod(has3ForwardReferences2, {
|
|
766
|
-
browseName: "Method3"
|
|
767
|
-
});
|
|
768
|
-
namespace.addVariable({
|
|
769
|
-
browseName: "Property",
|
|
770
|
-
propertyOf: has3ForwardReferences2,
|
|
771
|
-
dataType: "UInt32"
|
|
772
|
-
});
|
|
773
|
-
})();
|
|
774
|
-
|
|
775
|
-
(() => {
|
|
776
|
-
const has3ForwardReferences3 = namespace.addObject({
|
|
777
|
-
browseName: "Has3ForwardReferences3",
|
|
778
|
-
nodeId: "s=Demo.CTT.References.Has3ForwardReferences3",
|
|
779
|
-
componentOf: referenceFolder,
|
|
780
|
-
typeDefinition: "FolderType"
|
|
781
|
-
});
|
|
782
|
-
const referencedNode1 = namespace.addFolder(has3ForwardReferences3, "ReferencedNode1");
|
|
783
|
-
const referencedNode2 = namespace.addFolder(has3ForwardReferences3, "ReferencedNode2");
|
|
784
|
-
const referencedNode3 = namespace.addFolder(has3ForwardReferences3, "ReferencedNode3");
|
|
785
|
-
|
|
786
|
-
const has3InverseReferences = namespace.addObject({
|
|
787
|
-
browseName: "Has3InverseReferences",
|
|
788
|
-
nodeId: "s=Demo.CTT.References.Has3InverseReferences",
|
|
789
|
-
componentOf: referenceFolder,
|
|
790
|
-
typeDefinition: "FolderType"
|
|
791
|
-
});
|
|
792
|
-
|
|
793
|
-
referencedNode1.addReference({
|
|
794
|
-
referenceType: "Organizes",
|
|
795
|
-
nodeId: has3InverseReferences
|
|
796
|
-
});
|
|
797
|
-
referencedNode2.addReference({
|
|
798
|
-
referenceType: "Organizes",
|
|
799
|
-
nodeId: has3InverseReferences
|
|
800
|
-
});
|
|
801
|
-
referencedNode3.addReference({
|
|
802
|
-
referenceType: "Organizes",
|
|
803
|
-
nodeId: has3InverseReferences
|
|
804
|
-
});
|
|
805
|
-
})();
|
|
806
|
-
|
|
807
|
-
(() => {
|
|
808
|
-
const has3ForwardReferences4 = namespace.addObject({
|
|
809
|
-
browseName: "Has3ForwardReferences4",
|
|
810
|
-
nodeId: "s=Demo.CTT.References.Has3ForwardReferences4",
|
|
811
|
-
componentOf: referenceFolder,
|
|
812
|
-
typeDefinition: "FolderType"
|
|
813
|
-
});
|
|
814
|
-
namespace.addVariable({
|
|
815
|
-
browseName: "ReferenceNode1",
|
|
816
|
-
propertyOf: has3ForwardReferences4,
|
|
817
|
-
dataType: "UInt32"
|
|
818
|
-
});
|
|
819
|
-
namespace.addVariable({
|
|
820
|
-
browseName: "ReferenceNode2",
|
|
821
|
-
propertyOf: has3ForwardReferences4,
|
|
822
|
-
dataType: "UInt32"
|
|
823
|
-
});
|
|
824
|
-
namespace.addVariable({
|
|
825
|
-
browseName: "ReferenceNode3",
|
|
826
|
-
propertyOf: has3ForwardReferences4,
|
|
827
|
-
dataType: "UInt32"
|
|
828
|
-
});
|
|
829
|
-
})();
|
|
830
|
-
(() => {
|
|
831
|
-
const has3ForwardReferences5 = namespace.addObject({
|
|
832
|
-
browseName: "Has3ForwardReferences5",
|
|
833
|
-
nodeId: "s=Demo.CTT.References.Has3ForwardReferences5",
|
|
834
|
-
componentOf: referenceFolder,
|
|
835
|
-
typeDefinition: "FolderType"
|
|
836
|
-
});
|
|
837
|
-
|
|
838
|
-
namespace.addFolder(has3ForwardReferences5, {
|
|
839
|
-
browseName: "ReferenceNode1"
|
|
840
|
-
});
|
|
841
|
-
namespace.addVariable({
|
|
842
|
-
browseName: "ReferenceNode2",
|
|
843
|
-
propertyOf: has3ForwardReferences5,
|
|
844
|
-
dataType: "UInt32"
|
|
845
|
-
});
|
|
846
|
-
namespace.addMethod(has3ForwardReferences5, {
|
|
847
|
-
browseName: "ReferenceNode3"
|
|
848
|
-
});
|
|
849
|
-
})();
|
|
850
|
-
|
|
851
|
-
(() => {
|
|
852
|
-
const hasInverseAndForwardReferences = namespace.addObject({
|
|
853
|
-
browseName: "HasInverseAndForwardReferences",
|
|
854
|
-
nodeId: "s=Demo.CTT.References.HasInverseAndForwardReferences",
|
|
855
|
-
componentOf: referenceFolder,
|
|
856
|
-
typeDefinition: "FolderType"
|
|
857
|
-
});
|
|
858
|
-
const nodeId = namespace.addFolder(hasInverseAndForwardReferences, {
|
|
859
|
-
browseName: "ReferenceNode1"
|
|
860
|
-
});
|
|
861
|
-
hasInverseAndForwardReferences.addReference({
|
|
862
|
-
nodeId,
|
|
863
|
-
referenceType: "AlarmGroupMember"
|
|
864
|
-
});
|
|
865
|
-
})();
|
|
866
|
-
|
|
867
|
-
const hasReferencesWithDifferentParentTypes = namespace.addObject({
|
|
868
|
-
browseName: "HasReferencesWithDifferentParentTypes",
|
|
869
|
-
nodeId: "s=Demo.CTT.References.HasReferencesWithDifferentParentTypes",
|
|
870
|
-
componentOf: referenceFolder,
|
|
871
|
-
typeDefinition: "FolderType"
|
|
872
|
-
});
|
|
873
|
-
hasReferencesWithDifferentParentTypes;
|
|
874
|
-
(() => {
|
|
875
|
-
const hasReferencesOfAReferenceTypeAndSubType = namespace.addObject({
|
|
876
|
-
browseName: "HasReferencesOfAReferenceTypeAndSubType",
|
|
877
|
-
nodeId: "s=Demo.CTT.References.HasReferencesOfAReferenceTypeAndSubType",
|
|
878
|
-
typeDefinition: "FolderType",
|
|
879
|
-
componentOf: referenceFolder
|
|
880
|
-
});
|
|
881
|
-
namespace.addVariable({
|
|
882
|
-
browseName: "ReferenceNode1",
|
|
883
|
-
propertyOf: hasReferencesOfAReferenceTypeAndSubType,
|
|
884
|
-
dataType: "UInt32"
|
|
885
|
-
});
|
|
886
|
-
namespace.addVariable({
|
|
887
|
-
browseName: "ReferenceNode2",
|
|
888
|
-
propertyOf: hasReferencesOfAReferenceTypeAndSubType,
|
|
889
|
-
dataType: "UInt32"
|
|
890
|
-
});
|
|
891
|
-
namespace.addVariable({
|
|
892
|
-
browseName: "ReferenceNode3",
|
|
893
|
-
propertyOf: hasReferencesOfAReferenceTypeAndSubType,
|
|
894
|
-
dataType: "UInt32"
|
|
895
|
-
});
|
|
896
|
-
namespace.addVariable({
|
|
897
|
-
browseName: "ReferenceNode4",
|
|
898
|
-
propertyOf: hasReferencesOfAReferenceTypeAndSubType,
|
|
899
|
-
dataType: "UInt32"
|
|
900
|
-
});
|
|
901
|
-
for (let i = 0; i < 4; i++) {
|
|
902
|
-
const a = namespace.addObject({
|
|
903
|
-
browseName: "AlarmSuppressionGroup" + i,
|
|
904
|
-
componentOf: referenceFolder
|
|
905
|
-
});
|
|
906
|
-
hasReferencesOfAReferenceTypeAndSubType.addReference({
|
|
907
|
-
nodeId: a,
|
|
908
|
-
referenceType: "HasAlarmSuppressionGroup"
|
|
909
|
-
});
|
|
910
|
-
}
|
|
911
|
-
})();
|
|
912
|
-
}
|
|
913
|
-
function add_path_10deep(namespace: Namespace, simulation_folder: UAObject) {
|
|
914
|
-
let parent = simulation_folder;
|
|
915
|
-
for (let i = 1; i <= 10; i++) {
|
|
916
|
-
const name = "Path_" + i.toString() + "Deep";
|
|
917
|
-
|
|
918
|
-
const child = namespace.addObject({
|
|
919
|
-
organizedBy: parent,
|
|
920
|
-
browseName: name,
|
|
921
|
-
description: "A folder at the top of " + i + " elements",
|
|
922
|
-
typeDefinition: "FolderType",
|
|
923
|
-
nodeId: "s=" + name
|
|
924
|
-
});
|
|
925
|
-
parent = child;
|
|
926
|
-
}
|
|
927
|
-
}
|
|
928
|
-
|
|
929
|
-
function add_very_large_array_variables(namespace: Namespace, objectsFolder: UAObject): void {
|
|
930
|
-
// add statics Array Variables
|
|
931
|
-
const scalarStaticLargeArray = namespace.addObject({
|
|
932
|
-
organizedBy: objectsFolder,
|
|
933
|
-
browseName: "Static_Scalar_Large_Array",
|
|
934
|
-
description: "Single dimension, suggested size of 100k-elements per array.",
|
|
935
|
-
nodeId: "s=Static_Scalar_Large_Array"
|
|
936
|
-
});
|
|
937
|
-
typeAndDefaultValue.forEach((e) => {
|
|
938
|
-
const dataType = e.type;
|
|
939
|
-
const realType = e.realType || dataType;
|
|
940
|
-
add_array_variable(namespace, scalarStaticLargeArray, dataType, e.defaultValue, realType, 50 * 1024, "");
|
|
941
|
-
});
|
|
942
|
-
}
|
|
943
|
-
|
|
944
|
-
// BaseDataVariableType
|
|
945
|
-
// |
|
|
946
|
-
// DataItemType
|
|
947
|
-
// ^
|
|
948
|
-
// |
|
|
949
|
-
// +----------------+---------------------+
|
|
950
|
-
// | | |
|
|
951
|
-
// ArrayItemType AnalogItemType DiscreteItemType
|
|
952
|
-
// ^
|
|
953
|
-
// |
|
|
954
|
-
// +-----------------------------+---------------------------------+
|
|
955
|
-
// | | |
|
|
956
|
-
// TwoStateDiscreteType MultiStateDiscreteType MultiStateValueDiscreteType
|
|
957
|
-
//
|
|
958
|
-
function add_analog_data_items(namespace: Namespace, parentFolder: UAObject): void {
|
|
959
|
-
function _addDataItem(localParentFolder: UAObject, dataType: DataType, initialValue: any): void {
|
|
960
|
-
const name = DataType[dataType] + "DataItem";
|
|
961
|
-
|
|
962
|
-
const nodeId = "s=" + name;
|
|
963
|
-
|
|
964
|
-
const v = namespace.addDataItem({
|
|
965
|
-
componentOf: localParentFolder,
|
|
966
|
-
nodeId,
|
|
967
|
-
browseName: name,
|
|
968
|
-
definition: "(tempA -25) + tempB",
|
|
969
|
-
dataType,
|
|
970
|
-
value: {
|
|
971
|
-
arrayType: VariantArrayType.Scalar,
|
|
972
|
-
dataType,
|
|
973
|
-
value: initialValue
|
|
974
|
-
}
|
|
975
|
-
});
|
|
976
|
-
assert(
|
|
977
|
-
v.nodeId.toString() === `ns=${namespace.index};${nodeId}`,
|
|
978
|
-
`ns=${namespace.index};${nodeId}` + " " + v.nodeId.toString()
|
|
979
|
-
);
|
|
980
|
-
}
|
|
981
|
-
function makeRange(dataType: DataType): { engineeringUnitsRange: RangeOptions; instrumentRange: RangeOptions } {
|
|
982
|
-
let engineeringUnitsRange = { low: -200, high: 200 };
|
|
983
|
-
let instrumentRange = { low: -200, high: 200 };
|
|
984
|
-
if (DataType[dataType][0] === "U" || dataType === DataType.Byte) {
|
|
985
|
-
engineeringUnitsRange = { low: 10, high: 250 };
|
|
986
|
-
instrumentRange = { low: 10, high: 250 };
|
|
987
|
-
}
|
|
988
|
-
return { engineeringUnitsRange, instrumentRange };
|
|
989
|
-
}
|
|
990
|
-
|
|
991
|
-
function _addAnalogDataItem(localParentFolder: UAObject, dataType: DataType, initialValue: any): void {
|
|
992
|
-
const { engineeringUnitsRange, instrumentRange } = makeRange(dataType);
|
|
993
|
-
assert(
|
|
994
|
-
Array.isArray(initialValue) || (initialValue >= engineeringUnitsRange.low && initialValue <= engineeringUnitsRange.high)
|
|
995
|
-
);
|
|
996
|
-
const name = (DataType as any)[dataType] + "AnalogDataItem";
|
|
997
|
-
const nodeId = "s=" + name;
|
|
998
|
-
// UAAnalogItem
|
|
999
|
-
// add a UAAnalogItem
|
|
1000
|
-
namespace.addAnalogDataItem({
|
|
1001
|
-
componentOf: localParentFolder,
|
|
1002
|
-
|
|
1003
|
-
nodeId,
|
|
1004
|
-
browseName: name,
|
|
1005
|
-
definition: "...",
|
|
1006
|
-
valuePrecision: 0.5,
|
|
1007
|
-
engineeringUnitsRange,
|
|
1008
|
-
instrumentRange,
|
|
1009
|
-
engineeringUnits: standardUnits.degree_celsius,
|
|
1010
|
-
dataType,
|
|
1011
|
-
value: {
|
|
1012
|
-
arrayType: VariantArrayType.Scalar,
|
|
1013
|
-
dataType,
|
|
1014
|
-
value: initialValue
|
|
1015
|
-
}
|
|
1016
|
-
});
|
|
1017
|
-
}
|
|
1018
|
-
|
|
1019
|
-
function _addArrayAnalogDataItem(localParentFolder: UAObject, dataType: DataType, initialValue: any) {
|
|
1020
|
-
const name = (DataType as any)[dataType] + "ArrayAnalogDataItem";
|
|
1021
|
-
const nodeId = "s=" + name;
|
|
1022
|
-
// UAAnalogItem
|
|
1023
|
-
const { engineeringUnitsRange, instrumentRange } = makeRange(dataType);
|
|
1024
|
-
// add a UAAnalogItem
|
|
1025
|
-
namespace.addAnalogDataItem({
|
|
1026
|
-
componentOf: localParentFolder,
|
|
1027
|
-
|
|
1028
|
-
nodeId,
|
|
1029
|
-
browseName: name,
|
|
1030
|
-
definition: "(tempA -25) + tempB",
|
|
1031
|
-
valuePrecision: 0.5,
|
|
1032
|
-
engineeringUnitsRange,
|
|
1033
|
-
instrumentRange,
|
|
1034
|
-
engineeringUnits: standardUnits.degree_celsius,
|
|
1035
|
-
dataType,
|
|
1036
|
-
value: {
|
|
1037
|
-
arrayType: VariantArrayType.Array,
|
|
1038
|
-
dataType,
|
|
1039
|
-
value: [initialValue, initialValue, initialValue, initialValue, initialValue]
|
|
1040
|
-
}
|
|
1041
|
-
});
|
|
1042
|
-
}
|
|
1043
|
-
|
|
1044
|
-
// add statics Array Variables
|
|
1045
|
-
const analogItemFolder = namespace.addObject({
|
|
1046
|
-
organizedBy: parentFolder,
|
|
1047
|
-
browseName: "Simulation_AnalogDataItem",
|
|
1048
|
-
typeDefinition: "FolderType",
|
|
1049
|
-
nodeId: "s=Simulation_AnalogDataItem"
|
|
1050
|
-
});
|
|
1051
|
-
|
|
1052
|
-
const name = "DoubleAnalogDataItemWithEU";
|
|
1053
|
-
const nodeId = "s=" + name;
|
|
1054
|
-
|
|
1055
|
-
const { engineeringUnitsRange, instrumentRange } = makeRange(DataType.Double);
|
|
1056
|
-
namespace.addAnalogDataItem({
|
|
1057
|
-
componentOf: analogItemFolder,
|
|
1058
|
-
nodeId,
|
|
1059
|
-
browseName: name,
|
|
1060
|
-
definition: "(tempA -25) + tempB",
|
|
1061
|
-
valuePrecision: 0.5,
|
|
1062
|
-
engineeringUnitsRange,
|
|
1063
|
-
instrumentRange,
|
|
1064
|
-
engineeringUnits: standardUnits.degree_celsius,
|
|
1065
|
-
dataType: DataType.Double,
|
|
1066
|
-
|
|
1067
|
-
value: {
|
|
1068
|
-
dataType: DataType.Double,
|
|
1069
|
-
value: 19.5
|
|
1070
|
-
}
|
|
1071
|
-
});
|
|
1072
|
-
|
|
1073
|
-
const data = [
|
|
1074
|
-
{ dataType: DataType.Double, value: 3.14 },
|
|
1075
|
-
{ dataType: DataType.Float, value: 3.14 },
|
|
1076
|
-
{ dataType: DataType.Int16, value: -10 },
|
|
1077
|
-
{ dataType: DataType.UInt16, value: 10 },
|
|
1078
|
-
{ dataType: DataType.Int32, value: -100 },
|
|
1079
|
-
{ dataType: DataType.UInt32, value: 100 },
|
|
1080
|
-
{ dataType: DataType.Int64, value: [0, 0] },
|
|
1081
|
-
{ dataType: DataType.UInt64, value: [0, 0] },
|
|
1082
|
-
{ dataType: DataType.Byte, value: 65 },
|
|
1083
|
-
{ dataType: DataType.SByte, value: -23 }
|
|
1084
|
-
];
|
|
1085
|
-
|
|
1086
|
-
data.forEach((e) => {
|
|
1087
|
-
_addAnalogDataItem(analogItemFolder, e.dataType, e.value);
|
|
1088
|
-
});
|
|
1089
|
-
|
|
1090
|
-
data.forEach((e) => {
|
|
1091
|
-
_addDataItem(analogItemFolder, e.dataType, e.value);
|
|
1092
|
-
});
|
|
1093
|
-
_addDataItem(analogItemFolder, DataType.String, "some string");
|
|
1094
|
-
_addDataItem(analogItemFolder, DataType.DateTime, new Date());
|
|
1095
|
-
|
|
1096
|
-
data.forEach((e) => {
|
|
1097
|
-
_addArrayAnalogDataItem(analogItemFolder, e.dataType, e.value);
|
|
1098
|
-
});
|
|
1099
|
-
}
|
|
1100
|
-
|
|
1101
|
-
function getDADiscreteTypeFolder(namespace: Namespace, parentFolder: UAObject): UAObject {
|
|
1102
|
-
const name = "Simulation_DA_DiscreteType";
|
|
1103
|
-
const nodeId = "s=Simulation_DA_DiscreteType";
|
|
1104
|
-
|
|
1105
|
-
let node = parentFolder.getFolderElementByName(name);
|
|
1106
|
-
if (!node) {
|
|
1107
|
-
node = namespace.addObject({
|
|
1108
|
-
organizedBy: parentFolder,
|
|
1109
|
-
typeDefinition: "FolderType",
|
|
1110
|
-
browseName: name,
|
|
1111
|
-
nodeId
|
|
1112
|
-
});
|
|
1113
|
-
}
|
|
1114
|
-
return node as UAObject;
|
|
1115
|
-
}
|
|
1116
|
-
|
|
1117
|
-
function add_two_state_discrete_variables(namespace: Namespace, parentFolder: UAObject): void {
|
|
1118
|
-
const DADiscreteTypeFolder = getDADiscreteTypeFolder(namespace, parentFolder);
|
|
1119
|
-
|
|
1120
|
-
const twoStateDiscrete001 = namespace.addTwoStateDiscrete({
|
|
1121
|
-
organizedBy: DADiscreteTypeFolder,
|
|
1122
|
-
nodeId: "s=TwoStateDiscrete001",
|
|
1123
|
-
browseName: "TwoStateDiscrete001",
|
|
1124
|
-
trueState: "Enabled",
|
|
1125
|
-
falseState: "Disabled"
|
|
1126
|
-
});
|
|
1127
|
-
|
|
1128
|
-
const twoStateDiscrete002 = namespace.addTwoStateDiscrete({
|
|
1129
|
-
organizedBy: DADiscreteTypeFolder,
|
|
1130
|
-
nodeId: "s=TwoStateDiscrete002",
|
|
1131
|
-
browseName: "TwoStateDiscrete002",
|
|
1132
|
-
trueState: "On",
|
|
1133
|
-
falseState: "Off",
|
|
1134
|
-
optionals: ["TransitionTime", "EffectiveDisplayName"]
|
|
1135
|
-
});
|
|
1136
|
-
|
|
1137
|
-
const twoStateDiscrete003 = namespace.addTwoStateDiscrete({
|
|
1138
|
-
browseName: "twoStateDiscrete003",
|
|
1139
|
-
nodeId: "s=TwoStateDiscrete003",
|
|
1140
|
-
optionals: ["TransitionTime"],
|
|
1141
|
-
isTrueSubStateOf: twoStateDiscrete002
|
|
1142
|
-
});
|
|
1143
|
-
|
|
1144
|
-
const twoStateDiscrete004 = namespace.addTwoStateDiscrete({
|
|
1145
|
-
organizedBy: DADiscreteTypeFolder,
|
|
1146
|
-
nodeId: "s=TwoStateDiscrete004",
|
|
1147
|
-
browseName: "TwoStateDiscrete004",
|
|
1148
|
-
trueState: "InProgress",
|
|
1149
|
-
falseState: "Stopped"
|
|
1150
|
-
});
|
|
1151
|
-
|
|
1152
|
-
const twoStateDiscrete005 = namespace.addTwoStateDiscrete({
|
|
1153
|
-
organizedBy: DADiscreteTypeFolder,
|
|
1154
|
-
nodeId: "s=TwoStateDiscrete005",
|
|
1155
|
-
browseName: "TwoStateDiscrete005",
|
|
1156
|
-
trueState: "InProgress",
|
|
1157
|
-
falseState: "Stopped"
|
|
1158
|
-
});
|
|
1159
|
-
|
|
1160
|
-
twoStateDiscrete001.setValueFromSource({ dataType: "Boolean", value: false });
|
|
1161
|
-
twoStateDiscrete002.setValueFromSource({ dataType: "Boolean", value: false });
|
|
1162
|
-
twoStateDiscrete003.setValueFromSource({ dataType: "Boolean", value: false });
|
|
1163
|
-
twoStateDiscrete004.setValueFromSource({ dataType: "Boolean", value: false });
|
|
1164
|
-
twoStateDiscrete005.setValueFromSource({ dataType: "Boolean", value: false });
|
|
1165
|
-
}
|
|
1166
|
-
|
|
1167
|
-
function add_multi_state_discrete_variable(namespace: Namespace, parentFolder: UAObject): void {
|
|
1168
|
-
const DADiscreteTypeFolder = getDADiscreteTypeFolder(namespace, parentFolder);
|
|
1169
|
-
|
|
1170
|
-
// MultiStateDiscrete001
|
|
1171
|
-
const multiStateDiscrete001 = namespace.addMultiStateDiscrete({
|
|
1172
|
-
organizedBy: DADiscreteTypeFolder,
|
|
1173
|
-
nodeId: "s=MultiStateDiscrete001",
|
|
1174
|
-
browseName: "MultiStateDiscrete001",
|
|
1175
|
-
enumStrings: ["Red", "Orange", "Green"],
|
|
1176
|
-
value: 1 // Orange
|
|
1177
|
-
});
|
|
1178
|
-
multiStateDiscrete001;
|
|
1179
|
-
|
|
1180
|
-
// MultiStateDiscrete002
|
|
1181
|
-
namespace.addMultiStateDiscrete({
|
|
1182
|
-
organizedBy: DADiscreteTypeFolder,
|
|
1183
|
-
nodeId: "s=MultiStateDiscrete002",
|
|
1184
|
-
browseName: "MultiStateDiscrete002",
|
|
1185
|
-
enumStrings: ["Red", "Orange", "Green"],
|
|
1186
|
-
value: 1 // Orange
|
|
1187
|
-
});
|
|
1188
|
-
|
|
1189
|
-
// MultiStateDiscrete002
|
|
1190
|
-
namespace.addMultiStateDiscrete({
|
|
1191
|
-
organizedBy: DADiscreteTypeFolder,
|
|
1192
|
-
nodeId: "s=MultiStateDiscrete003",
|
|
1193
|
-
browseName: "MultiStateDiscrete003",
|
|
1194
|
-
enumStrings: ["Red", "Orange", "Green"],
|
|
1195
|
-
value: 1 // Orange
|
|
1196
|
-
});
|
|
1197
|
-
|
|
1198
|
-
// MultiStateDiscrete002
|
|
1199
|
-
namespace.addMultiStateDiscrete({
|
|
1200
|
-
organizedBy: DADiscreteTypeFolder,
|
|
1201
|
-
nodeId: "s=MultiStateDiscrete004",
|
|
1202
|
-
browseName: "MultiStateDiscrete004",
|
|
1203
|
-
enumStrings: ["Red", "Orange", "Green"],
|
|
1204
|
-
value: 1 // Orange
|
|
1205
|
-
});
|
|
1206
|
-
|
|
1207
|
-
// MultiStateDiscrete002
|
|
1208
|
-
namespace.addMultiStateDiscrete({
|
|
1209
|
-
organizedBy: DADiscreteTypeFolder,
|
|
1210
|
-
nodeId: "s=MultiStateDiscrete005",
|
|
1211
|
-
browseName: "MultiStateDiscrete005",
|
|
1212
|
-
enumStrings: ["Red", "Orange", "Green"],
|
|
1213
|
-
value: 1 // Orange
|
|
1214
|
-
});
|
|
1215
|
-
}
|
|
1216
|
-
|
|
1217
|
-
function add_multi_state_value_discrete_variables(namespaceDemo: Namespace, parentFolder: UAObject): void {
|
|
1218
|
-
const multistateValueDiscreteTypeFolder = namespaceDemo.addObject({
|
|
1219
|
-
organizedBy: parentFolder,
|
|
1220
|
-
typeDefinition: "FolderType",
|
|
1221
|
-
browseName: "Simulation_DA_MultiStateValueDiscreteType",
|
|
1222
|
-
nodeId: "s=Simulation_DA_MultiStateValueDiscreteType"
|
|
1223
|
-
});
|
|
1224
|
-
|
|
1225
|
-
function _add_multi_state_variable(
|
|
1226
|
-
parentFolder: UAObject,
|
|
1227
|
-
dataType: string,
|
|
1228
|
-
value: number | UInt64 | Int64,
|
|
1229
|
-
enumValues: Record<string, number>
|
|
1230
|
-
) {
|
|
1231
|
-
const name = dataType + "MultiStateValueDiscrete";
|
|
1232
|
-
const nodeId = "s=" + name;
|
|
1233
|
-
|
|
1234
|
-
namespaceDemo.addMultiStateValueDiscrete({
|
|
1235
|
-
organizedBy: parentFolder,
|
|
1236
|
-
browseName: name,
|
|
1237
|
-
nodeId,
|
|
1238
|
-
dataType,
|
|
1239
|
-
enumValues,
|
|
1240
|
-
value: 0x0000 // Zero
|
|
1241
|
-
});
|
|
1242
|
-
}
|
|
1243
|
-
const enumValueUnsigned = { Zero: 0x00, One: 0x01, Two: 0x02, Three: 0x03, Four: 0x04, Five: 0x05, Six: 0x06, Seven: 0x07 };
|
|
1244
|
-
const enumValueSigned = { MinusOne: -1, MinusTwo: -2, MinusThree: -3, ...enumValueUnsigned };
|
|
1245
|
-
|
|
1246
|
-
const data = [
|
|
1247
|
-
{ dataType: "Int16", value: -1, enumValue: enumValueSigned },
|
|
1248
|
-
{ dataType: "UInt16", value: 10, enumValue: enumValueUnsigned },
|
|
1249
|
-
{ dataType: "Int32", value: -1, enumValue: enumValueSigned },
|
|
1250
|
-
{ dataType: "UInt32", value: 100, enumValue: enumValueUnsigned },
|
|
1251
|
-
{ dataType: "Int64", value: [0, 0], enumValue: enumValueUnsigned },
|
|
1252
|
-
{ dataType: "UInt64", value: [0, 0], enumValue: enumValueSigned },
|
|
1253
|
-
{ dataType: "Byte", value: 1, enumValue: enumValueUnsigned },
|
|
1254
|
-
{ dataType: "SByte", value: -1, enumValue: enumValueSigned }
|
|
1255
|
-
];
|
|
1256
|
-
data.forEach((e) => {
|
|
1257
|
-
_add_multi_state_variable(multistateValueDiscreteTypeFolder, e.dataType, e.value, e.enumValue);
|
|
1258
|
-
});
|
|
1259
|
-
}
|
|
1260
|
-
|
|
1261
|
-
function add_ObjectWithMethod(namespace: Namespace, parentFolder: UAObject) {
|
|
1262
|
-
const myObject = namespace.addObject({
|
|
1263
|
-
nodeId: "s=ObjectWithMethods",
|
|
1264
|
-
organizedBy: parentFolder,
|
|
1265
|
-
browseName: "ObjectWithMethods"
|
|
1266
|
-
});
|
|
1267
|
-
|
|
1268
|
-
const methodNoArgs = namespace.addMethod(myObject, {
|
|
1269
|
-
browseName: "MethodNoArgs",
|
|
1270
|
-
nodeId: "s=MethodNoArgs"
|
|
1271
|
-
// xx inputArguments: [],
|
|
1272
|
-
// xx outputArguments: []
|
|
1273
|
-
});
|
|
1274
|
-
assert(
|
|
1275
|
-
makeNodeId("MethodNoArgs", namespace.index)
|
|
1276
|
-
.toString()
|
|
1277
|
-
.match(/s=MethodNoArgs/)
|
|
1278
|
-
);
|
|
1279
|
-
assert(methodNoArgs.nodeId.toString().match(/s=MethodNoArgs/));
|
|
1280
|
-
|
|
1281
|
-
methodNoArgs.bindMethod((inputArguments, context, callback) => {
|
|
1282
|
-
const callMethodResult = {
|
|
1283
|
-
statusCode: StatusCodes.Good,
|
|
1284
|
-
outputArguments: []
|
|
1285
|
-
};
|
|
1286
|
-
callback(null, callMethodResult);
|
|
1287
|
-
});
|
|
1288
|
-
|
|
1289
|
-
const methodIO = namespace.addMethod(myObject, {
|
|
1290
|
-
/// xx modellingRule: "Mandatory",
|
|
1291
|
-
|
|
1292
|
-
browseName: "MethodIO",
|
|
1293
|
-
nodeId: makeNodeId("MethodIO", namespace.index),
|
|
1294
|
-
|
|
1295
|
-
inputArguments: [
|
|
1296
|
-
{
|
|
1297
|
-
name: "ShutterLag",
|
|
1298
|
-
description: { text: "specifies the number of seconds to wait before the picture is taken " },
|
|
1299
|
-
dataType: DataType.UInt32
|
|
1300
|
-
}
|
|
1301
|
-
],
|
|
1302
|
-
|
|
1303
|
-
outputArguments: [
|
|
1304
|
-
{
|
|
1305
|
-
name: "Result",
|
|
1306
|
-
description: { text: "the result" },
|
|
1307
|
-
dataType: "Int32"
|
|
1308
|
-
}
|
|
1309
|
-
]
|
|
1310
|
-
});
|
|
1311
|
-
methodIO.bindMethod((inputArguments, context, callback) => {
|
|
1312
|
-
const callMethodResult = {
|
|
1313
|
-
statusCode: StatusCodes.Good,
|
|
1314
|
-
outputArguments: [
|
|
1315
|
-
{
|
|
1316
|
-
dataType: DataType.Int32,
|
|
1317
|
-
value: 42
|
|
1318
|
-
}
|
|
1319
|
-
]
|
|
1320
|
-
};
|
|
1321
|
-
callback(null, callMethodResult);
|
|
1322
|
-
});
|
|
1323
|
-
|
|
1324
|
-
const methodI = namespace.addMethod(myObject, {
|
|
1325
|
-
/// xx modellingRule: "Mandatory",
|
|
1326
|
-
|
|
1327
|
-
browseName: "MethodI",
|
|
1328
|
-
nodeId: "s=MethodI",
|
|
1329
|
-
|
|
1330
|
-
inputArguments: [
|
|
1331
|
-
{
|
|
1332
|
-
name: "ShutterLag",
|
|
1333
|
-
description: { text: "specifies the number of seconds to wait before the picture is taken " },
|
|
1334
|
-
dataType: DataType.UInt32
|
|
1335
|
-
}
|
|
1336
|
-
]
|
|
1337
|
-
// xx outputArguments: []
|
|
1338
|
-
});
|
|
1339
|
-
methodI.bindMethod((inputArguments, context, callback) => {
|
|
1340
|
-
const callMethodResult = {
|
|
1341
|
-
statusCode: StatusCodes.Good,
|
|
1342
|
-
outputArguments: []
|
|
1343
|
-
};
|
|
1344
|
-
callback(null, callMethodResult);
|
|
1345
|
-
});
|
|
1346
|
-
|
|
1347
|
-
const methodO = namespace.addMethod(myObject, {
|
|
1348
|
-
/// xx modellingRule: "Mandatory",
|
|
1349
|
-
|
|
1350
|
-
browseName: "MethodO",
|
|
1351
|
-
nodeId: "s=MethodO",
|
|
1352
|
-
|
|
1353
|
-
// xx inputArguments: [],
|
|
1354
|
-
outputArguments: [
|
|
1355
|
-
{
|
|
1356
|
-
name: "Result",
|
|
1357
|
-
description: { text: "the result" },
|
|
1358
|
-
dataType: "Int32"
|
|
1359
|
-
}
|
|
1360
|
-
]
|
|
1361
|
-
});
|
|
1362
|
-
methodO.bindMethod((inputArguments, context, callback) => {
|
|
1363
|
-
const callMethodResult = {
|
|
1364
|
-
statusCode: StatusCodes.Good,
|
|
1365
|
-
outputArguments: [
|
|
1366
|
-
{
|
|
1367
|
-
dataType: DataType.Int32,
|
|
1368
|
-
value: 42
|
|
1369
|
-
}
|
|
1370
|
-
]
|
|
1371
|
-
};
|
|
1372
|
-
callback(null, callMethodResult);
|
|
1373
|
-
});
|
|
1374
|
-
}
|
|
1375
|
-
|
|
1376
|
-
function add_enumeration_variable(namespaceDemo: Namespace, parentFolder: UAObject): void {
|
|
1377
|
-
const addressSpace = namespaceDemo.addressSpace;
|
|
1378
|
-
|
|
1379
|
-
const myEnumType = namespaceDemo.addEnumerationType({
|
|
1380
|
-
browseName: "SimulationEnumerationType",
|
|
1381
|
-
enumeration: [
|
|
1382
|
-
{ value: 1, displayName: "RUNNING" },
|
|
1383
|
-
{ value: 2, displayName: "BLOCKED" },
|
|
1384
|
-
{ value: 3, displayName: "IDLE" },
|
|
1385
|
-
{ value: 4, displayName: "UNDER MAINTENANCE" }
|
|
1386
|
-
]
|
|
1387
|
-
});
|
|
1388
|
-
|
|
1389
|
-
// now instantiate a variable that have this type.
|
|
1390
|
-
const e = namespaceDemo.addVariable({
|
|
1391
|
-
organizedBy: parentFolder,
|
|
1392
|
-
propertyOf: (addressSpace.rootFolder.objects.server as any).vendorServerInfos,
|
|
1393
|
-
dataType: myEnumType,
|
|
1394
|
-
browseName: "RunningState"
|
|
1395
|
-
});
|
|
1396
|
-
e.writeEnumValue("RUNNING");
|
|
1397
|
-
}
|
|
1398
|
-
|
|
1399
|
-
function add_trigger_nodes(namespace: Namespace, parentFolder: UAObject): void {
|
|
1400
|
-
const addressSpace = namespace.addressSpace;
|
|
1401
|
-
|
|
1402
|
-
const myEvtType =
|
|
1403
|
-
namespace.findObjectType("MyEventType") ||
|
|
1404
|
-
namespace.addEventType({
|
|
1405
|
-
browseName: "MyEventType",
|
|
1406
|
-
subtypeOf: "BaseEventType" // should be implicit
|
|
1407
|
-
});
|
|
1408
|
-
|
|
1409
|
-
// add 2 nodes that generate an event when ever they are written to.
|
|
1410
|
-
function _add_trigger_node(parent: UAObject, browseName: string, nodeId: NodeIdLike) {
|
|
1411
|
-
const triggerNode = namespace.addVariable({
|
|
1412
|
-
browseName,
|
|
1413
|
-
nodeId,
|
|
1414
|
-
eventSourceOf: parent,
|
|
1415
|
-
dataType: "Double",
|
|
1416
|
-
typeDefinition: makeNodeId(68)
|
|
1417
|
-
});
|
|
1418
|
-
|
|
1419
|
-
let value = 100.0;
|
|
1420
|
-
const getFunc = () => {
|
|
1421
|
-
return new Variant({
|
|
1422
|
-
dataType: DataType.Double,
|
|
1423
|
-
value
|
|
1424
|
-
});
|
|
1425
|
-
};
|
|
1426
|
-
const setFunc = (variant: Variant) => {
|
|
1427
|
-
value = variant.value;
|
|
1428
|
-
const server = addressSpace.rootFolder.objects.server;
|
|
1429
|
-
server.raiseEvent(myEvtType, {
|
|
1430
|
-
message: {
|
|
1431
|
-
dataType: DataType.LocalizedText,
|
|
1432
|
-
value: { text: "Hello World" }
|
|
1433
|
-
},
|
|
1434
|
-
severity: {
|
|
1435
|
-
dataType: DataType.UInt32,
|
|
1436
|
-
value: 32
|
|
1437
|
-
}
|
|
1438
|
-
});
|
|
1439
|
-
};
|
|
1440
|
-
|
|
1441
|
-
const options = {
|
|
1442
|
-
get: getFunc,
|
|
1443
|
-
set: setFunc
|
|
1444
|
-
};
|
|
1445
|
-
triggerNode.bindVariable(options);
|
|
1446
|
-
}
|
|
1447
|
-
|
|
1448
|
-
const sampleTriggerNode = namespace.addObject({
|
|
1449
|
-
browseName: "SampleTriggerNode",
|
|
1450
|
-
eventNotifier: 0x1,
|
|
1451
|
-
organizedBy: parentFolder
|
|
1452
|
-
});
|
|
1453
|
-
const triggerNode01 = _add_trigger_node(sampleTriggerNode, "TriggerNode01", "s=TriggerNode01");
|
|
1454
|
-
triggerNode01;
|
|
1455
|
-
|
|
1456
|
-
const triggerNode02 = _add_trigger_node(sampleTriggerNode, "TriggerNode02", "s=TriggerNode02");
|
|
1457
|
-
triggerNode02;
|
|
1458
|
-
}
|
|
1459
|
-
|
|
1460
|
-
function add_sampleView(namespace: Namespace): void {
|
|
1461
|
-
const addressSpace = namespace.addressSpace;
|
|
1462
|
-
|
|
1463
|
-
const view1 = namespace.addView({
|
|
1464
|
-
organizedBy: addressSpace.rootFolder.views,
|
|
1465
|
-
browseName: "SampleView",
|
|
1466
|
-
nodeId: "s=SampleView"
|
|
1467
|
-
});
|
|
1468
|
-
view1.addReference({
|
|
1469
|
-
nodeId: "i=2256", // Server_Status
|
|
1470
|
-
referenceType: "Organizes"
|
|
1471
|
-
});
|
|
1472
|
-
view1.addReference({
|
|
1473
|
-
nodeId: "i=11715", // Server_Namespaces
|
|
1474
|
-
referenceType: "Organizes"
|
|
1475
|
-
});
|
|
1476
|
-
|
|
1477
|
-
const view2 = namespace.addView({
|
|
1478
|
-
organizedBy: addressSpace.rootFolder.views,
|
|
1479
|
-
browseName: "OtherSampleView",
|
|
1480
|
-
nodeId: "s=OtherSampleView"
|
|
1481
|
-
});
|
|
1482
|
-
view2;
|
|
1483
|
-
}
|
|
1484
8
|
|
|
1485
|
-
|
|
9
|
+
import { addAccessRightVariables } from "./conformance_testing/access_right_variables";
|
|
10
|
+
import { addAnalogDataItems } from "./conformance_testing/analog_data_items";
|
|
11
|
+
import { addMultiStateDiscreteVariable, addMultiStateValueDiscreteVariables, addTwoStateDiscreteVariables } from "./conformance_testing/discrete_variables";
|
|
12
|
+
import { addEnumerationVariable } from "./conformance_testing/enumeration_variable";
|
|
13
|
+
import { addMassVariables } from "./conformance_testing/mass_variables";
|
|
14
|
+
import { addNodeWithReferences } from "./conformance_testing/node_with_references";
|
|
15
|
+
import { addObjectWithMethod } from "./conformance_testing/object_with_methods";
|
|
16
|
+
import { addPath10Deep, addVeryLargeArrayVariables } from "./conformance_testing/path_and_large_arrays";
|
|
17
|
+
import { addSampleView } from "./conformance_testing/sample_view";
|
|
18
|
+
import { addSimulationVariables } from "./conformance_testing/simulation_variables";
|
|
19
|
+
import { addStaticVariables } from "./conformance_testing/static_variables";
|
|
20
|
+
import { addTriggerNodes } from "./conformance_testing/trigger_nodes";
|
|
21
|
+
|
|
22
|
+
export async function build_address_space_for_conformance_testing(
|
|
23
|
+
addressSpace: AddressSpace,
|
|
24
|
+
options?: { mass_variable?: boolean; mass_variables?: boolean }
|
|
25
|
+
): Promise<void> {
|
|
1486
26
|
const namespace = addressSpace.registerNamespace("urn://node-opcua-simulator");
|
|
1487
27
|
|
|
1488
28
|
options = options || {};
|
|
@@ -1495,7 +35,7 @@ export async function build_address_space_for_conformance_testing(addressSpace:
|
|
|
1495
35
|
nodeId: "s=SimulationFolder"
|
|
1496
36
|
});
|
|
1497
37
|
|
|
1498
|
-
|
|
38
|
+
addAccessRightVariables(namespace, simulationFolder);
|
|
1499
39
|
|
|
1500
40
|
const staticVariablesFolder = namespace.addFolder(simulationFolder, {
|
|
1501
41
|
browseName: "Static"
|
|
@@ -1506,37 +46,37 @@ export async function build_address_space_for_conformance_testing(addressSpace:
|
|
|
1506
46
|
});
|
|
1507
47
|
|
|
1508
48
|
// Scalars/Array/MultiDim array of all sorts
|
|
1509
|
-
await
|
|
49
|
+
await addStaticVariables(namespace, allProfileFolder);
|
|
1510
50
|
|
|
1511
51
|
if (options.mass_variables) {
|
|
1512
|
-
|
|
52
|
+
addMassVariables(namespace, allProfileFolder);
|
|
1513
53
|
}
|
|
1514
|
-
|
|
54
|
+
addAnalogDataItems(namespace, allProfileFolder);
|
|
1515
55
|
|
|
1516
56
|
const dynamicVariablesFolder = namespace.addFolder(simulationFolder, {
|
|
1517
57
|
browseName: "Dynamic"
|
|
1518
58
|
});
|
|
1519
|
-
|
|
59
|
+
addSimulationVariables(namespace, dynamicVariablesFolder);
|
|
1520
60
|
|
|
1521
|
-
|
|
61
|
+
addVeryLargeArrayVariables(namespace, staticVariablesFolder);
|
|
1522
62
|
|
|
1523
|
-
|
|
63
|
+
addPath10Deep(namespace, simulationFolder);
|
|
1524
64
|
|
|
1525
|
-
|
|
65
|
+
addNodeWithReferences(namespace, simulationFolder);
|
|
1526
66
|
|
|
1527
|
-
|
|
67
|
+
addObjectWithMethod(namespace, simulationFolder);
|
|
1528
68
|
|
|
1529
69
|
add_eventGeneratorObject(namespace, simulationFolder);
|
|
1530
70
|
|
|
1531
|
-
|
|
71
|
+
addSampleView(namespace);
|
|
1532
72
|
|
|
1533
|
-
|
|
73
|
+
addEnumerationVariable(namespace, simulationFolder);
|
|
1534
74
|
|
|
1535
|
-
|
|
75
|
+
addMultiStateValueDiscreteVariables(namespace, simulationFolder);
|
|
1536
76
|
|
|
1537
|
-
|
|
77
|
+
addTwoStateDiscreteVariables(namespace, simulationFolder);
|
|
1538
78
|
|
|
1539
|
-
|
|
79
|
+
addMultiStateDiscreteVariable(namespace, simulationFolder);
|
|
1540
80
|
|
|
1541
|
-
|
|
81
|
+
addTriggerNodes(namespace, simulationFolder);
|
|
1542
82
|
}
|