- High-level and easy to use classes similar to the Python opcua/asyncua API:
- 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
Explore all examples in the examples/
directory.
#include "open62541pp/open62541pp.h"
int main() {
opcua::Server server;
// Add a variable node to the Objects node
opcua::Node parentNode = server.getObjectsNode();
opcua::Node myIntegerNode = parentNode.addVariable({1, "the.answer"}, "the answer");
// Write some node attributes
myIntegerNode.writeDataType(opcua::Type::Int32)
.writeDisplayName({"en-US", "the answer"})
.writeDescription({"en-US", "the answer"})
.writeValueScalar(42);
server.run();
}
#include <iostream>
#include "open62541pp/open62541pp.h"
int main() {
opcua::Client client;
client.connect("opc.tcp://localhost:4840");
opcua::Node node = client.getNode(opcua::VariableId::Server_ServerStatus_CurrentTime);
const auto dt = node.readValueScalar<opcua::DateTime>();
std::cout << "Server date (UTC): " << dt.format("%Y-%m-%d %H:%M:%S") << std::endl;
}
Type conversion from and to native UA_*
types are handled by the opcua::TypeConverter
struct.
Have a look at the typeconversion example.
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);
// will compile
var.setScalarCopy(str);
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 = TypeIndexList<UA_TYPES_STRING, UA_TYPES_BYTESTRING, UA_TYPES_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 , std::string_view , const char* , char[N] |
|
DateTime | UA_DateTime |
int64_t |
opcua::DateTime |
std::chrono::time_point |
Guid | UA_Guid |
opcua::Guid |
||
ByteString | UA_ByteString |
UA_String |
opcua::ByteString |
|
XmlElement | UA_XmlElement |
UA_String |
opcua::XmlElement |
|
NodeId | UA_NodeId |
opcua::NodeId |
||
ExpandedNodeId | UA_ExpandedNodeId |
opcua::ExpandedNodeId |
||
StatusCode | UA_StatusCode |
uint32_t |
opcua::StatusCode |
|
QualifiedName | UA_QualifiedName |
opcua::QualifiedName |
||
LocalizedText | UA_LocalizedText |
opcua::LocalizedText |
||
ExtensionObject | UA_ExtensionObject |
opcua::ExtensionObject |
||
DataValue | UA_DataValue |
opcua::DataValue |
||
Variant | UA_Variant |
opcua::Variant |
||
DiagnosticInfo | UA_DiagnosticInfo |
opcua::DiagnosticInfo |
The library can be built, integrated and installed using CMake.
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 unit testsUAPP_BUILD_TESTS_AUTORUN
: Run unit tests after buildUAPP_ENABLE_CLANG_TIDY
: Enable static code analysis with Clang-TidyUAPP_ENABLE_COVERAGE
: Enable coverage analysisUAPP_ENABLE_PCH
: Use precompiled headers to speed up compilationUAPP_ENABLE_SANITIZER_ADDRESS/LEAK/MEMORY/THREAD/UNDEFINED_BEHAVIOUR
: Enable sanitizers
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_libraries(myexecutable PRIVATE open62541pp::open62541pp)
If you build and install this package to your system, a open62541ppConfig.cmake
file will be generated and installed to your system.
The installed library can be found and linked within CMake:
find_package(open62541pp::open62541pp CONFIG REQUIRED)
target_link_libraries(myexecutable PRIVATE open62541pp::open62541pp)
# clone repository
git clone --recursive https://github.com/open62541pp/open62541pp.git
cd open62541pp
# build
mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=Debug -DUAPP_BUILD_EXAMPLES=ON -DUAPP_BUILD_TESTS=ON ..
cmake --build .
# run tests
ctest --output-on-failure
# generate coverage reports (text or html) with UAPP_ENABLE_COVERAGE option enabled
cmake --build . --target open62541pp_coverage_report
cmake --build . --target open62541pp_coverage_report_html
# install to system
cmake --install .
Contributions and feature requests are very welcome. Please have a look at the contribution guidelines.