Browse Source

Created nodeiterator UA_Client_forEachChildNodeCall for Client.

ichrispa 9 years ago
parent
commit
141c369f5a
5 changed files with 106 additions and 29 deletions
  1. 13 0
      examples/client.c
  2. 8 0
      include/ua_client.h
  3. 3 0
      include/ua_server.h
  4. 53 0
      src/client/ua_client.c
  5. 29 29
      tests/check_services_attributes.c

+ 13 - 0
examples/client.c

@@ -19,6 +19,17 @@ void handler_TheAnswerChanged(UA_UInt32 handle, UA_DataValue *value) {
     return;
 }
 
+UA_StatusCode nodeIter(UA_NodeId childId, UA_Boolean isInverse, UA_NodeId referenceTypeId);
+UA_StatusCode nodeIter(UA_NodeId childId, UA_Boolean isInverse, UA_NodeId referenceTypeId) {  
+  printf("References ns=%d;i=%d using i=%d ", childId.namespaceIndex, childId.identifier.numeric, referenceTypeId.identifier.numeric);
+  if (isInverse == UA_TRUE) {
+    printf(" (inverse)");
+  }
+  printf("\n");
+  
+  return UA_STATUSCODE_GOOD;
+}
+
 int main(int argc, char *argv[]) {
     UA_Client *client = UA_Client_new(UA_ClientConfig_standard, Logger_Stdout_new());
     UA_StatusCode retval = UA_Client_connect(client, ClientNetworkLayerTCP_connect,
@@ -232,6 +243,8 @@ int main(int argc, char *argv[]) {
     free(theValue);
     /* Done creating a new node*/
 #endif
+    UA_Client_forEachChildNodeCall(client, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), nodeIter);
+    
     UA_Client_disconnect(client);
     UA_Client_delete(client);
     return UA_STATUSCODE_GOOD;

+ 8 - 0
include/ua_client.h

@@ -99,6 +99,14 @@ UA_StatusCode UA_EXPORT UA_Client_unMonitorItemChanges(UA_Client *client, UA_UIn
                                                        UA_UInt32 monitoredItemId );
 #endif
 
+#ifndef _HAVE_UA_NODEITERATORCALLBACK_D
+#define _HAVE_UA_NODEITERATORCALLBACK_D
+typedef UA_StatusCode (*UA_NodeIteratorCallback)(UA_NodeId childId, UA_Boolean isInverse, UA_NodeId referenceTypeId);
+#endif
+
+UA_StatusCode UA_EXPORT
+UA_Client_forEachChildNodeCall(UA_Client *client, UA_NodeId parentNodeId, UA_NodeIteratorCallback callback);
+
 #ifdef __cplusplus
 } // extern "C"
 #endif

+ 3 - 0
include/ua_server.h

@@ -346,7 +346,10 @@ UA_Server_addMethodNode(UA_Server *server, const UA_QualifiedName browseName, UA
                         UA_NodeId *createdNodeId);
 #endif
 
+#ifndef _HAVE_UA_NODEITERATORCALLBACK_D
+#define _HAVE_UA_NODEITERATORCALLBACK_D
 typedef UA_StatusCode (*UA_NodeIteratorCallback)(UA_NodeId childId, UA_Boolean isInverse, UA_NodeId referenceTypeId);
+#endif
 
 /** Iterate over all nodes referenced by parentNodeId by calling the callback function for each child node
  * 

+ 53 - 0
src/client/ua_client.c

@@ -1194,3 +1194,56 @@ UA_StatusCode UA_Client_addObjectTypeNode(UA_Client *client, UA_NodeId reqId, UA
     UA_AddNodesResponse_deleteMembers(adRes);
     return retval;
 }
+
+UA_StatusCode 
+UA_Client_forEachChildNodeCall(UA_Client *client, UA_NodeId parentNodeId, UA_NodeIteratorCallback callback) {
+  UA_StatusCode retval = UA_STATUSCODE_GOOD;
+  
+  UA_BrowseRequest  brq;
+  UA_BrowseRequest_init(&brq);
+  UA_BrowseResponse brs;
+  UA_BrowseResponse_init(&brs);
+  brq.nodesToBrowseSize = 1;
+  brq.requestedMaxReferencesPerNode = 0;
+  brq.nodesToBrowse = UA_BrowseDescription_new();
+  brq.nodesToBrowse[0].browseDirection = UA_BROWSEDIRECTION_BOTH;
+  brq.nodesToBrowse[0].includeSubtypes = UA_TRUE;
+  UA_NodeId_copy(&parentNodeId, &brq.nodesToBrowse[0].nodeId);
+  brq.nodesToBrowse[0].resultMask =UA_BROWSERESULTMASK_ALL;
+  brs = UA_Client_browse(client, &brq);
+  
+  UA_BrowseRequest_deleteMembers(&brq);
+  if (brs.responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
+    UA_BrowseResponse_deleteMembers(&brq);
+    return brs.responseHeader.serviceResult;
+  }
+  if (brs.resultsSize < 1) {
+    UA_BrowseResponse_deleteMembers(&brq);
+    return UA_STATUSCODE_GOOD;
+  }
+  if (brs.results[0].statusCode != UA_STATUSCODE_GOOD) {
+    UA_BrowseResponse_deleteMembers(&brq);
+    return brs.results[0].statusCode;
+  }
+  
+  UA_Boolean isInverse;
+  UA_NodeId *childId = UA_NodeId_new();
+  UA_NodeId *refTypeId = UA_NodeId_new();
+  for (int i = 0; i < brs.results[0].referencesSize; i++) {
+    isInverse = UA_FALSE;
+    if (brs.results[0].references[i].isForward == UA_FALSE)
+      isInverse = UA_TRUE;
+    UA_NodeId_copy(&brs.results[0].references[i].nodeId.nodeId, childId);
+    UA_NodeId_copy(&brs.results[0].references[i].referenceTypeId, refTypeId);
+    //UA_NodeId childId, UA_Boolean isInverse, UA_NodeId referenceTypeId
+    callback(*childId, isInverse, *refTypeId);
+    
+    UA_NodeId_deleteMembers(childId);
+    UA_NodeId_deleteMembers(refTypeId);
+  }
+  UA_NodeId_delete(childId);
+  UA_NodeId_delete(refTypeId);
+  
+  UA_BrowseResponse_deleteMembers(&brs);
+  return retval;
+}

+ 29 - 29
tests/check_services_attributes.c

@@ -28,35 +28,35 @@ static void copyNames(UA_Node *node, char *name) {
 
 
 static UA_Server* makeTestSequence(void) {
-	UA_Server *server = UA_Server_new(UA_ServerConfig_standard);
-
-	/* VariableNode */
-	UA_Variant *myIntegerVariant = UA_Variant_new();
-	UA_Int32 myInteger = 42;
-	UA_Variant_setScalarCopy(myIntegerVariant, &myInteger,
-			&UA_TYPES[UA_TYPES_INT32]);
-	const UA_QualifiedName myIntegerName = UA_QUALIFIEDNAME(1, "the answer");
-	const UA_NodeId myIntegerNodeId = UA_NODEID_STRING(1, "the.answer");
-	UA_NodeId parentNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER);
-	UA_NodeId parentReferenceNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES);
-        UA_Server_addVariableNode(server, myIntegerNodeId, myIntegerName, UA_LOCALIZEDTEXT("en_US",""), UA_LOCALIZEDTEXT("en_US",""),
-                                  parentNodeId, parentReferenceNodeId, 0, 0, myIntegerVariant, NULL);
-
-	/* ObjectNode */
-        UA_Server_addObjectNode(server, UA_NODEID_NUMERIC(1, 50), UA_QUALIFIEDNAME(1, "Demo"), UA_LOCALIZEDTEXT("en_US","Demo"), 
-                                UA_LOCALIZEDTEXT("en_US","Demo"), UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), 
-                                UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), 0, 0, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE), NULL);
-
-	/* ReferenceTypeNode */
-	UA_ReferenceTypeNode *organizes = UA_ReferenceTypeNode_new();
-	copyNames((UA_Node*)organizes, "Organizes");
-	organizes->inverseName = UA_LOCALIZEDTEXT_ALLOC("", "OrganizedBy");
-	organizes->nodeId.identifier.numeric = UA_NS0ID_ORGANIZES;
-	organizes->isAbstract = UA_FALSE;
-	organizes->symmetric  = UA_FALSE;
-	UA_Server_addNode(server, (UA_Node*)organizes, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_HIERARCHICALREFERENCES), UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE));
-
-	/* ViewNode */
+    UA_Server *server = UA_Server_new(UA_ServerConfig_standard);
+
+    /* VariableNode */
+    UA_Variant *myIntegerVariant = UA_Variant_new();
+    UA_Int32 myInteger = 42;
+    UA_Variant_setScalarCopy(myIntegerVariant, &myInteger,
+                    &UA_TYPES[UA_TYPES_INT32]);
+    const UA_QualifiedName myIntegerName = UA_QUALIFIEDNAME(1, "the answer");
+    const UA_NodeId myIntegerNodeId = UA_NODEID_STRING(1, "the.answer");
+    UA_NodeId parentNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER);
+    UA_NodeId parentReferenceNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES);
+    UA_Server_addVariableNode(server, myIntegerNodeId, myIntegerName, UA_LOCALIZEDTEXT("en_US",""), UA_LOCALIZEDTEXT("en_US",""),
+                              parentNodeId, parentReferenceNodeId, 0, 0, myIntegerVariant, NULL);
+
+    /* ObjectNode */
+    UA_Server_addObjectNode(server, UA_NODEID_NUMERIC(1, 50), UA_QUALIFIEDNAME(1, "Demo"), UA_LOCALIZEDTEXT("en_US","Demo"), 
+                            UA_LOCALIZEDTEXT("en_US","Demo"), UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), 
+                            UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), 0, 0, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE), NULL);
+
+    /* ReferenceTypeNode */
+    UA_ReferenceTypeNode *organizes = UA_ReferenceTypeNode_new();
+    copyNames((UA_Node*)organizes, "Organizes");
+    organizes->inverseName = UA_LOCALIZEDTEXT_ALLOC("", "OrganizedBy");
+    organizes->nodeId.identifier.numeric = UA_NS0ID_ORGANIZES;
+    organizes->isAbstract = UA_FALSE;
+    organizes->symmetric  = UA_FALSE;
+    UA_Server_addNode(server, (UA_Node*)organizes, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_HIERARCHICALREFERENCES), UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE));
+
+    /* ViewNode */
     UA_ViewNode *viewtest = UA_ViewNode_new();
     copyNames((UA_Node*)viewtest, "Viewtest");
     viewtest->nodeId.identifier.numeric = UA_NS0ID_VIEWNODE;