Quellcode durchsuchen

Clientside UA_Client_getAttributeValue() is in place.

ichrispa vor 9 Jahren
Ursprung
Commit
e9792a4415
3 geänderte Dateien mit 252 neuen und 5 gelöschten Zeilen
  1. 3 5
      doc/tutorial_nodes.rst
  2. 5 0
      include/ua_client.h
  3. 244 0
      src/client/ua_client.c

+ 3 - 5
doc/tutorial_nodes.rst

@@ -306,10 +306,8 @@ Supposing the client wants to clean up? All we need to do is to pass the nodeId
       return 0;
     } 
 
-Assigning and changing values
------------------------------
+Conclusion
+----------
 
-
-Callback concept and datasources
---------------------------------
+In this tutorial you learned how to create a client and create or delete nodes on the server and client side. In the next tutorial, we will cover how to manipulate node contents and how to use callbacks in datasources for ever changing variables (such as time or temperature data) on the serverside.
 

+ 5 - 0
include/ua_client.h

@@ -153,6 +153,11 @@ UA_Client_getNodeCopy(UA_Client *client, UA_NodeId nodeId, void **copyInto);
 UA_StatusCode UA_EXPORT 
 UA_Client_deleteNodeCopy(UA_Client *client, void **node);
 
+UA_StatusCode UA_EXPORT 
+UA_Client_setAttributeValue(UA_Client *client, UA_NodeId nodeId, UA_AttributeId attributeId, void *value);
+UA_StatusCode UA_EXPORT 
+UA_Client_getAttributeValue(UA_Client *client, UA_NodeId nodeId, UA_AttributeId attributeId, void **value);
+
 #ifdef __cplusplus
 } // extern "C"
 #endif

+ 244 - 0
src/client/ua_client.c

