C++ wrapper of the amazing open62541 OPC UA library.
Open source and free implementation licensed under the Mozilla Public License v2.0.
π Documentation β’ π Examples
- 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 - Asynchronous model similar to (Boost) Asio
- 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 2025. No major breaking changes are expected.
While in v0.x.x
, breaking changes may occur in minor releases. This projects follows the two-version deprecation path: when a feature is marked as deprecated in v0.x.0
, it may be removed as early as v0.(x+2).0
. Deprecated APIs are declared with the [[deprecated]]
attribute and noted in the changelog.
Explore all examples in the examples/
directory.
#include <open62541pp/node.hpp>
#include <open62541pp/server.hpp>
int main() {
opcua::Server server;
// Add a variable node to the Objects node
opcua::Node parentNode{server, opcua::ObjectId::ObjectsFolder};
opcua::Node myIntegerNode = parentNode.addVariable({1, 1000}, "TheAnswer");
// Write value attribute
myIntegerNode.writeValue(opcua::Variant{42});
server.run();
}
#include <iostream>
#include <open62541pp/client.hpp>
#include <open62541pp/node.hpp>
int main() {
opcua::Client client;
client.connect("opc.tcp://localhost:4840");
opcua::Node node{client, opcua::VariableId::Server_ServerStatus_CurrentTime};
const auto dt = node.readValue().to<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.assign(&number);
// β won't compile, because std::string can't be assigned without copy (conversion needed)
std::string str{"test"};
var.assign(&str);
// β
will compile
var.assign(str);
You can add template specializations to add conversions for arbitrary types:
namespace opcua {
template <>
struct TypeConverter<std::byte> {
using NativeType = UA_Byte;
[[nodiscard]] static std::byte fromNative(const UA_Byte& src) { /* ... */ }
[[nodiscard]] static UA_Byte toNative(const std::byte& src) { /* ... */ }
};
} // namespace opcua
Type | Type open62541 | 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
Open62541pp provides additional build options:
UAPP_INTERNAL_OPEN62541
: Use internal open62541 library ifON
or search for installed open62541 library ifOFF
UAPP_ENABLE_NODESETLOADER
: Enable nodeset loader to loadNodeSet2.xml
files at runtimeUAPP_BUILD_DOCUMENTATION
: Build documentationUAPP_BUILD_EXAMPLES
: Build examples forexamples
directoryUAPP_BUILD_TESTS
: Build unit testsUAPP_ENABLE_COVERAGE
: Enable coverage analysisUAPP_ENABLE_CLANG_TIDY
: Enable static code analysis with Clang-TidyUAPP_ENABLE_SANITIZER_ADDRESS/LEAK/UNDEFINED/THREAD
: 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)
The library is available through the following package managers:
-
vcpkg: Please refer to the vcpkg documentation how to use it within your project. You can easily use vcpkg to build and install open62541pp:
vcpkg install open62541pp
# clone repository
git clone --recursive https://github.com/open62541pp/open62541pp.git
cd open62541pp
# build
mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=Release -DUAPP_BUILD_EXAMPLES=ON -DUAPP_BUILD_TESTS=ON ..
cmake --build . # single-configuration generator like Make or Ninja
cmake --build . --config Release # multi-configuration generator like Visual Studio, Xcode
# run tests
ctest --output-on-failure
# install to system
cmake --install .
Contributions and feature requests are very welcome. Please have a look at the contribution guidelines.