node-opcua-address-space-for-conformance-testing 2.167.0 → 2.168.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/dist/address_space_for_conformance_testing.d.ts +6 -2
  2. package/dist/address_space_for_conformance_testing.js +27 -1306
  3. package/dist/address_space_for_conformance_testing.js.map +1 -1
  4. package/dist/conformance_testing/access_right_variables.d.ts +5 -0
  5. package/dist/conformance_testing/access_right_variables.js +45 -0
  6. package/dist/conformance_testing/access_right_variables.js.map +1 -0
  7. package/dist/conformance_testing/analog_data_items.d.ts +5 -0
  8. package/dist/conformance_testing/analog_data_items.js +117 -0
  9. package/dist/conformance_testing/analog_data_items.js.map +1 -0
  10. package/dist/conformance_testing/discrete_variables.d.ts +4 -0
  11. package/dist/conformance_testing/discrete_variables.js +111 -0
  12. package/dist/conformance_testing/discrete_variables.js.map +1 -0
  13. package/dist/conformance_testing/enumeration_variable.d.ts +5 -0
  14. package/dist/conformance_testing/enumeration_variable.js +24 -0
  15. package/dist/conformance_testing/enumeration_variable.js.map +1 -0
  16. package/dist/conformance_testing/helpers.d.ts +13 -0
  17. package/dist/conformance_testing/helpers.js +204 -0
  18. package/dist/conformance_testing/helpers.js.map +1 -0
  19. package/dist/conformance_testing/mass_variables.d.ts +5 -0
  20. package/dist/conformance_testing/mass_variables.js +31 -0
  21. package/dist/conformance_testing/mass_variables.js.map +1 -0
  22. package/dist/conformance_testing/node_with_references.d.ts +5 -0
  23. package/dist/conformance_testing/node_with_references.js +119 -0
  24. package/dist/conformance_testing/node_with_references.js.map +1 -0
  25. package/dist/conformance_testing/object_with_methods.d.ts +5 -0
  26. package/dist/conformance_testing/object_with_methods.js +85 -0
  27. package/dist/conformance_testing/object_with_methods.js.map +1 -0
  28. package/dist/conformance_testing/path_and_large_arrays.d.ts +6 -0
  29. package/dist/conformance_testing/path_and_large_arrays.js +33 -0
  30. package/dist/conformance_testing/path_and_large_arrays.js.map +1 -0
  31. package/dist/conformance_testing/sample_view.d.ts +5 -0
  32. package/dist/conformance_testing/sample_view.js +25 -0
  33. package/dist/conformance_testing/sample_view.js.map +1 -0
  34. package/dist/conformance_testing/simulation_variables.d.ts +5 -0
  35. package/dist/conformance_testing/simulation_variables.js +113 -0
  36. package/dist/conformance_testing/simulation_variables.js.map +1 -0
  37. package/dist/conformance_testing/static_variables.d.ts +2 -0
  38. package/dist/conformance_testing/static_variables.js +70 -0
  39. package/dist/conformance_testing/static_variables.js.map +1 -0
  40. package/dist/conformance_testing/trigger_nodes.d.ts +5 -0
  41. package/dist/conformance_testing/trigger_nodes.js +41 -0
  42. package/dist/conformance_testing/trigger_nodes.js.map +1 -0
  43. package/dist/conformance_testing/type_defaults.d.ts +54 -0
  44. package/dist/conformance_testing/type_defaults.js +96 -0
  45. package/dist/conformance_testing/type_defaults.js.map +1 -0
  46. package/package.json +12 -12
  47. package/src/address_space_for_conformance_testing.ts +34 -1494
  48. package/src/conformance_testing/access_right_variables.ts +55 -0
  49. package/src/conformance_testing/analog_data_items.ts +136 -0
  50. package/src/conformance_testing/discrete_variables.ts +131 -0
  51. package/src/conformance_testing/enumeration_variable.ts +27 -0
  52. package/src/conformance_testing/helpers.ts +226 -0
  53. package/src/conformance_testing/mass_variables.ts +42 -0
  54. package/src/conformance_testing/node_with_references.ts +130 -0
  55. package/src/conformance_testing/object_with_methods.ts +93 -0
  56. package/src/conformance_testing/path_and_large_arrays.ts +35 -0
  57. package/src/conformance_testing/sample_view.ts +28 -0
  58. package/src/conformance_testing/simulation_variables.ts +129 -0
  59. package/src/conformance_testing/static_variables.ts +71 -0
  60. package/src/conformance_testing/trigger_nodes.ts +49 -0
  61. 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
- export async function build_address_space_for_conformance_testing(addressSpace: AddressSpace, options: any): Promise<void> {
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
- add_access_right_variables(namespace, simulationFolder);
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 add_static_variables(namespace, allProfileFolder);
49
+ await addStaticVariables(namespace, allProfileFolder);
1510
50
 
1511
51
  if (options.mass_variables) {
1512
- add_mass_variables(namespace, allProfileFolder);
52
+ addMassVariables(namespace, allProfileFolder);
1513
53
  }
1514
- add_analog_data_items(namespace, allProfileFolder);
54
+ addAnalogDataItems(namespace, allProfileFolder);
1515
55
 
1516
56
  const dynamicVariablesFolder = namespace.addFolder(simulationFolder, {
1517
57
  browseName: "Dynamic"
1518
58
  });
1519
- add_simulation_variables(namespace, dynamicVariablesFolder);
59
+ addSimulationVariables(namespace, dynamicVariablesFolder);
1520
60
 
1521
- add_very_large_array_variables(namespace, staticVariablesFolder);
61
+ addVeryLargeArrayVariables(namespace, staticVariablesFolder);
1522
62
 
1523
- add_path_10deep(namespace, simulationFolder);
63
+ addPath10Deep(namespace, simulationFolder);
1524
64
 
1525
- add_node_with_references(namespace, simulationFolder);
65
+ addNodeWithReferences(namespace, simulationFolder);
1526
66
 
1527
- add_ObjectWithMethod(namespace, simulationFolder);
67
+ addObjectWithMethod(namespace, simulationFolder);
1528
68
 
1529
69
  add_eventGeneratorObject(namespace, simulationFolder);
1530
70
 
1531
- add_sampleView(namespace);
71
+ addSampleView(namespace);
1532
72
 
1533
- add_enumeration_variable(namespace, simulationFolder);
73
+ addEnumerationVariable(namespace, simulationFolder);
1534
74
 
1535
- add_multi_state_value_discrete_variables(namespace, simulationFolder);
75
+ addMultiStateValueDiscreteVariables(namespace, simulationFolder);
1536
76
 
1537
- add_two_state_discrete_variables(namespace, simulationFolder);
77
+ addTwoStateDiscreteVariables(namespace, simulationFolder);
1538
78
 
1539
- add_multi_state_discrete_variable(namespace, simulationFolder);
79
+ addMultiStateDiscreteVariable(namespace, simulationFolder);
1540
80
 
1541
- add_trigger_nodes(namespace, simulationFolder);
81
+ addTriggerNodes(namespace, simulationFolder);
1542
82
  }