Browse Source

NodesetCompiler: Allow optional Description for Argument Type

Also fixes #2721
Stefan Profanter 5 years ago
parent
commit
b1f246d498

+ 1 - 1
tools/nodeset_compiler/backend_open62541_datatypes.py

@@ -66,7 +66,7 @@ def generateByteStringCode(value, valueName, global_var_code, isPointer):
 
 def generateLocalizedTextCode(value, alloc=False):
     vt = makeCLiteral(value.text)
-    return u"UA_LOCALIZEDTEXT{}(\"{}\", {})".format("_ALLOC" if alloc else "", value.locale,
+    return u"UA_LOCALIZEDTEXT{}(\"{}\", {})".format("_ALLOC" if alloc else "", '' if value.locale is None else value.locale,
                                                    splitStringLiterals(vt))
 
 def generateQualifiedNameCode(value, alloc=False,):

+ 17 - 13
tools/nodeset_compiler/backend_open62541_nodes.py

@@ -203,9 +203,6 @@ def generateCommonVariableCode(node, nodeset):
                 if hasZero == False and len(node.value.value) == numElements:
                     code.append("attr.value.arrayDimensionsSize = attr.arrayDimensionsSize;")
                     code.append("attr.value.arrayDimensions = attr.arrayDimensions;")
-                    logger.warning("printing arrayDimensions")
-                else:
-                    logger.error("Dimension with size 0 or value count mismatch detected, ArrayDimensions won't be copied to the Value attribute.")
     elif node.value is not None:
         raise RuntimeError("Cannot encode dataTypeNode: " + dataTypeNode.browseName.name + " for value of node " + node.browseName.name + " " + str(node.id))
 
@@ -283,36 +280,42 @@ def generateExtensionObjectSubtypeCode(node, parent, nodeset, global_var_code, i
         encField = node.encodingRule[encFieldIdx]
         encFieldIdx = encFieldIdx + 1
         memberName = lowerFirstChar(encField[0])
+
+        # Check if this is an array
+        accessor = "." if isArrayElement else "->"
+
         if isinstance(subv, list):
             if len(subv) == 0:
                 continue
             logger.info("ExtensionObject contains array")
             memberName = lowerFirstChar(encField[0])
             encTypeString = "UA_" + subv[0].__class__.__name__
-            code.append("UA_STACKARRAY(" + encTypeString + ", " + instanceName + "_" + memberName+", {0});".format(len(subv)))
+            instanceNameSafe = makeCIdentifier(instanceName)
+            code.append("UA_STACKARRAY(" + encTypeString + ", " + instanceNameSafe + "_" + memberName+", {0});".format(len(subv)))
             encTypeArr = nodeset.getDataTypeNode(subv[0].__class__.__name__).typesArray
             encTypeArrayString = encTypeArr + "[" + encTypeArr + "_" + subv[0].__class__.__name__.upper() + "]"
             code.append("UA_init({ref}{instanceName}, &{typeArrayString});".format(ref="&" if isArrayElement else "",
-                                                                                instanceName=instanceName + "_" + memberName,
+                                                                                instanceName=instanceNameSafe + "_" + memberName,
                                                                                 typeArrayString=encTypeArrayString))
 
             subArrayIdx = 0
             for val in subv:
-                code.append(generateNodeValueCode(instanceName + "_" + memberName + "[" + str(subArrayIdx) + "]" +" = ", val, instanceName,instanceName + "_gehtNed_member", global_var_code, asIndirect=False))
+                code.append(generateNodeValueCode(instanceNameSafe + "_" + memberName + "[" + str(subArrayIdx) + "]" +" = ", val, instanceName,instanceName + "_gehtNed_member", global_var_code, asIndirect=False))
                 subArrayIdx = subArrayIdx + 1
-            code.append(instanceName + "->" + memberName + " = " + instanceName+"_"+ memberName+";")
+            code.append(instanceName + accessor + memberName + " = " + instanceNameSafe+"_"+ memberName+";")
             continue
         else:
             logger.debug(
             "Encoding of field " + memberName + " is " + str(subv.encodingRule) + "defined by " + str(encField))
-        # Check if this is an array
-        accessor = "." if isArrayElement else "->"
+
 
 
         if subv.valueRank is None or subv.valueRank == 0:
-            valueName = instanceName + accessor + memberName
-            code.append(generateNodeValueCode(valueName + " = " ,
-                        subv, instanceName,valueName, global_var_code, asIndirect=False))
+            if not subv.isNone():
+                # Some values can be optional
+                valueName = instanceName + accessor + memberName
+                code.append(generateNodeValueCode(valueName + " = " ,
+                            subv, instanceName,valueName, global_var_code, asIndirect=False))
         else:
             memberName = lowerFirstChar(encField[0])
             code.append(generateNodeValueCode(instanceName + accessor + memberName + "Size = ", subv, instanceName,valueName, global_var_code, asIndirect=False))
@@ -414,10 +417,11 @@ def generateValueCode(node, parentNode, nodeset, bootstrapping=True):
                 code = code + code1
                 codeCleanup = codeCleanup + codeCleanup1
             instanceName = generateNodeValueInstanceName(node.value[0], parentNode, 0)
-            if not(isinstance(node.value[0], ExtensionObject)):
+            if not node.value[0].isNone() and not(isinstance(node.value[0], ExtensionObject)):
                 code.append("UA_" + node.value[0].__class__.__name__ + " *" + valueName + " =  UA_" + node.value[
                     0].__class__.__name__ + "_new();")
                 code.append("if (!" + valueName + ") return UA_STATUSCODE_BADOUTOFMEMORY;")
+                code.append("UA_" + node.value[0].__class__.__name__ + "_init(" + valueName + ");")
                 code.append(generateNodeValueCode("*" + valueName + " = " , node.value[0], instanceName, valueName, codeGlobal, asIndirect=True))
                 code.append(
                         "UA_Variant_setScalar(&attr.value, " + valueName + ", " +

+ 21 - 9
tools/nodeset_compiler/datatypes.py

@@ -189,7 +189,7 @@ class Value(object):
             if isinstance(enc[0], string_types):
                 # 0: 'BuiltinType'
                 if alias is not None:
-                    if not xmlvalue.localName == alias and not xmlvalue.localName == enc[0]:
+                    if xmlvalue is not None and not xmlvalue.localName == alias and not xmlvalue.localName == enc[0]:
                         logger.error(str(parent.id) + ": Expected XML element with tag " + alias + " but found " + xmlvalue.localName + " instead")
                         return None
                     else:
@@ -207,7 +207,8 @@ class Value(object):
                                 values.append(val)
                             return values
                         else:
-                            t.parseXML(xmlvalue, namespaceMapping=namespaceMapping)
+                            if xmlvalue is not None:
+                                t.parseXML(xmlvalue, namespaceMapping=namespaceMapping)
                             return t
                 else:
                     if not valueIsInternalType(xmlvalue.localName):
@@ -290,16 +291,16 @@ class Value(object):
 
             extobj.value = []
             for e in enc:
-                if not ebodypart is None:
-                    extobj.value.append(extobj.__parseXMLSingleValue(ebodypart, parentDataTypeNode, parent, namespaceMapping=namespaceMapping, alias=None, encodingPart=e))
-                else:
-                    logger.error(str(parent.id) + ": Expected encoding " + str(e) + " but found none in body.")
+                extobj.value.append(extobj.__parseXMLSingleValue(ebodypart, parentDataTypeNode, parent, namespaceMapping=namespaceMapping, alias=None, encodingPart=e))
                 ebodypart = getNextElementNode(ebodypart)
             return extobj
 
     def __str__(self):
         return self.__class__.__name__ + "(" + str(self.value) + ")"
 
+    def isNone(self):
+        return self.value is None
+
     def __repr__(self):
         return self.__str__()
 
@@ -478,8 +479,8 @@ class ExtensionObject(Value):
 class LocalizedText(Value):
     def __init__(self, xmlvalue=None):
         Value.__init__(self)
-        self.locale = ''
-        self.text = ''
+        self.locale = None
+        self.text = None
         if xmlvalue:
             self.parseXML(xmlvalue)
 
@@ -500,11 +501,16 @@ class LocalizedText(Value):
             self.text = tmp[0].firstChild.data.strip(' \t\n\r')
 
     def __str__(self):
+        if self.locale is None and self.text is None:
+            return "None"
         if self.locale is not None and len(self.locale) > 0:
             return "(" + self.locale + ":" + self.text + ")"
         else:
             return self.text
 
+    def isNone(self):
+        return self.text is None
+
 class NodeId(Value):
     def __init__(self, idstring=None):
         Value.__init__(self)
@@ -586,6 +592,9 @@ class NodeId(Value):
         elif self.s != None:
             return s + "s=" + str(self.s)
 
+    def isNone(self):
+        return self.i is None and self.b is None and self.s is None and self.g is None
+
     def __eq__(self, nodeId2):
         return (str(self) == str(nodeId2))
 
@@ -645,7 +654,7 @@ class QualifiedName(Value):
     def __init__(self, xmlelement=None):
         Value.__init__(self)
         self.ns = 0
-        self.name = ''
+        self.name = None
         if xmlelement:
             self.parseXML(xmlelement)
 
@@ -678,6 +687,9 @@ class QualifiedName(Value):
     def __str__(self):
         return "ns=" + str(self.ns) + ";" + str(self.name)
 
+    def isNone(self):
+        return self.name is None
+
 class StatusCode(UInt32):
     def __init__(self, xmlelement=None):
         UInt32.__init__(self, xmlelement)