diff -r 000000000000 -r b622defdfd98 plcopen/plcopen.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plcopen/plcopen.py Wed Jan 31 16:31:39 2007 +0100 @@ -0,0 +1,1792 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +#This file is part of PLCOpenEditor, a library implementing an IEC 61131-3 editor +#based on the plcopen standard. +# +#Copyright (C): Edouard TISSERANT and Laurent BESSARD +# +#See COPYING file for copyrights details. +# +#This library is free software; you can redistribute it and/or +#modify it under the terms of the GNU Lesser General Public +#License as published by the Free Software Foundation; either +#version 2.1 of the License, or (at your option) any later version. +# +#This library is distributed in the hope that it will be useful, +#but WITHOUT ANY WARRANTY; without even the implied warranty of +#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +#Lesser General Public License for more details. +# +#You should have received a copy of the GNU Lesser General Public +#License along with this library; if not, write to the Free Software +#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +from xml.parsers import expat +from minixsv import pyxsval +from random import * + +from types import * +from datetime import * + +import sys,re + +classes = {} +TimeType = time(0,0,0).__class__ +DateType = date(1,1,1).__class__ +DateTimeType = datetime(1,1,1,0,0,0).__class__ + +""" +Dictionary that makes the relation between var names in plcopen and displayed values +""" +VarTypes = {"Local" : "localVars", "Temp" : "tempVars", "Input" : "inputVars", + "Output" : "outputVars", "InOut" : "inOutVars", "External" : "externalVars", + "Global" : "globalVars", "Access" : "accessVars"} + +""" +Define in which order var types must be displayed +""" +VarOrder = ["Local","Temp","Input","Output","InOut","External","Global","Access"] + +""" +Regular expression models for extracting dates and times from a string +""" +time_model = re.compile('([0-9]{2}):([0-9]{2}):([0-9]{2})') +date_model = re.compile('([0-9]{4})-([0-9]{2})-([0-9]{2})') +datetime_model = re.compile('([0-9]{4})-([0-9]{2})-([0-9]{2})[ T]([0-9]{2}):([0-9]{2}):([0-9]{2})') + +""" +Define which action qualifier must be associated with a duration +""" +QualifierList = {"N" : False, "R" : False, "S" : False, "L" : True, "D" : True, + "P" : False, "P0" : False, "P1" : False, "SD" : True, "DS" : True, "SL" : True} + +""" +pyxsval is not complete and the parts that are not supported print some error +reports. This class is used for not displaying them +""" +class HolePseudoFile: + """ Base class for file like objects to facilitate StdOut for the Shell.""" + def __init__(self, output = None): + if output is None: output = [] + self.output = output + + def writelines(self, l): + map(self.write, l) + + def write(self, s): + pass + + def flush(self): + pass + + def isatty(self): + return false + +""" +This function calculates the number of whitespace for indentation +""" +def getIndent(indent, balise): + first = indent * 2 + second = first + len(balise) + 1 + return "\t".expandtabs(first), "\t".expandtabs(second) + +""" +This function recursively creates a definition of the classes and their attributes +for plcopen from the xsd file of plcopen opened in a DOM model +""" +def Generate_classes(tree, parent, sequence = False): + attributes = {} + inheritance = [] + if sequence: + order = [] + # The lists of attributes and inheritance of the node are generated from the childrens + for node in tree.childNodes: + # We make fun of #text elements and all other tags that don't are xsd tags + if node.nodeName != "#text" and node.nodeName.startswith("xsd:"): + recursion = False + name = node.nodeName[4:].encode() + + # This tags defines an attribute of the class + if name in ["element", "attribute"]: + nodename = GetAttributeValue(node._attrs["name"]) + if "type" in node._attrs: + nodetype = GetAttributeValue(node._attrs["type"]) + else: + # The type of attribute is defines in the child tree so we generate a new class + # No name is defined so we create one from nodename and parent class name + # (because some different nodes can have the same name) + if parent: + classname = "%s_%s"%(parent, nodename) + else: + classname = nodename + Generate_classes(node, classname) + nodetype = "ppx:%s"%classname + if name == "attribute": + if "use" in node._attrs: + use = GetAttributeValue(node._attrs["use"]) + else: + use = "optional" + if name == "element": + # If a tag can be written more than one time we define a list attribute + if "maxOccurs" in node._attrs and GetAttributeValue(node._attrs["maxOccurs"]) == "unbounded": + nodetype = "%s[]"%nodetype + if "minOccurs" in node._attrs and GetAttributeValue(node._attrs["minOccurs"]) == "0": + use = "optional" + else: + use = "required" + attributes[nodename] = (nodetype, name, use) + if sequence: + order.append(nodename) + + # This tag defines a new class + elif name == "complexType" or name == "simpleType": + if "name" in node._attrs: + classname = GetAttributeValue(node._attrs["name"]) + super, attrs = Generate_classes(node, classname) + else: + classname = parent + super, attrs = Generate_classes(node, classname.split("_")[-1]) + # When all attributes and inheritances have been extracted, the + # values are added in the list of classes to create + if classname not in classes: + classes[classname] = (super, attrs) + elif classes[classname] != (super, attrs): + print "A different class has already got %s for name"%classname + + # This tag defines an attribute that can have different types + elif name == "choice": + super, attrs = Generate_classes(node, parent) + if "ref" in attrs.keys(): + choices = attrs + else: + choices = {} + for attr, (attr_type, xml_type, write_type) in attrs.items(): + choices[attr] = attr_type + if "maxOccurs" in node._attrs and GetAttributeValue(node._attrs["maxOccurs"]) == "unbounded": + attributes["multichoice_content"] = choices + if sequence: + order.append("multichoice_content") + else: + attributes["choice_content"] = choices + if sequence: + order.append("choice_content") + + # This tag defines the order in which class attributes must be written + # in plcopen xml file. We have to store this order like an attribute + elif name in "sequence": + super, attrs, order = Generate_classes(node, parent, True) + if "maxOccurs" in node._attrs and GetAttributeValue(node._attrs["maxOccurs"]) == "unbounded": + for attr, (attr_type, xml_type, write_type) in attrs.items(): + attrs[attr] = ("%s[]"%attr_type, xml_type, write_type) + if "minOccurs" in node._attrs and GetAttributeValue(node._attrs["minOccurs"]) == "0": + for attr, (attr_type, xml_type, write_type) in attrs.items(): + attrs[attr] = (attr_type, xml_type, "optional") + inheritance.extend(super) + attributes.update(attrs) + attributes["order"] = order + + # This tag defines of types + elif name == "group": + if "name" in node._attrs: + nodename = GetAttributeValue(node._attrs["name"]) + super, attrs = Generate_classes(node, None) + classes[nodename] = (super, {"group":attrs["choice_content"]}) + elif "ref" in node._attrs: + if "ref" not in attributes: + attributes["ref"] = [GetAttributeValue(node._attrs["ref"])] + else: + attributes["ref"].append(GetAttributeValue(node._attrs["ref"])) + + # This tag define a base class for the node + elif name == "extension": + super = GetAttributeValue(node._attrs["base"]) + inheritance.append(super[4:]) + recursion = True + + # This tag defines a restriction on the type of attribute + elif name == "restriction": + attributes["basetype"] = GetAttributeValue(node._attrs["base"]) + recursion = True + + # This tag defines an enumerated type + elif name == "enumeration": + if "enum" not in attributes: + attributes["enum"] = [GetAttributeValue(node._attrs["value"])] + else: + attributes["enum"].append(GetAttributeValue(node._attrs["value"])) + + # This tags defines a restriction on a numerical value + elif name in ["minInclusive","maxInclusive"]: + if "limit" not in attributes: + attributes["limit"] = {} + if name == "minInclusive": + attributes["limit"]["min"] = eval(GetAttributeValue(node._attrs["value"])) + elif name == "maxInclusive": + attributes["limit"]["max"] = eval(GetAttributeValue(node._attrs["value"])) + + # This tag are not important but their childrens are. The childrens are then parsed. + elif name in ["complexContent", "schema"]: + recursion = True + + # We make fun of xsd documentation + elif name in ["annotation"]: + pass + + else: + #print name + Generate_classes(node, parent) + + # Parse the childrens of node + if recursion: + super, attrs = Generate_classes(node, parent) + inheritance.extend(super) + attributes.update(attrs) + + # if sequence tag have been found, order is returned + if sequence: + return inheritance, attributes, order + else: + return inheritance, attributes +""" +Function that extracts data from a node +""" +def GetAttributeValue(attr): + if len(attr.childNodes) == 1: + return attr.childNodes[0].data.encode() + else: + return "" + +""" +Funtion that returns the Python type and default value for a given xsd type +""" +def GetTypeInitialValue(attr_type): + type_compute = attr_type[4:].replace("[]", "") + if attr_type.startswith("xsd:"): + if type_compute == "boolean": + return BooleanType, "False" + elif type_compute in ["decimal","unsignedLong","long","integer"]: + return IntType, "0" + elif type_compute in ["string","anyURI","NMTOKEN"]: + return StringType, "\"\"" + elif type_compute == "time": + return TimeType, "time(0,0,0)" + elif type_compute == "date": + return DateType, "date(1,1,1)" + elif type_compute == "dateTime": + return DateTimeType, "datetime(1,1,1,0,0,0)" + elif type_compute == "language": + return StringType, "\"en-US\"" + else: + print "Can't affect: %s"%type_compute + elif attr_type.startswith("ppx:"): + if type_compute in PLCOpenClasses: + return PLCOpenClasses[type_compute],"%s()"%type_compute + +""" +Function that computes value from a python type (Only Boolean are critical because +there is no uppercase in plcopen) +""" +def ComputeValue(value): + if type(value) == BooleanType: + if value: + return "true" + else: + return "false" + else: + return str(value) + +""" +Function that extracts a value from a string following the xsd type given +""" +def GetComputedValue(attr_type, value): + type_compute = attr_type[4:].replace("[]", "") + if type_compute == "boolean": + if value == "true": + return True + elif value == "false": + return False + else: + raise ValueError, "\"%s\" is not a valid boolean!"%value + elif type_compute in ["decimal","unsignedLong","long","integer"]: + return int(value) + elif type_compute in ["string","anyURI","NMTOKEN","language"]: + return value + elif type_compute == "time": + result = time_model.match(value) + if result: + time_values = [int(v) for v in result.groups()] + return time(*time_values) + else: + raise ValueError, "\"%s\" is not a valid time!"%value + elif type_compute == "date": + result = date_model.match(value) + if result: + date_values = [int(v) for v in result.groups()] + return date(*date_values) + else: + raise ValueError, "\"%s\" is not a valid date!"%value + elif type_compute == "dateTime": + result = datetime_model.match(value) + if result: + datetime_values = [int(v) for v in result.groups()] + return datetime(*datetime_values) + else: + raise ValueError, "\"%s\" is not a valid datetime!"%value + else: + print "Can't affect: %s"%type_compute + return None + +""" +This is the Metaclass for PLCOpen element classes. It generates automatically +the basic useful methods for manipulate the differents attributes of the classes +""" +class MetaClass(type): + + def __init__(cls, name, bases, dict): + super(MetaClass, cls).__init__(name, bases, {}) + #print name, bases, dict, "\n" + initialValues = {} + for attr, values in dict.items(): + if attr in ["order", "basetype"]: + pass + + # Class is a enumerated type + elif attr == "enum": + value_type, initial = GetTypeInitialValue(dict["basetype"]) + initialValues["value"] = "\"%s\""%values[0] + setattr(cls, "value", values[0]) + setattr(cls, "setValue", MetaClass.generateSetEnumMethod(cls, values, value_type)) + setattr(cls, "getValue", MetaClass.generateGetMethod(cls, "value")) + + # Class is a limited type + elif attr == "limit": + value_type, initial = GetTypeInitialValue(dict["basetype"]) + initial = 0 + if "min" in values: + initial = max(initial, values["min"]) + if "max" in values: + initial = min(initial, values["max"]) + initialValues["value"] = "%d"%initial + setattr(cls, "value", initial) + setattr(cls, "setValue", MetaClass.generateSetLimitMethod(cls, values, value_type)) + setattr(cls, "getValue", MetaClass.generateGetMethod(cls, "value")) + + # Class has an attribute that can have different value types + elif attr == "choice_content": + setattr(cls, "content", None) + initialValues["content"] = "None" + setattr(cls, "deleteContent", MetaClass.generateDeleteMethod(cls, "content")) + setattr(cls, "setContent", MetaClass.generateSetChoiceMethod(cls, values)) + setattr(cls, "getContent", MetaClass.generateGetMethod(cls, "content")) + elif attr == "multichoice_content": + setattr(cls, "content", []) + initialValues["content"] = "[]" + setattr(cls, "appendContent", MetaClass.generateAppendChoiceMethod(cls, values)) + setattr(cls, "insertContent", MetaClass.generateInsertChoiceMethod(cls, values)) + setattr(cls, "removeContent", MetaClass.generateRemoveMethod(cls, "content")) + setattr(cls, "countContent", MetaClass.generateCountMethod(cls, "content")) + setattr(cls, "setContent", MetaClass.generateSetMethod(cls, "content", ListType)) + setattr(cls, "getContent", MetaClass.generateGetMethod(cls, "content")) + + # It's an attribute of the class + else: + attrname = attr[0].upper()+attr[1:] + attr_type, xml_type, write_type = values + value_type, initial = GetTypeInitialValue(attr_type) + # Value of the attribute is a list + if attr_type.endswith("[]"): + setattr(cls, attr, []) + initialValues[attr] = "[]" + setattr(cls, "append"+attrname, MetaClass.generateAppendMethod(cls, attr, value_type)) + setattr(cls, "insert"+attrname, MetaClass.generateInsertMethod(cls, attr, value_type)) + setattr(cls, "remove"+attrname, MetaClass.generateRemoveMethod(cls, attr)) + setattr(cls, "count"+attrname, MetaClass.generateCountMethod(cls, attr)) + setattr(cls, "set"+attrname, MetaClass.generateSetMethod(cls, attr, ListType)) + else: + if write_type == "optional": + setattr(cls, attr, None) + initialValues[attr] = "None" + setattr(cls, "add"+attrname, MetaClass.generateAddMethod(cls, attr, initial)) + setattr(cls, "delete"+attrname, MetaClass.generateDeleteMethod(cls, attr)) + else: + setattr(cls, attr, initial) + initialValues[attr] = initial + setattr(cls, "set"+attrname, MetaClass.generateSetMethod(cls, attr, value_type)) + setattr(cls, "get"+attrname, MetaClass.generateGetMethod(cls, attr)) + setattr(cls, "__init__", MetaClass.generateInitMethod(cls, bases, initialValues)) + setattr(cls, "loadXMLTree", MetaClass.generateLoadXMLTree(cls, bases, dict)) + setattr(cls, "generateXMLText", MetaClass.generateGenerateXMLText(cls, bases, dict)) + setattr(cls, "singleLineAttributes", True) + + """ + Method that generate the method for loading an xml tree by following the + attributes list defined + """ + def generateLoadXMLTree(cls, bases, dict): + def loadXMLTreeMethod(self, tree): + # If class is derived, values of inheritance classes are loaded + for base in bases: + base.loadXMLTree(self, tree) + # Class is a enumerated or limited value + if "enum" in dict.keys() or "limit" in dict.keys(): + attr_value = GetAttributeValue(tree) + attr_type = dict["basetype"] + val = GetComputedValue(attr_type, attr_value) + self.setValue(val) + else: + + # Load the node attributes if they are defined in the list + for attrname, attr in tree._attrs.items(): + if attrname in dict.keys(): + attr_type, xml_type, write_type = dict[attrname] + attr_value = GetAttributeValue(attr) + if write_type != "optional" or attr_value != "": + # Extracts the value + if attr_type.startswith("xsd:"): + val = GetComputedValue(attr_type, attr_value) + elif attr_type.startswith("ppx:"): + val = eval("%s()"%attr_type[4:], globals().update(PLCOpenClasses)) + val.loadXMLTree(attr) + setattr(self, attrname, val) + + # Load the node childs if they are defined in the list + for node in tree.childNodes: + name = node.nodeName + # We make fun of #text elements + if name != "#text": + + # Class has an attribute that can have different value types + if "choice_content" in dict.keys() and name in dict["choice_content"].keys(): + attr_type = dict["choice_content"][name] + # Extracts the value + if attr_type.startswith("xsd:"): + attr_value = GetAttributeValue(node) + if write_type != "optional" or attr_value != "": + val = GetComputedValue(attr_type.replace("[]",""), attr_value) + else: + val = None + elif attr_type.startswith("ppx:"): + val = eval("%s()"%attr_type[4:].replace("[]",""), globals().update(PLCOpenClasses)) + val.loadXMLTree(node) + # Stock value in content attribute + if val: + if attr_type.endswith("[]"): + if self.content: + self.content["value"].append(val) + else: + self.content = {"name":name,"value":[val]} + else: + self.content = {"name":name,"value":val} + + # Class has a list of attributes that can have different value types + elif "multichoice_content" in dict.keys() and name in dict["multichoice_content"].keys(): + attr_type = dict["multichoice_content"][name] + # Extracts the value + if attr_type.startswith("xsd:"): + attr_value = GetAttributeValue(node) + if write_type != "optional" or attr_value != "": + val = GetComputedValue(attr_type, attr_value) + else: + val = None + elif attr_type.startswith("ppx:"): + val = eval("%s()"%attr_type[4:], globals().update(PLCOpenClasses)) + val.loadXMLTree(node) + # Add to content attribute list + if val: + self.content.append({"name":name,"value":val}) + + # The node child is defined in the list + elif name in dict.keys(): + attr_type, xml_type, write_type = dict[name] + # Extracts the value + if attr_type.startswith("xsd:"): + attr_value = GetAttributeValue(node) + if write_type != "optional" or attr_value != "": + val = GetComputedValue(attr_type.replace("[]",""), attr_value) + else: + val = None + elif attr_type.startswith("ppx:"): + val = eval("%s()"%attr_type[4:].replace("[]",""), globals().update(PLCOpenClasses)) + val.loadXMLTree(node) + # Stock value in attribute + if val: + if attr_type.endswith("[]"): + getattr(self, name).append(val) + else: + setattr(self, name, val) + return loadXMLTreeMethod + + """ + Method that generates the method for generating an xml text by following the + attributes list defined + """ + def generateGenerateXMLText(cls, bases, dict): + def generateXMLTextMethod(self, name, indent, extras = {}, derived = False): + ind1, ind2 = getIndent(indent, name) + if not derived: + text = ind1 + "<%s"%name + else: + text = "" + if len(bases) > 0: + base_extras = {} + if "order" in dict.keys(): + order = dict["order"] + else: + order = [] + if "choice_content" in dict.keys() and "choice_content" not in order: + order.append("choice_content") + if "multichoice_content" in dict.keys() and "multichoice_content" not in order: + order.append("multichoice_content") + size = 0 + first = True + for attr, value in extras.items(): + if not first and not self.singleLineAttributes: + text += "\n%s"%(ind2) + text += " %s=\"%s\""%(attr, ComputeValue(value)) + first = False + for attr, values in dict.items(): + if attr in ["order","choice_content","multichoice_content"]: + pass + elif attr in ["enum","limit"]: + if not derived: + text += ">%s\n"%(ComputeValue(self.value),name) + else: + text += ComputeValue(self.value) + return text + elif values[1] == "attribute": + value = getattr(self, attr, None) + if values[2] != "optional" or value != None: + if not first and not self.singleLineAttributes: + text += "\n%s"%(ind2) + if values[0].startswith("ppx"): + if len(bases) > 0: + base_extras[attr] = value.getValue() + else: + text += " %s=\"%s\""%(attr, ComputeValue(value.getValue())) + else: + if len(bases) > 0: + base_extras[attr] = value + else: + text += " %s=\"%s\""%(attr, ComputeValue(value)) + first = False + if len(bases) > 0: + first, new_text = bases[0].generateXMLText(self, name, indent, base_extras, True) + text += new_text + else: + first = True + ind3, ind4 = getIndent(indent + 1, name) + for attr in order: + value = getattr(self, attr, None) + if attr == "choice_content": + if self.content: + if first: + text += ">\n" + first = False + value_type = dict[attr][self.content["name"]] + if value_type.startswith("xsd:"): + if value_type.endswith("[]"): + for content in self.content["value"]: + text += ind1 + "<%s>%s\n"%(self.content["name"], ComputeValue(content), self.content["name"]) + else: + text += ind1 + "<%s>%s\n"%(self.content["name"], ComputeValue(self.content["value"]), self.content["name"]) + elif value_type.endswith("[]"): + for content in self.content["value"]: + text += content.generateXMLText(self.content["name"], indent + 1) + else: + text += self.content["value"].generateXMLText(self.content["name"], indent + 1) + elif attr == "multichoice_content": + if len(self.content) > 0: + for element in self.content: + if first: + text += ">\n" + first = False + value_type = dict[attr][element["name"]] + if value_type.startswith("xsd:"): + text += ind1 + "<%s>%s\n"%(element["name"], ComputeValue(element["value"]), element["name"]) + else: + text += element["value"].generateXMLText(element["name"], indent + 1) + elif dict[attr][2] != "optional" or value != None: + if dict[attr][0].endswith("[]"): + if first and len(value) > 0: + text += ">\n" + first = False + for element in value: + if dict[attr][0].startswith("xsd:"): + text += ind3 + "<%s>%s\n"%(attr, ComputeValue(element), attr) + else: + text += element.generateXMLText(attr, indent + 1) + else: + if first: + text += ">\n" + first = False + if dict[attr][0].startswith("xsd:"): + text += ind3 + "<%s>%s\n"%(attr, ComputeValue(value), attr) + else: + text += getattr(self, attr).generateXMLText(attr, indent + 1) + if not derived: + if first: + text += "/>\n" + else: + text += ind1 + "\n"%(name) + return text + else: + return first, text + return generateXMLTextMethod + + """ + Methods that generates the different methods for setting and getting the attributes + """ + + def generateInitMethod(cls, bases, dict): + def initMethod(self): + for base in bases: + base.__init__(self) + for attr, initial in dict.items(): + setattr(self, attr, eval(initial, globals().update(PLCOpenClasses))) + return initMethod + + def generateSetMethod(cls, attr, choice_type): + def setMethod(self, value): + setattr(self, attr, value) + return setMethod + + def generateSetChoiceMethod(cls, attr_type): + def setChoiceMethod(self, name, value): + self.content = {"name":name,"value":value} + return setChoiceMethod + + def generateSetEnumMethod(cls, enum, attr_type): + def setEnumMethod(self, value): + if value in enum: + self.value = value + else: + raise ValueError, "%s is not a valid value. Must be in %s"%(value, str(enum)) + return setEnumMethod + + def generateSetLimitMethod(cls, limit, attr_type): + def setMethod(self, value): + if "min" in limit and value < limit["min"]: + raise ValueError, "%s is not a valid value. Must be greater than %d"%(value, limit["min"]) + elif "max" in limit and value > limit["max"]: + raise ValueError, "%s is not a valid value. Must be smaller than %d"%(value, limit["max"]) + else: + self.value = value + return setMethod + + def generateGetMethod(cls, attr): + def getMethod(self): + return getattr(self, attr, None) + return getMethod + + def generateAddMethod(cls, attr, initial): + def addMethod(self): + setattr(self, attr, eval(initial, globals().update(PLCOpenClasses))) + return addMethod + + def generateDeleteMethod(cls, attr): + def deleteMethod(self): + setattr(self, attr, None) + return deleteMethod + + def generateAppendMethod(cls, attr, attr_type): + def appendMethod(self, value): + getattr(self, attr).append(value) + return appendMethod + + def generateInsertMethod(cls, attr, attr_type): + def insertMethod(self, index, value): + getattr(self, attr).insert(index, value) + return insertMethod + + def generateAppendChoiceMethod(cls, choice_types): + def appendMethod(self, name, value): + self.content.append({"name":name,"value":value}) + return appendMethod + + def generateInsertChoiceMethod(cls, choice_types): + def insertMethod(self, index, name, value): + self.content.insert(index, {"name":name,"value":value}) + return insertMethod + + def generateRemoveMethod(cls, attr): + def removeMethod(self, index): + getattr(self, attr).pop(index) + return removeMethod + + def generateCountMethod(cls, attr): + def countMethod(self): + return len(getattr(self, attr)) + return countMethod + +""" +Method that generate the classes +""" +def CreateClass(classe): + # Checks that classe haven't been generated yet + if classe not in PLCOpenClasses and classe not in PLCOpenTypes and classe in classes: + inheritance, attributes = classes[classe] + #print classe, inheritance, attributes + dict = {} + bases = [] + + # If inheritance classes haven't been generated + for base in inheritance: + if base not in PLCOpenClasses: + CreateClass(base) + bases.append(PLCOpenClasses[base]) + + # Checks that all attribute types are available + for attribute, type_attribute in attributes.items(): + if attribute == "group": + PLCOpenTypes[classe] = type_attribute + elif attribute == "ref": + PLCOpenTypes[classe] = {} + for attr in type_attribute: + if attr[4:] not in PLCOpenTypes: + CreateClass(attr[4:]) + PLCOpenTypes[classe].update(PLCOpenTypes[attr[4:]]) + elif attribute in ["choice_content","multichoice_content"]: + element_types = {} + for attr, value in type_attribute.items(): + if attr == "ref": + for ref in type_attribute["ref"]: + if ref[4:] not in PLCOpenTypes: + CreateClass(ref[4:]) + element_types.update(PLCOpenTypes[ref[4:]]) + else: + element_types[attr] = value + dict[attribute] = element_types + else: + dict[attribute] = type_attribute + if attribute == "enum": + PLCOpenTypes["%s_enum"%classe] = type_attribute + elif attribute not in ["limit", "order"]: + if type_attribute[0].startswith("ppx:"): + type_compute = type_attribute[0][4:].replace("[]","") + if type_compute not in PLCOpenClasses: + CreateClass(type_compute) + if "group" not in attributes.keys() and "ref" not in attributes.keys(): + cls = MetaClass.__new__(MetaClass, classe, tuple(bases), dict) + MetaClass.__init__(cls, classe, tuple(bases), dict) + PLCOpenClasses[classe] = cls + +def Generate_Methods(): + if "dataType" in PLCOpenClasses: + cls = PLCOpenClasses["dataType"] + cls.value = None + + def getValue(self): + return self.value + setattr(cls, "getValue", getValue) + + def setValue(self, value): + self.value = value + setattr(cls, "setValue", setValue) + + def loadXMLTree(self, tree): + self.value = tree.childNodes[1].nodeName + setattr(cls, "loadXMLTree", loadXMLTree) + + def generateXMLText(self, name, indent, extras = {}): + ind1, ind2 = getIndent(indent, name) + text = ind1 + "<%s>\n"%name + ind3, ind4 = getIndent(indent + 1, self.value) + text += ind3 + "<%s/>\n"%self.value + text += ind1 + "\n"%name + return text + setattr(cls, "generateXMLText", generateXMLText) + + if "formattedText" in PLCOpenClasses: + cls = PLCOpenClasses["formattedText"] + cls.text = "" + + def getText(self): + return self.text + setattr(cls, "getText", getText) + + def setText(self, text): + self.text = text + setattr(cls, "setText", setText) + + def loadXMLTree(self, tree): + self.text = GetAttributeValue(tree) + if len(self.text.splitlines()) > 1: + self.text = self.text[1:].rstrip() + setattr(cls, "loadXMLTree", loadXMLTree) + + def generateXMLText(self, name, indent, extras = {}): + ind1, ind2 = getIndent(indent, name) + if len(self.text.splitlines()) > 1: + text = ind1 + "<%s>\n"%name + text += "%s\n"%self.text + text += ind1 + "\n"%name + return text + else: + return ind1 + "<%s>%s\n"%(name, self.text, name) + setattr(cls, "generateXMLText", generateXMLText) + + if "project" in PLCOpenClasses: + cls = PLCOpenClasses["project"] + cls.singleLineAttributes = False + + def getFileHeader(self): + fileheader = {} + fileheader["companyName"] = self.fileHeader.getCompanyName() + if self.fileHeader.getCompanyURL(): + fileheader["companyURL"] = self.fileHeader.getCompanyURL() + fileheader["productName"] = self.fileHeader.getProductName() + fileheader["productVersion"] = self.fileHeader.getProductVersion() + if self.fileHeader.getProductRelease(): + fileheader["productRelease"] = self.fileHeader.getProductRelease() + fileheader["creationDateTime"] = self.fileHeader.getCreationDateTime() + if self.fileHeader.getContentDescription(): + fileheader["contentDescription"] = self.fileHeader.getContentDescription() + return fileheader + setattr(cls, "getFileHeader", getFileHeader) + + def setFileHeader(self, fileheader): + self.fileHeader.setCompanyName(fileheader["companyName"]) + if "companyURL" in fileheader: + self.fileHeader.setCompanyURL(fileheader["companyURL"]) + self.fileHeader.setProductName(fileheader["productName"]) + self.fileHeader.setProductVersion(fileheader["productVersion"]) + if "productRelease" in fileheader: + self.fileHeader.setProductRelease(fileheader["productRelease"]) + self.fileHeader.setCreationDateTime(fileheader["creationDateTime"]) + if "contentDescription" in fileheader: + self.fileHeader.setContentDescription(fileheader["contentDescription"]) + setattr(cls, "setFileHeader", setFileHeader) + + def setName(self, name): + self.contentHeader.setName(name) + setattr(cls, "setName", setName) + + def getName(self): + return self.contentHeader.getName() + setattr(cls, "getName", getName) + + def getPous(self): + return self.types.getPouElements() + setattr(cls, "getPous", getPous) + + def getPou(self, name): + return self.types.getPouElement(name) + setattr(cls, "getPou", getPou) + + def appendPou(self, name, pou_type, body_type): + self.types.appendPouElement(name, pou_type, body_type) + setattr(cls, "appendPou", appendPou) + + def insertPou(self, index, pou): + self.types.insertPouElement(index, pou) + setattr(cls, "insertPou", insertPou) + + def removePou(self, name): + self.types.removePouElement(name) + setattr(cls, "removePou", removePou) + + def getConfigurations(self): + configurations = self.instances.configurations.getConfiguration() + if configurations: + return configurations + return [] + setattr(cls, "getConfigurations", getConfigurations) + + def getConfiguration(self, name): + for configuration in self.instances.configurations.getConfiguration(): + if configuration.getName() == name: + return configuration + return None + setattr(cls, "getConfiguration", getConfiguration) + + def addConfiguration(self, name): + for configuration in self.instances.configurations.getConfiguration(): + if configuration.getName() == name: + raise ValueError, "\"%s\" configuration already exists !!!"%name + new_configuration = PLCOpenClasses["configurations_configuration"]() + new_configuration.setName(name) + self.instances.configurations.appendConfiguration(new_configuration) + setattr(cls, "addConfiguration", addConfiguration) + + def removeConfiguration(self, name): + found = False + for idx, configuration in enumerate(self.instances.configurations.getConfiguration()): + if configuration.getName() == name: + self.instances.configurations.removeConfiguration(idx) + found = True + break + if not found: + raise ValueError, "\"%s\" configuration doesn't exist !!!"%name + setattr(cls, "removeConfiguration", removeConfiguration) + + def getConfigurationResource(self, config_name, name): + configuration = self.getConfiguration(config_name) + if configuration: + for resource in configuration.getResource(): + if resource.getName() == name: + return resource + return None + setattr(cls, "getConfigurationResource", getConfigurationResource) + + def addConfigurationResource(self, config_name, name): + configuration = self.getConfiguration(config_name) + if configuration: + for resource in configuration.getResource(): + if resource.getName() == name: + raise ValueError, "\"%s\" resource already exists in \"%s\" configuration !!!"%(name, config_name) + new_resource = PLCOpenClasses["configuration_resource"]() + new_resource.setName(name) + configuration.appendResource(new_resource) + setattr(cls, "addConfigurationResource", addConfigurationResource) + + def removeConfigurationResource(self, config_name, name): + configuration = self.getConfiguration(config_name) + if configuration: + found = False + for idx, resource in enumerate(configuration.getResource()): + if resource.getName() == name: + configuration.removeResource(idx) + found = True + break + if not found: + raise ValueError, "\"%s\" resource doesn't exist in \"%s\" configuration !!!"%(name, config_name) + setattr(cls, "removeConfigurationResource", removeConfigurationResource) + + PLCOpenClasses["project_fileHeader"].singleLineAttributes = False + + if "project_types" in PLCOpenClasses: + cls = PLCOpenClasses["project_types"] + + def getPouElements(self): + return self.pous.getPou() + setattr(cls, "getPouElements", getPouElements) + + def getPouElement(self, name): + elements = self.pous.getPou() + for element in elements: + if element.getName() == name: + return element + return None + setattr(cls, "getPouElement", getPouElement) + + def appendPouElement(self, name, pou_type, body_type): + for element in self.pous.getPou(): + if element.getName() == name: + raise ValueError, "\"%s\" POU already exists !!!"%name + new_pou = PLCOpenClasses["pous_pou"]() + new_pou.setName(name) + new_pou.pouType.setValue(pou_type) + new_pou.setBody(PLCOpenClasses["body"]()) + new_pou.setBodyType(body_type) + self.pous.appendPou(new_pou) + setattr(cls, "appendPouElement", appendPouElement) + + def insertPouElement(self, index, pou): + self.pous.insertPou(index, pou) + setattr(cls, "insertPouElement", insertPouElement) + + def removePouElement(self, name): + found = False + for idx, element in enumerate(self.pous.getPou()): + if element.getName() == name: + self.pous.removePou(idx) + found = True + break + if not found: + raise ValueError, "\"%s\" POU doesn't exist !!!"%name + setattr(cls, "removePouElement", removePouElement) + + def setBodyType(self, type): + if type == "IL": + self.body.setContent("IL", PLCOpenClasses["formattedText"]()) + elif type == "ST": + self.body.setContent("ST", PLCOpenClasses["formattedText"]()) + elif type == "LD": + self.body.setContent("LD", PLCOpenClasses["body_LD"]()) + elif type == "FBD": + self.body.setContent("FBD", PLCOpenClasses["body_FBD"]()) + elif type == "SFC": + self.body.setContent("SFC", PLCOpenClasses["body_SFC"]()) + else: + raise ValueError, "%s isn't a valid body type!"%type + + def getBodyType(self): + return self.body.getContent()["name"] + + 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) + + if "pous_pou" in PLCOpenClasses: + cls = PLCOpenClasses["pous_pou"] + + setattr(cls, "setBodyType", setBodyType) + setattr(cls, "getBodyType", getBodyType) + setattr(cls, "addInstance", addInstance) + setattr(cls, "getInstances", getInstances) + setattr(cls, "getInstance", getInstance) + setattr(cls, "getRandomInstance", getRandomInstance) + setattr(cls, "getInstanceByName", getInstanceByName) + setattr(cls, "removeInstance", removeInstance) + setattr(cls, "setText", setText) + setattr(cls, "getText", getText) + + def getVars(self): + vars = [] + reverse_types = {} + for name, value in VarTypes.items(): + reverse_types[value] = name + for varlist in self.interface.getContent(): + vars.append((reverse_types[varlist["name"]], varlist["value"])) + return vars + setattr(cls, "getVars", getVars) + + def setVars(self, vars): + self.interface.setContent([]) + for vartype, varlist in vars: + self.interface.appendContent(VarTypes[vartype], varlist) + setattr(cls, "setVars", setVars) + + def addTransition(self, name, type): + if not self.transitions: + self.addTransitions() + self.transitions.setTransition([]) + transition = PLCOpenClasses["transitions_transition"]() + transition.setName(name) + transition.setBodyType(type) + self.transitions.appendTransition(transition) + setattr(cls, "addTransition", addTransition) + + def getTransition(self, name): + if self.transitions: + for transition in self.transitions.getTransition(): + if transition.getName() == name: + return transition + return None + setattr(cls, "getTransition", getTransition) + + def getTransitionList(self): + if self.transitions: + return self.transitions.getTransition() + return [] + setattr(cls, "getTransitionList", getTransitionList) + + def removeTransition(self, name): + if self.transitions: + transitions = self.transitions.getTransition() + i = 0 + removed = False + while i < len(transitions) and not removed: + if transitions[i].getName() == name: + transitions.removeTransition(i) + removed = True + i += 1 + if not removed: + raise ValueError, "Transition with name %s doesn't exists!"%name + setattr(cls, "removeTransition", removeTransition) + + def addAction(self, name, type): + if not self.actions: + self.addActions() + self.actions.setAction([]) + action = PLCOpenClasses["actions_action"]() + action.setName(name) + action.setBodyType(type) + self.actions.appendAction(action) + setattr(cls, "addAction", addAction) + + def getAction(self, name): + if self.actions: + for action in self.actions.getAction(): + if action.getName() == name: + return action + return None + setattr(cls, "getAction", getAction) + + def getActionList(self): + if self.actions: + return self.actions.getAction() + return [] + setattr(cls, "getActionList", getActionList) + + def removeAction(self, name): + if self.actions: + actions = self.actions.getAction() + i = 0 + removed = False + while i < len(actions) and not removed: + if actions[i].getName() == name: + actions.removeAction(i) + removed = True + i += 1 + if not removed: + raise ValueError, "Action with name %s doesn't exists!"%name + setattr(cls, "removeAction", removeAction) + + if "transitions_transition" in PLCOpenClasses: + cls = PLCOpenClasses["transitions_transition"] + + setattr(cls, "setBodyType", setBodyType) + setattr(cls, "getBodyType", getBodyType) + setattr(cls, "addInstance", addInstance) + setattr(cls, "getInstances", getInstances) + setattr(cls, "getInstance", getInstance) + setattr(cls, "getRandomInstance", getRandomInstance) + setattr(cls, "getInstanceByName", getInstanceByName) + setattr(cls, "removeInstance", removeInstance) + setattr(cls, "setText", setText) + setattr(cls, "getText", getText) + + if "actions_action" in PLCOpenClasses: + cls = PLCOpenClasses["actions_action"] + + setattr(cls, "setBodyType", setBodyType) + setattr(cls, "getBodyType", getBodyType) + setattr(cls, "addInstance", addInstance) + setattr(cls, "getInstances", getInstances) + setattr(cls, "getInstance", getInstance) + setattr(cls, "getRandomInstance", getRandomInstance) + setattr(cls, "getInstanceByName", getInstanceByName) + setattr(cls, "removeInstance", removeInstance) + setattr(cls, "setText", setText) + setattr(cls, "getText", getText) + + if "body" in PLCOpenClasses: + cls = PLCOpenClasses["body"] + + def appendContentInstance(self, name, instance): + if self.content["name"] in ["LD","FBD","SFC"]: + self.content["value"].appendContent(name, instance) + else: + raise TypeError, "%s body don't have instances!"%self.content["name"] + setattr(cls, "appendContentInstance", appendContentInstance) + + def getContentInstances(self): + if self.content["name"] in ["LD","FBD","SFC"]: + instances = [] + for element in self.content["value"].getContent(): + instances.append(element["value"]) + return instances + else: + raise TypeError, "%s body don't have instances!"%self.content["name"] + setattr(cls, "getContentInstances", getContentInstances) + + def getContentInstance(self, id): + if self.content["name"] in ["LD","FBD","SFC"]: + for element in self.content["value"].getContent(): + if element["value"].getLocalId() == id: + return element["value"] + return None + else: + raise TypeError, "%s body don't have instances!"%self.content["name"] + setattr(cls, "getContentInstance", getContentInstance) + + def getContentRandomInstance(self, exclude): + if self.content["name"] in ["LD","FBD","SFC"]: + for element in self.content["value"].getContent(): + if element["value"].getLocalId() not in exclude: + return element["value"] + return None + else: + raise TypeError, "%s body don't have instances!"%self.content["name"] + setattr(cls, "getContentRandomInstance", getContentRandomInstance) + + def getContentInstanceByName(self, name): + if self.content["name"] in ["LD","FBD","SFC"]: + for element in self.content["value"].getContent(): + if element["value"].getLocalId() == name: + return element["value"] + else: + raise TypeError, "%s body don't have instances!"%self.content["name"] + setattr(cls, "getContentInstanceByName", getContentInstanceByName) + + def removeContentInstance(self, id): + if self.content["name"] in ["LD","FBD","SFC"]: + i = 0 + removed = False + elements = self.content["value"].getContent() + while i < len(elements) and not removed: + if elements[i]["value"].getLocalId() == id: + self.content["value"].removeContent(i) + removed = True + i += 1 + if not removed: + raise ValueError, "Instance with id %d doesn't exists!"%id + else: + raise TypeError, "%s body don't have instances!"%self.content["name"] + setattr(cls, "removeContentInstance", removeContentInstance) + + def setText(self, text): + if self.content["name"] in ["IL","ST"]: + self.content["value"].setText(text) + else: + raise TypeError, "%s body don't have text!"%self.content["name"] + setattr(cls, "setText", setText) + + def getText(self): + if self.content["name"] in ["IL","ST"]: + return self.content["value"].getText() + else: + raise TypeError, "%s body don't have text!"%self.content["name"] + setattr(cls, "getText", getText) + + def getX(self): + return self.position.getX() + + def getY(self): + return self.position.getY() + + def setX(self, x): + self.position.setX(x) + + def setY(self, y): + self.position.setY(y) + + if "comment" in PLCOpenClasses: + cls = PLCOpenClasses["comment"] + setattr(cls, "getX", getX) + setattr(cls, "getY", getY) + setattr(cls, "setX", setX) + setattr(cls, "setY", setY) + + def setContentText(self, text): + self.content.setText(text) + setattr(cls, "setContentText", setContentText) + + def getContentText(self): + return self.content.getText() + setattr(cls, "getContentText", getContentText) + + if "block" in PLCOpenClasses: + cls = PLCOpenClasses["block"] + setattr(cls, "getX", getX) + setattr(cls, "getY", getY) + setattr(cls, "setX", setX) + setattr(cls, "setY", setY) + + if "inputVariables_variable" in PLCOpenClasses: + cls = PLCOpenClasses["inputVariables_variable"] + + def setConnectorEdge(self, edge): + if not self.edge: + self.edge = PLCOpenClasses["edgeModifierType"]() + self.edge.setValue(edge) + setattr(cls, "setConnectorEdge", setConnectorEdge) + + def getConnectorEdge(self): + if self.edge: + return self.edge.getValue() + return None + setattr(cls, "getConnectorEdge", getConnectorEdge) + + if "outputVariables_variable" in PLCOpenClasses: + cls = PLCOpenClasses["outputVariables_variable"] + + def setConnectorEdge(self, edge): + if not self.edge: + self.edge = PLCOpenClasses["edgeModifierType"]() + self.edge.setValue(edge) + setattr(cls, "setConnectorEdge", setConnectorEdge) + + def getConnectorEdge(self): + if self.edge: + return self.edge.getValue() + return None + setattr(cls, "getConnectorEdge", getConnectorEdge) + + if "leftPowerRail" in PLCOpenClasses: + cls = PLCOpenClasses["leftPowerRail"] + setattr(cls, "getX", getX) + setattr(cls, "getY", getY) + setattr(cls, "setX", setX) + setattr(cls, "setY", setY) + + if "contact" in PLCOpenClasses: + cls = PLCOpenClasses["contact"] + setattr(cls, "getX", getX) + setattr(cls, "getY", getY) + setattr(cls, "setX", setX) + setattr(cls, "setY", setY) + + def setContactEdge(self, edge): + if not self.edge: + self.edge = PLCOpenClasses["edgeModifierType"]() + self.edge.setValue(edge) + setattr(cls, "setContactEdge", setContactEdge) + + def getContactEdge(self): + if self.edge: + return self.edge.getValue() + return None + setattr(cls, "getContactEdge", getContactEdge) + + if "coil" in PLCOpenClasses: + cls = PLCOpenClasses["coil"] + setattr(cls, "getX", getX) + setattr(cls, "getY", getY) + setattr(cls, "setX", setX) + setattr(cls, "setY", setY) + + def setCoilStorage(self, edge): + if not self.storage: + self.storage = PLCOpenClasses["storageModifierType"]() + self.storage.setValue(edge) + setattr(cls, "setCoilStorage", setCoilStorage) + + def getCoilStorage(self): + if self.storage: + return self.storage.getValue() + return None + setattr(cls, "getCoilStorage", getCoilStorage) + + if "rightPowerRail" in PLCOpenClasses: + cls = PLCOpenClasses["rightPowerRail"] + setattr(cls, "getX", getX) + setattr(cls, "getY", getY) + setattr(cls, "setX", setX) + setattr(cls, "setY", setY) + + if "step" in PLCOpenClasses: + cls = PLCOpenClasses["step"] + setattr(cls, "getX", getX) + setattr(cls, "getY", getY) + setattr(cls, "setX", setX) + setattr(cls, "setY", setY) + + if "transition" in PLCOpenClasses: + cls = PLCOpenClasses["transition"] + setattr(cls, "getX", getX) + setattr(cls, "getY", getY) + setattr(cls, "setX", setX) + setattr(cls, "setY", setY) + + def setConditionContent(self, type, value): + if not self.condition: + self.addCondition() + if type == "reference": + condition = PLCOpenClasses["condition_reference"]() + condition.setName(value) + elif type == "inline": + condition = PLCOpenClasses["condition_inline"]() + condition.setContent("ST", PLCOpenClasses["formattedText"]()) + condition.setText(value) + self.condition.setContent(type, condition) + setattr(cls, "setConditionContent", setConditionContent) + + def getConditionContent(self): + if self.condition: + content = self.condition.getContent() + values = {"type" : content["name"]} + if values["type"] == "reference": + values["value"] = content["value"].getName() + elif values["type"] == "inline": + values["value"] = content["value"].getText() + return values + return "" + setattr(cls, "getConditionContent", getConditionContent) + + if "selectionDivergence" in PLCOpenClasses: + cls = PLCOpenClasses["selectionDivergence"] + setattr(cls, "getX", getX) + setattr(cls, "getY", getY) + setattr(cls, "setX", setX) + setattr(cls, "setY", setY) + + if "selectionConvergence" in PLCOpenClasses: + cls = PLCOpenClasses["selectionConvergence"] + setattr(cls, "getX", getX) + setattr(cls, "getY", getY) + setattr(cls, "setX", setX) + setattr(cls, "setY", setY) + + if "simultaneousDivergence" in PLCOpenClasses: + cls = PLCOpenClasses["simultaneousDivergence"] + setattr(cls, "getX", getX) + setattr(cls, "getY", getY) + setattr(cls, "setX", setX) + setattr(cls, "setY", setY) + + if "simultaneousDivergence" in PLCOpenClasses: + cls = PLCOpenClasses["simultaneousConvergence"] + setattr(cls, "getX", getX) + setattr(cls, "getY", getY) + setattr(cls, "setX", setX) + setattr(cls, "setY", setY) + + if "jumpStep" in PLCOpenClasses: + cls = PLCOpenClasses["jumpStep"] + setattr(cls, "getX", getX) + setattr(cls, "getY", getY) + setattr(cls, "setX", setX) + setattr(cls, "setY", setY) + + if "actionBlock_action" in PLCOpenClasses: + cls = PLCOpenClasses["actionBlock_action"] + + def setQualifierValue(self, value): + if self.qualifier: + self.qualifier.setValue(value) + setattr(cls, "setQualifierValue", setQualifierValue) + + def getQualifierValue(self): + if self.qualifier: + return self.qualifier.getValue() + return None + setattr(cls, "getQualifierValue", getQualifierValue) + + def setReferenceName(self, name): + if self.reference: + self.reference.setName(name) + setattr(cls, "setReferenceName", setReferenceName) + + def getReferenceName(self): + if self.reference: + return self.reference.getName() + return None + setattr(cls, "getReferenceName", getReferenceName) + + def setInlineContent(self, content): + if self.inline: + self.inline.setContent("ST", PLCOpenClasses["formattedText"]()) + self.inline.setText(content) + setattr(cls, "setInlineContent", setInlineContent) + + def getInlineContent(self): + if self.inline: + return self.inline.getText() + return None + setattr(cls, "getInlineContent", getInlineContent) + + if "actionBlock" in PLCOpenClasses: + cls = PLCOpenClasses["actionBlock"] + setattr(cls, "getX", getX) + setattr(cls, "getY", getY) + setattr(cls, "setX", setX) + setattr(cls, "setY", setY) + + def setActions(self, actions): + self.action = [] + for params in actions: + action = PLCOpenClasses["actionBlock_action"]() + action.addQualifier() + action.setQualifierValue(params["qualifier"]) + if params["type"] == "reference": + action.addReference() + action.setReferenceName(params["value"]) + else: + action.addInline() + action.setInlineContent(params["value"]) + if params["indicator"] != "": + action.setIndicator(params["indicator"]) + if "duration" in params: + action.setDuration(params["duration"]) + self.action.append(action) + setattr(cls, "setActions", setActions) + + def getActions(self): + actions = [] + for action in self.action: + params = {} + params["qualifier"] = action.getQualifierValue() + if action.getReference(): + params["type"] = "reference" + params["value"] = action.getReferenceName() + elif action.getInline(): + params["type"] = "inline" + params["value"] = action.getInlineContent() + duration = action.getDuration() + if duration: + params["duration"] = duration + indicator = action.getIndicator() + if indicator: + params["indicator"] = indicator + else: + params["indicator"] = "" + actions.append(params) + return actions + setattr(cls, "getActions", getActions) + + if "inVariable" in PLCOpenClasses: + cls = PLCOpenClasses["inVariable"] + setattr(cls, "getX", getX) + setattr(cls, "getY", getY) + setattr(cls, "setX", setX) + setattr(cls, "setY", setY) + + def setConnectorEdge(self, edge): + if not self.edge: + self.edge = PLCOpenClasses["edgeModifierType"]() + self.edge.setValue(edge) + setattr(cls, "setConnectorEdge", setConnectorEdge) + + def getConnectorEdge(self): + if self.edge: + return self.edge.getValue() + return None + setattr(cls, "getConnectorEdge", getConnectorEdge) + + if "outVariable" in PLCOpenClasses: + cls = PLCOpenClasses["outVariable"] + setattr(cls, "getX", getX) + setattr(cls, "getY", getY) + setattr(cls, "setX", setX) + setattr(cls, "setY", setY) + + def setConnectorEdge(self, edge): + if not self.edge: + self.edge = PLCOpenClasses["edgeModifierType"]() + self.edge.setValue(edge) + setattr(cls, "setConnectorEdge", setConnectorEdge) + + def getConnectorEdge(self): + if self.edge: + return self.edge.getValue() + return None + setattr(cls, "getConnectorEdge", getConnectorEdge) + + if "inOutVariable" in PLCOpenClasses: + cls = PLCOpenClasses["inOutVariable"] + setattr(cls, "getX", getX) + setattr(cls, "getY", getY) + setattr(cls, "setX", setX) + setattr(cls, "setY", setY) + + def setInputEdge(self, edge): + if not self.edgeIn: + self.edgeIn = PLCOpenClasses["edgeModifierType"]() + self.edgeIn.setValue(edge) + setattr(cls, "setInputEdge", setInputEdge) + + def getInputEdge(self): + if self.edgeIn: + return self.edgeIn.getValue() + return None + setattr(cls, "getInputEdge", getInputEdge) + + def setOutputEdge(self, edge): + if not self.edgeOut: + self.edgeOut = PLCOpenClasses["edgeModifierType"]() + self.edgeOut.setValue(edge) + setattr(cls, "setInputEdge", setInputEdge) + + def getOutputEdge(self): + if self.edgeOut: + return self.edgeOut.getValue() + return None + setattr(cls, "getOutputEdge", getOutputEdge) + + if "continuation" in PLCOpenClasses: + cls = PLCOpenClasses["continuation"] + setattr(cls, "getX", getX) + setattr(cls, "getY", getY) + setattr(cls, "setX", setX) + setattr(cls, "setY", setY) + + if "connector" in PLCOpenClasses: + cls = PLCOpenClasses["connector"] + setattr(cls, "getX", getX) + setattr(cls, "getY", getY) + setattr(cls, "setX", setX) + setattr(cls, "setY", setY) + + if "connection" in PLCOpenClasses: + cls = PLCOpenClasses["connection"] + + def setPoints(self, points): + self.position = [] + for point in points: + position = PLCOpenClasses["position"]() + position.setX(point.x) + position.setY(point.y) + self.position.append(position) + setattr(cls, "setPoints", setPoints) + + def getPoints(self): + points = [] + for position in self.position: + points.append((position.getX(),position.getY())) + return points + setattr(cls, "getPoints", getPoints) + + if "connectionPointIn" in PLCOpenClasses: + cls = PLCOpenClasses["connectionPointIn"] + + def setRelPosition(self, x, y): + self.relPosition = PLCOpenClasses["position"]() + self.relPosition.setX(x) + self.relPosition.setY(y) + setattr(cls, "setRelPosition", setRelPosition) + + def getRelPosition(self): + if self.relPosition: + return self.relPosition.getX(), self.relPosition.getY() + else: + return self.relPosition + setattr(cls, "getRelPosition", getRelPosition) + + def addConnection(self): + if not self.content: + self.content = {"name":"connection","value":[PLCOpenClasses["connection"]()]} + else: + self.content["value"].append(PLCOpenClasses["connection"]()) + setattr(cls, "addConnection", addConnection) + + def removeConnection(self, idx): + if self.content: + self.content["value"].pop(idx) + if len(self.content["value"]) == 0: + self.content = None + setattr(cls, "removeConnection", removeConnection) + + def removeConnections(self): + if self.content: + self.content = None + setattr(cls, "removeConnections", removeConnections) + + def getConnections(self): + if self.content: + return self.content["value"] + setattr(cls, "getConnections", getConnections) + + def setConnectionId(self, idx, id): + if self.content: + self.content["value"][idx].setRefLocalId(id) + setattr(cls, "setConnectionId", setConnectionId) + + def getConnectionId(self, idx): + if self.content: + return self.content["value"][idx].getRefLocalId() + return None + setattr(cls, "getConnectionId", getConnectionId) + + def setConnectionPoints(self, idx, points): + if self.content: + self.content["value"][idx].setPoints(points) + setattr(cls, "setConnectionPoints", setConnectionPoints) + + def getConnectionPoints(self, idx): + if self.content: + return self.content["value"][idx].getPoints() + return None + setattr(cls, "getConnectionPoints", getConnectionPoints) + + if "connectionPointOut" in PLCOpenClasses: + cls = PLCOpenClasses["connectionPointOut"] + + def setRelPosition(self, x, y): + self.relPosition = PLCOpenClasses["position"]() + self.relPosition.setX(x) + self.relPosition.setY(y) + setattr(cls, "setRelPosition", setRelPosition) + + def getRelPosition(self): + if self.relPosition: + return self.relPosition.getX(), self.relPosition.getY() + return self.relPosition + setattr(cls, "getRelPosition", getRelPosition) + + if "value" in PLCOpenClasses: + cls = PLCOpenClasses["value"] + + def setValue(self, value): + try: + value = eval(value) + except: + pass + if type(value) == ListType: + arrayValue = PLCOpenClasses["value_arrayValue"]() + arrayValue.setValue(value) + self.content = {"name":"arrayValue","value":arrayValue} + elif type(value) == DictType: + structValue = PLCOpenClasses["value_structValue"]() + structValue.setValue(value) + self.content = {"name":"structValue","value":structValue} + else: + simpleValue = PLCOpenClasses["value_simpleValue"]() + simpleValue.setValue(str(value)) + self.content = {"name":"simpleValue","value":simpleValue} + setattr(cls, "setValue", setValue) + + def getValue(self): + value = self.content["value"].getValue() + try: + value = eval(value) + except: + pass + return value + setattr(cls, "getValue", getValue) + + if "value_arrayValue" in PLCOpenClasses: + cls = PLCOpenClasses["value_arrayValue"] + + def setValue(self, array): + self.value = [] + for value in array: + element = PLCOpenClasses["arrayValue_value"]() + element.setValue(value) + self.value.append(element) + setattr(cls, "setValue", setValue) + + def getValue(self): + return [element.getValue() for element in self.value] + setattr(cls, "getValue", getValue) + + if "value_structValue" in PLCOpenClasses: + cls = PLCOpenClasses["value_structValue"] + + def setValue(self, dict): + self.value = [] + for name,value in dict.items(): + element = PLCOpenClasses["structValue_value"]() + element.setMember(name) + element.setValue(value) + self.value.append(element) + setattr(cls, "setValue", setValue) + + def getValue(self): + value = {} + for element in self.value: + value[element.getMember()] = element.getValue() + return value + setattr(cls, "getValue", getValue) + +if sys: + sys.stdout = HolePseudoFile() +xsdschema = pyxsval.parseAndValidateXmlSchema("plcopen/TC6_XML_V10_B.xsd") +if sys: + sys.stdout = sys.__stdout__ +Generate_classes(xsdschema.getTree(), None) + +PLCOpenClasses = {} +PLCOpenTypes = {} +#for classname, classe in classes.items(): +# print "%s : %s\n"%(classname, str(classe)) +"""classnames = classes.keys() +classnames.sort() +for classname in classnames: + print classname""" +for classe in classes.keys(): + CreateClass(classe) +Generate_Methods()