Prechádzať zdrojové kódy

NodesetCompiler: Print an empty ExtensionObject for unknown datatypes

Julius Pfrommer 5 rokov pred
rodič
commit
1666968d9c

+ 19 - 21
tools/nodeset_compiler/backend_open62541_nodes.py

@@ -208,7 +208,8 @@ def generateCommonVariableCode(node, nodeset):
                     code.append("attr.value.arrayDimensionsSize = attr.arrayDimensionsSize;")
                     code.append("attr.value.arrayDimensions = attr.arrayDimensions;")
     elif node.value is not None:
-        raise RuntimeError("Cannot encode dataTypeNode: " + dataTypeNode.browseName.name + " for value of node " + node.browseName.name + " " + str(node.id))
+        code.append("/* Cannot encode the value */")
+        logger.warn("Cannot encode dataTypeNode: " + dataTypeNode.browseName.name + " for value of node " + node.browseName.name + " " + str(node.id))
 
     return [code, codeCleanup, codeGlobal]
 
@@ -279,10 +280,11 @@ def generateExtensionObjectSubtypeCode(node, parent, nodeset, global_var_code, i
 
     # Assign data to the struct contents
     # Track the encoding rule definition to detect arrays and/or ExtensionObjects
-    encFieldIdx = 0
-    for subv in node.value:
-        encField = node.encodingRule[encFieldIdx]
-        encFieldIdx = encFieldIdx + 1
+    values = node.value
+    if values == None:
+        values = []
+    for idx,subv in enumerate(values):
+        encField = node.encodingRule[idx]
         memberName = lowerFirstChar(encField[0])
 
         # Check if this is an array
@@ -298,22 +300,16 @@ def generateExtensionObjectSubtypeCode(node, parent, nodeset, global_var_code, i
             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({instanceName}, &{typeArrayString});".format(
-                                                                                instanceName=instanceNameSafe + "_" + memberName,
-                                                                                typeArrayString=encTypeArrayString))
-
-            subArrayIdx = 0
-            for val in subv:
-                code.append(generateNodeValueCode(instanceNameSafe + "_" + memberName + "[" + str(subArrayIdx) + "]" +" = ", val, instanceName,instanceName + "_gehtNed_member", global_var_code, asIndirect=False))
-                subArrayIdx = subArrayIdx + 1
+            code.append("UA_init({instanceName}, &{typeArrayString});".format(instanceName=instanceNameSafe + "_" + memberName,
+                                                                              typeArrayString=encTypeArrayString))
+
+            for subArrayIdx,val in enumerate(subv):
+                code.append(generateNodeValueCode(instanceNameSafe + "_" + memberName + "[" + str(subArrayIdx) + "]" +" = ",
+                                                  val, instanceName,instanceName + "_gehtNed_member", global_var_code, asIndirect=False))
             code.append(instanceName + accessor + memberName + " = " + instanceNameSafe+"_"+ memberName+";")
             continue
-        else:
-            logger.debug(
-            "Encoding of field " + memberName + " is " + str(subv.encodingRule) + "defined by " + str(encField))
-
-
 
+        logger.debug("Encoding of field " + memberName + " is " + str(subv.encodingRule) + "defined by " + str(encField))
         if subv.valueRank is None or subv.valueRank == 0:
             if not subv.isNone():
                 # Some values can be optional
@@ -322,7 +318,8 @@ def generateExtensionObjectSubtypeCode(node, parent, nodeset, global_var_code, i
                             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))
+            code.append(generateNodeValueCode(instanceName + accessor + memberName + "Size = ", subv,
+                                              instanceName,valueName, global_var_code, asIndirect=False))
 
     if not isArrayElement:
         code.append("UA_Variant_setScalar(&attr.value, " + instanceName + ", &" + typeArrayString + ");")
@@ -392,7 +389,7 @@ def generateValueCode(node, parentNode, nodeset, bootstrapping=True):
                     logger.debug("Building extObj array index " + str(idx))
                     instanceName = valueName + "[" + str(idx) + "]"
                     [code1, codeCleanup1] = generateExtensionObjectSubtypeCode(v, parent=parentNode, nodeset=nodeset,
-                                                                                global_var_code=codeGlobal, instanceName=instanceName,
+                                                                               global_var_code=codeGlobal, instanceName=instanceName,
                                                                                isArrayElement=True)
                     code = code + code1
                     codeCleanup = codeCleanup + codeCleanup1
@@ -417,7 +414,8 @@ def generateValueCode(node, parentNode, nodeset, bootstrapping=True):
         else:
             # The following strategy applies to all other types, in particular strings and numerics.
             if isinstance(node.value[0], ExtensionObject):
-                [code1, codeCleanup1] = generateExtensionObjectSubtypeCode(node.value[0], parent=parentNode, nodeset=nodeset, global_var_code=codeGlobal, isArrayElement=False)
+                [code1, codeCleanup1] = generateExtensionObjectSubtypeCode(node.value[0], parent=parentNode, nodeset=nodeset,
+                                                                           global_var_code=codeGlobal, isArrayElement=False)
                 code = code + code1
                 codeCleanup = codeCleanup + codeCleanup1
             instanceName = generateNodeValueInstanceName(node.value[0], parentNode, 0)

+ 36 - 32
tools/nodeset_compiler/datatypes.py

@@ -186,7 +186,7 @@ class Value(object):
                 if alias is not None:
                     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
+                        return ExtensionObject()
                     else:
                         t = self.getTypeByString(enc[0], enc)
                         t.alias = alias
@@ -237,20 +237,20 @@ class Value(object):
             #        OPCUA Namespace 0 nodeset.
             #        Consider moving this ExtensionObject specific parsing into the
             #        builtin type and only determining the multipart type at this stage.
+            extobj = ExtensionObject()
             if not xmlvalue.localName == "ExtensionObject":
                 logger.error(str(parent.id) + ": Expected XML tag <ExtensionObject> for multipart type, but found " + xmlvalue.localName + " instead.")
-                return None
+                return extobj
 
-            extobj = ExtensionObject()
             extobj.encodingRule = enc
             etype = xmlvalue.getElementsByTagName("TypeId")
             if len(etype) == 0:
                 logger.error(str(parent.id) + ": Did not find <TypeId> for ExtensionObject")
-                return None
+                return extobj
             etype = etype[0].getElementsByTagName("Identifier")
             if len(etype) == 0:
                 logger.error(str(parent.id) + ": Did not find <Identifier> for ExtensionObject")
-                return None
+                return extobj
 
             etype = NodeId(etype[0].firstChild.data.strip(' \t\n\r'))
             extobj.typeId = etype
@@ -258,35 +258,39 @@ class Value(object):
             ebody = xmlvalue.getElementsByTagName("Body")
             if len(ebody) == 0:
                 logger.error(str(parent.id) + ": Did not find <Body> for ExtensionObject")
-                return None
+                return extobj
             ebody = ebody[0]
 
-            # Body must contain an Object of type 'DataType' as defined in Variable
-            ebodypart = ebody.firstChild
-            if not ebodypart.nodeType == ebodypart.ELEMENT_NODE:
-                ebodypart = getNextElementNode(ebodypart)
-            if ebodypart is None:
-                logger.error(str(parent.id) + ": Expected ExtensionObject to hold a variable of type " + str(parentDataTypeNode.browseName) + " but found nothing.")
-                return None
-
-            if not ebodypart.localName == "OptionSet" and not ebodypart.localName == parentDataTypeNode.browseName.name:
-                logger.error(str(parent.id) + ": Expected ExtensionObject to hold a variable of type " + str(parentDataTypeNode.browseName) + " but found " +
-                             str(ebodypart.localName) + " instead.")
-                return None
-            extobj.alias = ebodypart.localName
-
-            ebodypart = ebodypart.firstChild
-            if not ebodypart.nodeType == ebodypart.ELEMENT_NODE:
-                ebodypart = getNextElementNode(ebodypart)
-            if ebodypart is None:
-                logger.error(str(parent.id) + ": Description of dataType " + str(parentDataTypeNode.browseName) + " in ExtensionObject is empty/invalid.")
-                return None
-
-            extobj.value = []
-            for e in enc:
-                extobj.value.append(extobj.__parseXMLSingleValue(ebodypart, parentDataTypeNode, parent,
-                                                                 alias=None, encodingPart=e))
-                ebodypart = getNextElementNode(ebodypart)
+            try:
+                # Body must contain an Object of type 'DataType' as defined in Variable
+                ebodypart = ebody.firstChild
+                if not ebodypart.nodeType == ebodypart.ELEMENT_NODE:
+                    ebodypart = getNextElementNode(ebodypart)
+                if ebodypart is None:
+                    logger.error(str(parent.id) + ": Expected ExtensionObject to hold a variable of type " + str(parentDataTypeNode.browseName) + " but found nothing.")
+                    return extobj
+
+                if not ebodypart.localName == "OptionSet" and not ebodypart.localName == parentDataTypeNode.browseName.name:
+                    logger.error(str(parent.id) + ": Expected ExtensionObject to hold a variable of type " + str(parentDataTypeNode.browseName) + " but found " +
+                                 str(ebodypart.localName) + " instead.")
+                    return extobj
+                extobj.alias = ebodypart.localName
+
+                ebodypart = ebodypart.firstChild
+                if not ebodypart.nodeType == ebodypart.ELEMENT_NODE:
+                    ebodypart = getNextElementNode(ebodypart)
+                if ebodypart is None:
+                    logger.error(str(parent.id) + ": Description of dataType " + str(parentDataTypeNode.browseName) + " in ExtensionObject is empty/invalid.")
+                    return extobj
+
+                extobj.value = []
+                for e in enc:
+                    extobj.value.append(extobj.__parseXMLSingleValue(ebodypart, parentDataTypeNode, parent,
+                                                                     alias=None, encodingPart=e))
+                    ebodypart = getNextElementNode(ebodypart)
+            except Exception:
+                logger.error(str(parent.id) + ": Could not parse <Body> for ExtensionObject")
+
             return extobj
 
     def __str__(self):