plcopen/plcopen.py
changeset 1333 7f264cc6e75d
parent 1331 38c5de794e62
child 1334 b0c2c4e1c1f1
equal deleted inserted replaced
1329:9d0cb01312f0 1333:7f264cc6e75d
    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: