24 |
24 |
25 from xmlclass import * |
25 from xmlclass import * |
26 from types import * |
26 from types import * |
27 import os, re |
27 import os, re |
28 from lxml import etree |
28 from lxml import etree |
|
29 from collections import OrderedDict |
|
30 |
29 """ |
31 """ |
30 Dictionary that makes the relation between var names in plcopen and displayed values |
32 Dictionary that makes the relation between var names in plcopen and displayed values |
31 """ |
33 """ |
32 VarTypes = {"Local" : "localVars", "Temp" : "tempVars", "Input" : "inputVars", |
34 VarTypes = {"Local" : "localVars", "Temp" : "tempVars", "Input" : "inputVars", |
33 "Output" : "outputVars", "InOut" : "inOutVars", "External" : "externalVars", |
35 "Output" : "outputVars", "InOut" : "inOutVars", "External" : "externalVars", |
154 <body> |
156 <body> |
155 <%(body_type)s>%%s</%(body_type)s> |
157 <%(body_type)s>%%s</%(body_type)s> |
156 </body> |
158 </body> |
157 </pou>""" % locals() |
159 </pou>""" % locals() |
158 |
160 |
159 def LoadProject(filepath): |
161 def LoadProjectXML(project_xml): |
160 project_file = open(filepath) |
162 project_xml = project_xml.replace( |
161 project_xml = project_file.read().replace( |
|
162 "http://www.plcopen.org/xml/tc6.xsd", |
163 "http://www.plcopen.org/xml/tc6.xsd", |
163 "http://www.plcopen.org/xml/tc6_0201") |
164 "http://www.plcopen.org/xml/tc6_0201") |
164 for cre, repl in [ |
165 for cre, repl in [ |
165 (re.compile("(?<!<xhtml:p>)(?:<!\[CDATA\[)"), "<xhtml:p><![CDATA["), |
166 (re.compile("(?<!<xhtml:p>)(?:<!\[CDATA\[)"), "<xhtml:p><![CDATA["), |
166 (re.compile("(?:]]>)(?!</xhtml:p>)"), "]]></xhtml:p>")]: |
167 (re.compile("(?:]]>)(?!</xhtml:p>)"), "]]></xhtml:p>")]: |
167 project_xml = cre.sub(repl, project_xml) |
168 project_xml = cre.sub(repl, project_xml) |
|
169 |
|
170 try: |
|
171 tree, error = PLCOpenParser.LoadXMLString(project_xml) |
|
172 if error is not None: |
|
173 # TODO Validate file according to PLCOpen v1 and modify it for |
|
174 # compatibility with PLCOpen v2 |
|
175 return tree, error |
|
176 return tree, None |
|
177 except Exception, e: |
|
178 return None, e.message |
|
179 |
|
180 def LoadProject(filepath): |
|
181 project_file = open(filepath) |
|
182 project_xml = project_file.read() |
168 project_file.close() |
183 project_file.close() |
169 |
184 return LoadProjectXML(project_xml) |
170 return etree.fromstring(project_xml, PLCOpenParser) |
|
171 |
185 |
172 project_pou_xpath = PLCOpen_XPath("/ppx:project/ppx:types/ppx:pous/ppx:pou") |
186 project_pou_xpath = PLCOpen_XPath("/ppx:project/ppx:types/ppx:pous/ppx:pou") |
173 def LoadPou(xml_string): |
187 def LoadPou(xml_string): |
174 root = etree.fromstring( |
188 root, error = LoadProjectXML(LOAD_POU_PROJECT_TEMPLATE % xml_string) |
175 LOAD_POU_PROJECT_TEMPLATE % xml_string, |
189 return project_pou_xpath(root)[0], error |
176 PLCOpenParser) |
|
177 return project_pou_xpath(root)[0] |
|
178 |
190 |
179 project_pou_instances_xpath = { |
191 project_pou_instances_xpath = { |
180 body_type: PLCOpen_XPath( |
192 body_type: PLCOpen_XPath( |
181 "/ppx:project/ppx:types/ppx:pous/ppx:pou[@name='paste_pou']/ppx:body/ppx:%s/*" % body_type) |
193 "/ppx:project/ppx:types/ppx:pous/ppx:pou[@name='paste_pou']/ppx:body/ppx:%s/*" % body_type) |
182 for body_type in ["FBD", "LD", "SFC"]} |
194 for body_type in ["FBD", "LD", "SFC"]} |
183 def LoadPouInstances(xml_string, body_type): |
195 def LoadPouInstances(xml_string, body_type): |
184 root = etree.fromstring( |
196 root, error = LoadProjectXML( |
185 LOAD_POU_INSTANCES_PROJECT_TEMPLATE(body_type) % xml_string, |
197 LOAD_POU_INSTANCES_PROJECT_TEMPLATE(body_type) % xml_string) |
186 PLCOpenParser) |
198 return project_pou_instances_xpath[body_type](root), error |
187 return project_pou_instances_xpath[body_type](root) |
|
188 |
199 |
189 def SaveProject(project, filepath): |
200 def SaveProject(project, filepath): |
190 project_file = open(filepath, 'w') |
201 project_file = open(filepath, 'w') |
191 project_file.write(etree.tostring( |
202 project_file.write(etree.tostring( |
192 project, |
203 project, |
1078 if len(self.body) > 0: |
1089 if len(self.body) > 0: |
1079 return self.body[0].getcontentInstance(id) |
1090 return self.body[0].getcontentInstance(id) |
1080 return None |
1091 return None |
1081 setattr(cls, "getinstance", getinstance) |
1092 setattr(cls, "getinstance", getinstance) |
1082 |
1093 |
1083 def getrandomInstance(self, exclude): |
1094 def getinstancesIds(self): |
1084 if len(self.body) > 0: |
1095 if len(self.body) > 0: |
1085 return self.body[0].getcontentRandomInstance(exclude) |
1096 return self.body[0].getcontentInstancesIds() |
1086 return None |
1097 return [] |
1087 setattr(cls, "getrandomInstance", getrandomInstance) |
1098 setattr(cls, "getinstancesIds", getinstancesIds) |
1088 |
1099 |
1089 def getinstanceByName(self, name): |
1100 def getinstanceByName(self, name): |
1090 if len(self.body) > 0: |
1101 if len(self.body) > 0: |
1091 return self.body[0].getcontentInstanceByName(name) |
1102 return self.body[0].getcontentInstanceByName(name) |
1092 return None |
1103 return None |
1598 return None |
1609 return None |
1599 else: |
1610 else: |
1600 raise TypeError, _("%s body don't have instances!")%self.content.getLocalTag() |
1611 raise TypeError, _("%s body don't have instances!")%self.content.getLocalTag() |
1601 setattr(cls, "getcontentInstance", getcontentInstance) |
1612 setattr(cls, "getcontentInstance", getcontentInstance) |
1602 |
1613 |
1603 def getcontentRandomInstance(self, exclude): |
1614 def getcontentInstancesIds(self): |
1604 if self.content.getLocalTag() in ["LD","FBD","SFC"]: |
1615 if self.content.getLocalTag() in ["LD","FBD","SFC"]: |
1605 instance = self.content.xpath("*%s[position()=1]" % |
1616 return OrderedDict([(instance.getlocalId(), True) |
1606 ("[not(%s)]" % " or ".join( |
1617 for instance in self.content]) |
1607 map(lambda x: "@localId=%d" % x, exclude)) |
|
1608 if len(exclude) > 0 else "")) |
|
1609 if len(instance) > 0: |
|
1610 return instance[0] |
|
1611 return None |
|
1612 else: |
1618 else: |
1613 raise TypeError, _("%s body don't have instances!")%self.content.getLocalTag() |
1619 raise TypeError, _("%s body don't have instances!")%self.content.getLocalTag() |
1614 setattr(cls, "getcontentRandomInstance", getcontentRandomInstance) |
1620 setattr(cls, "getcontentInstancesIds", getcontentInstancesIds) |
1615 |
1621 |
1616 def getcontentInstanceByName(self, name): |
1622 def getcontentInstanceByName(self, name): |
1617 if self.content.getLocalTag() in ["LD","FBD","SFC"]: |
1623 if self.content.getLocalTag() in ["LD","FBD","SFC"]: |
1618 instance = instance_by_name_xpath(self.content) |
1624 instance = instance_by_name_xpath(self.content) |
1619 if len(instance) > 0: |
1625 if len(instance) > 0: |