Pārlūkot izejas kodu

Fixed: Can instantiate NS0 DataTypes /w DataType definitions (closes #805). Adapted API to allow type passing in variableTypes. Adapted namespace compiler to new value encoding scheme (closes #806).

ichrispa 8 gadi atpakaļ
vecāks
revīzija
36f430eacc

+ 2 - 1
include/ua_server.h

@@ -719,12 +719,13 @@ UA_Server_addVariableTypeNode(UA_Server *server,
                               const UA_NodeId parentNodeId,
                               const UA_NodeId referenceTypeId,
                               const UA_QualifiedName browseName,
+                              const UA_NodeId typeDefinition,
                               const UA_VariableTypeAttributes attr,
                               UA_InstantiationCallback *instantiationCallback,
                               UA_NodeId *outNewNodeId) {
     return __UA_Server_addNode(server, UA_NODECLASS_VARIABLETYPE,
                                requestedNewNodeId, parentNodeId, referenceTypeId,
-                               browseName, UA_NODEID_NULL,
+                               browseName, typeDefinition,
                                (const UA_NodeAttributes*)&attr,
                                &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],
                                instantiationCallback, outNewNodeId);

+ 2 - 1
src/server/ua_server.c

@@ -866,7 +866,8 @@ UA_Server * UA_Server_new(const UA_ServerConfig config) {
     /*********************/
     /* The Server Object */
     /*********************/
-
+    
+    /* Create our own server object */ 
     UA_ObjectNode *servernode = UA_NodeStore_newObjectNode();
     copyNames((UA_Node*)servernode, "Server");
     servernode->nodeId.identifier.numeric = UA_NS0ID_SERVER;

+ 27 - 13
src/server/ua_services_nodemanagement.c

@@ -482,33 +482,47 @@ static UA_StatusCode
 copyCommonVariableAttributes(UA_Server *server, UA_VariableNode *node,
                              const UA_AddNodesItem *item,
                              const UA_VariableAttributes *attr) {
-    const UA_NodeId basevartype = UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE);
+    const UA_NodeId basevartype = UA_NODEID_NUMERIC(0, UA_NS0ID_BASEVARIABLETYPE);
+    const UA_NodeId basedatavartype = UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE);
     const UA_NodeId *typeDef = &item->typeDefinition.nodeId;
     if(UA_NodeId_isNull(typeDef))
         typeDef = &basevartype;
-
+    
+    
+    /* Make sure we can instantiate the basetypes themselves */
+    UA_StatusCode retval = UA_STATUSCODE_GOOD;
+    if(UA_NodeId_equal(&node->nodeId, &basevartype) == UA_TRUE || 
+       UA_NodeId_equal(&node->nodeId, &basedatavartype) == UA_TRUE
+    )
+      return retval;
+    
     const UA_VariableTypeNode *vt =
         (const UA_VariableTypeNode*)UA_NodeStore_get(server->nodestore, typeDef);
-    if(!vt || vt->nodeClass != UA_NODECLASS_VARIABLETYPE)
+    if(!vt || (vt->nodeClass != UA_NODECLASS_VARIABLETYPE && vt->nodeClass != UA_NODECLASS_DATATYPE))
         return UA_STATUSCODE_BADTYPEDEFINITIONINVALID;
     
     /* Set the constraints */
-    UA_StatusCode retval;
     if(!UA_NodeId_isNull(&attr->dataType))
         retval  = UA_VariableNode_setDataType(server, node, vt, &attr->dataType);
     else /* workaround common error where the datatype is left as NA_NODEID_NULL */
+      /* Note that most NS0 VarTypeNodes are DataTypes, not VariableTypes! */
+      if (vt->nodeClass == UA_NODECLASS_DATATYPE) 
+        UA_NodeId_copy(&vt->nodeId, &node->dataType);
+      else
         retval = UA_VariableNode_setDataType(server, node, vt, &vt->dataType);
         
     node->valueRank = -2; /* allow all dimensions first */
-    retval |= UA_VariableNode_setArrayDimensions(server, node, vt,
-                                                 attr->arrayDimensionsSize,
-                                                 attr->arrayDimensions);
-
-    if(attr->valueRank != 0 || !UA_Variant_isScalar(&attr->value))
-        retval |= UA_VariableNode_setValueRank(server, node, vt, attr->valueRank);
-    else /* workaround common error where the valuerank is left as 0 */
-        retval |= UA_VariableNode_setValueRank(server, node, vt, vt->valueRank);
-
+    if (vt->nodeClass != UA_NODECLASS_DATATYPE) {
+      retval |= UA_VariableNode_setArrayDimensions(server, node, vt,
+                                                  attr->arrayDimensionsSize,
+                                                  attr->arrayDimensions);
+
+      if(attr->valueRank != 0 || !UA_Variant_isScalar(&attr->value))
+          retval |= UA_VariableNode_setValueRank(server, node, vt, attr->valueRank);
+      else /* workaround common error where the valuerank is left as 0 */
+          retval |= UA_VariableNode_setValueRank(server, node, vt, vt->valueRank);
+    }
+    
     /* Set the value */
     UA_DataValue value;
     UA_DataValue_init(&value);

+ 11 - 3
tools/pyUANamespace/open62541_MacroHelper.py

@@ -213,8 +213,16 @@ class open62541_MacroHelper():
         code.append("attr.userExecutable = true;")
 
     code.append("UA_NodeId nodeId = " + str(self.getCreateNodeIDMacro(node)) + ";")
-    if nodetype in ["Object", "Variable"]:
-      code.append("UA_NodeId typeDefinition = UA_NODEID_NULL;") #due to the current API we cannot set types here since the API will generate nodes with random IDs
+    if nodetype in ["Object", "Variable", "VariableType"]:
+      typeDefinition = None
+      for r in node.getReferences():
+        if r.isForward() and r.referenceType().id().ns == 0 and r.referenceType().id().i == 40:
+          typeDefinition = r.target()
+      if typeDefinition == None:
+        # FIXME: We might want to resort to BaseXYTTypes here?
+        code.append("UA_NodeId typeDefinition = UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATATYPE);")
+      else:
+        code.append("UA_NodeId typeDefinition = " + str(self.getCreateNodeIDMacro(typeDefinition)) + ";")
     code.append("UA_NodeId parentNodeId = " + str(self.getCreateNodeIDMacro(parentNode)) + ";")
     code.append("UA_NodeId parentReferenceNodeId = " + str(self.getCreateNodeIDMacro(parentReference.referenceType())) + ";")
     extrNs = node.browseName().split(":")
@@ -227,7 +235,7 @@ class open62541_MacroHelper():
     # Djikstra (check that arguments have not been printed). (@ichrispa)
     code.append("UA_Server_add%sNode(server, nodeId, parentNodeId, parentReferenceNodeId, nodeName" % nodetype)
 
-    if nodetype in ["Object", "Variable"]:
+    if nodetype in ["Object", "Variable", "VariableType"]:
       code.append("       , typeDefinition")
     if nodetype != "Method":
       code.append("       , attr, NULL, NULL);")

+ 4 - 4
tools/pyUANamespace/ua_node_types.py

@@ -1105,8 +1105,8 @@ class opcua_node_variable_t(opcua_node_t):
     code.append(self.getCodePrintableID() + "->accessLevel = (UA_Int32) " + str(self.accessLevel()) + ";")
     code.append(self.getCodePrintableID() + "->valueRank = (UA_Int32) " + str(self.valueRank()) + ";")
     # The variant is guaranteed to exist by SubtypeEarly()
-    code.append(self.getCodePrintableID() + "->value.variant.value = *" + self.getCodePrintableID() + "_variant;")
-    code.append(self.getCodePrintableID() + "->valueSource = UA_VALUESOURCE_VARIANT;")
+    code.append("UA_Variant_copy(" + self.getCodePrintableID() + "_variant, &" + self.getCodePrintableID() + "->value.data.value.value );")
+    code.append(self.getCodePrintableID() + "->valueSource = UA_VALUESOURCE_DATA;")
     return code
 
 class opcua_node_method_t(opcua_node_t):
@@ -1360,8 +1360,8 @@ class opcua_node_variableType_t(opcua_node_t):
       code.append(self.getCodePrintableID() + "->isAbstract = false;")
 
     # The variant is guaranteed to exist by SubtypeEarly()
-    code.append(self.getCodePrintableID() + "->value.variant.value = *" + self.getCodePrintableID() + "_variant;")
-    code.append(self.getCodePrintableID() + "->valueSource = UA_VALUESOURCE_VARIANT;")
+    code.append("UA_Variant_copy(" + self.getCodePrintableID() + "_variant, &" + self.getCodePrintableID() + "->value.data.value.value );")
+    code.append(self.getCodePrintableID() + "->valueSource = UA_VALUESOURCE_DATA;")
     return code
 
 class opcua_node_dataType_t(opcua_node_t):