OPC UA Concepts and Implementation

OPC UA is a platform-neutral standard that allows systems and devices to communicate and exchange messages over multiple types of networks. It defines a set of services that servers would implement and clients request. The services are based on an authenticated session and a secure channel. Three transport protocols are defined: OPC UA TCP, SOAP/HTTP, and HTTPS as well as a couple of data encoding: UA Binary and XML/Text. In the rest of the posts, only OPC UA TCP and UA Binary are discussed.

The OPC UA specification is quite large and is included in more than a dozen documents. In this post, we will only present the fundamental concepts.

Definitions

  • A node is the fundamental component of an address space
  • A NodeId is the unique identifier of a node
  • Each node belongs to a class.
  • Classes inherit from the base node class
  • The standard node classes are defined as: Object, Variable, Method, ObjectType, VariableType, ReferenceType, DataType and View
  • Each node has a set of attributes which depend on the class of the node
  • The base node class has the following attributes: NodeId, NodeClass, BrowseName, DisplayName, Description
  • In addition to the base class attributes, classes will have their specific attributes.
  • The variable node class has also the value, data type, value rank, array dimensions, access levels, minimum sampling interval and historizing as attributes
  • An endpoint is the set of URL, security algorithms and parameters used to connect to the server

Open Secure Channel

The connection starts with the creation of a secure channel. The client establishes a TCP connection with the server then sends a ‘Hello Message’. The server replies with an ‘Acknowledge’  (or an ‘Error’) message. During this initial handshake, information such as the maximum number of message chunks, the maximum response size, and the size of send and receive buffers are exchanged between the client and the server. The next step for the client is to send the ‘Open Secure Channel’ message which includes:

  • A certificate identifying the client unless the security mode is set to None in which case this parameter is ignored
  • The request type stating whether the secure channel should be created or renewed
  • An identifier when renewing the secure channel, otherwise left to null.
  • The security mode of the secure channel which indicates whether messages should be signed and/or encrypted
  • A random byte string called client nonce used by the client and server to generate the symmetric keys. The keys are used to encrypt messages.
  • The secure channel lifetime requested by the client. The lifetime is the amount of time that the client and server should wait before renewing the channel.

If everything goes well and the server accepts to open a secure channel, the response includes:

  • A random byte string called server nonce used by the client and server to generate the symmetric keys. The keys are used to encrypt messages.
  • A security token that includes:
    • A unique identifier for the secure channel
    • A token identifier which should be passed with each message and updated  when the secure channel is renewed
    • The time when the security token was created
    • The revised secure channel lifetime

Find Servers and Get EndPoints

After establishing a secure channel, the client will typically request the list of servers known to the (discovery) server using the ‘Find Servers” service. The client can then select one of the servers returned to request the list of endpoints using the ‘Get EndPoints’ service. An endpoint includes, among other things, the following information:

  • The endpoint URL
  • The server certificate associated with the endpoint
  • The endpoint security mode stating whether the messages must be signed, signed and encrypted, or none
  • The security policy URI that defines the security profile and mode. The security profile defines the security algorithm and parameters such as key lengths.

Create and Activate Session

Before using the rest of the services, the client must create a session. When creating a session, the client provides, among other things, the session name, a random byte string, and the client certificate. The server replies, among other things, with a unique session nodeId, an authentication token (used in request headers to identify the session), a random byte string, the server certificate, and the ‘server signature’. The server signature is calculated by appending the client nonce and certificate then signing it with the server’s private key. The client uses the server certificate to verify the server’s signature.

Once the session created, it needs to be activated. To activate the session, the client sends, among other things, a ‘client signature’ and the user credentials when required. The server replies with a ‘server nonce’, which is a random number, of at least 32 bytes, that the client can use to prove possession of its certificate in the next call of ‘Activate Session’.

Browsing the address space

The client can use the ‘Browse’ and ‘Browse Next’ services to navigate the server’s address space. The result of the ‘Browse’ service is a list of nodes based on the parameters passed in the request. The ‘Browse Next’ is used when the result is too large to be passed in one single ‘Browse’ request.

Subscriptions

Subscriptions are used to report notifications to the client. They serve as logical containers for monitored items. When sending the ‘Create Subscription’ request, the client includes:

  • The requested publishing interval. The publishing interval determines how often the server should be sending notifications to the client.
  • The requested lifetime. The subscription lifetime is the maximum amount of time without receiving a ‘Publish’ request from the client, after which the server should delete the subscription.
  • The maximum keep alive count. The keep-alive is the number of publishing intervals without sending notifications to the client, after which the server must send a keep-alive message to keep the subscription alive.
  • The maximum number of notifications per ‘Publish’ response.
  • The subscription ‘enable’ state. If set to false, the subscription is created disabled.

The server replies with the subscription identifier, revised values for the publishing interval, the lifetime, and the maximum keep alive count.

