@vitormnm/node-red-simple-opcua 1.4.3 → 1.5.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.
- package/client/icons/opcua.svg +132 -132
- package/client/lib/opcua-client-browser.js +368 -330
- package/client/lib/opcua-client-method-service.js +88 -88
- package/client/lib/opcua-client-read-service.js +15 -15
- package/client/lib/opcua-client-subscription-id-service.js +24 -24
- package/client/lib/opcua-client-subscription-service.js +170 -170
- package/client/lib/opcua-client-write-service.js +146 -146
- package/client/opcua-client-config.html +80 -80
- package/client/opcua-client-utils.js +12 -11
- package/client/opcua-client.html +140 -140
- package/client/view/opcua-client.js +1144 -1140
- package/icons/opcua.svg +132 -132
- package/icons/opcua2.svg +132 -132
- package/package.json +3 -3
- package/server/icons/opcua.svg +132 -132
- package/server/lib/opcua-address-space-alarm.js +341 -341
- package/server/lib/opcua-address-space-builder.js +1603 -1485
- package/server/lib/opcua-config.js +677 -546
- package/server/lib/opcua-constants.js +119 -109
- package/server/lib/opcua-server-events-child.js +139 -139
- package/server/lib/opcua-server-runtime-child.js +873 -819
- package/server/lib/opcua-server-runtime.js +376 -311
- package/server/lib/opcua-server-status-child.js +187 -187
- package/server/lib/server-node-utils.js +16 -16
- package/server/opcua-server-io.html +346 -346
- package/server/opcua-server-io.js +497 -496
- package/server/opcua-server-registry.js +270 -270
- package/server/opcua-server.css +265 -265
- package/server/opcua-server.html +155 -1643
- package/server/opcua-server.js +24 -13
- package/server/view/opcua-server.css +492 -0
- package/server/view/opcua-server.js +1435 -0
|
@@ -1,88 +1,88 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
const { dataValueToItemResult, ensureArrayPayload, resolveNodeId, resolveMethodObjectId, buildVariantFromItem, callResultToItemResult } = require("../opcua-client-utils");
|
|
4
|
-
|
|
5
|
-
class OpcUaClientMethodService {
|
|
6
|
-
async execute(node, msg, session, itemsResolver) {
|
|
7
|
-
|
|
8
|
-
// const items = ensureArrayPayload(msg, "OPC UA method call");
|
|
9
|
-
const items = itemsResolver.ensureMethodItems(node, msg, "OPC UA method");
|
|
10
|
-
const payload = [];
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
for (const item of items) {
|
|
15
|
-
const methodNodeId = this.resolveMethodId(item);
|
|
16
|
-
|
|
17
|
-
try {
|
|
18
|
-
const objectId = this.resolveMethodObjectIdFromItem(item) || await resolveMethodObjectId(
|
|
19
|
-
session,
|
|
20
|
-
methodNodeId,
|
|
21
|
-
node.connection.methodObjectIdCache
|
|
22
|
-
);
|
|
23
|
-
const argumentDefinition = await this.safeGetMethodArgumentDefinition(
|
|
24
|
-
session,
|
|
25
|
-
methodNodeId,
|
|
26
|
-
node.connection.methodDefinitionCache
|
|
27
|
-
);
|
|
28
|
-
const callRequest = {
|
|
29
|
-
objectId,
|
|
30
|
-
methodId: methodNodeId
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
if (Array.isArray(item.inputs) && item.inputs.length > 0) {
|
|
34
|
-
callRequest.inputArguments = item.inputs.map((input) => buildVariantFromItem(input, input.type));
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const callResult = await session.call(callRequest);
|
|
38
|
-
payload.push(callResultToItemResult(item, callResult, argumentDefinition));
|
|
39
|
-
} catch (itemError) {
|
|
40
|
-
payload.push({
|
|
41
|
-
name: item.name || methodNodeId,
|
|
42
|
-
nodeID: methodNodeId,
|
|
43
|
-
status: itemError.message,
|
|
44
|
-
outputs: []
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
return payload;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
resolveMethodId(item) {
|
|
55
|
-
const methodId = item && (item.methodID || item.methodId || item.nodeID || item.nodeId);
|
|
56
|
-
if (!methodId || !String(methodId).trim()) {
|
|
57
|
-
throw new Error("Each method item must contain methodId or nodeID");
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
return String(methodId).trim();
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
resolveMethodObjectIdFromItem(item) {
|
|
65
|
-
const objectId = item && (item.objectID || item.objectId);
|
|
66
|
-
if (!objectId || !String(objectId).trim()) {
|
|
67
|
-
return "";
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
return String(objectId).trim();
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
async safeGetMethodArgumentDefinition(session, methodNodeId, cache) {
|
|
74
|
-
try {
|
|
75
|
-
return await getMethodArgumentDefinition(session, methodNodeId, cache);
|
|
76
|
-
} catch (error) {
|
|
77
|
-
return {
|
|
78
|
-
inputArguments: [],
|
|
79
|
-
outputArguments: []
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
module.exports = {
|
|
87
|
-
OpcUaClientMethodService
|
|
88
|
-
};
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const { dataValueToItemResult, ensureArrayPayload, resolveNodeId, resolveMethodObjectId, buildVariantFromItem, callResultToItemResult } = require("../opcua-client-utils");
|
|
4
|
+
|
|
5
|
+
class OpcUaClientMethodService {
|
|
6
|
+
async execute(node, msg, session, itemsResolver) {
|
|
7
|
+
|
|
8
|
+
// const items = ensureArrayPayload(msg, "OPC UA method call");
|
|
9
|
+
const items = itemsResolver.ensureMethodItems(node, msg, "OPC UA method");
|
|
10
|
+
const payload = [];
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
for (const item of items) {
|
|
15
|
+
const methodNodeId = this.resolveMethodId(item);
|
|
16
|
+
|
|
17
|
+
try {
|
|
18
|
+
const objectId = this.resolveMethodObjectIdFromItem(item) || await resolveMethodObjectId(
|
|
19
|
+
session,
|
|
20
|
+
methodNodeId,
|
|
21
|
+
node.connection.methodObjectIdCache
|
|
22
|
+
);
|
|
23
|
+
const argumentDefinition = await this.safeGetMethodArgumentDefinition(
|
|
24
|
+
session,
|
|
25
|
+
methodNodeId,
|
|
26
|
+
node.connection.methodDefinitionCache
|
|
27
|
+
);
|
|
28
|
+
const callRequest = {
|
|
29
|
+
objectId,
|
|
30
|
+
methodId: methodNodeId
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
if (Array.isArray(item.inputs) && item.inputs.length > 0) {
|
|
34
|
+
callRequest.inputArguments = item.inputs.map((input) => buildVariantFromItem(input, input.type));
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const callResult = await session.call(callRequest);
|
|
38
|
+
payload.push(callResultToItemResult(item, callResult, argumentDefinition));
|
|
39
|
+
} catch (itemError) {
|
|
40
|
+
payload.push({
|
|
41
|
+
name: item.name || methodNodeId,
|
|
42
|
+
nodeID: methodNodeId,
|
|
43
|
+
status: itemError.message,
|
|
44
|
+
outputs: []
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return payload;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
resolveMethodId(item) {
|
|
55
|
+
const methodId = item && (item.methodID || item.methodId || item.nodeID || item.nodeId);
|
|
56
|
+
if (!methodId || !String(methodId).trim()) {
|
|
57
|
+
throw new Error("Each method item must contain methodId or nodeID");
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return String(methodId).trim();
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
resolveMethodObjectIdFromItem(item) {
|
|
65
|
+
const objectId = item && (item.objectID || item.objectId);
|
|
66
|
+
if (!objectId || !String(objectId).trim()) {
|
|
67
|
+
return "";
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return String(objectId).trim();
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
async safeGetMethodArgumentDefinition(session, methodNodeId, cache) {
|
|
74
|
+
try {
|
|
75
|
+
return await getMethodArgumentDefinition(session, methodNodeId, cache);
|
|
76
|
+
} catch (error) {
|
|
77
|
+
return {
|
|
78
|
+
inputArguments: [],
|
|
79
|
+
outputArguments: []
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
module.exports = {
|
|
87
|
+
OpcUaClientMethodService
|
|
88
|
+
};
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
const { dataValueToItemResult, resolveNodeId } = require("../opcua-client-utils");
|
|
4
|
-
|
|
5
|
-
class OpcUaClientReadService {
|
|
6
|
-
async execute(node, msg, session, itemsResolver) {
|
|
7
|
-
const items = itemsResolver.ensureClientItems(node, msg, "OPC UA read");
|
|
8
|
-
const nodeIds = items.map((item) => resolveNodeId(item));
|
|
9
|
-
const values = await session.readVariableValue(nodeIds);
|
|
10
|
-
return values.map((dataValue, index) => dataValueToItemResult(items[index], dataValue));
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
module.exports = {
|
|
15
|
-
OpcUaClientReadService
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const { dataValueToItemResult, resolveNodeId } = require("../opcua-client-utils");
|
|
4
|
+
|
|
5
|
+
class OpcUaClientReadService {
|
|
6
|
+
async execute(node, msg, session, itemsResolver) {
|
|
7
|
+
const items = itemsResolver.ensureClientItems(node, msg, "OPC UA read");
|
|
8
|
+
const nodeIds = items.map((item) => resolveNodeId(item));
|
|
9
|
+
const values = await session.readVariableValue(nodeIds);
|
|
10
|
+
return values.map((dataValue, index) => dataValueToItemResult(items[index], dataValue));
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
module.exports = {
|
|
15
|
+
OpcUaClientReadService
|
|
16
16
|
};
|
|
@@ -1,25 +1,25 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
const { ClientSubscription } = require("node-opcua");
|
|
4
|
-
|
|
5
|
-
class OpcUaClientSubscriptionIdService {
|
|
6
|
-
async execute(node) {
|
|
7
|
-
const session = await node.connection.getSession();
|
|
8
|
-
const subscription = ClientSubscription.create(session, {
|
|
9
|
-
requestedPublishingInterval: 1000,
|
|
10
|
-
requestedLifetimeCount: 100,
|
|
11
|
-
requestedMaxKeepAliveCount: 10,
|
|
12
|
-
maxNotificationsPerPublish: 100,
|
|
13
|
-
publishingEnabled: true,
|
|
14
|
-
priority: 10
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
const subscriptionId = subscription.subscriptionId;
|
|
18
|
-
await subscription.terminate();
|
|
19
|
-
return subscriptionId;
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
module.exports = {
|
|
24
|
-
OpcUaClientSubscriptionIdService
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const { ClientSubscription } = require("node-opcua");
|
|
4
|
+
|
|
5
|
+
class OpcUaClientSubscriptionIdService {
|
|
6
|
+
async execute(node) {
|
|
7
|
+
const session = await node.connection.getSession();
|
|
8
|
+
const subscription = ClientSubscription.create(session, {
|
|
9
|
+
requestedPublishingInterval: 1000,
|
|
10
|
+
requestedLifetimeCount: 100,
|
|
11
|
+
requestedMaxKeepAliveCount: 10,
|
|
12
|
+
maxNotificationsPerPublish: 100,
|
|
13
|
+
publishingEnabled: true,
|
|
14
|
+
priority: 10
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
const subscriptionId = subscription.subscriptionId;
|
|
18
|
+
await subscription.terminate();
|
|
19
|
+
return subscriptionId;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
module.exports = {
|
|
24
|
+
OpcUaClientSubscriptionIdService
|
|
25
25
|
};
|
|
@@ -1,171 +1,171 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
const {
|
|
4
|
-
ClientMonitoredItem,
|
|
5
|
-
ClientSubscription,
|
|
6
|
-
TimestampsToReturn,
|
|
7
|
-
AttributeIds,
|
|
8
|
-
constructEventFilter
|
|
9
|
-
} = require("node-opcua");
|
|
10
|
-
|
|
11
|
-
const {
|
|
12
|
-
dataValueToItemResult,
|
|
13
|
-
dataValueToItemResultEvent,
|
|
14
|
-
resolveName,
|
|
15
|
-
resolveNodeId,
|
|
16
|
-
statusCodeToString
|
|
17
|
-
} = require("../opcua-client-utils");
|
|
18
|
-
|
|
19
|
-
class OpcUaClientSubscriptionService {
|
|
20
|
-
async startDataSubscription(node, msg, itemsResolver) {
|
|
21
|
-
const items = itemsResolver.ensureClientItems(node, msg, "OPC UA subscription");
|
|
22
|
-
await this.stop(node);
|
|
23
|
-
|
|
24
|
-
const session = await node.connection.getSession();
|
|
25
|
-
const subscription = ClientSubscription.create(session, {
|
|
26
|
-
requestedPublishingInterval: node.publishingInterval,
|
|
27
|
-
requestedLifetimeCount: 60,
|
|
28
|
-
requestedMaxKeepAliveCount: 10,
|
|
29
|
-
maxNotificationsPerPublish: 100,
|
|
30
|
-
publishingEnabled: true,
|
|
31
|
-
priority: 1
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
subscription.on("error", (error) => {
|
|
35
|
-
node.status({ fill: "red", shape: "ring", text: "subscription error" });
|
|
36
|
-
node.error(error);
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
node.subscription = subscription;
|
|
40
|
-
node.monitoredItems = items.map((item) => {
|
|
41
|
-
const monitoredItem = ClientMonitoredItem.create(
|
|
42
|
-
subscription,
|
|
43
|
-
{ nodeId: resolveNodeId(item) },
|
|
44
|
-
{
|
|
45
|
-
samplingInterval: node.samplingInterval,
|
|
46
|
-
discardOldest: true,
|
|
47
|
-
queueSize: 1
|
|
48
|
-
},
|
|
49
|
-
TimestampsToReturn.Both
|
|
50
|
-
);
|
|
51
|
-
|
|
52
|
-
monitoredItem.on("changed", (dataValue) => {
|
|
53
|
-
const payload = dataValueToItemResult(item, dataValue);
|
|
54
|
-
node.status({
|
|
55
|
-
fill: "blue",
|
|
56
|
-
shape: "dot",
|
|
57
|
-
text: resolveName(item, payload.nodeID) + " changed"
|
|
58
|
-
});
|
|
59
|
-
node.send({
|
|
60
|
-
topic: payload.name,
|
|
61
|
-
payload,
|
|
62
|
-
opcua: {
|
|
63
|
-
mode: "subscription",
|
|
64
|
-
nodeID: payload.nodeID,
|
|
65
|
-
status: payload.status
|
|
66
|
-
}
|
|
67
|
-
});
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
monitoredItem.on("err", (message) => {
|
|
71
|
-
node.status({ fill: "red", shape: "ring", text: statusCodeToString(message) });
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
return monitoredItem;
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
return items;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
async startEventSubscription(node, msg, itemsResolver) {
|
|
81
|
-
const items = itemsResolver.ensureClientItems(node, msg, "OPC UA subscription");
|
|
82
|
-
await this.stop(node);
|
|
83
|
-
|
|
84
|
-
const session = await node.connection.getSession();
|
|
85
|
-
const subscription = ClientSubscription.create(session, {
|
|
86
|
-
requestedPublishingInterval: node.publishingInterval,
|
|
87
|
-
requestedLifetimeCount: 60,
|
|
88
|
-
requestedMaxKeepAliveCount: 10,
|
|
89
|
-
maxNotificationsPerPublish: 100,
|
|
90
|
-
publishingEnabled: true,
|
|
91
|
-
priority: 2
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
subscription.on("error", (error) => {
|
|
95
|
-
node.status({ fill: "red", shape: "ring", text: "subscription error" });
|
|
96
|
-
node.error(error);
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
node.subscription = subscription;
|
|
100
|
-
|
|
101
|
-
const eventFilter = constructEventFilter([
|
|
102
|
-
"EventId",
|
|
103
|
-
"EventType",
|
|
104
|
-
"SourceName",
|
|
105
|
-
"SourceNode",
|
|
106
|
-
"Message",
|
|
107
|
-
"Severity",
|
|
108
|
-
"ActiveState",
|
|
109
|
-
"AckedState",
|
|
110
|
-
"ConfirmedState",
|
|
111
|
-
"Time"
|
|
112
|
-
]);
|
|
113
|
-
|
|
114
|
-
node.monitoredItems = items.map((item) => {
|
|
115
|
-
const monitoredItem = ClientMonitoredItem.create(
|
|
116
|
-
subscription,
|
|
117
|
-
{
|
|
118
|
-
nodeId: resolveNodeId(item),
|
|
119
|
-
attributeId: AttributeIds.EventNotifier
|
|
120
|
-
},
|
|
121
|
-
{
|
|
122
|
-
samplingInterval: 0,
|
|
123
|
-
queueSize: 100,
|
|
124
|
-
discardOldest: true,
|
|
125
|
-
filter: eventFilter
|
|
126
|
-
},
|
|
127
|
-
TimestampsToReturn.Both
|
|
128
|
-
);
|
|
129
|
-
|
|
130
|
-
monitoredItem.on("changed", async (eventFields) => {
|
|
131
|
-
const payload = await dataValueToItemResultEvent(item, eventFields, session);
|
|
132
|
-
node.status({
|
|
133
|
-
fill: "blue",
|
|
134
|
-
shape: "dot",
|
|
135
|
-
text: resolveName(item, payload.nodeID) + " changed"
|
|
136
|
-
});
|
|
137
|
-
node.send({
|
|
138
|
-
topic: payload.name,
|
|
139
|
-
payload,
|
|
140
|
-
opcua: {
|
|
141
|
-
mode: "subscription",
|
|
142
|
-
nodeID: payload.nodeID,
|
|
143
|
-
status: payload.status
|
|
144
|
-
}
|
|
145
|
-
});
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
monitoredItem.on("err", (message) => {
|
|
149
|
-
node.status({ fill: "red", shape: "ring", text: statusCodeToString(message) });
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
return monitoredItem;
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
return items;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
async stop(node) {
|
|
159
|
-
const subscription = node.subscription;
|
|
160
|
-
node.monitoredItems = [];
|
|
161
|
-
node.subscription = null;
|
|
162
|
-
|
|
163
|
-
if (subscription) {
|
|
164
|
-
await subscription.terminate();
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
module.exports = {
|
|
170
|
-
OpcUaClientSubscriptionService
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const {
|
|
4
|
+
ClientMonitoredItem,
|
|
5
|
+
ClientSubscription,
|
|
6
|
+
TimestampsToReturn,
|
|
7
|
+
AttributeIds,
|
|
8
|
+
constructEventFilter
|
|
9
|
+
} = require("node-opcua");
|
|
10
|
+
|
|
11
|
+
const {
|
|
12
|
+
dataValueToItemResult,
|
|
13
|
+
dataValueToItemResultEvent,
|
|
14
|
+
resolveName,
|
|
15
|
+
resolveNodeId,
|
|
16
|
+
statusCodeToString
|
|
17
|
+
} = require("../opcua-client-utils");
|
|
18
|
+
|
|
19
|
+
class OpcUaClientSubscriptionService {
|
|
20
|
+
async startDataSubscription(node, msg, itemsResolver) {
|
|
21
|
+
const items = itemsResolver.ensureClientItems(node, msg, "OPC UA subscription");
|
|
22
|
+
await this.stop(node);
|
|
23
|
+
|
|
24
|
+
const session = await node.connection.getSession();
|
|
25
|
+
const subscription = ClientSubscription.create(session, {
|
|
26
|
+
requestedPublishingInterval: node.publishingInterval,
|
|
27
|
+
requestedLifetimeCount: 60,
|
|
28
|
+
requestedMaxKeepAliveCount: 10,
|
|
29
|
+
maxNotificationsPerPublish: 100,
|
|
30
|
+
publishingEnabled: true,
|
|
31
|
+
priority: 1
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
subscription.on("error", (error) => {
|
|
35
|
+
node.status({ fill: "red", shape: "ring", text: "subscription error" });
|
|
36
|
+
node.error(error);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
node.subscription = subscription;
|
|
40
|
+
node.monitoredItems = items.map((item) => {
|
|
41
|
+
const monitoredItem = ClientMonitoredItem.create(
|
|
42
|
+
subscription,
|
|
43
|
+
{ nodeId: resolveNodeId(item) },
|
|
44
|
+
{
|
|
45
|
+
samplingInterval: node.samplingInterval,
|
|
46
|
+
discardOldest: true,
|
|
47
|
+
queueSize: 1
|
|
48
|
+
},
|
|
49
|
+
TimestampsToReturn.Both
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
monitoredItem.on("changed", (dataValue) => {
|
|
53
|
+
const payload = dataValueToItemResult(item, dataValue);
|
|
54
|
+
node.status({
|
|
55
|
+
fill: "blue",
|
|
56
|
+
shape: "dot",
|
|
57
|
+
text: resolveName(item, payload.nodeID) + " changed"
|
|
58
|
+
});
|
|
59
|
+
node.send({
|
|
60
|
+
topic: payload.name,
|
|
61
|
+
payload,
|
|
62
|
+
opcua: {
|
|
63
|
+
mode: "subscription",
|
|
64
|
+
nodeID: payload.nodeID,
|
|
65
|
+
status: payload.status
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
monitoredItem.on("err", (message) => {
|
|
71
|
+
node.status({ fill: "red", shape: "ring", text: statusCodeToString(message) });
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
return monitoredItem;
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
return items;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
async startEventSubscription(node, msg, itemsResolver) {
|
|
81
|
+
const items = itemsResolver.ensureClientItems(node, msg, "OPC UA subscription");
|
|
82
|
+
await this.stop(node);
|
|
83
|
+
|
|
84
|
+
const session = await node.connection.getSession();
|
|
85
|
+
const subscription = ClientSubscription.create(session, {
|
|
86
|
+
requestedPublishingInterval: node.publishingInterval,
|
|
87
|
+
requestedLifetimeCount: 60,
|
|
88
|
+
requestedMaxKeepAliveCount: 10,
|
|
89
|
+
maxNotificationsPerPublish: 100,
|
|
90
|
+
publishingEnabled: true,
|
|
91
|
+
priority: 2
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
subscription.on("error", (error) => {
|
|
95
|
+
node.status({ fill: "red", shape: "ring", text: "subscription error" });
|
|
96
|
+
node.error(error);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
node.subscription = subscription;
|
|
100
|
+
|
|
101
|
+
const eventFilter = constructEventFilter([
|
|
102
|
+
"EventId",
|
|
103
|
+
"EventType",
|
|
104
|
+
"SourceName",
|
|
105
|
+
"SourceNode",
|
|
106
|
+
"Message",
|
|
107
|
+
"Severity",
|
|
108
|
+
"ActiveState",
|
|
109
|
+
"AckedState",
|
|
110
|
+
"ConfirmedState",
|
|
111
|
+
"Time"
|
|
112
|
+
]);
|
|
113
|
+
|
|
114
|
+
node.monitoredItems = items.map((item) => {
|
|
115
|
+
const monitoredItem = ClientMonitoredItem.create(
|
|
116
|
+
subscription,
|
|
117
|
+
{
|
|
118
|
+
nodeId: resolveNodeId(item),
|
|
119
|
+
attributeId: AttributeIds.EventNotifier
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
samplingInterval: 0,
|
|
123
|
+
queueSize: 100,
|
|
124
|
+
discardOldest: true,
|
|
125
|
+
filter: eventFilter
|
|
126
|
+
},
|
|
127
|
+
TimestampsToReturn.Both
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
monitoredItem.on("changed", async (eventFields) => {
|
|
131
|
+
const payload = await dataValueToItemResultEvent(item, eventFields, session);
|
|
132
|
+
node.status({
|
|
133
|
+
fill: "blue",
|
|
134
|
+
shape: "dot",
|
|
135
|
+
text: resolveName(item, payload.nodeID) + " changed"
|
|
136
|
+
});
|
|
137
|
+
node.send({
|
|
138
|
+
topic: payload.name,
|
|
139
|
+
payload,
|
|
140
|
+
opcua: {
|
|
141
|
+
mode: "subscription",
|
|
142
|
+
nodeID: payload.nodeID,
|
|
143
|
+
status: payload.status
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
monitoredItem.on("err", (message) => {
|
|
149
|
+
node.status({ fill: "red", shape: "ring", text: statusCodeToString(message) });
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
return monitoredItem;
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
return items;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
async stop(node) {
|
|
159
|
+
const subscription = node.subscription;
|
|
160
|
+
node.monitoredItems = [];
|
|
161
|
+
node.subscription = null;
|
|
162
|
+
|
|
163
|
+
if (subscription) {
|
|
164
|
+
await subscription.terminate();
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
module.exports = {
|
|
170
|
+
OpcUaClientSubscriptionService
|
|
171
171
|
};
|