瀏覽代碼

Tutorial on variable/attribute manipulation updated. Several minor problems fixed.

ichrispa 9 年之前
父節點
當前提交
d93de433a0

+ 31 - 0
doc/tutorial_noderelations.rst

@@ -0,0 +1,31 @@
+Examining and interacting with node relations
+=============================================
+
+In the past tutorials you learned to compile the stack in various configurations, create/delete nodes and manage variables. The core of OPC UA are it's data modelling capabilities, and you will invariably find yourself confronted to investigate these relations during runtime. This tutorial will show you how to interact with object and types hierarchies and how to create your own.
+
+
+
+
+Iterating over Child nodes
+--------------------------
+
+``` UA_(Server|Client)_forEachChildNodeCall();```
+
+Examining node copies
+---------------------
+
+``` UA_(Server|Client)_getNodeCopy()```
+
+``` UA_(Server|Client)_destroyNodeCopy()```
+
+Compile XML Namespaces
+----------------------
+
+Stasiks comfy CMake method.
+
+Manual script call.
+
+Creating object instances
+-------------------------
+
+``` UA_(Server|Client)_createInstanceOf()```

File diff suppressed because it is too large
+ 189 - 16
doc/tutorial_nodescontents.rst


+ 20 - 20
examples/client.c

@@ -19,8 +19,8 @@ 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) {  
+UA_StatusCode nodeIter(UA_NodeId childId, UA_Boolean isInverse, UA_NodeId referenceTypeId, void *handle);
+UA_StatusCode nodeIter(UA_NodeId childId, UA_Boolean isInverse, UA_NodeId referenceTypeId, void *handle) {  
   printf("References ns=%d;i=%d using i=%d ", childId.namespaceIndex, childId.identifier.numeric, referenceTypeId.identifier.numeric);
   if (isInverse == UA_TRUE) {
     printf(" (inverse)");
@@ -156,7 +156,7 @@ int main(int argc, char *argv[]) {
     UA_Int32 outputSize;
     UA_Variant *output;
     
-    retval = UA_Client_CallServerMethod(client, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
+    retval = UA_Client_callServerMethod(client, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
                                         UA_NODEID_NUMERIC(1, 62541), 1, &input, &outputSize, &output);
     if(retval == UA_STATUSCODE_GOOD) {
         printf("Method call was successfull, and %i returned values available.\n", outputSize);
@@ -246,23 +246,23 @@ int main(int argc, char *argv[]) {
   // retNodeId is needed for the next test
   UA_NodeId retNodeId = UA_NODEID_STRING(1, "the.answer");
 #endif
-    // Iterate over all nodes in 'Objects'
-    UA_Client_forEachChildNodeCall(client, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), nodeIter);
+  // Iterate over all nodes in 'Objects'
+  UA_Client_forEachChildNodeCall(client, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), nodeIter, NULL);
     
-    // Get a copy of the node 'TheNewVariableNode' and delete it
-    void *theCopy;
-    UA_Client_getNodeCopy(client, retNodeId, (void*) &theCopy);
-    UA_Client_deleteNodeCopy(client, &theCopy);
-    
-    // Delete a serverside node
-    UA_Client_deleteMethodNode(client, UA_NODEID_NUMERIC(1,62541));
-    
-    // Set a localized string version of "Objects"
-    UA_LocalizedText objectsLocale = UA_LOCALIZEDTEXT("de_DE", "Die Objekte");
-    UA_Client_setAttributeValue(client, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_ATTRIBUTEID_WRITEMASK, (void *) &objectsLocale);
-    
-    UA_Client_disconnect(client);
-    UA_Client_delete(client);
-    return UA_STATUSCODE_GOOD;
+  // Get a copy of the node 'TheNewVariableNode' and delete it
+  void *theCopy;
+  UA_Client_getNodeCopy(client, retNodeId, (void*) &theCopy);
+  UA_Client_deleteNodeCopy(client, &theCopy);
+  
+  // Delete a serverside node
+  UA_Client_deleteMethodNode(client, UA_NODEID_NUMERIC(1,62541));
+  
+  // Set a localized string version of "Objects"
+  UA_LocalizedText objectsLocale = UA_LOCALIZEDTEXT("de_DE", "Die Objekte");
+  UA_Client_setAttributeValue(client, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_ATTRIBUTEID_WRITEMASK, (void *) &objectsLocale);
+  
+  UA_Client_disconnect(client);
+  UA_Client_delete(client);
+  return UA_STATUSCODE_GOOD;
 }
 

+ 20 - 19
examples/server.c

@@ -116,17 +116,18 @@ FILE* ledFile = NULL;
 UA_Boolean ledStatus = 0;
 
 static UA_StatusCode readLedStatus(void *handle, UA_Boolean sourceTimeStamp, const UA_NumericRange *range, UA_DataValue *value) {
-    if(range)
-        return UA_STATUSCODE_BADINDEXRANGEINVALID;
+  if(range)
+    return UA_STATUSCODE_BADINDEXRANGEINVALID;
 
-    UA_StatusCode retval = UA_Variant_setScalarCopy(&value->value, &ledStatus, &UA_TYPES[UA_TYPES_BOOLEAN]);
-    if(retval != UA_STATUSCODE_GOOD)
-        return retval;
-	if(sourceTimeStamp) {
-		value->sourceTimestamp = UA_DateTime_now();
-		value->hasSourceTimestamp = UA_TRUE;
-	}
-	return UA_STATUSCODE_GOOD;
+  UA_StatusCode retval = UA_Variant_setScalarCopy(&value->value, &ledStatus, &UA_TYPES[UA_TYPES_BOOLEAN]);
+  if(retval != UA_STATUSCODE_GOOD)
+    return retval;
+  
+  if(sourceTimeStamp) {
+          value->sourceTimestamp = UA_DateTime_now();
+          value->hasSourceTimestamp = UA_TRUE;
+  }
+  return UA_STATUSCODE_GOOD;
 }
 
 static UA_StatusCode writeLedStatus(void *handle, const UA_Variant *data, const UA_NumericRange *range) {
@@ -191,8 +192,8 @@ static UA_ByteString loadCertificate(void) {
     return certificate;
 }
 
-UA_StatusCode nodeIter(UA_NodeId childId, UA_Boolean isInverse, UA_NodeId referenceTypeId);
-UA_StatusCode nodeIter(UA_NodeId childId, UA_Boolean isInverse, UA_NodeId referenceTypeId) {  
+UA_StatusCode nodeIter(UA_NodeId childId, UA_Boolean isInverse, UA_NodeId referenceTypeId, void *handle);
+UA_StatusCode nodeIter(UA_NodeId childId, UA_Boolean isInverse, UA_NodeId referenceTypeId, void *handle) {  
   printf("References ns=%d;i=%d using i=%d ", childId.namespaceIndex, childId.identifier.numeric, referenceTypeId.identifier.numeric);
   if (isInverse == UA_TRUE) {
     printf(" (inverse)");
@@ -214,13 +215,13 @@ int main(int argc, char** argv) {
   UA_ByteString certificate = loadCertificate();
   UA_Server_setServerCertificate(server, certificate);
   UA_ByteString_deleteMembers(&certificate);
-      UA_Server_addNetworkLayer(server, ServerNetworkLayerTCP_new(UA_ConnectionConfig_standard, 16664));
+  UA_Server_addNetworkLayer(server, ServerNetworkLayerTCP_new(UA_ConnectionConfig_standard, 16664));
 
-      // add node with the datetime data source
-      UA_DataSource dateDataSource = (UA_DataSource) {.handle = NULL, .read = readTimeData, .write = NULL};
-      const UA_QualifiedName dateName = UA_QUALIFIEDNAME(1, "current time");
-      UA_Server_addDataSourceVariableNode(server, dateDataSource, dateName, UA_NODEID_NULL,
-                                      UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), NULL);
+  // add node with the datetime data source
+  UA_DataSource dateDataSource = (UA_DataSource) {.handle = NULL, .read = readTimeData, .write = NULL};
+  const UA_QualifiedName dateName = UA_QUALIFIEDNAME(1, "current time");
+  UA_Server_addDataSourceVariableNode(server, dateDataSource, dateName, UA_NODEID_NULL,
+                                  UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), NULL);
 
 #ifndef _WIN32
   //cpu temperature monitoring for linux machines
@@ -353,7 +354,7 @@ int main(int argc, char** argv) {
    
   // Example for iterating over all nodes referenced by "Objects":
   printf("Nodes connected to 'Objects':\n=============================\n");
-  UA_Server_forEachChildNodeCall(server, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), nodeIter);
+  UA_Server_forEachChildNodeCall(server, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), nodeIter, NULL);
   
   // Some easy localization
   UA_LocalizedText objectsName = UA_LOCALIZEDTEXT("de_DE", "Objekte");

+ 3 - 3
include/ua_client.h

@@ -83,7 +83,7 @@ UA_CLIENT_DELETENODETYPEALIAS_DECL(View)
 
 #ifdef ENABLE_METHODCALLS
 UA_CallResponse UA_EXPORT UA_Client_call(UA_Client *client, UA_CallRequest *request);
-UA_StatusCode UA_EXPORT UA_Client_CallServerMethod(UA_Client *client, UA_NodeId objectNodeId, UA_NodeId methodNodeId,
+UA_StatusCode UA_EXPORT UA_Client_callServerMethod(UA_Client *client, UA_NodeId objectNodeId, UA_NodeId methodNodeId,
                                                    UA_Int32 inputSize, const UA_Variant *input,
                                                    UA_Int32 *outputSize, UA_Variant **output);
 #endif
@@ -122,11 +122,11 @@ UA_StatusCode UA_EXPORT UA_Client_unMonitorItemChanges(UA_Client *client, UA_UIn
 
 #ifndef _HAVE_UA_NODEITERATORCALLBACK_D
 #define _HAVE_UA_NODEITERATORCALLBACK_D
-typedef UA_StatusCode (*UA_NodeIteratorCallback)(UA_NodeId childId, UA_Boolean isInverse, UA_NodeId referenceTypeId);
+typedef UA_StatusCode (*UA_NodeIteratorCallback)(UA_NodeId childId, UA_Boolean isInverse, UA_NodeId referenceTypeId, void *handle);
 #endif
 
 UA_StatusCode UA_EXPORT
-UA_Client_forEachChildNodeCall(UA_Client *client, UA_NodeId parentNodeId, UA_NodeIteratorCallback callback);
+UA_Client_forEachChildNodeCall(UA_Client *client, UA_NodeId parentNodeId, UA_NodeIteratorCallback callback, void *handle);
 
 UA_StatusCode 
 UA_Client_copyBaseAttributes(UA_Client *client, UA_ReadResponse *readResponseSrc, void *dst);

+ 2 - 2
include/ua_server.h

@@ -289,7 +289,7 @@ UA_Server_addMethodNode(UA_Server *server, UA_NodeId nodeId, const UA_QualifiedN
 
 #ifndef _HAVE_UA_NODEITERATORCALLBACK_D
 #define _HAVE_UA_NODEITERATORCALLBACK_D
-typedef UA_StatusCode (*UA_NodeIteratorCallback)(UA_NodeId childId, UA_Boolean isInverse, UA_NodeId referenceTypeId);
+typedef UA_StatusCode (*UA_NodeIteratorCallback)(UA_NodeId childId, UA_Boolean isInverse, UA_NodeId referenceTypeId, void *handle);
 #endif
 
 /** Iterate over all nodes referenced by parentNodeId by calling the callback function for each child node
@@ -302,7 +302,7 @@ typedef UA_StatusCode (*UA_NodeIteratorCallback)(UA_NodeId childId, UA_Boolean i
  *
  * @return Upon success, UA_STATUSCODE_GOOD is returned. An error code otherwise.
  */
-UA_StatusCode UA_EXPORT UA_Server_forEachChildNodeCall(UA_Server *server, UA_NodeId parentNodeId, UA_NodeIteratorCallback callback);
+UA_StatusCode UA_EXPORT UA_Server_forEachChildNodeCall(UA_Server *server, UA_NodeId parentNodeId, UA_NodeIteratorCallback callback, void *handle);
 
 UA_StatusCode UA_EXPORT UA_Server_setAttributeValue(UA_Server *server, UA_NodeId nodeId, UA_AttributeId attributeId, void *value);
 

+ 4 - 6
src/client/ua_client.c

@@ -957,7 +957,7 @@ UA_CallResponse UA_Client_call(UA_Client *client, UA_CallRequest *request) {
     return response;
 }
 
-UA_StatusCode UA_Client_CallServerMethod(UA_Client *client, UA_NodeId objectNodeId, UA_NodeId methodNodeId,
+UA_StatusCode UA_Client_callServerMethod(UA_Client *client, UA_NodeId objectNodeId, UA_NodeId methodNodeId,
                                          UA_Int32 inputSize, const UA_Variant *input,
                                          UA_Int32 *outputSize, UA_Variant **output) {
     UA_CallRequest request;
@@ -988,9 +988,7 @@ UA_StatusCode UA_Client_CallServerMethod(UA_Client *client, UA_NodeId objectNode
         response.results[0].outputArguments = UA_NULL;
         response.results[0].outputArgumentsSize = -1;
     }
-    else {
-      retval |= response.responseHeader.serviceResult;
-    }
+    
     UA_CallResponse_deleteMembers(&response);
     return retval;
 }
@@ -1240,7 +1238,7 @@ UA_StatusCode UA_Client_addObjectTypeNode(UA_Client *client, UA_NodeId reqId, UA
 }
 
 UA_StatusCode 
-UA_Client_forEachChildNodeCall(UA_Client *client, UA_NodeId parentNodeId, UA_NodeIteratorCallback callback) {
+UA_Client_forEachChildNodeCall(UA_Client *client, UA_NodeId parentNodeId, UA_NodeIteratorCallback callback, void *handle) {
   UA_StatusCode retval = UA_STATUSCODE_GOOD;
   
   UA_BrowseRequest  brq;
@@ -1280,7 +1278,7 @@ UA_Client_forEachChildNodeCall(UA_Client *client, UA_NodeId parentNodeId, UA_Nod
     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);
+    callback(*childId, isInverse, *refTypeId, NULL);
     
     UA_NodeId_deleteMembers(childId);
     UA_NodeId_deleteMembers(refTypeId);

+ 2 - 2
src/server/ua_server_addressspace.c

@@ -129,7 +129,7 @@ UA_StatusCode UA_Server_deleteNodeCopy(UA_Server *server, void **nodeptr) {
 } 
 
 UA_StatusCode 
-UA_Server_forEachChildNodeCall(UA_Server *server, UA_NodeId parentNodeId, UA_NodeIteratorCallback callback) {
+UA_Server_forEachChildNodeCall(UA_Server *server, UA_NodeId parentNodeId, UA_NodeIteratorCallback callback, void *handle) {
   UA_StatusCode retval = UA_STATUSCODE_GOOD;
   const UA_Node *parent = UA_NodeStore_get(server->nodestore, &parentNodeId);
   if (!parent)
@@ -137,7 +137,7 @@ UA_Server_forEachChildNodeCall(UA_Server *server, UA_NodeId parentNodeId, UA_Nod
   
   for(int i=0; i<parent->referencesSize; i++) {
     UA_ReferenceNode *ref = &parent->references[i];
-    retval |= callback(ref->targetId.nodeId, ref->isInverse, ref->referenceTypeId);
+    retval |= callback(ref->targetId.nodeId, ref->isInverse, ref->referenceTypeId, handle);
   }
   
   UA_NodeStore_release(parent);

+ 2 - 2
src/server/ua_services_attribute.c

@@ -460,11 +460,11 @@ UA_StatusCode writeValue(UA_Server *server, UA_WriteValue *wvalue) {
           done = UA_TRUE;
           break;
         case UA_ATTRIBUTEID_DISPLAYNAME:
-          SETATTRIBUTE_IF_DATATYPE_IS(UINT32)
+          SETATTRIBUTE_IF_DATATYPE_IS(LOCALIZEDTEXT)
           done = UA_TRUE;
           break;
         case UA_ATTRIBUTEID_DESCRIPTION:
-          SETATTRIBUTE_IF_DATATYPE_IS(UINT32)
+          SETATTRIBUTE_IF_DATATYPE_IS(LOCALIZEDTEXT)
           done = UA_TRUE;
           break;
         case UA_ATTRIBUTEID_WRITEMASK: