@vitormnm/node-red-simple-opcua 1.0.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 (32) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +128 -0
  3. package/client/lib/opcua-client-browser.js +291 -0
  4. package/client/lib/opcua-client-read-service.js +16 -0
  5. package/client/lib/opcua-client-subscription-id-service.js +25 -0
  6. package/client/lib/opcua-client-subscription-service.js +171 -0
  7. package/client/lib/opcua-client-write-service.js +53 -0
  8. package/client/opcua-client-config.html +80 -0
  9. package/client/opcua-client-config.js +159 -0
  10. package/client/opcua-client-utils.js +320 -0
  11. package/client/opcua-client.html +1225 -0
  12. package/client/opcua-client.js +380 -0
  13. package/object.json +65 -0
  14. package/package.json +38 -0
  15. package/resources/editorClient.PNG +0 -0
  16. package/resources/editorServer.PNG +0 -0
  17. package/server/lib/opcua-address-space-alarm.js +341 -0
  18. package/server/lib/opcua-address-space-builder.js +1456 -0
  19. package/server/lib/opcua-config.js +543 -0
  20. package/server/lib/opcua-constants.js +106 -0
  21. package/server/lib/opcua-server-events-child.js +140 -0
  22. package/server/lib/opcua-server-methods.js +198 -0
  23. package/server/lib/opcua-server-runtime-child.js +729 -0
  24. package/server/lib/opcua-server-runtime.js +311 -0
  25. package/server/lib/opcua-server-status-child.js +188 -0
  26. package/server/lib/server-node-utils.js +16 -0
  27. package/server/opcua-server-io.html +347 -0
  28. package/server/opcua-server-io.js +463 -0
  29. package/server/opcua-server-registry.js +270 -0
  30. package/server/opcua-server.css +265 -0
  31. package/server/opcua-server.html +1548 -0
  32. package/server/opcua-server.js +143 -0
