open62541++ 0.13.0
C++ wrapper of open62541
Loading...
Searching...
No Matches
open62541++

open62541++

License: MPL 2.0 CI Compatibility Package Documentation Coverage

C++ wrapper of the amazing open62541 OPC UA library.

Open source and free implementation licensed under the Mozilla Public License v2.0.
DocumentationExamples

🎯 Features and goals

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 2024. No major breaking changes are expected.

✍ Examples

Explore all examples in the examples/ directory.

Server

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"})
.writeValueScalar(42);
server.run();
}
High-level node class to access node attribute, browse and populate address space.
Definition Node.h:42
Node & writeDisplayName(const LocalizedText &name)
Write the AttributeId::DisplayName attribute of a node.
Definition Node.h:483
Node addVariable(const NodeId &id, std::string_view browseName, const VariableAttributes &attributes={}, const NodeId &variableType=VariableTypeId::BaseDataVariableType, const NodeId &referenceType=ReferenceTypeId::HasComponent)
Add variable.
Definition Node.h:120
High-level server class.
Definition Server.h:61
Node< Server > getObjectsNode()
void run()
Run the server's main loop. This method will block until Server::stop is called.
Result< void > writeDataType(T &connection, const NodeId &id, const NodeId &dataType) noexcept
Write the AttributeId::DataType attribute of a node.

Client

#include <iostream>
int main() {
opcua::Client client;
client.connect("opc.tcp://localhost:4840");
const auto dt = node.readValueScalar<opcua::DateTime>();
std::cout << "Server date (UTC): " << dt.format("%Y-%m-%d %H:%M:%S") << std::endl;
}
High-level client class.
Definition Client.h:60
void connect(std::string_view endpointUrl)
Connect to the selected server.
Node< Client > getNode(NodeId id)
UA_DateTime wrapper class.
Definition DateTime.h:23
std::string format(std::string_view format, bool localtime=false) const
Convert to string with given format (same format codes as strftime).
T readValueScalar()
Read scalar value from variable node.
Definition Node.h:421

⇆ Type conversion

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:

// 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);
UA_Variant wrapper class.
Definition Variant.h:46
void setArrayCopy(const ArrayLike &array)
Copy array to variant.
Definition Variant.h:360
void setScalarCopy(const T &value)
Copy scalar value to variant.
Definition Variant.h:315
void setScalar(T &value) noexcept
Assign scalar value to variant (no copy).
Definition Variant.h:302

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
uint8_t UA_Byte

Type map of built-in types

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

🚀 Getting started

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 if ON or search for installed open62541 library if OFF
  • UAPP_BUILD_DOCUMENTATION: Build documentation
  • UAPP_BUILD_EXAMPLES: Build examples for examples directory
  • UAPP_BUILD_TESTS: Build unit tests
  • UAPP_BUILD_TESTS_AUTORUN: Run unit tests after build
  • UAPP_ENABLE_CLANG_TIDY: Enable static code analysis with Clang-Tidy
  • UAPP_ENABLE_INCLUDE_WHAT_YOU_USE: Enable static code analysis with Include What You Use
  • UAPP_ENABLE_COVERAGE: Enable coverage analysis
  • UAPP_ENABLE_PCH: Use precompiled headers to speed up compilation
  • UAPP_ENABLE_SANITIZER_ADDRESS/LEAK/MEMORY/THREAD/UNDEFINED_BEHAVIOUR: Enable sanitizers

Integrate as an embedded (in-source) dependency

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)

Integrate as a pre-compiled library

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)

Integrate via package managers

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

Build and install

# 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 .

Dependencies

  • open62541 as integrated submodule or external dependency
  • doctest for tests as integrated submodule

🤝 Contribute

Contributions and feature requests are very welcome. Please have a look at the contribution guidelines.