Main Content

Subscribe OPC UA Nodes for Data Change

This example shows how to use OPC UA subscriptions to monitor and react to data change events on OPC UA nodes.

This example also shows how to modify your list of subscribed nodes, and how to enable and disable a subscription.

Set Up Server

To run this example in your MATLAB® session, you must install and start the Prosys OPC UA Simulation Server. For more information, see Install an OPC UA Simulation Server for OPC UA Examples.

Create an OPC UA Client and Connect to Server

Create a connection from MATLAB to the OPC UA server specifying the hostname and port.

clientObj = opcua('localhost',53530)
clientObj = 
OPC UA Client:

   Server Information:
                     Name: 'SimulationServer@BGL-SREEDX'
                 Hostname: 'BGL-SREEDX.dhcp.mathworks.com'
                     Port: 53530
              EndpointUrl: 'opc.tcp://BGL-SREEDX.dhcp.mathworks.com:53530/OPCUA/SimulationServer'

   Connection Information:
                  Timeout: 10
                   Status: 'Disconnected'
              ServerState: '<Not connected>'

   Security Information:
      MessageSecurityMode: SignAndEncrypt
    ChannelSecurityPolicy: Aes256_Sha256_RsaPss
                Endpoints: [1×11 opc.ua.EndpointDescription]

The display of the client object properties indicates that the client is initially disconnected from the server. You can view the Status property or call the isConnected function.

connect(clientObj);
isConnected(clientObj)
ans = logical
   1

Select Nodes to Monitor

Use the browseNamespace graphical UI to select nodes to monitor.

nodesToMonitor = browseNamespace(clientObj)
nodesToMonitor = 
1×2 OPC UA Node array:
    index    Name    NsInd  Identifier  NodeType
    -----  --------  -----  ----------  --------
      1    Random    3      Random      Variable
      2    Sawtooth  3      Sawtooth    Variable

Create Subscription

To create a subscription, you construct an OPC UA subscription object with the subscribe function, specifying the OPC UA client object, nodes to be monitored, and a custom callback function handle. The callback executes when a data change event is received from one of the subscribed nodes. You can pass additional data with the callback function to help with the implementation of the callback logic.

In the following code, thresholdValue is used by the callback function for comparison with the actual data received from the monitored nodes. Note that this user supplied additional data is not displayed in the subscription object properties.

thresholdValue = 1;
subObj = subscribe(clientObj,nodesToMonitor,{@mycallback,thresholdValue})
subObj = 
  Subscription with properties:

             Server: "SimulationServer@BGL-SREEDX"
              Nodes: [1×2 opc.ua.Node]
                 ID: 2
            Enabled: 1
    PublishInterval: 1
     DataChangedFcn: @mycallback

With the subscription now defined, whenever the OPC UA server detects a a change in value for any of the subscribed nodes, it sends the change information and triggers execution of the callback.

Add Nodes to Subscription

You can add nodes to the subscription with the addnode function. First use browseNamespace to find and specify the nodes you want to add.

browsenamespace.PNG

Alternatively, you can obtain node handles using the findNodeByName or findNodeById function.

newnode = browseNamespace(clientObj)
newnode = 
1×2 OPC UA Node array:
    index    Name    NsInd  Identifier  NodeType
    -----  --------  -----  ----------  --------
      1    Sinusoid  3      Sinusoid    Variable
      2    Square    3      Square      Variable

With this list of nodes returned by browseNamespace, use addnode to add them to your subscription.

addnode(subObj,newnode)

You can verify the addition of these nodes in the subscription by checking the Nodes property of the original subscription object.

subObj.Nodes
ans = 
1×4 OPC UA Node array:
    index    Name    NsInd  Identifier  NodeType
    -----  --------  -----  ----------  --------
      1    Random    3      Random      Variable
      2    Sawtooth  3      Sawtooth    Variable
      3    Sinusoid  3      Sinusoid    Variable
      4    Square    3      Square      Variable

Remove Nodes from Subscription

During the course of monitoring, you might need to remove some of the nodes that are no longer required in the subscription. Use the removenode function to do this.

As before when you added nodes, you can use browseNamespace to find and specify nodes to remove. Or you can examine the Nodes property of the subscription object to get the node names, or namespace indices and identifiers.

In this example, the nodes named Sawtooth and Square are specified for removal. Then the Nodes property is examined to verify removal.

removenode(subObj,["Sawtooth","Square"]);
subObj.Nodes
ans = 
1×2 OPC UA Node array:
    index    Name    NsInd  Identifier  NodeType
    -----  --------  -----  ----------  --------
      1    Random    3      Random      Variable
      2    Sinusoid  3      Sinusoid    Variable

Disable Subscription

By default, a subscription is enabled when you create it. If necessary you can set the subscription object Enabled property to disable or enable the subscription.

subObj.Enabled = false;

Delete Subscription

When finished with your subscription, clear the subscription and OPC UA client connection. Clearing the subscription handle sends a delete subscription request to the server, and removes the handle from the workspace.

clear subObj
clear clientObj

Callback Function

This callback function receives notification of changed nodes along with their new data, then compares those new data values with a predetermined threshold value.

function mycallback(subObj,notification,userdata)
    % Get the nodes that have data change and the corresponding data.
    % notification is an object containing the data values received from the
    % server and node names, in response to the subscription request.

    nodes = [notification(:).Node]; % Array of structures with fields: Name, Namespace, Identifier.
    data = [notification(:).Data];  % Array of structures with fields: Value, Quality, Timestamp.

    % Get name of nodes that changed and their corresponding values
    changedNodes = string({nodes(:).Name})';
    nodeValues = [data(:).Value]';
    timestamp  = [data(:).Timestamp]';
    quality    = [data(:).Quality]';

    threshold = userdata{1};
    % Get the information of nodes that have value greater than the threshold
    % value
    interestedNodes = changedNodes(nodeValues > threshold);
    interestedValues = nodeValues(nodeValues > threshold);
    interestedTimestamp = timestamp(nodeValues > threshold);
    interestedQuality = quality(nodeValues > threshold);

    % Display information of nodes that have value greater than the threshold
    if ~isempty(interestedNodes)
        disp("Nodes of Interest");
        disp(table(interestedNodes,interestedValues,interestedTimestamp,string(interestedQuality.char)));
        disp("*****************************************");
    end
end