ua_client_highlevel.c 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. #include "ua_client.h"
  2. #include "ua_nodeids.h"
  3. #include "ua_client_highlevel.h"
  4. #include "ua_types_encoding_binary.h"
  5. #include "ua_util.h"
  6. UA_StatusCode
  7. UA_Client_NamespaceGetIndex(UA_Client *client, UA_String *namespaceUri, UA_UInt16 *namespaceIndex) {
  8. UA_ReadRequest request;
  9. UA_ReadRequest_init(&request);
  10. UA_ReadValueId id;
  11. id.attributeId = UA_ATTRIBUTEID_VALUE;
  12. id.nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_NAMESPACEARRAY);
  13. request.nodesToRead = &id;
  14. request.nodesToReadSize = 1;
  15. UA_ReadResponse response = UA_Client_Service_read(client, request);
  16. UA_StatusCode retval = UA_STATUSCODE_GOOD;
  17. if(response.responseHeader.serviceResult != UA_STATUSCODE_GOOD)
  18. retval = response.responseHeader.serviceResult;
  19. else if(response.resultsSize != 1 || !response.results[0].hasValue)
  20. retval = UA_STATUSCODE_BADNODEATTRIBUTESINVALID;
  21. else if(response.results[0].value.type != &UA_TYPES[UA_TYPES_STRING])
  22. retval = UA_STATUSCODE_BADTYPEMISMATCH;
  23. if(retval != UA_STATUSCODE_GOOD) {
  24. UA_ReadResponse_deleteMembers(&response);
  25. return retval;
  26. }
  27. retval = UA_STATUSCODE_BADNOTFOUND;
  28. UA_String *ns = response.results[0].value.data;
  29. for(size_t i = 0; i < response.results[0].value.arrayLength; i++){
  30. if(UA_String_equal(namespaceUri, &ns[i])) {
  31. *namespaceIndex = (UA_UInt16)i;
  32. retval = UA_STATUSCODE_GOOD;
  33. break;
  34. }
  35. }
  36. UA_ReadResponse_deleteMembers(&response);
  37. return retval;
  38. }
  39. /*******************/
  40. /* Node Management */
  41. /*******************/
  42. UA_StatusCode UA_EXPORT
  43. UA_Client_addReference(UA_Client *client, const UA_NodeId sourceNodeId, const UA_NodeId referenceTypeId,
  44. UA_Boolean isForward, const UA_String targetServerUri,
  45. const UA_ExpandedNodeId targetNodeId, UA_NodeClass targetNodeClass) {
  46. UA_AddReferencesItem item;
  47. UA_AddReferencesItem_init(&item);
  48. item.sourceNodeId = sourceNodeId;
  49. item.referenceTypeId = referenceTypeId;
  50. item.isForward = isForward;
  51. item.targetServerUri = targetServerUri;
  52. item.targetNodeId = targetNodeId;
  53. item.targetNodeClass = targetNodeClass;
  54. UA_AddReferencesRequest request;
  55. UA_AddReferencesRequest_init(&request);
  56. request.referencesToAdd = &item;
  57. request.referencesToAddSize = 1;
  58. UA_AddReferencesResponse response = UA_Client_Service_addReferences(client, request);
  59. UA_StatusCode retval = response.responseHeader.serviceResult;
  60. if(retval != UA_STATUSCODE_GOOD) {
  61. UA_AddReferencesResponse_deleteMembers(&response);
  62. return retval;
  63. }
  64. if(response.resultsSize != 1) {
  65. UA_AddReferencesResponse_deleteMembers(&response);
  66. return UA_STATUSCODE_BADUNEXPECTEDERROR;
  67. }
  68. retval = response.results[0];
  69. UA_AddReferencesResponse_deleteMembers(&response);
  70. return retval;
  71. }
  72. UA_StatusCode UA_EXPORT
  73. UA_Client_deleteReference(UA_Client *client, const UA_NodeId sourceNodeId, const UA_NodeId referenceTypeId,
  74. UA_Boolean isForward, const UA_ExpandedNodeId targetNodeId,
  75. UA_Boolean deleteBidirectional) {
  76. UA_DeleteReferencesItem item;
  77. UA_DeleteReferencesItem_init(&item);
  78. item.sourceNodeId = sourceNodeId;
  79. item.referenceTypeId = referenceTypeId;
  80. item.isForward = isForward;
  81. item.targetNodeId = targetNodeId;
  82. item.deleteBidirectional = deleteBidirectional;
  83. UA_DeleteReferencesRequest request;
  84. UA_DeleteReferencesRequest_init(&request);
  85. request.referencesToDelete = &item;
  86. request.referencesToDeleteSize = 1;
  87. UA_DeleteReferencesResponse response = UA_Client_Service_deleteReferences(client, request);
  88. UA_StatusCode retval = response.responseHeader.serviceResult;
  89. if(retval != UA_STATUSCODE_GOOD) {
  90. UA_DeleteReferencesResponse_deleteMembers(&response);
  91. return retval;
  92. }
  93. if(response.resultsSize != 1) {
  94. UA_DeleteReferencesResponse_deleteMembers(&response);
  95. return UA_STATUSCODE_BADUNEXPECTEDERROR;
  96. }
  97. retval = response.results[0];
  98. UA_DeleteReferencesResponse_deleteMembers(&response);
  99. return retval;
  100. }
  101. UA_StatusCode
  102. UA_Client_deleteNode(UA_Client *client, const UA_NodeId nodeId, UA_Boolean deleteTargetReferences) {
  103. UA_DeleteNodesItem item;
  104. UA_DeleteNodesItem_init(&item);
  105. item.nodeId = nodeId;
  106. item.deleteTargetReferences = deleteTargetReferences;
  107. UA_DeleteNodesRequest request;
  108. UA_DeleteNodesRequest_init(&request);
  109. request.nodesToDelete = &item;
  110. request.nodesToDeleteSize = 1;
  111. UA_DeleteNodesResponse response = UA_Client_Service_deleteNodes(client, request);
  112. UA_StatusCode retval = response.responseHeader.serviceResult;
  113. if(retval != UA_STATUSCODE_GOOD) {
  114. UA_DeleteNodesResponse_deleteMembers(&response);
  115. return retval;
  116. }
  117. if(response.resultsSize != 1) {
  118. UA_DeleteNodesResponse_deleteMembers(&response);
  119. return UA_STATUSCODE_BADUNEXPECTEDERROR;
  120. }
  121. retval = response.results[0];
  122. UA_DeleteNodesResponse_deleteMembers(&response);
  123. return retval;
  124. }
  125. UA_StatusCode
  126. __UA_Client_addNode(UA_Client *client, const UA_NodeClass nodeClass, const UA_NodeId requestedNewNodeId,
  127. const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId,
  128. const UA_QualifiedName browseName, const UA_NodeId typeDefinition,
  129. const UA_NodeAttributes *attr, const UA_DataType *attributeType, UA_NodeId *outNewNodeId) {
  130. UA_StatusCode retval = UA_STATUSCODE_GOOD;
  131. UA_AddNodesRequest request;
  132. UA_AddNodesRequest_init(&request);
  133. UA_AddNodesItem item;
  134. UA_AddNodesItem_init(&item);
  135. item.parentNodeId.nodeId = parentNodeId;
  136. item.referenceTypeId = referenceTypeId;
  137. item.requestedNewNodeId.nodeId = requestedNewNodeId;
  138. item.browseName = browseName;
  139. item.nodeClass = nodeClass;
  140. item.typeDefinition.nodeId = typeDefinition;
  141. item.nodeAttributes.encoding = UA_EXTENSIONOBJECT_DECODED_NODELETE;
  142. item.nodeAttributes.content.decoded.type = attributeType;
  143. item.nodeAttributes.content.decoded.data = (void*)(uintptr_t)attr; // hack. is not written into.
  144. request.nodesToAdd = &item;
  145. request.nodesToAddSize = 1;
  146. UA_AddNodesResponse response = UA_Client_Service_addNodes(client, request);
  147. if(response.responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
  148. retval = response.responseHeader.serviceResult;
  149. UA_AddNodesResponse_deleteMembers(&response);
  150. return retval;
  151. }
  152. if(response.resultsSize != 1) {
  153. UA_AddNodesResponse_deleteMembers(&response);
  154. return UA_STATUSCODE_BADUNEXPECTEDERROR;
  155. }
  156. if(outNewNodeId && response.results[0].statusCode == UA_STATUSCODE_GOOD) {
  157. *outNewNodeId = response.results[0].addedNodeId;
  158. UA_NodeId_init(&response.results[0].addedNodeId);
  159. }
  160. retval = response.results[0].statusCode;
  161. UA_AddNodesResponse_deleteMembers(&response);
  162. return retval;
  163. }
  164. /********/
  165. /* Call */
  166. /********/
  167. UA_StatusCode
  168. UA_Client_call(UA_Client *client, const UA_NodeId objectId, const UA_NodeId methodId, size_t inputSize,
  169. const UA_Variant *input, size_t *outputSize, UA_Variant **output) {
  170. UA_CallRequest request;
  171. UA_CallRequest_init(&request);
  172. UA_CallMethodRequest item;
  173. UA_CallMethodRequest_init(&item);
  174. item.methodId = methodId;
  175. item.objectId = objectId;
  176. item.inputArguments = (void*)(uintptr_t)input; // cast const...
  177. item.inputArgumentsSize = inputSize;
  178. request.methodsToCall = &item;
  179. request.methodsToCallSize = 1;
  180. UA_CallResponse response = UA_Client_Service_call(client, request);
  181. UA_StatusCode retval = response.responseHeader.serviceResult;
  182. if(retval != UA_STATUSCODE_GOOD) {
  183. UA_CallResponse_deleteMembers(&response);
  184. return retval;
  185. }
  186. if(response.resultsSize != 1) {
  187. UA_CallResponse_deleteMembers(&response);
  188. return UA_STATUSCODE_BADUNEXPECTEDERROR;
  189. }
  190. retval = response.results[0].statusCode;
  191. if(retval == UA_STATUSCODE_GOOD) {
  192. *output = response.results[0].outputArguments;
  193. *outputSize = response.results[0].outputArgumentsSize;
  194. response.results[0].outputArguments = NULL;
  195. response.results[0].outputArgumentsSize = 0;
  196. }
  197. UA_CallResponse_deleteMembers(&response);
  198. return retval;
  199. }
  200. /**************/
  201. /* Attributes */
  202. /**************/
  203. UA_StatusCode
  204. __UA_Client_readAttribute(UA_Client *client, UA_NodeId nodeId, UA_AttributeId attributeId,
  205. void *out, const UA_DataType *outDataType) {
  206. UA_ReadValueId item;
  207. UA_ReadValueId_init(&item);
  208. item.nodeId = nodeId;
  209. item.attributeId = attributeId;
  210. UA_ReadRequest request;
  211. UA_ReadRequest_init(&request);
  212. request.nodesToRead = &item;
  213. request.nodesToReadSize = 1;
  214. UA_ReadResponse response = UA_Client_Service_read(client, request);
  215. UA_StatusCode retval = response.responseHeader.serviceResult;
  216. if(retval == UA_STATUSCODE_GOOD && response.resultsSize != 1)
  217. retval = UA_STATUSCODE_BADUNEXPECTEDERROR;
  218. if(retval != UA_STATUSCODE_GOOD) {
  219. UA_ReadResponse_deleteMembers(&response);
  220. return retval;
  221. }
  222. UA_DataValue *res = response.results;
  223. if(res->hasStatus != UA_STATUSCODE_GOOD)
  224. retval = res->hasStatus;
  225. else if(!res->hasValue || !UA_Variant_isScalar(&res->value))
  226. retval = UA_STATUSCODE_BADUNEXPECTEDERROR;
  227. if(retval != UA_STATUSCODE_GOOD) {
  228. UA_ReadResponse_deleteMembers(&response);
  229. return retval;
  230. }
  231. if(attributeId == UA_ATTRIBUTEID_VALUE) {
  232. memcpy(out, &res->value, sizeof(UA_Variant));
  233. UA_Variant_init(&res->value);
  234. } else if(res->value.type != outDataType) {
  235. retval = UA_STATUSCODE_BADUNEXPECTEDERROR;
  236. } else {
  237. memcpy(out, res->value.data, res->value.type->memSize);
  238. UA_free(res->value.data);
  239. res->value.data = NULL;
  240. }
  241. UA_ReadResponse_deleteMembers(&response);
  242. return retval;
  243. }