C++ wrapper of the amazing open62541 OPC UA library.
Open source and free implementation licensed under the Mozilla Public License v2.0.
- High-level and easy to use classes similar to the Python opcua/asyncua API:
- Free functions in
services
namespace as an alternative to theopcua::Node
class - 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
The latest stable open62541 release is integrated as a submodule. Depending on the value of the CMake flag UAPP_INTERNAL_OPEN62541
, the submodule or an external open62541 installation is used.
All open62541 releases since v1.0 are supported and tested in a CI pipeline with debug/release builds and as static/dynamic library.
The project is currently in beta
stage but already used in production.
Version v1.0.0
is planned for the beginning of 2024. No (major) breaking changes are expected.
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, 1000}, "TheAnswer");
// Write some node attributes
myIntegerNode.writeDisplayName({"en-US", "The Answer"})
.writeDataType(opcua::DataTypeId::Int32)
.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::byte> {
using ValueType = std::byte;
using NativeType = UA_Byte;
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_INCLUDE_WHAT_YOU_USE
: Enable static code analysis with Include What You UseUAPP_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 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.