November 11, 2025

Creating Custom OPC UA Information Models and Servers Using .NET

Blog Details Image

Building OPC UA applications requires understanding how to create information models that describe industrial equipment and processes. This tutorial demonstrates how to design a custom OPC UA information model using XML, compile it to generate necessary code files, and implement both server and client applications using the OPC UA .NET Standard SDK.

We'll build a complete batch plant information model with sensors, actuators, and callable methods to demonstrate the entire development process.

Three Approaches to Creating OPC UA Information Models

The goal of information model design is to produce a NodeSet2.xml file—a standardized format that all OPC UA compliant SDKs use to generate code and populate the server address space.

There are three main approaches to creating this file:

Manual Text Editing: Type the NodeSet2 file directly using any text editor. This requires extensive experience with the NodeSet2 file format and deep knowledge of OPC UA specifications.

Graphical Modeling Tools: Use specialized software like UA Modeler from Unified Automation or UA Model Accelerator Pro. These tools provide visual interfaces for designing models and automatically generate both the NodeSet2 file and programming language code (C or C#). They also allow importing and modifying existing NodeSet2 files.

Model Design XML Compilation: Design the model using a more intuitive, non-standard XML format, then compile it to NodeSet2. The OPC Foundation provides the UA Model Compiler tool that converts Model Design XML files into NodeSet2.xml files and produces C# classes for .NET servers. The Foundation also provides XML schema definition files for syntax checking and auto-completion during the design process.

This tutorial uses the third approach because it offers a good balance between flexibility and ease of use.

Designing the Batch Plant Information Model

Our demonstration model represents a small batch processing plant with these components:

Three Silos: Each silo holds raw materials and includes a level indicator (sensor) and an analog discharge valve (actuator)

Mixer: Contains a load cell for measuring product weight and a motor for mixing materials before discharge

Packaging Unit: Receives mixed product for packaging operations

Conveyor System: Transports finished product with its own motor

The information model also includes two callable methods—Start Process and Stop Process—that OPC UA clients can invoke to control the batch plant operations.

Creating the Model Design XML File

Setting Up the Document Structure

Begin with an empty Model Design XML file. The outermost element is ModelDesign with opening and closing tags. Inside the opening tag, define the namespaces that associate your model with OPC Foundation XML schema definition files.

Key namespace definitions include:

  • Prefix "opc" for the model design namespace
  • Prefix "ua" for the OPC Foundation namespace
  • A default namespace for your custom model

Map these namespace prefixes to their corresponding URLs for proper identification.

Defining Generic Types

Start by defining generic types that serve as templates for specific equipment instances. Since the batch plant contains multiple similar objects (sensors, actuators, motors), create generic types first, then derive concrete implementations from them.

Generic Sensor Type: Inherits from the OPC UA base object type node class. Contains two children:

  • An output variable of type double (the sensor reading)
  • A units property of type string (measurement units)

Generic Actuator Type: Also inherits from the base object type. Contains:

  • An input variable of type double (setpoint)
  • An output variable showing current position

Generic Motor Type: Inherits from the base object type with a speed variable as its child property.

Creating Concrete Types

After defining generic types, create concrete implementations for specific equipment:

Level Indicator Type: Inherits from Generic Sensor Type for measuring material levels in silos

Load Cell Transmitter Type: Also inherits from Generic Sensor Type but extends it by adding an excitation voltage property specific to load cell operation

Valve Type: Inherits from Generic Actuator Type for controlling material flow

Mixer Motor Type and Conveyor Motor Type: Both inherit from Generic Motor Type but represent distinct motors in the system

Organizing Equipment into Container Objects

Define types for equipment containers that group related components:

Silo One Type: Inherits from UA Folder Type (since it organizes elements in a tree structure) and contains:

  • Silo one level indicator (of Level Indicator Type)
  • Silo one valve (of Valve Type)
  • Event notifier references

Create similar definitions for Silo Two Type and Silo Three Type.

Mixer Type: Contains load cell transmitter, mixer motor, and discharge valve, all organized under a folder type structure.

Packaging Unit Type: Contains its level indicator.

Conveyor Type: Contains the conveyor motor.

Defining the Complete Batch Plant

Create the Batch Plant Type that inherits from the OPC UA base object type and composes all subsystems:

  • Silo One (of Silo One Type)
  • Silo Two (of Silo Two Type)
  • Silo Three (of Silo Three Type)
  • Mixer (of Mixer Type)
  • Packaging Unit (of Packaging Unit Type)
  • Conveyor (of Conveyor Type)
  • Start Process method
  • Stop Process method

Declaring an Instance

Finally, declare an instance of the Batch Plant Type called "Batch Plant Number One." This creates the actual object that will appear in the OPC UA server address space, linking it to the Objects folder where OPC UA clients can discover it.

Compiling the Model Design

The UA Model Compiler converts your Model Design XML into the standardized NodeSet2 format and generates C# code.

Getting the UA Model Compiler

The UA Model Compiler is available on GitHub but doesn't include a pre-built executable. Clone the repository to your computer, open the solution in Visual Studio, ensure you're in Release mode, and build the solution. The executable appears in the bin/release folder.

Running the Compilation

The compiler requires three arguments:

  1. File path to your Model Design XML
  2. File path for the CSV output (lists all nodes)
  3. Output file path for generated files

Open PowerShell, navigate to the compiler executable directory, and run the compilation command with your file paths.

After successful compilation, the output directory contains:

  • C# class files for your information model
  • CSV file listing all nodes
  • NodeSet.xml file
  • NodeSet2.xml file (the standardized format)

The NodeSet2.xml file contains all nodes from your information model in the format that OPC UA servers can import.

Creating the OPC UA Server in .NET

Setting Up the Server Project

Create a new .NET Console Application in Visual Studio. Install the OPC Foundation .NET Standard SDK through NuGet Package Manager by searching for "OPC.UA.Core."

Adding the Information Model

Copy your generated C# class files and NodeSet2.xml file into the project directory. These files contain the code representation of your batch plant model.

Implementing Server Functionality

Configure the server with application settings including name, URI, security settings, and endpoint configurations. Create the server instance and load your NodeSet2.xml file to populate the address space.

Implement the Start Process and Stop Process methods that clients can call. Add simulation logic to generate realistic sensor values (for example, level indicators, load cell readings).

Start the server, which begins listening for client connections on the configured endpoint.

Creating the OPC UA Client in .NET

Setting Up the Client Project

Create another .NET Console Application and install the same OPC Foundation .NET Standard SDK through NuGet.

Implementing Client Functionality

Configure the client application with similar settings to the server (application name, URI, security configuration). Specify the server endpoint URL to connect to—copy this from the running server application.

Create a session with the server and implement browsing functionality to navigate through the address space. Starting from the root Objects folder, recursively browse through nodes, displaying their:

  • Display name
  • Browse name
  • Node class type
  • Node ID

Testing the Implementation

Run the server application first to ensure it's listening for connections. Then run the client application. The client connects to the server and displays the batch plant structure:

  • Batch Plant Number One (the instance)
  • Silo One, Two, and Three with their components
  • Mixer with load cell and motor
  • Packaging Unit
  • Conveyor
  • Start Process and Stop Process methods

Test with a graphical OPC UA client like UA Expert to verify the server exposes the information model correctly. Browse through the address space, read sensor values, and invoke the Start Process and Stop Process methods.

Summary

Creating custom OPC UA information models involves designing the model structure in XML, compiling it to generate NodeSet2 files and programming language code, then implementing server and client applications using the generated code.

The process starts with defining generic types that serve as templates, creating concrete types for specific equipment, organizing components into logical containers, and finally declaring instances that appear in the server address space.

The OPC Foundation's UA Model Compiler and .NET Standard SDK provide the tools needed to transform information model designs into working OPC UA servers and clients. This approach enables standardized communication between industrial equipment and software systems, supporting interoperability across different manufacturers and platforms.