ソースを参照

Reinstated userspace UA_Server_methodNode_attachCallback (for the 3rd time now?) and put it into the example server;
Fixed minor error in nodestore concurrent: Was forcing browsename ns==nodeId.ns for variables, which breakes method calls.

ichrispa 9 年 前
コミット
882b7e5a6c
共有4 個のファイルを変更した74 個の追加4 個の削除を含む
  1. 23 0
      examples/server_method.c
  2. 4 0
      include/ua_server.h
  3. 11 4
      src/server/ua_nodestore_concurrent.c
  4. 36 0
      src/server/ua_services_nodemanagement.c

+ 23 - 0
examples/server_method.c

@@ -34,6 +34,23 @@ helloWorldMethod(void *handle, const UA_NodeId objectId, size_t inputSize, const
         return UA_STATUSCODE_GOOD;
 } 
 
+static UA_StatusCode
+fooBarMethod(void *handle, const UA_NodeId objectId, size_t inputSize, const UA_Variant *input,
+                 size_t outputSize, UA_Variant *output) {
+	// Exactly the same as helloWorld, but returns foobar
+        UA_String *inputStr = (UA_String*)input->data;
+        UA_String tmp = UA_STRING_ALLOC("FooBar! ");
+        if(inputStr->length > 0) {
+            tmp.data = realloc(tmp.data, tmp.length + inputStr->length);
+            memcpy(&tmp.data[tmp.length], inputStr->data, inputStr->length);
+            tmp.length += inputStr->length;
+        }
+        UA_Variant_setScalarCopy(output, &tmp, &UA_TYPES[UA_TYPES_STRING]);
+        UA_String_deleteMembers(&tmp);
+        UA_LOG_INFO(logger, UA_LOGCATEGORY_SERVER, "Hello World was called");
+        return UA_STATUSCODE_GOOD;
+} 
+
 static UA_StatusCode
 IncInt32ArrayValuesMethod(void *handle, const UA_NodeId objectId, size_t inputSize,
                           const UA_Variant *input, size_t outputSize, UA_Variant *output) {
@@ -134,6 +151,12 @@ int main(int argc, char** argv) {
                             1, &inputArguments, 1, &outputArguments, NULL);
     //END OF EXAMPLE 2
 
+    /* If out methodnode is part of an instantiated object, we never had
+       the opportunity to define the callback... we could do that now
+    */
+    UA_Server_methodNode_attachCallback(server, UA_NODEID_NUMERIC(1,62541), &fooBarMethod, NULL);
+    
+    //END OF EXAMPLE 3
     /* start server */
     UA_StatusCode retval = UA_Server_run(server, &running);
 

+ 4 - 0
include/ua_server.h

@@ -356,6 +356,10 @@ typedef UA_StatusCode (*UA_MethodCallback)(void *methodHandle, const UA_NodeId o
                                            size_t outputSize, UA_Variant *output);
 
 #ifdef UA_ENABLE_METHODCALLS
+UA_StatusCode UA_EXPORT
+UA_Server_methodNode_attachCallback(UA_Server *server, const UA_NodeId methodNodeId,
+				    UA_MethodCallback method, void *handle);
+
 UA_StatusCode UA_EXPORT
 UA_Server_addMethodNode(UA_Server *server, const UA_NodeId requestedNewNodeId,
                         const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId,

+ 11 - 4
src/server/ua_nodestore_concurrent.c

@@ -119,10 +119,17 @@ UA_StatusCode UA_NodeStore_insert(UA_NodeStore *ns, UA_Node *node) {
         node->nodeId.identifierType = UA_NODEIDTYPE_NUMERIC;
         if(node->nodeId.namespaceIndex == 0) // original request for ns=0 should yield ns=1
             node->nodeId.namespaceIndex = 1;
-        /* set namespaceIndex in browseName in case id is generated */
-        if(node->nodeClass == UA_NODECLASS_VARIABLE)
-        	((UA_VariableNode*)node)->browseName.namespaceIndex = node->nodeId.namespaceIndex;
-
+        /* set namespaceIndex in browseName in case id is generated, 
+	   --> unless these are method arguments, in which case never ever set anything other than 0!
+	*/
+        if(node->nodeClass == UA_NODECLASS_VARIABLE) {
+	    UA_String inArgName = UA_STRING("InputArguments");
+	    UA_String outArgName = UA_STRING("OutputArguments");
+	    if (UA_String_equal(&inArgName, &node->browseName.name) != UA_TRUE &&
+		UA_String_equal(&outArgName, &node->browseName.name) != UA_TRUE)
+		((UA_VariableNode*)node)->browseName.namespaceIndex = node->nodeId.namespaceIndex;
+	}
+	
         unsigned long identifier;
         long before, after;
         cds_lfht_count_nodes(ht, &before, &identifier, &after); // current amount of nodes stored

+ 36 - 0
src/server/ua_services_nodemanagement.c

@@ -734,6 +734,42 @@ UA_Server_addMethodNode(UA_Server *server, const UA_NodeId requestedNewNodeId,
         UA_AddNodesResult_deleteMembers(&result);
     return result.statusCode;
 }
+
+static UA_StatusCode __UA_Server_editMethodCallback(UA_Server *server, UA_Session* session, UA_Node* node, const void* handle) {
+  const struct {
+    UA_MethodCallback callback;
+    void *handle;
+  } *newCallback = handle;
+  
+  if (node == NULL)
+    return UA_STATUSCODE_BADNODEIDINVALID;
+  if (node->nodeClass != UA_NODECLASS_METHOD)
+    return UA_STATUSCODE_BADNODECLASSINVALID;
+  if (newCallback == NULL)
+    return UA_STATUSCODE_BADNODEATTRIBUTESINVALID;
+  
+  UA_MethodNode *mnode = (UA_MethodNode *) node;
+  mnode->attachedMethod = newCallback->callback;
+  mnode->methodHandle   = newCallback->handle;
+  return 0;
+}
+
+UA_StatusCode UA_EXPORT
+UA_Server_methodNode_attachCallback(UA_Server *server, const UA_NodeId methodNodeId,
+				    UA_MethodCallback method, void *handle) {
+  struct {
+    UA_MethodCallback callback;
+    void *handle;
+  } newCallback;  
+  newCallback.callback = method;
+  newCallback.handle   = handle;
+  UA_RCU_LOCK();
+  UA_StatusCode retval = UA_Server_editNode(server, &adminSession, &methodNodeId,
+                            __UA_Server_editMethodCallback, &newCallback);
+  UA_RCU_UNLOCK();
+  return retval;
+}
+
 #endif
 
 /******************/