Getting started with OPC-UA on Azure IoT Edge

OPC-UA brings the promise of secure and platform independent M2M communication:

“The OPC Unified Architecture (UA), released in 2008, is a platform-independent service-oriented architecture that integrates all the functionality of the individual OPC Classic specifications into one extensible framework.”

Microsoft invests heavily in OPC-UA by providing several solutions, eg.:

And most of it is open-source!

But it’s hard to get started, what do you need to get data from an OPC-UA Server into the cloud using IoT Edge?

Here is a quick start by using the UPC UA Publisher module.

Note: This is just an introduction. We leave out security for convenience. Don’t try that in your factory!

I run this demonstration with Linux containers on a Windows 10 (Pro) OS.

OPC-UA Server

To get started, we need an OPC-UA server. If you are lucky and you have an OPC-UA device, you can start with that one.

But for those who do not have an actual device, there are several alternatives.

In this case, we use the free OPC-UA Simulation server from Prosys OPC.

If you install the simulator, it automatically starts a simulation with multiple types of values (randomly generated values, a counter, etc.)  which is available for us to consume:

Note: When starting the server for the first time, you have to accept some firewall changes.

Server settings

The only thing regarding the server you need to know are two values:

1. The address of the server

On the opening page of the simulator, you will see the OPC address of your simulation.

Copy this UA TCP address;


Note: later on, I replace this machine name by the IP address of this device. The machine name corrupted my URI.

2. The names of the nodes

From this server, we need to read (simulation) values. Values are available as nodes:

The value of Counter1 has the node:


Docker settings

The IoT Edge module which we are going to publish needs access to the Operating system.
In our case, we give Docker access to a folder named:


Create this folder if it does not exist yet.

To get access to this directory/drive, Docker needs access permissions to the C drive:

Only once, you have to provide credentials to apply this change.

Publisher configuration

