# HG changeset patch # User laurent # Date 1248431388 -7200 # Node ID 6a72016d721a1b710fc50fbf56e2856de90ead4d # Parent 7ea1f5094df34f3dfb1e18650c1ea8e484a7afe0 Adding support for plcopen version 2.01 diff -r 7ea1f5094df3 -r 6a72016d721a DataTypeEditor.py --- a/DataTypeEditor.py Fri Jul 24 11:55:46 2009 +0200 +++ b/DataTypeEditor.py Fri Jul 24 12:29:48 2009 +0200 @@ -597,8 +597,8 @@ elif type_infos["type"] == "Subrange": self.SubrangeBaseType.SetStringSelection(type_infos["base_type"]) self.RefreshBoundsRange() - self.SubrangeMinimum.SetValue(type_infos["min"]) - self.SubrangeMaximum.SetValue(type_infos["max"]) + self.SubrangeMinimum.SetValue(int(type_infos["min"])) + self.SubrangeMaximum.SetValue(int(type_infos["max"])) self.RefreshSubrangeInitialValueRange() if type_infos["initial"] != "": self.SubrangeInitialValue.SetValue(int(type_infos["initial"])) @@ -610,7 +610,7 @@ self.EnumeratedInitialValue.SetStringSelection(type_infos["initial"]) elif type_infos["type"] == "Array": self.ArrayBaseType.SetStringSelection(type_infos["base_type"]) - self.ArrayDimensions.SetStrings(map(lambda x : "..".join(map(str, x)), type_infos["dimensions"])) + self.ArrayDimensions.SetStrings(map(lambda x : "..".join(x), type_infos["dimensions"])) self.ArrayInitialValue.SetValue(type_infos["initial"]) elif type_infos["type"] == "Structure": self.StructureElementsTable.SetData(type_infos["elements"]) @@ -849,8 +849,8 @@ infos["initial"] = self.DirectlyInitialValue.GetValue() elif selected == "Subrange": infos["base_type"] = self.SubrangeBaseType.GetStringSelection() - infos["min"] = self.SubrangeMinimum.GetValue() - infos["max"] = self.SubrangeMaximum.GetValue() + infos["min"] = str(self.SubrangeMinimum.GetValue()) + infos["max"] = str(self.SubrangeMaximum.GetValue()) initial_value = self.SubrangeInitialValue.GetValue() if initial_value == infos["min"]: infos["initial"] = "" @@ -877,7 +877,7 @@ message.Destroy() self.RefreshView() return - infos["dimensions"].append(map(int, bounds)) + infos["dimensions"].append(bounds) infos["initial"] = self.ArrayInitialValue.GetValue() elif selected == "Structure": infos["elements"] = self.StructureElementsTable.GetData() diff -r 7ea1f5094df3 -r 6a72016d721a PLCControler.py --- a/PLCControler.py Fri Jul 24 11:55:46 2009 +0200 +++ b/PLCControler.py Fri Jul 24 12:29:48 2009 +0200 @@ -369,11 +369,11 @@ resource_infos = {"name" : resource.getname(), "type": ITEM_RESOURCE, "values": []} for task in resource.gettask(): for pou in task.getpouInstance(): - instance_infos = self.GetPouTopology(pou.getname(), pou.gettype(), debug=debug) + instance_infos = self.GetPouTopology(pou.getname(), pou.gettypeName(), debug=debug) if instance_infos is not None: resource_infos["values"].append(instance_infos) for pou in resource.getpouInstance(): - instance_infos = self.GetPouTopology(pou.getname(), pou.gettype(), debug=debug) + instance_infos = self.GetPouTopology(pou.getname(), pou.gettypeName(), debug=debug) if instance_infos is not None: resource_infos["values"].append(instance_infos) for varlist in resource.getglobalVars(): @@ -2266,7 +2266,7 @@ transition.connectionPointOut.setrelPositionXY(position.x, position.y) elif infos.get("type", None) == "connection" and param == "connection" and value: transition.setconditionContent("connection", None) - self.SetConnectionWires(transition, value) + self.SetConnectionWires(transition.condition.content["value"], value) def AddEditedElementDivergence(self, tagname, id, type): element = self.GetEditedElement(tagname) @@ -2426,17 +2426,19 @@ new_task.setname(task["Name"]) if task["Single"] != "": new_task.setsingle(task["Single"]) - result = duration_model.match(task["Interval"]).groups() - if reduce(lambda x, y: x or y != None, result): - values = [] - for value in result[:-1]: - if value != None: - values.append(int(value)) - else: - values.append(0) - if result[-1] is not None: - values.append(int(float(result[-1]) * 1000)) - new_task.setinterval(datetime.time(*values)) +## result = duration_model.match(task["Interval"]).groups() +## if reduce(lambda x, y: x or y != None, result): +## values = [] +## for value in result[:-1]: +## if value != None: +## values.append(int(value)) +## else: +## values.append(0) +## if result[-1] is not None: +## values.append(int(float(result[-1]) * 1000)) +## new_task.setinterval(datetime.time(*values)) + if task["Interval"] != "": + new_task.setinterval(task["Interval"]) new_task.setpriority(int(task["Priority"])) if task["Name"] != "": task_list[task["Name"]] = new_task @@ -2444,7 +2446,7 @@ for instance in instances: new_instance = plcopen.pouInstance() new_instance.setname(instance["Name"]) - new_instance.settype(instance["Type"]) + new_instance.settypeName(instance["Type"]) if instance["Task"] != "": task_list[instance["Task"]].appendpouInstance(new_instance) else: @@ -2467,19 +2469,20 @@ new_task["Single"] = "" interval = task.getinterval() if interval: - text = "" - if interval.hour != 0: - text += "%dh"%interval.hour - if interval.minute != 0: - text += "%dm"%interval.minute - if interval.second != 0: - text += "%ds"%interval.second - if interval.microsecond != 0: - if interval.microsecond % 1000 != 0: - text += "%.3fms"%(float(interval.microsecond) / 1000) - else: - text += "%dms"%(interval.microsecond / 1000) - new_task["Interval"] = text +## text = "" +## if interval.hour != 0: +## text += "%dh"%interval.hour +## if interval.minute != 0: +## text += "%dm"%interval.minute +## if interval.second != 0: +## text += "%ds"%interval.second +## if interval.microsecond != 0: +## if interval.microsecond % 1000 != 0: +## text += "%.3fms"%(float(interval.microsecond) / 1000) +## else: +## text += "%dms"%(interval.microsecond / 1000) +## new_task["Interval"] = text + new_task["Interval"] = interval else: new_task["Interval"] = "" new_task["Priority"] = str(task.getpriority()) @@ -2487,13 +2490,13 @@ for instance in task.getpouInstance(): new_instance = {} new_instance["Name"] = instance.getname() - new_instance["Type"] = instance.gettype() + new_instance["Type"] = instance.gettypeName() new_instance["Task"] = task.getname() instances_data.append(new_instance) for instance in instances: new_instance = {} new_instance["Name"] = instance.getname() - new_instance["Type"] = instance.gettype() + new_instance["Type"] = instance.gettypeName() new_instance["Task"] = "" instances_data.append(new_instance) return tasks_data, instances_data diff -r 7ea1f5094df3 -r 6a72016d721a PLCGenerator.py --- a/PLCGenerator.py Fri Jul 24 11:55:46 2009 +0200 +++ b/PLCGenerator.py Fri Jul 24 12:29:48 2009 +0200 @@ -143,9 +143,9 @@ max_value = basetype_content["value"].range.getupper() datatype_def += [(basetype_name, (tagname, "base")), (" (", ()), - ("%d"%min_value, (tagname, "lower")), + ("%s"%min_value, (tagname, "lower")), ("..", ()), - ("%d"%max_value, (tagname, "upper")), + ("%s"%max_value, (tagname, "upper")), (")",())] # Data type is an enumerated type elif basetype_content["name"] == "enum": @@ -167,9 +167,9 @@ # Array derived directly from an elementary type else: basetype_name = base_type["name"] - dimensions = [[("%d"%dimension.getlower(), (tagname, "range", i, "lower")), + dimensions = [[("%s"%dimension.getlower(), (tagname, "range", i, "lower")), ("..", ()), - ("%d"%dimension.getupper(), (tagname, "range", i, "upper"))] + ("%s"%dimension.getupper(), (tagname, "range", i, "upper"))] for i, dimension in enumerate(basetype_content["value"].getdimension())] datatype_def += [("ARRAY [", ())] datatype_def += JoinList([(",", ())], dimensions) @@ -356,16 +356,19 @@ # Interval argument if exists interval = task.getinterval() if interval: - resrce += [("INTERVAL := t#", ())] - if interval.hour != 0: - resrce += [("%dh"%interval.hour, (tagname, "task", task_number, "interval", "hour"))] - if interval.minute != 0: - resrce += [("%dm"%interval.minute, (tagname, "task", task_number, "interval", "minute"))] - if interval.second != 0: - resrce += [("%ds"%interval.second, (tagname, "task", task_number, "interval", "second"))] - if interval.microsecond != 0: - resrce += [("%dms"%(interval.microsecond / 1000), (tagname, "task", task_number, "interval", "millisecond"))] - resrce += [(",", ())] + resrce += [("INTERVAL := ", ()), + (interval, (tagname, "task", task_number, "interval")), + (",", ())] +## resrce += [("INTERVAL := t#", ())] +## if interval.hour != 0: +## resrce += [("%dh"%interval.hour, (tagname, "task", task_number, "interval", "hour"))] +## if interval.minute != 0: +## resrce += [("%dm"%interval.minute, (tagname, "task", task_number, "interval", "minute"))] +## if interval.second != 0: +## resrce += [("%ds"%interval.second, (tagname, "task", task_number, "interval", "second"))] +## if interval.microsecond != 0: +## resrce += [("%dms"%(interval.microsecond / 1000), (tagname, "task", task_number, "interval", "millisecond"))] +## resrce += [(",", ())] # Priority argument resrce += [("PRIORITY := ", ()), ("%d"%task.getpriority(), (tagname, "task", task_number, "priority")), @@ -380,7 +383,7 @@ (" WITH ", ()), (task.getname(), (tagname, "instance", instance_number, "task")), (" : ", ()), - (instance.gettype(), (tagname, "instance", instance_number, "type")), + (instance.gettypeName(), (tagname, "instance", instance_number, "type")), (";\n", ())] instance_number += 1 # Generate any program assign to no task @@ -388,7 +391,7 @@ resrce += [(" PROGRAM ", ()), (instance.getname(), (tagname, "instance", instance_number, "name")), (" : ", ()), - (instance.gettype(), (tagname, "instance", instance_number, "type")), + (instance.gettypeName(), (tagname, "instance", instance_number, "type")), (";\n", ())] instance_number += 1 resrce += [(" END_RESOURCE\n", ())] @@ -532,6 +535,8 @@ interface = pou.getinterface() if interface is not None: body = pou.getbody() + if isinstance(body, ListType): + body = body[0] body_content = body.getcontent() if self.Type == "FUNCTION": returntype_content = interface.getreturnType().getcontent() @@ -596,6 +601,8 @@ def ComputeConnectionTypes(self, pou): body = pou.getbody() + if isinstance(body, ListType): + body = body[0] body_content = body.getcontent() body_type = body_content["name"] if body_type in ["FBD", "LD", "SFC"]: @@ -684,56 +691,61 @@ raise PLCGenException, "No connector found corresponding to \"%s\" continuation in \"%s\" POU"%(name, self.Name) elif isinstance(instance, plcopen.fbdObjects_block): block_infos = self.GetBlockType(instance.gettypeName()) - undefined = {} - for variable in instance.outputVariables.getvariable(): - output_name = variable.getformalParameter() - if output_name == "ENO": - for connection in self.ExtractRelatedConnections(variable.connectionPointOut): - self.ConnectionTypes[connection] = "BOOL" - else: - for oname, otype, oqualifier in block_infos["outputs"]: - if output_name == oname: - if otype.startswith("ANY"): - if not undefined.has_key(otype): - undefined[otype] = [] - undefined[otype].append(variable.connectionPointOut) - elif not self.ConnectionTypes.has_key(variable.connectionPointOut): - for connection in self.ExtractRelatedConnections(variable.connectionPointOut): - self.ConnectionTypes[connection] = otype - for variable in instance.inputVariables.getvariable(): - input_name = variable.getformalParameter() - if input_name == "EN": - for connection in self.ExtractRelatedConnections(variable.connectionPointIn): - self.ConnectionTypes[connection] = "BOOL" - for iname, itype, iqualifier in block_infos["inputs"]: - if input_name == iname: - connected = self.GetConnectedConnector(variable.connectionPointIn, body) - if itype.startswith("ANY"): - if not undefined.has_key(itype): - undefined[itype] = [] - undefined[itype].append(variable.connectionPointIn) - if connected: - undefined[itype].append(connected) + if block_infos is not None: + undefined = {} + for variable in instance.outputVariables.getvariable(): + output_name = variable.getformalParameter() + if output_name == "ENO": + for connection in self.ExtractRelatedConnections(variable.connectionPointOut): + self.ConnectionTypes[connection] = "BOOL" + else: + for oname, otype, oqualifier in block_infos["outputs"]: + if output_name == oname: + if otype.startswith("ANY"): + if not undefined.has_key(otype): + undefined[otype] = [] + undefined[otype].append(variable.connectionPointOut) + elif not self.ConnectionTypes.has_key(variable.connectionPointOut): + for connection in self.ExtractRelatedConnections(variable.connectionPointOut): + self.ConnectionTypes[connection] = otype + for variable in instance.inputVariables.getvariable(): + input_name = variable.getformalParameter() + if input_name == "EN": + for connection in self.ExtractRelatedConnections(variable.connectionPointIn): + self.ConnectionTypes[connection] = "BOOL" + for iname, itype, iqualifier in block_infos["inputs"]: + if input_name == iname: + connected = self.GetConnectedConnector(variable.connectionPointIn, body) + if itype.startswith("ANY"): + if not undefined.has_key(itype): + undefined[itype] = [] + undefined[itype].append(variable.connectionPointIn) + if connected: + undefined[itype].append(connected) + else: + self.ConnectionTypes[variable.connectionPointIn] = itype + if connected and not self.ConnectionTypes.has_key(connected): + for connection in self.ExtractRelatedConnections(connected): + self.ConnectionTypes[connection] = itype + for var_type, connections in undefined.items(): + related = [] + for connection in connections: + if self.ConnectionTypes.has_key(connection): + var_type = self.ConnectionTypes[connection] else: - self.ConnectionTypes[variable.connectionPointIn] = itype - if connected and not self.ConnectionTypes.has_key(connected): - for connection in self.ExtractRelatedConnections(connected): - self.ConnectionTypes[connection] = itype - for var_type, connections in undefined.items(): - related = [] - for connection in connections: - if self.ConnectionTypes.has_key(connection): - var_type = self.ConnectionTypes[connection] + related.extend(self.ExtractRelatedConnections(connection)) + if var_type.startswith("ANY") and len(related) > 0: + self.RelatedConnections.append(related) else: - related.extend(self.ExtractRelatedConnections(connection)) - if var_type.startswith("ANY") and len(related) > 0: - self.RelatedConnections.append(related) - else: - for connection in related: - self.ConnectionTypes[connection] = var_type - + for connection in related: + self.ConnectionTypes[connection] = var_type + else: + raise PLCGenException, _("No informations found for \"%s\" block")%(instance.gettypeName()) + def ComputeProgram(self, pou): body = pou.getbody() + if isinstance(body, ListType): + body = body[0] body_content = body.getcontent() body_type = body_content["name"] if body_type in ["IL","ST"]: @@ -958,7 +970,10 @@ connections = connectionPointIn.getconnections() if connections is not None and len(connections) == 1: instanceLocalId = connections[0].getrefLocalId() - return pou.body.getcontentInstance(instanceLocalId) + body = pou.getbody() + if isinstance(body, ListType): + body = body[0] + return body.getcontentInstance(instanceLocalId) return None def ExtractConvergenceInputs(self, convergence, pou): @@ -967,7 +982,10 @@ connections = connectionPointIn.getconnections() if len(connections) == 1: instanceLocalId = connections[0].getrefLocalId() - instances.append(pou.body.getcontentInstance(instanceLocalId)) + body = pou.getbody() + if isinstance(body, ListType): + body = body[0] + instances.append(body.getcontentInstance(instanceLocalId)) return instances def GenerateSFCStep(self, step, pou): @@ -984,7 +1002,10 @@ connections = step.connectionPointIn.getconnections() if len(connections) == 1: instanceLocalId = connections[0].getrefLocalId() - instance = pou.body.getcontentInstance(instanceLocalId) + body = pou.getbody() + if isinstance(body, ListType): + body = body[0] + instance = body.getcontentInstance(instanceLocalId) if isinstance(instance, plcopen.sfcObjects_transition): instances.append(instance) elif isinstance(instance, plcopen.sfcObjects_selectionConvergence): @@ -1010,7 +1031,10 @@ connections = jump.connectionPointIn.getconnections() if len(connections) == 1: instanceLocalId = connections[0].getrefLocalId() - instance = pou.body.getcontentInstance(instanceLocalId) + body = pou.getbody() + if isinstance(body, ListType): + body = body[0] + instance = body.getcontentInstance(instanceLocalId) if isinstance(instance, plcopen.sfcObjects_transition): instances.append(instance) elif isinstance(instance, plcopen.sfcObjects_selectionConvergence): @@ -1032,7 +1056,10 @@ connections = actionBlock.connectionPointIn.getconnections() if connections is not None and len(connections) == 1: stepLocalId = connections[0].getrefLocalId() - step = pou.body.getcontentInstance(stepLocalId) + body = pou.getbody() + if isinstance(body, ListType): + body = body[0] + step = body.getcontentInstance(stepLocalId) self.GenerateSFCStep(step, pou) step_name = step.getname() if step_name in self.SFCNetworks["Steps"].keys(): @@ -1073,7 +1100,10 @@ connections = transition.connectionPointIn.getconnections() if connections is not None and len(connections) == 1: instanceLocalId = connections[0].getrefLocalId() - instance = pou.body.getcontentInstance(instanceLocalId) + body = pou.getbody() + if isinstance(body, ListType): + body = body[0] + instance = body.getcontentInstance(instanceLocalId) if isinstance(instance, plcopen.sfcObjects_step): steps.append(instance) elif isinstance(instance, plcopen.sfcObjects_selectionDivergence): @@ -1119,6 +1149,8 @@ self.TagName = previous_tagname elif transitionValues["type"] == "connection": body = pou.getbody() + if isinstance(body, ListType): + body = body[0] connections = transition.getconnections() if connections is not None: expression = self.ComputeExpression(body, connections) diff -r 7ea1f5094df3 -r 6a72016d721a plcopen/plcopen.py --- a/plcopen/plcopen.py Fri Jul 24 11:55:46 2009 +0200 +++ b/plcopen/plcopen.py Fri Jul 24 12:29:48 2009 +0200 @@ -89,7 +89,7 @@ return self.x_min, self.y_min, width, height -PLCOpenClasses = GenerateClassesFromXSD(os.path.join(os.path.split(__file__)[0], "TC6_XML_V10_B.xsd")) +PLCOpenClasses = GenerateClassesFromXSD(os.path.join(os.path.split(__file__)[0], "tc6_xml_v201.xsd")) ElementNameToClass = {} @@ -703,6 +703,30 @@ cls = PLCOpenClasses.get("resource_task", None) if cls: + def compatibility(self, tree): + if tree.hasAttribute("interval"): + interval = GetAttributeValue(tree._attrs["interval"]) + result = time_model.match(interval) + if result is not None: + 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)]) + text = "t#" + 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) + else: + 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: self.single = new_name @@ -712,6 +736,11 @@ cls = PLCOpenClasses.get("pouInstance", None) if cls: + 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.type == old_name: self.type = new_name @@ -772,7 +801,7 @@ new_pou = PLCOpenClasses["pous_pou"]() new_pou.setname(name) new_pou.setpouType(pou_type) - new_pou.setbody(PLCOpenClasses["body"]()) + new_pou.appendbody(PLCOpenClasses["body"]()) new_pou.setbodyType(body_type) self.pous.appendpou(new_pou) setattr(cls, "appendpouElement", appendpouElement) @@ -792,71 +821,88 @@ raise ValueError, "\"%s\" POU doesn't exist !!!"%name setattr(cls, "removepouElement", removepouElement) -def setbodyType(self, type): - if type == "IL": - self.body.setcontent({"name" : "IL", "value" : PLCOpenClasses["formattedText"]()}) - elif type == "ST": - self.body.setcontent({"name" : "ST", "value" : PLCOpenClasses["formattedText"]()}) - elif type == "LD": - self.body.setcontent({"name" : "LD", "value" : PLCOpenClasses["body_LD"]()}) - elif type == "FBD": - self.body.setcontent({"name" : "FBD", "value" : PLCOpenClasses["body_FBD"]()}) - elif type == "SFC": - self.body.setcontent({"name" : "SFC", "value" : PLCOpenClasses["body_SFC"]()}) - else: - raise ValueError, "%s isn't a valid body type!"%type - -def getbodyType(self): - return self.body.getcontent()["name"] - -def resetexecutionOrder(self): - self.body.resetexecutionOrder() - -def compileexecutionOrder(self): - self.body.compileexecutionOrder() - -def setelementExecutionOrder(self, instance, new_executionOrder): - self.body.setelementExecutionOrder(instance, new_executionOrder) - -def addinstance(self, name, instance): - self.body.appendcontentInstance(name, instance) - -def getinstances(self): - return self.body.getcontentInstances() - -def getinstance(self, id): - return self.body.getcontentInstance(id) - -def getrandomInstance(self, exclude): - return self.body.getcontentRandomInstance(exclude) - -def getinstanceByName(self, name): - return self.body.getcontentInstanceByName(name) - -def removeinstance(self, id): - self.body.removecontentInstance(id) - -def settext(self, text): - self.body.settext(text) - -def gettext(self): - return self.body.gettext() -setattr(cls, "gettext", gettext) - cls = PLCOpenClasses.get("pous_pou", None) if cls: + + def setbodyType(self, type): + if len(self.body) > 0: + if type == "IL": + self.body[0].setcontent({"name" : "IL", "value" : PLCOpenClasses["formattedText"]()}) + elif type == "ST": + self.body[0].setcontent({"name" : "ST", "value" : PLCOpenClasses["formattedText"]()}) + elif type == "LD": + self.body[0].setcontent({"name" : "LD", "value" : PLCOpenClasses["body_LD"]()}) + elif type == "FBD": + self.body[0].setcontent({"name" : "FBD", "value" : PLCOpenClasses["body_FBD"]()}) + elif type == "SFC": + self.body[0].setcontent({"name" : "SFC", "value" : PLCOpenClasses["body_SFC"]()}) + else: + raise ValueError, "%s isn't a valid body type!"%type setattr(cls, "setbodyType", setbodyType) + + def getbodyType(self): + if len(self.body) > 0: + return self.body[0].getcontent()["name"] setattr(cls, "getbodyType", getbodyType) + + def resetexecutionOrder(self): + if len(self.body) > 0: + self.body[0].resetexecutionOrder() setattr(cls, "resetexecutionOrder", resetexecutionOrder) + + def compileexecutionOrder(self): + if len(self.body) > 0: + self.body[0].compileexecutionOrder() setattr(cls, "compileexecutionOrder", compileexecutionOrder) + + def setelementExecutionOrder(self, instance, new_executionOrder): + if len(self.body) > 0: + self.body[0].setelementExecutionOrder(instance, new_executionOrder) setattr(cls, "setelementExecutionOrder", setelementExecutionOrder) + + def addinstance(self, name, instance): + if len(self.body) > 0: + self.body[0].appendcontentInstance(name, instance) setattr(cls, "addinstance", addinstance) + + def getinstances(self): + if len(self.body) > 0: + return self.body[0].getcontentInstances() + return [] setattr(cls, "getinstances", getinstances) + + def getinstance(self, id): + if len(self.body) > 0: + return self.body[0].getcontentInstance(id) + return None setattr(cls, "getinstance", getinstance) + + def getrandomInstance(self, exclude): + if len(self.body) > 0: + return self.body[0].getcontentRandomInstance(exclude) + return None setattr(cls, "getrandomInstance", getrandomInstance) + + def getinstanceByName(self, name): + if len(self.body) > 0: + return self.body[0].getcontentInstanceByName(name) + return None setattr(cls, "getinstanceByName", getinstanceByName) + + def removeinstance(self, id): + if len(self.body) > 0: + self.body[0].removecontentInstance(id) setattr(cls, "removeinstance", removeinstance) + + def settext(self, text): + if len(self.body) > 0: + self.body[0].settext(text) setattr(cls, "settext", settext) + + def gettext(self): + if len(self.body) > 0: + return self.body[0].gettext() + return "" setattr(cls, "gettext", gettext) def getvars(self): @@ -1042,6 +1088,56 @@ transition.updateElementName(old_name, new_name) setattr(cls, "updateElementName", updateElementName) +def setbodyType(self, type): + if type == "IL": + self.body.setcontent({"name" : "IL", "value" : PLCOpenClasses["formattedText"]()}) + elif type == "ST": + self.body.setcontent({"name" : "ST", "value" : PLCOpenClasses["formattedText"]()}) + elif type == "LD": + self.body.setcontent({"name" : "LD", "value" : PLCOpenClasses["body_LD"]()}) + elif type == "FBD": + self.body.setcontent({"name" : "FBD", "value" : PLCOpenClasses["body_FBD"]()}) + elif type == "SFC": + self.body.setcontent({"name" : "SFC", "value" : PLCOpenClasses["body_SFC"]()}) + else: + raise ValueError, "%s isn't a valid body type!"%type + +def getbodyType(self): + return self.body.getcontent()["name"] + +def resetexecutionOrder(self): + self.body.resetexecutionOrder() + +def compileexecutionOrder(self): + self.body.compileexecutionOrder() + +def setelementExecutionOrder(self, instance, new_executionOrder): + self.body.setelementExecutionOrder(instance, new_executionOrder) + +def addinstance(self, name, instance): + self.body.appendcontentInstance(name, instance) + +def getinstances(self): + return self.body.getcontentInstances() + +def getinstance(self, id): + return self.body.getcontentInstance(id) + +def getrandomInstance(self, exclude): + return self.body.getcontentRandomInstance(exclude) + +def getinstanceByName(self, name): + return self.body.getcontentInstanceByName(name) + +def removeinstance(self, id): + self.body.removecontentInstance(id) + +def settext(self, text): + self.body.settext(text) + +def gettext(self): + return self.body.gettext() + cls = PLCOpenClasses.get("transitions_transition", None) if cls: setattr(cls, "setbodyType", setbodyType) @@ -1635,6 +1731,23 @@ return infos setattr(cls, "getinfos", getinfos) +cls = PLCOpenClasses.get("transition_condition", None) +if cls: + def compatibility(self, tree): + connections = [] + 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_transition", "single") if cls: def getinfos(self): @@ -1648,8 +1761,7 @@ condition = self.getconditionContent() specific_values["condition_type"] = condition["type"] if specific_values["condition_type"] == "connection": - - specific_values["connection"] = _getconnectioninfos(self, self, True) + specific_values["connection"] = _getconnectioninfos(self, condition["value"], True) else: specific_values["condition"] = condition["value"] infos["inputs"].append(_getconnectioninfos(self, self.connectionPointIn, True)) @@ -1668,7 +1780,8 @@ condition.setcontent({"name" : "ST", "value" : PLCOpenClasses["formattedText"]()}) condition.settext(value) elif type == "connection": - condition = [PLCOpenClasses["connection"]()] + type = "connectionPointIn" + condition = PLCOpenClasses["connectionPointIn"]() self.condition.setcontent({"name" : type, "value" : condition}) setattr(cls, "setconditionContent", setconditionContent) @@ -1680,6 +1793,9 @@ values["value"] = content["value"].getname() elif values["type"] == "inline": values["value"] = content["value"].gettext() + elif values["type"] == "connectionPointIn": + values["type"] = "connection" + values["value"] = content["value"] return values return "" setattr(cls, "getconditionContent", getconditionContent) @@ -1694,89 +1810,12 @@ content["value"].updateElementName(old_name, new_name) setattr(cls, "updateElementName", updateElementName) - def setrelPositionXY(self, x, y): - pass - setattr(cls, "setrelPositionXY", setrelPositionXY) - - def getrelPositionXY(self): - return None - setattr(cls, "getrelPositionXY", getrelPositionXY) - - def addconnection(self): - if self.condition: - content = self.condition.getcontent() - if content["name"] != "connection": - self.condition.setcontent({"name" : "connection", "value" : [PLCOpenClasses["connection"]()]}) - content = self.condition.getcontent() - else: - content["value"].append(PLCOpenClasses["connection"]()) - setattr(cls, "addconnection", addconnection) - - def removeconnection(self, idx): - if self.condition: - content = self.condition.getcontent() - if content["name"] == "connection": - content["value"].pop(idx) - setattr(cls, "removeconnection", removeconnection) - - def removeconnections(self): - if self.condition: - content = self.condition.getcontent() - if content["name"] == "connection": - content["value"] = [PLCOpenClasses["connection"]()] - setattr(cls, "removeconnections", removeconnections) - def getconnections(self): if self.condition: content = self.condition.getcontent() - if content["name"] == "connection": - return content["value"] + if content["name"] == "connectionPointIn": + return content["value"].getconnections() setattr(cls, "getconnections", getconnections) - - def setconnectionId(self, idx, id): - if self.condition: - content = self.condition.getcontent() - if content["name"] == "connection": - content["value"][idx].setrefLocalId(id) - setattr(cls, "setconnectionId", setconnectionId) - - def getconnectionId(self, idx): - if self.condition: - content = self.condition.getcontent() - if content["name"] == "connection": - return content["value"][idx].getrefLocalId() - return None - setattr(cls, "getconnectionId", getconnectionId) - - def setconnectionPoints(self, idx, points): - if self.condition: - content = self.condition.getcontent() - if content["name"] == "connection": - content["value"][idx].setpoints(points) - setattr(cls, "setconnectionPoints", setconnectionPoints) - - def getconnectionPoints(self, idx): - if self.condition: - content = self.condition.getcontent() - if content["name"] == "connection": - return content["value"][idx].getpoints() - return None - setattr(cls, "getconnectionPoints", getconnectionPoints) - - def setconnectionParameter(self, idx, parameter): - if self.condition: - content = self.condition.getcontent() - if content["name"] == "connection": - content["value"][idx].setformalParameter(parameter) - setattr(cls, "setconnectionParameter", setconnectionParameter) - - def getconnectionParameter(self, idx): - if self.condition: - content = self.condition.getcontent() - if content["name"] == "connection": - content["value"][idx].getformalParameter() - return None - setattr(cls, "getconnectionParameter", getconnectionParameter) cls = _initElementClass("selectionDivergence", "sfcObjects_selectionDivergence", "single") if cls: @@ -1806,6 +1845,17 @@ cls = PLCOpenClasses.get("actionBlock_action", None) if cls: + 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") + if not relPosition: + 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: self.reference.setname(name) @@ -2082,7 +2132,7 @@ result = arrayValue_model.match(item) if result is not None: groups = result.groups() - element.setrepetitionValue(int(groups[0])) + element.setrepetitionValue(groups[0]) element.setvalue(groups[1].strip()) else: element.setvalue(item) @@ -2094,7 +2144,7 @@ for element in self.value: repetition = element.getrepetitionValue() if repetition is not None and repetition > 1: - values.append("%d(%s)"%(repetition, element.getvalue())) + values.append("%s(%s)"%(repetition, element.getvalue())) else: values.append(element.getvalue()) return "[%s]"%", ".join(values) diff -r 7ea1f5094df3 -r 6a72016d721a plcopen/tc6_xml_v201.xsd --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plcopen/tc6_xml_v201.xsd Fri Jul 24 12:29:48 2009 +0200 @@ -0,0 +1,1756 @@ + + + + + The complete project + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Documentation language of the project e.g. "en-US" + + + + + + + + + + + + + + + + + + + Additional userspecific information to the element + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Additional userspecific information to the element + + + + + + + + + + + + + + + + Additional userspecific information to the element + + + + + + + + + + + + + + + + + + + + + Additional userspecific information to the element + + + + + + + + + + + + + + + Additional userspecific information to the element + + + + + + + + + + + + + + + + + + + + + + + + Represents a group of resources and global variables + + + + + + Represents a group of programs and tasks and global variables + + + + + + Represents a periodic or triggered task + + + + + + + Additional userspecific information to the element + + + + + + + + Vendor specific: Either a constant duration as defined in the IEC or variable name. + + + + + + + + + + + + + + + + + + + Additional userspecific information to the element + + + + + + + + + + + + + + Additional userspecific information to the element + + + + + + + + + + + + + + + + + Additional userspecific information to the element + + + + + + + + A generic data type + + + + + + + + + + Defines a range with signed bounds + + + + + + + Defines a range with unsigned bounds + + + + + + + A generic value + + + + + + Value that can be represented as a single token string + + + + + + + + Array value consisting of a list of occurrances - value pairs + + + + + + + + + + + + + + + + + + Struct value consisting of a list of member - value pairs + + + + + + + + + + + + + + + + + + + Implementation part of a POU, action or transistion + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Additional userspecific information to the element + + + + + + + + + List of variable declarations that share the same memory attributes (CONSTANT, RETAIN, NON_RETAIN, PERSISTENT) + + + + + + + + + + + + + + + List of variable declarations without attributes + + + + + + Declaration of a variable + + + + + + + + + + + + + + + + + + + List of access variable declarations + + + + + + Declaration of an access variable + + + + + + + + + Name that is visible to the communication partner + + + + + Variable name including instance path inside the configuration + + + + + + + + + + + + List of VAR_CONFIG variables + + + + + + Declaration of an access variable + + + + + + + + + + Variable name including instance path + + + + + + + + + + + + Defines a graphical position in X, Y coordinates + + + + + + + Describes a connection between the consumer element (eg. input variable of a function block) and the producer element (eg. output variable of a function block). It may contain a list of positions that describes the path of the connection. + + + + + All positions of the directed connection path. If any positions are given, the list has to contain the first (input pin of the consumer element) as well as the last (output pin of the producer element). + + + + + + + + Identifies the element the connection starts from. + + + + + If present: + This attribute denotes the name of the VAR_OUTPUT / VAR_IN_OUTparameter of the pou block that is the start of the connection. + If not present: + If the refLocalId attribute refers to a pou block, the start of the connection is the first output of this block, which is not ENO. + If the refLocalId attribute refers to any other element type, the start of the connection is the elements single native output. + + + + + + Defines a connection point on the consumer side + + + + + Relative position of the connection pin. Origin is the anchor position of the block. + + + + + + + The operand is a valid iec variable e.g. avar[0] or an iec expression or multiple token text e.g. a + b (*sum*). An iec 61131-3 parser has to be used to extract variable information. + + + + + + + + + + Defines a connection point on the producer side + + + + + Relative position of the connection pin. Origin is the anchor position of the block. + + + + + The operand is a valid iec variable e.g. avar[0]. + + + + + + + + + Represents a program or function block instance either running with or without a task + + + + + + + + + + + + Formatted text according to parts of XHTML 1.1 + + + + + + + + Application specific data defined in external schemata + + + + + + + + + + Uniquely identifies the additional data element. + + + + + Recommended processor handling for unknown data elements. +Specifies if the processor should try to preserve the additional data element, dismiss the element (e.g. because the data is invalid if not updated correctly) or use the processors default behaviour for unknown data. + + + + + + + + + + + + + + + + List of additional data elements used in the document with description + + + + + + + + + + Unique name of the additional data element. + + + + + Version of additional data, eg. schema version. + + + + + Vendor responsible for the definition of the additional data element. + + + + + + + + + Collection of elementary IEC 61131-3 datatypes + + + + + + + + + + + + + + + + + + + + + + + + + The single byte character string type + + + + + + + + The wide character (WORD) string type + + + + + + + + + + + + + + + + + + + Collection of derived IEC 61131-3 datatypes + + + + + + + + + + + + + Reference to a user defined datatype or POU. Variable declarations use this type to declare e.g. function block instances. + + + + The user defined alias type + + + + + + + + + + + + + + + + + An enumeration value used to build up enumeration types + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Collection of datatypes not defined in IEC 61131-3 + + + + + + + + + + + + + + Collection of objects which have no direct iec scope and can be used in any graphical body. + + + + + + + + + + + + + + + + + + + + Describes a graphical object representing a conversion error. Used to keep information which can not be interpreted by the importing system + + + + + + + + + + + + + + + + + Describes a graphical object representing a variable, literal or expression used as r-value + + + + + + + + + + The operand is a valid iec variable e.g. avar[0] + + + + + + + + + + + Counterpart of the connector element + + + + Describes a graphical object representing a variable, literal or expression used as r-value + + + + + + + + + + The operand is a valid iec variable e.g. avar[0] + + + + + + + + + + + + + + + + + Association of an action with qualifier + + + + + Relative position of the action. Origin is the anchor position of the action block. + + + + + Name of an action or boolean variable. + + + + + + + + Inline implementation of an action body. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Used to identify the order of execution. Also used to identify one special block if there are several blocks with the same name. + + + + + + + + + + + + + + + Used to identify the order of execution. Also used to identify one special block if there are several blocks with the same name. + + + + + + + + + Describes a graphical object representing a call statement + + + + + Anchor position of the box. Top left corner excluding the instance name. + + + + + An alternative text to be displayed in generic representation of unknown elements. + + + + + The list of used input variables (consumers) + + + + + + + Describes an inputVariable of a Function or a FunctionBlock + + + + + + + + + + + + + + + + + + The list of used inOut variables + + + + + + + Describes a inOutVariable of a Function or a FunctionBlock + + + + + + + + + + + + + + + + + + + The list of used output variables (producers) + + + + + + + Describes a outputVariable of a Function or a FunctionBlock + + + + + + + + + + + + + + + + + + Additional, vendor specific data for the element. Also defines the vendor specific meaning of the element. + + + + + + + + + Used to identify the order of execution. Also used to identify one special block if there are several blocks with the same name. + + + + + + + + + + Collection of objects which are defined in fbd. They can be used in all graphical bodies. + + + + + + Describes a graphical object representing a call statement + + + + + Anchor position of the box. Top left corner excluding the instance name. + + + + + The list of used input variables (consumers) + + + + + + + Describes an inputVariable of a Function or a FunctionBlock + + + + + + + + + + + + + + + + + + The list of used inOut variables + + + + + + + Describes a inOutVariable of a Function or a FunctionBlock + + + + + + + + + + + + + + + + + + + The list of used output variables (producers) + + + + + + + Describes a outputVariable of a Function or a FunctionBlock + + + + + + + + + + + + + + + + + + + + + + + + + + Used to identify the order of execution. Also used to identify one special block if there are several blocks with the same name. + + + + + + + + Expression used as producer + + + + Describes a graphical object representing a variable, literal or expression used as r-value + + + + + + + The operand is a valid iec variable e.g. avar[0]. + + + + + + + + + + + + + + + + + + Expression used as consumer + + + + Describes a graphical object representing a variable or expression used as l-value + + + + + + + The operand is a valid iec variable e.g. avar[0]. + + + + + + + + + + + + + + + + + + Expression used as producer and consumer + + + + Describes a graphical object representing a variable which can be used as l-value and r-value at the same time + + + + + + + + The operand is a valid iec variable e.g. avar[0]. + + + + + + + + + + + + + + + + + + + + + + Describes a graphical object representing a jump label + + + + + + + + + + + + + + + + + + Describes a graphical object representing a jump statement + + + + + + + + + + + + + + + + + + + Describes a graphical object representing areturn statement + + + + + + + + + + + + + + + + + + + Collection of objects which are defined in ld and are an extension to fbd. They can be used in ld and sfc bodies + + + + + + Describes a graphical object representing a left powerrail + + + + + + + + + + + + + + + + + + + + + Used to identify the order of execution. Also used to identify one special block if there are several blocks with the same name. + + + + + + + + + Describes a graphical object representing a right powerrail + + + + + + + + + + + + + Used to identify the order of execution. Also used to identify one special block if there are several blocks with the same name. + + + + + + + + + Describes a graphical object representing a boolean variable which can be used as l-value and r-value at the same time + + + + + + + + The operand is a valid boolean iec variable e.g. avar[0] + + + + + + + + + + + + + + + + + + + Describes a graphical object representing a variable which can be used as l-value and r-value at the same time + + + + + + + + The operand is a valid boolean iec variable e.g. avar[0] + + + + + + + + + + + + + + + + + + + + Collection of objects which are defined in sfc. They can only be used in sfc bodies + + + + + A single step in a SFC Sequence. Actions are associated with a step by using an actionBlock element with a connection to the step element + + + + Contains actions + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Used to identify the order of execution. Also used to identify one special block if there are several blocks with the same name. + + + + + + + + + + + + + + + + + + + + + + Used to identify the order of execution. Also used to identify one special block if there are several blocks with the same name. + + + + + + + + Jump to a step, macro step or simultaneous divergence. Acts like a step. Predecessor should be a transition. + + + + + + + + + + + + + + + Used to identify the order of execution. Also used to identify one special block if there are several blocks with the same name. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The priority of a transition is evaluated, if the transition is connected to a selectionDivergence element. + + + + + Used to identify the order of execution. Also used to identify one special block if there are several blocks with the same name. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Defines the edge detection behaviour of a variable + + + + + + + + + + Defines the storage mode (S/R) behaviour of a variable + + + + + + + + + + Defines the different access types to an accessVariable + + + + + + + + + Defines the different types of a POU + + + + + + + +