156 <body> |
156 <body> |
157 <%(body_type)s>%%s</%(body_type)s> |
157 <%(body_type)s>%%s</%(body_type)s> |
158 </body> |
158 </body> |
159 </pou>""" % locals() |
159 </pou>""" % locals() |
160 |
160 |
|
161 PLCOpen_v1_file = open(os.path.join(os.path.split(__file__)[0], "TC6_XML_V10_B.xsd")) |
|
162 PLCOpen_v1_xml = PLCOpen_v1_file.read() |
|
163 PLCOpen_v1_file.close() |
|
164 PLCOpen_v1_xml = PLCOpen_v1_xml.replace( |
|
165 "http://www.plcopen.org/xml/tc6.xsd", |
|
166 "http://www.plcopen.org/xml/tc6_0201") |
|
167 PLCOpen_v1_xsd = etree.XMLSchema(etree.fromstring(PLCOpen_v1_xml)) |
|
168 |
|
169 # XPath for file compatibility process |
|
170 ProjectResourcesXPath = PLCOpen_XPath("ppx:instances/ppx:configurations/ppx:configuration/ppx:resource") |
|
171 ResourceInstancesXpath = PLCOpen_XPath("ppx:pouInstance | ppx:task/ppx:pouInstance") |
|
172 TransitionsConditionXPath = PLCOpen_XPath("ppx:types/ppx:pous/ppx:pou/ppx:body/*/ppx:transition/ppx:condition") |
|
173 ConditionConnectionsXPath = PLCOpen_XPath("ppx:connection") |
|
174 ActionBlocksXPath = PLCOpen_XPath("ppx:types/ppx:pous/ppx:pou/ppx:body/*/ppx:actionBlock") |
|
175 ActionBlocksConnectionPointOutXPath = PLCOpen_XPath("ppx:connectionPointOut") |
|
176 |
161 def LoadProjectXML(project_xml): |
177 def LoadProjectXML(project_xml): |
162 project_xml = project_xml.replace( |
178 project_xml = project_xml.replace( |
163 "http://www.plcopen.org/xml/tc6.xsd", |
179 "http://www.plcopen.org/xml/tc6.xsd", |
164 "http://www.plcopen.org/xml/tc6_0201") |
180 "http://www.plcopen.org/xml/tc6_0201") |
165 for cre, repl in [ |
181 for cre, repl in [ |
167 (re.compile("(?:]]>)(?!</xhtml:p>)"), "]]></xhtml:p>")]: |
183 (re.compile("(?:]]>)(?!</xhtml:p>)"), "]]></xhtml:p>")]: |
168 project_xml = cre.sub(repl, project_xml) |
184 project_xml = cre.sub(repl, project_xml) |
169 |
185 |
170 try: |
186 try: |
171 tree, error = PLCOpenParser.LoadXMLString(project_xml) |
187 tree, error = PLCOpenParser.LoadXMLString(project_xml) |
172 if error is not None: |
188 if error is None: |
173 # TODO Validate file according to PLCOpen v1 and modify it for |
189 return tree, None |
174 # compatibility with PLCOpen v2 |
190 |
175 return tree, error |
191 if PLCOpen_v1_xsd.validate(tree): |
176 return tree, None |
192 # Make file compatible with PLCOpen v2 |
|
193 |
|
194 # Update resource interval value |
|
195 for resource in ProjectResourcesXPath(tree): |
|
196 for task in resource.gettask(): |
|
197 interval = task.get("interval") |
|
198 if interval is not None: |
|
199 result = time_model.match(interval) |
|
200 if result is not None: |
|
201 values = result.groups() |
|
202 time_values = [int(v) for v in values[:2]] |
|
203 seconds = float(values[2]) |
|
204 time_values.extend([int(seconds), int((seconds % 1) * 1000000)]) |
|
205 text = "T#" |
|
206 if time_values[0] != 0: |
|
207 text += "%dh"%time_values[0] |
|
208 if time_values[1] != 0: |
|
209 text += "%dm"%time_values[1] |
|
210 if time_values[2] != 0: |
|
211 text += "%ds"%time_values[2] |
|
212 if time_values[3] != 0: |
|
213 if time_values[3] % 1000 != 0: |
|
214 text += "%.3fms"%(float(time_values[3]) / 1000) |
|
215 else: |
|
216 text += "%dms"%(time_values[3] / 1000) |
|
217 task.set("interval", text) |
|
218 |
|
219 # Update resources pou instance attributes |
|
220 for pouInstance in ResourceInstancesXpath(resource): |
|
221 type_name = pouInstance.get("type") |
|
222 if type_name is not None: |
|
223 pouInstance.set("typeName", type_name) |
|
224 |
|
225 # Update transitions condition |
|
226 for transition_condition in TransitionsConditionXPath(tree): |
|
227 connections = ConditionConnectionsXPath(transition_condition) |
|
228 if len(connections) > 0: |
|
229 connectionPointIn = PLCOpenParser.CreateElement("connectionPointIn", "condition") |
|
230 transition_condition.setcontent(connectionPointIn) |
|
231 connectionPointIn.setrelPositionXY(0, 0) |
|
232 for connection in connections: |
|
233 connectionPointIn.append(connection) |
|
234 |
|
235 # Update actionBlocks |
|
236 for actionBlock in ActionBlocksXPath(tree): |
|
237 for connectionPointOut in ActionBlocksConnectionPointOutXPath(actionBlock): |
|
238 actionBlock.remove(connectionPointOut) |
|
239 |
|
240 for action in actionBlock.getaction(): |
|
241 action.set("localId", "0") |
|
242 relPosition = PLCOpenParser.CreateElement("relPosition", "action") |
|
243 relPosition.set("x", "0") |
|
244 relPosition.set("y", "0") |
|
245 action.setrelPosition(relPosition) |
|
246 |
|
247 return tree, None |
|
248 |
|
249 return tree, error |
|
250 |
177 except Exception, e: |
251 except Exception, e: |
178 return None, e.message |
252 return None, e.message |
179 |
253 |
180 def LoadProject(filepath): |
254 def LoadProject(filepath): |
181 project_file = open(filepath) |
255 project_file = open(filepath) |
691 return search_result |
765 return search_result |
692 setattr(cls, "Search", Search) |
766 setattr(cls, "Search", Search) |
693 |
767 |
694 cls = PLCOpenParser.GetElementClass("task", "resource") |
768 cls = PLCOpenParser.GetElementClass("task", "resource") |
695 if cls: |
769 if cls: |
696 def compatibility(self, tree): |
|
697 if tree.hasAttribute("interval"): |
|
698 interval = GetAttributeValue(tree._attrs["interval"]) |
|
699 result = time_model.match(interval) |
|
700 if result is not None: |
|
701 values = result.groups() |
|
702 time_values = [int(v) for v in values[:2]] |
|
703 seconds = float(values[2]) |
|
704 time_values.extend([int(seconds), int((seconds % 1) * 1000000)]) |
|
705 text = "t#" |
|
706 if time_values[0] != 0: |
|
707 text += "%dh"%time_values[0] |
|
708 if time_values[1] != 0: |
|
709 text += "%dm"%time_values[1] |
|
710 if time_values[2] != 0: |
|
711 text += "%ds"%time_values[2] |
|
712 if time_values[3] != 0: |
|
713 if time_values[3] % 1000 != 0: |
|
714 text += "%.3fms"%(float(time_values[3]) / 1000) |
|
715 else: |
|
716 text += "%dms"%(time_values[3] / 1000) |
|
717 NodeSetAttr(tree, "interval", text) |
|
718 setattr(cls, "compatibility", compatibility) |
|
719 |
|
720 def updateElementName(self, old_name, new_name): |
770 def updateElementName(self, old_name, new_name): |
721 if self.single == old_name: |
771 if self.single == old_name: |
722 self.single = new_name |
772 self.single = new_name |
723 if self.interval == old_name: |
773 if self.interval == old_name: |
724 self.interval = new_name |
774 self.interval = new_name |
740 criteria, parent_infos) |
790 criteria, parent_infos) |
741 setattr(cls, "Search", Search) |
791 setattr(cls, "Search", Search) |
742 |
792 |
743 cls = PLCOpenParser.GetElementClass("pouInstance") |
793 cls = PLCOpenParser.GetElementClass("pouInstance") |
744 if cls: |
794 if cls: |
745 def compatibility(self, tree): |
|
746 if tree.hasAttribute("type"): |
|
747 NodeRenameAttr(tree, "type", "typeName") |
|
748 setattr(cls, "compatibility", compatibility) |
|
749 |
|
750 def updateElementName(self, old_name, new_name): |
795 def updateElementName(self, old_name, new_name): |
751 if self.typeName == old_name: |
796 if self.typeName == old_name: |
752 self.typeName = new_name |
797 self.typeName = new_name |
753 setattr(cls, "updateElementName", updateElementName) |
798 setattr(cls, "updateElementName", updateElementName) |
754 |
799 |
2100 |
2145 |
2101 def Search(self, criteria, parent_infos=[]): |
2146 def Search(self, criteria, parent_infos=[]): |
2102 return _Search([("name", self.getname())], criteria, parent_infos + ["step", self.getlocalId()]) |
2147 return _Search([("name", self.getname())], criteria, parent_infos + ["step", self.getlocalId()]) |
2103 setattr(cls, "Search", Search) |
2148 setattr(cls, "Search", Search) |
2104 |
2149 |
2105 cls = PLCOpenParser.GetElementClass("condition", "transition") |
|
2106 if cls: |
|
2107 def compatibility(self, tree): |
|
2108 connections = [] |
|
2109 for child in tree.childNodes: |
|
2110 if child.nodeName == "connection": |
|
2111 connections.append(child) |
|
2112 if len(connections) > 0: |
|
2113 node = CreateNode("connectionPointIn") |
|
2114 relPosition = CreateNode("relPosition") |
|
2115 NodeSetAttr(relPosition, "x", "0") |
|
2116 NodeSetAttr(relPosition, "y", "0") |
|
2117 node.childNodes.append(relPosition) |
|
2118 node.childNodes.extend(connections) |
|
2119 tree.childNodes = [node] |
|
2120 setattr(cls, "compatibility", compatibility) |
|
2121 |
|
2122 cls = _initElementClass("transition", "sfcObjects") |
2150 cls = _initElementClass("transition", "sfcObjects") |
2123 if cls: |
2151 if cls: |
2124 def getinfos(self): |
2152 def getinfos(self): |
2125 infos = _getelementinfos(self) |
2153 infos = _getelementinfos(self) |
2126 infos["type"] = "transition" |
2154 infos["type"] = "transition" |
2280 return _Search([("target", self.gettargetName())], criteria, parent_infos + ["jump", self.getlocalId()]) |
2308 return _Search([("target", self.gettargetName())], criteria, parent_infos + ["jump", self.getlocalId()]) |
2281 setattr(cls, "Search", Search) |
2309 setattr(cls, "Search", Search) |
2282 |
2310 |
2283 cls = PLCOpenParser.GetElementClass("action", "actionBlock") |
2311 cls = PLCOpenParser.GetElementClass("action", "actionBlock") |
2284 if cls: |
2312 if cls: |
2285 def compatibility(self, tree): |
|
2286 relPosition = reduce(lambda x, y: x | (y.nodeName == "relPosition"), tree.childNodes, False) |
|
2287 if not tree.hasAttribute("localId"): |
|
2288 NodeSetAttr(tree, "localId", "0") |
|
2289 if not relPosition: |
|
2290 node = CreateNode("relPosition") |
|
2291 NodeSetAttr(node, "x", "0") |
|
2292 NodeSetAttr(node, "y", "0") |
|
2293 tree.childNodes.insert(0, node) |
|
2294 setattr(cls, "compatibility", compatibility) |
|
2295 |
|
2296 def setreferenceName(self, name): |
2313 def setreferenceName(self, name): |
2297 if self.reference is not None: |
2314 if self.reference is not None: |
2298 self.reference.setname(name) |
2315 self.reference.setname(name) |
2299 setattr(cls, "setreferenceName", setreferenceName) |
2316 setattr(cls, "setreferenceName", setreferenceName) |
2300 |
2317 |
2342 criteria, parent_infos) |
2359 criteria, parent_infos) |
2343 setattr(cls, "Search", Search) |
2360 setattr(cls, "Search", Search) |
2344 |
2361 |
2345 cls = _initElementClass("actionBlock", "commonObjects", "single") |
2362 cls = _initElementClass("actionBlock", "commonObjects", "single") |
2346 if cls: |
2363 if cls: |
2347 def compatibility(self, tree): |
|
2348 for child in tree.childNodes[:]: |
|
2349 if child.nodeName == "connectionPointOut": |
|
2350 tree.childNodes.remove(child) |
|
2351 setattr(cls, "compatibility", compatibility) |
|
2352 |
|
2353 def getinfos(self): |
2364 def getinfos(self): |
2354 infos = _getelementinfos(self) |
2365 infos = _getelementinfos(self) |
2355 infos["type"] = "actionBlock" |
2366 infos["type"] = "actionBlock" |
2356 infos["specific_values"]["actions"] = self.getactions() |
2367 infos["specific_values"]["actions"] = self.getactions() |
2357 infos["inputs"].append(_getconnectioninfos(self, self.connectionPointIn, True)) |
2368 infos["inputs"].append(_getconnectioninfos(self, self.connectionPointIn, True)) |