open62541pp 0.17.0
C++ wrapper of open62541
Loading...
Searching...
No Matches
attribute_handler.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <cassert>
4#include <cstdint>
5#include <type_traits>
6#include <utility> // forward, move
7#include <vector>
8
10#include "open62541pp/common.hpp" // AttributeId, WriteMask, EventNotifier, AccessLevel
12#include "open62541pp/types.hpp"
13
14namespace opcua::services::detail {
15
16inline Result<Variant> getVariant(DataValue&& dv) noexcept {
17 if (dv.status().isBad()) {
18 return BadResult(dv.status());
19 }
20 if (!dv.hasValue()) {
21 return BadResult(UA_STATUSCODE_BADUNEXPECTEDERROR);
22 }
23 return std::move(dv).value();
24}
25
26/**
27 * Attribute handler to convert DataValue objects to/from the attribute specific types.
28 * Template specializations must be provided for all AttributeIds.
29 */
30template <AttributeId Attribute>
31struct AttributeHandler;
32
33struct AttributeHandlerVariant {
34 using Type = Variant;
35
36 static Result<Variant> fromDataValue(DataValue&& dv) noexcept {
37 return getVariant(std::move(dv));
38 }
39
40 static DataValue toDataValue(const Variant& value) noexcept {
41 DataValue dv;
42 dv->value = value; // shallow copy
43 dv->value.storageType = UA_VARIANT_DATA_NODELETE; // prevent double delete
44 dv->hasValue = true;
45 return dv;
46 }
47};
48
49template <typename T, typename Enable = void>
50struct AttributeHandlerScalar {
51 using Type = T;
52
53 static Result<Type> fromDataValue(DataValue&& dv) noexcept {
54 return getVariant(std::move(dv)).transform([](Variant&& var) {
55 assert(var.isType<T>());
56 assert(var.isScalar());
57 return std::move(var).scalar<T>();
58 });
59 }
60
61 template <typename U>
62 static DataValue toDataValue(U&& value) {
63 return DataValue(Variant(std::forward<U>(value)));
64 }
65};
66
67template <typename T>
68struct AttributeHandlerScalar<T, std::enable_if_t<std::is_enum_v<T>>> {
69 using Type = T;
70 using UnderlyingType = std::underlying_type_t<Type>;
71 using UnderlyingHandler = AttributeHandlerScalar<UnderlyingType>;
72
73 static Result<Type> fromDataValue(DataValue&& dv) noexcept {
74 return UnderlyingHandler::fromDataValue(std::move(dv)).transform([](auto value) {
75 return static_cast<Type>(value);
76 });
77 }
78
79 static DataValue toDataValue(Type value) {
80 return UnderlyingHandler::toDataValue(static_cast<UnderlyingType>(value));
81 }
82};
83
84template <typename T>
85struct AttributeHandlerScalar<Bitmask<T>> {
86 using Type = Bitmask<T>;
87 using UnderlyingType = typename Bitmask<T>::Underlying;
88 using UnderlyingHandler = AttributeHandlerScalar<UnderlyingType>;
89
90 static Result<Type> fromDataValue(DataValue&& dv) noexcept {
91 return UnderlyingHandler::fromDataValue(std::move(dv)).transform([](auto value) {
92 return Bitmask<T>(value);
93 });
94 }
95
96 static DataValue toDataValue(Type value) {
97 return UnderlyingHandler::toDataValue(value.get());
98 }
99};
100
101template <>
102struct AttributeHandler<AttributeId::NodeId> : AttributeHandlerScalar<NodeId> {};
103
104template <>
105struct AttributeHandler<AttributeId::NodeClass> {
106 using Type = NodeClass;
107
108 static Result<Type> fromDataValue(DataValue&& dv) noexcept {
109 return getVariant(std::move(dv)).transform([](const Variant& var) {
110 // workaround to read enum from variant...
111 return *static_cast<const NodeClass*>(var.data());
112 });
113 }
114};
115
116template <>
117struct AttributeHandler<AttributeId::BrowseName> : AttributeHandlerScalar<QualifiedName> {};
118
119template <>
120struct AttributeHandler<AttributeId::DisplayName> : AttributeHandlerScalar<LocalizedText> {};
121
122template <>
123struct AttributeHandler<AttributeId::Description> : AttributeHandlerScalar<LocalizedText> {};
124
125template <>
126struct AttributeHandler<AttributeId::WriteMask> : AttributeHandlerScalar<Bitmask<WriteMask>> {};
127
128template <>
129struct AttributeHandler<AttributeId::UserWriteMask> : AttributeHandlerScalar<Bitmask<WriteMask>> {};
130
131template <>
132struct AttributeHandler<AttributeId::IsAbstract> : AttributeHandlerScalar<bool> {};
133
134template <>
135struct AttributeHandler<AttributeId::Symmetric> : AttributeHandlerScalar<bool> {};
136
137template <>
138struct AttributeHandler<AttributeId::InverseName> : AttributeHandlerScalar<LocalizedText> {};
139
140template <>
141struct AttributeHandler<AttributeId::ContainsNoLoops> : AttributeHandlerScalar<bool> {};
142
143template <>
144struct AttributeHandler<AttributeId::EventNotifier>
145 : AttributeHandlerScalar<Bitmask<EventNotifier>> {};
146
147template <>
148struct AttributeHandler<AttributeId::Value> : AttributeHandlerVariant {};
149
150template <>
151struct AttributeHandler<AttributeId::DataType> : AttributeHandlerScalar<NodeId> {};
152
153template <>
154struct AttributeHandler<AttributeId::ValueRank> : AttributeHandlerScalar<ValueRank> {};
155
156template <>
157struct AttributeHandler<AttributeId::ArrayDimensions> {
158 using Type = std::vector<uint32_t>;
159
160 static Result<Type> fromDataValue(DataValue&& dv) noexcept {
161 return getVariant(std::move(dv)).transform([](Variant&& var) {
162 assert(var.isType<uint32_t>());
163 assert(var.isArray());
164 return std::move(var).to<Type>();
165 });
166 }
167
168 static DataValue toDataValue(Span<const uint32_t> dimensions) {
169 return DataValue(Variant(dimensions));
170 }
171};
172
173template <>
174struct AttributeHandler<AttributeId::AccessLevel> : AttributeHandlerScalar<Bitmask<AccessLevel>> {};
175
176template <>
177struct AttributeHandler<AttributeId::UserAccessLevel>
178 : AttributeHandlerScalar<Bitmask<AccessLevel>> {};
179
180template <>
181struct AttributeHandler<AttributeId::MinimumSamplingInterval> : AttributeHandlerScalar<double> {};
182
183template <>
184struct AttributeHandler<AttributeId::Historizing> : AttributeHandlerScalar<bool> {};
185
186template <>
187struct AttributeHandler<AttributeId::Executable> : AttributeHandlerScalar<bool> {};
188
189template <>
190struct AttributeHandler<AttributeId::UserExecutable> : AttributeHandlerScalar<bool> {};
191
192template <>
193struct AttributeHandler<AttributeId::DataTypeDefinition> : AttributeHandlerVariant {};
194
195} // namespace opcua::services::detail
std::underlying_type_t< T > Underlying
Definition bitmask.hpp:132
Span(Container &) -> Span< typename Container::value_type >
NodeClass
Node class.
Definition common.hpp:111
AccessLevel
Access level.
Definition common.hpp:134
EventNotifier
Event notifier.
Definition common.hpp:214
ValueRank
Value rank.
Definition common.hpp:197
WriteMask
Write mask.
Definition common.hpp:156
AttributeId
Attribute identifiers.
Definition common.hpp:28
@ UserExecutable
Indicates if the method is currently executable taking user access rights into account.
@ Historizing
Indicates whether the server is actively collecting data for the history of the variable.
@ Executable
Indicates if the method is currently executable.
@ DisplayName
The localized name of the node.
@ NodeId
Unambiguous identifier of a node.
@ BrowseName
A non-localised human-readable name used to browse the address space.
@ Value
The most recent value of the variable that the server has.
@ MinimumSamplingInterval
Specifies (in milliseconds) how fast the server can reasonably sample the value for changes.
@ IsAbstract
If a reference is abstract, no reference of this type shall exist, only of its subtypes.
@ InverseName
The inverse name describes the reference type as seen from the target node.
@ DataType
The NodeId of the data type definition for the Value attribute.
@ Description
Explains the meaning of the node in a localized text.
@ UserWriteMask
Exposes the possibilities of a client to write the attributes of the node.
@ ArrayDimensions
Specifies the maximum supported length of each dimension of the Value attribute.
@ ContainsNoLoops
Indicates that by following the references in the context of the view there are no loops.
@ UserAccessLevel
Indicates how the value of a variable can be accessed (read/write) and if it contains current and/or ...
@ DataTypeDefinition
Provides the meta data and encoding information for custom data types.
@ Symmetric
If a reference is symmetric, it can seen from both the source and target node.
UA_VARIANT_DATA_NODELETE