node-opcua-alarm-condition 2.119.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 (38) hide show
  1. package/LICENSE +22 -0
  2. package/dist/acknowledge_all_conditions.d.ts +10 -0
  3. package/dist/acknowledge_all_conditions.js +173 -0
  4. package/dist/acknowledge_all_conditions.js.map +1 -0
  5. package/dist/call_condition_refresh.d.ts +3 -0
  6. package/dist/call_condition_refresh.js +46 -0
  7. package/dist/call_condition_refresh.js.map +1 -0
  8. package/dist/call_method_condition.d.ts +8 -0
  9. package/dist/call_method_condition.js +65 -0
  10. package/dist/call_method_condition.js.map +1 -0
  11. package/dist/client_alarm.d.ts +30 -0
  12. package/dist/client_alarm.js +54 -0
  13. package/dist/client_alarm.js.map +1 -0
  14. package/dist/client_alarm_list.d.ts +26 -0
  15. package/dist/client_alarm_list.js +98 -0
  16. package/dist/client_alarm_list.js.map +1 -0
  17. package/dist/client_alarm_tools_dump_event.d.ts +9 -0
  18. package/dist/client_alarm_tools_dump_event.js +60 -0
  19. package/dist/client_alarm_tools_dump_event.js.map +1 -0
  20. package/dist/event_stuff.d.ts +23 -0
  21. package/dist/event_stuff.js +48 -0
  22. package/dist/event_stuff.js.map +1 -0
  23. package/dist/extract_condition_fields.d.ts +3 -0
  24. package/dist/extract_condition_fields.js +15 -0
  25. package/dist/extract_condition_fields.js.map +1 -0
  26. package/dist/index.d.ts +8 -0
  27. package/dist/index.js +25 -0
  28. package/dist/index.js.map +1 -0
  29. package/package.json +52 -0
  30. package/source/acknowledge_all_conditions.ts +193 -0
  31. package/source/call_condition_refresh.ts +42 -0
  32. package/source/call_method_condition.ts +86 -0
  33. package/source/client_alarm.ts +73 -0
  34. package/source/client_alarm_list.ts +112 -0
  35. package/source/client_alarm_tools_dump_event.ts +66 -0
  36. package/source/event_stuff.ts +65 -0
  37. package/source/extract_condition_fields.ts +12 -0
  38. package/source/index.ts +8 -0