In this folder, create this configuration file named ‘c:\iiotedge\pn.json’:

    "EndpointUrl": "opc.tcp://",
    "UseSecurity": false,
    "OpcNodes": [
        "Id": "ns=5;s=Counter1"
        "Id": "ns=5;s=Random1"

Here you fill in the OPC-UA endpoint URL and the Nodes you want to make available in the cloud.

Note: I inserted the IP address instead of the machine name. I have encountered errors because the URL was not recognized due to the machine name.

Note: I disabled the security by setting it to ‘None’. In production, please implement a secure connection!

IoT Edge module using the marketplace

As always, register an IoT Edge in the Azure Portal.

Once registered, go to the official marketplace for public IoT Edge modules.

This is a good starting point for using official modules from Microsoft or third-party modules.

Here you can find the OPC-UA module we want to deploy:

This marketplace saves us a lot of hassle (downloading the code from GitHub, recompiling, adding it into a container repository, etc.) so get it now!

Follow the dialogs and before you know it, you start adding the OPC-UA Publisher to your device:


This wizard has no knowledge about your actual device or OPC-UA server. The default container create options are insufficient.

Remove the container create options:

And replace it with:

  "Hostname": "publisher",
  "Cmd": [
  "HostConfig": {
    "PortBindings": {
      "62222/tcp": [
          "HostPort": "62222"
    "Binds": [
    "ExtraHosts": [

Note: The ExtraHosts seems to be ignored.

Now, we can read the pn.json file. This configuration published a message every ten seconds (–si=10).

Also, repair the routes, the wizard added this line which we do not need in here:

Finally, deploy this configuration.

Checking the configuration

Now comes the interesting part, will everything work together?

I encountered several little issues during various deployments: IP address instead of the machine name, typos in configurations, node names, etc. Check out the logging of both the edgeAgent and the OPCPublisher modules.

So if everything works, then “docker logs -f OPCPublusher” will show:

IoTEdge detected.
[22:46:38 INF] Current directory is: /appdata
[22:46:38 INF] Log file is: publisher-publisher.log
[22:46:38 INF] Log level is: info
[22:46:38 INF] Publisher is starting up...
[22:46:38 INF] Application Certificate store type is: X509Store
[22:46:38 INF] Application Certificate store path is: CurrentUser\UA_MachineDefault
[22:46:38 INF] Application Certificate subject name is: publisher
[22:46:38 INF] Application certificate found in Application Certificate Store
[22:46:38 INF] Application certificate is for Application URI 'urn:publisher:publisher:microsoft:', Application 'publisher and has Subject 'publisher'
[22:46:38 INF] Trusted Issuer store type is: Directory
[22:46:38 INF] Trusted Issuer Certificate store path is: CertificateStores/issuers
[22:46:38 INF] Trusted Peer Certificate store type is: Directory
[22:46:38 INF] Trusted Peer Certificate store path is: CertificateStores/trusted
[22:46:38 INF] Rejected certificate store type is: Directory
[22:46:38 INF] Rejected Certificate store path is: CertificateStores/rejected
[22:46:38 INF] Rejection of SHA1 signed certificates is disabled
[22:46:38 INF] Minimum certificate key size set to 1024
[22:46:38 INF] Adding publisher certificate to trusted peer store. StorePath=CertificateStores/trusted
[22:46:38 INF] A certificate with the same thumbprint is already in the trusted store.
[22:46:38 INF] OperationTimeout set to 120000
[22:46:38 INF] Publisher server base address: opc.tcp://publisher:62222/UA/Publisher
[22:46:38 INF] Security policy with mode SignAndEncrypt added
[22:46:38 INF] LDS(-ME) registration intervall set to 0 ms (0 means no registration)
[22:46:38 INF] opcstacktracemask set to: 0x0
[22:46:38 INF] There is no site configured.
[22:46:38 INF] Publisher configured to auto trust server certificates of the servers it is connecting to.
[22:46:38 INF] Starting server on endpoint opc.tcp://publisher:62222/UA/Publisher ...
[22:46:40 INF] Server started.
[22:46:40 INF] Using default telemetry configuration.
[22:46:40 INF] The name of the configuration file for published nodes is: ./pn.json
[22:46:40 INF] Attemtping to load node configuration from: ./pn.json
[22:46:40 INF] Loaded 1 config file entry/entries.
[22:46:40 INF] There are 2 nodes to publish.
[22:46:40 INF] Create IoTEdgeHub module client using 'Amqp_Tcp_Only' for communication.
[22:46:41 INF] IoTCentral mode: False
[22:46:42 INF] Connection status changed to 'Connected', reason 'Connection_Ok'
[22:46:42 INF] Message processing and hub communication configured with a send interval of 10 sec and a message buffer size of 262144 bytes.
[22:46:42 INF] Creating task process and batch monitored item data updates...
[22:46:42 INF] Publisher is running. Press CTRL-C to quit.
[22:46:43 INF] Connect and monitor session and nodes on endpoint 'opc.tcp://'.
[22:46:44 INF] Create unsecured session for endpoint URI 'opc.tcp://' with timeout of 10000 ms.
[22:46:44 INF] Certificate 'DC=DESKTOP-1ETOHD3, O=Prosys OPC, CN=SimulationServer' will be trusted, since the autotrustservercerts options was specified.
[22:46:44 INF] Session successfully created with Id ns=1;g=c92c780c-e4f7-4b96-af34-717afbd283fe.
[22:46:44 INF] The session to endpoint 'opc.tcp://' has 7 entries in its namespace array:
[22:46:44 INF] Namespace index 0:
[22:46:44 INF] Namespace index 1: urn:DESKTOP-1ETOHD3:OPCUA:SimulationServer
[22:46:44 INF] Namespace index 2:
[22:46:44 INF] Namespace index 3:
[22:46:44 INF] Namespace index 4:
[22:46:44 INF] Namespace index 5:
[22:46:44 INF] Namespace index 6:
[22:46:44 INF] The server on endpoint 'opc.tcp://' supports a minimal sampling interval of 0 ms.
[22:46:45 INF] Created subscription with id 2 on endpoint 'opc.tcp://'
[22:46:45 INF] Create subscription on endpoint 'opc.tcp://' requested OPC publishing interval is 0 ms. (revised: 0 ms)
[22:46:45 INF] Start monitoring items on endpoint 'opc.tcp://'. Currently monitoring 0 items.
[22:46:45 INF] Done processing unmonitored items on endpoint 'opc.tcp://' took 37 msec. Now monitoring 2 items in subscription with id '2'.

You see the namespaces exposed by the OPC-UA server. Check out namespace 5. This is the simulation. And the node of the counter of this simulation is named “ns=5;s=Counter1”. Nice.

And later on, you will see that messages are sent:

[22:49:44 INF] ==========================================================================
[22:49:44 INF] OpcPublisher status @ 11/05/2018 22:49:44 (started @ 11/05/2018 22:46:38)
[22:49:44 INF] ---------------------------------
[22:49:44 INF] OPC sessions: 1
[22:49:44 INF] connected OPC sessions: 1
[22:49:44 INF] connected OPC subscriptions: 1
[22:49:44 INF] OPC monitored items: 2
[22:49:44 INF] ---------------------------------
[22:49:44 INF] monitored items queue bounded capacity: 8192
[22:49:44 INF] monitored items queue current items: 0
[22:49:44 INF] monitored item notifications enqueued: 360
[22:49:44 INF] monitored item notifications enqueue failure: 0
[22:49:44 INF] monitored item notifications dequeued: 360
[22:49:44 INF] ---------------------------------
[22:49:44 INF] messages sent to IoTHub: 18
[22:49:44 INF] last successful msg sent @: 11/05/2018 22:49:42
[22:49:44 INF] bytes sent to IoTHub: 71353
[22:49:44 INF] avg msg size: 3964
[22:49:44 INF] msg send failures: 0
[22:49:44 INF] messages too large to sent to IoTHub: 0
[22:49:44 INF] times we missed send interval: 0
[22:49:44 INF] ---------------------------------
[22:49:44 INF] current working set in MB: 90
[22:49:44 INF] --si setting: 10
[22:49:44 INF] --ms setting: 262144
[22:49:44 INF] --ih setting: Amqp_Tcp_Only
[22:49:44 INF] ==========================================================================

Here, 18 messages were sent.

I see the arrival of the messages using the Device Explorer. Here is one message:

11/5/2018 11:53:43 PM> Device: [opc-ua-edge], Data:[

I removed a few lines, only the first and last are shown. We see the counter values and the random values, ten in total because we are listening with a ten-second interval.

Help, I am missing values!

The OPC Publisher is using the publisher-subscribe pattern for getting data from the master. But I ran into an issue where I was missing data. I should get telemetry four times a second but I only received every fourth message!

I was quite disappointed at first.

Then I double checked all settings of the OPC Publisher, I found this interesting setting…

Take a good look at:

--oi, --opcsamplinginterval=VALUE
the publisher is using this as default value in
milliseconds to request the servers to sample
the nodes with this interval
this value might be revised by the OPC UA
servers to a supported sampling interval.
please check the OPC UA specification for
details how this is handled by the OPC UA stack.
a negative value will set the sampling interval
to the publishing interval of the subscription
this node is on.
0 will configure the OPC UA server to sample in
the highest possible resolution and should be
taken with care.
Default: 1000

Although we are subscribed to receive for every message, it can be ‘throttled’.

And look at the default interval, 1 second.

When I changed it to 200 (200 milliseconds), I received all messages.


This is a quickstart regarding OPC-UA. There is a lot more to discover. But this will help you on your journey.

Do not forget to add actual security, the code shown here is not what you want to deliver in a production environment.


Een reactie op “Getting started with OPC-UA on Azure IoT Edge

Reacties zijn gesloten.