Managing nodes from the cloud in the OPC-UA Publisher Edge

In my previous blog, we learned how to get started with the Azure IoT Edge module named OPC Publisher.

This module makes it possible to extract data from a ‘local’ OPC-UA server and to expose this data to the Azure IoT Hub. The data is sent using the routing feature within Azure IoT Edge so before we sent the data to the cloud, we first can have an insight in the actual data, take actions locally and transform the data.

But the OPC Publisher connects to the OPC-UA server based on local settings. Here is the configuration, taken from my c:\iiot\pn.json file:

[
  {
    "EndpointUrl": "opc.tcp://[IP address]:53530/OPCUA/SimulationServer",
    "UseSecurity": false,
    "OpcNodes": [
      {
        "Id": "ns=5;s=Counter1"
      },
      {
        "Id": "ns=5;s=Random1"
      }
    ]
  }
]

These settings are ‘hardcoded’, the file is on the file system, not in Docker.

Can we change these settings remotely, using the cloud?

The short answer is: yes.

The OPC Publisher has capabilities to manipulate the published nodes using DirectMethods.

An example is provided by Microsoft in this sample application.

You can run it as an executable but the documentation is very poor. I wanted to dig a bit deeper into the capabilities of the OPC Publisher and especially this DirectMethod usage.

If you look into the code, you will find DirectMethod support for:

  • PublishNodes
  • UnpublishNodes
  • UnpublishAllNodes
  • GetConfiguredEndpoints
  • GetConfiguredNodesOnEndpoint

So we know what the names of the methods are. Now we must know how the body of each method must look like.

I played around with the first three methods:

namespace OpCUaNodeChanger
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using Microsoft.Azure.Devices;
    using Newtonsoft.Json;

    class Program
    {
        static void Main(string[] args)
        {
            string iotHubConnectionString = "HostName=[hostname].azure-devices.net;SharedAccessKeyName=iothubowner;SharedAccessKey=[key]";
            string _publisherDeviceName = "opc-ua-edge";
            string _publisherModuleName = "OPCPublisher";

            var _iotHubClient = ServiceClient.CreateFromConnectionString(iotHubConnectionString, TransportType.Amqp_WebSocket_Only);

            TimeSpan responseTimeout = TimeSpan.FromSeconds(300);
            TimeSpan connectionTimeout = TimeSpan.FromSeconds(30);

            var _method = new CloudToDeviceMethod("PublishNodes", responseTimeout, connectionTimeout); 

            var json = File.ReadAllText("methodpayload.json").Replace("\r", string.Empty).Replace("\n", string.Empty);
            _method.SetPayloadJson(json);

            var methodResult = _iotHubClient.InvokeDeviceMethodAsync(_publisherDeviceName, _publisherModuleName, _method).Result;

            Console.WriteLine($"Result: {methodResult.Status}");
            Console.WriteLine("Press a key to exit...");
            Console.ReadKey();
        }
    }
}

The code is very straightforward, connect to the IoTHub using the connection string and call a direct method for a module on a device, part of this IoTHub.

Note: you have to provide an IoTHub connection string. So this logic is typically executed in the cloud only. Do not use this connection string outside the cloud without securing it!

Adding Nodes

We call ‘PublishNodes’. This method adds new nodes to the existing configuration.

Let’s add the SawTooth and the Sinusoid. So the body of the DirectMethod looks like:

{
  "EndpointUrl": "opc.tcp://[IP addres]:53530/OPCUA/SimulationServer",
  "OpcNodes": [
    {
      "Id": "ns=5;s=Sawtooth1"
    },
    {
      "Id": "ns=5;s=Sinusoid1"
    }
  ]
}

Once executed, the method returns return status 202.

Note: if the status 200 is returned, the execution succeeded but no nodes are added.

Now the pn.json is updated to:

[
  {
    "EndpointUrl": "opc.tcp://192.168.43.8:53530/OPCUA/SimulationServer",
    "UseSecurity": false,
    "OpcNodes": [
      {
        "Id": "ns=5;s=Counter1"
      },
      {
        "Id": "ns=5;s=Random1"
      },
      {
        "Id": "ns=5;s=Sawtooth1"
      },
      {
        "Id": "ns=5;s=Sinusoid1"
      }
    ]
  }
]

As you can see, the security is untouched, only nodes are added.

Removing certain Nodes

We can also remove nodes. This works exactly the same, you only have to call ‘UnpublishNodes’:

var _method = new CloudToDeviceMethod("UnpublishNodes", responseTimeout, connectionTimeout);

Provide the same direct method body as ‘PublishNodes’, just tell which node to remove.

If nodes are deleted, the status 202 is returned. If no nodes are deleted, a 200 is returned.

Remove all nodes

The direct method ‘UnpublishAllNodes’ can be used to remove all nodes. In fact, it removes the complete endpoint:

var _method = new CloudToDeviceMethod("UnpublishAllNodes", responseTimeout, connectionTimeout);

Use this method only if you want to get rid of the complete endpoint, you cannot recover this endpoint later on.

I was not able to manipulate the kind of security using ‘PublishNodes’.

You will have to return to the actual device to repair this endpoint.

Update 2019-02-01: This issue with “useSecurity” is fixed in a recent pull request. See this conversation for more information.

Conclusion

Yes, we are able to manipulate the nodes of an OPC Publisher after the initial deployment. from the cloud.

Advertenties