Node.js / TypeScript · recipe

Subscribe to alarms and events in Node.js

Monitor the EventNotifier attribute of the Server object with an event filter that selects the fields you need. Selecting server-side keeps the volume down, and ConditionClassId is the field that makes a downtime reason portable.

Stacknode-opcua
Version2.181.1

The code

const {
  OPCUAClient, AttributeIds, TimestampsToReturn,
  constructEventFilter, ObjectIds,
} = require("node-opcua");

(async () => {
  const client = OPCUAClient.create({ endpointMustExist: false });
  await client.connect("opc.tcp://milo.digitalpetri.com:62541/milo");
  const session = await client.createSession();

  const subscription = await session.createSubscription2({
    requestedPublishingInterval: 500,
    requestedLifetimeCount: 100,
    requestedMaxKeepAliveCount: 10,
    publishingEnabled: true,
  });

  const fields = ["EventId", "EventType", "SourceName", "Time", "Severity", "Message"];
  const eventFilter = constructEventFilter(fields);

  const item = await subscription.monitor(
    { nodeId: ObjectIds.Server, attributeId: AttributeIds.EventNotifier },
    { samplingInterval: 0, queueSize: 100, filter: eventFilter },
    TimestampsToReturn.Both
  );

  item.on("changed", (values) => {
    const e = {};
    fields.forEach((f, i) => (e[f] = values[i].value));
    console.log(`[${e.Severity}] ${e.SourceName}: ${e.Message && e.Message.text}`);
  });

  setTimeout(async () => {
    await subscription.terminate();
    await session.close();
    await client.disconnect();
  }, 10000);
})();

What it prints

[500] MachineTool_1: Tool life below threshold
[800] MachineTool_1: Tool breakage detected
[100] Server: Session activated

Notes

  • The field order in the select clause is the order values arrive in. Zip them back to names yourself, as above: positional arrays are easy to get subtly wrong.
  • samplingInterval: 0 means report as fast as events occur, which is what you want for events rather than values.
  • Add ConditionClassId to the field list for OEE work. It gives you a standardised reason taxonomy.
  • Call ConditionRefresh after reconnecting, or you will miss alarms that were already active.

What breaks first

The subscription is created but no events ever arrive BadEventFilterInvalid
A field in your select clause does not exist on the event types the server emits. Reduce to the base fields, confirm events flow, then add fields back one at a time.
Other recipes in this stack

Last verified 7 September 2026 against OPC UA 1.05.07. OPC UA Connect is an educational resource and is not affiliated with the OPC Foundation.

Free download
OPC UA Troubleshooting & Integration Checklist
The field-tested checklist engineers use to diagnose certificates, ports and namespace problems fast, plus a Python (asyncua) client template.
Get the free checklist →
Free, no course, no login