node-opcua-address-space-for-conformance-testing 2.179.0 → 2.181.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 (52) hide show
  1. package/dist/address_space_for_conformance_testing.d.ts +12 -2
  2. package/dist/address_space_for_conformance_testing.js +32 -27
  3. package/dist/address_space_for_conformance_testing.js.map +1 -1
  4. package/dist/conformance_testing/alarm_input_nodes.d.ts +2 -0
  5. package/dist/conformance_testing/alarm_input_nodes.js +102 -0
  6. package/dist/conformance_testing/alarm_input_nodes.js.map +1 -0
  7. package/dist/conformance_testing/ctt_folder.d.ts +2 -0
  8. package/dist/conformance_testing/ctt_folder.js +375 -0
  9. package/dist/conformance_testing/ctt_folder.js.map +1 -0
  10. package/dist/conformance_testing/ctt_tree.d.ts +35 -0
  11. package/dist/conformance_testing/ctt_tree.js +85 -0
  12. package/dist/conformance_testing/ctt_tree.js.map +1 -0
  13. package/dist/conformance_testing/custom_extension_object.d.ts +63 -0
  14. package/dist/conformance_testing/custom_extension_object.js +48 -0
  15. package/dist/conformance_testing/custom_extension_object.js.map +1 -0
  16. package/dist/conformance_testing/discrete_variables.js +6 -4
  17. package/dist/conformance_testing/discrete_variables.js.map +1 -1
  18. package/dist/conformance_testing/helpers.d.ts +2 -1
  19. package/dist/conformance_testing/helpers.js +23 -5
  20. package/dist/conformance_testing/helpers.js.map +1 -1
  21. package/dist/conformance_testing/mass_variables.d.ts +2 -1
  22. package/dist/conformance_testing/mass_variables.js +7 -6
  23. package/dist/conformance_testing/mass_variables.js.map +1 -1
  24. package/dist/conformance_testing/path_and_large_arrays.d.ts +2 -1
  25. package/dist/conformance_testing/path_and_large_arrays.js +6 -5
  26. package/dist/conformance_testing/path_and_large_arrays.js.map +1 -1
  27. package/dist/conformance_testing/simulation_variables.d.ts +2 -1
  28. package/dist/conformance_testing/simulation_variables.js +9 -9
  29. package/dist/conformance_testing/simulation_variables.js.map +1 -1
  30. package/dist/conformance_testing/static_variables.d.ts +2 -1
  31. package/dist/conformance_testing/static_variables.js +19 -12
  32. package/dist/conformance_testing/static_variables.js.map +1 -1
  33. package/dist/conformance_testing/type_defaults.d.ts +15 -1
  34. package/dist/conformance_testing/type_defaults.js +30 -1
  35. package/dist/conformance_testing/type_defaults.js.map +1 -1
  36. package/dist/index.d.ts +1 -1
  37. package/dist/index.js +1 -1
  38. package/dist/index.js.map +1 -1
  39. package/package.json +19 -14
  40. package/src/address_space_for_conformance_testing.ts +37 -18
  41. package/src/conformance_testing/alarm_input_nodes.ts +151 -0
  42. package/src/conformance_testing/ctt_folder.ts +440 -0
  43. package/src/conformance_testing/ctt_tree.ts +105 -0
  44. package/src/conformance_testing/custom_extension_object.ts +105 -0
  45. package/src/conformance_testing/discrete_variables.ts +6 -4
  46. package/src/conformance_testing/helpers.ts +26 -6
  47. package/src/conformance_testing/mass_variables.ts +5 -4
  48. package/src/conformance_testing/path_and_large_arrays.ts +5 -4
  49. package/src/conformance_testing/simulation_variables.ts +6 -6
  50. package/src/conformance_testing/static_variables.ts +31 -9
  51. package/src/conformance_testing/type_defaults.ts +31 -2
  52. package/src/index.ts +1 -1
@@ -4,7 +4,17 @@
4
4
  * Builds the conformance-testing address space by delegating to focused sub-modules.
5
5
  */
6
6
  import type { AddressSpace } from "node-opcua-address-space";
7
- export declare function build_address_space_for_conformance_testing(addressSpace: AddressSpace, options?: {
7
+ import { type CustomExtensionObjectOptions } from "./conformance_testing/custom_extension_object.js";
8
+ export type { CustomExtensionObjectOptions } from "./conformance_testing/custom_extension_object.js";
9
+ export interface BuildAddressSpaceForConformanceTestingOptions {
8
10
  mass_variable?: boolean;
9
11
  mass_variables?: boolean;
10
- }): Promise<void>;
12
+ /**
13
+ * The concrete structure the ExtensionObject variables hold. Namespace zero
14
+ * has none worth exercising, so a caller that has loaded a companion nodeset
15
+ * passes one in; without it those variables keep a null ExtensionObject.
16
+ * See ./conformance_testing/custom_extension_object.ts.
17
+ */
18
+ extensionObject?: CustomExtensionObjectOptions;
19
+ }
20
+ export declare function build_address_space_for_conformance_testing(addressSpace: AddressSpace, options?: BuildAddressSpaceForConformanceTestingOptions): Promise<void>;
@@ -2,28 +2,31 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.build_address_space_for_conformance_testing = build_address_space_for_conformance_testing;
4
4
  const testHelpers_1 = require("node-opcua-address-space/testHelpers");
