I'm trying to monitor events (instead of variables) from a OPC-UA server using node-opcua.
I did not found any example of monitoring events in the client tutorial and found some old issues like this online and some sample code
Based on what I see it seems like "monitoring" an event should be quite similar to monitor variables: I need to change the attributeId from AttributeIds.Value
to AttributeIds.EventNotifier
in the ReadValueIdOptions
parameter, add a filter
variable in MonitoringParametersOptions
object and then call a method like ClientMonitoredItem.create
, passing a subscription, or directly calling monitor
method on the subscription itself.
I'm testing code with an online demo server opc.tcp://opcua.demo-this.com:62544/Quickstarts/AlarmConditionServer
, and I'm able to monitor a variable like "LastSeverity" by its nodeid, which I found by using the UAExpert client. :
I get the following output if I run the source code posted below
PS PATH_TO_DIRECTORY> node out/main2.js
17:46:03.763Z :opcua_client_impl :248
Warning: endpoint_must_exist is now deprecated, use endpointMustExist instead
session created !
Monitored item value (LastSeverity) changed: 300
Monitored item value (LastSeverity) changed: 500
Monitored item value (LastSeverity) changed: 700
Monitored item value (LastSeverity) changed: 900
Monitored item value (LastSeverity) changed: 100
main2.ts source code:
import {
AttributeIds,
ClientMonitoredItem,
ClientSubscription,
DataValue,
MessageSecurityMode,
MonitoringParametersOptions,
OPCUAClient,
OPCUAClientOptions,
ReadValueIdOptions,
SecurityPolicy,
TimestampsToReturn,
} from "node-opcua-client";
async function main(): Promise<void> {
try {
const options: OPCUAClientOptions = {
connectionStrategy: {
initialDelay: 1000,
maxRetry: 100000,
},
securityMode: MessageSecurityMode.None,
securityPolicy: SecurityPolicy.None,
endpoint_must_exist: false,
};
const client = OPCUAClient.create(options);
await client.connect("opc.tcp://opcua.demo-this.com:62544/Quickstarts/AlarmConditionServer");
const session = await client.createSession();
console.log("session created !");
const subscription = ClientSubscription.create(session, {
requestedPublishingInterval: 1000,
maxNotificationsPerPublish: 100,
publishingEnabled: true,
priority: 10
});
const itemToMonitor: ReadValueIdOptions = {
nodeId: "ns=2;s=1:Metals/WestTank?Bronze/LastSeverity",
attributeId: AttributeIds.Value
};
const parameters: MonitoringParametersOptions = {
samplingInterval: 100,
discardOldest: true,
queueSize: 10
};
const monitoredItem = ClientMonitoredItem.create(
subscription,
itemToMonitor,
parameters,
TimestampsToReturn.Both
);
monitoredItem.on("changed", (dataValue: DataValue) => {
const value = dataValue.value.value;
console.log("Monitored item value (LastSeverity) changed: ", value);
});
}
catch (err) {
console.log("Execution failed: ", err);
}
}
main();
So the variable monitoring is fine, but I can't succeed in monitoring an event. If I add Event View in UAExpert I can see a lot of events:
By changing the code in something like the following (I also tried a very similar code to the first I posted, by changing AttributeIds.EventNotifier
and stuff like that as I said above), nothing happens and no events are logged on console:
import {
AttributeIds,
ClientSubscription,
DataValue,
MessageSecurityMode,
OPCUAClient,
OPCUAClientOptions,
SecurityPolicy,
TimestampsToReturn,
} from "node-opcua-client";
import * as opcua from "node-opcua";
async function main(): Promise<void> {
try {
const options: OPCUAClientOptions = {
connectionStrategy: {
initialDelay: 1000,
maxRetry: 100000,
},
securityMode: MessageSecurityMode.None,
securityPolicy: SecurityPolicy.None,
endpoint_must_exist: false,
};
const client = OPCUAClient.create(options);
await client.connect("opc.tcp://opcua.demo-this.com:62544/Quickstarts/AlarmConditionServer");
const session = await client.createSession();
console.log("session created !");
const subscription = ClientSubscription.create(session, {
requestedPublishingInterval: 1000,
maxNotificationsPerPublish: 100,
publishingEnabled: true,
priority: 10
});
var fields = [
"EventId",
"EventType",
"SourceNode",
"SourceName",
"Time",
"ReceiveTime",
"Message",
"Severity"
];
var eventFilter = opcua.constructEventFilter(fields);
var event_monitoringItem = await subscription.monitor(
{
nodeId: "ns=0;i=9764",
attributeId: AttributeIds.EventNotifier
},
{
queueSize: 100000,
filter: eventFilter,
discardOldest: true
},
TimestampsToReturn.Both
);
event_monitoringItem.on("changed", (dataValue: DataValue) => {
const value = dataValue.value.value;
console.log("Monitored item value (Event) changed: ", value);
});
}
catch (err) {
console.log("Execution failed: ", err);
}
}
main();
I've tried different node ids like ns=0;i=9764
and i=9764
but it's not working.
What am I missing? Is it just a node id issue (how should I get it from the event?) or I need to change the code in something different?
Thanks for the attention.
For anyone interested, i opened a new issue in the official project github page. The accepted solution shows how to directly point to the "Server" nodeid (ObjectIds.Server) in monitoring events.
I paste the solution code below:
import {
AttributeIds,
constructEventFilter,
ObjectIds,
OPCUAClient,
TimestampsToReturn,
Variant,
} from "node-opcua-client";
async function main(): Promise<void> {
const client = OPCUAClient.create({});
const endpointUrl = "opc.tcp://opcua.demo-this.com:62544/Quickstarts/AlarmConditionServer";
const subscriptionParamters = {
requestedPublishingInterval: 1000,
maxNotificationsPerPublish: 100,
publishingEnabled: true,
priority: 10,
};
await client.withSubscriptionAsync(endpointUrl, subscriptionParamters, async (session, subscription) => {
const fields = [
"EventId",
"EventType",
"SourceNode",
"SourceName",
"Time",
"ReceiveTime",
"Message",
"Severity",
];
const eventFilter = constructEventFilter(fields);
const event_monitoringItem = await subscription.monitor(
{
nodeId: ObjectIds.Server,
attributeId: AttributeIds.EventNotifier,
},
{
queueSize: 10,
filter: eventFilter,
discardOldest: true,
},
TimestampsToReturn.Both
);
event_monitoringItem.on("changed", (events: Variant[]) => {
for(let i=0;i<events.length;i++) {
console.log(fields[i],"=", events[i].toString());
}
console.log("----------------\n\n")
});
console.log("CTRL+C to stop");
await new Promise<void>((resolve) => process.once("SIGINT", resolve));
}
);
}
main();