PLCControler.py
changeset 1308 ad61268dbdb6
parent 1306 1ff1cdf6c318
child 1311 85ca4fa0720b
equal deleted inserted replaced
1307:26e8b99bc2c3 1308:ad61268dbdb6
    22 #License along with this library; if not, write to the Free Software
    22 #License along with this library; if not, write to the Free Software
    23 #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    23 #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    24 
    24 
    25 from xml.dom import minidom
    25 from xml.dom import minidom
    26 from types import StringType, UnicodeType, TupleType
    26 from types import StringType, UnicodeType, TupleType
       
    27 from lxml import etree
    27 from copy import deepcopy
    28 from copy import deepcopy
    28 import os,sys,re
    29 import os,sys,re
    29 import datetime
    30 import datetime
    30 from time import localtime
    31 from time import localtime
    31 
    32 
    95             _("Configurations"), _("Resources"), _("Properties")]
    96             _("Configurations"), _("Resources"), _("Properties")]
    96 UNEDITABLE_NAMES = GetUneditableNames()
    97 UNEDITABLE_NAMES = GetUneditableNames()
    97 [USER_DEFINED_POUS, FUNCTIONS, FUNCTION_BLOCKS, PROGRAMS, 
    98 [USER_DEFINED_POUS, FUNCTIONS, FUNCTION_BLOCKS, PROGRAMS, 
    98  DATA_TYPES, TRANSITIONS, ACTIONS, CONFIGURATIONS, 
    99  DATA_TYPES, TRANSITIONS, ACTIONS, CONFIGURATIONS, 
    99  RESOURCES, PROPERTIES] = UNEDITABLE_NAMES
   100  RESOURCES, PROPERTIES] = UNEDITABLE_NAMES
       
   101 
       
   102 #-------------------------------------------------------------------------------
       
   103 #                 Helpers object for generating pou var list
       
   104 #-------------------------------------------------------------------------------
       
   105 
       
   106 def compute_dimensions(el):
       
   107     return [
       
   108         (dimension.get("lower"), dimension.get("upper"))
       
   109         for dimension in el.findall("dimension")]
       
   110 
       
   111 def extract_param(el):
       
   112     if el.tag == "Type" and el.text is None:
       
   113         array = el.find("array")
       
   114         return ('array', array.text, compute_dimensions(array))
       
   115     elif el.tag == "Tree":
       
   116         return generate_var_tree(el)
       
   117     elif el.tag == "Edit":
       
   118         return True
       
   119     elif el.text is None:
       
   120         return ''
       
   121     return el.text
       
   122 
       
   123 def generate_var_tree(tree):
       
   124     return ([
       
   125         (var.get("name"), var.text, generate_var_tree(var))
       
   126          for var in tree.findall("var")],
       
   127         compute_dimensions(tree))
       
   128 
       
   129 class AddVariable(etree.XSLTExtension):
       
   130     
       
   131     def __init__(self, variables):
       
   132         etree.XSLTExtension.__init__(self)
       
   133         self.Variables = variables
       
   134     
       
   135     def execute(self, context, self_node, input_node, output_parent):
       
   136         infos = etree.Element('var_infos')
       
   137         self.process_children(context, infos)
       
   138         self.Variables.append(
       
   139             {el.tag.replace("_", " "): extract_param(el) for el in infos})
       
   140 
       
   141 class VarTree(etree.XSLTExtension):
       
   142     
       
   143     def __init__(self, controller):
       
   144         etree.XSLTExtension.__init__(self)
       
   145         self.Controller = controller
       
   146     
       
   147     def execute(self, context, self_node, input_node, output_parent):
       
   148         typename = input_node.get("name")
       
   149         pou_infos = self.Controller.GetPou(typename)
       
   150         if pou_infos is not None:
       
   151             self.apply_templates(context, pou_infos, output_parent)
       
   152             return
       
   153         
       
   154         datatype_infos = self.Controller.GetDataType(typename)
       
   155         if datatype_infos is not None:
       
   156             self.apply_templates(context, datatype_infos, output_parent)
       
   157             return
       
   158 
       
   159 variables_infos_xslt = etree.parse(
       
   160     os.path.join(ScriptDirectory, "plcopen", "variables_infos.xslt"))
   100 
   161 
   101 #-------------------------------------------------------------------------------
   162 #-------------------------------------------------------------------------------
   102 #                         Undo Buffer for PLCOpenEditor
   163 #                         Undo Buffer for PLCOpenEditor
   103 #-------------------------------------------------------------------------------
   164 #-------------------------------------------------------------------------------
   104 
   165 
  1222 
  1283 
  1223             # Add variable to varList
  1284             # Add variable to varList
  1224             current_varlist.appendvariable(tempvar)
  1285             current_varlist.appendvariable(tempvar)
  1225         return varlist_list
  1286         return varlist_list
  1226     
  1287     
  1227     def GetVariableDictionary(self, varlist, var):
  1288     def GetVariableDictionary(self, object_with_vars):
  1228         '''
  1289         variables = []
  1229         convert a PLC variable to the dictionary representation
       
  1230         returned by Get*Vars)
       
  1231         '''
       
  1232 
       
  1233         tempvar = {"Name": var.getname()}
       
  1234 
       
  1235         vartype_content = var.gettype().getcontent()
       
  1236         vartype_content_type = vartype_content.getLocalTag()
       
  1237         if vartype_content_type == "derived":
       
  1238             tempvar["Type"] = vartype_content.getname()
       
  1239         elif vartype_content_type == "array":
       
  1240             dimensions = []
       
  1241             for dimension in vartype_content.getdimension():
       
  1242                 dimensions.append((dimension.getlower(), dimension.getupper()))
       
  1243             base_type = vartype_content.baseType.getcontent()
       
  1244             base_type_type = base_type.getLocalTag()
       
  1245             if base_type_type == "derived":
       
  1246                 base_type_name = base_type.getname()
       
  1247             else:
       
  1248                 base_type_name = base_type_type.upper()
       
  1249             tempvar["Type"] = ("array", base_type_name, dimensions)
       
  1250         else:
       
  1251             tempvar["Type"] = vartype_content_type.upper()
       
  1252         
  1290         
  1253         tempvar["Edit"] = True
  1291         variables_infos_xslt_tree = etree.XSLT(
       
  1292             variables_infos_xslt, extensions = {
       
  1293                 ("var_infos_ns", "add_variable"): AddVariable(variables),
       
  1294                 ("var_infos_ns", "var_tree"): VarTree(self)})
       
  1295         variables_infos_xslt_tree(object_with_vars)
  1254         
  1296         
  1255         initial = var.getinitialValue()
  1297         return variables
  1256         if initial is not None:
  1298             
  1257             tempvar["Initial Value"] = initial.getvalue()
       
  1258         else:
       
  1259             tempvar["Initial Value"] = ""
       
  1260 
       
  1261         address = var.getaddress()
       
  1262         if address:
       
  1263             tempvar["Location"] = address
       
  1264         else:
       
  1265             tempvar["Location"] = ""
       
  1266 
       
  1267         if varlist.getconstant():
       
  1268             tempvar["Option"] = "Constant"
       
  1269         elif varlist.getretain():
       
  1270             tempvar["Option"] = "Retain"
       
  1271         elif varlist.getnonretain():
       
  1272             tempvar["Option"] = "Non-Retain"
       
  1273         else:
       
  1274             tempvar["Option"] = ""
       
  1275 
       
  1276         doc = var.getdocumentation()
       
  1277         if doc is not None:
       
  1278             tempvar["Documentation"] = doc.getanyText()
       
  1279         else:
       
  1280             tempvar["Documentation"] = ""
       
  1281 
       
  1282         return tempvar
       
  1283     
       
  1284     # Add a global var to configuration to configuration
  1299     # Add a global var to configuration to configuration
  1285     def AddConfigurationGlobalVar(self, config_name, type, var_name, 
  1300     def AddConfigurationGlobalVar(self, config_name, type, var_name, 
  1286                                            location="", description=""):
  1301                                            location="", description=""):
  1287         if self.Project is not None:
  1302         if self.Project is not None:
  1288             # Found the configuration corresponding to name
  1303             # Found the configuration corresponding to name
  1302                     varlist for vartype, varlist
  1317                     varlist for vartype, varlist
  1303                     in self.ExtractVarLists(vars)])
  1318                     in self.ExtractVarLists(vars)])
  1304     
  1319     
  1305     # Return the configuration globalvars
  1320     # Return the configuration globalvars
  1306     def GetConfigurationGlobalVars(self, name, debug = False):
  1321     def GetConfigurationGlobalVars(self, name, debug = False):
  1307         vars = []
       
  1308         project = self.GetProject(debug)
  1322         project = self.GetProject(debug)
  1309         if project is not None:
  1323         if project is not None:
  1310             # Found the configuration corresponding to name
  1324             # Found the configuration corresponding to name
  1311             configuration = project.getconfiguration(name)
  1325             configuration = project.getconfiguration(name)
  1312             if configuration is not None:
  1326             if configuration is not None:
  1313                 # Extract variables from every varLists
  1327                 # Extract variables defined in configuration
  1314                 for varlist in configuration.getglobalVars():
  1328                 return self.GetVariableDictionary(configuration)
  1315                     for var in varlist.getvariable():
  1329         
  1316                         tempvar = self.GetVariableDictionary(varlist, var)
  1330         return []
  1317                         tempvar["Class"] = "Global"
       
  1318                         vars.append(tempvar)
       
  1319         return vars
       
  1320 
  1331 
  1321     # Return configuration variable names
  1332     # Return configuration variable names
  1322     def GetConfigurationVariableNames(self, config_name = None, debug = False):
  1333     def GetConfigurationVariableNames(self, config_name = None, debug = False):
  1323         variables = []
  1334         variables = []
  1324         project = self.GetProject(debug)
  1335         project = self.GetProject(debug)
  1343                     varlist for vartype, varlist
  1354                     varlist for vartype, varlist
  1344                     in self.ExtractVarLists(vars)])
  1355                     in self.ExtractVarLists(vars)])
  1345     
  1356     
  1346     # Return the resource globalvars
  1357     # Return the resource globalvars
  1347     def GetConfigurationResourceGlobalVars(self, config_name, name, debug = False):
  1358     def GetConfigurationResourceGlobalVars(self, config_name, name, debug = False):
  1348         vars = []
       
  1349         project = self.GetProject(debug)
  1359         project = self.GetProject(debug)
  1350         if project is not None:
  1360         if project is not None:
  1351             # Found the resource corresponding to name
  1361             # Found the resource corresponding to name
  1352             resource = project.getconfigurationResource(config_name, name)
  1362             resource = project.getconfigurationResource(config_name, name)
  1353             if resource is not None:
  1363             if resource is not None:
  1354                 # Extract variables from every varLists
  1364                 # Extract variables defined in configuration
  1355                 for varlist in resource.getglobalVars():
  1365                 return self.GetVariableDictionary(resource)
  1356                     for var in varlist.getvariable():
  1366         
  1357                         tempvar = self.GetVariableDictionary(varlist, var)
  1367         return []
  1358                         tempvar["Class"] = "Global"
       
  1359                         vars.append(tempvar)
       
  1360         return vars
       
  1361     
  1368     
  1362     # Return resource variable names
  1369     # Return resource variable names
  1363     def GetConfigurationResourceVariableNames(self, 
  1370     def GetConfigurationResourceVariableNames(self, 
  1364                 config_name = None, resource_name = None, debug = False):
  1371                 config_name = None, resource_name = None, debug = False):
  1365         variables = []
  1372         variables = []
  1373                                 [var.getname() for var in reduce(
  1380                                 [var.getname() for var in reduce(
  1374                                     lambda x, y: x + y, [varlist.getvariable() 
  1381                                     lambda x, y: x + y, [varlist.getvariable() 
  1375                                         for varlist in resource.globalVars],
  1382                                         for varlist in resource.globalVars],
  1376                                     [])])
  1383                                     [])])
  1377         return variables
  1384         return variables
  1378     
       
  1379     # Recursively generate element name tree for a structured variable
       
  1380     def GenerateVarTree(self, typename, debug = False):
       
  1381         project = self.GetProject(debug)
       
  1382         if project is not None:
       
  1383             blocktype = self.GetBlockType(typename, debug = debug)
       
  1384             if blocktype is not None:
       
  1385                 tree = []
       
  1386                 en = False
       
  1387                 eno = False
       
  1388                 for var_name, var_type, var_modifier in blocktype["inputs"] + blocktype["outputs"]:
       
  1389                     en |= var_name.upper() == "EN"
       
  1390                     eno |= var_name.upper() == "ENO"    
       
  1391                     tree.append((var_name, var_type, self.GenerateVarTree(var_type, debug)))
       
  1392                 if not eno:
       
  1393                     tree.insert(0, ("ENO", "BOOL", ([], [])))
       
  1394                 if not en:
       
  1395                     tree.insert(0, ("EN", "BOOL", ([], [])))
       
  1396                 return tree, []
       
  1397             datatype = self.GetDataType(typename)
       
  1398             if datatype is not None:
       
  1399                 tree = []
       
  1400                 basetype_content = datatype.baseType.getcontent()
       
  1401                 basetype_content_type = basetype_content.getLocalTag()
       
  1402                 if basetype_content_type == "derived":
       
  1403                     return self.GenerateVarTree(basetype_content.getname())
       
  1404                 elif basetype_content_type == "array":
       
  1405                     dimensions = []
       
  1406                     base_type = basetype_content.baseType.getcontent()
       
  1407                     if base_type.getLocalTag() == "derived":
       
  1408                         tree = self.GenerateVarTree(base_type.getname())
       
  1409                         if len(tree[1]) == 0:
       
  1410                             tree = tree[0]
       
  1411                         for dimension in basetype_content.getdimension():
       
  1412                             dimensions.append((dimension.getlower(), dimension.getupper()))
       
  1413                     return tree, dimensions
       
  1414                 elif basetype_content_type == "struct":
       
  1415                     for element in basetype_content.getvariable():
       
  1416                         element_type = element.type.getcontent()
       
  1417                         element_type_type = element_type.getLocalTag()
       
  1418                         if element_type_type == "derived":
       
  1419                             tree.append((element.getname(), element_type.getname(), self.GenerateVarTree(element_type.getname())))
       
  1420                         else:
       
  1421                             tree.append((element.getname(), element_type_type, ([], [])))
       
  1422                     return tree, []
       
  1423         return [], []
       
  1424 
  1385 
  1425     # Return the interface for the given pou
  1386     # Return the interface for the given pou
  1426     def GetPouInterfaceVars(self, pou, debug = False):
  1387     def GetPouInterfaceVars(self, pou, debug = False):
  1427         vars = []
  1388         interface = pou.interface
  1428         # Verify that the pou has an interface
  1389         # Verify that the pou has an interface
  1429         if pou.interface is not None:
  1390         if interface is not None:
  1430             # Extract variables from every varLists
  1391             # Extract variables defined in interface
  1431             for type, varlist in pou.getvars():
  1392             return self.GetVariableDictionary(interface)
  1432                 for var in varlist.getvariable():
  1393         return []
  1433                     tempvar = self.GetVariableDictionary(varlist, var)
       
  1434 
       
  1435                     tempvar["Class"] = type
       
  1436                     tempvar["Tree"] = ([], [])
       
  1437 
       
  1438                     vartype_content = var.gettype().getcontent()
       
  1439                     if vartype_content.getLocalTag() == "derived":
       
  1440                         tempvar["Edit"] = not pou.hasblock(tempvar["Name"])
       
  1441                         tempvar["Tree"] = self.GenerateVarTree(tempvar["Type"], debug)
       
  1442 
       
  1443                     vars.append(tempvar)
       
  1444         return vars
       
  1445 
  1394 
  1446     # Replace the Pou interface by the one given
  1395     # Replace the Pou interface by the one given
  1447     def SetPouInterfaceVars(self, name, vars):
  1396     def SetPouInterfaceVars(self, name, vars):
  1448         if self.Project is not None:
  1397         if self.Project is not None:
  1449             # Found the pou corresponding to name and add interface if there isn't one yet
  1398             # Found the pou corresponding to name and add interface if there isn't one yet
  1501         # Verify that the pou has an interface
  1450         # Verify that the pou has an interface
  1502         if pou.interface is not None:
  1451         if pou.interface is not None:
  1503             # Return the return type if there is one
  1452             # Return the return type if there is one
  1504             return_type = pou.interface.getreturnType()
  1453             return_type = pou.interface.getreturnType()
  1505             if return_type is not None:
  1454             if return_type is not None:
  1506                 returntype_content = return_type.getcontent()
  1455                 return_type_infos_xslt_tree = etree.XSLT(
  1507                 returntype_content_type = returntype_content.getLocalTag()
  1456                     variables_infos_xslt, extensions = {
  1508                 if returntype_content_type == "derived":
  1457                           ("var_infos_ns", "var_tree"): VarTree(self)})
  1509                     return returntype_content.getname()
  1458             return [extract_param(el) 
  1510                 else:
  1459                    for el in return_type_infos_xslt_tree(return_type).getroot()]
  1511                     return returntype_content_type.upper()
  1460                 
  1512         return None
  1461         return [None, ([], [])] 
  1513 
  1462 
  1514     # Function that add a new confnode to the confnode list
  1463     # Function that add a new confnode to the confnode list
  1515     def AddConfNodeTypesList(self, typeslist):
  1464     def AddConfNodeTypesList(self, typeslist):
  1516         self.ConfNodeTypes.extend(typeslist)
  1465         self.ConfNodeTypes.extend(typeslist)
  1517         addedcat = [{"name": _("%s POUs") % confnodetypes["name"],
  1466         addedcat = [{"name": _("%s POUs") % confnodetypes["name"],
  1676                 if not only_locatables or self.IsLocatableDataType(datatype, debug)])
  1625                 if not only_locatables or self.IsLocatableDataType(datatype, debug)])
  1677         if confnodetypes:
  1626         if confnodetypes:
  1678             for category in self.GetConfNodeDataTypes(name, only_locatables):
  1627             for category in self.GetConfNodeDataTypes(name, only_locatables):
  1679                 datatypes.extend(category["list"])
  1628                 datatypes.extend(category["list"])
  1680         return datatypes
  1629         return datatypes
       
  1630 
       
  1631     # Return Data Type Object
       
  1632     def GetPou(self, typename, debug = False):
       
  1633         project = self.GetProject(debug)
       
  1634         if project is not None:
       
  1635             result = project.getpou(typename)
       
  1636             if result is not None:
       
  1637                 return result
       
  1638         for confnodetype in self.ConfNodeTypes:
       
  1639             result = confnodetype["types"].getpou(typename)
       
  1640             if result is not None:
       
  1641                 return result
       
  1642         return None
       
  1643 
  1681 
  1644 
  1682     # Return Data Type Object
  1645     # Return Data Type Object
  1683     def GetDataType(self, typename, debug = False):
  1646     def GetDataType(self, typename, debug = False):
  1684         project = self.GetProject(debug)
  1647         project = self.GetProject(debug)
  1685         if project is not None:
  1648         if project is not None: