In the last article we had the opportunity to introduce OPC UA by discussing its history and key features.
Today we take a step further towards the development of an OPC UA server and, in particular, we focus on the definition of a data model describing a simple production line composed of some industrial components.
By the end of this article, we’ll have everything ready for our own OPC UA server.
To start our journey well, it is first necessary to be clear about what we want to describe.
In our case, let’s imagine we have a simple machine composed of a motor to move a conveyor belt, a temperature sensor and a proximity sensor:
We want to describe this architecture so that we have a usable model later to develop our server.
In order to describe the model just presented, according to the OPC standard, it is necessary to produce an XML file called NodeSet2 that acts as the ultimate interface with the OPC UA servers. There are several ways to accomplish this:
- Produce the Nodeset2.xml file manually;
- Use a graphical tool such as ModelDesign;
- Use the UAModelCompiler tool provided by the OPC Foundation.
Starting with the former, it is not to be considered a good practice to write NodeSet2.xml files on your own, as this requires a deep knowledge of the standard as well as being an error-prone method.
The use of graphical tools, then, could seem a good compromise, the problem is that at the time of writing I can not say that there are so advanced to be taken as a reference.
It remains for us to delve into the third point that will inevitably be our choice.
The OPC Foundation over the years has defined a standard for describing models called Model Design.
This is always based on the writing of an XML file much more intuitive, however, than its counterpart NodeSet2.
To write this file, we can safely use a text editor. Once finished writing, we can make use of the UAModelCompiler tool to compile the model and generate the NodeSet2.xml file along with a whole set of important data such as C# classes and metadata needed to create the server.
XSD Editor Setup
At this point it is worth pausing for a moment to prepare some tools that will make our life easier. We can think of writing our XML without any help, but how much better would it be to have an editor to guide us while typing the various elements?
In this regard, when it comes to XML there is a standard that allows you to quickly extend the functionality of the most popular development editors, namely XSD (XML Schema Definition) files.
An XSD file is nothing more than a set of rules that can be imported into an editor. Once done, it will be the editor itself to suggest us the commands to write while we develop our model and to signal us eventual errors committed.
In this article we see how to import the XSD provided by OPC Foundation in Visual Studio, the editor that I will use to develop this project. It is obviously possible to import this file also in other editors such as IntelliJ, Notepad++ and others.
So, the XSD of our interest should be copied from the official github repository reachable here.
Once downloaded and saved locally (UAModelDesign.xsd), we open Visual Studio, choose to continue without code:
Once the editor is open, click on File -> Open -> File.
In the window that opens select UAModelDesign.xsd and load it.
Now create a new XML file by clicking on File -> New -> File -> XML File.
At this point you can write models in a guided way.
OPC UA Model Design
Well, we said we want to describe the previously discussed template.
A good place to start is with the template I’m putting below, which is the basis from which to begin any future development.
In the template, first of all we start with the definition of the file type (lines 1-9) which we have already said is an XML.
We then go on to define the application namespace, which is the workspace of our server, which as you may have seen we will call OPCUAServer. This is defined in lines 10-13.
Be sure to copy the contents of the template inside the XML file created earlier in Visual Studio.
The Generic Types
As mentioned in the last article, the OPC UA data description model allows us to treat data with the same concepts as object-oriented programming.
So we want to describe a generic sensor type that can act as a base class for the sensors actually installed in our machine.
This parent sensor, will have a read-only value that will represent the sensed data.
Adding a generic type is a very simple operation. You must define an ObjectType and then specify its name and class.
In OPCUA all objects are derived from the base node BaseObjectType.
The attributes of a node are specified within the Children tags, in this case we have a read-only variable of type double called Value.
Great, now we can move on to create the two types of sensors installed in the car: temperature and proximity.
We finish the definition of our starting nodes by defining the motor that will move the conveyor belt.
In this case, we would like to be able to both read and write the speed at which the motor is rotating and to be able to control its on/off.
It will therefore be necessary to add remote methods. Let’s go and see how this is done:
This time, in addition to the classic notation used to create a node with attributes, we have both specified a read and write access level and added two remote methods visible in lines 5 and 6.
Great, so far we’ve defined generic types that describe possible sensors and motors. Now, we want to create a container that will represent our machine.
Unlike the previous nodes, the BaseType of this one will be a FolderType that will then be displayed in our server as a container folder.
Inside this folder we will have our sensors and our engine. Let’s go over how to write the XML:
Inside MachineType, we have inserted 3 nodes of type Object that this time are no longer abstract definitions of types, but are real instances of the nodes previously defined.
In line 3 we have created a temperature sensor, in line 6 the proximity sensor and in line 9 the motor.
All three have the SupportEvents field set to true. This value allows to associate events whenever one of the attributes changes.
To finish our model, it is now time to create a generic node that will represent our machine and, finally, the node from which we will cascade all the objects defined so far:
With lines 1 through 8, we create a node that will represent the server once created.
The server will consist of a machine of type MachineType (line 4).
Having defined this, in lines 10 and 11, we finally create an instance of the OPCUAServerType node called OPCUAServer1.
Finally in lines 12-17, we link this instance to the ObjectFolder of the OPC UA server.
Now that we have the model ready, we just have to compile it.
Compilation allows us both to verify that the model is correct, and to produce the files needed for further development of the server.
As introduced earlier, the compilation of the XML file is possible thanks to the OPC Foundation tool called UA-ModelCompiler.
In order to use it on Windows, you first need to clone the code from the official repository:
Before opening the Visual Studio project, we need to download and install two .NET Developer Packs:
Once the installation is finished, we open the UA-ModelCompiler project from the previously cloned folder, clicking on the ModelCompiler Solution.sln file and proceed to build the solution.
Perfect, if all went well you should now have an executable in the Debug or Release folder.
Let’s open a powershell window in this folder and run the following command:
By doing so we are asking the ModelCompiler to take the xml saved in the path specified as first parameter (-d2), validate its correctness and create the files in the output paths specified in the next two parameters.
In this article we have focused on how to create a model to compile then with the tool developed by OPC Foundation.
The output of this phase are a series of files that we will use to design, in the next article, our server.