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 |