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.

Server Configuration

The configuration structure is passed to the server during initialization, it cannot and should not be changed during runtime. After shutdown the configuration should be cleaned to free the memory.

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.

Conclusion

From my testing on the SiOME modeler, there is no way to do setup the IP and Port through the modeler. Currently the Server can set it up, by accepting the values as command line arguments <arg1:IP> <arg2:port>. This will be moved to a config file.

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 the open62541/tools folder.

  • Create a new CMakeLists.txt file and add include("<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>, where TARGET_PREFIX and NAME 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.

Conclusion

This will always be done by a CMakeFile, where the function calls are generated with insert_cmk_ufcall.py.

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 or make 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,

Conclusion

We might use it in the future, but it needs much more research and the nodeset loader implementation not finished yet.

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>
  1. ADI - DI - NS compiles - C compiles

  2. AMB - NS compiles - C compiles

  3. AML - NS compiles - C compiles

  4. AutoID - DI - NS compiles - C compiles

  5. BACnet - NS compiles - C compile error

  6. CAS - DI, IA, Machinery - NS compiles -C compiles

  7. CNC - CAS - NS compiles - C compiles

  8. Commercial Kitchen Equipment - DI - NS compiles - C compiles

  9. CSPPlusForMachine - DI - NS compile error

  10. DI - NS compiles - C compiles

  11. DEXPI - DI - NS compiles - C compiles

  12. FDI - DI - NS compiles - C compiles - Error loading Nodeset

  13. FDT - DI - NS compiles - C compiles

  14. GDS - NS compiles - C compiles

  15. Glass - DI, Machinery - NS compile error

  16. GMS - Machinery/Result, MachineTool, DI, Machinery - NS Compiles - C compiles

  17. I4AAS - NS compiles - C compile error

  18. IA - DI - NS compiles - C compiles

  19. IEC61850 - 7-3 - NS compiles - C compiles

  20. IJT - Machinery - NS compiles - C compiles

  21. IOLink - DI - NS compiles - C compiles

  22. ISA-95 - NS compiles - C compiles - Error loading Nodeset

  23. ISA-95JOBCONTROL - NS compiles - C compiles

  24. MDIS - NS compiles - C compiles

  25. MTConnect - NS compiles - C compiles

  26. Machinery - NS compiles - C compiles

    1. Machinery/Result - NS compiles - C compiles

    2. Machinery/ProcessValues - PADIM - NS compile error - Unknown - Maybe can be fixed?

  27. MachineTool - Machinery, DI, AI - NS compiles - C compiles

  28. MachineVision - NS compiles - C compile error

  29. Mining/General - Machinery - NS compiles - C compile error

    1. Mining/DevelopmentSupport/General/ - NS compiles - C compiles

    2. Mining/DevelopmentSupport/Dozer - Mining/General - NS compiles - C compile error

    3. Mining/DevelopmentSupport/RoofSupportSystem - Mining/General - NS compiles - C compile error

    4. Mining/Extraction/General- NS compiles - C compiles

    5. Mining/Extraction/ShearerLoader - Mining/General - NS compiles - C compile error

    6. Mining/Loading/General - Mining/General - NS compiles - C compile error

    7. Mining/Loading/HydraulicExcavator - Mining/General, Mining/Loading/General - NS compiles - C compile error

    8. Mining/MineralProcessing/General - NS compiles - C compiles

    9. Mining/MineralProcessing/RockCrusher - Machinery, DI, Mining/General

      • NS compiles - C compile error

    10. Mining/MonitoringSupervisionServices/General - NS compiles - C compiles

    11. Mining/PELOServices/General - NS compiles - C compiles

    12. Mining/PELOServices/FaceAlignmentSystem NodeSet - Mining/General, DI

      • NS compiles - C compile error

    13. Mining/TransportDumping/General - Mining/General - NS compiles - C C compile error

    14. Mining/TransportDumping/ArmouredFaceConveyor - Mining/General - NS compiles - C compile error

    15. Mining/TransportDumping/RearDumpTruck - Mining/General, Mining//TransportDumping/General - NS compiles - C compile error

  30. Onboarding - NS compiles - C compiles

  31. OpenSCS - NS compiles - C compiles

  32. PackML - NS compiles - C compiles

  33. PADIM - Dictionary/IRDI, DI - NS compiles - C compiles

  34. PlasticsRubber/GeneralTypes - DI - NS compiles - C compiles

    1. PlasticsRubber/Extrusion/GeneralTypes - PlasticsRubber/GeneralTypes, DI - NS compiles - C compiles, only 2 loades

      1. PlasticsRubber/Extrusion/HaulOff - PlasticsRubber/Extrustion/GeneralTypes - NS compiles - C compiles

      2. PlasticsRubber/Extrusion/Calendar - PlasticsRubber/Extrustion/GeneralTypes - NS compiles - C compiles

      3. PlasticsRubber/Extrusion/Calibrator - PlasticsRubber/Extrustion/GeneralTypes - NS compiles - C compiles

      4. PlasticsRubber/Extrusion/Corrugator - PlasticsRubber/Extrustion/HaulOff - NS compiles - C compiles

      5. PlasticsRubber/Extrusion/Cutter - PlasticsRubber/Extrustion/HaulOff

        • NS compiles - C compiles

      6. PlasticsRubber/Extrusion/Die - PlasticsRubber/Extrustion/HaulOff - NS compiles - C compiles

      7. PlasticsRubber/Extrusion/Extruder - PlasticsRubber/Extrustion/HaulOff - NS compiles - C compiles

      8. PlasticsRubber/Extrusion/ExtrusionLine - PlasticsRubber/Extrustion/HaulOff - NS compiles - C compiles

      9. PlasticsRubber/Extrusion/Filter - PlasticsRubber/Extrustion/HaulOff

        • NS compiles - C compiles

      10. PlasticsRubber/Extrusion/MeltPump - PlasticsRubber/Extrustion/HaulOff - NS compiles - C compiles

      11. PlasticsRubber/Extrusion/Pelletizer - PlasticsRubber/Extrustion/HaulOff - NS compiles - C compiles

    2. PlasticsRubber/Extrusion/v2/GeneralTypes - NS compiles - C compiles - Error loading Nodeset

      1. PlasticsRubber/Extrusion/v2/HaulOff - NS compiles - C compiles

      2. PlasticsRubber/Extrusion/v2/Calendar - NS compiles - C compiles

      3. PlasticsRubber/Extrusion/v2/Calibrator - NS compiles - C compiles - Error loading Nodeset

      4. PlasticsRubber/Extrusion/v2/Corrugator - NS compiles - C compiles

      5. PlasticsRubber/Extrusion/v2/Cutter - NS compiles - C compiles - Error loading Nodeset

      6. PlasticsRubber/Extrusion/v2/Die - NS compiles - C compiles

      7. PlasticsRubber/Extrusion/v2/Extruder - NS compiles - C compiles - Error loading Nodeset

      8. PlasticsRubber/Extrusion/v2/ExtrusionLine - NS compiles - C compiles

      9. PlasticsRubber/Extrusion/v2/Filter - NS compiles - C compiles - Error loading Nodeset

      10. PlasticsRubber/Extrusion/v2/MeltPump - NS compiles - C compiles - Error loading Nodeset

      11. PlasticsRubber/Extrusion/v2/Pelletizer - NS compiles - C compiles - Error loading Nodeset

    3. PlasticsRubber/HotRunner - NS compiles - C compiles

    4. PlasticsRubber/IMM2MES - NS compiles - C compiles

    5. PlasticsRubber/LDS - NS compiles - C compiles

    6. PlasticsRubber/TCD - NS compiles - C compiles - Error loading Nodeset

  35. PLCOpen - DI - NS compiles - C compiles

  36. PNEM - DI - NS compiles - C compile error

  37. PNENC - DI - NS compiles - C compiles

  38. PNRIO - DI - NS compiles - C compiles

  39. POWERLINK - NS compiles - C compile error

  40. PROFINET - NS compiles - C compiles

  41. Pumps - Machinery, DI - NS compiles - C compiles

  42. RSL - NS compiles - C compiles - Error loading Nodeset

  43. Robotics - NS compiles - C compiles

  44. Safety - NS compiles - C compile error

  45. Scales - Di, Machinery, PackML - NS compiles - C compile error

  46. Scheduler - NS compiles - C compiles

  47. SERCOS - NS compiles - C compiles

  48. TMC - NS compile - C compile error

  49. UAFX - FX/AC, DI, FX/Data - NS compiles - C compiles - Error loading Nodeset

  50. Weihenstephan - DI, Machinery, PackML - NS compiles - C compiles

  51. Woodworking - Eumabois, Machinery, DI - NS compiles - C compiles - Error loading Nodeset : MAX compile 8 seconds

  52. 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 nodesets ua-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, replace compile 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.

  1. 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].

    1. files - holds the JSON objects, one for each file and its dependencies

    2. name - name of the XML file, does not need the .xml suffix

    3. dependencies - array of the dependencies

      1. 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 called user_nodeset.

      2. NOTE: It is crucial that the JSON objects are defined in an hierarchical ascending order.

  2. Compile the Nodesets : make compile-ns-<name-of-the-nodeset>

  3. Insert The Generated Files Into The Server Source Code : Call python3 insert_generated.py

  4. Compile The Server Source Code : Will create a MakeFile for this

Example of a build-config.json file

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 . and make 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 file server-conf.json. NOTE : The config file has one array called ADDRS 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 :


1. Defined by UPC UA part 7, this is a FullFeatured Profile intended for small devices with limited resources.
2. Message Oriented Middleware