High Performance OPC UA Server SDK
Provider Architecture


A provider is responsible for providing access to its address space and data requested by different OPC UA services like read or write. Most servers have at least two providers, the Server Provider and at least one provider for handling the application specific data. Each provider can be responsible for one or more namespaces. An example of how to implement a provider can be found at Lesson 2: Custom Provider with Value Stores.

Server Provider

The server provider is already implemented and included in the SDK and must be loaded as first provider in every server. It handles the special namespace with index zero defined by the OPC Foundation and the diagnostic namespace with index one.

Register Addressspace

The provider must register and create the part of the address space it is responsible for. There are currently three approaches to do so:

  • Create nodes manually: Register a new namespace with ua_addressspace_register and create nodes and references manually as shown in Lesson 2: Custom Provider with Value Stores. This is an easy way to get started, but hardly feasible for larger address spaces.
  • Load from binary file: Convert a XML file containing your address space into the SDK's binary format using the provided xml2bin tool, then load the address space from the generated file using ua_addressspace_load_file. This is useful for large address space that are already in XML format or created by tools with XML export functionality like UaModeler.
  • Load form C source file: Use the provided xml2c tool to convert a XML file to a C source file with all the address space information. This source file must be included into your provider and the containing address space must be registered by calling the function register_static_addressspace that is part of the generated source file.

All of the register addressspace functions return the namespace index of the newly registered address space on success. Each of these namespace indices the provider handles must be registered at the provider management using uaprovider_register_nsindex. This is necessary for multiplexing subscription services to the correct provider and the internal provider to work properly.

For further details about the address space, see the corresponding chapter Address Space.

Provider Interface

For the provider to be able to handle certain OPC UA services it must register its service handler functions. These must be set at the uaprovider during provider initialization and are called by the SDK when the corresponding service request is encountered. The following handlers can be set:

Service Description
read Called for the Read service
write Called for the Write service
call Called for the Call service
registernodes Called for the RegisterNodes service
unregisternodes Called for the UnregisterNodes service, must match the registernodes implementation
add_item Called for the CreateMonitoredItems service, each item is added separately
remove_item Called for the DeleteMonitoredItems service, each item is removed separately
modify_item Called for the ModifyMonitoredItems service, each item is modified separately
subscribe Called when all MonitoredItems handlers are called and the provider may finish an async operation

For simple implementation of these handlers the Internal Provider can be used.

There are two more function pointers that can be registered, that are not related to OPC UA Services:

Handler Description
cleanup Called when the server shuts down, so the provider can cleanup any allocated resources
node_delete Called when a node from this provider is deleted from the address space

All of the handler functions are optional, however your server may lack vital functionality if e.g. the read service is not implemented.

Internal Provider

The internal provider is not an actual provider, but implements some of the service handlers in a generic way. So a provider may not need to implement these itself, but can use the provided service handlers for all or part of its service implementation.

The implementation of the read, write and monitoreditem services of the internal provider use the Value Store to access values, so they can only be used by providers that use a valuestore to access their values.

The registernodes and unregisternodes services are optimized to the address space implementation, so it is always recommended to use the internal provider for these service handlers.

Value Store

The valuestore is a mechanism for the SDK to access values stored by a provider. A provider can use a valuestore implemented by the SDK or implement its own valuestore and use it to store its values. The valuestore must then be registered at the SDK and is used to access the value attribute in the read and write service by the Internal Provider. It is also possible for one provider to access the values of another provider using uaserver_read_internal and uaserver_write_internal.

The valuestore is limited to use cases where the value can be accessed synchronously, so it can only be used for direct IO or cached IO. To implement an own valuestore ua_valuestore_interface must be implemented and registered with ua_valuestore_register_store.

Lesson 2: Custom Provider with Value Stores gives and example how to use and implement valuestores.