@@ -1731,4 +1731,248 @@ UA_Client_getNodeCopy(UA_Client *client, UA_NodeId nodeId, void **copyInto) {
 
 UA_StatusCode UA_Client_deleteNodeCopy(UA_Client *client, void **node) {
   return UA_Server_deleteNodeCopy(UA_NULL, node);
+}
+
+#define SETATTRIBUTE_COPYTYPEVALUE(TYPE)                                                       \
+wrq->nodesToWrite[0].value.value.data = UA_##TYPE##_new();                                     \
+UA_##TYPE##_copy((UA_##TYPE *) value, (UA_##TYPE *) wrq->nodesToWrite[0].value.value.data);
+
+UA_StatusCode 
+UA_Client_setAttributeValue(UA_Client *client, UA_NodeId nodeId, UA_AttributeId attributeId, void *value) {
+  UA_StatusCode retval = UA_STATUSCODE_GOOD;
+  
+  UA_WriteRequest *wrq = UA_WriteRequest_new();
+  UA_WriteResponse wrs;
+  UA_WriteResponse_init(&wrs);
+  wrq->nodesToWriteSize = 1;
+  wrq->nodesToWrite = UA_WriteValue_new();
+  UA_NodeId_copy(&nodeId, &wrq->nodesToWrite[0].nodeId);
+  wrq->nodesToWrite[0].attributeId = attributeId;
+  wrq->nodesToWrite[0].value.hasValue = UA_TRUE;
+  wrq->nodesToWrite[0].value.value.storageType = UA_VARIANT_DATA;
+  
+  switch(attributeId) {
+    case UA_ATTRIBUTEID_NODEID:
+      UA_WriteRequest_delete(wrq);
+      UA_WriteResponse_deleteMembers(&wrs);
+      return UA_STATUSCODE_BADATTRIBUTEIDINVALID;
+      break;
+    case UA_ATTRIBUTEID_NODECLASS:
+      UA_WriteRequest_delete(wrq);
+      UA_WriteResponse_deleteMembers(&wrs);
+      return UA_STATUSCODE_BADATTRIBUTEIDINVALID;
+      break;
+    case UA_ATTRIBUTEID_BROWSENAME:
+      wrq->nodesToWrite[0].value.value.type = &UA_TYPES[UA_TYPES_QUALIFIEDNAME];
+      SETATTRIBUTE_COPYTYPEVALUE(QualifiedName);
+      break;
+    case UA_ATTRIBUTEID_DISPLAYNAME:
+      wrq->nodesToWrite[0].value.value.type = &UA_TYPES[UA_TYPES_LOCALIZEDTEXT];
+      SETATTRIBUTE_COPYTYPEVALUE(LocalizedText);
+      break;
+    case UA_ATTRIBUTEID_DESCRIPTION:
+      wrq->nodesToWrite[0].value.value.type = &UA_TYPES[UA_TYPES_LOCALIZEDTEXT];
+      SETATTRIBUTE_COPYTYPEVALUE(LocalizedText);
+      break;
+    case UA_ATTRIBUTEID_WRITEMASK:
+      wrq->nodesToWrite[0].value.value.type = &UA_TYPES[UA_TYPES_UINT32];
+      SETATTRIBUTE_COPYTYPEVALUE(UInt32);
+      break;
+    case UA_ATTRIBUTEID_USERWRITEMASK:
+      wrq->nodesToWrite[0].value.value.type = &UA_TYPES[UA_TYPES_UINT32];
+      SETATTRIBUTE_COPYTYPEVALUE(UInt32);
+      break;    
+    case UA_ATTRIBUTEID_ISABSTRACT:
+      wrq->nodesToWrite[0].value.value.type = &UA_TYPES[UA_TYPES_BOOLEAN];
+      SETATTRIBUTE_COPYTYPEVALUE(Boolean);
+      break;
+    case UA_ATTRIBUTEID_SYMMETRIC:
+      wrq->nodesToWrite[0].value.value.type = &UA_TYPES[UA_TYPES_BOOLEAN];
+      SETATTRIBUTE_COPYTYPEVALUE(Boolean);
+      break;
+    case UA_ATTRIBUTEID_INVERSENAME:
+      wrq->nodesToWrite[0].value.value.type = &UA_TYPES[UA_TYPES_LOCALIZEDTEXT];
+      SETATTRIBUTE_COPYTYPEVALUE(LocalizedText);
+      break;
+    case UA_ATTRIBUTEID_CONTAINSNOLOOPS:
+      wrq->nodesToWrite[0].value.value.type = &UA_TYPES[UA_TYPES_BOOLEAN];
+      SETATTRIBUTE_COPYTYPEVALUE(Boolean);
+      break;
+    case UA_ATTRIBUTEID_EVENTNOTIFIER:
+      wrq->nodesToWrite[0].value.value.type = &UA_TYPES[UA_TYPES_BYTE];
+      SETATTRIBUTE_COPYTYPEVALUE(Byte); 
+      break;
+    case UA_ATTRIBUTEID_VALUE:
+      UA_Variant_copy((UA_Variant *) value, (UA_Variant *) &wrq->nodesToWrite[0].value.value);
+      break;
+    case UA_ATTRIBUTEID_DATATYPE:
+      UA_WriteRequest_delete(wrq);
+      UA_WriteResponse_deleteMembers(&wrs);
+      return UA_STATUSCODE_BADATTRIBUTEIDINVALID;
+      break;
+    case UA_ATTRIBUTEID_VALUERANK:
+      UA_WriteRequest_delete(wrq);
+      UA_WriteResponse_deleteMembers(&wrs);
+      return UA_STATUSCODE_BADATTRIBUTEIDINVALID;
+      break;
+    case UA_ATTRIBUTEID_ARRAYDIMENSIONS:
+      UA_WriteRequest_delete(wrq);
+      UA_WriteResponse_deleteMembers(&wrs);
+      return UA_STATUSCODE_BADATTRIBUTEIDINVALID;
+      break;
+    case UA_ATTRIBUTEID_ACCESSLEVEL:
+      wrq->nodesToWrite[0].value.value.type = &UA_TYPES[UA_TYPES_UINT32];
+      SETATTRIBUTE_COPYTYPEVALUE(UInt32);
+      break;
+    case UA_ATTRIBUTEID_USERACCESSLEVEL:
+      wrq->nodesToWrite[0].value.value.type = &UA_TYPES[UA_TYPES_UINT32];
+      SETATTRIBUTE_COPYTYPEVALUE(UInt32);
+      break;
+    case UA_ATTRIBUTEID_MINIMUMSAMPLINGINTERVAL:
+      wrq->nodesToWrite[0].value.value.type = &UA_TYPES[UA_TYPES_DOUBLE];
+      SETATTRIBUTE_COPYTYPEVALUE(Double);
+      break;
+    case UA_ATTRIBUTEID_HISTORIZING:
+      wrq->nodesToWrite[0].value.value.type = &UA_TYPES[UA_TYPES_BOOLEAN];
+      SETATTRIBUTE_COPYTYPEVALUE(Boolean);
+      break;
+    case UA_ATTRIBUTEID_EXECUTABLE:
+      wrq->nodesToWrite[0].value.value.type = &UA_TYPES[UA_TYPES_BOOLEAN];
+      SETATTRIBUTE_COPYTYPEVALUE(Boolean);
+      break;
+    case UA_ATTRIBUTEID_USEREXECUTABLE:
+      wrq->nodesToWrite[0].value.value.type = &UA_TYPES[UA_TYPES_BOOLEAN];
+      SETATTRIBUTE_COPYTYPEVALUE(Boolean);
+      break;
+    default:
+      UA_WriteRequest_delete(wrq);
+      UA_WriteResponse_deleteMembers(&wrs);
+      return UA_STATUSCODE_BADATTRIBUTEIDINVALID;
+  }
+  
+  wrs = UA_Client_write(client, wrq);
+  UA_WriteRequest_delete(wrq);
+  
+  if (wrs.responseHeader.serviceResult)
+    return wrs.responseHeader.serviceResult;
+  if (wrs.resultsSize != 1)
+    return wrs.responseHeader.serviceResult;
+  
+  retval = wrs.results[0];
+  
+  UA_WriteResponse_deleteMembers(&wrs);
+  return retval;
+}
+
+#define GETATTRIBUTE_COPYTYPEVALUE(TYPE)                                           \
+if (rrs.results[0].hasValue == UA_TRUE) {                                          \
+  *value = (void *) UA_##TYPE##_new();                                             \
+  UA_##TYPE##_copy((UA_##TYPE *) rrs.results[0].value.data, (UA_##TYPE *) *value  ); \
+}
+  
+UA_StatusCode UA_EXPORT 
+UA_Client_getAttributeValue(UA_Client *client, UA_NodeId nodeId, UA_AttributeId attributeId, void **value) {
+  UA_StatusCode retval = UA_STATUSCODE_GOOD;
+  UA_ReadRequest *rrq = UA_ReadRequest_new();
+  UA_ReadResponse rrs;
+  UA_ReadResponse_init(&rrs);
+  *value = UA_NULL;
+  
+  rrq->timestampsToReturn = UA_TIMESTAMPSTORETURN_NEITHER;
+  rrq->nodesToReadSize = 1;
+  rrq->nodesToRead = UA_ReadValueId_new();
+  rrq->nodesToRead[0].attributeId = attributeId;
+  UA_NodeId_copy(&nodeId, &rrq->nodesToRead[0].nodeId);
+  
+  rrs = UA_Client_read(client, rrq);
+  UA_ReadRequest_delete(rrq);
+  
+  if(rrs.responseHeader.serviceResult != UA_STATUSCODE_GOOD)
+    return rrs.responseHeader.serviceResult;
+  if(rrs.resultsSize < 1)
+    return rrs.responseHeader.serviceResult;
+  if (rrs.results[0].status != UA_STATUSCODE_GOOD)
+    return rrs.results[0].status;
+  
+  switch(attributeId) {
+    case UA_ATTRIBUTEID_NODEID:
+      GETATTRIBUTE_COPYTYPEVALUE(NodeId)
+      break;
+    case UA_ATTRIBUTEID_NODECLASS:
+      GETATTRIBUTE_COPYTYPEVALUE(NodeClass)
+      break;
+    case UA_ATTRIBUTEID_BROWSENAME:
+      GETATTRIBUTE_COPYTYPEVALUE(QualifiedName)
+      break;
+    case UA_ATTRIBUTEID_DISPLAYNAME:
+      GETATTRIBUTE_COPYTYPEVALUE(LocalizedText)
+      break;
+    case UA_ATTRIBUTEID_DESCRIPTION:
+      GETATTRIBUTE_COPYTYPEVALUE(LocalizedText)
+      break;
+    case UA_ATTRIBUTEID_WRITEMASK:
+      GETATTRIBUTE_COPYTYPEVALUE(UInt32)
+      break;
+    case UA_ATTRIBUTEID_USERWRITEMASK:
+      GETATTRIBUTE_COPYTYPEVALUE(UInt32)
+      break;    
+    case UA_ATTRIBUTEID_ISABSTRACT:
+      GETATTRIBUTE_COPYTYPEVALUE(Boolean)
+      break;
+    case UA_ATTRIBUTEID_SYMMETRIC:
+      GETATTRIBUTE_COPYTYPEVALUE(Boolean)
+      break;
+    case UA_ATTRIBUTEID_INVERSENAME:
+      GETATTRIBUTE_COPYTYPEVALUE(LocalizedText)
+      break;
+    case UA_ATTRIBUTEID_CONTAINSNOLOOPS:
+      GETATTRIBUTE_COPYTYPEVALUE(Boolean)
+      break;
+    case UA_ATTRIBUTEID_EVENTNOTIFIER:
+      GETATTRIBUTE_COPYTYPEVALUE(Byte)
+      break;
+    case UA_ATTRIBUTEID_VALUE:
+      GETATTRIBUTE_COPYTYPEVALUE(Variant)
+      break;
+    case UA_ATTRIBUTEID_DATATYPE:
+      *value = UA_NULL;
+      UA_ReadResponse_deleteMembers(&rrs);
+      return UA_STATUSCODE_BADATTRIBUTEIDINVALID;
+      break;
+    case UA_ATTRIBUTEID_VALUERANK:
+      *value = UA_NULL;
+      UA_ReadResponse_deleteMembers(&rrs);
+      return UA_STATUSCODE_BADATTRIBUTEIDINVALID;
+      break;
+    case UA_ATTRIBUTEID_ARRAYDIMENSIONS:
+      *value = UA_NULL;
+      UA_ReadResponse_deleteMembers(&rrs);
+      return UA_STATUSCODE_BADATTRIBUTEIDINVALID;
+      break;
+    case UA_ATTRIBUTEID_ACCESSLEVEL:
+      GETATTRIBUTE_COPYTYPEVALUE(UInt32)
+      break;
+    case UA_ATTRIBUTEID_USERACCESSLEVEL:
+      GETATTRIBUTE_COPYTYPEVALUE(UInt32)
+      break;
+    case UA_ATTRIBUTEID_MINIMUMSAMPLINGINTERVAL:
+      GETATTRIBUTE_COPYTYPEVALUE(Double)
+      break;
+    case UA_ATTRIBUTEID_HISTORIZING:
+      GETATTRIBUTE_COPYTYPEVALUE(Boolean)
+      break;
+    case UA_ATTRIBUTEID_EXECUTABLE:
+      GETATTRIBUTE_COPYTYPEVALUE(Boolean)
+      break;
+    case UA_ATTRIBUTEID_USEREXECUTABLE:
+      GETATTRIBUTE_COPYTYPEVALUE(Boolean)
+      break;
+    default:
+      *value = UA_NULL;
+      UA_ReadResponse_deleteMembers(&rrs);
+      return UA_STATUSCODE_BADATTRIBUTEIDINVALID;
+  }
+  
+  UA_ReadResponse_deleteMembers(&rrs);
+  return retval;
 }