Przeglądaj źródła

use functionality already provided in the services

Julius Pfrommer 9 lat temu
rodzic
commit
0628fac947

+ 15 - 3
include/ua_server.h

@@ -133,6 +133,9 @@ UA_StatusCode UA_EXPORT UA_Server_addReference(UA_Server *server, const UA_NodeI
  */
 UA_StatusCode UA_EXPORT UA_Server_deleteNode(UA_Server *server, UA_NodeId nodeId);
 
+UA_StatusCode UA_Server_getNodeCopy(UA_Server *server, UA_NodeId nodeId, void **copyInto);
+UA_StatusCode UA_Server_deleteNodeCopy(UA_Server *server, void **nodeptr);
+
 /** A new variable Node with a value passed in variant.
  *
  * @param server The server object
@@ -316,10 +319,19 @@ UA_StatusCode UA_EXPORT
 UA_Server_setNodeAttribute_valueDataSource(UA_Server *server, UA_NodeId nodeId, UA_DataSource *value);
 
 UA_StatusCode UA_EXPORT
-UA_Server_getNodeAttribute(UA_Server *server, UA_NodeId nodeId, UA_AttributeId attributeId, void **value);
+UA_Server_getNodeAttribute(UA_Server *server, UA_NodeId nodeId, UA_AttributeId attributeId, UA_Variant *v);
+
+UA_StatusCode UA_EXPORT
+UA_Server_getNodeAttributeUnpacked(UA_Server *server, UA_NodeId nodeId, UA_AttributeId attributeId, void *v);
   
-#define UA_Server_getNodeAttribute_nodeId(SERVER, NODEID, VALUE) UA_Server_getAttribute(SERVER, NODEID, UA_ATTRIBUTEID_NODEID, (UA_NodeId **) VALUE);
-#define UA_Server_getNodeAttribute_nodeClass(SERVER, NODEID, VALUE) UA_Server_getAttribute(SERVER, NODEID, UA_ATTRIBUTEID_NODECLASS, (UA_NodeClass **) VALUE);
+static UA_INLINE UA_StatusCode UA_Server_getNodeAttribute_nodeId(UA_Server *server, UA_NodeId nodeId, UA_NodeId *outNodeId) {
+    return UA_Server_getNodeAttributeUnpacked(server, nodeId, UA_ATTRIBUTEID_NODEID, outNodeId);
+}
+
+static UA_INLINE UA_StatusCode UA_Server_getNodeAttribute_nodeClass(UA_Server *server, UA_NodeId nodeId, UA_NodeClass *outNodeClass) {
+    return UA_Server_getNodeAttributeUnpacked(server, nodeId, UA_ATTRIBUTEID_NODECLASS, outNodeClass);
+}
+
 #define UA_Server_getNodeAttribute_browseName(SERVER, NODEID, VALUE) UA_Server_getAttribute(SERVER, NODEID, UA_ATTRIBUTEID_BROWSENAME, (UA_QualifiedName **) VALUE);
 #define UA_Server_getNodeAttribute_displayName(SERVER, NODEID, VALUE) UA_Server_getAttribute(SERVER, NODEID, UA_ATTRIBUTEID_DISPLAYNAME, (UA_LocalizedText **) VALUE);
 #define UA_Server_getNodeAttribute_description(SERVER, NODEID, VALUE) UA_Server_getAttribute(SERVER, NODEID, UA_ATTRIBUTEID_DESCRIPTION, (UA_LocalizedText **) VALUE);

+ 2 - 2
src/server/ua_nodes.c

@@ -71,8 +71,8 @@ void UA_Node_deleteAnyNodeClass(UA_Node *node) {
     }
 }
 
-typedef const UA_Node *(*UA_CopyNodeFunction)(const UA_Node *src, UA_Node *dst);
-typedef const UA_Node *(*UA_NewNodeFunction)(void);
+typedef UA_Node *(*UA_NewNodeFunction)(void);
+typedef UA_StatusCode *(*UA_CopyNodeFunction)(const UA_Node *src, UA_Node *dst);
 typedef void (*UA_DeleteNodeFunction)(UA_Node *p);
 
 UA_Node * UA_Node_copyAnyNodeClass(const UA_Node *node) {

+ 115 - 10
src/server/ua_server_addressspace.c

@@ -2,6 +2,97 @@
 #include "ua_services.h"
 #include "ua_server_internal.h"
 
+UA_StatusCode UA_Server_getNodeCopy(UA_Server *server, UA_NodeId nodeId, void **copyInto) {
+  const UA_Node *node = UA_NodeStore_get(server->nodestore, &nodeId);
+  UA_Node **copy = (UA_Node **) copyInto;
+  
+  UA_StatusCode retval = UA_STATUSCODE_GOOD;
+  
+  if (!node)
+    return UA_STATUSCODE_BADNODEIDINVALID;
+  
+  switch(node->nodeClass) {
+    case UA_NODECLASS_DATATYPE:
+      *copy = (UA_Node *) UA_VariableNode_new();
+      retval |= UA_DataTypeNode_copy((const UA_DataTypeNode *) node, (UA_DataTypeNode *) *copy);
+      break;
+    case UA_NODECLASS_METHOD:
+      *copy =  (UA_Node *) UA_MethodNode_new();
+      retval |= UA_MethodNode_copy((const UA_MethodNode *) node, (UA_MethodNode *) *copy);
+      break;      
+    case UA_NODECLASS_OBJECT:
+      *copy =  (UA_Node *) UA_ObjectNode_new();
+      retval |= UA_ObjectNode_copy((const UA_ObjectNode *) node, (UA_ObjectNode *) *copy);
+      break;      
+    case UA_NODECLASS_OBJECTTYPE:
+      *copy =  (UA_Node *) UA_ObjectTypeNode_new();
+      retval |= UA_ObjectTypeNode_copy((const UA_ObjectTypeNode *) node, (UA_ObjectTypeNode *) *copy);
+      break;      
+    case UA_NODECLASS_REFERENCETYPE:
+      *copy =  (UA_Node *) UA_ReferenceTypeNode_new();
+      retval |= UA_ReferenceTypeNode_copy((const UA_ReferenceTypeNode *) node, (UA_ReferenceTypeNode *) *copy);
+      break;      
+    case UA_NODECLASS_VARIABLE:
+      *copy =  (UA_Node *) UA_VariableNode_new();
+      retval |= UA_VariableNode_copy((const UA_VariableNode *) node, (UA_VariableNode *) *copy);
+      break;      
+    case UA_NODECLASS_VARIABLETYPE:
+      *copy =  (UA_Node *) UA_VariableTypeNode_new();
+      retval |= UA_VariableTypeNode_copy((const UA_VariableTypeNode *) node, (UA_VariableTypeNode *) *copy);
+      break;      
+    case UA_NODECLASS_VIEW:
+      *copy =  (UA_Node *) UA_ViewNode_new();
+      retval |= UA_ViewNode_copy((const UA_ViewNode *) node, (UA_ViewNode *) *copy);
+      break;      
+    default:
+      break;
+  }
+  
+  UA_NodeStore_release(node);
+  
+  return retval;
+} 
+
+UA_StatusCode UA_Server_deleteNodeCopy(UA_Server *server, void **nodeptr) {
+  UA_StatusCode retval = UA_STATUSCODE_GOOD;
+  UA_Node **node = (UA_Node **) nodeptr;
+  
+  if (!(*node))
+    return UA_STATUSCODE_BADNODEIDINVALID;
+  
+  switch((*node)->nodeClass) {
+    case UA_NODECLASS_DATATYPE:
+      UA_DataTypeNode_delete((UA_DataTypeNode *) *node);
+      break;
+    case UA_NODECLASS_METHOD:
+      UA_MethodNode_delete((UA_MethodNode *) *node);
+      break;      
+    case UA_NODECLASS_OBJECT:
+      UA_ObjectNode_delete((UA_ObjectNode *) *node);
+      break;      
+    case UA_NODECLASS_OBJECTTYPE:
+      UA_ObjectTypeNode_delete((UA_ObjectTypeNode *) *node);
+      break;      
+    case UA_NODECLASS_REFERENCETYPE:
+      UA_ReferenceTypeNode_delete((UA_ReferenceTypeNode *) *node);
+      break;      
+    case UA_NODECLASS_VARIABLE:
+      UA_VariableNode_delete((UA_VariableNode *) *node);
+      break;      
+    case UA_NODECLASS_VARIABLETYPE:
+      UA_VariableTypeNode_delete((UA_VariableTypeNode *) *node);
+      break;      
+    case UA_NODECLASS_VIEW:
+      UA_ViewNode_delete((UA_ViewNode *) *node);
+      break;      
+    default:
+      break;
+  }
+  
+  return retval;
+} 
+
+
 UA_StatusCode UA_Server_deleteNode(UA_Server *server, UA_NodeId nodeId) {
   union nodeUnion {
     const UA_Node *delNodeConst;
@@ -761,7 +852,7 @@ UA_StatusCode UA_Server_setNodeAttribute(UA_Server *server, const UA_NodeId node
     wvalue.attributeId = attributeId;
     wvalue.value.value = value;
     wvalue.value.hasValue = UA_TRUE;
-    return UA_Service_Write_single(server, &adminSession, &wvalue);
+    return Service_Write_single(server, &adminSession, &wvalue);
 }
 
 #ifdef ENABLE_METHODCALLS
@@ -846,15 +937,31 @@ UA_Server_setNodeAttribute_valueDataSource(UA_Server *server, UA_NodeId nodeId,
 }
 
 UA_StatusCode UA_Server_getNodeAttribute(UA_Server *server, const UA_NodeId nodeId, UA_AttributeId attributeId, UA_Variant *v) {
-    const UA_ReadValueId rvi = {.nodeId = nodeId, .attributeId = attributeId, indexRange = UA_STRING_NULL,
+    const UA_ReadValueId rvi = {.nodeId = nodeId, .attributeId = attributeId, .indexRange = UA_STRING_NULL,
                                 .dataEncoding = UA_QUALIFIEDNAME(0, "DefaultBinary")};
     UA_DataValue dv;
     UA_DataValue_init(&dv);
-    UA_StatusCode retval = Service_Read_single(server, &adminSession, UA_TIMESTAMPSTORETURN_NEITHER,
-                                               &rvi, &dv);
+    Service_Read_single(server, &adminSession, UA_TIMESTAMPSTORETURN_NEITHER, &rvi, &dv);
+    if(dv.hasStatus && dv.status != UA_STATUSCODE_GOOD)
+        return dv.status;
+    *v = dv.value; // The caller needs to free the content eventually
+    return UA_STATUSCODE_GOOD;
+}
+
+UA_StatusCode UA_Server_getNodeAttributeUnpacked(UA_Server *server, const UA_NodeId nodeId, const UA_AttributeId attributeId, void *v) {
+    UA_Variant out;
+    UA_Variant_init(&out);
+    UA_StatusCode retval = UA_Server_getNodeAttribute(server, nodeId, attributeId, &out); 
     if(retval != UA_STATUSCODE_GOOD)
         return retval;
-    *v = dv.value; // The caller needs to free the content eventually
+    if(attributeId == UA_ATTRIBUTEID_VALUE)
+        UA_memcpy(v, &out, sizeof(UA_Variant));
+    else {
+        UA_memcpy(v, out.data, out.type->memSize);
+        out.data = UA_NULL;
+        out.arrayLength = -1;
+        UA_Variant_deleteMembers(&out);
+    }
     return UA_STATUSCODE_GOOD;
 }
 
@@ -1023,7 +1130,7 @@ void UA_Server_addInstanceOf_instatiateChildNode(UA_Server *server, arrayOfNodeI
                                                  void *typeDefNode, UA_Boolean instantiateObjects, arrayOfNodeIds *instantiatedTypes,
                                                  void *handle) {
   UA_Boolean refTypeValid;
-  UA_NodeClass *refClass;
+  UA_NodeClass refClass;
   UA_Node      *nodeClone;
   UA_ExpandedNodeId *objectRootExpanded = UA_ExpandedNodeId_new();
   UA_VariableNode *newVarNode;
@@ -1040,9 +1147,8 @@ void UA_Server_addInstanceOf_instatiateChildNode(UA_Server *server, arrayOfNodeI
       continue;
     
     // What type of node is this?
-    refClass = UA_NULL;
-    UA_Server_getNodeAttribute(server, ref.targetId.nodeId, UA_ATTRIBUTEID_NODECLASS, (void **) &refClass);
-    switch (*refClass) {
+    UA_Server_getNodeAttribute_nodeClass(server, ref.targetId.nodeId, &refClass);
+    switch (refClass) {
       case UA_NODECLASS_VARIABLE: // Just clone the variable node with a new nodeId
         UA_Server_getNodeCopy(server, ref.targetId.nodeId, (void **) &nodeClone);
         if (nodeClone == UA_NULL)
@@ -1119,7 +1225,6 @@ void UA_Server_addInstanceOf_instatiateChildNode(UA_Server *server, arrayOfNodeI
       default:
         break;
     }
-    UA_NodeClass_delete(refClass);
   }
   
   if (objectRootExpanded != UA_NULL)

+ 7 - 2
src/server/ua_services_attribute.c

@@ -433,7 +433,7 @@ void Service_Read(UA_Server *server, UA_Session *session, const UA_ReadRequest *
 			break;														\
 		} } while(0)
 
-UA_StatusCode UA_Service_Write_single(UA_Server *server, UA_Session *session, const UA_WriteValue *wvalue) {
+UA_StatusCode Service_Write_single(UA_Server *server, UA_Session *session, const UA_WriteValue *wvalue) {
 	UA_assert(server != UA_NULL && session != UA_NULL && wvalue != UA_NULL);
 
 	union {
@@ -454,6 +454,11 @@ UA_StatusCode UA_Service_Write_single(UA_Server *server, UA_Session *session, co
   
 	void *value = wvalue->value.value.data;
 	switch(wvalue->attributeId) {
+    case UA_ATTRIBUTEID_NODEID:
+    case UA_ATTRIBUTEID_NODECLASS:
+    case UA_ATTRIBUTEID_DATATYPE:
+		retval = UA_STATUSCODE_BADWRITENOTSUPPORTED;
+		break;
 	case UA_ATTRIBUTEID_BROWSENAME:
 		CHECK_DATATYPE(QUALIFIEDNAME);
 		UA_QualifiedName_deleteMembers(&anyTypeNode.node->browseName);
@@ -662,6 +667,6 @@ void Service_Write(UA_Server *server, UA_Session *session, const UA_WriteRequest
 #ifdef UA_EXTERNAL_NAMESPACES
         if(!isExternal[i])
 #endif
-		  response->results[i] = UA_Service_Write_single(server, session, &request->nodesToWrite[i]);
+		  response->results[i] = Service_Write_single(server, session, &request->nodesToWrite[i]);
     }
 }

Plik diff jest za duży
+ 181 - 387
tests/check_services_attributes.c