open62541++ is a C++ wrapper built on top of the amazing open62541 OPC UA (OPC Unified Architecture) library.
Features and goals:
- High-level and easy to use classes similar to the python-opcua API:
opcua::Server
opcua::Client
TODOopcua::Node
- Safe wrapper classes for open62541
UA_*
types to prevent memory leaks - Native open62541 objects can be accessed using the
handle()
method of the wrapping classes - Extensible type conversion system to convert arbitrary types to/from native
UA_*
types - Cross-platform (tested on Windows, Linux and MacOS)
- Compatible with all stable open62541 versions (> v1.0)
- Easy installation and integration with CMake
- Use modern C++ (C++ 17) and best practices
- Less hurdle to get started with OPC UA
#include <iostream>
#include "open62541pp/open62541pp.h"
int main() {
opcua::Server server;
const opcua::NodeId myIntegerNodeId{"the.answer", 1};
const std::string myIntegerName{"the answer"};
// add variable node
auto parentNode = server.getObjectsNode();
auto myIntegerNode = parentNode.addVariable(myIntegerNodeId, myIntegerName);
// set node attributes
myIntegerNode.setDataType(opcua::Type::Int32);
myIntegerNode.setDisplayName("the answer", "en-US");
myIntegerNode.setDescription("the answer", "en-US");
// write value
myIntegerNode.writeScalar(42);
// read value
std::cout << "The answer is: " << myIntegerNode.readScalar<int>() << std::endl;
server.run();
}
Type conversion from and to native UA_*
types are handled by the opcua::TypeConverter
struct.
Compile-time checks are used where possible:
opcua::Variant var;
// will compile
int number = 5;
var.setScalar(number);
var.setArrayCopy<double>({1.1, 2.2, 3.3});
// won't compile, because the std::string can't be assigned without copy (conversion needed)
std::string str{"test"};
var.setScalar(str);
// won't compile, because the type std::string is associated with more than one variant types:
// - opcua::Type::String
// - opcua::Type::ByteString
// - opcua::Type::XmlElement
var.setScalarCopy<std::string>("test");
// finally compiles
var.setScalarCopy<std::string, opcua::Type::String>("test");
You can add template specializations to add conversions for arbitrary types:
namespace opcua {
template <>
struct TypeConverter<std::string> {
using ValueType = std::string;
using NativeType = UA_String;
using ValidTypes = TypeList<Type::String, Type::ByteString, Type::XmlElement>;
static void fromNative(const NativeType& src, ValueType& dst) { /* ... */ }
static void toNative(const ValueType& src, NativeType& dst) { /* ... */ }
};
} // namespace opcua
Type Enum opcua::Type |
Type | Typedef | Wrapper | Conversions |
---|---|---|---|---|
Boolean | UA_Boolean |
bool |
||
SByte | UA_SByte |
int8_t |
||
Byte | UA_Byte |
uint8_t |
||
Int16 | UA_Int16 |
int16_t |
||
UInt16 | UA_UInt16 |
uint16_t |
||
Int32 | UA_Int32 |
int32_t |
||
UInt32 | UA_UInt32 |
uint32_t |
||
Int64 | UA_Int64 |
int64_t |
||
UInt64 | UA_UInt64 |
uint64_t |
||
Float | UA_Float |
float |
||
Double | UA_Double |
double |
||
String | UA_String |
opcua::String |
std::string |
|
DateTime | UA_DateTime |
int64_t |
opcua::DateTime |
std::chrono::time_point |
Guid | UA_Guid |
opcua::Guid |
||
ByteString | UA_ByteString |
UA_String |
opcua::ByteString |
std::string |
XmlElement | UA_XmlElement |
UA_String |
opcua::XmlElement |
std::string |
NodeId | UA_NodeId |
opcua::NodeId |
||
ExpandedNodeId | UA_ExpandedNodeId |
opcua::ExpandedNodeId |
||
StatusCode | UA_StatusCode |
uint32_t |
||
QualifiedName | UA_QualifiedName |
opcua::QualifiedName |
||
LocalizedText | UA_LocalizedText |
opcua::LocalizedText |
||
ExtensionObjectDataValue | UA_ExtensionObject |
opcua::ExtensionObjectDataValue |
||
DataValue | UA_DataValue |
opcua::DataValue |
||
Variant | UA_Variant |
opcua::Variant |
||
DiagnosticInfo | UA_DiagnosticInfo |
opcua::DiagnosticInfo |
The library can be installed using CMake.
Add it to your project as a Git submodule (git submodule add https://github.com/open62541pp/open62541pp.git
) and link it with CMake:
add_subdirectory(extern/open62541pp) # the submodule directory
target_link_library(myexecutable PRIVATE open62541pp::open62541pp)
Please check out the open62541 build options here: https://www.open62541.org/doc/1.3/building.html#build-options
open62541++ provides additional build options:
UAPP_INTERNAL_OPEN62541
: Use internal open62541 library ifON
or search for installed open62541 library ifOFF
UAPP_BUILD_DOCUMENTATION
: Build documentationUAPP_BUILD_EXAMPLES
: Build examples forexamples
directoryUAPP_BUILD_TESTS
: Build an run testsUAPP_ENABLE_CLANG_TIDY
: Enable static code analysis with Clang-TidyUAPP_ENABLE_COVERAGE
: Enable coverage analysisUAPP_ENABLE_SANITIZER_ADDRESS/LEAK/MEMORY/THREAD/UNDEFINED_BEHAVIOUR
: Enable sanitizers