OPC UA for Multitenant Applications

OPC UA is an industry standard for machine-to-machine communication extensible enough to run in a multitenancy environment such as enterprise cloud platforms.

In my recent article, I focused on the basic concepts of OPC UA with regard to the most typical use-case: OPC UA server running on a device such as a steamer or coffee machine. However, OPC UA is not limited to the use case and could also be successfully implemented as a multitenant service.


Let us briefly summarize what OPC UA is and why we should care:

OPC UA (Open Platform Communications Unified Architecture) is an open industry standard defining an interface and modeling system for machine-to-machine communication. It is mainly used in industrial automation for standardized read-and-write access to current and historical data.

OPC UA uses the client-server approach, where the server typically encapsulates the device data and makes it available to the client via a well-defined interface. An OPC UA application can be both server and client to enable machine-to-machine communication.

Data modeling in OPC UA uses object-oriented techniques including type hierarchies and inheritance to describe systems of arbitrary complexity. The data structure of an OPC UA server is self-descriptive and enables the client to navigate through instances and types with little or no prior knowledge.

OPC UA describes platform and vendor-independent service-oriented architecture. The complete software stack can be implemented with C/C++, .NET, Java, or JavaScript. OPC UA is not limited to these programming languages and development platforms.

OPC UA specifies data encoding, security, and transportation with the focus on reliability, robustness, scalability, interoperability and high performance in communication between distributed systems.

OPC UA is extended by a bunch of companion specifications for specific purposes (e.g. commercial kitchen equipment).

Why OPC UA in the Cloud

Looking at the OPC UA designers' architectural decisions, we do not see any clash in the concepts of modern cloud platforms.

Bringing OPC UA to the cloud would make the life of operators easier in many ways while retaining all of its benefits: Centralization of a platform-based solution allows the client to manage multiple and potentially heterogeneous devices from a single place in the same manner. As all data are stored in one place, heuristic analysis could be performed on data from multiple sources. Remote access would remove the burden of physical presence commonly required for on-premises devices usually via access to the local network that the device is connected to. Security Security in a cloud platform is well-defined and globally applied and does not have to be solved individually per device. Integration with standard protocol should be worked out by any platform with ease. Even devices that do not implement OPC UA themselves could publish data via OPC UA with a cloud platform in the middle.

Cloud platform with an OPC UA interface
Cloud platform with an OPC UA interface

Running OPC UA applications in the cloud would extend its features for convenient functionality which would be welcomed by many users!

For OPC UA clients, the platform is fully transparent, so little or no change will be needed in existing programs. In fact, clients would see no difference in working against a cloud platform or a device directly. Moreover, clients could consume data from multiple devices via a single connection.

On the other hand, the platform providers would obtain their desired insights into the device data and valuable feedback which would deliver a definite advantage on the market.

OPC UA on a Device

The setup of an OPC UA application can differ significantly from device to device. The most commonly used setup, popular among manufacturers and deployed on various kinds of machines, is as ingenious as follows:

Traditional on device OPC UA setup
Traditional "on device" OPC UA setup

The OPC UA server is running on the device and the operator can directly access it via an OPC UA client such as a Python script. This setup is notoriously simple and easy to implement. However, it places a huge burden on the operator.

As devices like coffee machines or combi steamers are usually not exposed to the Internet, the operator needs access to the local network. This typically means that she must be physically present at the location where the device is placed. This is not very practical if the company has stores in the US as well as in Europe. Global device management and monitoring are also almost impossible for the same reasons.

Bringing the device data to an OPC UA compliant cloud platform would not only remove the burden and enable a centralized kind of solution, but also makes it possible for the operator to leave the management and maintenance completely to the platform provider.

OPC UA as a Service

Shifting to an OPC UA-based cloud platform brings a lot of challenges. Let us analyze the new requirements in comparison to a traditional "on device" solution.