5
- const access_right_variables_1 = require("./conformance_testing/access_right_variables");
6
- const analog_data_items_1 = require("./conformance_testing/analog_data_items");
7
- const discrete_variables_1 = require("./conformance_testing/discrete_variables");
8
- const enumeration_variable_1 = require("./conformance_testing/enumeration_variable");
9
- const mass_variables_1 = require("./conformance_testing/mass_variables");
10
- const node_with_references_1 = require("./conformance_testing/node_with_references");
11
- const object_with_methods_1 = require("./conformance_testing/object_with_methods");
12
- const path_and_large_arrays_1 = require("./conformance_testing/path_and_large_arrays");
13
- const sample_view_1 = require("./conformance_testing/sample_view");
14
- const simulation_variables_1 = require("./conformance_testing/simulation_variables");
15
- const static_variables_1 = require("./conformance_testing/static_variables");
16
- const trigger_nodes_1 = require("./conformance_testing/trigger_nodes");
5
+ const access_right_variables_js_1 = require("./conformance_testing/access_right_variables.js");
6
+ const analog_data_items_js_1 = require("./conformance_testing/analog_data_items.js");
7
+ const ctt_folder_js_1 = require("./conformance_testing/ctt_folder.js");
8
+ const custom_extension_object_js_1 = require("./conformance_testing/custom_extension_object.js");
9
+ const discrete_variables_js_1 = require("./conformance_testing/discrete_variables.js");
10
+ const enumeration_variable_js_1 = require("./conformance_testing/enumeration_variable.js");
11
+ const mass_variables_js_1 = require("./conformance_testing/mass_variables.js");
12
+ const node_with_references_js_1 = require("./conformance_testing/node_with_references.js");
13
+ const object_with_methods_js_1 = require("./conformance_testing/object_with_methods.js");
14
+ const path_and_large_arrays_js_1 = require("./conformance_testing/path_and_large_arrays.js");
15
+ const sample_view_js_1 = require("./conformance_testing/sample_view.js");
16
+ const simulation_variables_js_1 = require("./conformance_testing/simulation_variables.js");
17
+ const static_variables_js_1 = require("./conformance_testing/static_variables.js");
18
+ const trigger_nodes_js_1 = require("./conformance_testing/trigger_nodes.js");
17
19
  async function build_address_space_for_conformance_testing(addressSpace, options) {
18
20
  const namespace = addressSpace.registerNamespace("urn://node-opcua-simulator");
19
21
  options = options || {};
20
22
  options.mass_variable = options.mass_variable || false;
23
+ const custom = (0, custom_extension_object_js_1.resolveCustomExtensionObject)(addressSpace, options.extensionObject);
21
24
  const objectsFolder = addressSpace.findNode("ObjectsFolder");
22
25
  const simulationFolder = namespace.addFolder(objectsFolder, {
23
26
  browseName: "Simulation",
24
27
  nodeId: "s=SimulationFolder"
25
28
  });
26
- (0, access_right_variables_1.addAccessRightVariables)(namespace, simulationFolder);
29
+ (0, access_right_variables_js_1.addAccessRightVariables)(namespace, simulationFolder);
27
30
  const staticVariablesFolder = namespace.addFolder(simulationFolder, {
28
31
  browseName: "Static"
29
32
  });
@@ -31,25 +34,27 @@ async function build_address_space_for_conformance_testing(addressSpace, options
31
34
  browseName: "All Profiles"
32
35
  });
33
36
  // Scalars/Array/MultiDim array of all sorts
34
- await (0, static_variables_1.addStaticVariables)(namespace, allProfileFolder);
37
+ await (0, static_variables_js_1.addStaticVariables)(namespace, allProfileFolder, custom);
35
38
  if (options.mass_variables) {
36
- (0, mass_variables_1.addMassVariables)(namespace, allProfileFolder);
39
+ (0, mass_variables_js_1.addMassVariables)(namespace, allProfileFolder, custom);
37
40
  }
38
- (0, analog_data_items_1.addAnalogDataItems)(namespace, allProfileFolder);
41
+ (0, analog_data_items_js_1.addAnalogDataItems)(namespace, allProfileFolder);
39
42
  const dynamicVariablesFolder = namespace.addFolder(simulationFolder, {
40
43
  browseName: "Dynamic"
41
44
  });
42
- (0, simulation_variables_1.addSimulationVariables)(namespace, dynamicVariablesFolder);
43
- (0, path_and_large_arrays_1.addVeryLargeArrayVariables)(namespace, staticVariablesFolder);
44
- (0, path_and_large_arrays_1.addPath10Deep)(namespace, simulationFolder);
45
- (0, node_with_references_1.addNodeWithReferences)(namespace, simulationFolder);
46
- (0, object_with_methods_1.addObjectWithMethod)(namespace, simulationFolder);
45
+ (0, simulation_variables_js_1.addSimulationVariables)(namespace, dynamicVariablesFolder, custom);
46
+ (0, path_and_large_arrays_js_1.addVeryLargeArrayVariables)(namespace, staticVariablesFolder, custom);
47
+ (0, path_and_large_arrays_js_1.addPath10Deep)(namespace, simulationFolder);
48
+ (0, node_with_references_js_1.addNodeWithReferences)(namespace, simulationFolder);
49
+ (0, object_with_methods_js_1.addObjectWithMethod)(namespace, simulationFolder);
47
50
  (0, testHelpers_1.add_eventGeneratorObject)(namespace, simulationFolder);
48
- (0, sample_view_1.addSampleView)(namespace);
49
- (0, enumeration_variable_1.addEnumerationVariable)(namespace, simulationFolder);
50
- (0, discrete_variables_1.addMultiStateValueDiscreteVariables)(namespace, simulationFolder);
51
- (0, discrete_variables_1.addTwoStateDiscreteVariables)(namespace, simulationFolder);
52
- (0, discrete_variables_1.addMultiStateDiscreteVariable)(namespace, simulationFolder);
53
- (0, trigger_nodes_1.addTriggerNodes)(namespace, simulationFolder);
51
+ (0, sample_view_js_1.addSampleView)(namespace);
52
+ (0, enumeration_variable_js_1.addEnumerationVariable)(namespace, simulationFolder);
53
+ (0, discrete_variables_js_1.addMultiStateValueDiscreteVariables)(namespace, simulationFolder);
54
+ (0, discrete_variables_js_1.addTwoStateDiscreteVariables)(namespace, simulationFolder);
55
+ (0, discrete_variables_js_1.addMultiStateDiscreteVariable)(namespace, simulationFolder);
56
+ (0, trigger_nodes_js_1.addTriggerNodes)(namespace, simulationFolder);
57
+ // nodes named after the CTT settings the folders above do not serve
58
+ (0, ctt_folder_js_1.addCttFolder)(namespace, objectsFolder);
54
59
  }
55
60
  //# sourceMappingURL=address_space_for_conformance_testing.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"address_space_for_conformance_testing.js","sourceRoot":"","sources":["../src/address_space_for_conformance_testing.ts"],"names":[],"mappings":";;AAyBA,kGA4DC;AA/ED,sEAAgF;AAEhF,yFAAuF;AACvF,+EAA6E;AAC7E,iFAIkD;AAClD,qFAAoF;AACpF,yEAAwE;AACxE,qFAAmF;AACnF,mFAAgF;AAChF,uFAAwG;AACxG,mEAAkE;AAClE,qFAAoF;AACpF,6EAA4E;AAC5E,uEAAsE;AAE/D,KAAK,UAAU,2CAA2C,CAC7D,YAA0B,EAC1B,OAA+D;IAE/D,MAAM,SAAS,GAAG,YAAY,CAAC,iBAAiB,CAAC,4BAA4B,CAAC,CAAC;IAE/E,OAAO,GAAG,OAAO,IAAI,EAAE,CAAC;IACxB,OAAO,CAAC,aAAa,GAAG,OAAO,CAAC,aAAa,IAAI,KAAK,CAAC;IAEvD,MAAM,aAAa,GAAG,YAAY,CAAC,QAAQ,CAAC,eAAe,CAAa,CAAC;IAEzE,MAAM,gBAAgB,GAAG,SAAS,CAAC,SAAS,CAAC,aAAa,EAAE;QACxD,UAAU,EAAE,YAAY;QACxB,MAAM,EAAE,oBAAoB;KAC/B,CAAC,CAAC;IAEH,IAAA,gDAAuB,EAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC;IAErD,MAAM,qBAAqB,GAAG,SAAS,CAAC,SAAS,CAAC,gBAAgB,EAAE;QAChE,UAAU,EAAE,QAAQ;KACvB,CAAC,CAAC;IAEH,MAAM,gBAAgB,GAAG,SAAS,CAAC,SAAS,CAAC,qBAAqB,EAAE;QAChE,UAAU,EAAE,cAAc;KAC7B,CAAC,CAAC;IAEH,4CAA4C;IAC5C,MAAM,IAAA,qCAAkB,EAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC;IAEtD,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;QACzB,IAAA,iCAAgB,EAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC;IAClD,CAAC;IACD,IAAA,sCAAkB,EAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC;IAEhD,MAAM,sBAAsB,GAAG,SAAS,CAAC,SAAS,CAAC,gBAAgB,EAAE;QACjE,UAAU,EAAE,SAAS;KACxB,CAAC,CAAC;IACH,IAAA,6CAAsB,EAAC,SAAS,EAAE,sBAAsB,CAAC,CAAC;IAE1D,IAAA,kDAA0B,EAAC,SAAS,EAAE,qBAAqB,CAAC,CAAC;IAE7D,IAAA,qCAAa,EAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC;IAE3C,IAAA,4CAAqB,EAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC;IAEnD,IAAA,yCAAmB,EAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC;IAEjD,IAAA,sCAAwB,EAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC;IAEtD,IAAA,2BAAa,EAAC,SAAS,CAAC,CAAC;IAEzB,IAAA,6CAAsB,EAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC;IAEpD,IAAA,wDAAmC,EAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC;IAEjE,IAAA,iDAA4B,EAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC;IAE1D,IAAA,kDAA6B,EAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC;IAE3D,IAAA,+BAAe,EAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC;AACjD,CAAC"}
