PLCControler.py
changeset 1308 ad61268dbdb6
parent 1306 1ff1cdf6c318
child 1311 85ca4fa0720b
--- a/PLCControler.py	Mon Sep 09 00:48:34 2013 +0200
+++ b/PLCControler.py	Mon Sep 09 23:36:12 2013 +0200
@@ -24,6 +24,7 @@
 
 from xml.dom import minidom
 from types import StringType, UnicodeType, TupleType
+from lxml import etree
 from copy import deepcopy
 import os,sys,re
 import datetime
@@ -99,6 +100,66 @@
  RESOURCES, PROPERTIES] = UNEDITABLE_NAMES
 
 #-------------------------------------------------------------------------------
+#                 Helpers object for generating pou var list
+#-------------------------------------------------------------------------------
+
+def compute_dimensions(el):
+    return [
+        (dimension.get("lower"), dimension.get("upper"))
+        for dimension in el.findall("dimension")]
+
+def extract_param(el):
+    if el.tag == "Type" and el.text is None:
+        array = el.find("array")
+        return ('array', array.text, compute_dimensions(array))
+    elif el.tag == "Tree":
+        return generate_var_tree(el)
+    elif el.tag == "Edit":
+        return True
+    elif el.text is None:
+        return ''
+    return el.text
+
+def generate_var_tree(tree):
+    return ([
+        (var.get("name"), var.text, generate_var_tree(var))
+         for var in tree.findall("var")],
+        compute_dimensions(tree))
+
+class AddVariable(etree.XSLTExtension):
+    
+    def __init__(self, variables):
+        etree.XSLTExtension.__init__(self)
+        self.Variables = variables
+    
+    def execute(self, context, self_node, input_node, output_parent):
+        infos = etree.Element('var_infos')
+        self.process_children(context, infos)
+        self.Variables.append(
+            {el.tag.replace("_", " "): extract_param(el) for el in infos})
+
+class VarTree(etree.XSLTExtension):
+    
+    def __init__(self, controller):
+        etree.XSLTExtension.__init__(self)
+        self.Controller = controller
+    
+    def execute(self, context, self_node, input_node, output_parent):
+        typename = input_node.get("name")
+        pou_infos = self.Controller.GetPou(typename)
+        if pou_infos is not None:
+            self.apply_templates(context, pou_infos, output_parent)
+            return
+        
+        datatype_infos = self.Controller.GetDataType(typename)
+        if datatype_infos is not None:
+            self.apply_templates(context, datatype_infos, output_parent)
+            return
+
+variables_infos_xslt = etree.parse(
+    os.path.join(ScriptDirectory, "plcopen", "variables_infos.xslt"))
+
+#-------------------------------------------------------------------------------
 #                         Undo Buffer for PLCOpenEditor
 #-------------------------------------------------------------------------------
 
@@ -1224,63 +1285,17 @@
             current_varlist.appendvariable(tempvar)
         return varlist_list
     
-    def GetVariableDictionary(self, varlist, var):
-        '''
-        convert a PLC variable to the dictionary representation
-        returned by Get*Vars)
-        '''
-
-        tempvar = {"Name": var.getname()}
-
-        vartype_content = var.gettype().getcontent()
-        vartype_content_type = vartype_content.getLocalTag()
-        if vartype_content_type == "derived":
-            tempvar["Type"] = vartype_content.getname()
-        elif vartype_content_type == "array":
-            dimensions = []
-            for dimension in vartype_content.getdimension():
-                dimensions.append((dimension.getlower(), dimension.getupper()))
-            base_type = vartype_content.baseType.getcontent()
-            base_type_type = base_type.getLocalTag()
-            if base_type_type == "derived":
-                base_type_name = base_type.getname()
-            else:
-                base_type_name = base_type_type.upper()
-            tempvar["Type"] = ("array", base_type_name, dimensions)
-        else:
-            tempvar["Type"] = vartype_content_type.upper()
+    def GetVariableDictionary(self, object_with_vars):
+        variables = []
         
