UA Ansi C Server Professional  1.3.1.232
 All Data Structures Functions Variables Typedefs Enumerations Enumerator Groups Pages
SDK Tutorial - How to create a new data provider

There are two main development tasks to implement an OPC UA Server using the SDK.

One is to integrate the SDK and the UA Server into a new or an existing application. The second task is to integrate the data sources into the SDK. This tutorial gives an introduction on how to integrate data sources into the ANSI C UA SDK by implementing a data provider. It doesn't cover everything. The emphasis is on teaching how to quickly create a new Data Provider with new address space and new IO data.

Please read the Introduction section before working through this tutorial.

Contents:

Source Structure

Before we start we have to take a look at the SDK source structure.

FolderDescription
uaservercMain UA Server source folder containing the generic server sources.
uaserverc/toolsFolder containing some helper 'classes' like container (TurboList, TurboStack, etc.).
uaserverc/providersFolder containing all data providers.
uaserverc/providers/serverFolder containing the Server Provider which implements the Server address space defined by the OPC UA Specification.
uaserverc/providers/sampleFolder containing a simple sample provider with demo values.
uaserverc/providers/xyzFolder containing your vendor specific XYZ provider.

Creating a new provider

If you want to create your first data provider it's the easiest way to just copy the sample provider and rename the files. A basic provider should contain these files:

FileDescription
uaprovider_xyz.hContains provider function definitions. Normally only UaProvider_XYZ_Initialize for initializing your provider.
uaprovider_xyz.cImplements the provider initialization and cleanup.
xyz_read.cImplements the read service of the provider interface.
xyz_write.cImplements the write service of the provider interface.
xyz_subscription.cImplements the subscription functionality described in Provider Subscription Mechanism
uaserver_helper.hContains generic helper functions for using the provider callback interface.

Implementing UaProvider_XYZ_Initialize

Every provider has to implement a Initialize function with the following signature. This is the main entry point to setup all other functions a provider may provide.

IFMETHODIMP(UaProvider_XYZ_Initialize)(
UaServer_Provider *a_pProvider,
UaServer_pProviderCBInterface *a_pProviderCBInterface,
UaServer_pProviderInterface *a_pProviderInterface)
{
OpcUa_StatusCode uStatus = OpcUa_Good;
// TODO
return uStatus;
}

This is called when loading the provider and has the following purposes:

  • The server passes the provider context to provider.
  • The server passes the provider callback interface to the provider. The provider should store this pointer to be able to call the server later.
  • The provider must fill the provider interface table with it's own functions pointers so that the server is able to call provider functions.
  • The provider can do some initialization work like adding new nodes to the address space or setting up the underlying communication.

Implementing UaProvider_XYZ_Cleanup

This is called from the Server SDK before the provider is unloaded to give the provider the chance to cleanup it's resources.

IFMETHOD(Cleanup)(OpcUa_Void)
{
OpcUa_StatusCode uStatus = OpcUa_Good;
// TODO
return uStatus;
}

Dynamically Linking a Provider

Providers can also be compiled as Dynamic Link Libraries (aka shared objects). In this case you have to provide an exported Dll function InitializeProvider which calls the UaProvider_XYZ_InitializeProvider function. All other functions will be accessed through the Provider Interface Table and do not need to be exported. You can use the define UAPROVIDER_STATIC to check if providers are linked statically or dynamically. See Start up code for UA Stack and UA Server to see how to load dynamic and static providers.

//============================================================================
// Exported Initialization Wrapper For Dynamically Loadable Providers
//===========================================================================
#ifndef UAPROVIDER_STATIC
IFMETHODIMP(InitializeProvider)(OpcUa_Handle a_hProviderHandle,
UaServer_pProviderCBInterface *a_pProviderCBInterface,
UaServer_pProviderInterface *a_pProviderInterface)
{
return UaProvider_XYZ_InitializeProvider(a_hProviderHandle,
a_pProviderCBInterface,
a_pProviderInterface);
}
#endif // UAPROVIDER_STATIC