@@ -0,0 +1,341 @@
1
+ const {
2
+ StatusCodes,
3
+ Variant,
4
+ DataType
5
+ } = require("./opcua-constants");
6
+
7
+ class OpcUaAddressSpaceAlarm {
8
+
9
+ constructor(options) {
10
+ this.namespace = options.namespace;
11
+ this.node = options.node;
12
+ this.serverName = options.registry;
13
+ this.registry = options.registry;
14
+ this.alarmTypesByNamespace = new Map();
15
+ }
16
+
17
+ emitTagAccess(operation, details) {
18
+ this.registry.emitTagAccess({
19
+ operation,
20
+ serverId: this.node.id,
21
+ serverNodeName: this.node.name || "",
22
+ serverName: this.serverName,
23
+ timestamp: new Date().toISOString(),
24
+ path: details.path,
25
+ nodeID: details.nodeID,
26
+ browseName: details.browseName,
27
+ dataType: details.dataType,
28
+ value: details.value
29
+ });
30
+ }
31
+
32
+ createAlarm(namespace, browseName, parentNode, inputNode, conditionName, nodeId, sourceName, alarmConfig) {
33
+ try {
34
+ const type = alarmConfig.type;
35
+ let alarmNode = null;
36
+ const alarmTypes = this.ensureNamespaceTypes(namespace);
37
+
38
+ const config = {
39
+ browseName: browseName,
40
+ componentOf: parentNode,
41
+ inputNode: inputNode,
42
+ conditionSource: parentNode,
43
+ conditionName: conditionName,
44
+ normalState: false,
45
+ nodeId: nodeId,
46
+ description: alarmConfig.description || "",
47
+ namespace: namespace,
48
+ optionals: [
49
+ "ConfirmedState",
50
+ "Confirm"
51
+ ]
52
+ };
53
+
54
+ if (type === "digitalAlarm") {
55
+ alarmNode = namespace.instantiateAlarmCondition(alarmTypes.digitalAlarmType, config);
56
+ }
57
+
58
+ if (type === "levelAlarm") {
59
+ alarmNode = namespace.instantiateAlarmCondition(alarmTypes.levelAlarmType, config);
60
+
61
+ alarmNode.getPropertyByName("lowLowLimit")
62
+ .setValueFromSource({
63
+ dataType: DataType.Int32,
64
+ value: alarmConfig.lowLowLimit
65
+ });
66
+
67
+ alarmNode.getPropertyByName("lowLimit")
68
+ .setValueFromSource({
69
+ dataType: DataType.Int32,
70
+ value: alarmConfig.lowLimit
71
+ });
72
+
73
+ alarmNode.getPropertyByName("highHighLimit")
74
+ .setValueFromSource({
75
+ dataType: DataType.Int32,
76
+ value: alarmConfig.highHighLimit
77
+ });
78
+
79
+ alarmNode.getPropertyByName("highLimit")
80
+ .setValueFromSource({
81
+ dataType: DataType.Int32,
82
+ value: alarmConfig.highLimit
83
+ });
84
+ }
85
+
86
+ alarmNode.getPropertyByName("enabled")
87
+ .setValueFromSource({
88
+ dataType: DataType.Boolean,
89
+ value: alarmConfig.enabled
90
+ });
91
+
92
+ alarmNode.sourceName.setValueFromSource({
93
+ dataType: DataType.String,
94
+ value: sourceName
95
+ });
96
+
97
+ return alarmNode;
98
+ } catch (error) {
99
+ console.error("createAlarm");
100
+ console.error(error);
101
+ }
102
+ }
103
+
104
+ checkAlarm(alarm, variableValue) {
105
+ if (alarm) {
106
+ const alarmConfig = alarm.alarmConfig;
107
+ const type = alarmConfig.type;
108
+
109
+ if (type === "levelAlarm") {
110
+ this.levelAlarm(alarm, variableValue);
111
+ }
112
+ if (type === "digitalAlarm") {
113
+ this.digitalAlarm(alarm, variableValue);
114
+ }
115
+ }
116
+ }
117
+
118
+ levelAlarm(alarm, variableValue) {
119
+ const alarmNode = alarm.node;
120
+ const alarmConfig = alarm.alarmConfig;
121
+
122
+ const isActive = alarmNode.activeState.id.readValue().value.value;
123
+ const highHighSp = alarmNode.getPropertyByName("highHighLimit").readValue().value.value;
124
+ const highSp = alarmNode.getPropertyByName("highLimit").readValue().value.value;
125
+ const lowSp = alarmNode.getPropertyByName("lowLimit").readValue().value.value;
126
+ const lowLowSp = alarmNode.getPropertyByName("lowLowLimit").readValue().value.value;
127
+ const enabled = alarmNode.getPropertyByName("enabled").readValue().value.value;
128
+ let lastMessage = null;
129
+ let message = null;
130
+
131
+ if (variableValue >= highHighSp && enabled) {
132
+ message = alarmConfig.highHighMessage + ": " + variableValue;
133
+ this.raiseAlarm(alarmNode, message, alarmConfig.severity);
134
+ lastMessage = message;
135
+ } else if (variableValue >= highSp && enabled) {
136
+ message = alarmConfig.highMessage + ": " + variableValue;
137
+ this.raiseAlarm(alarmNode, message, alarmConfig.severity);
138
+ lastMessage = message;
139
+ } else if (variableValue <= lowLowSp && enabled) {
140
+ message = alarmConfig.lowLowMessage + ": " + variableValue;
141
+ this.raiseAlarm(alarmNode, message, alarmConfig.severity);
142
+ lastMessage = message;
143
+ } else if (variableValue <= lowSp && enabled) {
144
+ message = alarmConfig.lowMessage + ": " + variableValue;
145
+ this.raiseAlarm(alarmNode, message, alarmConfig.severity);
146
+ lastMessage = message;
147
+ } else if (isActive) {
148
+ this.clearAlarm(alarmNode, lastMessage, alarmConfig.severity);
149
+ }
150
+
151
+ this.alarmMethods(alarmNode);
152
+ }
153
+
154
+ digitalAlarm(alarm, variableValue) {
155
+ const alarmNode = alarm.node;
156
+ const alarmConfig = alarm.alarmConfig;
157
+ const enabled = alarmNode.getPropertyByName("enabled").readValue().value.value;
158
+
159
+ if (variableValue && enabled) {
160
+ this.raiseAlarm(alarmNode, alarmConfig.digitalMessage, alarmConfig.severity);
161
+ } else {
162
+ this.clearAlarm(alarmNode, alarmConfig.digitalMessage, alarmConfig.severity);
163
+ }
164
+
165
+ this.alarmMethods(alarmNode);
166
+ }
167
+
168
+ alarmMethods(alarmNode) {
169
+ alarmNode.confirm.bindMethod((inputArguments, context, callback) => {
170
+ const alarm = context.object;
171
+ const severity = alarm.severity.readValue().value.value;
172
+ const message = alarm.message.readValue().value.value.text;
173
+ alarm.confirmedState.setValue(true);
174
+
175
+ const isAcked = alarm.ackedState.id.readValue().value.value;
176
+
177
+ if (isAcked) {
178
+ alarm.raiseNewCondition({
179
+ message: message,
180
+ severity: severity,
181
+ retain: false
182
+ });
183
+
184
+ this.raiseNewConditionAlarm(alarm, message, severity, false);
185
+ } else {
186
+ this.raiseNewConditionAlarm(alarm, message, severity, true);
187
+ }
188
+
189
+ callback(null, {
190
+ statusCode: StatusCodes.Good,
191
+ outputArguments: []
192
+ });
193
+ });
194
+
195
+ alarmNode.acknowledge.bindMethod((inputArguments, context, callback) => {
196
+ const alarm = context.object;
197
+ const severity = alarm.severity.readValue().value.value;
198
+ const message = alarm.message.readValue().value.value.text;
199
+ alarm.ackedState.setValue(true);
200
+ alarm.confirmedState.setValue(false);
201
+
202
+ this.raiseNewConditionAlarm(alarm, message, severity, true);
203
+
204
+ callback(null, {
205
+ statusCode: StatusCodes.Good,
206
+ outputArguments: []
207
+ });
208
+ });
209
+
210
+ alarmNode.addComment.bindMethod((inputArguments, context, callback) => {
211
+ const comment = inputArguments[1].value;
212
+ const alarm = context.object;
213
+
214
+ alarm.comment.setValueFromSource({
215
+ value: comment,
216
+ dataType: DataType.LocalizedText
217
+ });
218
+ callback(null, {
219
+ statusCode: StatusCodes.Good,
220
+ outputArguments: []
221
+ });
222
+ });
223
+ }
224
+
225
+ clearAlarm(alarmNode, message, severity) {
226
+ const isAcked = !alarmNode.ackedState.id.readValue().value.value;
227
+
228
+ alarmNode.activeState.setValue(false);
229
+ alarmNode.raiseNewCondition({ message, severity: severity, isAcked });
230
+
231
+ this.raiseNewConditionAlarm(alarmNode, message, severity, isAcked);
232
+ }
233
+
234
+ raiseAlarm(alarmNode, message, severity, retain = true) {
235
+ const isActive = alarmNode.activeState.id.readValue().value.value;
236
+ const isAcked = alarmNode.ackedState.id.readValue().value.value;
237
+ if (isActive && isAcked) {
238
+ alarmNode.activeState.setValue(false);
239
+ alarmNode.ackedState.setValue(true);
240
+ alarmNode.confirmedState.setValue(true);
241
+ } else {
242
+ alarmNode.ackedState.setValue(false);
243
+ alarmNode.confirmedState.setValue(true);
244
+ }
245
+
246
+ alarmNode.activeState.setValue(true);
247
+ this.raiseNewConditionAlarm(alarmNode, message, severity, retain);
248
+ }
249
+
250
+ raiseNewConditionAlarm(alarmNode, message, severity, retain) {
251
+ alarmNode.raiseNewCondition({ message, severity, retain });
252
+
253
+ this.registry.registerActiveAlarms(alarmNode, message, severity, retain, this.node);
254
+
255
+ this.emitTagAccess("alarm", {
256
+ message: message,
257
+ severity: severity,
258
+ retain: retain,
259
+ dataType: "alarm",
260
+ value: "highHighSp"
261
+ });
262
+ }
263
+
264
+ ensureNamespaceTypes(namespace) {
265
+ const namespaceKey = namespace.index;
266
+ if (this.alarmTypesByNamespace.has(namespaceKey)) {
267
+ return this.alarmTypesByNamespace.get(namespaceKey);
268
+ }
269
+
270
+ const types = this.createObjectType(namespace);
271
+ this.alarmTypesByNamespace.set(namespaceKey, types);
272
+ return types;
273
+ }
274
+
275
+ createObjectType(namespace) {
276
+ const digitalAlarm = namespace.addObjectType({
277
+ browseName: "digitalAlarm",
278
+ subtypeOf: "OffNormalAlarmType"
279
+ });
280
+
281
+ const levelAlarm = namespace.addObjectType({
282
+ browseName: "levelAlarm",
283
+ subtypeOf: "OffNormalAlarmType"
284
+ });
285
+
286
+ namespace.addVariable({
287
+ propertyOf: digitalAlarm,
288
+ browseName: "enabled",
289
+ dataType: "Boolean",
290
+ modellingRule: "Mandatory",
291
+ value: new Variant({ dataType: DataType.Boolean, value: true })
292
+ });
293
+
294
+ namespace.addVariable({
295
+ propertyOf: levelAlarm,
296
+ browseName: "enabled",
297
+ dataType: "Boolean",
298
+ modellingRule: "Mandatory",
299
+ value: new Variant({ dataType: DataType.Boolean, value: true })
300
+ });
301
+
302
+ namespace.addVariable({
303
+ propertyOf: levelAlarm,
304
+ browseName: "highHighLimit",
305
+ dataType: "Int32",
306
+ modellingRule: "Mandatory",
307
+ value: new Variant({ dataType: DataType.Int32, value: 0 })
308
+ });
309
+
310
+ namespace.addVariable({
311
+ propertyOf: levelAlarm,
312
+ browseName: "highLimit",
313
+ dataType: "Int32",
314
+ modellingRule: "Mandatory",
315
+ value: new Variant({ dataType: DataType.Int32, value: 0 })
316
+ });
317
+
318
+ namespace.addVariable({
319
+ propertyOf: levelAlarm,
320
+ browseName: "lowLimit",
321
+ dataType: "Int32",
322
+ modellingRule: "Mandatory",
323
+ value: new Variant({ dataType: DataType.Int32, value: 0 })
324
+ });
325
+
326
+ namespace.addVariable({
327
+ propertyOf: levelAlarm,
328
+ browseName: "lowLowLimit",
329
+ dataType: "Int32",
330
+ modellingRule: "Mandatory",
331
+ value: new Variant({ dataType: DataType.Int32, value: 0 })
332
+ });
333
+
334
+ return {
335
+ digitalAlarmType: digitalAlarm,
336
+ levelAlarmType: levelAlarm
337
+ };
338
+ }
339
+ }
340
+
341
+ module.exports = { OpcUaAddressSpaceAlarm };