-        tempvar["Edit"] = True
+        variables_infos_xslt_tree = etree.XSLT(
+            variables_infos_xslt, extensions = {
+                ("var_infos_ns", "add_variable"): AddVariable(variables),
+                ("var_infos_ns", "var_tree"): VarTree(self)})
+        variables_infos_xslt_tree(object_with_vars)
         
-        initial = var.getinitialValue()
-        if initial is not None:
-            tempvar["Initial Value"] = initial.getvalue()
-        else:
-            tempvar["Initial Value"] = ""
-
-        address = var.getaddress()
-        if address:
-            tempvar["Location"] = address
-        else:
-            tempvar["Location"] = ""
-
-        if varlist.getconstant():
-            tempvar["Option"] = "Constant"
-        elif varlist.getretain():
-            tempvar["Option"] = "Retain"
-        elif varlist.getnonretain():
-            tempvar["Option"] = "Non-Retain"
-        else:
-            tempvar["Option"] = ""
-
-        doc = var.getdocumentation()
-        if doc is not None:
-            tempvar["Documentation"] = doc.getanyText()
-        else:
-            tempvar["Documentation"] = ""
-
-        return tempvar
-    
+        return variables
+            
     # Add a global var to configuration to configuration
     def AddConfigurationGlobalVar(self, config_name, type, var_name, 
                                            location="", description=""):
@@ -1304,19 +1319,15 @@
     
     # Return the configuration globalvars
     def GetConfigurationGlobalVars(self, name, debug = False):
-        vars = []
         project = self.GetProject(debug)
         if project is not None:
             # Found the configuration corresponding to name
             configuration = project.getconfiguration(name)
             if configuration is not None:
-                # Extract variables from every varLists
-                for varlist in configuration.getglobalVars():
-                    for var in varlist.getvariable():
-                        tempvar = self.GetVariableDictionary(varlist, var)
-                        tempvar["Class"] = "Global"
-                        vars.append(tempvar)
-        return vars
+                # Extract variables defined in configuration
+                return self.GetVariableDictionary(configuration)
+        
+        return []
 
     # Return configuration variable names
     def GetConfigurationVariableNames(self, config_name = None, debug = False):
@@ -1345,19 +1356,15 @@
     
     # Return the resource globalvars
     def GetConfigurationResourceGlobalVars(self, config_name, name, debug = False):
-        vars = []
         project = self.GetProject(debug)
         if project is not None:
             # Found the resource corresponding to name
             resource = project.getconfigurationResource(config_name, name)
             if resource is not None:
-                # Extract variables from every varLists
-                for varlist in resource.getglobalVars():
-                    for var in varlist.getvariable():
-                        tempvar = self.GetVariableDictionary(varlist, var)
-                        tempvar["Class"] = "Global"
-                        vars.append(tempvar)
-        return vars
+                # Extract variables defined in configuration
+                return self.GetVariableDictionary(resource)
+        
+        return []
     
     # Return resource variable names
     def GetConfigurationResourceVariableNames(self, 
@@ -1375,73 +1382,15 @@
                                         for varlist in resource.globalVars],
                                     [])])
         return variables
