OPC UA Implementation With open62541
Introduction
The open62451 is an open source, free implementation of OPC UA for C and C++. It is platform independent, where platform specific functionality can be added via plugins.
OPC Unified Architecture
Information is sourced from the official documentation. OPC UA is applicable in all industrial domains, ranging from industrial sensors and actuators to control systems and IoT systems. It establishes a common infrastructure model for facilitating information exchange, command execution, and control within industrial processes.
Protocol
Used protocols can be TCP, HTTP or SOAP, all three protocols share the same general concepts. Messages are exchanged via sessions.
-
Request/Response: All communication is based on these 2 concepts. Clients can only send request, while Servers can only answer to requests with responses.
-
Asynchronous Responses:Responses do not need to be sent immediately upon receiving a request; they can be dispatched in a different order than the requests themselves.
-
TCP Connection: The TCP connection is established by a HEL/ACK message handshake, connecting to a hostname and port. The reverse connect extension allows the server to initiate the connection.
-
SecureChannel: It is created on top of the TCP connection and is mandatory, although it doesn’t necessarily mean the connection is encrypted (encryption can still be disabled). The service can be invoked without a session and an encrypted SecureChannel, enabling clients to discover new endpoints and subsequently utilize appropriate encryption.
-
Session: Sessions are built on top of a SecureChannel, initiated by the exchange of two messages: CreateSession and ActivateSession (which can also be used to change the SecureChannel).
Information Modelling
It is represented by a graph with nodes and references between them. Nodes: There are 8 possible NodeClasses
-
Variable, VariableType
-
Object, ObjectType
-
ReferenceType, DataType
-
Method, View
Each node has a unique IDNode and carries different attributes depending on the NodeClass. These attributes can be read or written via the OPC UA protocol. Nodes and References can be created or removed at runtime, although not all servers support this. All node attributes can be found here,
References: These are links between nodes and can be typed or directed. They consist of a triple: Source Node ID, Reference Type, and Target Node ID (which can even point to a different server). Some references are hierarchical and cannot form loops.
Additional Information
OPC UA PubSub is an extension that enables many-to-many communication within the OPC UA framework. It diverges from the traditional client-server protocol and instead integrates with existing protocols like MQTT, UDP multicast, and more. Typically, an OPC UA Server is employed to configure and manage PubSub communication.
Library
open62451
Open62451 is an open source implementation of the OPC UA. It is licensed under MPLv2, meaning it can be combined and redistributed with any proprietary software.
Features
The open62451 brings various features, that are complaint to the OPC UA standards, it also supports the Micro Embedded Device Server Profile[1]. Feature list :
-
Communication Stack
-
OPC UA binary protocol
-
Chunking large messages
-
Exchangeable network layer for using custom networking APIs (e.g. on embedded targets)
-
Async. and encrypted communication
-
-
Information Model
-
Support for ALL OPC UA node types
-
Support for adding/removing nodes during runtime
-
Access control for individual nodes
-
-
Subscriptions
-
Support for subscriptions for data change notifications
-
-
Code-Generation
-
support for generating data types and generation of server-side information models (nodesets) form standard XML definitions.
-
JSON or XML EN/Decoding is also available to parse encoding as per official OPC UA standard.
Building The Library
All major platforms are supported automatically by the CMake configurations. Also allows building for freeRTOS and building Debian Packages inside Docker containers. All build options and tutorials can be found HERE.
Services
All communication is rooted in service calls, which encompass both request and response messages. While the majority of these services are pre-defined by the standard, users have the flexibility to introduce and utilize custom services. It’s important to note that most of these services reside on the client side, with the server primarily responding to these service requests.
PubSub
Information about PubSub is sourced directly from the offical OPC UA documentation.
In the context of OPC UA Applications, applications play dual roles as Publishers and Subscribers. Communication within this framework is message-based, with Publishers acting as data sources and Subscribers as data consumers. Importantly, they do not necessarily need to be aware of each other’s existence, if at all.
Two different variants of Message Oriented Middleware are supported: broker-less and broker-based forms. Broker-less uses UDP for communication, while Broker-based uses MQTT or AMQP for communication with the Broker.
The open62451 PubSub API uses the following scheme:
-
Create a config. for the needed PubSub element.
-
Call the add function and pass the config.
-
The add function returns the unique ID of the element.
Concepts
Various concepts that revolve around subscribers and publishers and their communication are explained below:
-
DataSet - Constitutes the payload of messages provided by the Publisher and consumed by the Subscriber.
-
Pub & Sub Coupling - Publishers and Subscribers often do not know of each other, their primary relation is the understanding of specific types of data (DataSets), the publish characteristics of this messages that include this data and of the MOM[2].
-
Messages - This are Network Messages that include a header (various possible metadata about the message) and one or more payload (DataSetMessages).
-
DataSetMessage - Created by the DataSet, the application data/payload.
-
DataSetWriter - Is a component of the publisher, it continuously generates a sequence of DataSetMessages.
-
DataSetMetaData - Describes the syntax and semantics of the DataSets.
-
PublishedDataSet - The selection of information for a DataSet in the Publisher and the data acquisition parameters. It can select a list of Event fields or contaion a list of Variables.
DataSet
A list of name and value pairs represents an Event or a list of Variable Values. It can be created either from an Event or from a sample of Variable Values. The configuration of this application-data collector is called a PublishedDataSet. The DataSet fields can be defined to represent any information. For publishing, they will be encoded into a DataSetMessage, which is combined to form the payload of a NetworkMessage.
DataSetMetaData defines the structure and content of a DataSet.
Only the DataSetWriter holds the settings for the encoding and transport of a DataSetMesasage, since they create them.
A DataSetClass is a template for DataSets that declares the content of a DataSet. They hold a unique ID (DataSetClassId). The DataSetMetaData is identical for all PublishedDataSets that are configured based on a DataSetClass. When all DataSets that are instances of DataSetClass are in the same NetworkMessage, it can contain the DataSetClassId.
DataSetMetaData describes the content and semantics of a DataSet (overall attributes) and a set of fields with their name and data type. The order shall match the order in the DataSetMessages.
Subscribers use the DataSetMetaData for decoding the values of a DataSetMessage to a DataSet.
There are various ways that a Subscriber can receive the initial DataSetMetaData. An exchange of new/changed DataSetMetaData can also be done between the Publisher and Subscriber.
Messages
A DataSetMessage field represents a DataSet field within a DataSetMessage. A DataSet field contains the actual value and additional information about the value (e.g., status and timestamp). The DataSet field can be represented as a DataValue (value, status, and timestamp), as a Variant (value or bad status), or as RawData (common status and timestamp) in the DataSetMessage field. This representation depends on the DataSetFieldContentMask.
A DataSetMessage is created from a DataSet and consists of a header and encoded fields from the DataSet. They do not contain information about data acquisition or the information source in the Publisher. They can be either acyclic (such as events) or cyclic. Cyclic DataSetMessages can contain all fields or only the changed ones.
DataSetMetaData defines the fields contained in the DataSetMessage. A heartbeat DataSetMessage is not created from a DataSet.
NetworkMessages serve as containers for DataSetMessages. Individual fields of a DataSetMessage can be marked as promoted fields, intended for filtering or routing and are never encrypted.
Publisher
This is the PubSub entity that sends NetworkMEssages to a MOM. It can support multiple PublishedDataSets and multiple DataSetWriters to multiple MOMs. A DataSetWriter is a logical component of a Publisher.
If the Publisher is a OPC UA Server, it can expose the Publisher configuration in its AddressSpace. Message sending sequence :
-
Collection of data (DataSet) to be published. The configuration for a such a collection is a PublishedDataSet (it also defines the DataSetMetaData). Two concrete options are PublishedDataItems for Vairable base collection and PublishedEvents for Event based.
-
A DataSetWriter takes the DataSet and creates a DataSetMessage. DataSetMessages from DataSetWriters in one WriterGroup can be inserted into a single NetworkMessage. The creation of a DataSetMessage is guided by :
-
DataSetFieldContentMask - attributes of a value that shall be encoded.
-
DataSetMessageContentMask - which header fields shall be encoded.
-
KeyFrameCount - key or delta frame message.
-
The resulting DataSetMessage is passed together with the DataSetWritetId, DataSetClassId, the ConfigVersion of the DataSetMetaData and a list of values that match the configured propagated fields. Afterwards a NetworkMessage is created and shipped.
Subscriber
Subscribers are the consumers of NetworkMessages from the MOM. Once a DataSetMessage is selected as relevant, it will be forwarded to the corresponding DataSetReader for decoding into a DataSet. The resulting DataSet is then further processed or dispatched in the Subscriber.
Message Reception Sequence :
-
A NetworkMessage is received and, if configured, filtered.
-
Each DataSetMessage of interest is passed on to a DataSetReader. Here, the DataSetMetaData is used to decode the DataSetMessage content to a DataSet. The metadata provides the complete field and syntax including the name, data type and other relevant properties.
-
An additional dispatching step may map the received values to Nodes in the Subscribers OPC UA AddressSpace. The configuration for such dispatching is called a SubscribedDataSet. Two concrete options are available, a TargetVariables and SubscribedDataSetMirror. The configuration of TargetVariables allows the dispatching of DataSetMessage fields to existing Variables in the Subscribers OPC UA AddressSpace. The other configuration is used when the Variables don’t exist in the Address Space and need to be created as part of the Subscriber configuration.
Findings
OPC UA is a standard that defines communication between a server and a client. Message exchange can be implemented using various protocols. Our primary focus is on the TCP/IP server and the PubSub server, which is implemented using the MQTT protocol.
Building The open62541 Library
Version 1.4 of the open62541 library should be used, since it brings improved basic features and improved PubSub MQTT features. Building is supported for all platforms, I will only explain how to do it on Linux based systems, the C-Make options are the same on all platforms.
Build steps for Linux :
-
Clone the GitHub repository :
git clone https://github.com/open62541/open62541.git
-
Create a new Branch for version 1.4 :
git checkout -b 1.4 origin/1.4
-
Update the submodules :
git submodule update --init --recursive
-
Create a build directory and move into it :
mkdir build && cd build
-
Run C-Make with build options :
cmake -DUA_ENABLE_PUBSUB=ON -DUA_ENABLE_JSON_ENCODING=ON -DUA_NAMESPACE_ZERO=FULL -DUA_ENABLE_MQTT=ON -DUA_ENABLE_PARSING=ON ..
-
If you want to make a shared library : add
-DBUILD_SHARED_LIBS=ON
-
-
Build the library :
make
-
If you want it installed :
make install
-
Setting Up The TCP/IP Server
The basic TCP/IP server only needs the hostname and the port where the
server will listen on. The server listens on URIs that are in the form
of: opc.tcp://<hostname>:<port>
Defaults :
-
If no hostname is provided : it defaults to 192.168.0.100.
-
If no port is provided : it defaults to 4840.
For the server to function (receive and send data) an information model needs to be inserted and built together with the server code.
Setting Up The PubSub MQTT Server
Only the QOS and the broker address URI needs to be passed. The format for URI is ;
-
opc.mqtt://<hostname>:<port>
Conclusion
This might be possible to do through the NodeSet Compiler generation. Currently this can be set with a modeler (with a nodeset), but do to problems with the PubSub implementation, this does not function as it should. In the future we might create a generator for this that reads the nodeset and generates code for creating a PubSub configuration.
Setting Up The Information Model With The NodeSet Compiler
An information model is needed for clients to query and interact with objects, which can hold various data. Since its not expected that the user will write this in C code, a Node-Set Compiler can be used to compile XML files that conform with OPC UA Nodeset XML schema into C code, this C code is included into the Server code and built together with it.
The Node-Set Compiler is one of the tools open62541 provides, which is written as a Python3 script. An example of usage and integration into server code is can be found below.
-
Create an information model as an XML schema: This can be done with something like Free OPCUA modeler, NOTE: this one is not supported anymore, so finding a new one might be better.
-
Update submodules: If
/deps/ua-nodeset
is missing, run submodule update as seen in 3.1. -
Compiling the NodeSet: Locate the
nodeset_compiler.py
and run it, example :./nodeset_compiler.py --types-array=UA_TYPES --existing <path to ua-nodeset>/Schema/Opc.Ua.NodeSet2.xml --xml <xml file name>.xml <output name>
Explanation of the command :
--types-array=UA_TYPES
defines the name of the global array in open62541 which contains the corresponding types used in the nodeset--existing <path to ua-nodeset>/Schema/Opc.Ua.NodeSet2.xml
points to an existing XML schema used in the server, since all servers use the same base/root schema for namespace 0, this existing XML file must always be added, other (personal) existing XML schemes can also be added here--xml <xml file name>.xml
path to the XML nodeset that is to be compiled<output name>
name of the output file (this means names of the .c and .h files that are compiled and name of the function that will be used in the server code to initialize the model -
Include the header and initialize: Add
-
#include <compiledheaderfile>.h
and -
<compiledheaderfile>(*server)
to the server code. Calling the initialize function, must be done before running the server.
-
Generating With CMake
Another way to generate the C code from an XML is to use the CMake files that are build with the library. Instructions :
-
After building the open62541 library, in the build folder, you will find
open62541Macros.cmake
, this CMake file defines 4 functions-
ua_generate_headers
-
ua_generate_nodeset
-
ua_generate_datatypes
-
ua_generate_nodeset_and_datatypes
-
-
Copy this file to a local folder, and make sure to set
open62541_TOOLS_DIR
macro (defined in the aforementioned file) to point to theopen62541/tools
folder. -
Create a new
CMakeLists.txt
file and addinclude("<path-to-open62541Macros.cmake>")
into it, then you can call any of the 4 functions. -
After you set the parameters of the function, use
cmake .
to generate MakeFiles. -
To start compiling the XML to C code, call
make <TARGET_PREFIX>-ns-<NAME>
, whereTARGET_PREFIX
andNAME
are parameters of the function.
CMake makes compiling the XML much easier, since it is easier to also
compile datatypes and multiple XML nodesets (including existing ones)
and use the NodeSet Injector. I’m not exactly sure how we can generate
the CMakeLists.txt
, but if we can do it, this could make generating
the C code more trivial.
Setting Up The Information Model With The NodeSet Loader
NodeSet loader allows loading NodeSets directly into the server without compiling the with the NodeSet Compiler. Meaning it can read and parse the XML and create an information model. Building the Nodeset Loader library:
-
NodeSet Loader Library : It can be found on Github or in the
open62541/deps/NodesetLoader
folder. -
Compilng the library : Compiling is easy and only takes a few steps :
-
mkdir build && cd build
-
cmake .
-
make
ormake install
-
-
Add include statements to server code :
-
#include <NodesetLoader/dataTypes.h>
-
#include <NodesetLoader/backendOpen62541.h>
-
-
Load the XML files before running the server :
NodesetLoader_loadFile(server, "<Path-to-the-XML", NULL);
-
Run the server
It is a mechanism for automatically loading nodeset specifications during the server initialization. It provides a fast and easy way to load nodesets in all applications, focusing on the official OPCFoundation Repository (can be found here. This is done through CMake. Multiple can be added at once,
Industry NodeSets
Various industry nodesets are created in XML form by the OPC UA
Foundation and distributed freely on
Github or in the open62541
source code within the open62541/deps/ua-nodesets
folder. These
nodesets can be either compiled using the Nodeset Compiler or loaded
using the Nodeset Loader.
NOTE: Some nodesets depend on others, meaning that those must be
compiled or loaded beforehand. Additionally, some nodesets include
custom datatypes that need to be precompiled either with the
type_parser.py
script or with the aforementioned CMake function before
compiling the XML or if using the Nodeset Loader, loaded before loading
the XML nodesets.
Compiling The Industry Nodesets
The nodesets are in form :
<NodeSet Name> - <Dependency List> - <NS Compiles> - <C compiles> - <Extra Information>
-
ADI - DI - NS compiles - C compiles
-
AMB - NS compiles - C compiles
-
AML - NS compiles - C compiles
-
AutoID - DI - NS compiles - C compiles
-
BACnet - NS compiles - C compile error
-
CAS - DI, IA, Machinery - NS compiles -C compiles
-
CNC - CAS - NS compiles - C compiles
-
Commercial Kitchen Equipment - DI - NS compiles - C compiles
-
CSPPlusForMachine - DI - NS compile error
-
DI - NS compiles - C compiles
-
DEXPI - DI - NS compiles - C compiles
-
FDI - DI - NS compiles - C compiles - Error loading Nodeset
-
FDT - DI - NS compiles - C compiles
-
GDS - NS compiles - C compiles
-
Glass - DI, Machinery - NS compile error
-
GMS - Machinery/Result, MachineTool, DI, Machinery - NS Compiles - C compiles
-
I4AAS - NS compiles - C compile error
-
IA - DI - NS compiles - C compiles
-
IEC61850 - 7-3 - NS compiles - C compiles
-
IJT - Machinery - NS compiles - C compiles
-
IOLink - DI - NS compiles - C compiles
-
ISA-95 - NS compiles - C compiles - Error loading Nodeset
-
ISA-95JOBCONTROL - NS compiles - C compiles
-
MDIS - NS compiles - C compiles
-
MTConnect - NS compiles - C compiles
-
Machinery - NS compiles - C compiles
-
Machinery/Result - NS compiles - C compiles
-
Machinery/ProcessValues - PADIM - NS compile error - Unknown - Maybe can be fixed?
-
-
MachineTool - Machinery, DI, AI - NS compiles - C compiles
-
MachineVision - NS compiles - C compile error
-
Mining/General - Machinery - NS compiles - C compile error
-
Mining/DevelopmentSupport/General/ - NS compiles - C compiles
-
Mining/DevelopmentSupport/Dozer - Mining/General - NS compiles - C compile error
-
Mining/DevelopmentSupport/RoofSupportSystem - Mining/General - NS compiles - C compile error
-
Mining/Extraction/General- NS compiles - C compiles
-
Mining/Extraction/ShearerLoader - Mining/General - NS compiles - C compile error
-
Mining/Loading/General - Mining/General - NS compiles - C compile error
-
Mining/Loading/HydraulicExcavator - Mining/General, Mining/Loading/General - NS compiles - C compile error
-
Mining/MineralProcessing/General - NS compiles - C compiles
-
Mining/MineralProcessing/RockCrusher - Machinery, DI, Mining/General
-
NS compiles - C compile error
-
-
Mining/MonitoringSupervisionServices/General - NS compiles - C compiles
-
Mining/PELOServices/General - NS compiles - C compiles
-
Mining/PELOServices/FaceAlignmentSystem NodeSet - Mining/General, DI
-
NS compiles - C compile error
-
-
Mining/TransportDumping/General - Mining/General - NS compiles - C C compile error
-
Mining/TransportDumping/ArmouredFaceConveyor - Mining/General - NS compiles - C compile error
-
Mining/TransportDumping/RearDumpTruck - Mining/General, Mining//TransportDumping/General - NS compiles - C compile error
-
-
Onboarding - NS compiles - C compiles
-
OpenSCS - NS compiles - C compiles
-
PackML - NS compiles - C compiles
-
PADIM - Dictionary/IRDI, DI - NS compiles - C compiles
-
PlasticsRubber/GeneralTypes - DI - NS compiles - C compiles
-
PlasticsRubber/Extrusion/GeneralTypes - PlasticsRubber/GeneralTypes, DI - NS compiles - C compiles, only 2 loades
-
PlasticsRubber/Extrusion/HaulOff - PlasticsRubber/Extrustion/GeneralTypes - NS compiles - C compiles
-
PlasticsRubber/Extrusion/Calendar - PlasticsRubber/Extrustion/GeneralTypes - NS compiles - C compiles
-
PlasticsRubber/Extrusion/Calibrator - PlasticsRubber/Extrustion/GeneralTypes - NS compiles - C compiles
-
PlasticsRubber/Extrusion/Corrugator - PlasticsRubber/Extrustion/HaulOff - NS compiles - C compiles
-
PlasticsRubber/Extrusion/Cutter - PlasticsRubber/Extrustion/HaulOff
-
NS compiles - C compiles
-
-
PlasticsRubber/Extrusion/Die - PlasticsRubber/Extrustion/HaulOff - NS compiles - C compiles
-
PlasticsRubber/Extrusion/Extruder - PlasticsRubber/Extrustion/HaulOff - NS compiles - C compiles
-
PlasticsRubber/Extrusion/ExtrusionLine - PlasticsRubber/Extrustion/HaulOff - NS compiles - C compiles
-
PlasticsRubber/Extrusion/Filter - PlasticsRubber/Extrustion/HaulOff
-
NS compiles - C compiles
-
-
PlasticsRubber/Extrusion/MeltPump - PlasticsRubber/Extrustion/HaulOff - NS compiles - C compiles
-
PlasticsRubber/Extrusion/Pelletizer - PlasticsRubber/Extrustion/HaulOff - NS compiles - C compiles
-
-
PlasticsRubber/Extrusion/v2/GeneralTypes - NS compiles - C compiles - Error loading Nodeset
-
PlasticsRubber/Extrusion/v2/HaulOff - NS compiles - C compiles
-
PlasticsRubber/Extrusion/v2/Calendar - NS compiles - C compiles
-
PlasticsRubber/Extrusion/v2/Calibrator - NS compiles - C compiles - Error loading Nodeset
-
PlasticsRubber/Extrusion/v2/Corrugator - NS compiles - C compiles
-
PlasticsRubber/Extrusion/v2/Cutter - NS compiles - C compiles - Error loading Nodeset
-
PlasticsRubber/Extrusion/v2/Die - NS compiles - C compiles
-
PlasticsRubber/Extrusion/v2/Extruder - NS compiles - C compiles - Error loading Nodeset
-
PlasticsRubber/Extrusion/v2/ExtrusionLine - NS compiles - C compiles
-
PlasticsRubber/Extrusion/v2/Filter - NS compiles - C compiles - Error loading Nodeset
-
PlasticsRubber/Extrusion/v2/MeltPump - NS compiles - C compiles - Error loading Nodeset
-
PlasticsRubber/Extrusion/v2/Pelletizer - NS compiles - C compiles - Error loading Nodeset
-
-
PlasticsRubber/HotRunner - NS compiles - C compiles
-
PlasticsRubber/IMM2MES - NS compiles - C compiles
-
PlasticsRubber/LDS - NS compiles - C compiles
-
PlasticsRubber/TCD - NS compiles - C compiles - Error loading Nodeset
-
-
PLCOpen - DI - NS compiles - C compiles
-
PNEM - DI - NS compiles - C compile error
-
PNENC - DI - NS compiles - C compiles
-
PNRIO - DI - NS compiles - C compiles
-
POWERLINK - NS compiles - C compile error
-
PROFINET - NS compiles - C compiles
-
Pumps - Machinery, DI - NS compiles - C compiles
-
RSL - NS compiles - C compiles - Error loading Nodeset
-
Robotics - NS compiles - C compiles
-
Safety - NS compiles - C compile error
-
Scales - Di, Machinery, PackML - NS compiles - C compile error
-
Scheduler - NS compiles - C compiles
-
SERCOS - NS compiles - C compiles
-
TMC - NS compile - C compile error
-
UAFX - FX/AC, DI, FX/Data - NS compiles - C compiles - Error loading Nodeset
-
Weihenstephan - DI, Machinery, PackML - NS compiles - C compiles
-
Woodworking - Eumabois, Machinery, DI - NS compiles - C compiles - Error loading Nodeset : MAX compile 8 seconds
-
XML - NS compiles - C compiles
NOTE : If a Nodeset has a C or NS compile error or a loading error it doesn’t mean something is wrong with it. This can just be because they need to be compiled/loaded with an additional user made Nodeset. Since this Nodesets are supposed to be use in tandem with a user Nodeset, and only act as something to build upon!
Instructions For Compiling And Loading The NodeSets
This are the instructions for compiling the Industry nodesets and then compiling the generated C files with the server source code.
-
Needed Files :
-
CMakeFiles :
-
open62541Macros.cmake
- holds the CMake function definitions-
IMPORTANT NOTE : Set the value of
open62541_TOOLS_DIR
to the tools directory that is in the open62541 library
-
-
CMakeLists.txt
- holds the CMake function calls for the Industry Nodesets-
IMPORTANT NOTE : Set the value of
UA_NODESET_DIR
to the directory with the industry nodesetsua-nodesets
-
IMPORTANT NOTE : Set the value of
XML_NODESET_DIR
to the directory with the user made XML nodesets -
NOTE : You can also set the value of
MAIN_PREFIX
to change the target names for generating the nodesets
-
-
-
Python Files :
-
DEPS.py
- holds the dictionary of the nodeset dependencies for generating the function calls in the right order -
insert_gen_files.py
- inserts headers and function calls into the server source code
-
-
-
Call Sequence:
-
Set Up The Environment : Call
cmake .
-
Compile The NodeSet : Call
make compile-ns-<name-of-the-nodeset>
-
NOTE : If
MAIN_PREFIX
was changed, replacecompile
with the new prefix
-
-
Insert The Generated Files Into The Server Source Code : Call
python3 insert_generated.py
-
Compile The Server Source Code : Will create a MakeFile for this
-
Instructions For Compiling The Industry And User Nodesets
User-made nodesets also need to be compiled, this is done with
insert_cmk_ufcall.py
script. Usage of the script and steps is
explained below.
-
Create a build-config.json file: This JSON file is used to create the function calls and to set up the dependencies in the right order. An example of a JSON configuration can be seen below #fig:build-config.json[3.1].
-
files
- holds the JSON objects, one for each file and its dependencies -
name
- name of the XML file, does not need the .xml suffix -
dependencies
- array of the dependencies-
NOTE: The dependencies between the user nodesets are done automatically in the same order as the JSON objects in the
files
array. Only allowed special character in names is_
, the resulting make target is just calleduser_nodeset
. -
NOTE: It is crucial that the JSON objects are defined in an hierarchical ascending order.
-
-
-
Compile the Nodesets :
make compile-ns-<name-of-the-nodeset>
-
Insert The Generated Files Into The Server Source Code : Call
python3 insert_generated.py
-
Compile The Server Source Code : Will create a MakeFile for this
Conclusion
Since the industry nodesets are normaly used under a user nodeset, they are almost never standalone compiled. This means that section 3.6.3 is the way that will be used.
Miscellaneous Information
Here various miscellaneous information/questions will be answered :
-
Persistence :
-
Best way to handle it, is to let the user create a client that saves the data, from my understanding there is no direct persistence implementation in open62541
-
MQTT can be used with Node-RED
-
-
Server Build, Rebuild and Restart Time :
-
Build Time : is heavily dependent on the size of the Nodeset(s), it combines the time it takes to compile the NodeSets and the time to compile the source and generated code. From my tests it should always be under 1 minute.
-
Rebuild Time : It will always equal the build time, since the source code needs to be edited (new headers and function calls)
-
Restart Time : This is practically instantaneous
-
-
User Side:
-
Button For Uploading Files (XML) and a Field for declaring the hierarchy of the nodesets, from the bottom to the top file. This needs to then go into the
xml/user-nodesets/build_conf/build-config.json
file.-
IMPORTANT NOTE : The order, starting from the bottom XML nodeset to the top one is important! Since they need to be loaded bottom up the hierarchy.
-
-
A build/rebuild button
-
Effect :
-
1. : Calls the script for creating the CMake function call
insert_cmk_ufcall.py
-
2. : Calls
cmake .
andmake compile-ns-<name>
-
3. : Calls
python insert_cmk_ufcall.py
-
4. : Calls
python insert_gen_files.py
-
5. : Calls
make
to build the server
-
-
Extra : A way to report errors. NOTE : currently this is automatically done by resetting the Docker container of the OPC-UA server, meaning we just need a way to turn reset the container.
-
-
A stop button :
-
Effect : Stops the running server, if one is running.
-
Extra : Report errors. NOTE : This should just stop the OPC-UA server container.
-
-
A start button :
-
Effect : Runs the server instance.
-
Extra : Report errors. NOTE : This should just start the OPC-UA server container.
-
-
An input field for IP and Port of the Server (Multiple can be inserted)
-
Extra : Reporting if its not in the correct format, which is
IP:PORT
. This is then saved into a config fileserver-conf.json
. NOTE : The config file has one array calledADDRS
with entries in form of IP:PORT, if there is no file or the array is empty, it just opens on default addresses.
-
-
-
Necessary Inputs :
-
An XML file / nodeset of the information model and the hierarchy of the nodesets, if it exists.
-
-
Third party tools :
-
FreeOpcUa Modeler for creating NodeSets and FreeOpcUa Client for testing
-
Siemens OPC-UA Modeling Editor or SiOME : SiOME is a Modeling Editor for OPC-UA from Siemens. It is free and only needs registration. It can be used with Windows 7 or Windows 10. Siemens also offers a manual for SiOME with an example.
-