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,112 @@
1
+ import { EventEmitter } from "events";
2
+ import { assert } from "node-opcua-assert";
3
+ import { NodeId } from "node-opcua-nodeid";
4
+ import { EventStuff } from "./event_stuff";
5
+ import { ClientAlarm } from "./client_alarm";
6
+
7
+ export interface ClientAlarmList {
8
+ on(eventName: "alarmChanged", handler: (alarm: ClientAlarm) => void): this;
9
+ on(eventName: "alarmDeleted", handler: (alarm: ClientAlarm) => void): this;
10
+ on(eventName: "newAlarm", handler: (alarm: ClientAlarm) => void): this;
11
+
12
+ emit(eventName: "alarmChanged", alarm: ClientAlarm): boolean;
13
+ emit(eventName: "newAlarm", alarm: ClientAlarm): boolean;
14
+ emit(eventName: "alarmDeleted", alarm: ClientAlarm): boolean;
15
+ }
16
+ // maintain a set of alarm list for a client
17
+ export class ClientAlarmList extends EventEmitter implements Iterable<ClientAlarm> {
18
+ private _map: { [key: string]: ClientAlarm } = {};
19
+
20
+ public constructor() {
21
+ super();
22
+ }
23
+
24
+ public [Symbol.iterator](): Iterator<ClientAlarm> {
25
+ let pointer = 0;
26
+ const components = Object.values(this._map);
27
+ return {
28
+ next(): IteratorResult<ClientAlarm> {
29
+ if (pointer >= components.length) {
30
+ return {
31
+ done: true,
32
+ value: components[pointer++]
33
+ };
34
+ } else {
35
+ return {
36
+ done: false,
37
+ value: components[pointer++]
38
+ };
39
+ }
40
+ }
41
+ };
42
+ }
43
+
44
+ public alarms(): ClientAlarm[] {
45
+ return Object.values(this._map);
46
+ }
47
+
48
+ public update(eventField: EventStuff): void {
49
+ // Spec says:
50
+ // Clients shall check for multiple Event Notifications for a ConditionBranch to avoid
51
+ // overwriting a new state delivered together with an older state from the Refresh
52
+ // process.
53
+
54
+ const { conditionId, eventType } = eventField;
55
+ assert(conditionId, "must have a valid conditionId ( verify that event is a acknowledgeable type");
56
+ const alarm = this.findAlarm(conditionId.value, eventType.value);
57
+
58
+ if (!alarm) {
59
+ const key = this.makeKey(conditionId.value, eventType.value);
60
+ const newAlarm = new ClientAlarm(eventField);
61
+ this._map[key] = newAlarm;
62
+ this.emit("newAlarm", newAlarm);
63
+ this.emit("alarmChanged", newAlarm);
64
+ } else {
65
+ alarm.update(eventField);
66
+ this.emit("alarmChanged", alarm);
67
+ }
68
+ }
69
+ public removeAlarm(eventField: EventStuff): void {
70
+ const { conditionId, eventType } = eventField;
71
+ const alarm = this.findAlarm(conditionId.value, eventType.value);
72
+ if (alarm) {
73
+ alarm.update(eventField);
74
+ this._removeAlarm(alarm);
75
+ }
76
+ }
77
+
78
+ public get length(): number {
79
+ return Object.keys(this._map).length;
80
+ }
81
+ public purgeUnusedAlarms(): void {
82
+ const alarms = this.alarms();
83
+ for (const alarm of alarms) {
84
+ if (!alarm.getRetain()) {
85
+ this._removeAlarm(alarm);
86
+ }
87
+ }
88
+ }
89
+
90
+ private _removeAlarm(alarm: ClientAlarm) {
91
+ this.emit("alarmDeleted", alarm);
92
+ this.deleteAlarm(alarm.conditionId, alarm.eventType);
93
+ }
94
+
95
+ private makeKey(conditionId: NodeId, eventType: NodeId) {
96
+ return conditionId.toString() + "|" + eventType.toString();
97
+ }
98
+ private findAlarm(conditionId: NodeId, eventType: NodeId): ClientAlarm | null {
99
+ const key = this.makeKey(conditionId, eventType);
100
+ const _c = this._map[key];
101
+ return _c || null;
102
+ }
103
+ private deleteAlarm(conditionId: NodeId, eventType: NodeId): boolean {
104
+ const key = this.makeKey(conditionId, eventType);
105
+ const _c = this._map[key];
106
+ if (_c) {
107
+ delete this._map[key];
108
+ return true;
109
+ }
110
+ return false;
111
+ }
112
+ }
@@ -0,0 +1,66 @@
1
+ import chalk from "chalk";
2
+ import { AttributeIds } from "node-opcua-data-model";
3
+ import { NodeId } from "node-opcua-nodeid";
4
+ import { IBasicSessionReadAsyncSimple } from "node-opcua-pseudo-session";
5
+ import { DataType, Variant, VariantLike } from "node-opcua-variant";
6
+ import { make_traceLog } from "node-opcua-debug";
7
+
8
+ const traceLog = make_traceLog("ClientAlarmTool");
9
+
10
+ /**
11
+ *
12
+ * @param session
13
+ * @param fields
14
+ * @param eventFields
15
+ */
16
+ export async function dumpEvent(session: IBasicSessionReadAsyncSimple, fields: string[], eventFields: Variant[]): Promise<void> {
17
+ async function getBrowseName(_session: IBasicSessionReadAsyncSimple, nodeId: NodeId): Promise<string> {
18
+ const dataValue = await _session.read({
19
+ attributeId: AttributeIds.BrowseName,
20
+ nodeId
21
+ });
22
+ if (dataValue.statusCode.isGood()) {
23
+ const browseName = dataValue.value.value.name!;
24
+ return browseName;
25
+ } else {
26
+ return "???";
27
+ }
28
+ }
29
+ function w(str: string, l: number): string {
30
+ return (str || "").toString().padEnd(l, " ").substring(0, l);
31
+ }
32
+ async function __dumpEvent1(_session: IBasicSessionReadAsyncSimple, _fields: any, variant: VariantLike, index: number) {
33
+ if (variant.dataType === DataType.Null) {
34
+ return;
35
+ }
36
+ if (variant.dataType === DataType.NodeId) {
37
+ const name = await getBrowseName(_session, variant.value);
38
+ traceLog(
39
+ chalk.yellow(w(name, 30), w(_fields[index], 25)),
40
+ chalk.cyan(w(DataType[variant.dataType], 10).toString()),
41
+ chalk.cyan.bold(name),
42
+ "(",
43
+ w(variant.value, 20),
44
+ ")"
45
+ );
46
+ } else {
47
+ // tslint:disable-next-line: no-console
48
+ traceLog(
49
+ chalk.yellow(w("", 30), w(_fields[index], 25)),
50
+ chalk.cyan(w(DataType[variant.dataType as number], 10).toString()),
51
+ variant.value
52
+ );
53
+ }
54
+ }
55
+
56
+ async function __dumpEvent(_session: IBasicSessionReadAsyncSimple, _fields: string[], _eventFields: Variant[]) {
57
+ let index = 0;
58
+ const promises = [];
59
+ for (const variant of _eventFields) {
60
+ promises.push(__dumpEvent1(_session, _fields, variant, index));
61
+ index++;
62
+ }
63
+ await Promise.all(promises);
64
+ }
65
+ await __dumpEvent(session, fields, eventFields);
66
+ }
@@ -0,0 +1,65 @@
1
+ import { NodeId } from "node-opcua-nodeid";
2
+ import { lowerFirstLetter } from "node-opcua-utils";
3
+ import { Variant } from "node-opcua-variant";
4
+
5
+ import { make_warningLog } from "node-opcua-debug";
6
+ const warningLog = make_warningLog(__filename);
7
+
8
+ export interface TVariant<T> extends Variant {
9
+ value: T;
10
+ }
11
+ export interface TTwoStateStatus extends TVariant<string> {
12
+ id: TVariant<boolean>;
13
+ }
14
+ export interface EventStuff {
15
+ conditionId: TVariant<NodeId>;
16
+ eventType: TVariant<NodeId>;
17
+ eventId: TVariant<Buffer>;
18
+ retain: TVariant<boolean>;
19
+ activeState: TTwoStateStatus;
20
+ ackedState: TTwoStateStatus;
21
+ confirmedState: TTwoStateStatus;
22
+ conditionName?: TVariant<string>;
23
+ }
24
+
25
+
26
+ /**
27
+ * @private
28
+ */
29
+ export function fieldsToJson(fields: string[], eventFields: Variant[], flat?: boolean): EventStuff {
30
+
31
+ function setProperty(_data: Record<string, unknown>, fieldName: string, value: Variant) {
32
+ let name: string;
33
+ if (!fieldName || value === null) {
34
+ return;
35
+ }
36
+ if (!flat) {
37
+ const f = fieldName.split(".");
38
+ if (f.length === 1) {
39
+ fieldName = lowerFirstLetter(fieldName);
40
+ _data[fieldName] = value;
41
+ } else {
42
+ for (let i = 0; i < f.length - 1; i++) {
43
+ name = lowerFirstLetter(f[i]);
44
+ _data[name] = _data[name] || {};
45
+ _data = _data[name] as Record<string, unknown>;
46
+ }
47
+ name = lowerFirstLetter(f[f.length - 1]);
48
+ _data[name] = value;
49
+ }
50
+ } else {
51
+ const name = fieldName.split(".").map(lowerFirstLetter).join(".");
52
+ _data[name] = value;
53
+ }
54
+ }
55
+ if (fields.length > eventFields.length) {
56
+ warningLog("warning fields.length !== eventFields.length", fields.length, eventFields.length);
57
+ }
58
+ const data: any = {};
59
+ for (let index = 0; index < fields.length; index++) {
60
+ const variant = eventFields[index];
61
+ setProperty(data, fields[index], variant);
62
+ }
63
+
64
+ return data;
65
+ }
@@ -0,0 +1,12 @@
1
+ import { NodeIdLike } from "node-opcua-nodeid";
2
+ import { ISessionForExtractField, extractFields, simpleBrowsePathsToString } from "node-opcua-pseudo-session";
3
+
4
+ export async function extractConditionFields(session: ISessionForExtractField, conditionNodeId: NodeIdLike): Promise<string[]> {
5
+ // conditionNodeId could be a Object of type ConditionType
6
+ // or it could be directly a ObjectType which is a subType of ConditionType
7
+ const p = await extractFields(session, conditionNodeId);
8
+ const fields1 = simpleBrowsePathsToString(p.map((a) => a.path));
9
+ // add this field which will always be added
10
+ fields1.push("ConditionId");
11
+ return fields1;
12
+ }
@@ -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";