For the subscription to stay alive, the client must keep sending ‘Publish’ messages.

Monitoring Data

For the client to receive data change notifications, it must add ‘Monitored Items’ to the subscription. When creating monitored items, the client includes, among others, the nodeId, the attribute to monitor, the requested sampling interval, and the sampling mode (reporting, sampling, or disabled). Once the monitored items created, the client must keep sending ‘Publish’ messages to the subscription to receive change notifications in the ‘Publish Response’.

Attributes Services

This set of attributes can be used to read and write current and historical data.

  • Read  is used to read one or more Attributes of one or more nodes
  • Write is used to write values to one or more Attributes of one or more nodes
  • ‘History Read’  is used to read historical values or events of one or more nodes
  • ‘History Update’ is used to update historical values or events of one or more nodes

OPC Classic Concepts and Implementation

Before the OPC era, industrial applications had to carry the burden of maintaining their own communication drivers. The OPC standard provided a common method for accessing data. Consequently, OPC client applications can access all sorts of devices such as PLC, DCS, RTU…etc, using the same interfaces.

OPC classic is based on a Microsoft interprocess communications standard called COM. A COM component is identified by a CLSID or its user-friendly version called ProgID. COM components expose their services through interfaces that users can query then use to interact with the components. The interfaces are defined using the IDL language.

OPC Classic is a set of specifications, each one defines a set of COM interfaces. For example, Data Access Specification defines interfaces to access real-time data.

In order for an OPC client to connect to a server, it needs the server’s ProgID and hostname. Once connected, the client queries the interfaces from the server as shown in the code snippet below:

// retrieve CLSID from user friendly ProgID
Type opcServerType = Type.GetTypeFromProgID(progId, machine, false);
if (opcServerType != null)
{
  // connect to OPC server using CLSID
  opcServerObject = Activator.CreateInstance(opcServerType);
  // query IOPCServer interface using a simple cast
  opcServer = opcServerObject as IOPCServer;
  if (opcServer != null)
  {
     opcCommon = opcServerObject as IOPCCommon;
     opcBrowse = opcServer as IOPCBrowseServerAddressSpace;
     opcItemProperties = opcServer as IOPCItemProperties;
     opcConnectionPointContainer = opcServerObject as IConnectionPointContainer;
     // ...
     // do something useful with the interfaces
     // ...
  }
}

OPC Interfaces

The list below shows the main responsibilities of the most important OPC DA interfaces:

  • IOPCServer is used by a client to add/remove groups and retrieve the server status information
  • IOPCBrowseServerAddressSpace is used by a client to browse the server’s address space and provide the user with a graphical representation of the address space hierarchy
  • IOPCItemProperties retrieves item properties
  • IOPCItemMgt adds, validates and removes items
  • IOPCSyncIO allows the client to perform synchronous read and write requests
  • IOPCAsyncIO2 same as above except that the requests are non-blocking
  • IOPCDataCallback is a client interface used by the server to notify the client about changes in item values and qualities

OPC Item

An OPC item is the simplest unit of information provided by a server. An item might correspond to a physical I/O such as a relay state, a temperature or humidity value, a robotic arm position… or a value in memory such as the constants of a PID algorithm…

An OPC item has static properties, such as the canonical datatype, the description, the engineering unit…etc and runtime properties such as the value, the quality (level of confidence in the value provided), the timestamp of the latest change in value and/or quality and the item active state.

OPC Subscription

While it is possible for a client to make synchronous or asynchronous calls to read and write, creating a subscription is the most common and efficient way for a client to receive data. Basically, a subscription occurs when the client registers itself at the server in order to receive notifications when item values or qualities change. This method saves CPU/bandwidth by avoiding unnecessary read calls for items that didn’t necessarily change.

OPC Group

A group is a logical container for OPC items, the most important properties of a group are:

  • Active State: when a group is inactive the server stops sending change notifications for all the items that belong to the group
  • Update Rate: The server should not send change notifications to the client faster than the update rate (in milliseconds). When set to zero, the client requests data to be sent as quickly as possible

Be careful, when changing the value of this property, a small value may lead to a situation where data is oversampled which means an increase in the network traffic and eventually an overload of the end controller.

Subscriptions are made at the group level and they use a COM interface called IConnectionPointContainer as illustrated in the code snippet below:

// retrieve the connection point container interface from IOPCGroupStateMgt
// IOPCGroupStateMgt is returned from a call to IOPCServer::AddGroup
callbackConnectionPointContainer = opcGroupStateMgt as IConnectionPointContainer;
// retrieve the callbakc interface GUID
Guid riid = typeof(IOPCDataCallback).GUID;
// retrieve the connection point
callbackConnectionPointContainer.FindConnectionPoint(ref riid, out callbackConnectionPoint);
// use the connection point to register the caller object as recipient of change notifications
callbackConnectionPoint?.Advise(this, out callbackCookie);