1
+ {"version":3,"file":"address_space_for_conformance_testing.js","sourceRoot":"","sources":["../src/address_space_for_conformance_testing.ts"],"names":[],"mappings":";;AAwCA,kGAgEC;AAlGD,sEAAgF;AAChF,+FAA0F;AAC1F,qFAAgF;AAChF,uEAAmE;AACnE,iGAAmI;AACnI,uFAIqD;AACrD,2FAAuF;AACvF,+EAA2E;AAC3E,2FAAsF;AACtF,yFAAmF;AACnF,6FAA2G;AAC3G,yEAAqE;AACrE,2FAAuF;AACvF,mFAA+E;AAC/E,6EAAyE;AAgBlE,KAAK,UAAU,2CAA2C,CAC7D,YAA0B,EAC1B,OAAuD;IAEvD,MAAM,SAAS,GAAG,YAAY,CAAC,iBAAiB,CAAC,4BAA4B,CAAC,CAAC;IAE/E,OAAO,GAAG,OAAO,IAAI,EAAE,CAAC;IACxB,OAAO,CAAC,aAAa,GAAG,OAAO,CAAC,aAAa,IAAI,KAAK,CAAC;IACvD,MAAM,MAAM,GAAG,IAAA,yDAA4B,EAAC,YAAY,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC;IAEnF,MAAM,aAAa,GAAG,YAAY,CAAC,QAAQ,CAAC,eAAe,CAAa,CAAC;IAEzE,MAAM,gBAAgB,GAAG,SAAS,CAAC,SAAS,CAAC,aAAa,EAAE;QACxD,UAAU,EAAE,YAAY;QACxB,MAAM,EAAE,oBAAoB;KAC/B,CAAC,CAAC;IAEH,IAAA,mDAAuB,EAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC;IAErD,MAAM,qBAAqB,GAAG,SAAS,CAAC,SAAS,CAAC,gBAAgB,EAAE;QAChE,UAAU,EAAE,QAAQ;KACvB,CAAC,CAAC;IAEH,MAAM,gBAAgB,GAAG,SAAS,CAAC,SAAS,CAAC,qBAAqB,EAAE;QAChE,UAAU,EAAE,cAAc;KAC7B,CAAC,CAAC;IAEH,4CAA4C;IAC5C,MAAM,IAAA,wCAAkB,EAAC,SAAS,EAAE,gBAAgB,EAAE,MAAM,CAAC,CAAC;IAE9D,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;QACzB,IAAA,oCAAgB,EAAC,SAAS,EAAE,gBAAgB,EAAE,MAAM,CAAC,CAAC;IAC1D,CAAC;IACD,IAAA,yCAAkB,EAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC;IAEhD,MAAM,sBAAsB,GAAG,SAAS,CAAC,SAAS,CAAC,gBAAgB,EAAE;QACjE,UAAU,EAAE,SAAS;KACxB,CAAC,CAAC;IACH,IAAA,gDAAsB,EAAC,SAAS,EAAE,sBAAsB,EAAE,MAAM,CAAC,CAAC;IAElE,IAAA,qDAA0B,EAAC,SAAS,EAAE,qBAAqB,EAAE,MAAM,CAAC,CAAC;IAErE,IAAA,wCAAa,EAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC;IAE3C,IAAA,+CAAqB,EAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC;IAEnD,IAAA,4CAAmB,EAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC;IAEjD,IAAA,sCAAwB,EAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC;IAEtD,IAAA,8BAAa,EAAC,SAAS,CAAC,CAAC;IAEzB,IAAA,gDAAsB,EAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC;IAEpD,IAAA,2DAAmC,EAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC;IAEjE,IAAA,oDAA4B,EAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC;IAE1D,IAAA,qDAA6B,EAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC;IAE3D,IAAA,kCAAe,EAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC;IAE7C,oEAAoE;IACpE,IAAA,4BAAY,EAAC,SAAS,EAAE,aAAa,CAAC,CAAC;AAC3C,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { CttFolder } from "./ctt_tree.js";
2
+ export declare function addAlarmInputNodes(ctt: CttFolder): void;
@@ -0,0 +1,102 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.addAlarmInputNodes = addAlarmInputNodes;
4
+ const node_opcua_variant_1 = require("node-opcua-variant");
5
+ /** where the CTT keeps these settings; outside "Server Test/NodeIds", so the whole path is the key */
6
+ const GROUP = "Server Test/Alarms and Conditions/Supported Condition Types";
7
+ /** the limits every limit-derived alarm here is given, in the units of a 0..100 input */
8
+ const LIMITS = { lowLowLimit: 10, lowLimit: 25, highLimit: 75, highHighLimit: 90 };
9
+ const double = (value) => new node_opcua_variant_1.Variant({ dataType: node_opcua_variant_1.DataType.Double, value });
10
+ const boolean = (value) => new node_opcua_variant_1.Variant({ dataType: node_opcua_variant_1.DataType.Boolean, value });
11
+ /**
12
+ * The object every alarm is a condition of. It must be an event source of
13
+ * something, or `conditionSource` throws; making it an event source of the
14
+ * Server object is what puts its events on the Server notifier the CTT
15
+ * subscribes to.
16
+ */
17
+ function addAlarmSource(ctt) {
18
+ const server = ctt.addressSpace.rootFolder.objects.server;
19
+ return ctt.namespace.addObject({
20
+ browseName: "AlarmSource",
21
+ nodeId: ctt.nodeId("Server Test/Alarms and Conditions/AlarmSource"),
22
+ organizedBy: ctt.folder("Server Test/Alarms and Conditions"),
23
+ description: "condition source of the CTT alarm input nodes",
24
+ eventSourceOf: server
25
+ });
26
+ }
27
+ function addAlarmInputNodes(ctt) {
28
+ const namespace = ctt.namespace;
29
+ const conditionSource = addAlarmSource(ctt);
30
+ /** the writable Variable a CTT alarm setting points at; 50 sits inside LIMITS, so alarms start inactive */
31
+ const inputNode = (leaf, kind) => ctt.variable(`${GROUP}/${leaf}`, kind, -1, kind === "Double" ? double(50) : boolean(false), null);
32
+ /** a deviation setpoint, at 0 so the deviation the alarm evaluates is the input value itself */
33
+ const setpointNode = (leaf) => ctt.variable(`${GROUP}/${leaf}`, "Double", -1, double(0), null);
34
+ const alarmOptions = (browseName, input) => ({
35
+ browseName,
36
+ nodeId: ctt.nodeId(`Server Test/Alarms and Conditions/${browseName}`),
37
+ conditionSource,
38
+ inputNode: input
39
+ });
40
+ // ── AlarmConditionType ──────────────────────────────────────────────
41
+ // the base type has no sub-state model: the CTT drives ActiveState itself
42
+ namespace.instantiateAlarmCondition("AlarmConditionType", alarmOptions("AlarmCondition", inputNode("AlarmConditionType Input Nodes", "Double")));
43
+ // ── the limit family ────────────────────────────────────────────────
44
+ namespace.instantiateLimitAlarm("LimitAlarmType", {
45
+ ...alarmOptions("LimitAlarm", inputNode("LimitAlarmType Input Nodes", "Double")),
46
+ ...LIMITS
47
+ });
48
+ for (const [typeName, leaf] of [
49
+ ["ExclusiveLimitAlarmType", "ExclusiveLimitAlarmType Input Nodes"],
50
+ ["ExclusiveLevelAlarmType", "ExclusiveLevelAlarmType Input Nodes"],
51
+ ["ExclusiveRateOfChangeAlarmType", "ExclusiveRateOfChangeAlarmType Input Nodes"]
52
+ ]) {
53
+ namespace.instantiateExclusiveLimitAlarm(typeName, {
54
+ ...alarmOptions(typeName.replace(/Type$/, ""), inputNode(leaf, "Double")),
55
+ ...LIMITS
56
+ });
57
+ }
58
+ for (const [typeName, leaf] of [
59
+ ["NonExclusiveLimitAlarmType", "NonExclusiveLimitAlarmType Input Nodes"],
60
+ ["NonExclusiveLevelAlarmType", "NonExclusiveLevelAlarmType Input Nodes"],
61
+ ["NonExclusiveRateOfChangeAlarmType", "NonExclusiveRateOfChangeAlarmType Input Nodes"]
62
+ ]) {
63
+ namespace.instantiateNonExclusiveLimitAlarm(typeName, {
64
+ ...alarmOptions(typeName.replace(/Type$/, ""), inputNode(leaf, "Double")),
65
+ ...LIMITS
66
+ });
67
+ }
68
+ // ── the deviation pairs: the setpoint is a setting of its own ───────
69
+ const exclusiveSetpoint = setpointNode("Exclusive Deviation Setpoint Source");
70
+ namespace.instantiateExclusiveDeviationAlarm({
71
+ ...alarmOptions("ExclusiveDeviationAlarm", inputNode("ExclusiveDeviationAlarmType Input Nodes", "Double")),
72
+ ...LIMITS,
73
+ setpointNode: exclusiveSetpoint
74
+ });
75
+ const nonExclusiveSetpoint = setpointNode("NonExclusive Deviation Setpoint Source");
76
+ namespace.instantiateNonExclusiveDeviationAlarm({
77
+ ...alarmOptions("NonExclusiveDeviationAlarm", inputNode("NonExclusiveDeviationAlarmType Input Nodes", "Double")),
78
+ ...LIMITS,
79
+ setpointNode: nonExclusiveSetpoint
80
+ });
81
+ // ── the discrete family ─────────────────────────────────────────────
82
+ namespace.instantiateDiscreteAlarm("DiscreteAlarmType", alarmOptions("DiscreteAlarm", inputNode("DiscreteAlarmType Input Nodes", "Boolean")));
83
+ // OffNormalAlarmType is active while its input differs from NormalState
84
+ const normalState = namespace.addVariable({
85
+ browseName: "OffNormalNormalState",
86
+ nodeId: ctt.nodeId("Server Test/Alarms and Conditions/OffNormalNormalState"),
87
+ componentOf: ctt.folder("Server Test/Alarms and Conditions"),
88
+ description: "the value OffNormalAlarmType considers normal",
89
+ dataType: "Boolean",
90
+ value: boolean(false)
91
+ });
92
+ namespace.instantiateOffNormalAlarm({
93
+ ...alarmOptions("OffNormalAlarm", inputNode("OffNormalAlarmType Input Nodes", "Boolean")),
94
+ normalState
95
+ });
96
+ // `instantiateOffNormalAlarm` is hardwired to OffNormalAlarmType and
97
+ // UASystemOffNormalAlarmImpl is not exported, so the derived type is
98
+ // instantiated generically: the node and its mandatory children exist,
99
+ // the NormalState comparison is not wired.
100
+ namespace.instantiateAlarmCondition("SystemOffNormalAlarmType", alarmOptions("SystemOffNormalAlarm", inputNode("SystemOffNormalAlarmType Input Nodes", "Boolean")));
101
+ }
102
+ //# sourceMappingURL=alarm_input_nodes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"alarm_input_nodes.js","sourceRoot":"","sources":["../../src/conformance_testing/alarm_input_nodes.ts"],"names":[],"mappings":";;AAsDA,gDAgGC;AA9HD,2DAAuD;AAIvD,sGAAsG;AACtG,MAAM,KAAK,GAAG,6DAA6D,CAAC;AAE5E,yFAAyF;AACzF,MAAM,MAAM,GAAG,EAAE,WAAW,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,aAAa,EAAE,EAAE,EAAE,CAAC;AAEnF,MAAM,MAAM,GAAG,CAAC,KAAa,EAAE,EAAE,CAAC,IAAI,4BAAO,CAAC,EAAE,QAAQ,EAAE,6BAAQ,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;AACpF,MAAM,OAAO,GAAG,CAAC,KAAc,EAAE,EAAE,CAAC,IAAI,4BAAO,CAAC,EAAE,QAAQ,EAAE,6BAAQ,CAAC,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;AAEvF;;;;;GAKG;AACH,SAAS,cAAc,CAAC,GAAc;IAClC,MAAM,MAAM,GAAG,GAAG,CAAC,YAAY,CAAC,UAAU,CAAC,OAAO,CAAC,MAAM,CAAC;IAC1D,OAAO,GAAG,CAAC,SAAS,CAAC,SAAS,CAAC;QAC3B,UAAU,EAAE,aAAa;QACzB,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,+CAA+C,CAAC;QACnE,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,mCAAmC,CAAC;QAC5D,WAAW,EAAE,+CAA+C;QAC5D,aAAa,EAAE,MAAM;KACxB,CAAC,CAAC;AACP,CAAC;AAED,SAAgB,kBAAkB,CAAC,GAAc;IAC7C,MAAM,SAAS,GAAc,GAAG,CAAC,SAAS,CAAC;IAC3C,MAAM,eAAe,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;IAE5C,2GAA2G;IAC3G,MAAM,SAAS,GAAG,CAAC,IAAY,EAAE,IAA0B,EAAc,EAAE,CACvE,GAAG,CAAC,QAAQ,CAAC,GAAG,KAAK,IAAI,IAAI,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,CAAC;IAEtG,gGAAgG;IAChG,MAAM,YAAY,GAAG,CAAC,IAAY,EAAc,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,KAAK,IAAI,IAAI,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IAEnH,MAAM,YAAY,GAAG,CAAC,UAAkB,EAAE,KAAiB,EAAE,EAAE,CAAC,CAAC;QAC7D,UAAU;QACV,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,qCAAqC,UAAU,EAAE,CAAC;QACrE,eAAe;QACf,SAAS,EAAE,KAAK;KACnB,CAAC,CAAC;IAEH,uEAAuE;IACvE,0EAA0E;IAC1E,SAAS,CAAC,yBAAyB,CAC/B,oBAAoB,EACpB,YAAY,CAAC,gBAAgB,EAAE,SAAS,CAAC,gCAAgC,EAAE,QAAQ,CAAC,CAAC,CACxF,CAAC;IAEF,uEAAuE;IACvE,SAAS,CAAC,qBAAqB,CAAC,gBAAgB,EAAE;QAC9C,GAAG,YAAY,CAAC,YAAY,EAAE,SAAS,CAAC,4BAA4B,EAAE,QAAQ,CAAC,CAAC;QAChF,GAAG,MAAM;KACZ,CAAC,CAAC;IAEH,KAAK,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI;QAC3B,CAAC,yBAAyB,EAAE,qCAAqC,CAAC;QAClE,CAAC,yBAAyB,EAAE,qCAAqC,CAAC;QAClE,CAAC,gCAAgC,EAAE,4CAA4C,CAAC;KACnF,EAAE,CAAC;QACA,SAAS,CAAC,8BAA8B,CAAC,QAAQ,EAAE;YAC/C,GAAG,YAAY,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,SAAS,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;YACzE,GAAG,MAAM;SACZ,CAAC,CAAC;IACP,CAAC;IAED,KAAK,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI;QAC3B,CAAC,4BAA4B,EAAE,wCAAwC,CAAC;QACxE,CAAC,4BAA4B,EAAE,wCAAwC,CAAC;QACxE,CAAC,mCAAmC,EAAE,+CAA+C,CAAC;KACzF,EAAE,CAAC;QACA,SAAS,CAAC,iCAAiC,CAAC,QAAQ,EAAE;YAClD,GAAG,YAAY,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,SAAS,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;YACzE,GAAG,MAAM;SACZ,CAAC,CAAC;IACP,CAAC;IAED,uEAAuE;IACvE,MAAM,iBAAiB,GAAG,YAAY,CAAC,qCAAqC,CAAC,CAAC;IAC9E,SAAS,CAAC,kCAAkC,CAAC;QACzC,GAAG,YAAY,CAAC,yBAAyB,EAAE,SAAS,CAAC,yCAAyC,EAAE,QAAQ,CAAC,CAAC;QAC1G,GAAG,MAAM;QACT,YAAY,EAAE,iBAAmG;KACpH,CAAC,CAAC;IAEH,MAAM,oBAAoB,GAAG,YAAY,CAAC,wCAAwC,CAAC,CAAC;IACpF,SAAS,CAAC,qCAAqC,CAAC;QAC5C,GAAG,YAAY,CAAC,4BAA4B,EAAE,SAAS,CAAC,4CAA4C,EAAE,QAAQ,CAAC,CAAC;QAChH,GAAG,MAAM;QACT,YAAY,EAAE,oBAAyG;KAC1H,CAAC,CAAC;IAEH,uEAAuE;IACvE,SAAS,CAAC,wBAAwB,CAC9B,mBAAmB,EACnB,YAAY,CAAC,eAAe,EAAE,SAAS,CAAC,+BAA+B,EAAE,SAAS,CAAC,CAAC,CACvF,CAAC;IAEF,wEAAwE;IACxE,MAAM,WAAW,GAAG,SAAS,CAAC,WAAW,CAAC;QACtC,UAAU,EAAE,sBAAsB;QAClC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,wDAAwD,CAAC;QAC5E,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,mCAAmC,CAAC;QAC5D,WAAW,EAAE,+CAA+C;QAC5D,QAAQ,EAAE,SAAS;QACnB,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC;KACxB,CAAC,CAAC;IACH,SAAS,CAAC,yBAAyB,CAAC;QAChC,GAAG,YAAY,CAAC,gBAAgB,EAAE,SAAS,CAAC,gCAAgC,EAAE,SAAS,CAAC,CAAC;QACzF,WAAW;KACd,CAAC,CAAC;IAEH,qEAAqE;IACrE,qEAAqE;IACrE,uEAAuE;IACvE,2CAA2C;IAC3C,SAAS,CAAC,yBAAyB,CAC/B,0BAA0B,EAC1B,YAAY,CAAC,sBAAsB,EAAE,SAAS,CAAC,sCAAsC,EAAE,SAAS,CAAC,CAAC,CACrG,CAAC;AACN,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { Namespace, UAObject } from "node-opcua-address-space";
2
+ export declare function addCttFolder(namespace: Namespace, objectsFolder: UAObject): UAObject;
@@ -0,0 +1,375 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.addCttFolder = addCttFolder;
7
+ /**
8
+ * The `CTT` folder: nodes named after the settings of the OPC Foundation
9
+ * Compliance Test Tool (UACTT) server project.
10
+ *
11
+ * The browse path below Objects/CTT mirrors the setting path below
12
+ * "Server Test/NodeIds", e.g. the setting
13
+ * Server Test/NodeIds/Static/HA Profile/Arrays/Int162D
14
+ * is served by
15
+ * Objects/CTT/Static/HA Profile/Arrays/Int162D (NodeId s=CTT/Static/HA Profile/Arrays/Int162D)
16
+ * so a CTT project generator can fill the setting by browsing, without any
17
+ * hand-maintained map. See ./ctt_tree.ts for how a setting outside that prefix
18
+ * is keyed. Only settings the rest of this address space does not already serve
19
+ * are built here - plus the two Bool settings, see addBooleanScalarAndArray().
20
+ *
21
+ * Not covered, and why:
22
+ * Decimal deprecated in OPC UA 1.05
23
+ * the HA Aggregates nodes need node-opcua-aggregates and a seeded
24
+ * history matching the CTT's StartOfBadData*
25
+ * NodeDoesNotSupportServerTimestamp needs the variable read path to omit it
26
+ * NodeManagement/RootNode the server has no AddNodes service
27
+ * Chattering Alarms needs an alarm that flips state on its own
28
+ * DiscrepancyAlarmType Input Nodes see ./alarm_input_nodes.ts
29
+ */
30
+ const node_fs_1 = __importDefault(require("node:fs"));
31
+ const node_path_1 = __importDefault(require("node:path"));
32
+ const node_opcua_data_access_1 = require("node-opcua-data-access");
33
+ const node_opcua_data_model_1 = require("node-opcua-data-model");
34
+ const node_opcua_variant_1 = require("node-opcua-variant");
35
+ const alarm_input_nodes_js_1 = require("./alarm_input_nodes.js");
36
+ const ctt_tree_js_1 = require("./ctt_tree.js");
37
+ // ─── Static / All Profiles ──────────────────────────────────────────────
38
+ function addVariantVariables(ctt) {
39
+ // "Variant" in CTT terms: a Variable whose DataType attribute is BaseDataType
40
+ const scalar = new node_opcua_variant_1.Variant({ dataType: node_opcua_variant_1.DataType.Double, value: 3.14 });
41
+ ctt.variable("Static/All Profiles/Scalar/Variant", "BaseDataType", -1, scalar, null);
42
+ // The array is the one case the CTT actually type-checks: Attribute Read 023.js
43
+ // asserts AssertUaValueOfType(BuiltInType.Variant, ...) against this node, so the
44
+ // *value* has to be Variant-encoded (BuiltInType 24), not merely stored on a
45
+ // BaseDataType-typed Variable. A Float64Array reads back as Double (11) and fails
46
+ // that assertion. Mixed element types are also the point of the type, and exercise
47
+ // the encoder the way the test intends.
48
+ ctt.variable("Static/All Profiles/Arrays/Variant", "BaseDataType", 1, new node_opcua_variant_1.Variant({
49
+ dataType: node_opcua_variant_1.DataType.Variant,
50
+ arrayType: node_opcua_variant_1.VariantArrayType.Array,
51
+ value: [
52
+ new node_opcua_variant_1.Variant({ dataType: node_opcua_variant_1.DataType.Double, value: 1 }),
53
+ new node_opcua_variant_1.Variant({ dataType: node_opcua_variant_1.DataType.UInt32, value: 2 }),
54
+ new node_opcua_variant_1.Variant({ dataType: node_opcua_variant_1.DataType.String, value: "three" }),
55
+ new node_opcua_variant_1.Variant({ dataType: node_opcua_variant_1.DataType.Boolean, value: true }),
56
+ new node_opcua_variant_1.Variant({ dataType: node_opcua_variant_1.DataType.Float, value: 5.5 })
57
+ ]
58
+ }), [5]);
59
+ ctt.variable("Static/All Profiles/Multi-Dimensional-Arrays/Variant", "BaseDataType", 2, new node_opcua_variant_1.Variant({
60
+ dataType: node_opcua_variant_1.DataType.Double,
61
+ arrayType: node_opcua_variant_1.VariantArrayType.Matrix,
62
+ dimensions: [2, 3],
63
+ value: new Float64Array([1, 2, 3, 4, 5, 6])
64
+ }), [2, 3]);
65
+ }
66
+ /**
67
+ * `Static/All Profiles/Scalar/Bool` and `.../Arrays/Bool`, which the Simulation
68
+ * folder would otherwise serve.
69
+ *
70
+ * A generator resolves a setting by overlay, then convention, then the CTT's own
71
+ * default, then by *browse name*, then by rule. The HA Profile nodes below are
72
+ * browse-named after their setting leaf, so `Static/HA Profile/Scalar/Bool` is
73
+ * literally named `Bool` - and the name step matches it against the All Profiles
74
+ * `Bool` settings, for which there is no convention node, while the Simulation
75
+ * node named `Boolean` matches neither. The name step runs before the rule step,
76
+ * so those two settings would silently resolve to a historizing node. Every other
77
+ * type name is safe: `Byte`, `Double` and the rest match both nodes and the rule
78
+ * scoring then prefers the non-historizing one.
79
+ *
80
+ * Building the two nodes here makes the convention step answer first, which is
81
+ * both deterministic and where the CTT-specific extras belong - hence the two
82
+ * Description properties, which View Minimum Continuation Point 01 012 needs
83
+ * (it browses the Scalar/Bool setting node with a NodeClassMask of Variable and
84
+ * wants at least two such references).
85
+ */
86
+ function addBooleanScalarAndArray(ctt) {
87
+ const scalar = ctt.typedVariable("Static/All Profiles/Scalar/Bool", "Boolean", -1);
88
+ for (const name of ["Description1", "Description2"]) {
89
+ ctt.namespace.addVariable({
90
+ propertyOf: scalar,
91
+ browseName: name,
92
+ nodeId: ctt.nodeId(`Static/All Profiles/Scalar/Bool/${name}`),
93
+ dataType: "String",
94
+ value: new node_opcua_variant_1.Variant({ dataType: node_opcua_variant_1.DataType.String, value: `${name} of the static Boolean` })
95
+ });
96
+ }
97
+ ctt.typedVariable("Static/All Profiles/Arrays/Bool", "Boolean", 1);
98
+ }
99
+ function addImageVariable(ctt) {
100
+ // the abstract Image data type (the concrete ImagePNG/GIF/JPG/BMP nodes live under Simulation)
101
+ let png;
102
+ try {
103
+ png = node_fs_1.default.readFileSync(node_path_1.default.join(__dirname, "../../data", "tux.png"));
104
+ }
105
+ catch (_err) {
106
+ png = Buffer.from("89504e470d0a1a0a", "hex");
107
+ }
108
+ ctt.variable("Static/All Profiles/Scalar/Image", "Image", -1, new node_opcua_variant_1.Variant({ dataType: node_opcua_variant_1.DataType.ByteString, value: png }), null);
109
+ }
110
+ function addStructureVariables(ctt) {
111
+ const addressSpace = ctt.addressSpace;
112
+ const structures = [
113
+ { dataType: "Range", fields: { low: -10, high: 10 } },
114
+ {
115
+ dataType: "EUInformation",
116
+ fields: {
117
+ namespaceUri: "http://www.opcfoundation.org/UA/units/un/cefact",
118
+ unitId: 4408652,
119
+ displayName: { text: "°C" },
120
+ description: { text: "degree Celsius" }
121
+ }
122
+ },
123
+ { dataType: "TimeZoneDataType", fields: { offset: 60, daylightSavingInOffset: false } },
124
+ {
125
+ dataType: "EnumValueType",
126
+ fields: { value: [1, 0], displayName: { text: "One" }, description: { text: "the value one" } }
127
+ },
128
+ {
129
+ dataType: "Argument",
130
+ fields: {
131
+ name: "arg",
132
+ dataType: "i=6",
133
+ valueRank: -1,
134
+ arrayDimensions: null,
135
+ description: { text: "an Int32 argument" }
136
+ }
137
+ }
138
+ ];
139
+ structures.forEach((s, i) => {
140
+ const dataTypeNode = addressSpace.findDataType(s.dataType);
141
+ if (!dataTypeNode)
142
+ throw new Error(`DataType ${s.dataType} not found`);
143
+ const value = addressSpace.constructExtensionObject(dataTypeNode, s.fields);
144
+ ctt.variable(`Static/All Profiles/Structures/Structure${String(i + 1).padStart(3, "0")}`, s.dataType, -1, new node_opcua_variant_1.Variant({ dataType: node_opcua_variant_1.DataType.ExtensionObject, value }), null);
145
+ });
146
+ }
147
+ // ─── Static / DA Profile ────────────────────────────────────────────────
148
+ function addAnalogItemArrays(ctt) {
149
+ const folder = ctt.folder("Static/DA Profile/AnalogItemType Arrays");
150
+ for (const dataTypeName of ["Double", "Float", "Int16", "Int32", "UInt16", "UInt32"]) {
151
+ const dataType = node_opcua_variant_1.DataType[dataTypeName];
152
+ ctt.namespace.addAnalogDataItem({
153
+ organizedBy: folder,
154
+ browseName: dataTypeName,
155
+ nodeId: ctt.nodeId(`Static/DA Profile/AnalogItemType Arrays/${dataTypeName}`),
156
+ dataType: dataTypeName,
157
+ valueRank: 1,
158
+ arrayDimensions: [5],
159
+ arrayType: node_opcua_variant_1.VariantArrayType.Array,
160
+ engineeringUnitsRange: { low: -100, high: 100 },
161
+ instrumentRange: { low: -1000, high: 1000 },
162
+ engineeringUnits: node_opcua_data_access_1.standardUnits.degree_celsius,
163
+ value: new node_opcua_variant_1.Variant({ dataType, arrayType: node_opcua_variant_1.VariantArrayType.Array, value: (0, node_opcua_variant_1.buildVariantArray)(dataType, 5, 0) }),
164
+ accessLevel: ctt_tree_js_1.readWrite,
165
+ userAccessLevel: ctt_tree_js_1.readWrite
166
+ });
167
+ }
168
+ }
169
+ function axis(addressSpace, title, low, high) {
170
+ const axisInformation = addressSpace.findDataType("AxisInformation");
171
+ if (!axisInformation)
172
+ throw new Error("AxisInformation not found");
173
+ return addressSpace.constructExtensionObject(axisInformation, {
174
+ engineeringUnits: node_opcua_data_access_1.standardUnits.second,
175
+ euRange: { low, high },
176
+ title: { text: title },
177
+ axisScaleType: 0, // Linear
178
+ axisSteps: null
179
+ });
180
+ }
181
+ /**
182
+ * The five ArrayItemType subtypes: plain variables of the right VariableType,
183
+ * given the mandatory ArrayItemType properties by hand. instantiate() refuses
184
+ * a ValueRank that differs from the type's (ImageItemType and CubeItemType
185
+ * need 2 and 3) and namespace.addYArrayItem() ignores nodeId and organizedBy.
186
+ */
187
+ function addArrayItems(ctt) {
188
+ const addressSpace = ctt.addressSpace;
189
+ const namespace = ctt.namespace;
190
+ const group = "Static/DA Profile/ArrayItemType";
191
+ const folder = ctt.folder(group);
192
+ const xAxis = axis(addressSpace, "x", 0, 10);
193
+ const yAxis = axis(addressSpace, "y", 0, 20);
194
+ const zAxis = axis(addressSpace, "z", 0, 30);
195
+ const rangeType = addressSpace.findDataType("Range");
196
+ const xvType = addressSpace.findDataType("XVType");
197
+ if (!rangeType || !xvType)
198
+ throw new Error("Range or XVType not found");
199
+ const extensionObject = (value) => new node_opcua_variant_1.Variant({ dataType: node_opcua_variant_1.DataType.ExtensionObject, value });
200
+ const arrayItem = (typeName, options, axes) => {
201
+ const v = namespace.addVariable({
202
+ organizedBy: folder,
203
+ browseName: typeName,
204
+ nodeId: ctt.nodeId(`${group}/${typeName}`),
205
+ typeDefinition: typeName,
206
+ dataType: options.dataType,
207
+ valueRank: options.valueRank,
208
+ arrayDimensions: options.arrayDimensions,
209
+ accessLevel: ctt_tree_js_1.readWrite,
210
+ userAccessLevel: ctt_tree_js_1.readWrite,
211
+ value: options.value
212
+ });
213
+ const property = (browseName, dataType, value, valueRank = -1) => namespace.addVariable({ propertyOf: v, browseName, dataType, valueRank, value, modellingRule: "Mandatory" });
214
+ property("Title", "LocalizedText", new node_opcua_variant_1.Variant({ dataType: node_opcua_variant_1.DataType.LocalizedText, value: { text: typeName } }));
215
+ property("AxisScaleType", "AxisScaleEnumeration", new node_opcua_variant_1.Variant({ dataType: node_opcua_variant_1.DataType.Int32, value: 0 }));
216
+ property("EURange", "Range", extensionObject(addressSpace.constructExtensionObject(rangeType, { low: 0, high: 100 })));
217
+ property("InstrumentRange", "Range", extensionObject(addressSpace.constructExtensionObject(rangeType, { low: 0, high: 1000 })));
218
+ property("EngineeringUnits", "EUInformation", extensionObject(node_opcua_data_access_1.standardUnits.degree_celsius));
219
+ for (const [name, value] of Object.entries(axes)) {
220
+ property(name, "AxisInformation", value, value.arrayType === node_opcua_variant_1.VariantArrayType.Array ? 1 : -1);
221
+ }
222
+ return v;
223
+ };
224
+ arrayItem("YArrayItemType", {
225
+ dataType: "Double",
226
+ valueRank: 1,
227
+ arrayDimensions: [5],
228
+ value: new node_opcua_variant_1.Variant({
229
+ dataType: node_opcua_variant_1.DataType.Double,
230
+ arrayType: node_opcua_variant_1.VariantArrayType.Array,
231
+ value: new Float64Array([1, 2, 3, 4, 5])
232
+ })
233
+ }, { XAxisDefinition: extensionObject(xAxis) });
234
+ arrayItem("XYArrayItemType", {
235
+ dataType: "XVType",
236
+ valueRank: 1,
237
+ arrayDimensions: [3],
238
+ value: new node_opcua_variant_1.Variant({
239
+ dataType: node_opcua_variant_1.DataType.ExtensionObject,
240
+ arrayType: node_opcua_variant_1.VariantArrayType.Array,
241
+ value: [0, 1, 2].map((i) => addressSpace.constructExtensionObject(xvType, { x: i, value: i * 2 }))
242
+ })
243
+ }, { XAxisDefinition: extensionObject(xAxis) });
244
+ arrayItem("ImageItemType", {
245
+ dataType: "UInt16",
246
+ valueRank: 2,
247
+ arrayDimensions: [2, 3],
248
+ value: new node_opcua_variant_1.Variant({
249
+ dataType: node_opcua_variant_1.DataType.UInt16,
250
+ arrayType: node_opcua_variant_1.VariantArrayType.Matrix,
251
+ dimensions: [2, 3],
252
+ value: new Uint16Array([1, 2, 3, 4, 5, 6])
253
+ })
254
+ }, { XAxisDefinition: extensionObject(xAxis), YAxisDefinition: extensionObject(yAxis) });
255
+ arrayItem("CubeItemType", {
256
+ dataType: "Double",
257
+ valueRank: 3,
258
+ arrayDimensions: [2, 2, 2],
259
+ value: new node_opcua_variant_1.Variant({
260
+ dataType: node_opcua_variant_1.DataType.Double,
261
+ arrayType: node_opcua_variant_1.VariantArrayType.Matrix,
262
+ dimensions: [2, 2, 2],
263
+ value: new Float64Array([1, 2, 3, 4, 5, 6, 7, 8])
264
+ })
265
+ }, {
266
+ XAxisDefinition: extensionObject(xAxis),
267
+ YAxisDefinition: extensionObject(yAxis),
268
+ ZAxisDefinition: extensionObject(zAxis)
269
+ });
270
+ arrayItem("NDimensionArrayItemType", {
271
+ dataType: "Double",
272
+ valueRank: 2,
273
+ arrayDimensions: [2, 3],
274
+ value: new node_opcua_variant_1.Variant({
275
+ dataType: node_opcua_variant_1.DataType.Double,
276
+ arrayType: node_opcua_variant_1.VariantArrayType.Matrix,
277
+ dimensions: [2, 3],
278
+ value: new Float64Array([1, 2, 3, 4, 5, 6])
279
+ })
280
+ }, {
281
+ AxisDefinition: new node_opcua_variant_1.Variant({
282
+ dataType: node_opcua_variant_1.DataType.ExtensionObject,
283
+ arrayType: node_opcua_variant_1.VariantArrayType.Array,
284
+ value: [xAxis, yAxis]
285
+ })
286
+ });
287
+ }
288
+ // ─── Static / HA Profile ────────────────────────────────────────────────
289
+ const HA_TYPES = [
290
+ "Bool",
291
+ "Byte",
292
+ "ByteString",
293
+ "DateTime",
294
+ "Double",
295
+ "Float",
296
+ "Int16",
297
+ "Int32",
298
+ "Int64",
299
+ "SByte",
300
+ "String",
301
+ "UInt16",
302
+ "UInt32",
303
+ "UInt64",
304
+ "XmlElement"
305
+ ];
306
+ /** a variable with in-memory history and a first value, so reads are Good with timestamps */
307
+ function historize(ctt, variable) {
308
+ ctt.addressSpace.installHistoricalDataNode(variable);
309
+ const current = variable.readValue().value;
310
+ variable.setValueFromSource(current);
311
+ return variable;
312
+ }
313
+ function addHistorizingVariables(ctt) {
314
+ for (const leaf of HA_TYPES) {
315
+ const dataTypeName = ctt_tree_js_1.TYPE_ALIAS[leaf] ?? leaf;
316
+ historize(ctt, ctt.typedVariable(`Static/HA Profile/Scalar/${leaf}`, dataTypeName, -1));
317
+ historize(ctt, ctt.typedVariable(`Static/HA Profile/Arrays/${leaf}`, dataTypeName, 1));
318
+ historize(ctt, ctt.typedVariable(`Static/HA Profile/Arrays/${leaf}2D`, dataTypeName, 2));
319
+ }
320
+ const range = ctt.addressSpace.findDataType("Range");
321
+ if (!range)
322
+ throw new Error("Range not found");
323
+ historize(ctt, ctt.variable("Static/HA Profile/StructureNodeSupportingHistory", "Range", -1, new node_opcua_variant_1.Variant({
324
+ dataType: node_opcua_variant_1.DataType.ExtensionObject,
325
+ value: ctt.addressSpace.constructExtensionObject(range, { low: 0, high: 1 })
326
+ }), null));
327
+ // AccessLevel_* : the AccessLevel attribute; UserAccessLevel_* : the UserAccessLevel attribute
328
+ const history = node_opcua_data_model_1.AccessLevelFlag.HistoryRead;
329
+ const flags = {
330
+ ReadOnly: node_opcua_data_model_1.AccessLevelFlag.CurrentRead | history,
331
+ WriteOnly: node_opcua_data_model_1.AccessLevelFlag.CurrentWrite | history,
332
+ None: history
333
+ };
334
+ for (const attribute of ["AccessLevel", "UserAccessLevel"]) {
335
+ for (const [kind, flag] of Object.entries(flags)) {
336
+ const relPath = `Static/HA Profile/AccessRights/${attribute}_${kind}`;
337
+ const i = relPath.lastIndexOf("/");
338
+ const full = node_opcua_data_model_1.AccessLevelFlag.CurrentRead | node_opcua_data_model_1.AccessLevelFlag.CurrentWrite | history;
339
+ const v = ctt.namespace.addVariable({
340
+ componentOf: ctt.folder(relPath.slice(0, i)),
341
+ browseName: relPath.slice(i + 1),
342
+ nodeId: ctt.nodeId(relPath),
343
+ description: `CTT setting ${relPath}`,
344
+ dataType: "Int32",
345
+ valueRank: -1,
346
+ accessLevel: full,
347
+ userAccessLevel: full,
348
+ value: new node_opcua_variant_1.Variant({ dataType: node_opcua_variant_1.DataType.Int32, value: 36 })
349
+ });
350
+ historize(ctt, v);
351
+ // installHistoricalDataNode() adds CurrentRead to both attributes: set the flags after it
352
+ v.accessLevel = attribute === "AccessLevel" ? flag : full;
353
+ v.userAccessLevel = attribute === "UserAccessLevel" ? flag : full;
354
+ }
355
+ }
356
+ }
357
+ // ─── entry point ────────────────────────────────────────────────────────
358
+ function addCttFolder(namespace, objectsFolder) {
359
+ const root = namespace.addFolder(objectsFolder, {
360
+ browseName: "CTT",
361
+ nodeId: "s=CTT",
362
+ description: "Nodes named after the settings of the OPC Foundation Compliance Test Tool server project"
363
+ });
364
+ const ctt = new ctt_tree_js_1.CttFolder(namespace, root);
365
+ addVariantVariables(ctt);
366
+ addBooleanScalarAndArray(ctt);
367
+ addImageVariable(ctt);
368
+ addStructureVariables(ctt);
369
+ addAnalogItemArrays(ctt);
370
+ addArrayItems(ctt);
371
+ addHistorizingVariables(ctt);
372
+ (0, alarm_input_nodes_js_1.addAlarmInputNodes)(ctt);
373
+ return root;
374
+ }
375
+ //# sourceMappingURL=ctt_folder.js.map