@@ -0,0 +1,60 @@
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.dumpEvent = void 0;
7
+ const chalk_1 = __importDefault(require("chalk"));
8
+ const node_opcua_data_model_1 = require("node-opcua-data-model");
9
+ const node_opcua_variant_1 = require("node-opcua-variant");
10
+ const node_opcua_debug_1 = require("node-opcua-debug");
11
+ const traceLog = (0, node_opcua_debug_1.make_traceLog)("ClientAlarmTool");
12
+ /**
13
+ *
14
+ * @param session
15
+ * @param fields
16
+ * @param eventFields
17
+ */
18
+ async function dumpEvent(session, fields, eventFields) {
19
+ async function getBrowseName(_session, nodeId) {
20
+ const dataValue = await _session.read({
21
+ attributeId: node_opcua_data_model_1.AttributeIds.BrowseName,
22
+ nodeId
23
+ });
24
+ if (dataValue.statusCode.isGood()) {
25
+ const browseName = dataValue.value.value.name;
26
+ return browseName;
27
+ }
28
+ else {
29
+ return "???";
30
+ }
31
+ }
32
+ function w(str, l) {
33
+ return (str || "").toString().padEnd(l, " ").substring(0, l);
34
+ }
35
+ async function __dumpEvent1(_session, _fields, variant, index) {
36
+ if (variant.dataType === node_opcua_variant_1.DataType.Null) {
37
+ return;
38
+ }
39
+ if (variant.dataType === node_opcua_variant_1.DataType.NodeId) {
40
+ const name = await getBrowseName(_session, variant.value);
41
+ traceLog(chalk_1.default.yellow(w(name, 30), w(_fields[index], 25)), chalk_1.default.cyan(w(node_opcua_variant_1.DataType[variant.dataType], 10).toString()), chalk_1.default.cyan.bold(name), "(", w(variant.value, 20), ")");
42
+ }
43
+ else {
44
+ // tslint:disable-next-line: no-console
45
+ traceLog(chalk_1.default.yellow(w("", 30), w(_fields[index], 25)), chalk_1.default.cyan(w(node_opcua_variant_1.DataType[variant.dataType], 10).toString()), variant.value);
46
+ }
47
+ }
48
+ async function __dumpEvent(_session, _fields, _eventFields) {
49
+ let index = 0;
50
+ const promises = [];
51
+ for (const variant of _eventFields) {
52
+ promises.push(__dumpEvent1(_session, _fields, variant, index));
53
+ index++;
54
+ }
55
+ await Promise.all(promises);
56
+ }
57
+ await __dumpEvent(session, fields, eventFields);
58
+ }
59
+ exports.dumpEvent = dumpEvent;
60
+ //# sourceMappingURL=client_alarm_tools_dump_event.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client_alarm_tools_dump_event.js","sourceRoot":"","sources":["../source/client_alarm_tools_dump_event.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ /// <reference types="node" />
2
+ import { NodeId } from "node-opcua-nodeid";
3
+ import { Variant } from "node-opcua-variant";
4
+ export interface TVariant<T> extends Variant {
5
+ value: T;
6
+ }
7
+ export interface TTwoStateStatus extends TVariant<string> {
8
+ id: TVariant<boolean>;
9
+ }
10
+ export interface EventStuff {
11
+ conditionId: TVariant<NodeId>;
12
+ eventType: TVariant<NodeId>;
13
+ eventId: TVariant<Buffer>;
14
+ retain: TVariant<boolean>;
15
+ activeState: TTwoStateStatus;
16
+ ackedState: TTwoStateStatus;
17
+ confirmedState: TTwoStateStatus;
18
+ conditionName?: TVariant<string>;
19
+ }
20
+ /**
21
+ * @private
22
+ */
23
+ export declare function fieldsToJson(fields: string[], eventFields: Variant[], flat?: boolean): EventStuff;
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.fieldsToJson = void 0;
4
+ const node_opcua_utils_1 = require("node-opcua-utils");
5
+ const node_opcua_debug_1 = require("node-opcua-debug");
6
+ const warningLog = (0, node_opcua_debug_1.make_warningLog)(__filename);
7
+ /**
8
+ * @private
9
+ */
10
+ function fieldsToJson(fields, eventFields, flat) {
11
+ function setProperty(_data, fieldName, value) {
12
+ let name;
13
+ if (!fieldName || value === null) {
14
+ return;
15
+ }
16
+ if (!flat) {
17
+ const f = fieldName.split(".");
18
+ if (f.length === 1) {
19
+ fieldName = (0, node_opcua_utils_1.lowerFirstLetter)(fieldName);
20
+ _data[fieldName] = value;
21
+ }
22
+ else {
23
+ for (let i = 0; i < f.length - 1; i++) {
24
+ name = (0, node_opcua_utils_1.lowerFirstLetter)(f[i]);
25
+ _data[name] = _data[name] || {};
26
+ _data = _data[name];
27
+ }
28
+ name = (0, node_opcua_utils_1.lowerFirstLetter)(f[f.length - 1]);
29
+ _data[name] = value;
30
+ }
31
+ }
32
+ else {
33
+ const name = fieldName.split(".").map(node_opcua_utils_1.lowerFirstLetter).join(".");
34
+ _data[name] = value;
35
+ }
36
+ }
37
+ if (fields.length > eventFields.length) {
38
+ warningLog("warning fields.length !== eventFields.length", fields.length, eventFields.length);
39
+ }
40
+ const data = {};
41
+ for (let index = 0; index < fields.length; index++) {
42
+ const variant = eventFields[index];
43
+ setProperty(data, fields[index], variant);
44
+ }
45
+ return data;
46
+ }
47
+ exports.fieldsToJson = fieldsToJson;
48
+ //# sourceMappingURL=event_stuff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event_stuff.js","sourceRoot":"","sources":["../source/event_stuff.ts"],"names":[],"mappings":";;;AACA,uDAAoD;AAGpD,uDAAmD;AACnD,MAAM,UAAU,GAAG,IAAA,kCAAe,EAAC,UAAU,CAAC,CAAC;AAoB/C;;GAEG;AACH,SAAgB,YAAY,CAAC,MAAgB,EAAE,WAAsB,EAAE,IAAc;IAEjF,SAAS,WAAW,CAAC,KAA8B,EAAE,SAAiB,EAAE,KAAc;QAClF,IAAI,IAAY,CAAC;QACjB,IAAI,CAAC,SAAS,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YAC/B,OAAO;QACX,CAAC;QACD,IAAI,CAAC,IAAI,EAAE,CAAC;YACR,MAAM,CAAC,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAC/B,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACjB,SAAS,GAAG,IAAA,mCAAgB,EAAC,SAAS,CAAC,CAAC;gBACxC,KAAK,CAAC,SAAS,CAAC,GAAG,KAAK,CAAC;YAC7B,CAAC;iBAAM,CAAC;gBACJ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;oBACpC,IAAI,GAAG,IAAA,mCAAgB,EAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;oBAC9B,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;oBAChC,KAAK,GAAG,KAAK,CAAC,IAAI,CAA4B,CAAC;gBACnD,CAAC;gBACD,IAAI,GAAG,IAAA,mCAAgB,EAAC,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;gBACzC,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;YACxB,CAAC;QACL,CAAC;aAAM,CAAC;YACJ,MAAM,IAAI,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,mCAAgB,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAClE,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;QACxB,CAAC;IACL,CAAC;IACD,IAAI,MAAM,CAAC,MAAM,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC;QACrC,UAAU,CAAC,+CAA+C,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACnG,CAAC;IACD,MAAM,IAAI,GAAQ,EAAE,CAAC;IACrB,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC;QACjD,MAAM,OAAO,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;QACnC,WAAW,CAAC,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,CAAC;IAC9C,CAAC;IAED,OAAO,IAAI,CAAC;AAChB,CAAC;AApCD,oCAoCC"}
@@ -0,0 +1,3 @@
1
+ import { NodeIdLike } from "node-opcua-nodeid";
2
+ import { ISessionForExtractField } from "node-opcua-pseudo-session";
3
+ export declare function extractConditionFields(session: ISessionForExtractField, conditionNodeId: NodeIdLike): Promise<string[]>;
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.extractConditionFields = void 0;
4
+ const node_opcua_pseudo_session_1 = require("node-opcua-pseudo-session");
5
+ async function extractConditionFields(session, conditionNodeId) {
6
+ // conditionNodeId could be a Object of type ConditionType
7
+ // or it could be directly a ObjectType which is a subType of ConditionType
8
+ const p = await (0, node_opcua_pseudo_session_1.extractFields)(session, conditionNodeId);
9
+ const fields1 = (0, node_opcua_pseudo_session_1.simpleBrowsePathsToString)(p.map((a) => a.path));
10
+ // add this field which will always be added
11
+ fields1.push("ConditionId");
12
+ return fields1;
13
+ }
14
+ exports.extractConditionFields = extractConditionFields;
15
+ //# sourceMappingURL=extract_condition_fields.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extract_condition_fields.js","sourceRoot":"","sources":["../source/extract_condition_fields.ts"],"names":[],"mappings":";;;AACA,yEAA8G;AAEvG,KAAK,UAAU,sBAAsB,CAAC,OAAgC,EAAE,eAA2B;IACtG,0DAA0D;IAC1D,2EAA2E;IAC3E,MAAM,CAAC,GAAG,MAAM,IAAA,yCAAa,EAAC,OAAO,EAAE,eAAe,CAAC,CAAC;IACxD,MAAM,OAAO,GAAG,IAAA,qDAAyB,EAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IAChE,4CAA4C;IAC5C,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAC5B,OAAO,OAAO,CAAC;AACnB,CAAC;AARD,wDAQC"}
@@ -0,0 +1,8 @@
1
+ export * from "./acknowledge_all_conditions";
2
+ export * from "./call_condition_refresh";
3
+ export * from "./call_method_condition";
4
+ export * from "./client_alarm_list";
5
+ export * from "./client_alarm_tools_dump_event";
6
+ export * from "./client_alarm";
7
+ export * from "./event_stuff";
8
+ export * from "./extract_condition_fields";
package/dist/index.js ADDED
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./acknowledge_all_conditions"), exports);
18
+ __exportStar(require("./call_condition_refresh"), exports);
19
+ __exportStar(require("./call_method_condition"), exports);
20
+ __exportStar(require("./client_alarm_list"), exports);
21
+ __exportStar(require("./client_alarm_tools_dump_event"), exports);
22
+ __exportStar(require("./client_alarm"), exports);
23
+ __exportStar(require("./event_stuff"), exports);
24
+ __exportStar(require("./extract_condition_fields"), exports);
25
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../source/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,+DAA6C;AAC7C,2DAAyC;AACzC,0DAAwC;AACxC,sDAAoC;AACpC,kEAAgD;AAChD,iDAA+B;AAC/B,gDAA8B;AAC9B,6DAA2C"}
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "node-opcua-alarm-condition",
3
+ "version": "2.119.0",
4
+ "description": "pure nodejs OPCUA SDK - module pseudo-session",
5
+ "scripts": {
6
+ "clean": "npx rimraf node_modules dist *.tsbuildinfo",
7
+ "build": "tsc -b",
8
+ "lint": "eslint source/**/*.ts",
9
+ "test": "echo mocha test"
10
+ },
11
+ "main": "./dist/index.js",
12
+ "types": "./dist/index.d.ts",
13
+ "dependencies": {
14
+ "node-opcua-assert": "2.105.0",
15
+ "node-opcua-basic-types": "2.119.0",
16
+ "node-opcua-constants": "2.114.0",
17
+ "node-opcua-data-model": "2.119.0",
18
+ "node-opcua-debug": "2.118.0",
19
+ "node-opcua-nodeid": "2.118.0",
20
+ "node-opcua-pseudo-session": "2.119.0",
21
+ "node-opcua-service-browse": "2.119.0",
22
+ "node-opcua-service-filter": "2.119.0",
23
+ "node-opcua-service-read": "2.119.0",
24
+ "node-opcua-service-subscription": "2.119.0",
25
+ "node-opcua-service-translate-browse-path": "2.119.0",
26
+ "node-opcua-status-code": "2.117.0",
27
+ "node-opcua-types": "2.119.0",
28
+ "node-opcua-utils": "2.117.0",
29
+ "node-opcua-variant": "2.119.0",
30
+ "thenify": "^3.3.1"
31
+ },
32
+ "author": "Etienne Rossignon",
33
+ "license": "MIT",
34
+ "repository": {
35
+ "type": "git",
36
+ "url": "git://github.com/node-opcua/node-opcua.git"
37
+ },
38
+ "keywords": [
39
+ "OPCUA",
40
+ "opcua",
41
+ "m2m",
42
+ "iot",
43
+ "opc ua",
44
+ "internet of things"
45
+ ],
46
+ "homepage": "http://node-opcua.github.io/",
47
+ "gitHead": "f985d1ada89600c33696c541e6ba3c78a1a7f340",
48
+ "files": [
49
+ "dist",
50
+ "source"
51
+ ]
52
+ }
@@ -0,0 +1,193 @@
1
+ import { resolveNodeId } from "node-opcua-nodeid";
2
+ import { constructEventFilter } from "node-opcua-service-filter";
3
+ import { AttributeIds, ReadValueIdOptions, TimestampsToReturn } from "node-opcua-service-read";
4
+ import { CreateSubscriptionRequestOptions, MonitoringParametersOptions } from "node-opcua-service-subscription";
5
+ import { StatusCode, StatusCodes } from "node-opcua-status-code";
6
+ import { DataType, Variant } from "node-opcua-variant";
7
+ import { checkDebugFlag, make_debugLog, make_errorLog } from "node-opcua-debug";
8
+
9
+ import { IBasicSessionAsync } from "node-opcua-pseudo-session";
10
+ import { IBasicSessionEx } from "node-opcua-pseudo-session";
11
+
12
+ import { EventStuff, fieldsToJson } from "./event_stuff";
13
+ import { extractConditionFields } from "./extract_condition_fields";
14
+ import { acknowledgeCondition, confirmCondition } from "./call_method_condition";
15
+ import { callConditionRefresh } from "./call_condition_refresh";
16
+
17
+ const doDebug = checkDebugFlag(__filename);
18
+ const debugLog = make_debugLog(__filename);
19
+ const errorLog = make_errorLog(__filename);
20
+
21
+ /**
22
+ *
23
+ * @param session
24
+ * @param eventStuff
25
+ * @param comment
26
+ */
27
+
28
+ async function acknowledgeConditionEV(session: IBasicSessionAsync, eventStuff: EventStuff, comment: string): Promise<StatusCode> {
29
+ const conditionId = eventStuff.conditionId?.value;
30
+ const eventId = eventStuff.eventId?.value;
31
+ try {
32
+ return await acknowledgeCondition(session, conditionId, eventId, comment);
33
+ } catch (err) {
34
+ errorLog(`conditionId: ${conditionId?.toString()}`);
35
+ errorLog("Acknowledging Condition has failed !", err);
36
+ return StatusCodes.BadInternalError;
37
+ }
38
+ }
39
+
40
+ async function confirmConditionEV(session: IBasicSessionAsync, eventStuff: EventStuff, comment: string): Promise<StatusCode> {
41
+ const conditionId = eventStuff.conditionId?.value;
42
+ const eventId = eventStuff.eventId?.value;
43
+ try {
44
+ return await confirmCondition(session, conditionId, eventId, comment);
45
+ } catch (err) {
46
+ errorLog(`conditionId: ${conditionId?.toString()}`);
47
+ errorLog("Confirming Condition has failed !", err);
48
+ return StatusCodes.BadInternalError;
49
+ }
50
+ }
51
+
52
+ export type FindActiveConditions = () => Promise<EventStuff[]>;
53
+
54
+ /**
55
+ * Enumerate all events
56
+ * @param session
57
+ */
58
+ export async function findActiveConditions(session: IBasicSessionEx): Promise<EventStuff[]> {
59
+ const request: CreateSubscriptionRequestOptions = {
60
+ maxNotificationsPerPublish: 10000,
61
+ priority: 6,
62
+ publishingEnabled: true,
63
+ requestedLifetimeCount: 1000,
64
+ requestedMaxKeepAliveCount: 100,
65
+ requestedPublishingInterval: 100
66
+ };
67
+
68
+ const subscription = await session.createSubscription2(request);
69
+
70
+ const itemToMonitor: ReadValueIdOptions = {
71
+ attributeId: AttributeIds.EventNotifier,
72
+ nodeId: resolveNodeId("Server") // i=2253session
73
+ };
74
+
75
+ const fields = await extractConditionFields(session, "AcknowledgeableConditionType");
76
+
77
+ // note: we may want to have this select clause
78
+ // Or(OfType("AcknowledgeableConditionType"), OfType("RefreshStartEventType"), OfType("RefreshEndEventType"))
79
+ const eventFilter = constructEventFilter(fields);
80
+
81
+ const monitoringParameters: MonitoringParametersOptions = {
82
+ discardOldest: false,
83
+ filter: eventFilter,
84
+ queueSize: 100,
85
+ samplingInterval: 0
86
+ };
87
+
88
+ const event_monitoringItem = await subscription.monitor(itemToMonitor, monitoringParameters, TimestampsToReturn.Both);
89
+
90
+ const acknowledgeableConditions: EventStuff[] = [];
91
+
92
+ let refreshStartEventHasBeenReceived = false;
93
+ let RefreshEndEventHasBeenReceived = false;
94
+
95
+ const RefreshStartEventType = resolveNodeId("RefreshStartEventType").toString();
96
+ const RefreshEndEventType = resolveNodeId("RefreshEndEventType").toString();
97
+
98
+ await new Promise<void>((resolve, reject) => {
99
+ // now create a event monitored Item
100
+ event_monitoringItem.on("changed", (_eventFields: any) => {
101
+ const eventFields = _eventFields as Variant[];
102
+
103
+ try {
104
+ if (RefreshEndEventHasBeenReceived) {
105
+ return;
106
+ }
107
+
108
+ // dumpEvent(session, fields, eventFields);
109
+ const pojo = fieldsToJson(fields, eventFields) as any;
110
+
111
+ // make sure we only start recording event after the RefreshStartEvent has been received
112
+ if (!refreshStartEventHasBeenReceived) {
113
+ if (pojo.eventType.value.toString() === RefreshStartEventType) {
114
+ refreshStartEventHasBeenReceived = true;
115
+ }
116
+ return;
117
+ }
118
+ if (pojo.eventType.value.toString() === RefreshEndEventType) {
119
+ RefreshEndEventHasBeenReceived = true;
120
+ resolve();
121
+ return;
122
+ }
123
+ if (!pojo.conditionId.value) {
124
+ // not a Acknowledgeable condition
125
+ return;
126
+ }
127
+
128
+ if (pojo.ackedState.id.dataType === DataType.Boolean) {
129
+ acknowledgeableConditions.push(pojo as EventStuff);
130
+ }
131
+ } catch (err) {
132
+ errorLog("Error !!", err);
133
+ }
134
+ });
135
+ // async call without waiting !
136
+ try {
137
+ callConditionRefresh(session, subscription.subscriptionId);
138
+ } catch (err) {
139
+ // it is possible that server do not implement conditionRefresh ...
140
+ errorLog("Server may not implement conditionRefresh", (err as Error).message);
141
+ }
142
+ });
143
+
144
+ // now shut down subscription
145
+ await subscription.terminate();
146
+
147
+ return acknowledgeableConditions;
148
+ }
149
+
150
+ // let conditions = await findActiveConditions(session);
151
+ // if (conditions.length === 0) {
152
+ // debugLog("Warning: cannot find conditions ");
153
+ // }
154
+
155
+ export async function acknowledgeAllConditions(session: IBasicSessionEx, message: string): Promise<void> {
156
+ try {
157
+ let conditions: EventStuff[] = await findActiveConditions(session);
158
+ // filter acknowledgeable conditions (no acked yet)
159
+ conditions = conditions.filter((pojo) => pojo.ackedState.id.value === false);
160
+
161
+ const promises: Array<Promise<StatusCode>> = [];
162
+ for (const eventStuff of conditions) {
163
+ promises.push(acknowledgeConditionEV(session, eventStuff, message));
164
+ }
165
+ const result = await Promise.all(promises);
166
+ // istanbul ignore next
167
+ if (doDebug) {
168
+ debugLog("Acked all results: ", result.map((e) => e.toString()).join(" "));
169
+ }
170
+ } catch (err) {
171
+ errorLog("Error", err);
172
+ }
173
+ }
174
+
175
+ export async function confirmAllConditions(session: IBasicSessionEx, message: string): Promise<void> {
176
+ try {
177
+ let conditions: EventStuff[] = await findActiveConditions(session);
178
+ // filter acknowledgeable conditions (no acked yet)
179
+ conditions = conditions.filter((pojo) => pojo.confirmedState.id.value === false);
180
+
181
+ const promises: Array<Promise<any>> = [];
182
+ for (const eventStuff of conditions) {
183
+ promises.push(confirmConditionEV(session, eventStuff, message));
184
+ }
185
+ const result = await Promise.all(promises);
186
+ // istanbul ignore next
187
+ if (doDebug) {
188
+ debugLog("Confirm all results: ", result.map((e) => e.toString()).join(" "));
189
+ }
190
+ } catch (err) {
191
+ errorLog("Error", err);
192
+ }
193
+ }
@@ -0,0 +1,42 @@
1
+ import assert from "node-opcua-assert";
2
+ import { DataType, StatusCode, StatusCodes } from "node-opcua-basic-types";
3
+ import { resolveNodeId } from "node-opcua-nodeid";
4
+ import { makeBrowsePath } from "node-opcua-service-translate-browse-path";
5
+ import { CallMethodRequest } from "node-opcua-types";
6
+ import { Variant } from "node-opcua-variant";
7
+ import { make_debugLog, make_warningLog } from "node-opcua-debug";
8
+ import { IBasicSessionAsync, CallMethodRequestLike } from "node-opcua-pseudo-session";
9
+
10
+ const doDebug = false;
11
+ const debugLog = make_debugLog("A&E");
12
+ const warningLog = make_warningLog("A&E");
13
+
14
+ export async function callConditionRefresh(session: IBasicSessionAsync, subscriptionId: number): Promise<StatusCode> {
15
+ assert(isFinite(subscriptionId), "May be subscription is not yet initialized");
16
+ const conditionTypeNodeId = resolveNodeId("ConditionType");
17
+ let conditionRefreshId = resolveNodeId("ConditionType_ConditionRefresh");
18
+ // find conditionRefreshId
19
+ const browsePath = makeBrowsePath(conditionTypeNodeId, ".ConditionRefresh");
20
+ const translateResult = await session.translateBrowsePath(browsePath);
21
+
22
+ // istanbul ignore next
23
+ if (translateResult.targets && translateResult.targets.length > 0) {
24
+ conditionRefreshId = translateResult.targets[0].targetId;
25
+ } else {
26
+ // cannot find conditionRefreshId
27
+ return StatusCodes.BadInternalError;
28
+ }
29
+ const methodToCall: CallMethodRequestLike = {
30
+ inputArguments: [new Variant({ dataType: DataType.UInt32, value: subscriptionId })],
31
+ methodId: conditionRefreshId,
32
+ objectId: conditionTypeNodeId
33
+ };
34
+
35
+ doDebug && debugLog("Calling method ", new CallMethodRequest(methodToCall).toString());
36
+ const callResult = await session.call(methodToCall);
37
+ // istanbul ignore next
38
+ if (callResult.statusCode.isNotGood()) {
39
+ warningLog(new CallMethodRequest(methodToCall).toString());
40
+ }
41
+ return callResult.statusCode;
42
+ }
@@ -0,0 +1,86 @@
1
+ import assert from "node-opcua-assert";
2
+ import { LocalizedText, LocalizedTextLike } from "node-opcua-data-model";
3
+ import { NodeId, NodeIdLike, coerceNodeId, resolveNodeId } from "node-opcua-nodeid";
4
+ import { StatusCode, StatusCodes } from "node-opcua-status-code";
5
+ import { CallMethodRequest } from "node-opcua-types";
6
+ import { Variant } from "node-opcua-variant";
7
+ import { IBasicSessionAsync, findMethodId } from "node-opcua-pseudo-session";
8
+ import { MethodIds } from "node-opcua-constants";
9
+
10
+
11
+
12
+
13
+ export async function callMethodCondition(
14
+ session: IBasicSessionAsync,
15
+ methodName: string,
16
+ conditionId: NodeIdLike,
17
+ eventId: Buffer,
18
+ comment: LocalizedTextLike,
19
+
20
+ ): Promise<StatusCode>
21
+ {
22
+ conditionId = coerceNodeId(conditionId);
23
+ assert(conditionId instanceof NodeId);
24
+ assert(eventId instanceof Buffer);
25
+ assert(typeof comment === "string" || comment instanceof LocalizedText);
26
+
27
+ comment = LocalizedText.coerce(comment) || new LocalizedText();
28
+ const r = await findMethodId(session, conditionId, methodName);
29
+
30
+ let methodId = r.methodId;
31
+ if (!methodId) {
32
+ // https://reference.opcfoundation.org/Core/Part9/v104/docs/5.7.3#_Ref224987672
33
+ // The Acknowledge Method is used to acknowledge an Event Notification for a Condition instance
34
+ // state where AckedState is False. Normally, the NodeId of the object instance is passed as the
35
+ // ObjectId to the Call Service. However, some Servers do not expose Condition instances in the AddressSpace.
36
+ // Therefore, Servers shall allow Clients to call the Acknowledge Method by specifying ConditionId as the ObjectId.
37
+ // The Method cannot be called with an ObjectId of the AcknowledgeableConditionType Node.
38
+ //
39
+ // The Confirm Method is used to confirm an Event Notifications for a Condition instance state where ConfirmedState is False.
40
+
41
+ switch (methodName) {
42
+ case "Acknowledge":
43
+ methodId = resolveNodeId(MethodIds.AcknowledgeableConditionType_Acknowledge);
44
+ break;
45
+ case "Confirm":
46
+ methodId = resolveNodeId(MethodIds.AcknowledgeableConditionType_Confirm);
47
+ break;
48
+ default:
49
+ return StatusCodes.BadNodeIdUnknown;
50
+ }
51
+ }
52
+ const methodToCalls = [];
53
+
54
+ methodToCalls.push(
55
+ new CallMethodRequest({
56
+ inputArguments: [
57
+ /* eventId */ new Variant({ dataType: "ByteString", value: eventId }),
58
+ /* comment */ new Variant({ dataType: "LocalizedText", value: comment })
59
+ ],
60
+ methodId,
61
+ objectId: conditionId
62
+ })
63
+ );
64
+
65
+ const results = await session.call(methodToCalls);
66
+ const statusCode = results![0].statusCode;
67
+ return statusCode;
68
+ }
69
+
70
+
71
+ export async function acknowledgeCondition(
72
+ session: IBasicSessionAsync,
73
+ conditionId: NodeIdLike,
74
+ eventId: Buffer,
75
+ comment: LocalizedTextLike
76
+ ): Promise<StatusCode> {
77
+ return await callMethodCondition(session, "Acknowledge", conditionId, eventId, comment);
78
+ }
79
+ export async function confirmCondition(
80
+ session: IBasicSessionAsync,
81
+ conditionId: NodeIdLike,
82
+ eventId: Buffer,
83
+ comment: LocalizedTextLike
84
+ ): Promise<StatusCode> {
85
+ return await callMethodCondition(session, "Confirm", conditionId, eventId, comment);
86
+ }
@@ -0,0 +1,73 @@
1
+ import { EventEmitter } from "events";
2
+ import { assert } from "node-opcua-assert";
3
+ import { NodeId, resolveNodeId } from "node-opcua-nodeid";
4
+ import { StatusCode } from "node-opcua-status-code";
5
+ import { DataType, Variant } from "node-opcua-variant";
6
+ import { IBasicSessionAsync} from "node-opcua-pseudo-session";
7
+ import { EventStuff} from "./event_stuff";
8
+ import { acknowledgeCondition, confirmCondition } from "./call_method_condition";
9
+
10
+
11
+
12
+ export interface ClientAlarm {
13
+ conditionId: NodeId;
14
+ eventType: NodeId;
15
+ fields: EventStuff;
16
+ on(eventName: "changed", eventHandler: () => void): this;
17
+ acknowledge(session: IBasicSessionAsync, comment: string): Promise<StatusCode>;
18
+ confirm(session: IBasicSessionAsync, comment: string): Promise<StatusCode>;
19
+ getField(fieldName: string): Variant | null;
20
+ }
21
+
22
+ /**
23
+ * describes a OPCUA Alarm as seen in the client side
24
+ */
25
+ export class ClientAlarm extends EventEmitter {
26
+ public conditionId: NodeId;
27
+ public eventType: NodeId;
28
+ public eventId: Buffer;
29
+ public fields: EventStuff;
30
+
31
+ public constructor(eventFields: EventStuff) {
32
+ super();
33
+ this.conditionId = resolveNodeId(eventFields.conditionId.value);
34
+ this.eventType = resolveNodeId(eventFields.eventType.value);
35
+ this.eventId = eventFields.eventId.value;
36
+ this.fields = eventFields;
37
+ this.update(eventFields);
38
+ }
39
+ public async acknowledge(session: IBasicSessionAsync, comment: string): Promise<StatusCode> {
40
+ return await acknowledgeCondition(session, this.conditionId, this.eventId, comment);
41
+ }
42
+ public async confirm(session: IBasicSessionAsync, comment: string): Promise<StatusCode> {
43
+ return await confirmCondition(session, this.conditionId, this.eventId, comment);
44
+ }
45
+ public update(eventFields: EventStuff): void {
46
+ assert(this.conditionId.toString() === resolveNodeId(eventFields.conditionId.value).toString());
47
+ assert(this.eventType.toString() === resolveNodeId(eventFields.eventType.value).toString());
48
+ this.eventId = eventFields.eventId.value;
49
+ this.fields = eventFields;
50
+ }
51
+ public getRetain(): boolean {
52
+ return this.fields.retain.value;
53
+ }
54
+ public toString(): string {
55
+ return (
56
+ this.constructor.name +
57
+ ": " +
58
+ this.conditionId.toString() +
59
+ " " +
60
+ this.eventType.toString() +
61
+ " " +
62
+ Object.entries(this.fields)
63
+ .filter(([key, value]) => value.dataType !== DataType.Null)
64
+ .map(([key, value]) => key.padEnd(30) + "=" + value.toString())
65
+ .join("\n") +
66
+ "\n\n"
67
+ );
68
+ }
69
+
70
+ public getField(fieldName: string): Variant | null {
71
+ return (this.fields as any)[fieldName] || null;
72
+ }
73
+ }