-    
-    # Recursively generate element name tree for a structured variable
-    def GenerateVarTree(self, typename, debug = False):
-        project = self.GetProject(debug)
-        if project is not None:
-            blocktype = self.GetBlockType(typename, debug = debug)
-            if blocktype is not None:
-                tree = []
-                en = False
-                eno = False
-                for var_name, var_type, var_modifier in blocktype["inputs"] + blocktype["outputs"]:
-                    en |= var_name.upper() == "EN"
-                    eno |= var_name.upper() == "ENO"    
-                    tree.append((var_name, var_type, self.GenerateVarTree(var_type, debug)))
-                if not eno:
-                    tree.insert(0, ("ENO", "BOOL", ([], [])))
-                if not en:
-                    tree.insert(0, ("EN", "BOOL", ([], [])))
-                return tree, []
-            datatype = self.GetDataType(typename)
-            if datatype is not None:
-                tree = []
-                basetype_content = datatype.baseType.getcontent()
-                basetype_content_type = basetype_content.getLocalTag()
-                if basetype_content_type == "derived":
-                    return self.GenerateVarTree(basetype_content.getname())
-                elif basetype_content_type == "array":
-                    dimensions = []
-                    base_type = basetype_content.baseType.getcontent()
-                    if base_type.getLocalTag() == "derived":
-                        tree = self.GenerateVarTree(base_type.getname())
-                        if len(tree[1]) == 0:
-                            tree = tree[0]
-                        for dimension in basetype_content.getdimension():
-                            dimensions.append((dimension.getlower(), dimension.getupper()))
-                    return tree, dimensions
-                elif basetype_content_type == "struct":
-                    for element in basetype_content.getvariable():
-                        element_type = element.type.getcontent()
-                        element_type_type = element_type.getLocalTag()
-                        if element_type_type == "derived":
-                            tree.append((element.getname(), element_type.getname(), self.GenerateVarTree(element_type.getname())))
-                        else:
-                            tree.append((element.getname(), element_type_type, ([], [])))
-                    return tree, []
-        return [], []
 
     # Return the interface for the given pou
     def GetPouInterfaceVars(self, pou, debug = False):
-        vars = []
+        interface = pou.interface
         # Verify that the pou has an interface
-        if pou.interface is not None:
-            # Extract variables from every varLists
-            for type, varlist in pou.getvars():
-                for var in varlist.getvariable():
-                    tempvar = self.GetVariableDictionary(varlist, var)
-
-                    tempvar["Class"] = type
-                    tempvar["Tree"] = ([], [])
-
-                    vartype_content = var.gettype().getcontent()
-                    if vartype_content.getLocalTag() == "derived":
-                        tempvar["Edit"] = not pou.hasblock(tempvar["Name"])
-                        tempvar["Tree"] = self.GenerateVarTree(tempvar["Type"], debug)
-
-                    vars.append(tempvar)
-        return vars
+        if interface is not None:
+            # Extract variables defined in interface
+            return self.GetVariableDictionary(interface)
+        return []
 
     # Replace the Pou interface by the one given
     def SetPouInterfaceVars(self, name, vars):
@@ -1503,13 +1452,13 @@
             # Return the return type if there is one
             return_type = pou.interface.getreturnType()
             if return_type is not None:
-                returntype_content = return_type.getcontent()
-                returntype_content_type = returntype_content.getLocalTag()
-                if returntype_content_type == "derived":
-                    return returntype_content.getname()
-                else:
-                    return returntype_content_type.upper()
-        return None
+                return_type_infos_xslt_tree = etree.XSLT(
+                    variables_infos_xslt, extensions = {
+                          ("var_infos_ns", "var_tree"): VarTree(self)})
+            return [extract_param(el) 
+                   for el in return_type_infos_xslt_tree(return_type).getroot()]
+                
+        return [None, ([], [])] 
 
     # Function that add a new confnode to the confnode list
     def AddConfNodeTypesList(self, typeslist):
@@ -1680,6 +1629,20 @@
         return datatypes
 
     # Return Data Type Object
+    def GetPou(self, typename, debug = False):
+        project = self.GetProject(debug)
+        if project is not None:
+            result = project.getpou(typename)
+            if result is not None:
+                return result
+        for confnodetype in self.ConfNodeTypes:
+            result = confnodetype["types"].getpou(typename)
+            if result is not None:
+                return result
+        return None
+
+
+    # Return Data Type Object
     def GetDataType(self, typename, debug = False):
         project = self.GetProject(debug)
         if project is not None: