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.
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
@@ -0,0 +1,130 @@
1
+ /**
2
+ * Reference test nodes for CTT conformance testing.
3
+ */
4
+ import type { Namespace, UAObject } from "node-opcua-address-space";
5
+
6
+ export function addNodeWithReferences(namespace: Namespace, simulation_folder: UAObject): void {
7
+ const parent = simulation_folder;
8
+ const referenceFolder = namespace.addObject({
9
+ browseName: "References",
10
+ nodeId: "s=Demo.CTT.References",
11
+ organizedBy: parent,
12
+ typeDefinition: "FolderType"
13
+ });
14
+
15
+ // --- Has3ForwardReferences1: 3 variable components ---
16
+ {
17
+ const has3ForwardReferences1 = namespace.addObject({
18
+ browseName: "Has3ForwardReferences1",
19
+ nodeId: "s=Demo.CTT.References.Has3ForwardReferences1",
20
+ componentOf: referenceFolder,
21
+ typeDefinition: "FolderType"
22
+ });
23
+ namespace.addVariable({ browseName: "ReferenceNode1", componentOf: has3ForwardReferences1, dataType: "UInt32" });
24
+ namespace.addVariable({ browseName: "ReferenceNode2", componentOf: has3ForwardReferences1, dataType: "UInt32" });
25
+ namespace.addVariable({ browseName: "ReferenceNode3", componentOf: has3ForwardReferences1, dataType: "UInt32" });
26
+ }
27
+
28
+ // --- Has3ForwardReferences2: variable + 3 methods + property ---
29
+ {
30
+ const has3ForwardReferences2 = namespace.addObject({
31
+ browseName: "Has3ForwardReferences2",
32
+ nodeId: "s=Demo.CTT.References.Has3ForwardReferences2",
33
+ componentOf: referenceFolder,
34
+ typeDefinition: "FolderType"
35
+ });
36
+ namespace.addVariable({ browseName: "BaseDataVariable", componentOf: has3ForwardReferences2, dataType: "UInt32" });
37
+ namespace.addMethod(has3ForwardReferences2, { browseName: "Method1" });
38
+ namespace.addMethod(has3ForwardReferences2, { browseName: "Method2" });
39
+ namespace.addMethod(has3ForwardReferences2, { browseName: "Method3" });
40
+ namespace.addVariable({ browseName: "Property", propertyOf: has3ForwardReferences2, dataType: "UInt32" });
41
+ }
42
+
43
+ // --- Has3ForwardReferences3 + Has3InverseReferences ---
44
+ {
45
+ const has3ForwardReferences3 = namespace.addObject({
46
+ browseName: "Has3ForwardReferences3",
47
+ nodeId: "s=Demo.CTT.References.Has3ForwardReferences3",
48
+ componentOf: referenceFolder,
49
+ typeDefinition: "FolderType"
50
+ });
51
+ const referencedNode1 = namespace.addFolder(has3ForwardReferences3, "ReferencedNode1");
52
+ const referencedNode2 = namespace.addFolder(has3ForwardReferences3, "ReferencedNode2");
53
+ const referencedNode3 = namespace.addFolder(has3ForwardReferences3, "ReferencedNode3");
54
+
55
+ const has3InverseReferences = namespace.addObject({
56
+ browseName: "Has3InverseReferences",
57
+ nodeId: "s=Demo.CTT.References.Has3InverseReferences",
58
+ componentOf: referenceFolder,
59
+ typeDefinition: "FolderType"
60
+ });
61
+
62
+ referencedNode1.addReference({ referenceType: "Organizes", nodeId: has3InverseReferences });
63
+ referencedNode2.addReference({ referenceType: "Organizes", nodeId: has3InverseReferences });
64
+ referencedNode3.addReference({ referenceType: "Organizes", nodeId: has3InverseReferences });
65
+ }
66
+
67
+ // --- Has3ForwardReferences4: 3 properties ---
68
+ {
69
+ const has3ForwardReferences4 = namespace.addObject({
70
+ browseName: "Has3ForwardReferences4",
71
+ nodeId: "s=Demo.CTT.References.Has3ForwardReferences4",
72
+ componentOf: referenceFolder,
73
+ typeDefinition: "FolderType"
74
+ });
75
+ namespace.addVariable({ browseName: "ReferenceNode1", propertyOf: has3ForwardReferences4, dataType: "UInt32" });
76
+ namespace.addVariable({ browseName: "ReferenceNode2", propertyOf: has3ForwardReferences4, dataType: "UInt32" });
77
+ namespace.addVariable({ browseName: "ReferenceNode3", propertyOf: has3ForwardReferences4, dataType: "UInt32" });
78
+ }
79
+
80
+ // --- Has3ForwardReferences5: folder + property + method ---
81
+ {
82
+ const has3ForwardReferences5 = namespace.addObject({
83
+ browseName: "Has3ForwardReferences5",
84
+ nodeId: "s=Demo.CTT.References.Has3ForwardReferences5",
85
+ componentOf: referenceFolder,
86
+ typeDefinition: "FolderType"
87
+ });
88
+ namespace.addFolder(has3ForwardReferences5, { browseName: "ReferenceNode1" });
89
+ namespace.addVariable({ browseName: "ReferenceNode2", propertyOf: has3ForwardReferences5, dataType: "UInt32" });
90
+ namespace.addMethod(has3ForwardReferences5, { browseName: "ReferenceNode3" });
91
+ }
92
+
93
+ // --- HasInverseAndForwardReferences ---
94
+ {
95
+ const hasInverseAndForwardReferences = namespace.addObject({
96
+ browseName: "HasInverseAndForwardReferences",
97
+ nodeId: "s=Demo.CTT.References.HasInverseAndForwardReferences",
98
+ componentOf: referenceFolder,
99
+ typeDefinition: "FolderType"
100
+ });
101
+ const nodeId = namespace.addFolder(hasInverseAndForwardReferences, { browseName: "ReferenceNode1" });
102
+ hasInverseAndForwardReferences.addReference({ nodeId, referenceType: "AlarmGroupMember" });
103
+ }
104
+
105
+ // --- HasReferencesWithDifferentParentTypes ---
106
+ namespace.addObject({
107
+ browseName: "HasReferencesWithDifferentParentTypes",
108
+ nodeId: "s=Demo.CTT.References.HasReferencesWithDifferentParentTypes",
109
+ componentOf: referenceFolder,
110
+ typeDefinition: "FolderType"
111
+ });
112
+
113
+ // --- HasReferencesOfAReferenceTypeAndSubType ---
114
+ {
115
+ const hasReferencesOfAReferenceTypeAndSubType = namespace.addObject({
116
+ browseName: "HasReferencesOfAReferenceTypeAndSubType",
117
+ nodeId: "s=Demo.CTT.References.HasReferencesOfAReferenceTypeAndSubType",
118
+ typeDefinition: "FolderType",
119
+ componentOf: referenceFolder
120
+ });
121
+ namespace.addVariable({ browseName: "ReferenceNode1", propertyOf: hasReferencesOfAReferenceTypeAndSubType, dataType: "UInt32" });
122
+ namespace.addVariable({ browseName: "ReferenceNode2", propertyOf: hasReferencesOfAReferenceTypeAndSubType, dataType: "UInt32" });
123
+ namespace.addVariable({ browseName: "ReferenceNode3", propertyOf: hasReferencesOfAReferenceTypeAndSubType, dataType: "UInt32" });
124
+ namespace.addVariable({ browseName: "ReferenceNode4", propertyOf: hasReferencesOfAReferenceTypeAndSubType, dataType: "UInt32" });
125
+ for (let i = 0; i < 4; i++) {
126
+ const a = namespace.addObject({ browseName: `AlarmSuppressionGroup${i}`, componentOf: referenceFolder });
127
+ hasReferencesOfAReferenceTypeAndSubType.addReference({ nodeId: a, referenceType: "HasAlarmSuppressionGroup" });
128
+ }
129
+ }
130
+ }
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Object with methods for conformance testing (MethodNoArgs, MethodIO, MethodI, MethodO).
3
+ */
4
+ import type { Namespace, UAObject } from "node-opcua-address-space";
5
+ import { assert } from "node-opcua-assert";
6
+ import { makeNodeId } from "node-opcua-nodeid";
7
+ import { StatusCodes } from "node-opcua-status-code";
8
+ import { DataType } from "node-opcua-variant";
9
+
10
+ export function addObjectWithMethod(namespace: Namespace, parentFolder: UAObject) {
11
+ const myObject = namespace.addObject({
12
+ nodeId: "s=ObjectWithMethods",
13
+ organizedBy: parentFolder,
14
+ browseName: "ObjectWithMethods"
15
+ });
16
+
17
+ // MethodNoArgs
18
+ const methodNoArgs = namespace.addMethod(myObject, {
19
+ browseName: "MethodNoArgs",
20
+ nodeId: "s=MethodNoArgs"
21
+ });
22
+ assert(
23
+ makeNodeId("MethodNoArgs", namespace.index)
24
+ .toString()
25
+ .match(/s=MethodNoArgs/)
26
+ );
27
+ assert(methodNoArgs.nodeId.toString().match(/s=MethodNoArgs/));
28
+
29
+ methodNoArgs.bindMethod((_inputArguments, _context, callback) => {
30
+ callback(null, { statusCode: StatusCodes.Good, outputArguments: [] });
31
+ });
32
+
33
+ // MethodIO (input + output)
34
+ const methodIO = namespace.addMethod(myObject, {
35
+ browseName: "MethodIO",
36
+ nodeId: makeNodeId("MethodIO", namespace.index),
37
+ inputArguments: [
38
+ {
39
+ name: "ShutterLag",
40
+ description: { text: "specifies the number of seconds to wait before the picture is taken " },
41
+ dataType: DataType.UInt32
42
+ }
43
+ ],
44
+ outputArguments: [
45
+ {
46
+ name: "Result",
47
+ description: { text: "the result" },
48
+ dataType: "Int32"
49
+ }
50
+ ]
51
+ });
52
+ methodIO.bindMethod((_inputArguments, _context, callback) => {
53
+ callback(null, {
54
+ statusCode: StatusCodes.Good,
55
+ outputArguments: [{ dataType: DataType.Int32, value: 42 }]
56
+ });
57
+ });
58
+
59
+ // MethodI (input only)
60
+ const methodI = namespace.addMethod(myObject, {
61
+ browseName: "MethodI",
62
+ nodeId: "s=MethodI",
63
+ inputArguments: [
64
+ {
65
+ name: "ShutterLag",
66
+ description: { text: "specifies the number of seconds to wait before the picture is taken " },
67
+ dataType: DataType.UInt32
68
+ }
69
+ ]
70
+ });
71
+ methodI.bindMethod((_inputArguments, _context, callback) => {
72
+ callback(null, { statusCode: StatusCodes.Good, outputArguments: [] });
73
+ });
74
+
75
+ // MethodO (output only)
76
+ const methodO = namespace.addMethod(myObject, {
77
+ browseName: "MethodO",
78
+ nodeId: "s=MethodO",
79
+ outputArguments: [
80
+ {
81
+ name: "Result",
82
+ description: { text: "the result" },
83
+ dataType: "Int32"
84
+ }
85
+ ]
86
+ });
87
+ methodO.bindMethod((_inputArguments, _context, callback) => {
88
+ callback(null, {
89
+ statusCode: StatusCodes.Good,
90
+ outputArguments: [{ dataType: DataType.Int32, value: 42 }]
91
+ });
92
+ });
93
+ }
@@ -0,0 +1,35 @@
1
+ /**
2
+ * 10-deep path and very large array variables for conformance testing.
3
+ */
4
+ import type { Namespace, UAObject } from "node-opcua-address-space";
5
+
6
+ import { addArrayVariable } from "./helpers";
7
+ import { typeAndDefaultValue } from "./type_defaults";
8
+
9
+ export function addPath10Deep(namespace: Namespace, simulation_folder: UAObject) {
10
+ let parent = simulation_folder;
11
+ for (let i = 1; i <= 10; i++) {
12
+ const name = `Path_${i.toString()}Deep`;
13
+ const child = namespace.addObject({
14
+ organizedBy: parent,
15
+ browseName: name,
16
+ description: `A folder at the top of ${i} elements`,
17
+ typeDefinition: "FolderType",
18
+ nodeId: `s=${name}`
19
+ });
20
+ parent = child;
21
+ }
22
+ }
23
+
24
+ export function addVeryLargeArrayVariables(namespace: Namespace, objectsFolder: UAObject): void {
25
+ const scalarStaticLargeArray = namespace.addObject({
26
+ organizedBy: objectsFolder,
27
+ browseName: "Static_Scalar_Large_Array",
28
+ description: "Single dimension, suggested size of 100k-elements per array.",
29
+ nodeId: "s=Static_Scalar_Large_Array"
30
+ });
31
+ for (const e of typeAndDefaultValue) {
32
+ const realType = e.realType || e.type;
33
+ addArrayVariable(namespace, scalarStaticLargeArray, e.type, e.defaultValue, realType, 50 * 1024, "");
34
+ }
35
+ }
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Sample views for conformance testing.
3
+ */
4
+ import type { Namespace } from "node-opcua-address-space";
5
+
6
+ export function addSampleView(namespace: Namespace): void {
7
+ const addressSpace = namespace.addressSpace;
8
+
9
+ const view1 = namespace.addView({
10
+ organizedBy: addressSpace.rootFolder.views,
11
+ browseName: "SampleView",
12
+ nodeId: "s=SampleView"
13
+ });
14
+ view1.addReference({
15
+ nodeId: "i=2256", // Server_Status
16
+ referenceType: "Organizes"
17
+ });
18
+ view1.addReference({
19
+ nodeId: "i=11715", // Server_Namespaces
20
+ referenceType: "Organizes"
21
+ });
22
+
23
+ namespace.addView({
24
+ organizedBy: addressSpace.rootFolder.views,
25
+ browseName: "OtherSampleView",
26
+ nodeId: "s=OtherSampleView"
27
+ });
28
+ }
@@ -0,0 +1,129 @@
1
+ /**
2
+ * Simulation (dynamic) variables that change randomly on a timer.
3
+ */
4
+ import type { Namespace, UAObject, UAVariable } from "node-opcua-address-space";
5
+ import { assert } from "node-opcua-assert";
6
+ import { isValidBoolean, isValidUInt16 } from "node-opcua-basic-types";
7
+ import { DataType, Variant, VariantArrayType } from "node-opcua-variant";
8
+
9
+ import { addVariable, findDataType, getRandomFuncForType } from "./helpers";
10
+ import { typeAndDefaultValue } from "./type_defaults";
11
+
12
+ export function addSimulationVariables(namespace: Namespace, scalarFolder: UAObject): void {
13
+ let values_to_change: { dataType: DataType; randomFunc: () => unknown; variable: UAVariable }[] = [];
14
+
15
+ function add_simulation_variable(parent: UAObject, dataTypeName: string, defaultValue: unknown, realTypeName: string): UAVariable {
16
+ realTypeName = realTypeName || dataTypeName;
17
+ const dataType = findDataType(realTypeName);
18
+ const randomFunc = getRandomFuncForType(dataType);
19
+
20
+ // c8 ignore next
21
+ if (typeof randomFunc !== "function") {
22
+ throw new Error(`a random function must exist for basicType ${dataTypeName}`);
23
+ }
24
+
25
+ const variable = addVariable(namespace, parent, dataTypeName, realTypeName, defaultValue, -1, null, "");
26
+ values_to_change.push({ dataType, randomFunc, variable });
27
+ return variable;
28
+ }
29
+
30
+ const simulation = namespace.addObject({
31
+ browseName: "Scalar_Simulation",
32
+ description: "This folder will contain one item per supported data-type.",
33
+ nodeId: "s=Scalar_Simulation",
34
+ organizedBy: scalarFolder
35
+ });
36
+
37
+ for (const e of typeAndDefaultValue) {
38
+ const dataType = e.type;
39
+ const defaultValue = typeof e.defaultValue === "function" ? e.defaultValue() : e.defaultValue;
40
+ const realType = e.realType || dataType;
41
+ add_simulation_variable(simulation, dataType, defaultValue, realType);
42
+ }
43
+
44
+ // Management nodes
45
+ let interval = 2000;
46
+ let enabled = true;
47
+ let timer: NodeJS.Timeout | undefined;
48
+
49
+ function change_randomly() {
50
+ for (const element of values_to_change) {
51
+ const variant = (element.variable as unknown as Record<string, { variant: Variant }>)._backdoor_placeholder.variant;
52
+ variant.value = element.randomFunc();
53
+ element.variable.setValueFromSource(variant);
54
+ }
55
+ }
56
+
57
+ function delete_Timer() {
58
+ if (timer) {
59
+ try {
60
+ clearInterval(timer);
61
+ } catch (_err) {
62
+ /* c8 ignore next */
63
+ // the leak detector may throw if the timer handle is already disposed
64
+ }
65
+ timer = undefined;
66
+ }
67
+ }
68
+
69
+ function install_Timer() {
70
+ delete_Timer();
71
+ assert(!timer);
72
+ if (enabled) {
73
+ timer = setInterval(() => {
74
+ change_randomly();
75
+ }, interval);
76
+ }
77
+ }
78
+
79
+ function tearDown_Timer() {
80
+ delete_Timer();
81
+ values_to_change = [];
82
+ }
83
+
84
+ const intervalVariable = namespace.addVariable({
85
+ browseName: "Interval",
86
+ componentOf: simulation,
87
+ dataType: "UInt16",
88
+ description: { locale: "en", text: "The rate (in msec) of change for all Simulated items." },
89
+ nodeId: "s=Scalar_Simulation_Interval",
90
+ value: new Variant({
91
+ arrayType: VariantArrayType.Scalar,
92
+ dataType: DataType.UInt16,
93
+ value: interval
94
+ })
95
+ });
96
+
97
+ intervalVariable.on("value_changed", (dataValue /*,indexRange*/) => {
98
+ const variant = dataValue.value;
99
+ assert(variant instanceof Variant);
100
+ assert(isValidUInt16(variant.value), " value must be valid for dataType");
101
+ interval = variant.value;
102
+ install_Timer();
103
+ });
104
+
105
+ const enabledVariable = namespace.addVariable({
106
+ componentOf: simulation,
107
+ browseName: "Enabled",
108
+ description: { locale: "en", text: "Enabled" },
109
+ nodeId: "s=Scalar_Simulation_Enabled",
110
+ dataType: "Boolean",
111
+ value: new Variant({
112
+ dataType: DataType.Boolean,
113
+ arrayType: VariantArrayType.Scalar,
114
+ value: enabled
115
+ })
116
+ });
117
+
118
+ enabledVariable.on("value_changed", (dataValue /*,indexRange*/) => {
119
+ const variant = dataValue.value;
120
+ assert(variant instanceof Variant);
121
+ assert(isValidBoolean(variant.value), " value must be valid for dataType");
122
+ enabled = variant.value;
123
+ install_Timer();
124
+ });
125
+ install_Timer();
126
+
127
+ const addressSpace = namespace.addressSpace;
128
+ addressSpace.registerShutdownTask(tearDown_Timer);
129
+ }
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Static scalar, array, and multi-dimensional array variables + image loading.
3
+ */
4
+ import fs from "node:fs";
5
+ import path from "node:path";
6
+ import type { Namespace, UAObject, UAVariable } from "node-opcua-address-space";
7
+ import { make_errorLog } from "node-opcua-debug";
8
+ import { DataType, Variant } from "node-opcua-variant";
9
+
10
+ import { addArrayVariable, addMultiDimensionalArrayVariable, addScalarVariable } from "./helpers";
11
+ import { typeAndDefaultValue } from "./type_defaults";
12
+
13
+ const errorLog = make_errorLog(__filename);
14
+
15
+ export async function addStaticVariables(namespace: Namespace, scalarFolder: UAObject): Promise<void> {
16
+ const staticScalarFolder = namespace.addObject({
17
+ organizedBy: scalarFolder,
18
+ browseName: "Scalars",
19
+ description: "This folder will contain one item per supported data-type.",
20
+ nodeId: "s=Static_Scalar"
21
+ });
22
+
23
+ // Scalar variables
24
+ for (const e of typeAndDefaultValue) {
25
+ const dataType = e.type;
26
+ const realType = e.realType || dataType;
27
+ const defaultValue = typeof e.defaultValue === "function" ? e.defaultValue() : e.defaultValue;
28
+ addScalarVariable(namespace, staticScalarFolder, dataType, realType, defaultValue, "");
29
+ }
30
+
31
+ // Load images
32
+ async function setImage(imageType: string, filename: string): Promise<void> {
33
+ const fullPath = path.join(__dirname, "../../data", filename);
34
+ const imageNode = namespace.findNode(`s=Static_Scalar_Image${imageType}`) as UAVariable;
35
+ try {
36
+ const data = await fs.promises.readFile(fullPath);
37
+ imageNode.setValueFromSource(new Variant({ dataType: DataType.ByteString, value: data }));
38
+ } catch (_err) {
39
+ errorLog("cannot load file =", fullPath);
40
+ }
41
+ }
42
+
43
+ await setImage("BMP", "image.bmp");
44
+ await setImage("PNG", "tux.png");
45
+ await setImage("GIF", "gif-anime.gif");
46
+ await setImage("JPG", "tiger.jpg");
47
+
48
+ // Array variables
49
+ const staticArraysFolders = namespace.addObject({
50
+ organizedBy: scalarFolder,
51
+ browseName: "Arrays",
52
+ description: "Single dimension, suggested size of 10-elements per array. Unsupported types will be missing from the address-space.",
53
+ nodeId: "s=Static_Array"
54
+ });
55
+ for (const e of typeAndDefaultValue) {
56
+ const realType = e.realType || e.type;
57
+ addArrayVariable(namespace, staticArraysFolders, e.type, e.defaultValue, realType, 10, "");
58
+ }
59
+
60
+ // Multi-dimensional array variables
61
+ const staticMultiDimensionalArrays = namespace.addObject({
62
+ organizedBy: scalarFolder,
63
+ browseName: "Multi-Dimensional Arrays",
64
+ description: "Single dimension, suggested size of 10-elements per array. Unsupported types will be missing from the address-space.",
65
+ nodeId: "s=Static_MultiDimensional_Array"
66
+ });
67
+ for (const e of typeAndDefaultValue) {
68
+ const realType = e.realType || e.type;
69
+ addMultiDimensionalArrayVariable(namespace, staticMultiDimensionalArrays, e.type, e.defaultValue, realType, 2, 3, "");
70
+ }
71
+ }
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Trigger nodes that raise events on write.
3
+ */
4
+ import type { Namespace, UAObject } from "node-opcua-address-space";
5
+ import type { NodeIdLike } from "node-opcua-nodeid";
6
+ import { makeNodeId } from "node-opcua-nodeid";
7
+ import { DataType, Variant } from "node-opcua-variant";
8
+
9
+ export function addTriggerNodes(namespace: Namespace, parentFolder: UAObject): void {
10
+ const addressSpace = namespace.addressSpace;
11
+
12
+ const myEvtType =
13
+ namespace.findObjectType("MyEventType") ||
14
+ namespace.addEventType({
15
+ browseName: "MyEventType",
16
+ subtypeOf: "BaseEventType"
17
+ });
18
+
19
+ function _add_trigger_node(parent: UAObject, browseName: string, nodeId: NodeIdLike) {
20
+ const triggerNode = namespace.addVariable({
21
+ browseName,
22
+ nodeId,
23
+ eventSourceOf: parent,
24
+ dataType: "Double",
25
+ typeDefinition: makeNodeId(68)
26
+ });
27
+
28
+ let value = 100.0;
29
+ const getFunc = () => new Variant({ dataType: DataType.Double, value });
30
+ const setFunc = (variant: Variant) => {
31
+ value = variant.value;
32
+ const server = addressSpace.rootFolder.objects.server;
33
+ server.raiseEvent(myEvtType, {
34
+ message: { dataType: DataType.LocalizedText, value: { text: "Hello World" } },
35
+ severity: { dataType: DataType.UInt32, value: 32 }
36
+ });
37
+ };
38
+
39
+ triggerNode.bindVariable({ get: getFunc, set: setFunc });
40
+ }
41
+
42
+ const sampleTriggerNode = namespace.addObject({
43
+ browseName: "SampleTriggerNode",
44
+ eventNotifier: 0x1,
45
+ organizedBy: parentFolder
46
+ });
47
+ _add_trigger_node(sampleTriggerNode, "TriggerNode01", "s=TriggerNode01");
48
+ _add_trigger_node(sampleTriggerNode, "TriggerNode02", "s=TriggerNode02");
49
+ }
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Default type/value table shared by static, simulation, mass, and large array builders.
3
+ */
4
+ import { emptyGuid } from "node-opcua-basic-types";
5
+ import * as ec from "node-opcua-basic-types";
6
+ import { LocalizedText, QualifiedName } from "node-opcua-data-model";
7
+ import { coerceNodeId } from "node-opcua-nodeid";
8
+
9
+ export const typeAndDefaultValue = [
10
+ { type: "Boolean", defaultValue: false },
11
+ { type: "ByteString", defaultValue: Buffer.from("OPCUA") },
12
+ { type: "DateTime", defaultValue: ec.getMinOPCUADate() },
13
+ { type: "Double", defaultValue: 0.0 },
14
+ { type: "Float", defaultValue: 0.0 },
15
+ { type: "Guid", defaultValue: emptyGuid },
16
+ { type: "SByte", defaultValue: 0 },
17
+ { type: "Int16", defaultValue: 0 },
18
+ { type: "Int32", defaultValue: 0 },
19
+ {
20
+ type: "NodeId",
21
+ defaultValue() {
22
+ return coerceNodeId(`ns=${3};g=00000000-0000-0000-0000-000000000023`);
23
+ }
24
+ },
25
+ { type: "String", defaultValue: "OPCUA" },
26
+ { type: "Byte", defaultValue: 0 },
27
+ { type: "UInt16", defaultValue: 0 },
28
+ { type: "UInt32", defaultValue: 0 },
29
+ { type: "Duration", realType: "Double", defaultValue: 0.0 },
30
+ { type: "Number", realType: "UInt16", defaultValue: 0 }, // Number is abstract
31
+ { type: "Integer", realType: "Int64", defaultValue: 0 }, // because Integer is abstract, we choose Int64
32
+ { type: "UInteger", realType: "UInt64", defaultValue: 0 },
33
+ {
34
+ type: "UtcTime",
35
+ realType: "DateTime",
36
+ defaultValue() {
37
+ return new Date();
38
+ }
39
+ },
40
+ { type: "LocaleId", realType: "String", defaultValue: "" },
41
+ {
42
+ type: "LocalizedText",
43
+ defaultValue() {
44
+ return new LocalizedText({});
45
+ }
46
+ },
47
+ {
48
+ type: "QualifiedName",
49
+ defaultValue() {
50
+ return new QualifiedName();
51
+ }
52
+ },
53
+ { type: "UInt64", defaultValue: [0, 0] },
54
+ { type: "Int64", defaultValue: [0, 0] },
55
+ { type: "XmlElement", defaultValue: "<string1>OPCUA</string1>" },
56
+ { type: "ImageBMP", realType: "ByteString", defaultValue: null },
57
+ { type: "ImageGIF", realType: "ByteString", defaultValue: null },
58
+ { type: "ImageJPG", realType: "ByteString", defaultValue: null },
59
+ { type: "ImagePNG", realType: "ByteString", defaultValue: null }
60
+ ];