A cloud platform is by definition a multi-tenant system. It contains multiple accounts, users, and devices. The response from the server must be dynamically constructed based on the given request. Devices could be dynamically added and removed and the view on them must be restricted based on the user privileges. Client A can never see devices owned by client B and vice-versa. This is very different from the traditional setup where a server running on a device contains a static structure that simply reflects the device itself.

Multi-tenant platform with dynamic nodes
Multi-tenant platform with dynamic nodes

A good platform must also act transparently for its users. This means that once a connection is established, a user will not spot any difference whether the communication is carried out via the platform or directly with a device. Existing programs do not need any changes made.

Platform communication is transparent
Platform communication is transparent

It is not only functional requirements that need to be taken into account. Practical and cultural requirements are no less important.

A cloud platform usually provides its functionality via stateless HTTP endpoints creating a conventional structure known as REST API. Such endpoints are easy to use, understand and design. REST APIs are dynamic but stable. For instance, an endpoint /device/{id}/sernum for reading a serial number of a particular device identified by an ID has a stable and solid URI that can be used in client programs as a constant while it will dynamically work for all devices.

Last but not least, enterprise software such as cloud platforms is typically built using high-level programming languages and environments such as Java (JVM) or C# (.NET). An OPC UA server that runs on a device is, on the other hand, likely written with a low-level C/C++ stack.

Dynamic Node Manager

To satisfy all of the above mentioned functional and non-functional requirements, we need the sort of node manager that would be able to create statically-addressable nodes dynamically based on the user context. The dynamic node manager would intercept every request and handle it in a REST-ish manner. For instance, a node providing a serial number as a property of a device would have a dynamic node definition Device<ID>/Sernum where <ID> is a mandatory placeholder provided by the client and resolved by the node manager on the fly. A client would query a concrete node ID Device123/Sernum where 123 is a unique identifier of a particular device in the platform. The node manager searches the device with ID 123 and responds with its serial number as to whether it exists and belongs to the client.

Dynamic node manager intercepts the client request
Dynamic node manager intercepts the client request

Dynamic nodes should be easy to use and develop. Ideally via a simple configuration to assign a backend that holds the device data:

var node = new DynNode("Device<ID>/Sernum", ::getSernum)

The pseudo-code above creates a new dynamic node definition and assigns a function to retrieve data from the backend service. The function has a signature as follows:

String getSernum(Int id, ClientContext ctx)

The dynamic node manager must call the backend with the resolved device ID as well as the context of the current client to allow the backend to decide if the client has permission to access the device:

String getSernum(Int id, ClientContext ctx) {
  var device = findDeviceById(id)
  if (!device || !device.ownedBy(ctx.clientId)) {
    throw new Error("Cannot access device")
  return device.sernum

In addition, it would be handy to construct nodes as hierarchies. For instance, create the device node (Device<ID>) first and assign the serial number node (Sernum) to it afterward:

var sernumNode = 
  childVariable("SerialNumber", ::getSernum).

OPC UA Dynamic Node Manager Java Library

The popular Java OPC UA SDKs Prosys and open-source Eclipse Milo provide flexible solutions for OPC UA on the server side with possibilities of intercepting client requests with custom logic, but none offer the functionality of dynamic nodes out of the box.

Fortunately, there is a small free open-source library written in Java that aims to work seamlessly with OPC UA Java SDKs Prosys and Eclipse Milo (planned). This library offers all desired functionality of a dynamic node manager.

It works as a plug-in to the existing OPC UA server to extend its functionally of dynamic node definitions. The dynamic node definitions are independent of the SDK so the very same code could be used with different vendors just by switching to a different vendor-specific adaptor. An adaptor serves as a bridge between a particular SDK and dynamic node definitions. This makes the library very extensible as a new adaptor could be created for any SDK.

The library is flexible enough to create complex structures of dynamic nodes and is easy to use thanks to a handful of fluent builders.

Check it out on GitHub!

OPC UA dynamic node manager meme