Comprehensive Guide to Node OPC UA API for Seamless Industrial Automation

Introduction to node-opcua

Node-OPCUA is a Node.js library for creating OPC UA clients and servers. OPC UA (Open Platform Communications Unified Architecture) is a machine-to-machine communication protocol for industrial automation developed by the OPC Foundation. This library provides a set of APIs to facilitate communication between industrial hardware and software systems.

Getting Started

First, install the node-opcua library:

  npm install node-opcua

Creating an OPC UA Server

Here is a basic example of creating an OPC UA server:

  const opcua = require("node-opcua");
  
  const server = new opcua.OPCUAServer({
    port: 4840, 
    resourcePath: "/UA/MyLittleServer"
  });

  async function post_initialize() {
    const addressSpace = server.engine.addressSpace;
    const namespace = addressSpace.getOwnNamespace();

    const myDevice = namespace.addObject({
      organizedBy: addressSpace.rootFolder.objects,
      browseName: "MyDevice"
    });

    namespace.addVariable({
      componentOf: myDevice,
      browseName: "MyVariable",
      dataType: "Double",
      value: {
        get: () => new opcua.Variant({dataType: opcua.DataType.Double, value: Math.random()})
      }
    });
  }

  server.initialize(post_initialize);

  server.start(() => {
    console.log("Server is now listening...");
    console.log("Port:", server.endpoints[0].port);
  });

Creating an OPC UA Client

Here is a basic example of creating an OPC UA client:

  const opcua = require("node-opcua");

  const client = opcua.OPCUAClient.create({
    endpoint_must_exist: false
  });

  const endpointUrl = "opc.tcp://localhost:4840/UA/MyLittleServer";

  async function main() {
    try {
      await client.connect(endpointUrl);
      console.log("Client connected!");

      const session = await client.createSession();
      console.log("Session created!");

      const browseResult = await session.browse("RootFolder");
      console.log("Browse Result:");
      console.log(browseResult);

      await session.close();
      console.log("Session closed!");

      await client.disconnect();
      console.log("Client disconnected!");
    } catch(err) {
      console.log("Error:", err);
    }
  }

  main();

Monitoring Nodes

Monitoring a node in an OPC UA server:

  const opcua = require("node-opcua");
  
  const client = opcua.OPCUAClient.create({});
  const endpointUrl = "opc.tcp://localhost:4840";

  async function main() {
    await client.connect(endpointUrl);
    const session = await client.createSession();
    
    const subscription = opcua.ClientSubscription.create(session, {
      requestedPublishingInterval: 1000,
      requestedLifetimeCount: 100,
      requestedMaxKeepAliveCount: 10,
      maxNotificationsPerPublish: 10,
      publishingEnabled: true,
      priority: 10
    });

    subscription.on("started", () => {
      console.log("Subscription started - ID:", subscription.subscriptionId);
    }).on("keepalive", () => {
      console.log("keepalive");
    }).on("terminated", () => {
      console.log("terminated");
    });

    const monitoredItem = subscription.monitor({
      nodeId: opcua.resolveNodeId("ns=1;s=MyDevice.MyVariable"),
      attributeId: opcua.AttributeIds.Value
    }, {
      samplingInterval: 100,
      discardOldest: true,
      queueSize: 10
    }, opcua.TimestampsToReturn.Both);

    monitoredItem.on("changed", (dataValue) => {
      console.log("New Value:", dataValue.value.value);
    });

    setTimeout(async () => {
      await subscription.terminate();
      await session.close();
      await client.disconnect();
      console.log("Done!");
    }, 10000);
  }

  main();

Complete App Example

A complete application example combining server and client with monitoring:

  const opcua = require("node-opcua");
  
  // Server Setup
  const server = new opcua.OPCUAServer({
    port: 4840,
    resourcePath: "/UA/MyOPAUServer"
  });

  server.initialize(() => {
    const addressSpace = server.engine.addressSpace;
    const namespace = addressSpace.getOwnNamespace();

    const myDevice = namespace.addObject({
      organizedBy: addressSpace.rootFolder.objects,
      browseName: "MyDevice"
    });

    namespace.addVariable({
      componentOf: myDevice,
      browseName: "MyVariable",
      dataType: "Double",
      value: {
        get: () => new opcua.Variant({dataType: opcua.DataType.Double, value: Math.random() * 100})
      }
    });

    server.start(() => {
      console.log("Server is now listening on port", server.endpoints[0].port);
    });
  });

  // Client Setup
  const client = opcua.OPCUAClient.create({});
  const endpointUrl = "opc.tcp://localhost:4840/UA/MyOPAUServer";

  async function monitorValue() {
    await client.connect(endpointUrl);
    const session = await client.createSession();
    
    const subscription = opcua.ClientSubscription.create(session, {
      requestedPublishingInterval: 1000,
      requestedLifetimeCount: 100,
      requestedMaxKeepAliveCount: 10,
      maxNotificationsPerPublish: 10,
      publishingEnabled: true,
      priority: 10
    });

    subscription.on("started", () => {
      console.log("Subscription started - ID:", subscription.subscriptionId);
    });

    const monitoredItem = subscription.monitor({
      nodeId: opcua.resolveNodeId("ns=1;s=MyDevice.MyVariable"),
      attributeId: opcua.AttributeIds.Value
    }, {
      samplingInterval: 100,
      discardOldest: true,
      queueSize: 10
    }, opcua.TimestampsToReturn.Both);

    monitoredItem.on("changed", (dataValue) => {
      console.log("New monitored value = ", dataValue.value.value);
    });

    setTimeout(async () => {
      await subscription.terminate();
      await session.close();
      await client.disconnect();
      console.log("Client disconnected");
    }, 10000);
  }

  monitorValue();

By leveraging the node-opcua library, developers can create robust industrial automation applications with ease.

Hash: 5028175436a99b032184a343bca6b0ecea82763737096c2b030cfdf99753bee5

Leave a Reply

Your email address will not be published. Required fields are marked *