plcopen/plcopen.py
changeset 1294 f02ba5b83811
parent 1293 40117d02601b
child 1298 f034fb2b1aab
equal deleted inserted replaced
1293:40117d02601b 1294:f02ba5b83811
   125 
   125 
   126 PLCOpenParser = GenerateParserFromXSD(os.path.join(os.path.split(__file__)[0], "tc6_xml_v201.xsd"))
   126 PLCOpenParser = GenerateParserFromXSD(os.path.join(os.path.split(__file__)[0], "tc6_xml_v201.xsd"))
   127 
   127 
   128 def LoadProject(filepath):
   128 def LoadProject(filepath):
   129     project_file = open(filepath)
   129     project_file = open(filepath)
   130     project_xml = project_file.read()\
   130     project_xml = project_file.read().replace(
   131         .replace("http://www.plcopen.org/xml/tc6.xsd", 
   131         "http://www.plcopen.org/xml/tc6.xsd", 
   132                  "http://www.plcopen.org/xml/tc6_0201")\
   132         "http://www.plcopen.org/xml/tc6_0201")
   133         .replace("<![CDATA[", "<xhtml:p><![CDATA[")\
   133     for cre, repl in [
   134         .replace("]]>", "]]></xhtml:p>")
   134         (re.compile("(?<!<xhtml:p>)(?:<!\[CDATA\[)"), "<xhtml:p><![CDATA["),
       
   135         (re.compile("(?:]]>)(?!</xhtml:p>)"), "]]></xhtml:p>")]:
       
   136         project_xml = cre.sub(repl, project_xml)
   135     project_file.close()
   137     project_file.close()
   136     
   138     
   137     return etree.fromstring(project_xml, PLCOpenParser)
   139     return etree.fromstring(project_xml, PLCOpenParser)
   138 
   140 
   139 def SaveProject(project, filepath):
   141 def SaveProject(project, filepath):
   146     project_file.close()
   148     project_file.close()
   147 
   149 
   148 cls = PLCOpenParser.GetElementClass("formattedText")
   150 cls = PLCOpenParser.GetElementClass("formattedText")
   149 if cls:
   151 if cls:
   150     def updateElementName(self, old_name, new_name):
   152     def updateElementName(self, old_name, new_name):
   151         text = self.text
   153         text = self.getanyText()
   152         index = text.find(old_name)
   154         index = text.find(old_name)
   153         while index != -1:
   155         while index != -1:
   154             if index > 0 and (text[index - 1].isalnum() or text[index - 1] == "_"):
   156             if index > 0 and (text[index - 1].isalnum() or text[index - 1] == "_"):
   155                 index = text.find(old_name, index + len(old_name))
   157                 index = text.find(old_name, index + len(old_name))
   156             elif index < len(text) - len(old_name) and (text[index + len(old_name)].isalnum() or text[index + len(old_name)] == "_"):
   158             elif index < len(text) - len(old_name) and (text[index + len(old_name)].isalnum() or text[index + len(old_name)] == "_"):
   157                 index = text.find(old_name, index + len(old_name))
   159                 index = text.find(old_name, index + len(old_name))
   158             else:
   160             else:
   159                 text = text[:index] + new_name + text[index + len(old_name):]
   161                 text = text[:index] + new_name + text[index + len(old_name):]
   160                 index = text.find(old_name, index + len(new_name))
   162                 index = text.find(old_name, index + len(new_name))
   161         self.text = text
   163         self.setanyText(text)
   162     setattr(cls, "updateElementName", updateElementName)
   164     setattr(cls, "updateElementName", updateElementName)
   163     
   165     
   164     def updateElementAddress(self, address_model, new_leading):
   166     def updateElementAddress(self, address_model, new_leading):
   165         text = self.text
   167         text = self.getanyText()
   166         startpos = 0
   168         startpos = 0
   167         result = address_model.search(text, startpos)
   169         result = address_model.search(text, startpos)
   168         while result is not None:
   170         while result is not None:
   169             groups = result.groups()
   171             groups = result.groups()
   170             new_address = groups[0] + new_leading + groups[2]
   172             new_address = groups[0] + new_leading + groups[2]
   171             text = text[:result.start()] + new_address + text[result.end():]
   173             text = text[:result.start()] + new_address + text[result.end():]
   172             startpos = result.start() + len(new_address)
   174             startpos = result.start() + len(new_address)
   173             result = address_model.search(self.text, startpos)
   175             result = address_model.search(self.text, startpos)
   174         self.text = text
   176         self.setanyText(text)
   175     setattr(cls, "updateElementAddress", updateElementAddress)
   177     setattr(cls, "updateElementAddress", updateElementAddress)
   176     
   178     
   177     def hasblock(self, block_type):
   179     def hasblock(self, block_type):
   178         text = self.text.upper()
   180         text = self.getanyText().upper()
   179         index = text.find(block_type.upper())
   181         index = text.find(block_type.upper())
   180         while index != -1:
   182         while index != -1:
   181             if (not (index > 0 and (text[index - 1].isalnum() or text[index - 1] == "_")) and 
   183             if (not (index > 0 and (text[index - 1].isalnum() or text[index - 1] == "_")) and 
   182                 not (index < len(text) - len(block_type) and text[index + len(block_type)] != "(")):
   184                 not (index < len(text) - len(block_type) and text[index + len(block_type)] != "(")):
   183                 return True
   185                 return True
   324         self.RefreshElementUsingTree()
   326         self.RefreshElementUsingTree()
   325     setattr(cls, "removepou", removepou)
   327     setattr(cls, "removepou", removepou)
   326 
   328 
   327     def getconfigurations(self):
   329     def getconfigurations(self):
   328         configurations = self.instances.configurations.getconfiguration()
   330         configurations = self.instances.configurations.getconfiguration()
   329         if configurations:
   331         if configurations is not None:
   330             return configurations
   332             return configurations
   331         return []
   333         return []
   332     setattr(cls, "getconfigurations", getconfigurations)
   334     setattr(cls, "getconfigurations", getconfigurations)
   333 
   335 
   334     def getconfiguration(self, name):
   336     def getconfiguration(self, name):
   358             raise ValueError, ("\"%s\" configuration doesn't exist !!!")%name
   360             raise ValueError, ("\"%s\" configuration doesn't exist !!!")%name
   359     setattr(cls, "removeconfiguration", removeconfiguration)
   361     setattr(cls, "removeconfiguration", removeconfiguration)
   360 
   362 
   361     def getconfigurationResource(self, config_name, name):
   363     def getconfigurationResource(self, config_name, name):
   362         configuration = self.getconfiguration(config_name)
   364         configuration = self.getconfiguration(config_name)
   363         if configuration:
   365         if configuration is not None:
   364             for resource in configuration.getresource():
   366             for resource in configuration.getresource():
   365                 if resource.getname() == name:
   367                 if resource.getname() == name:
   366                     return resource
   368                     return resource
   367         return None
   369         return None
   368     setattr(cls, "getconfigurationResource", getconfigurationResource)
   370     setattr(cls, "getconfigurationResource", getconfigurationResource)
   369 
   371 
   370     def addconfigurationResource(self, config_name, name):
   372     def addconfigurationResource(self, config_name, name):
   371         configuration = self.getconfiguration(config_name)
   373         configuration = self.getconfiguration(config_name)
   372         if configuration:
   374         if configuration is not None:
   373             for resource in configuration.getresource():
   375             for resource in configuration.getresource():
   374                 if resource.getname() == name:
   376                 if resource.getname() == name:
   375                     raise ValueError, _("\"%s\" resource already exists in \"%s\" configuration !!!")%(name, config_name)
   377                     raise ValueError, _("\"%s\" resource already exists in \"%s\" configuration !!!")%(name, config_name)
   376             new_resource = PLCOpenParser.CreateElement("resource", "configuration")
   378             new_resource = PLCOpenParser.CreateElement("resource", "configuration")
   377             new_resource.setname(name)
   379             new_resource.setname(name)
   378             configuration.appendresource(new_resource)
   380             configuration.appendresource(new_resource)
   379     setattr(cls, "addconfigurationResource", addconfigurationResource)
   381     setattr(cls, "addconfigurationResource", addconfigurationResource)
   380 
   382 
   381     def removeconfigurationResource(self, config_name, name):
   383     def removeconfigurationResource(self, config_name, name):
   382         configuration = self.getconfiguration(config_name)
   384         configuration = self.getconfiguration(config_name)
   383         if configuration:
   385         if configuration is not None:
   384             found = False
   386             found = False
   385             for idx, resource in enumerate(configuration.getresource()):
   387             for idx, resource in enumerate(configuration.getresource()):
   386                 if resource.getname() == name:
   388                 if resource.getname() == name:
   387                     configuration.removeresource(idx)
   389                     configuration.removeresource(idx)
   388                     found = True
   390                     found = True
   445             range = (basetype_content.range.getlower(), 
   447             range = (basetype_content.range.getlower(), 
   446                      basetype_content.range.getupper())
   448                      basetype_content.range.getupper())
   447             self.CustomDataTypeRange[name] = range
   449             self.CustomDataTypeRange[name] = range
   448             base_type = basetype_content.baseType.getcontent()
   450             base_type = basetype_content.baseType.getcontent()
   449             if base_type.__class__ == DefaultElementClass:
   451             if base_type.__class__ == DefaultElementClass:
   450                 self.CustomTypeHierarchy[name] = basetype.getLocalTag()
   452                 self.CustomTypeHierarchy[name] = base_type.getLocalTag()
   451             else:
   453             else:
   452                 self.CustomTypeHierarchy[name] = base_type.getname()
   454                 self.CustomTypeHierarchy[name] = base_type.getname()
   453         else:
   455         else:
   454             if basetype_content_name == "enum":
   456             if basetype_content_name == "enum":
   455                 values = []
   457                 values = []
   878             var_type_obj.setcontent(derived_type)
   880             var_type_obj.setcontent(derived_type)
   879         var.settype(var_type_obj)
   881         var.settype(var_type_obj)
   880         if location != "":
   882         if location != "":
   881             var.setaddress(location)
   883             var.setaddress(location)
   882         if description != "":
   884         if description != "":
   883             ft = PLCOpenParser.CreateElement("formattedText")
   885             ft = PLCOpenParser.CreateElement("documentation", "variable")
   884             ft.setanyText(description)
   886             ft.setanyText(description)
   885             var.setdocumentation(ft)
   887             var.setdocumentation(ft)
   886         globalvars[-1].appendvariable(var)
   888         globalvars[-1].appendvariable(var)
   887     setattr(cls, "addglobalVar", addglobalVar)
   889     setattr(cls, "addglobalVar", addglobalVar)
   888     
   890     
  1079 
  1081 
  1080     def appenddataTypeElement(self, name):
  1082     def appenddataTypeElement(self, name):
  1081         new_datatype = PLCOpenParser.CreateElement("dataType", "dataTypes")
  1083         new_datatype = PLCOpenParser.CreateElement("dataType", "dataTypes")
  1082         self.dataTypes.appenddataType(new_datatype)
  1084         self.dataTypes.appenddataType(new_datatype)
  1083         new_datatype.setname(name)
  1085         new_datatype.setname(name)
  1084         new_datatype.baseType.setcontent(PLCOpenParser.CreateElement("BOOL"))
  1086         new_datatype.baseType.setcontent(PLCOpenParser.CreateElement("BOOL", "dataType"))
  1085     setattr(cls, "appenddataTypeElement", appenddataTypeElement)
  1087     setattr(cls, "appenddataTypeElement", appenddataTypeElement)
  1086     
  1088     
  1087     def insertdataTypeElement(self, index, dataType):
  1089     def insertdataTypeElement(self, index, dataType):
  1088         self.dataTypes.insertdataType(index, dataType)
  1090         self.dataTypes.insertdataType(index, dataType)
  1089     setattr(cls, "insertdataTypeElement", insertdataTypeElement)
  1091     setattr(cls, "insertdataTypeElement", insertdataTypeElement)
  1181 
  1183 
  1182     def Search(self, criteria, parent_infos=[]):
  1184     def Search(self, criteria, parent_infos=[]):
  1183         search_result = []
  1185         search_result = []
  1184         content_name = self.content.getLocalTag()
  1186         content_name = self.content.getLocalTag()
  1185         if content_name in ["derived", "array", "enum", "subrangeSigned", "subrangeUnsigned"]:
  1187         if content_name in ["derived", "array", "enum", "subrangeSigned", "subrangeUnsigned"]:
  1186             search_result.extend(self.content["value"].Search(criteria, parent_infos))
  1188             search_result.extend(self.content.Search(criteria, parent_infos + ["base"]))
  1187         elif content_name == "struct":
  1189         elif content_name == "struct":
  1188             for i, element in enumerate(self.content["value"].getvariable()):
  1190             for i, element in enumerate(self.content.getvariable()):
  1189                 search_result.extend(element.Search(criteria, parent_infos + ["struct", i]))
  1191                 search_result.extend(element.Search(criteria, parent_infos + ["struct", i]))
  1190         else:
  1192         else:
  1191             if content_name in ["string", "wstring"]:
  1193             if content_name in ["string", "wstring"]:
  1192                 content_name = content_name.upper()
  1194                 content_name = content_name.upper()
  1193             search_result.extend(_Search([("base", content_name)], criteria, parent_infos))
  1195             search_result.extend(_Search([("base", content_name)], criteria, parent_infos))
  1194         return search_result
  1196         return search_result
       
  1197     setattr(cls, "Search", Search)
       
  1198 
       
  1199 cls = PLCOpenParser.GetElementClass("derived", "dataType")
       
  1200 if cls:
       
  1201     def updateElementName(self, old_name, new_name):
       
  1202         if self.name == old_name:
       
  1203             self.name = new_name
       
  1204     setattr(cls, "updateElementName", updateElementName)
       
  1205     
       
  1206     def Search(self, criteria, parent_infos=[]):
       
  1207         return [(tuple(parent_infos),) + result for result in TestTextElement(self.name, criteria)]
  1195     setattr(cls, "Search", Search)
  1208     setattr(cls, "Search", Search)
  1196 
  1209 
  1197 cls = PLCOpenParser.GetElementClass("array", "dataType")
  1210 cls = PLCOpenParser.GetElementClass("array", "dataType")
  1198 if cls:
  1211 if cls:
  1199     setattr(cls, "updateElementName", _updateBaseTypeElementName)
  1212     setattr(cls, "updateElementName", _updateBaseTypeElementName)
  1231         pass
  1244         pass
  1232     setattr(cls, "updateElementName", updateElementName)
  1245     setattr(cls, "updateElementName", updateElementName)
  1233     
  1246     
  1234     def Search(self, criteria, parent_infos=[]):
  1247     def Search(self, criteria, parent_infos=[]):
  1235         search_result = []
  1248         search_result = []
  1236         for i, value in enumerate(self.values.getvalue()):
  1249         for i, value in enumerate(self.xpath("ppx:values/ppx:value", namespaces=PLCOpenParser.NSMAP)):
  1237             for result in TestTextElement(value.getname(), criteria):
  1250             for result in TestTextElement(value.getname(), criteria):
  1238                 search_result.append((tuple(parent_infos + ["value", i]),) + result)
  1251                 search_result.append((tuple(parent_infos + ["value", i]),) + result)
  1239         return search_result
  1252         return search_result
  1240     setattr(cls, "Search", Search)
  1253     setattr(cls, "Search", Search)
  1241 
  1254 
  1243 if cls:
  1256 if cls:
  1244     
  1257     
  1245     def setdescription(self, description):
  1258     def setdescription(self, description):
  1246         doc = self.getdocumentation()
  1259         doc = self.getdocumentation()
  1247         if doc is None:
  1260         if doc is None:
  1248             doc = PLCOpenParser.CreateElement("formattedText")
  1261             doc = PLCOpenParser.CreateElement("documentation", "pou")
  1249             self.setdocumentation(doc)
  1262             self.setdocumentation(doc)
  1250         doc.setanyText(description)
  1263         doc.setanyText(description)
  1251     setattr(cls, "setdescription", setdescription)
  1264     setattr(cls, "setdescription", setdescription)
  1252     
  1265     
  1253     def getdescription(self):
  1266     def getdescription(self):
  1357     
  1370     
  1358     def addpouVar(self, var_type, name, var_class="localVars", location="", description=""):
  1371     def addpouVar(self, var_type, name, var_class="localVars", location="", description=""):
  1359         if self.interface is None:
  1372         if self.interface is None:
  1360             self.interface = PLCOpenParser.CreateElement("interface", "pou")
  1373             self.interface = PLCOpenParser.CreateElement("interface", "pou")
  1361         content = self.interface.getcontent()
  1374         content = self.interface.getcontent()
  1362         if len(content) == 0 or content[-1]["name"] != var_class:
  1375         if len(content) == 0:
  1363             self.appendcontent(PLCOpenParser.CreateElement(var_class, "interface"))
  1376             varlist = PLCOpenParser.CreateElement(var_class, "interface")
       
  1377             self.interface.setcontent([varlist])
       
  1378         elif content[-1] != var_class:
       
  1379             varlist = PLCOpenParser.CreateElement(var_class, "interface")
       
  1380             content[-1].addnext(varlist)
  1364         else:
  1381         else:
  1365             varlist = content[-1]["value"]
  1382             varlist = content[-1]
  1366             variables = varlist.getvariable()
  1383             variables = varlist.getvariable()
  1367             if varlist.getconstant() or varlist.getretain() or len(variables) > 0 and variables[0].getaddress():
  1384             if varlist.getconstant() or varlist.getretain() or len(variables) > 0 and variables[0].getaddress():
  1368                 self.appendcontent(PLCOpenParser.CreateElement(var_class, "interface"))
  1385                 varlist = PLCOpenParser.CreateElement(var_class, "interface")
       
  1386                 content[-1].addnext(varlist)
  1369         var = PLCOpenParser.CreateElement("variable", "varListPlain")
  1387         var = PLCOpenParser.CreateElement("variable", "varListPlain")
  1370         var.setname(name)
  1388         var.setname(name)
  1371         var_type_obj = PLCOpenParser.CreateElement("dataType")
  1389         var_type_obj = PLCOpenParser.CreateElement("type", "variable")
  1372         if var_type in [x for x,y in TypeHierarchy_list if not x.startswith("ANY")]:
  1390         if var_type in [x for x,y in TypeHierarchy_list if not x.startswith("ANY")]:
  1373             var_type_obj.setcontent(PLCOpenParser.CreateElement(
  1391             var_type_obj.setcontent(PLCOpenParser.CreateElement(
  1374                 var_type.lower() if var_type in ["STRING", "WSTRING"]
  1392                 var_type.lower() if var_type in ["STRING", "WSTRING"]
  1375                 else var_type, "dataType"))
  1393                 else var_type, "dataType"))
  1376         else:
  1394         else:
  1379             var_type_obj.setcontent(derived_type)
  1397             var_type_obj.setcontent(derived_type)
  1380         var.settype(var_type_obj)
  1398         var.settype(var_type_obj)
  1381         if location != "":
  1399         if location != "":
  1382             var.setaddress(location)
  1400             var.setaddress(location)
  1383         if description != "":
  1401         if description != "":
  1384             ft = PLCOpenParser.GetElementClass("formattedText")()
  1402             ft = PLCOpenParser.CreateElement("documentation", "variable")
  1385             ft.setanyText(description)
  1403             ft.setanyText(description)
  1386             var.setdocumentation(ft)
  1404             var.setdocumentation(ft)
  1387         
  1405         
  1388         content[-1]["value"].appendvariable(var)
  1406         varlist.appendvariable(var)
  1389     setattr(cls, "addpouVar", addpouVar)
  1407     setattr(cls, "addpouVar", addpouVar)
  1390     
  1408     
  1391     def changepouVar(self, old_type, old_name, new_type, new_name):
  1409     def changepouVar(self, old_type, old_name, new_type, new_name):
  1392         if self.interface is not None:
  1410         if self.interface is not None:
  1393             content = self.interface.getcontent()
  1411             content = self.interface.getcontent()
  1394             for varlist in content:
  1412             for varlist in content:
  1395                 variables = varlist["value"].getvariable()
  1413                 variables = varlist.getvariable()
  1396                 for var in variables:
  1414                 for var in variables:
  1397                     if var.getname() == old_name:
  1415                     if var.getname() == old_name:
  1398                         vartype_content = var.gettype().getcontent()
  1416                         vartype_content = var.gettype().getcontent()
  1399                         if vartype_content.getLocalTag() == "derived" and vartype_content.getname() == old_type:
  1417                         if vartype_content.getLocalTag() == "derived" and vartype_content.getname() == old_type:
  1400                             var.setname(new_name)
  1418                             var.setname(new_name)
  1783         else:
  1801         else:
  1784             raise TypeError, _("Can only generate execution order on FBD networks!")
  1802             raise TypeError, _("Can only generate execution order on FBD networks!")
  1785     setattr(cls, "compileelementExecutionOrder", compileelementExecutionOrder)
  1803     setattr(cls, "compileelementExecutionOrder", compileelementExecutionOrder)
  1786     
  1804     
  1787     def setelementExecutionOrder(self, instance, new_executionOrder):
  1805     def setelementExecutionOrder(self, instance, new_executionOrder):
  1788         if self.contentLgetLocalTag() == "FBD":
  1806         if self.content.getLocalTag() == "FBD":
  1789             old_executionOrder = instance.getexecutionOrderId()
  1807             old_executionOrder = instance.getexecutionOrderId()
  1790             if old_executionOrder is not None and old_executionOrder != 0 and new_executionOrder != 0:
  1808             if old_executionOrder is not None and old_executionOrder != 0 and new_executionOrder != 0:
  1791                 for element in self.content.getcontent():
  1809                 for element in self.content.getcontent():
  1792                     if element != instance and not isinstance(element, PLCOpenParser.GetElementClass("comment", "commonObjects")):
  1810                     if element != instance and not isinstance(element, PLCOpenParser.GetElementClass("comment", "commonObjects")):
  1793                         element_executionOrder = element.getexecutionOrderId()
  1811                         element_executionOrder = element.getexecutionOrderId()
  2146         specific_values = infos["specific_values"]
  2164         specific_values = infos["specific_values"]
  2147         specific_values["name"] = self.getvariable().text
  2165         specific_values["name"] = self.getvariable().text
  2148         _getexecutionOrder(self, specific_values)
  2166         _getexecutionOrder(self, specific_values)
  2149         specific_values["negated"] = self.getnegated()
  2167         specific_values["negated"] = self.getnegated()
  2150         specific_values["edge"] = self.getedge()
  2168         specific_values["edge"] = self.getedge()
  2151         if type == "coil":
  2169         if ld_element_type == "coil":
  2152             specific_values["storage"] = self.getstorage()
  2170             specific_values["storage"] = self.getstorage()
  2153         infos["inputs"].append(_getconnectioninfos(self, self.connectionPointIn, True))
  2171         infos["inputs"].append(_getconnectioninfos(self, self.connectionPointIn, True))
  2154         infos["outputs"].append(_getconnectioninfos(self, self.connectionPointOut))
  2172         infos["outputs"].append(_getconnectioninfos(self, self.connectionPointOut))
  2155         return infos
  2173         return infos
  2156     return getldelementinfos
  2174     return getldelementinfos
  2348             priority = 0
  2366             priority = 0
  2349         specific_values["priority"] = priority
  2367         specific_values["priority"] = priority
  2350         condition = self.getconditionContent()
  2368         condition = self.getconditionContent()
  2351         specific_values["condition_type"] = condition["type"]
  2369         specific_values["condition_type"] = condition["type"]
  2352         if specific_values["condition_type"] == "connection":
  2370         if specific_values["condition_type"] == "connection":
  2353             specific_values["connection"] = _getconnectioninfos(self, condition["value"], True)
  2371             specific_values["connection"] = _getconnectioninfos(self, condition, True)
  2354         else:
  2372         else:
  2355             specific_values["condition"] = condition["value"]
  2373             specific_values["condition"] = condition
  2356         infos["inputs"].append(_getconnectioninfos(self, self.connectionPointIn, True))
  2374         infos["inputs"].append(_getconnectioninfos(self, self.connectionPointIn, True))
  2357         infos["outputs"].append(_getconnectioninfos(self, self.connectionPointOut))
  2375         infos["outputs"].append(_getconnectioninfos(self, self.connectionPointOut))
  2358         return infos
  2376         return infos
  2359     setattr(cls, "getinfos", getinfos)
  2377     setattr(cls, "getinfos", getinfos)
  2360 
  2378