Browse Source

NodesetCompiler: enhancement for extension objects, array initialization

changes to testnodeset.xml
	geändert:       ../examples/nodeset/testnodeset.xml

NodesetCompiler: generate code for array within ExtensionObject

first prototype

generate nested array code

prototype nested array

added array1size

fix nodeset.xml

nodes

get the right type array

fixed datatypes.py

cleanup

cleanup debug comments

remove whitespace

remove trailing whitespaces
matkonnerth 5 years ago
parent
commit
6afa8c0fdf

+ 1 - 0
examples/nodeset/testnodeset.csv

@@ -16,3 +16,4 @@ BaseDataTypes_String1_scalar,16001,Variable
 BaseDataTypes_ByteString_Scalar,16002,Variable
 PointWithArray,3003,DataType
 NestedPoint,10008,DataType
+PointWithPointArray,3004,DataType

+ 27 - 22
examples/nodeset/testnodeset.xml

@@ -496,17 +496,36 @@
             <Field DataType="Double" Name="x"/>
             <Field DataType="Double" Name="y"/>
             <Field DataType="Double" Name="z"/>
-            <Field DataType="UInt32" Name="array1Size"/>
+            <Field DataType="Int32" Name="array1Size"/>
             <Field DataType="Double" ValueRank="1" Name="array1"/>
         </Definition>
     </UADataType>
+    <UADataType NodeId="ns=1;i=3004" BrowseName="1:PointWithPointArray">
+        <DisplayName>PointWithPointArray</DisplayName>
+        <References>
+            <Reference ReferenceType="HasSubtype" IsForward="false">i=22</Reference>
+        </References>
+        <Definition Name="1:PointWithPointArray">
+            <Field DataType="Double" Name="x"/>
+            <Field DataType="Double" Name="y"/>
+            <Field DataType="Double" Name="z"/>
+            <Field DataType="Int32" Name="array1Size"/>
+            <Field DataType="Double" ValueRank="1" Name="array1"/>
+        </Definition>
+    </UADataType>
+    <UAVariable DataType="ns=1;i=3004" NodeId="ns=1;i=6010" BrowseName="1:PointWithPointArray_scalar_noInit" UserAccessLevel="3" AccessLevel="3">
+        <DisplayName>PointWithArray_scalar_noInit</DisplayName>
+        <References>
+            <Reference ReferenceType="HasTypeDefinition">i=63</Reference>
+            <Reference ReferenceType="Organizes" IsForward="false">ns=1;i=5001</Reference>
+        </References>        
+    </UAVariable>
     <UAVariable DataType="ns=1;i=3003" NodeId="ns=1;i=6008" BrowseName="1:PointWithArray_scalar_noInit" UserAccessLevel="3" AccessLevel="3">
         <DisplayName>PointWithArray_scalar_noInit</DisplayName>
         <References>
             <Reference ReferenceType="HasTypeDefinition">i=63</Reference>
             <Reference ReferenceType="Organizes" IsForward="false">ns=1;i=5001</Reference>
         </References>
-        <!-->
         <Value>
             <uax:ExtensionObject>
                 <uax:TypeId>
@@ -517,12 +536,15 @@
                         <x>1.1</x>
                         <y>2.2</y>
                         <z>3.3</z>
-                        <array1Size>1</array1Size>
-                        <array1><Double>1.1</Double></array1>
+                        <array1Size>2</array1Size>
+                        <array1>                        
+                            <Double>11.1</Double>
+                            <Double>12.1</Double>
+                        </array1>
                     </PointWithArray>
                 </uax:Body>
             </uax:ExtensionObject>
-        </Value>-->
+        </Value>
     </UAVariable>
     <UAVariable DataType="ns=1;i=10008" NodeId="ns=1;i=6009" BrowseName="1:NestedPoint_scalar_noInit" UserAccessLevel="3" AccessLevel="3">
         <DisplayName>NestedPoint_scalar_noInit</DisplayName>
@@ -530,22 +552,5 @@
             <Reference ReferenceType="HasTypeDefinition">i=63</Reference>
             <Reference ReferenceType="Organizes" IsForward="false">ns=1;i=5001</Reference>
         </References>
-        <!-->
-        <Value>
-            <uax:ExtensionObject>
-                <uax:TypeId>
-                    <uax:Identifier>ns=1;i=3003</uax:Identifier>
-                </uax:TypeId>
-                <uax:Body>
-                    <PointWithArray xmlns="http://yourorganisation.org/exported2/Types.xsd">
-                        <x>1.1</x>
-                        <y>2.2</y>
-                        <z>3.3</z>
-                        <array1Size>1</array1Size>
-                        <array1><Double>1.1</Double></array1>
-                    </PointWithArray>
-                </uax:Body>
-            </uax:ExtensionObject>
-        </Value>-->
     </UAVariable>
 </UANodeSet>

+ 10 - 2
examples/nodeset/testtypes.bsd

@@ -53,8 +53,16 @@
     <opc:Field Name="x" TypeName="opc:Double" />
     <opc:Field Name="y" TypeName="opc:Double" />
     <opc:Field Name="z" TypeName="opc:Double" />
-    <opc:Field Name="array1Size" TypeName="opc:UInt32" />
-    <opc:Field Name="array1" TypeName="opc:Double" LengthField="array1Size" />
+    <opc:Field Name="NoOfArrayDimensions" TypeName="opc:Int32" />
+    <opc:Field Name="array1" TypeName="opc:Double" LengthField="NoOfArrayDimensions" />
+  </opc:StructuredType>
+
+  <opc:StructuredType Name="PointWithPointArray" BaseType="ua:ExtensionObject">
+    <opc:Field Name="x" TypeName="opc:Double" />
+    <opc:Field Name="y" TypeName="opc:Double" />
+    <opc:Field Name="z" TypeName="opc:Double" />
+    <opc:Field Name="NoOfArrayDimensions" TypeName="opc:Int32" />
+    <opc:Field Name="array1" TypeName="tns:Point" LengthField="NoOfArrayDimensions" />
   </opc:StructuredType>
 
 </opc:TypeDictionary>

+ 23 - 10
tools/nodeset_compiler/backend_open62541_nodes.py

@@ -70,6 +70,7 @@ def generateObjectNodeCode(node):
     return code
 
 def generateVariableNodeCode(node, nodeset, encode_binary_size):
+
     code = []
     codeCleanup = []
     codeGlobal = []
@@ -167,14 +168,6 @@ def generateExtensionObjectSubtypeCode(node, parent, nodeset, global_var_code, i
     logger.debug("Value    " + str(node.value))
     logger.debug("Encoding " + str(node.encodingRule))
 
-    # If there are any ExtensionObjects inside this ExtensionObject, we need to
-    # generate one-time-structs for them too before we can proceed;
-    for subv in node.value:
-        if isinstance(subv, list):
-            logger.error("ExtensionObject contains an ExtensionObject, which is currently not encodable!")
-            return
-
-
     typeBrowseNode = makeCIdentifier(nodeset.getDataTypeNode(parent.dataType).browseName.name)
     #TODO: review this
     if typeBrowseNode == "NumericRange":
@@ -200,8 +193,28 @@ def generateExtensionObjectSubtypeCode(node, parent, nodeset, global_var_code, i
     for subv in node.value:
         encField = node.encodingRule[encFieldIdx]
         encFieldIdx = encFieldIdx + 1
-        memberName= lowerFirstChar(encField[0])
-        logger.debug(
+        memberName = lowerFirstChar(encField[0])
+        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)))
+            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,
+                                                                                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))
+                subArrayIdx = subArrayIdx + 1
+            code.append(instanceName + "->" + memberName + " = " + instanceName+"_"+ 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 "->"

+ 13 - 2
tools/nodeset_compiler/datatypes.py

@@ -196,9 +196,20 @@ class Value(object):
                     else:
                         t = self.getTypeByString(enc[0], enc)
                         t.alias = alias
-                        t.parseXML(xmlvalue, namespaceMapping=namespaceMapping)
                         t.valueRank = valueRank
-                        return t
+
+                        if valueRank == 1:
+                            values = []
+                            for el in xmlvalue.childNodes:
+                                if not el.nodeType == el.ELEMENT_NODE:
+                                    continue
+                                val = self.getTypeByString(enc[0], enc)
+                                val.parseXML(el, namespaceMapping=namespaceMapping)
+                                values.append(val)
+                            return values
+                        else:
+                            t.parseXML(xmlvalue, namespaceMapping=namespaceMapping)
+                            return t
                 else:
                     if not valueIsInternalType(xmlvalue.localName):
                         logger.error(str(parent.id) + ": Expected XML describing builtin type " + enc[0] + " but found " + xmlvalue.localName + " instead")

+ 1 - 1
tools/nodeset_compiler/nodes.py

@@ -467,7 +467,7 @@ class DataTypeNode(Node):
             used.
         """
 
-        prefix = " " + "|"*indent+ "+"
+        prefix = " " + "|" * indent + "+"
 
         if force==True:
             self.__encodingBuilt__ = False