1 #ifndef OPCUABRIDGE_COMMON_H_ 2 #define OPCUABRIDGE_COMMON_H_ 4 #ifdef OPCUABRIDGE_ENABLE_SERIALIZATION 11 #include <json/json.h> 12 #include <open62541.h> 18 #include "opcuabridgeconfig.h" 21 namespace filesystem {
26 #define INITSERVERNODESET_FUNCTION_DEFINITION(TYPE) \ 27 void InitServerNodeset(UA_Server *server) { \ 28 opcuabridge::internal::AddDataSourceVariable<TYPE>(server, node_id_, this); \ 31 #define INITSERVERNODESET_BIN_FUNCTION_DEFINITION(TYPE, BINDATA) \ 32 void InitServerNodeset(UA_Server *server) { \ 33 opcuabridge::internal::AddDataSourceVariable<TYPE>(server, node_id_, this); \ 34 opcuabridge::internal::AddDataSourceVariable<opcuabridge::MessageBinaryData>( \ 35 server, bin_node_id_, BINDATA, UA_NODEID_STRING(kNSindex, const_cast<char *>(node_id_))); \ 38 #define INITSERVERNODESET_FILE_FUNCTION_DEFINITION(TYPE) \ 39 void InitServerNodeset(UA_Server *server) { \ 40 opcuabridge::internal::AddDataSourceVariable<TYPE>(server, node_id_, this); \ 41 opcuabridge::internal::AddDataSourceVariable<opcuabridge::MessageFileData>( \ 42 server, bin_node_id_, this, UA_NODEID_STRING(kNSindex, const_cast<char *>(node_id_))); \ 45 #define CLIENTWRITE_FUNCTION_DEFINITION() \ 46 UA_StatusCode ClientWrite(UA_Client *client) { return opcuabridge::internal::ClientWrite(client, node_id_, this); } 48 #define CLIENTWRITE_BIN_FUNCTION_DEFINITION(BINDATA) \ 49 UA_StatusCode ClientWrite(UA_Client *client) { \ 50 return opcuabridge::internal::ClientWrite(client, node_id_, this, BINDATA); \ 53 #define CLIENTWRITE_FILE_FUNCTION_DEFINITION() \ 54 UA_StatusCode ClientWriteFile(UA_Client *client, const boost::filesystem::path &f) { \ 55 return opcuabridge::internal::ClientWriteFile(client, node_id_, this, f); \ 58 #define CLIENTREAD_FUNCTION_DEFINITION() \ 59 UA_StatusCode ClientRead(UA_Client *client) { return opcuabridge::internal::ClientRead(client, node_id_, this); } 61 #define CLIENTREAD_BIN_FUNCTION_DEFINITION(BINDATA) \ 62 UA_StatusCode ClientRead(UA_Client *client) { \ 63 return opcuabridge::internal::ClientRead(client, node_id_, this, BINDATA); \ 66 #define READ_FUNCTION_FRIEND_DECLARATION(TYPE) \ 67 friend UA_StatusCode read<TYPE>(UA_Server *, const UA_NodeId *, void *, const UA_NodeId *, void *, UA_Boolean, \ 68 const UA_NumericRange *, UA_DataValue *); 70 #define WRITE_FUNCTION_FRIEND_DECLARATION(TYPE) \ 71 friend UA_StatusCode write<TYPE>(UA_Server *, const UA_NodeId *, void *, const UA_NodeId *, void *, \ 72 const UA_NumericRange *, const UA_DataValue *); 74 #define INTERNAL_FUNCTIONS_FRIEND_DECLARATION(TYPE) \ 75 friend UA_StatusCode opcuabridge::internal::ClientWrite<TYPE>(UA_Client *, const char *, TYPE *); \ 76 friend UA_StatusCode opcuabridge::internal::ClientWrite<TYPE>(UA_Client *, const char *, TYPE *, BinaryDataType *); \ 77 friend UA_StatusCode opcuabridge::internal::ClientRead<TYPE>(UA_Client *, const char *, TYPE *); \ 78 friend UA_StatusCode opcuabridge::internal::ClientRead<TYPE>(UA_Client *, const char *, TYPE *, BinaryDataType *); \ 79 friend UA_StatusCode opcuabridge::internal::ClientWriteFile<TYPE>(UA_Client *, const char *, TYPE *, \ 80 const boost::filesystem::path &); 82 #define WRAPMESSAGE_FUCTION_DEFINITION(TYPE) \ 83 static std::string wrapMessage(TYPE *obj) { \ 84 Json::Value value = obj->wrapMessage(); \ 85 Json::FastWriter fw; \ 86 return fw.write(value); \ 95 void parseJson(
const char *msg,
size_t len, Json::Value *value);
99 #define UNWRAPMESSAGE_FUCTION_DEFINITION(TYPE) \ 100 static void unwrapMessage(TYPE *obj, const char *msg, size_t len) { \ 102 opcuabridge::internal::parseJson(msg, len, &value); \ 103 obj->unwrapMessage(value); \ 106 #define DEFINE_SERIALIZE_METHOD() \ 107 template <typename Archive> \ 108 inline void serialize(Archive &ar, const unsigned int version) 110 #define SERIALIZE_FIELD(AR, XML_TAGNAME, FIELD) \ 111 { utility::make_serialize_field(AR, FIELD)(AR, XML_TAGNAME, FIELD); } 113 #define SERIALIZE_FUNCTION_FRIEND_DECLARATION friend class boost::serialization::access; 117 extern const UA_UInt16 kNSindex;
119 extern const char *kLocale;
121 extern void BoostLogOpcua(UA_LogLevel , UA_LogCategory ,
const char * , va_list );
123 enum HashFunction { HASH_FUN_SHA224, HASH_FUN_SHA256, HASH_FUN_SHA384 };
125 enum SignatureMethod { SIG_METHOD_RSASSA_PSS, SIG_METHOD_ED25519 };
129 virtual std::string getFullFilePath()
const = 0;
132 typedef std::vector<uint8_t> BinaryDataType;
134 template <
typename T>
136 typedef std::function<void(T *)> type;
139 template <
typename T>
141 typedef std::function<void(T *)> type;
144 template <
typename T>
145 UA_StatusCode read(UA_Server *server,
const UA_NodeId *sessionId,
void *sessionContext,
const UA_NodeId *nodeId,
146 void *nodeContext, UA_Boolean sourceTimeStamp,
const UA_NumericRange *range,
147 UA_DataValue *dataValue) {
148 auto *obj =
static_cast<T *
>(nodeContext);
150 if (obj->on_before_read_cb_) {
151 obj->on_before_read_cb_(obj);
154 std::string msg = T::wrapMessage(obj);
156 UA_Variant_setArrayCopy(&dataValue->value, msg.c_str(), msg.size(), &UA_TYPES[UA_TYPES_BYTE]);
157 dataValue->hasValue =
true;
159 return UA_STATUSCODE_GOOD;
163 UA_StatusCode read<MessageBinaryData>(UA_Server *server,
const UA_NodeId *sessionId,
void *sessionContext,
164 const UA_NodeId *nodeId,
void *nodeContext, UA_Boolean sourceTimeStamp,
165 const UA_NumericRange *range, UA_DataValue *dataValue);
168 UA_StatusCode read<MessageFileData>(UA_Server *server,
const UA_NodeId *sessionId,
void *sessionContext,
169 const UA_NodeId *nodeId,
void *nodeContext, UA_Boolean sourceTimeStamp,
170 const UA_NumericRange *range, UA_DataValue *dataValue);
172 template <
typename T>
173 UA_StatusCode write(UA_Server *server,
const UA_NodeId *sessionId,
void *sessionContext,
const UA_NodeId *nodeId,
174 void *nodeContext,
const UA_NumericRange *range,
const UA_DataValue *
data) {
175 auto *obj =
static_cast<T *
>(nodeContext);
177 if (!UA_Variant_isEmpty(&
data->value) && UA_Variant_hasArrayType(&
data->value, &UA_TYPES[UA_TYPES_BYTE])) {
178 T::unwrapMessage(obj, static_cast<const char *>(
data->value.data),
data->value.arrayLength);
180 if (obj->on_after_write_cb_) {
181 obj->on_after_write_cb_(obj);
183 return UA_STATUSCODE_GOOD;
187 UA_StatusCode write<MessageBinaryData>(UA_Server *server,
const UA_NodeId *sessionId,
void *sessionContext,
188 const UA_NodeId *nodeId,
void *nodeContext,
const UA_NumericRange *range,
189 const UA_DataValue *
data);
192 UA_StatusCode write<MessageFileData>(UA_Server *server,
const UA_NodeId *sessionId,
void *sessionContext,
193 const UA_NodeId *nodeId,
void *nodeContext,
const UA_NumericRange *range,
194 const UA_DataValue *
data);
198 template <
typename MessageT>
199 inline void AddDataSourceVariable(UA_Server *server,
const char *node_id,
void *node_context,
200 const UA_NodeId parent_node_id = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER)) {
201 UA_VariableAttributes attr = UA_VariableAttributes_default;
202 attr.displayName = UA_LOCALIZEDTEXT(const_cast<char *>(kLocale), const_cast<char *>(node_id));
203 attr.accessLevel = UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE;
204 UA_DataSource dataSource;
205 dataSource.read = &opcuabridge::read<MessageT>;
206 dataSource.write = &opcuabridge::write<MessageT>;
207 UA_Server_addDataSourceVariableNode(server, UA_NODEID_STRING(kNSindex, const_cast<char *>(node_id)), parent_node_id,
208 UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES),
209 UA_QUALIFIEDNAME(kNSindex, const_cast<char *>(node_id)), UA_NODEID_NULL, attr,
210 dataSource, node_context,
nullptr);
213 template <
typename MessageT>
214 inline UA_StatusCode ClientWrite(UA_Client *client,
const char *node_id, MessageT *obj) {
215 UA_Variant *val = UA_Variant_new();
216 std::string msg = MessageT::wrapMessage(obj);
217 UA_Variant_setArray(val, const_cast<char *>(msg.c_str()), msg.size(), &UA_TYPES[UA_TYPES_BYTE]);
218 val->storageType = UA_VARIANT_DATA_NODELETE;
219 UA_StatusCode retval =
220 UA_Client_writeValueAttribute(client, UA_NODEID_STRING(kNSindex, const_cast<char *>(node_id)), val);
221 UA_Variant_delete(val);
225 template <
typename MessageT>
226 inline UA_StatusCode ClientWrite(UA_Client *client,
const char *node_id, MessageT *obj, BinaryDataType *bin_data) {
228 UA_Variant *bin_val = UA_Variant_new();
229 UA_Variant_setArray(bin_val, &(*bin_data)[0], bin_data->size(), &UA_TYPES[UA_TYPES_BYTE]);
230 bin_val->storageType = UA_VARIANT_DATA_NODELETE;
231 UA_StatusCode retval =
232 UA_Client_writeValueAttribute(client, UA_NODEID_STRING(kNSindex, const_cast<char *>(obj->bin_node_id_)), bin_val);
233 UA_Variant_delete(bin_val);
235 if (retval == UA_STATUSCODE_GOOD) {
236 UA_Variant *val = UA_Variant_new();
237 std::string msg = MessageT::wrapMessage(obj);
238 UA_Variant_setArray(val, const_cast<char *>(msg.c_str()), msg.size(), &UA_TYPES[UA_TYPES_BYTE]);
239 val->storageType = UA_VARIANT_DATA_NODELETE;
240 retval = UA_Client_writeValueAttribute(client, UA_NODEID_STRING(kNSindex, const_cast<char *>(node_id)), val);
241 UA_Variant_delete(val);
246 UA_StatusCode ClientWriteFile(UA_Client * ,
const char * ,
247 const boost::filesystem::path & ,
248 std::size_t block_size = OPCUABRIDGE_FILEDATA_WRITE_BLOCK_SIZE);
250 template <
typename MessageT>
251 inline UA_StatusCode ClientWriteFile(UA_Client *client,
const char *node_id, MessageT *obj,
252 const boost::filesystem::path &file_path) {
253 UA_StatusCode retval = ClientWrite<MessageT>(client, node_id, obj);
254 if (retval == UA_STATUSCODE_GOOD) {
255 retval = ClientWriteFile(client, obj->bin_node_id_, file_path);
260 template <
typename MessageT>
261 inline UA_StatusCode ClientRead(UA_Client *client,
const char *node_id, MessageT *obj) {
262 UA_Variant *val = UA_Variant_new();
263 UA_StatusCode retval =
264 UA_Client_readValueAttribute(client, UA_NODEID_STRING(kNSindex, const_cast<char *>(node_id)), val);
265 if (retval == UA_STATUSCODE_GOOD && UA_Variant_hasArrayType(val, &UA_TYPES[UA_TYPES_BYTE])) {
266 MessageT::unwrapMessage(obj, static_cast<const char *>(val->data), val->arrayLength);
268 UA_Variant_delete(val);
272 template <
typename MessageT>
273 inline UA_StatusCode ClientRead(UA_Client *client,
const char *node_id, MessageT *obj, BinaryDataType *bin_data) {
274 UA_Variant *val = UA_Variant_new();
275 UA_StatusCode retval =
276 UA_Client_readValueAttribute(client, UA_NODEID_STRING(kNSindex, const_cast<char *>(node_id)), val);
277 if (retval == UA_STATUSCODE_GOOD && UA_Variant_hasArrayType(val, &UA_TYPES[UA_TYPES_BYTE])) {
278 MessageT::unwrapMessage(obj, static_cast<const char *>(val->data), val->arrayLength);
280 UA_Variant *bin_val = UA_Variant_new();
281 retval = UA_Client_readValueAttribute(
282 client, UA_NODEID_STRING(kNSindex, const_cast<char *>(obj->bin_node_id_)), bin_val);
283 if (retval == UA_STATUSCODE_GOOD && UA_Variant_hasArrayType(bin_val, &UA_TYPES[UA_TYPES_BYTE])) {
284 bin_data->resize(bin_val->arrayLength);
285 const auto *src =
static_cast<const unsigned char *
>(bin_val->data);
287 std::copy(src, src + bin_val->arrayLength, bin_data->begin());
289 UA_Variant_delete(bin_val);
291 UA_Variant_delete(val);
296 namespace convert_to {
298 template <
typename T>
299 inline Json::Value jsonArray(
const std::vector<T> &v) {
300 Json::Value jsonArray;
301 jsonArray.resize(static_cast<unsigned int>(v.size()));
302 for (
const auto &i : v) {
303 jsonArray.append(i.wrapMessage());
309 inline Json::Value jsonArray<int>(
const std::vector<int> &v) {
310 Json::Value jsonArray;
311 jsonArray.resize(static_cast<unsigned int>(v.size()));
312 for (
const auto &item : v) {
313 jsonArray.append(static_cast<Json::Value::Int>(item));
319 inline Json::Value jsonArray<std::size_t>(
const std::vector<std::size_t> &v) {
320 Json::Value jsonArray;
321 jsonArray.resize(static_cast<unsigned int>(v.size()));
322 for (
const auto &item : v) {
323 jsonArray.append(static_cast<Json::Value::UInt>(item));
328 template <
typename T>
329 inline std::vector<T> stdVector(
const Json::Value &v) {
331 for (
const auto &i : v) {
333 item.unwrapMessage(i);
334 stdv.push_back(item);
340 inline std::vector<int> stdVector(
const Json::Value &v) {
341 std::vector<int> stdv;
342 stdv.reserve(v.size());
343 for (
const auto &item : v) {
344 stdv.push_back(item.asInt());
353 #endif // OPCUABRIDGE_COMMON_H_