--- a/plcopen/plcopen.py Fri Sep 27 17:48:05 2013 +0200
+++ b/plcopen/plcopen.py Sun Sep 29 20:17:05 2013 +0200
@@ -158,6 +158,22 @@
+PLCOpen_v1_file = open(os.path.join(os.path.split(__file__)[0], "TC6_XML_V10_B.xsd")) +PLCOpen_v1_xml = PLCOpen_v1_file.read() +PLCOpen_v1_xml = PLCOpen_v1_xml.replace( + "http://www.plcopen.org/xml/tc6.xsd", + "http://www.plcopen.org/xml/tc6_0201") +PLCOpen_v1_xsd = etree.XMLSchema(etree.fromstring(PLCOpen_v1_xml)) +# XPath for file compatibility process +ProjectResourcesXPath = PLCOpen_XPath("ppx:instances/ppx:configurations/ppx:configuration/ppx:resource") +ResourceInstancesXpath = PLCOpen_XPath("ppx:pouInstance | ppx:task/ppx:pouInstance") +TransitionsConditionXPath = PLCOpen_XPath("ppx:types/ppx:pous/ppx:pou/ppx:body/*/ppx:transition/ppx:condition") +ConditionConnectionsXPath = PLCOpen_XPath("ppx:connection") +ActionBlocksXPath = PLCOpen_XPath("ppx:types/ppx:pous/ppx:pou/ppx:body/*/ppx:actionBlock") +ActionBlocksConnectionPointOutXPath = PLCOpen_XPath("ppx:connectionPointOut") def LoadProjectXML(project_xml):
project_xml = project_xml.replace(
"http://www.plcopen.org/xml/tc6.xsd",
@@ -169,11 +185,69 @@
tree, error = PLCOpenParser.LoadXMLString(project_xml)
- # TODO Validate file according to PLCOpen v1 and modify it for
- # compatibility with PLCOpen v2
+ if PLCOpen_v1_xsd.validate(tree): + # Make file compatible with PLCOpen v2 + # Update resource interval value + for resource in ProjectResourcesXPath(tree): + for task in resource.gettask(): + interval = task.get("interval") + if interval is not None: + result = time_model.match(interval) + values = result.groups() + time_values = [int(v) for v in values[:2]] + seconds = float(values[2]) + time_values.extend([int(seconds), int((seconds % 1) * 1000000)]) + if time_values[0] != 0: + text += "%dh"%time_values[0] + if time_values[1] != 0: + text += "%dm"%time_values[1] + if time_values[2] != 0: + text += "%ds"%time_values[2] + if time_values[3] != 0: + if time_values[3] % 1000 != 0: + text += "%.3fms"%(float(time_values[3]) / 1000) + text += "%dms"%(time_values[3] / 1000) + task.set("interval", text) + # Update resources pou instance attributes + for pouInstance in ResourceInstancesXpath(resource): + type_name = pouInstance.get("type") + if type_name is not None: + pouInstance.set("typeName", type_name) + # Update transitions condition + for transition_condition in TransitionsConditionXPath(tree): + connections = ConditionConnectionsXPath(transition_condition) + if len(connections) > 0: + connectionPointIn = PLCOpenParser.CreateElement("connectionPointIn", "condition") + transition_condition.setcontent(connectionPointIn) + connectionPointIn.setrelPositionXY(0, 0) + for connection in connections: + connectionPointIn.append(connection) + for actionBlock in ActionBlocksXPath(tree): + for connectionPointOut in ActionBlocksConnectionPointOutXPath(actionBlock): + actionBlock.remove(connectionPointOut) + for action in actionBlock.getaction(): + action.set("localId", "0") + relPosition = PLCOpenParser.CreateElement("relPosition", "action") + relPosition.set("x", "0") + relPosition.set("y", "0") + action.setrelPosition(relPosition) @@ -693,30 +767,6 @@
cls = PLCOpenParser.GetElementClass("task", "resource")
- def compatibility(self, tree):
- if tree.hasAttribute("interval"):
- interval = GetAttributeValue(tree._attrs["interval"])
- result = time_model.match(interval)
- values = result.groups()
- time_values = [int(v) for v in values[:2]]
- seconds = float(values[2])
- time_values.extend([int(seconds), int((seconds % 1) * 1000000)])
- if time_values[0] != 0:
- text += "%dh"%time_values[0]
- if time_values[1] != 0:
- text += "%dm"%time_values[1]
- if time_values[2] != 0:
- text += "%ds"%time_values[2]
- if time_values[3] != 0:
- if time_values[3] % 1000 != 0:
- text += "%.3fms"%(float(time_values[3]) / 1000)
- text += "%dms"%(time_values[3] / 1000)
- NodeSetAttr(tree, "interval", text)
- setattr(cls, "compatibility", compatibility)
def updateElementName(self, old_name, new_name):
if self.single == old_name:
@@ -742,11 +792,6 @@
cls = PLCOpenParser.GetElementClass("pouInstance")
- def compatibility(self, tree):
- if tree.hasAttribute("type"):
- NodeRenameAttr(tree, "type", "typeName")
- setattr(cls, "compatibility", compatibility)
def updateElementName(self, old_name, new_name):
if self.typeName == old_name:
@@ -2102,23 +2147,6 @@
return _Search([("name", self.getname())], criteria, parent_infos + ["step", self.getlocalId()])
setattr(cls, "Search", Search)
-cls = PLCOpenParser.GetElementClass("condition", "transition")
- def compatibility(self, tree):
- for child in tree.childNodes:
- if child.nodeName == "connection":
- connections.append(child)
- if len(connections) > 0:
- node = CreateNode("connectionPointIn")
- relPosition = CreateNode("relPosition")
- NodeSetAttr(relPosition, "x", "0")
- NodeSetAttr(relPosition, "y", "0")
- node.childNodes.append(relPosition)
- node.childNodes.extend(connections)
- tree.childNodes = [node]
- setattr(cls, "compatibility", compatibility)
cls = _initElementClass("transition", "sfcObjects")
@@ -2282,17 +2310,6 @@
cls = PLCOpenParser.GetElementClass("action", "actionBlock")
- def compatibility(self, tree):
- relPosition = reduce(lambda x, y: x | (y.nodeName == "relPosition"), tree.childNodes, False)
- if not tree.hasAttribute("localId"):
- NodeSetAttr(tree, "localId", "0")
- node = CreateNode("relPosition")
- NodeSetAttr(node, "x", "0")
- NodeSetAttr(node, "y", "0")
- tree.childNodes.insert(0, node)
- setattr(cls, "compatibility", compatibility)
def setreferenceName(self, name):
if self.reference is not None:
self.reference.setname(name)
@@ -2344,12 +2361,6 @@
cls = _initElementClass("actionBlock", "commonObjects", "single")
- def compatibility(self, tree):
- for child in tree.childNodes[:]:
- if child.nodeName == "connectionPointOut":
- tree.childNodes.remove(child)
- setattr(cls, "compatibility", compatibility)
infos = _getelementinfos(self)
infos["type"] = "actionBlock"