etisserant@0: #!/usr/bin/env python etisserant@0: # -*- coding: utf-8 -*- etisserant@0: etisserant@0: #This file is part of PLCOpenEditor, a library implementing an IEC 61131-3 editor etisserant@0: #based on the plcopen standard. etisserant@0: # lbessard@58: #Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD etisserant@0: # etisserant@0: #See COPYING file for copyrights details. etisserant@0: # etisserant@0: #This library is free software; you can redistribute it and/or etisserant@5: #modify it under the terms of the GNU General Public etisserant@0: #License as published by the Free Software Foundation; either etisserant@0: #version 2.1 of the License, or (at your option) any later version. etisserant@0: # etisserant@0: #This library is distributed in the hope that it will be useful, etisserant@0: #but WITHOUT ANY WARRANTY; without even the implied warranty of etisserant@0: #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU lbessard@58: #General Public License for more details. etisserant@0: # etisserant@5: #You should have received a copy of the GNU General Public etisserant@0: #License along with this library; if not, write to the Free Software etisserant@0: #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA etisserant@0: lbessard@27: from xml.dom import minidom laurent@567: from types import StringType, UnicodeType, TupleType etisserant@0: import cPickle etisserant@0: import os,sys,re laurent@385: import datetime lbessard@145: from time import localtime etisserant@0: etisserant@0: from plcopen import plcopen etisserant@0: from plcopen.structures import * etisserant@0: from graphics.GraphicCommons import * etisserant@0: from PLCGenerator import * etisserant@0: lbessard@188: duration_model = re.compile("(?:([0-9]{1,2})h)?(?:([0-9]{1,2})m(?!s))?(?:([0-9]{1,2})s)?(?:([0-9]{1,3}(?:\.[0-9]*)?)ms)?") lbessard@24: etisserant@184: ITEMS_EDITABLE = [ITEM_PROJECT, lbessard@249: ITEM_POU, lbessard@249: ITEM_VARIABLE, lbessard@249: ITEM_TRANSITION, lbessard@249: ITEM_ACTION, lbessard@249: ITEM_CONFIGURATION, lbessard@249: ITEM_RESOURCE, lbessard@249: ITEM_DATATYPE lbessard@249: ] = range(8) lbessard@249: lbessard@249: ITEMS_UNEDITABLE = [ITEM_DATATYPES, lbessard@249: ITEM_FUNCTION, lbessard@249: ITEM_FUNCTIONBLOCK, lbessard@249: ITEM_PROGRAM, lbessard@249: ITEM_TRANSITIONS, lbessard@249: ITEM_ACTIONS, lbessard@249: ITEM_CONFIGURATIONS, lbessard@249: ITEM_RESOURCES, lbessard@249: ITEM_PROPERTIES lbessard@249: ] = range(8, 17) lbessard@249: lbessard@249: ITEMS_VARIABLE = [ITEM_VAR_LOCAL, lbessard@236: ITEM_VAR_GLOBAL, lbessard@236: ITEM_VAR_EXTERNAL, lbessard@236: ITEM_VAR_TEMP, lbessard@236: ITEM_VAR_INPUT, lbessard@236: ITEM_VAR_OUTPUT, lbessard@249: ITEM_VAR_INOUT lbessard@249: ] = range(17, 24) lbessard@236: lbessard@236: VAR_CLASS_INFOS = {"Local" : (plcopen.interface_localVars, ITEM_VAR_LOCAL), lbessard@236: "Global" : (plcopen.interface_globalVars, ITEM_VAR_GLOBAL), lbessard@236: "External" : (plcopen.interface_externalVars, ITEM_VAR_EXTERNAL), lbessard@236: "Temp" : (plcopen.interface_tempVars, ITEM_VAR_TEMP), lbessard@236: "Input" : (plcopen.interface_inputVars, ITEM_VAR_INPUT), lbessard@236: "Output" : (plcopen.interface_outputVars, ITEM_VAR_OUTPUT), lbessard@236: "InOut" : (plcopen.interface_inOutVars, ITEM_VAR_INOUT) lbessard@236: } lbessard@125: laurent@684: POU_TYPES = {"program": ITEM_PROGRAM, laurent@684: "functionBlock": ITEM_FUNCTIONBLOCK, laurent@684: "function": ITEM_FUNCTION, laurent@684: } laurent@684: Edouard@681: LOCATIONS_ITEMS = [LOCATION_CONFNODE, laurent@435: LOCATION_MODULE, laurent@435: LOCATION_GROUP, laurent@435: LOCATION_VAR_INPUT, laurent@435: LOCATION_VAR_OUTPUT, laurent@435: LOCATION_VAR_MEMORY] = range(6) laurent@435: lbessard@125: ScriptDirectory = os.path.split(os.path.realpath(__file__))[0] etisserant@0: laurent@391: def GetUneditableNames(): laurent@391: _ = lambda x:x laurent@391: return [_("User-defined POUs"), _("Functions"), _("Function Blocks"), laurent@391: _("Programs"), _("Data Types"), _("Transitions"), _("Actions"), laurent@391: _("Configurations"), _("Resources"), _("Properties")] laurent@391: UNEDITABLE_NAMES = GetUneditableNames() laurent@391: [USER_DEFINED_POUS, FUNCTIONS, FUNCTION_BLOCKS, PROGRAMS, laurent@391: DATA_TYPES, TRANSITIONS, ACTIONS, CONFIGURATIONS, laurent@391: RESOURCES, PROPERTIES] = UNEDITABLE_NAMES laurent@391: etisserant@0: #------------------------------------------------------------------------------- etisserant@0: # Undo Buffer for PLCOpenEditor etisserant@0: #------------------------------------------------------------------------------- etisserant@0: etisserant@0: # Length of the buffer etisserant@0: UNDO_BUFFER_LENGTH = 20 etisserant@0: etisserant@0: """ lbessard@188: Class implementing a buffer of changes made on the current editing model etisserant@0: """ etisserant@0: class UndoBuffer: etisserant@0: etisserant@0: # Constructor initialising buffer etisserant@0: def __init__(self, currentstate, issaved = False): etisserant@0: self.Buffer = [] etisserant@0: self.CurrentIndex = -1 etisserant@0: self.MinIndex = -1 etisserant@0: self.MaxIndex = -1 etisserant@0: # if current state is defined etisserant@0: if currentstate: etisserant@0: self.CurrentIndex = 0 etisserant@0: self.MinIndex = 0 etisserant@0: self.MaxIndex = 0 etisserant@0: # Initialising buffer with currentstate at the first place etisserant@0: for i in xrange(UNDO_BUFFER_LENGTH): etisserant@0: if i == 0: etisserant@0: self.Buffer.append(currentstate) etisserant@0: else: etisserant@0: self.Buffer.append(None) etisserant@0: # Initialising index of state saved etisserant@0: if issaved: etisserant@0: self.LastSave = 0 etisserant@0: else: etisserant@0: self.LastSave = -1 etisserant@0: etisserant@0: # Add a new state in buffer etisserant@0: def Buffering(self, currentstate): etisserant@0: self.CurrentIndex = (self.CurrentIndex + 1) % UNDO_BUFFER_LENGTH etisserant@0: self.Buffer[self.CurrentIndex] = currentstate etisserant@0: # Actualising buffer limits etisserant@0: self.MaxIndex = self.CurrentIndex etisserant@0: if self.MinIndex == self.CurrentIndex: etisserant@0: # If the removed state was the state saved, there is no state saved in the buffer etisserant@0: if self.LastSave == self.MinIndex: etisserant@0: self.LastSave = -1 etisserant@0: self.MinIndex = (self.MinIndex + 1) % UNDO_BUFFER_LENGTH etisserant@0: self.MinIndex = max(self.MinIndex, 0) etisserant@0: etisserant@0: # Return current state of buffer etisserant@0: def Current(self): etisserant@0: return self.Buffer[self.CurrentIndex] etisserant@0: etisserant@0: # Change current state to previous in buffer and return new current state etisserant@0: def Previous(self): etisserant@0: if self.CurrentIndex != self.MinIndex: etisserant@0: self.CurrentIndex = (self.CurrentIndex - 1) % UNDO_BUFFER_LENGTH etisserant@0: return self.Buffer[self.CurrentIndex] etisserant@0: return None etisserant@0: etisserant@0: # Change current state to next in buffer and return new current state etisserant@0: def Next(self): etisserant@0: if self.CurrentIndex != self.MaxIndex: etisserant@0: self.CurrentIndex = (self.CurrentIndex + 1) % UNDO_BUFFER_LENGTH etisserant@0: return self.Buffer[self.CurrentIndex] etisserant@0: return None etisserant@0: etisserant@0: # Return True if current state is the first in buffer etisserant@0: def IsFirst(self): etisserant@0: return self.CurrentIndex == self.MinIndex etisserant@0: etisserant@0: # Return True if current state is the last in buffer etisserant@0: def IsLast(self): etisserant@0: return self.CurrentIndex == self.MaxIndex etisserant@0: etisserant@0: # Note that current state is saved etisserant@0: def CurrentSaved(self): etisserant@0: self.LastSave = self.CurrentIndex etisserant@0: etisserant@0: # Return True if current state is saved etisserant@0: def IsCurrentSaved(self): etisserant@0: return self.LastSave == self.CurrentIndex etisserant@0: etisserant@0: etisserant@0: #------------------------------------------------------------------------------- etisserant@0: # Controler for PLCOpenEditor etisserant@0: #------------------------------------------------------------------------------- etisserant@0: etisserant@0: """ etisserant@0: Class which controls the operations made on the plcopen model and answers to view requests etisserant@0: """ etisserant@0: class PLCControler: etisserant@0: etisserant@0: # Create a new PLCControler etisserant@0: def __init__(self): etisserant@0: self.LastNewIndex = 0 etisserant@0: self.Reset() etisserant@0: etisserant@0: # Reset PLCControler internal variables etisserant@0: def Reset(self): etisserant@0: self.Project = None laurent@530: self.ProjectBufferEnabled = True etisserant@0: self.ProjectBuffer = None greg@352: self.ProjectSaved = True lbessard@56: self.Buffering = False etisserant@0: self.FilePath = "" etisserant@0: self.FileName = "" lbessard@226: self.ProgramChunks = [] greg@369: self.ProgramOffset = 0 lbessard@252: self.NextCompiledProject = None lbessard@249: self.CurrentCompiledProject = None Edouard@681: self.ConfNodeTypes = [] lbessard@42: self.ProgramFilePath = "" lbessard@226: etisserant@0: def GetQualifierTypes(self): etisserant@0: return plcopen.QualifierList etisserant@0: lbessard@249: def GetProject(self, debug = False): lbessard@249: if debug and self.CurrentCompiledProject is not None: lbessard@249: return self.CurrentCompiledProject lbessard@249: else: lbessard@249: return self.Project lbessard@249: etisserant@0: #------------------------------------------------------------------------------- etisserant@0: # Project management functions etisserant@0: #------------------------------------------------------------------------------- etisserant@0: etisserant@0: # Return if a project is opened etisserant@0: def HasOpenedProject(self): lbessard@249: return self.Project is not None etisserant@0: etisserant@0: # Create a new project by replacing the current one lbessard@145: def CreateNewProject(self, properties): etisserant@0: # Create the project etisserant@0: self.Project = plcopen.project() laurent@385: properties["creationDateTime"] = datetime.datetime(*localtime()[:6]) lbessard@151: self.Project.setfileHeader(properties) lbessard@151: self.Project.setcontentHeader(properties) lbessard@56: self.SetFilePath("") etisserant@0: # Initialize the project buffer greg@349: self.CreateProjectBuffer(False) lbessard@249: self.ProgramChunks = [] greg@369: self.ProgramOffset = 0 lbessard@252: self.NextCompiledProject = self.Copy(self.Project) lbessard@249: self.CurrentCompiledProject = None lbessard@56: self.Buffering = False etisserant@0: lbessard@125: # Return project data type names lbessard@249: def GetProjectDataTypeNames(self, debug = False): lbessard@249: project = self.GetProject(debug) lbessard@249: if project is not None: lbessard@249: return [datatype.getname() for datatype in project.getdataTypes()] lbessard@125: return [] lbessard@125: etisserant@0: # Return project pou names lbessard@249: def GetProjectPouNames(self, debug = False): lbessard@249: project = self.GetProject(debug) lbessard@249: if project is not None: lbessard@249: return [pou.getname() for pou in project.getpous()] lbessard@80: return [] etisserant@0: etisserant@0: # Return project pou names lbessard@249: def GetProjectConfigNames(self, debug = False): lbessard@249: project = self.GetProject(debug) lbessard@249: if project is not None: b@421: return [config.getname() for config in project.getconfigurations()] lbessard@80: return [] etisserant@0: lbessard@6: # Return project pou variables lbessard@249: def GetProjectPouVariables(self, pou_name = None, debug = False): lbessard@6: variables = [] lbessard@249: project = self.GetProject(debug) lbessard@249: if project is not None: lbessard@249: for pou in project.getpous(): lbessard@249: if pou_name is None or pou_name == pou.getname(): lbessard@295: variables.extend([var["Name"] for var in self.GetPouInterfaceVars(pou, debug)]) lbessard@249: for transition in pou.gettransitionList(): lbessard@249: variables.append(transition.getname()) lbessard@249: for action in pou.getactionList(): lbessard@249: variables.append(action.getname()) lbessard@6: return variables lbessard@6: etisserant@0: # Return file path if project is an open file etisserant@0: def GetFilePath(self): etisserant@0: return self.FilePath etisserant@0: lbessard@42: # Return file path if project is an open file lbessard@42: def GetProgramFilePath(self): lbessard@42: return self.ProgramFilePath lbessard@42: etisserant@0: # Return file name and point out if file is up to date etisserant@0: def GetFilename(self): lbessard@249: if self.Project is not None: greg@349: if self.ProjectIsSaved(): lbessard@249: return self.FileName lbessard@249: else: lbessard@249: return "~%s~"%self.FileName lbessard@249: return "" etisserant@0: etisserant@0: # Change file path and save file name or create a default one if file path not defined etisserant@0: def SetFilePath(self, filepath): etisserant@0: self.FilePath = filepath etisserant@0: if filepath == "": etisserant@0: self.LastNewIndex += 1 laurent@391: self.FileName = _("Unnamed%d")%self.LastNewIndex etisserant@0: else: etisserant@0: self.FileName = os.path.splitext(os.path.basename(filepath))[0] etisserant@0: etisserant@0: # Change project properties laurent@647: def SetProjectProperties(self, name = None, properties = None, buffer = True): lbessard@249: if self.Project is not None: lbessard@249: if name is not None: lbessard@249: self.Project.setname(name) lbessard@249: if properties is not None: lbessard@249: self.Project.setfileHeader(properties) lbessard@249: self.Project.setcontentHeader(properties) Laurent@707: if buffer and (name is not None or properties is not None): lbessard@249: self.BufferProject() laurent@566: laurent@566: # Return project name laurent@566: def GetProjectName(self, debug=False): laurent@566: project = self.GetProject(debug) laurent@566: if project is not None: laurent@566: return project.getname() laurent@566: return None laurent@566: etisserant@0: # Return project properties lbessard@249: def GetProjectProperties(self, debug = False): lbessard@249: project = self.GetProject(debug) lbessard@249: if project is not None: lbessard@249: properties = project.getfileHeader() lbessard@249: properties.update(project.getcontentHeader()) lbessard@249: return properties lbessard@249: return None etisserant@0: etisserant@0: # Return project informations lbessard@249: def GetProjectInfos(self, debug = False): lbessard@249: project = self.GetProject(debug) lbessard@249: if project is not None: lbessard@249: infos = {"name": project.getname(), "type": ITEM_PROJECT} laurent@391: datatypes = {"name": DATA_TYPES, "type": ITEM_DATATYPES, "values":[]} lbessard@249: for datatype in project.getdataTypes(): lbessard@226: datatypes["values"].append({"name": datatype.getname(), "type": ITEM_DATATYPE, lbessard@226: "tagname": self.ComputeDataTypeName(datatype.getname()), "values": []}) laurent@391: pou_types = {"function": {"name": FUNCTIONS, "type": ITEM_FUNCTION, "values":[]}, laurent@391: "functionBlock": {"name": FUNCTION_BLOCKS, "type": ITEM_FUNCTIONBLOCK, "values":[]}, laurent@391: "program": {"name": PROGRAMS, "type": ITEM_PROGRAM, "values":[]}} lbessard@249: for pou in project.getpous(): lbessard@151: pou_type = pou.getpouType() lbessard@226: pou_infos = {"name": pou.getname(), "type": ITEM_POU, lbessard@226: "tagname": self.ComputePouName(pou.getname())} etisserant@0: pou_values = [] lbessard@151: if pou.getbodyType() == "SFC": etisserant@0: transitions = [] lbessard@151: for transition in pou.gettransitionList(): lbessard@226: transitions.append({"name": transition.getname(), "type": ITEM_TRANSITION, lbessard@226: "tagname": self.ComputePouTransitionName(pou.getname(), transition.getname()), lbessard@226: "values": []}) laurent@391: pou_values.append({"name": TRANSITIONS, "type": ITEM_TRANSITIONS, "values": transitions}) etisserant@0: actions = [] lbessard@151: for action in pou.getactionList(): lbessard@226: actions.append({"name": action.getname(), "type": ITEM_ACTION, lbessard@226: "tagname": self.ComputePouActionName(pou.getname(), action.getname()), lbessard@226: "values": []}) laurent@391: pou_values.append({"name": ACTIONS, "type": ITEM_ACTIONS, "values": actions}) etisserant@0: if pou_type in pou_types: etisserant@0: pou_infos["values"] = pou_values etisserant@0: pou_types[pou_type]["values"].append(pou_infos) laurent@391: configurations = {"name": CONFIGURATIONS, "type": ITEM_CONFIGURATIONS, "values": []} lbessard@249: for config in project.getconfigurations(): lbessard@151: config_name = config.getname() lbessard@226: config_infos = {"name": config_name, "type": ITEM_CONFIGURATION, lbessard@226: "tagname": self.ComputeConfigurationName(config.getname()), lbessard@226: "values": []} laurent@391: resources = {"name": RESOURCES, "type": ITEM_RESOURCES, "values": []} lbessard@151: for resource in config.getresource(): lbessard@151: resource_name = resource.getname() lbessard@226: resource_infos = {"name": resource_name, "type": ITEM_RESOURCE, lbessard@226: "tagname": self.ComputeConfigurationResourceName(config.getname(), resource.getname()), lbessard@226: "values": []} etisserant@0: resources["values"].append(resource_infos) lbessard@47: config_infos["values"] = [resources] etisserant@0: configurations["values"].append(config_infos) laurent@684: infos["values"] = [datatypes, pou_types["function"], pou_types["functionBlock"], etisserant@0: pou_types["program"], configurations] etisserant@0: return infos etisserant@0: return None etisserant@0: laurent@684: def GetPouVariableInfos(self, project, variable, var_class, debug=False): laurent@684: vartype_content = variable.gettype().getcontent() laurent@684: if vartype_content["name"] == "derived": laurent@684: var_type = vartype_content["value"].getname() laurent@684: pou_type = None laurent@684: pou = project.getpou(var_type) laurent@684: if pou is not None: laurent@684: pou_type = pou.getpouType() laurent@684: edit = debug = pou_type is not None laurent@684: if pou_type is None: laurent@684: block_infos = self.GetBlockType(var_type, debug = debug) laurent@693: if block_infos is not None: laurent@692: pou_type = block_infos["type"] laurent@684: if pou_type is not None: laurent@684: var_class = None laurent@684: if pou_type == "program": laurent@684: var_class = ITEM_PROGRAM laurent@684: elif pou_type != "function": laurent@684: var_class = ITEM_FUNCTIONBLOCK laurent@684: if var_class is not None: laurent@684: return {"name": variable.getname(), laurent@684: "type": var_type, laurent@684: "class": var_class, laurent@684: "edit": edit, laurent@684: "debug": debug} laurent@684: elif var_type in self.GetDataTypes(debug = debug): laurent@684: return {"name": variable.getname(), laurent@684: "type": var_type, laurent@684: "class": var_class, laurent@684: "edit": False, laurent@684: "debug": False} laurent@684: elif vartype_content["name"] in ["string", "wstring"]: laurent@684: return {"name": variable.getname(), laurent@684: "type": vartype_content["name"].upper(), laurent@684: "class": var_class, laurent@684: "edit": False, laurent@684: "debug": True} laurent@684: else: laurent@684: return {"name": variable.getname(), laurent@684: "type": vartype_content["name"], laurent@684: "class": var_class, laurent@684: "edit": False, laurent@684: "debug": True} laurent@684: return None laurent@684: laurent@684: def GetPouVariables(self, tagname, debug = False): laurent@684: vars = [] laurent@684: pou_type = None laurent@684: project = self.GetProject(debug) laurent@684: if project is not None: laurent@684: words = tagname.split("::") laurent@684: if words[0] == "P": laurent@684: pou = project.getpou(words[1]) laurent@684: if pou is not None: laurent@684: pou_type = pou.getpouType() laurent@684: if (pou_type in ["program", "functionBlock"] and laurent@684: pou.interface is not None): laurent@684: # Extract variables from every varLists laurent@684: for varlist_type, varlist in pou.getvars(): laurent@684: var_infos = VAR_CLASS_INFOS.get(varlist_type, None) laurent@684: if var_infos is not None: laurent@684: var_class = var_infos[1] laurent@684: else: laurent@684: var_class = ITEM_VAR_LOCAL laurent@684: for variable in varlist.getvariable(): laurent@684: var_infos = self.GetPouVariableInfos(project, variable, var_class, debug) laurent@684: if var_infos is not None: laurent@684: vars.append(var_infos) laurent@684: return {"class": POU_TYPES[pou_type], laurent@684: "type": words[1], laurent@684: "variables": vars, laurent@684: "edit": True, laurent@684: "debug": True} laurent@684: else: laurent@684: block_infos = self.GetBlockType(words[1], debug = debug) laurent@684: if (block_infos is not None and laurent@684: block_infos["type"] in ["program", "functionBlock"]): laurent@684: for varname, vartype, varmodifier in block_infos["inputs"]: laurent@684: vars.append({"name" : varname, laurent@684: "type" : vartype, laurent@684: "class" : ITEM_VAR_INPUT, laurent@684: "edit": False, laurent@684: "debug": True}) laurent@684: for varname, vartype, varmodifier in block_infos["outputs"]: laurent@684: vars.append({"name" : varname, laurent@684: "type" : vartype, laurent@684: "class" : ITEM_VAR_OUTPUT, laurent@684: "edit": False, laurent@684: "debug": True}) laurent@684: return {"class": POU_TYPES[block_infos["type"]], laurent@684: "type": None, laurent@684: "variables": vars, laurent@684: "edit": False, laurent@684: "debug": False} laurent@684: elif words[0] in ['C', 'R']: laurent@684: if words[0] == 'C': Laurent@705: element_type = ITEM_CONFIGURATION laurent@684: element = project.getconfiguration(words[1]) Laurent@705: if element is not None: Laurent@705: for resource in element.getresource(): Laurent@705: vars.append({"name": resource.getname(), Laurent@705: "type": None, Laurent@705: "class": ITEM_RESOURCE, Laurent@705: "edit": True, Laurent@705: "debug": False}) laurent@684: elif words[0] == 'R': Laurent@705: element_type = ITEM_RESOURCE laurent@684: element = project.getconfigurationResource(words[1], words[2]) Laurent@705: if element is not None: Laurent@705: for task in element.gettask(): Laurent@705: for pou in task.getpouInstance(): Laurent@705: vars.append({"name": pou.getname(), Laurent@705: "type": pou.gettypeName(), Laurent@705: "class": ITEM_PROGRAM, Laurent@705: "edit": True, Laurent@705: "debug": True}) Laurent@705: for pou in element.getpouInstance(): laurent@684: vars.append({"name": pou.getname(), laurent@684: "type": pou.gettypeName(), laurent@684: "class": ITEM_PROGRAM, laurent@684: "edit": True, laurent@684: "debug": True}) Laurent@705: if element is not None: Laurent@705: for varlist in element.getglobalVars(): Laurent@705: for variable in varlist.getvariable(): Laurent@705: var_infos = self.GetPouVariableInfos(project, variable, ITEM_VAR_GLOBAL, debug) Laurent@705: if var_infos is not None: Laurent@705: vars.append(var_infos) Laurent@705: return {"class": element_type, Laurent@705: "type": None, Laurent@705: "variables": vars, Laurent@705: "edit": True, Laurent@705: "debug": False} laurent@684: return None laurent@684: laurent@684: def RecursiveSearchPouInstances(self, project, pou_type, parent_path, varlists, debug = False): laurent@684: instances = [] laurent@684: for varlist in varlists: laurent@684: for variable in varlist.getvariable(): laurent@684: vartype_content = variable.gettype().getcontent() laurent@684: if vartype_content["name"] == "derived": laurent@684: var_path = "%s.%s" % (parent_path, variable.getname()) laurent@684: var_type = vartype_content["value"].getname() laurent@684: if var_type == pou_type: laurent@684: instances.append(var_path) laurent@684: else: laurent@684: pou = project.getpou(var_type) laurent@684: if pou is not None: laurent@684: instances.extend( laurent@684: self.RecursiveSearchPouInstances( laurent@684: project, pou_type, var_path, laurent@684: [varlist for type, varlist in pou.getvars()], laurent@684: debug)) laurent@684: return instances laurent@684: laurent@684: def SearchPouInstances(self, tagname, debug = False): laurent@684: project = self.GetProject(debug) laurent@684: if project is not None: laurent@684: words = tagname.split("::") laurent@684: if words[0] == "P": laurent@684: instances = [] laurent@684: for config in project.getconfigurations(): laurent@684: config_name = config.getname() laurent@684: instances.extend( laurent@684: self.RecursiveSearchPouInstances( laurent@684: project, words[1], config_name, laurent@684: config.getglobalVars(), debug)) laurent@684: for resource in config.getresource(): laurent@684: res_path = "%s.%s" % (config_name, resource.getname()) laurent@684: instances.extend( laurent@684: self.RecursiveSearchPouInstances( laurent@684: project, words[1], res_path, laurent@684: resource.getglobalVars(), debug)) laurent@684: pou_instances = resource.getpouInstance()[:] laurent@684: for task in resource.gettask(): laurent@684: pou_instances.extend(task.getpouInstance()) laurent@684: for pou_instance in pou_instances: laurent@684: pou_path = "%s.%s" % (res_path, pou_instance.getname()) laurent@684: pou_type = pou_instance.gettypeName() laurent@684: if pou_type == words[1]: laurent@684: instances.append(pou_path) laurent@684: pou = project.getpou(pou_type) laurent@684: if pou is not None: laurent@684: instances.extend( laurent@684: self.RecursiveSearchPouInstances( laurent@684: project, words[1], pou_path, laurent@684: [varlist for type, varlist in pou.getvars()], laurent@684: debug)) laurent@684: return instances laurent@684: elif words[0] == 'C': laurent@684: return [words[1]] laurent@684: elif words[0] == 'R': laurent@684: return ["%s.%s" % (words[1], words[2])] laurent@684: return [] laurent@684: laurent@687: def RecursiveGetPouInstanceTagName(self, project, pou_type, parts): laurent@684: pou = project.getpou(pou_type) laurent@684: if pou is not None: laurent@684: if len(parts) == 0: laurent@684: return self.ComputePouName(pou_type) laurent@684: laurent@684: for varlist_type, varlist in pou.getvars(): laurent@684: for variable in varlist.getvariable(): laurent@684: vartype_content = variable.gettype().getcontent() laurent@684: if vartype_content["name"] == "derived": laurent@687: return self.RecursiveGetPouInstanceTagName( laurent@684: project, laurent@684: vartype_content["value"].getname(), laurent@684: parts[1:]) laurent@684: return None laurent@684: laurent@687: def GetPouInstanceTagName(self, instance_path, debug = False): laurent@684: parts = instance_path.split(".") laurent@684: if len(parts) == 1: laurent@684: return self.ComputeConfigurationName(parts[0]) laurent@684: elif len(parts) == 2: laurent@684: return self.ComputeConfigurationResourceName(parts[0], parts[1]) laurent@684: else: laurent@684: project = self.GetProject(debug) laurent@684: for config in project.getconfigurations(): laurent@684: if config.getname() == parts[0]: laurent@684: for resource in config.getresource(): laurent@684: if resource.getname() == parts[1]: laurent@684: pou_instances = resource.getpouInstance()[:] laurent@684: for task in resource.gettask(): laurent@684: pou_instances.extend(task.getpouInstance()) laurent@684: for pou_instance in pou_instances: laurent@684: if pou_instance.getname() == parts[2]: laurent@684: if len(parts) == 3: laurent@684: return self.ComputePouName( laurent@684: pou_instance.gettypeName()) laurent@684: else: laurent@687: return self.RecursiveGetPouInstanceTagName( laurent@684: project, laurent@684: pou_instance.gettypeName(), laurent@684: parts[3:]) laurent@684: return None laurent@684: laurent@687: def GetInstanceInfos(self, instance_path, debug = False): laurent@684: tagname = self.GetPouInstanceTagName(instance_path) laurent@684: if tagname is not None: laurent@687: return self.GetPouVariables(tagname, debug) laurent@684: else: laurent@687: pou_path, var_name = instance_path.rsplit(".", 1) laurent@687: tagname = self.GetPouInstanceTagName(pou_path) laurent@684: if tagname is not None: laurent@687: pou_infos = self.GetPouVariables(tagname, debug) laurent@684: for var_infos in pou_infos["variables"]: laurent@684: if var_infos["name"] == var_name: laurent@684: return var_infos laurent@684: return None laurent@687: lbessard@125: # Return if data type given by name is used by another data type or pou lbessard@249: def DataTypeIsUsed(self, name, debug = False): lbessard@249: project = self.GetProject(debug) lbessard@249: if project is not None: lbessard@249: return project.ElementIsUsed(name) or project.DataTypeIsDerived(name) lbessard@249: return False lbessard@125: etisserant@0: # Return if pou given by name is used by another pou lbessard@249: def PouIsUsed(self, name, debug = False): lbessard@249: project = self.GetProject(debug) lbessard@249: if project is not None: lbessard@249: return project.ElementIsUsed(name) lbessard@249: return False lbessard@125: etisserant@0: # Return if pou given by name is directly or undirectly used by the reference pou lbessard@249: def PouIsUsedBy(self, name, reference, debug = False): lbessard@249: project = self.GetProject(debug) lbessard@249: if project is not None: lbessard@249: return project.ElementIsUsedBy(name, reference) lbessard@249: return False etisserant@0: greg@293: def GenerateProgram(self, filepath=None): lbessard@307: errors = [] lbessard@307: warnings = [] lbessard@249: if self.Project is not None: lbessard@97: try: lbessard@307: self.ProgramChunks = GenerateCurrentProgram(self, self.Project, errors, warnings) lbessard@252: self.NextCompiledProject = self.Copy(self.Project) laurent@622: program_text = "".join([item[0].decode("utf-8") for item in self.ProgramChunks]) greg@293: if filepath is not None: greg@293: programfile = open(filepath, "w") laurent@622: programfile.write(program_text.encode("utf-8")) greg@293: programfile.close() greg@293: self.ProgramFilePath = filepath lbessard@307: return program_text, errors, warnings etisserant@171: except PLCGenException, e: lbessard@307: errors.append(e.message) lbessard@307: else: lbessard@307: errors.append("No project opened") lbessard@307: return "", errors, warnings etisserant@0: laurent@407: def DebugAvailable(self): laurent@407: return self.CurrentCompiledProject is not None laurent@407: lbessard@252: def ProgramTransferred(self): laurent@661: if self.NextCompiledProject is None: laurent@661: self.CurrentCompiledProject = self.NextCompiledProject laurent@661: else: laurent@661: self.CurrentCompiledProject = self.Copy(self.Project) lbessard@252: lbessard@226: def GetChunkInfos(self, from_location, to_location): greg@369: row = self.ProgramOffset + 1 greg@369: col = 1 lbessard@226: infos = [] lbessard@226: for chunk, chunk_infos in self.ProgramChunks: lbessard@226: lines = chunk.split("\n") lbessard@226: if len(lines) > 1: lbessard@226: next_row = row + len(lines) - 1 lbessard@226: next_col = len(lines[-1]) + 1 lbessard@226: else: lbessard@236: next_row = row lbessard@226: next_col = col + len(chunk) lbessard@229: if (next_row > from_location[0] or next_row == from_location[0] and next_col >= from_location[1]) and len(chunk_infos) > 0: lbessard@226: infos.append((chunk_infos, (row, col))) lbessard@226: if next_row == to_location[0] and next_col > to_location[1] or next_row > to_location[0]: lbessard@226: return infos lbessard@226: row, col = next_row, next_col lbessard@226: return infos lbessard@226: etisserant@0: #------------------------------------------------------------------------------- etisserant@0: # Project Pous management functions etisserant@0: #------------------------------------------------------------------------------- lbessard@125: lbessard@125: # Add a Data Type to Project Laurent@705: def ProjectAddDataType(self, datatype_name=None): Laurent@705: if self.Project is not None: Laurent@705: if datatype_name is None: Laurent@705: datatype_name = self.GenerateNewName(None, None, "datatype%d") lbessard@249: # Add the datatype to project lbessard@249: self.Project.appenddataType(datatype_name) lbessard@249: self.BufferProject() laurent@555: return self.ComputeDataTypeName(datatype_name) laurent@555: return None lbessard@249: lbessard@125: # Remove a Data Type from project lbessard@125: def ProjectRemoveDataType(self, datatype_name): lbessard@249: if self.Project is not None: lbessard@249: self.Project.removedataType(datatype_name) lbessard@249: self.BufferProject() lbessard@125: etisserant@0: # Add a Pou to Project lbessard@107: def ProjectAddPou(self, pou_name, pou_type, body_type): lbessard@249: if self.Project is not None: lbessard@249: # Add the pou to project lbessard@249: self.Project.appendpou(pou_name, pou_type, body_type) lbessard@249: if pou_type == "function": lbessard@249: self.SetPouInterfaceReturnType(pou_name, "BOOL") lbessard@249: self.BufferProject() laurent@555: return self.ComputePouName(pou_name) laurent@555: return None etisserant@0: lbessard@275: def ProjectChangePouType(self, name, pou_type): lbessard@275: if self.Project is not None: lbessard@275: pou = self.Project.getpou(name) lbessard@275: if pou is not None: lbessard@275: pou.setpouType(pou_type) laurent@526: self.Project.RefreshCustomBlockTypes() lbessard@275: self.BufferProject() lbessard@275: laurent@447: def GetPouXml(self, pou_name): laurent@447: if self.Project is not None: laurent@447: pou = self.Project.getpou(pou_name) lbessard@274: if pou is not None: laurent@447: return pou.generateXMLText('pou', 0) laurent@447: return None lbessard@274: b@428: def PastePou(self, pou_type, pou_xml): b@428: ''' b@428: Adds the POU defined by 'pou_xml' to the current project with type 'pou_type' b@428: ''' b@428: try: laurent@629: tree = minidom.parseString(pou_xml.encode("utf-8")) b@428: root = tree.childNodes[0] b@428: except: b@428: return _("Couldn't paste non-POU object.") b@428: b@428: if root.nodeName == "pou": b@428: new_pou = plcopen.pous_pou() b@428: new_pou.loadXMLTree(root) b@428: b@428: name = new_pou.getname() laurent@447: laurent@447: idx = 0 laurent@447: new_name = name laurent@447: while self.Project.getpou(new_name): b@428: # a POU with that name already exists. b@428: # make a new name and test if a POU with that name exists. laurent@447: # append an incrementing numeric suffix to the POU name. laurent@447: idx += 1 laurent@447: new_name = "%s%d" % (name, idx) laurent@447: b@428: # we've found a name that does not already exist, use it laurent@447: new_pou.setname(new_name) Laurent@712: Laurent@712: if pou_type is not None: Laurent@712: orig_type = new_pou.getpouType() Laurent@712: Laurent@712: # prevent violations of POU content restrictions: Laurent@712: # function blocks cannot be pasted as functions, Laurent@712: # programs cannot be pasted as functions or function blocks Laurent@712: if orig_type == 'functionBlock' and pou_type == 'function' or \ Laurent@712: orig_type == 'program' and pou_type in ['function', 'functionBlock']: Laurent@712: return _('''%s "%s" can't be pasted as a %s.''') % (orig_type, name, pou_type) Laurent@712: Laurent@712: new_pou.setpouType(pou_type) b@428: b@428: self.Project.insertpou(-1, new_pou) b@428: self.BufferProject() Laurent@712: Laurent@712: return self.ComputePouName(new_name), b@428: else: b@428: return _("Couldn't paste non-POU object.") b@428: lbessard@125: # Remove a Pou from project lbessard@107: def ProjectRemovePou(self, pou_name): lbessard@249: if self.Project is not None: lbessard@249: self.Project.removepou(pou_name) lbessard@249: self.BufferProject() etisserant@0: laurent@687: # Return the name of the configuration if only one exist laurent@687: def GetProjectMainConfigurationName(self): laurent@687: if self.Project is not None: laurent@687: # Found the configuration corresponding to old name and change its name to new name laurent@687: configurations = self.Project.getconfigurations() laurent@687: if len(configurations) == 1: laurent@687: return configurations[0].getname() laurent@687: return None laurent@687: etisserant@0: # Add a configuration to Project Laurent@705: def ProjectAddConfiguration(self, config_name=None): Laurent@705: if self.Project is not None: Laurent@705: if config_name is None: Laurent@705: config_name = self.GenerateNewName(None, None, "configuration%d") lbessard@249: self.Project.addconfiguration(config_name) lbessard@249: self.BufferProject() laurent@555: return self.ComputeConfigurationName(config_name) laurent@555: return None etisserant@0: etisserant@0: # Remove a configuration from project lbessard@107: def ProjectRemoveConfiguration(self, config_name): lbessard@249: if self.Project is not None: lbessard@249: self.Project.removeconfiguration(config_name) lbessard@249: self.BufferProject() lbessard@107: lbessard@107: # Add a resource to a configuration of the Project Laurent@705: def ProjectAddConfigurationResource(self, config_name, resource_name=None): Laurent@705: if self.Project is not None: Laurent@705: if resource_name is None: Laurent@705: resource_name = self.GenerateNewName(None, None, "resource%d") lbessard@249: self.Project.addconfigurationResource(config_name, resource_name) lbessard@249: self.BufferProject() laurent@555: return self.ComputeConfigurationResourceName(config_name, resource_name) laurent@555: return None etisserant@0: etisserant@0: # Remove a resource from a configuration of the project lbessard@107: def ProjectRemoveConfigurationResource(self, config_name, resource_name): lbessard@249: if self.Project is not None: lbessard@249: self.Project.removeconfigurationResource(config_name, resource_name) lbessard@249: self.BufferProject() etisserant@0: etisserant@0: # Add a Transition to a Project Pou etisserant@0: def ProjectAddPouTransition(self, pou_name, transition_name, transition_type): lbessard@249: if self.Project is not None: lbessard@249: pou = self.Project.getpou(pou_name) lbessard@249: if pou is not None: lbessard@249: pou.addtransition(transition_name, transition_type) lbessard@249: self.BufferProject() laurent@555: return self.ComputePouTransitionName(pou_name, transition_name) laurent@555: return None etisserant@0: lbessard@107: # Remove a Transition from a Project Pou lbessard@107: def ProjectRemovePouTransition(self, pou_name, transition_name): lbessard@249: # Search if the pou removed is currently opened lbessard@249: if self.Project is not None: lbessard@249: pou = self.Project.getpou(pou_name) lbessard@249: if pou is not None: lbessard@249: pou.removetransition(transition_name) lbessard@249: self.BufferProject() lbessard@107: lbessard@107: # Add an Action to a Project Pou etisserant@0: def ProjectAddPouAction(self, pou_name, action_name, action_type): lbessard@249: if self.Project is not None: lbessard@249: pou = self.Project.getpou(pou_name) lbessard@249: if pou is not None: lbessard@249: pou.addaction(action_name, action_type) lbessard@249: self.BufferProject() laurent@555: return self.ComputePouActionName(pou_name, action_name) laurent@555: return None lbessard@107: lbessard@107: # Remove an Action from a Project Pou lbessard@107: def ProjectRemovePouAction(self, pou_name, action_name): lbessard@107: # Search if the pou removed is currently opened lbessard@249: if self.Project is not None: lbessard@249: pou = self.Project.getpou(pou_name) lbessard@249: if pou is not None: lbessard@249: pou.removeaction(action_name) lbessard@249: self.BufferProject() lbessard@125: lbessard@125: # Change the name of a pou lbessard@125: def ChangeDataTypeName(self, old_name, new_name): lbessard@249: if self.Project is not None: lbessard@249: # Found the pou corresponding to old name and change its name to new name lbessard@249: datatype = self.Project.getdataType(old_name) lbessard@249: if datatype is not None: lbessard@249: datatype.setname(new_name) lbessard@249: self.Project.updateElementName(old_name, new_name) greg@349: self.Project.RefreshElementUsingTree() greg@349: self.Project.RefreshDataTypeHierarchy() lbessard@249: self.BufferProject() lbessard@125: etisserant@0: # Change the name of a pou etisserant@0: def ChangePouName(self, old_name, new_name): lbessard@249: if self.Project is not None: lbessard@249: # Found the pou corresponding to old name and change its name to new name lbessard@249: pou = self.Project.getpou(old_name) lbessard@249: if pou is not None: lbessard@249: pou.setname(new_name) lbessard@249: self.Project.updateElementName(old_name, new_name) lbessard@249: self.Project.RefreshElementUsingTree() lbessard@249: self.Project.RefreshCustomBlockTypes() lbessard@249: self.BufferProject() etisserant@0: etisserant@0: # Change the name of a pou transition etisserant@0: def ChangePouTransitionName(self, pou_name, old_name, new_name): lbessard@249: if self.Project is not None: lbessard@249: # Found the pou transition corresponding to old name and change its name to new name lbessard@249: pou = self.Project.getpou(pou_name) lbessard@249: if pou is not None: lbessard@249: transition = pou.gettransition(old_name) lbessard@249: if transition is not None: lbessard@249: transition.setname(new_name) lbessard@249: pou.updateElementName(old_name, new_name) lbessard@249: self.BufferProject() etisserant@0: etisserant@0: # Change the name of a pou action etisserant@0: def ChangePouActionName(self, pou_name, old_name, new_name): lbessard@249: if self.Project is not None: lbessard@249: # Found the pou action corresponding to old name and change its name to new name lbessard@249: pou = self.Project.getpou(pou_name) lbessard@249: if pou is not None: lbessard@249: action = pou.getaction(old_name) lbessard@249: if action is not None: lbessard@249: action.setname(new_name) lbessard@249: pou.updateElementName(old_name, new_name) lbessard@249: self.BufferProject() lbessard@56: lbessard@80: # Change the name of a pou variable lbessard@6: def ChangePouVariableName(self, pou_name, old_name, new_name): lbessard@249: if self.Project is not None: lbessard@249: # Found the pou action corresponding to old name and change its name to new name lbessard@249: pou = self.Project.getpou(pou_name) lbessard@249: if pou is not None: lbessard@249: for type, varlist in pou.getvars(): lbessard@249: for var in varlist.getvariable(): lbessard@249: if var.getname() == old_name: lbessard@249: var.setname(new_name) lbessard@249: self.Project.RefreshCustomBlockTypes() lbessard@249: self.BufferProject() lbessard@6: etisserant@0: # Change the name of a configuration etisserant@0: def ChangeConfigurationName(self, old_name, new_name): lbessard@249: if self.Project is not None: lbessard@249: # Found the configuration corresponding to old name and change its name to new name lbessard@249: configuration = self.Project.getconfiguration(old_name) lbessard@249: if configuration is not None: lbessard@249: configuration.setname(new_name) lbessard@249: self.BufferProject() lbessard@56: etisserant@0: # Change the name of a configuration resource etisserant@0: def ChangeConfigurationResourceName(self, config_name, old_name, new_name): lbessard@249: if self.Project is not None: lbessard@249: # Found the resource corresponding to old name and change its name to new name b@421: resource = self.Project.getconfigurationResource(config_name, old_name) lbessard@249: if resource is not None: b@421: resource.setname(new_name) lbessard@249: self.BufferProject() etisserant@0: laurent@625: # Return the description of the pou given by its name laurent@625: def GetPouDescription(self, name, debug = False): laurent@625: project = self.GetProject(debug) laurent@625: if project is not None: laurent@625: # Found the pou correponding to name and return its type laurent@625: pou = project.getpou(name) laurent@625: if pou is not None: laurent@625: return pou.getdescription() laurent@625: return "" laurent@625: laurent@625: # Return the description of the pou given by its name laurent@625: def SetPouDescription(self, name, description, debug = False): laurent@625: project = self.GetProject(debug) laurent@625: if project is not None: laurent@625: # Found the pou correponding to name and return its type laurent@625: pou = project.getpou(name) laurent@625: if pou is not None: laurent@625: pou.setdescription(description) laurent@625: project.RefreshCustomBlockTypes() laurent@625: self.BufferProject() laurent@625: etisserant@0: # Return the type of the pou given by its name lbessard@249: def GetPouType(self, name, debug = False): lbessard@249: project = self.GetProject(debug) lbessard@249: if project is not None: lbessard@249: # Found the pou correponding to name and return its type lbessard@249: pou = project.getpou(name) lbessard@249: if pou is not None: lbessard@249: return pou.getpouType() lbessard@249: return None etisserant@0: etisserant@0: # Return pous with SFC language lbessard@249: def GetSFCPous(self, debug = False): etisserant@0: list = [] lbessard@249: project = self.GetProject(debug) lbessard@249: if project is not None: lbessard@249: for pou in project.getpous(): etisserant@0: if pou.getBodyType() == "SFC": lbessard@151: list.append(pou.getname()) etisserant@0: return list etisserant@0: etisserant@0: # Return the body language of the pou given by its name lbessard@249: def GetPouBodyType(self, name, debug = False): lbessard@249: project = self.GetProject(debug) lbessard@249: if project is not None: lbessard@249: # Found the pou correponding to name and return its body language lbessard@249: pou = project.getpou(name) lbessard@249: if pou is not None: lbessard@249: return pou.getbodyType() lbessard@249: return None etisserant@0: lbessard@46: # Return the actions of a pou lbessard@249: def GetPouTransitions(self, pou_name, debug = False): lbessard@46: transitions = [] lbessard@249: project = self.GetProject(debug) lbessard@249: if project is not None: lbessard@249: # Found the pou correponding to name and return its transitions if SFC lbessard@249: pou = project.getpou(pou_name) lbessard@249: if pou is not None and pou.getbodyType() == "SFC": lbessard@249: for transition in pou.gettransitionList(): lbessard@249: transitions.append(transition.getname()) lbessard@46: return transitions lbessard@46: etisserant@0: # Return the body language of the transition given by its name lbessard@249: def GetTransitionBodyType(self, pou_name, pou_transition, debug = False): lbessard@249: project = self.GetProject(debug) lbessard@249: if project is not None: lbessard@249: # Found the pou correponding to name lbessard@249: pou = project.getpou(pou_name) lbessard@249: if pou is not None: lbessard@249: # Found the pou transition correponding to name and return its body language lbessard@249: transition = pou.gettransition(pou_transition) lbessard@249: if transition is not None: lbessard@249: return transition.getbodyType() lbessard@249: return None etisserant@0: lbessard@46: # Return the actions of a pou lbessard@249: def GetPouActions(self, pou_name, debug = False): lbessard@46: actions = [] lbessard@249: project = self.GetProject(debug) lbessard@249: if project is not None: lbessard@249: # Found the pou correponding to name and return its actions if SFC lbessard@249: pou = project.getpou(pou_name) lbessard@249: if pou.getbodyType() == "SFC": lbessard@249: for action in pou.getactionList(): lbessard@249: actions.append(action.getname()) lbessard@46: return actions lbessard@46: etisserant@0: # Return the body language of the pou given by its name lbessard@249: def GetActionBodyType(self, pou_name, pou_action, debug = False): lbessard@249: project = self.GetProject(debug) lbessard@249: if project is not None: lbessard@249: # Found the pou correponding to name and return its body language lbessard@249: pou = project.getpou(pou_name) lbessard@249: if pou is not None: lbessard@249: action = pou.getaction(pou_action) lbessard@249: if action is not None: lbessard@249: return action.getbodyType() lbessard@249: return None etisserant@0: etisserant@0: # Extract varlists from a list of vars etisserant@0: def ExtractVarLists(self, vars): etisserant@0: varlist_list = [] etisserant@0: current_varlist = None etisserant@0: current_type = None etisserant@0: for var in vars: etisserant@233: next_type = (var["Class"], laurent@483: var["Option"], laurent@483: var["Location"] in ["", None] or laurent@483: # When declaring globals, located laurent@483: # and not located variables are laurent@483: # in the same declaration block laurent@483: var["Class"] == "Global") etisserant@233: if current_type != next_type: etisserant@233: current_type = next_type lbessard@236: infos = VAR_CLASS_INFOS.get(var["Class"], None) lbessard@236: if infos is not None: lbessard@236: current_varlist = infos[0]() lbessard@151: else: lbessard@151: current_varlist = plcopen.varList() etisserant@0: varlist_list.append((var["Class"], current_varlist)) laurent@483: if var["Option"] == "Constant": laurent@483: current_varlist.setconstant(True) laurent@483: elif var["Option"] == "Retain": lbessard@151: current_varlist.setretain(True) laurent@483: elif var["Option"] == "Non-Retain": laurent@483: current_varlist.setnonretain(True) etisserant@0: # Create variable and change its properties etisserant@0: tempvar = plcopen.varListPlain_variable() lbessard@151: tempvar.setname(var["Name"]) laurent@507: etisserant@0: var_type = plcopen.dataType() laurent@507: if isinstance(var["Type"], TupleType): laurent@507: if var["Type"][0] == "array": laurent@507: array_type, base_type_name, dimensions = var["Type"] laurent@507: array = plcopen.derivedTypes_array() laurent@507: for i, dimension in enumerate(dimensions): laurent@507: dimension_range = plcopen.rangeSigned() laurent@507: dimension_range.setlower(dimension[0]) laurent@507: dimension_range.setupper(dimension[1]) laurent@507: if i == 0: laurent@507: array.setdimension([dimension_range]) laurent@507: else: laurent@507: array.appenddimension(dimension_range) laurent@507: if base_type_name in self.GetBaseTypes(): laurent@507: if base_type_name == "STRING": laurent@507: array.baseType.setcontent({"name" : "string", "value" : plcopen.elementaryTypes_string()}) laurent@507: elif base_type_name == "WSTRING": laurent@507: array.baseType.setcontent({"name" : "wstring", "value" : plcopen.wstring()}) laurent@507: else: laurent@507: array.baseType.setcontent({"name" : base_type_name, "value" : None}) laurent@507: else: laurent@507: derived_datatype = plcopen.derivedTypes_derived() laurent@507: derived_datatype.setname(base_type_name) laurent@507: array.baseType.setcontent({"name" : "derived", "value" : derived_datatype}) laurent@507: var_type.setcontent({"name" : "array", "value" : array}) laurent@507: elif var["Type"] in self.GetBaseTypes(): lbessard@141: if var["Type"] == "STRING": lbessard@151: var_type.setcontent({"name" : "string", "value" : plcopen.elementaryTypes_string()}) lbessard@141: elif var["Type"] == "WSTRING": lbessard@151: var_type.setcontent({"name" : "wstring", "value" : plcopen.elementaryTypes_wstring()}) lbessard@141: else: lbessard@151: var_type.setcontent({"name" : var["Type"], "value" : None}) lbessard@67: else: lbessard@151: derived_type = plcopen.derivedTypes_derived() lbessard@151: derived_type.setname(var["Type"]) lbessard@151: var_type.setcontent({"name" : "derived", "value" : derived_type}) lbessard@151: tempvar.settype(var_type) b@424: etisserant@0: if var["Initial Value"] != "": etisserant@0: value = plcopen.value() lbessard@151: value.setvalue(var["Initial Value"]) lbessard@151: tempvar.setinitialValue(value) etisserant@0: if var["Location"] != "": lbessard@151: tempvar.setaddress(var["Location"]) lbessard@53: else: lbessard@151: tempvar.setaddress(None) b@424: if var['Documentation'] != "": b@424: ft = plcopen.formattedText() b@424: ft.settext(var['Documentation']) b@424: tempvar.setdocumentation(ft) b@424: etisserant@0: # Add variable to varList lbessard@151: current_varlist.appendvariable(tempvar) etisserant@0: return varlist_list b@424: b@424: def GetVariableDictionary(self, varlist, var): b@424: ''' b@424: convert a PLC variable to the dictionary representation b@424: returned by Get*Vars) b@424: ''' b@424: laurent@483: tempvar = {"Name": var.getname()} b@424: b@424: vartype_content = var.gettype().getcontent() b@424: if vartype_content["name"] == "derived": b@424: tempvar["Type"] = vartype_content["value"].getname() laurent@507: elif vartype_content["name"] == "array": laurent@507: dimensions = [] laurent@507: for dimension in vartype_content["value"].getdimension(): laurent@507: dimensions.append((dimension.getlower(), dimension.getupper())) laurent@507: base_type = vartype_content["value"].baseType.getcontent() laurent@507: if base_type["value"] is None: laurent@507: base_type_name = base_type["name"] laurent@507: else: laurent@507: base_type_name = base_type["value"].getname() laurent@507: tempvar["Type"] = ("array", base_type_name, dimensions) b@424: elif vartype_content["name"] in ["string", "wstring"]: b@424: tempvar["Type"] = vartype_content["name"].upper() b@424: else: b@424: tempvar["Type"] = vartype_content["name"] b@424: b@424: tempvar["Edit"] = True b@424: b@424: initial = var.getinitialValue() b@424: if initial: b@424: tempvar["Initial Value"] = initial.getvalue() b@424: else: b@424: tempvar["Initial Value"] = "" b@424: b@424: address = var.getaddress() b@424: if address: b@424: tempvar["Location"] = address b@424: else: b@424: tempvar["Location"] = "" b@424: laurent@483: if varlist.getconstant(): laurent@483: tempvar["Option"] = "Constant" laurent@483: elif varlist.getretain(): laurent@483: tempvar["Option"] = "Retain" laurent@483: elif varlist.getnonretain(): laurent@483: tempvar["Option"] = "Non-Retain" b@424: else: laurent@483: tempvar["Option"] = "" b@424: b@424: doc = var.getdocumentation() b@424: if doc: b@424: tempvar["Documentation"] = doc.gettext() b@424: else: b@424: tempvar["Documentation"] = "" b@424: b@424: return tempvar etisserant@0: etisserant@0: # Replace the configuration globalvars by those given etisserant@0: def SetConfigurationGlobalVars(self, name, vars): lbessard@249: if self.Project is not None: lbessard@249: # Found the configuration corresponding to name lbessard@249: configuration = self.Project.getconfiguration(name) lbessard@249: if configuration is not None: lbessard@249: # Set configuration global vars lbessard@249: configuration.setglobalVars([]) lbessard@249: for vartype, varlist in self.ExtractVarLists(vars): lbessard@249: configuration.globalVars.append(varlist) lbessard@56: etisserant@0: # Return the configuration globalvars lbessard@249: def GetConfigurationGlobalVars(self, name, debug = False): etisserant@0: vars = [] lbessard@249: project = self.GetProject(debug) lbessard@249: if project is not None: lbessard@249: # Found the configuration corresponding to name lbessard@249: configuration = project.getconfiguration(name) lbessard@249: if configuration is not None: lbessard@249: # Extract variables from every varLists lbessard@249: for varlist in configuration.getglobalVars(): lbessard@249: for var in varlist.getvariable(): b@424: tempvar = self.GetVariableDictionary(varlist, var) b@424: tempvar["Class"] = "Global" lbessard@249: vars.append(tempvar) etisserant@0: return vars etisserant@0: etisserant@0: # Replace the resource globalvars by those given etisserant@0: def SetConfigurationResourceGlobalVars(self, config_name, name, vars): lbessard@249: if self.Project is not None: lbessard@249: # Found the resource corresponding to name lbessard@249: resource = self.Project.getconfigurationResource(config_name, name) lbessard@249: # Set resource global vars lbessard@249: if resource is not None: lbessard@249: resource.setglobalVars([]) lbessard@249: for vartype, varlist in self.ExtractVarLists(vars): lbessard@249: resource.globalVars.append(varlist) lbessard@56: etisserant@0: # Return the resource globalvars lbessard@249: def GetConfigurationResourceGlobalVars(self, config_name, name, debug = False): etisserant@0: vars = [] lbessard@249: project = self.GetProject(debug) lbessard@249: if project is not None: lbessard@249: # Found the resource corresponding to name lbessard@249: resource = project.getconfigurationResource(config_name, name) lbessard@249: if resource: lbessard@249: # Extract variables from every varLists lbessard@249: for varlist in resource.getglobalVars(): lbessard@249: for var in varlist.getvariable(): b@424: tempvar = self.GetVariableDictionary(varlist, var) b@424: tempvar["Class"] = "Global" lbessard@249: vars.append(tempvar) etisserant@0: return vars etisserant@0: lbessard@295: # Recursively generate element name tree for a structured variable lbessard@295: def GenerateVarTree(self, typename, debug = False): lbessard@295: project = self.GetProject(debug) lbessard@295: if project is not None: lbessard@295: blocktype = self.GetBlockType(typename, debug = debug) lbessard@295: if blocktype is not None: lbessard@297: tree = [] laurent@549: en = False laurent@549: eno = False lbessard@295: for var_name, var_type, var_modifier in blocktype["inputs"] + blocktype["outputs"]: laurent@549: en |= var_name.upper() == "EN" laurent@549: eno |= var_name.upper() == "ENO" lbessard@297: tree.append((var_name, var_type, self.GenerateVarTree(var_type, debug))) laurent@549: if not eno: laurent@549: tree.insert(0, ("ENO", "BOOL", ([], []))) laurent@549: if not en: laurent@549: tree.insert(0, ("EN", "BOOL", ([], []))) lbessard@299: return tree, [] lbessard@295: datatype = project.getdataType(typename) laurent@630: if datatype is None: Edouard@681: datatype = self.GetConfNodeDataType(typename) lbessard@295: if datatype is not None: lbessard@297: tree = [] lbessard@295: basetype_content = datatype.baseType.getcontent() lbessard@295: if basetype_content["name"] == "derived": lbessard@299: return self.GenerateVarTree(basetype_content["value"].getname()) lbessard@295: elif basetype_content["name"] == "array": lbessard@299: dimensions = [] lbessard@295: base_type = basetype_content["value"].baseType.getcontent() lbessard@295: if base_type["name"] == "derived": lbessard@299: tree = self.GenerateVarTree(base_type["value"].getname()) lbessard@299: if len(tree[1]) == 0: lbessard@299: tree = tree[0] lbessard@299: for dimension in basetype_content["value"].getdimension(): lbessard@299: dimensions.append((dimension.getlower(), dimension.getupper())) lbessard@299: return tree, dimensions lbessard@295: elif basetype_content["name"] == "struct": lbessard@295: for element in basetype_content["value"].getvariable(): lbessard@295: element_type = element.type.getcontent() lbessard@295: if element_type["name"] == "derived": lbessard@297: tree.append((element.getname(), element_type["value"].getname(), self.GenerateVarTree(element_type["value"].getname()))) lbessard@295: else: lbessard@299: tree.append((element.getname(), element_type["name"], ([], []))) lbessard@299: return tree, [] lbessard@299: return [], [] b@424: etisserant@0: # Return the interface for the given pou lbessard@295: def GetPouInterfaceVars(self, pou, debug = False): etisserant@0: vars = [] etisserant@0: # Verify that the pou has an interface lbessard@249: if pou.interface is not None: etisserant@0: # Extract variables from every varLists lbessard@151: for type, varlist in pou.getvars(): lbessard@151: for var in varlist.getvariable(): b@424: tempvar = self.GetVariableDictionary(varlist, var) b@424: b@424: tempvar["Class"] = type b@424: tempvar["Tree"] = ([], []) b@424: lbessard@151: vartype_content = var.gettype().getcontent() lbessard@141: if vartype_content["name"] == "derived": lbessard@151: tempvar["Edit"] = not pou.hasblock(tempvar["Name"]) lbessard@295: tempvar["Tree"] = self.GenerateVarTree(tempvar["Type"], debug) b@424: etisserant@0: vars.append(tempvar) etisserant@0: return vars etisserant@0: etisserant@0: # Replace the Pou interface by the one given etisserant@0: def SetPouInterfaceVars(self, name, vars): lbessard@249: if self.Project is not None: lbessard@249: # Found the pou corresponding to name and add interface if there isn't one yet lbessard@249: pou = self.Project.getpou(name) lbessard@249: if pou is not None: lbessard@249: if pou.interface is None: lbessard@249: pou.interface = plcopen.pou_interface() lbessard@249: # Set Pou interface lbessard@249: pou.setvars(self.ExtractVarLists(vars)) lbessard@249: self.Project.RefreshElementUsingTree() lbessard@249: self.Project.RefreshCustomBlockTypes() lbessard@56: etisserant@0: # Replace the return type of the pou given by its name (only for functions) etisserant@0: def SetPouInterfaceReturnType(self, name, type): lbessard@249: if self.Project is not None: lbessard@249: pou = self.Project.getpou(name) lbessard@249: if pou is not None: lbessard@249: if pou.interface is None: lbessard@249: pou.interface = plcopen.pou_interface() lbessard@249: # If there isn't any return type yet, add it lbessard@249: return_type = pou.interface.getreturnType() lbessard@249: if not return_type: lbessard@249: return_type = plcopen.dataType() lbessard@249: pou.interface.setreturnType(return_type) lbessard@249: # Change return type lbessard@249: if type in self.GetBaseTypes(): lbessard@249: if type == "STRING": lbessard@249: return_type.setcontent({"name" : "string", "value" : plcopen.elementaryTypes_string()}) lbessard@249: elif type == "WSTRING": lbessard@249: return_type.setcontent({"name" : "wstring", "value" : plcopen.elementaryTypes_wstring()}) lbessard@249: else: lbessard@249: return_type.setcontent({"name" : type, "value" : None}) lbessard@249: else: lbessard@249: derived_type = plcopen.derivedTypes_derived() lbessard@249: derived_type.setname(type) lbessard@249: return_type.setcontent({"name" : "derived", "value" : derived_type}) lbessard@249: self.Project.RefreshElementUsingTree() lbessard@249: self.Project.RefreshCustomBlockTypes() lbessard@58: lbessard@58: def UpdateProjectUsedPous(self, old_name, new_name): lbessard@58: if self.Project: lbessard@58: self.Project.updateElementName(old_name, new_name) lbessard@58: lbessard@121: def UpdateEditedElementUsedVariable(self, tagname, old_name, new_name): lbessard@121: pou = self.GetEditedElement(tagname) lbessard@58: if pou: lbessard@58: pou.updateElementName(old_name, new_name) etisserant@0: etisserant@0: # Return the return type of the pou given by its name etisserant@0: def GetPouInterfaceReturnTypeByName(self, name): lbessard@249: project = self.GetProject(debug) lbessard@249: if project is not None: lbessard@249: # Found the pou correponding to name and return the return type lbessard@249: pou = project.getpou(name) lbessard@249: if pou is not None: lbessard@249: return self.GetPouInterfaceReturnType(pou) lbessard@249: return False etisserant@0: etisserant@0: # Return the return type of the given pou etisserant@0: def GetPouInterfaceReturnType(self, pou): etisserant@0: # Verify that the pou has an interface lbessard@249: if pou.interface is not None: etisserant@0: # Return the return type if there is one lbessard@151: return_type = pou.interface.getreturnType() etisserant@0: if return_type: lbessard@151: returntype_content = return_type.getcontent() lbessard@141: if returntype_content["name"] == "derived": lbessard@151: return returntype_content["value"].getname() lbessard@141: elif returntype_content["name"] in ["string", "wstring"]: lbessard@141: return returntype_content["name"].upper() lbessard@141: else: lbessard@125: return returntype_content["name"] etisserant@0: return None lbessard@226: Edouard@681: # Function that add a new confnode to the confnode list Edouard@681: def AddConfNodeTypesList(self, typeslist): Edouard@681: self.ConfNodeTypes.extend(typeslist) lbessard@226: Edouard@681: # Function that clear the confnode list Edouard@681: def ClearConfNodeTypes(self): Edouard@681: for i in xrange(len(self.ConfNodeTypes)): Edouard@681: self.ConfNodeTypes.pop(0) Edouard@681: Edouard@681: def GetConfNodeBlockTypes(self): Edouard@681: return [{"name": _("%s POUs") % confnodetypes["name"], Edouard@681: "list": confnodetypes["types"].GetCustomBlockTypes()} Edouard@681: for confnodetypes in self.ConfNodeTypes] laurent@630: Edouard@681: def GetConfNodeDataTypes(self, exclude = ""): Edouard@681: return [{"name": _("%s Data Types") % confnodetypes["name"], Edouard@681: "list": [datatype["name"] for datatype in confnodetypes["types"].GetCustomDataTypes(exclude)]} Edouard@681: for confnodetypes in self.ConfNodeTypes] Edouard@681: Edouard@681: def GetConfNodeDataType(self, type): Edouard@681: for confnodetype in self.ConfNodeTypes: Edouard@681: datatype = confnodetype["types"].getdataType(type) laurent@630: if datatype is not None: laurent@630: return datatype laurent@630: return None laurent@630: laurent@435: def GetVariableLocationTree(self): laurent@435: return [] laurent@435: lbessard@226: # Function that returns the block definition associated to the block type given lbessard@249: def GetBlockType(self, type, inputs = None, debug = False): laurent@526: result_blocktype = None Edouard@681: for category in BlockTypes + self.GetConfNodeBlockTypes(): lbessard@226: for blocktype in category["list"]: laurent@526: if blocktype["name"] == type: laurent@526: if inputs is not None and inputs != "undefined": laurent@526: block_inputs = tuple([var_type for name, var_type, modifier in blocktype["inputs"]]) Edouard@649: if reduce(lambda x, y: x and y, map(lambda x: x[0] == "ANY" or self.IsOfType(*x), zip(inputs, block_inputs)), True): laurent@526: return blocktype laurent@526: else: laurent@526: if result_blocktype is not None: laurent@526: if inputs == "undefined": laurent@526: return None laurent@526: else: laurent@526: result_blocktype["inputs"] = [(i[0], "ANY", i[2]) for i in result_blocktype["inputs"]] laurent@526: result_blocktype["outputs"] = [(o[0], "ANY", o[2]) for o in result_blocktype["outputs"]] laurent@526: return result_blocktype laurent@526: result_blocktype = blocktype laurent@526: if result_blocktype is not None: laurent@526: return result_blocktype lbessard@249: project = self.GetProject(debug) lbessard@249: if project is not None: lbessard@249: return project.GetCustomBlockType(type, inputs) lbessard@226: return None lbessard@226: etisserant@0: # Return Block types checking for recursion lbessard@249: def GetBlockTypes(self, tagname = "", debug = False): lbessard@125: type = None lbessard@252: words = tagname.split("::") lbessard@121: if self.Project: lbessard@226: name = "" lbessard@125: if words[0] in ["P","T","A"]: lbessard@121: name = words[1] lbessard@249: type = self.GetPouType(name, debug) lbessard@252: if type == "function" or words[0] == "T": lbessard@121: blocktypes = [] Edouard@681: for category in BlockTypes + self.GetConfNodeBlockTypes(): lbessard@121: cat = {"name" : category["name"], "list" : []} lbessard@121: for block in category["list"]: lbessard@121: if block["type"] == "function": lbessard@121: cat["list"].append(block) lbessard@121: if len(cat["list"]) > 0: lbessard@121: blocktypes.append(cat) lbessard@121: else: Edouard@681: blocktypes = [category for category in BlockTypes + self.GetConfNodeBlockTypes()] lbessard@249: project = self.GetProject(debug) lbessard@249: if project is not None: laurent@391: blocktypes.append({"name" : USER_DEFINED_POUS, "list": project.GetCustomBlockTypes(name, type == "function" or words[0] == "T")}) lbessard@121: return blocktypes lbessard@121: lbessard@121: # Return Function Block types checking for recursion lbessard@249: def GetFunctionBlockTypes(self, tagname = "", debug = False): lbessard@121: blocktypes = [] Edouard@681: for category in BlockTypes + self.GetConfNodeBlockTypes(): lbessard@121: for block in category["list"]: lbessard@286: if block["type"] == "functionBlock": lbessard@121: blocktypes.append(block["name"]) lbessard@249: project = self.GetProject(debug) lbessard@249: if project is not None: lbessard@226: name = "" lbessard@226: words = tagname.split("::") lbessard@226: if words[0] in ["P","T","A"]: lbessard@226: name = words[1] lbessard@249: blocktypes.extend(project.GetCustomFunctionBlockTypes(name)) lbessard@121: return blocktypes lbessard@68: etisserant@0: # Return Block types checking for recursion lbessard@249: def GetBlockResource(self, debug = False): etisserant@0: blocktypes = [] etisserant@0: for category in BlockTypes[:-1]: etisserant@0: for blocktype in category["list"]: lbessard@29: if blocktype["type"] == "program": etisserant@0: blocktypes.append(blocktype["name"]) lbessard@249: project = self.GetProject(debug) lbessard@249: if project is not None: lbessard@249: blocktypes.extend(project.GetCustomBlockResource()) etisserant@0: return blocktypes etisserant@0: lbessard@125: # Return Data Types checking for recursion laurent@552: def GetDataTypes(self, tagname = "", basetypes = True, only_locatables = False, debug = False): lbessard@125: if basetypes: lbessard@125: datatypes = self.GetBaseTypes() lbessard@125: else: lbessard@125: datatypes = [] lbessard@249: project = self.GetProject(debug) lbessard@249: if project is not None: lbessard@226: name = "" lbessard@125: words = tagname.split("::") lbessard@125: if words[0] in ["D"]: lbessard@125: name = words[1] laurent@630: datatypes.extend([datatype["name"] for datatype in project.GetCustomDataTypes(name, only_locatables)]) lbessard@125: return datatypes lbessard@125: lbessard@210: # Return Base Type of given possible derived type lbessard@249: def GetBaseType(self, type, debug = False): lbessard@249: project = self.GetProject(debug) lbessard@249: if project is not None: laurent@630: result = project.GetBaseType(type) laurent@630: if result is not None: laurent@630: return result Edouard@681: for confnodetype in self.ConfNodeTypes: Edouard@681: result = confnodetype["types"].GetBaseType(type) laurent@630: if result is not None: laurent@630: return result lbessard@226: return None lbessard@210: lbessard@125: def GetBaseTypes(self): b@420: ''' b@420: return the list of datatypes defined in IEC 61131-3. b@420: TypeHierarchy_list has a rough order to it (e.g. SINT, INT, DINT, ...), b@420: which makes it easy for a user to find a type in a menu. b@420: ''' b@420: return [x for x,y in TypeHierarchy_list if not x.startswith("ANY")] lbessard@226: lbessard@249: def IsOfType(self, type, reference, debug = False): laurent@630: if reference is None: lbessard@226: return True lbessard@226: elif type == reference: lbessard@226: return True laurent@630: elif type in TypeHierarchy: laurent@630: return self.IsOfType(TypeHierarchy[type], reference) lbessard@226: else: laurent@630: project = self.GetProject(debug) laurent@630: if project is not None and project.IsOfType(type, reference): laurent@630: return True Edouard@681: for confnodetype in self.ConfNodeTypes: Edouard@681: if confnodetype["types"].IsOfType(type, reference): laurent@630: return True laurent@630: return False lbessard@226: lbessard@226: def IsEndType(self, type): lbessard@226: if type is not None: lbessard@226: return not type.startswith("ANY") lbessard@226: return True lbessard@226: laurent@552: def IsLocatableType(self, type, debug = False): laurent@567: if isinstance(type, TupleType): laurent@567: return False laurent@552: project = self.GetProject(debug) laurent@552: if project is not None: laurent@552: datatype = project.getdataType(type) laurent@630: if datatype is None: Edouard@681: datatype = self.GetConfNodeDataType(type) laurent@552: if datatype is not None: laurent@552: return project.IsLocatableType(datatype) laurent@552: return True laurent@552: laurent@552: def IsEnumeratedType(self, type, debug = False): laurent@552: project = self.GetProject(debug) laurent@552: if project is not None: laurent@552: datatype = project.getdataType(type) laurent@630: if datatype is None: Edouard@681: datatype = self.GetConfNodeDataType(type) laurent@552: if datatype is not None: laurent@552: basetype_content = datatype.baseType.getcontent() laurent@552: return basetype_content["name"] == "enum" laurent@552: return False laurent@552: lbessard@249: def GetDataTypeRange(self, type, debug = False): laurent@630: if type in DataTypeRange: lbessard@226: return DataTypeRange[type] laurent@630: else: laurent@630: project = self.GetProject(debug) laurent@630: if project is not None: laurent@630: result = project.GetDataTypeRange(type) laurent@630: if result is not None: laurent@630: return result Edouard@681: for confnodetype in self.ConfNodeTypes: Edouard@681: result = confnodetype["types"].GetDataTypeRange(type) laurent@630: if result is not None: laurent@630: return result lbessard@226: return None lbessard@226: lbessard@125: # Return Subrange types lbessard@249: def GetSubrangeBaseTypes(self, exclude, debug = False): laurent@630: subrange_basetypes = [] laurent@630: project = self.GetProject(debug) laurent@630: if project is not None: laurent@630: subrange_basetypes.extend(project.GetSubrangeBaseTypes(exclude)) Edouard@681: for confnodetype in self.ConfNodeTypes: Edouard@681: subrange_basetypes.extend(confnodetype["types"].GetSubrangeBaseTypes(exclude)) laurent@630: return DataTypeRange.keys() + subrange_basetypes lbessard@226: lbessard@125: # Return Enumerated Values laurent@552: def GetEnumeratedDataValues(self, type = None, debug = False): laurent@630: values = [] laurent@630: project = self.GetProject(debug) laurent@630: if project is not None: laurent@630: values.extend(project.GetEnumeratedDataTypeValues(type)) laurent@630: if type is None and len(values) > 0: laurent@630: return values Edouard@681: for confnodetype in self.ConfNodeTypes: Edouard@681: values.extend(confnodetype["types"].GetEnumeratedDataTypeValues(type)) laurent@630: if type is None and len(values) > 0: laurent@630: return values laurent@630: return values lbessard@125: etisserant@0: #------------------------------------------------------------------------------- lbessard@121: # Project Element tag name computation functions etisserant@0: #------------------------------------------------------------------------------- etisserant@0: lbessard@125: # Compute a data type name lbessard@125: def ComputeDataTypeName(self, datatype): lbessard@125: return "D::%s" % datatype lbessard@125: lbessard@125: # Compute a pou name lbessard@80: def ComputePouName(self, pou): lbessard@80: return "P::%s" % pou lbessard@80: lbessard@80: # Compute a pou transition name etisserant@0: def ComputePouTransitionName(self, pou, transition): etisserant@0: return "T::%s::%s" % (pou, transition) etisserant@0: etisserant@0: # Compute a pou action name etisserant@0: def ComputePouActionName(self, pou, action): etisserant@0: return "A::%s::%s" % (pou, action) etisserant@0: etisserant@0: # Compute a pou name lbessard@47: def ComputeConfigurationName(self, config): lbessard@47: return "C::%s" % config lbessard@47: lbessard@47: # Compute a pou name etisserant@0: def ComputeConfigurationResourceName(self, config, resource): etisserant@0: return "R::%s::%s" % (config, resource) lbessard@125: lbessard@226: def GetElementType(self, tagname): lbessard@226: words = tagname.split("::") lbessard@226: return {"D" : ITEM_DATATYPE, "P" : ITEM_POU, lbessard@226: "T" : ITEM_TRANSITION, "A" : ITEM_ACTION, lbessard@226: "C" : ITEM_CONFIGURATION, "R" : ITEM_RESOURCE}[words[0]] lbessard@226: lbessard@125: #------------------------------------------------------------------------------- lbessard@125: # Project opened Data types management functions lbessard@125: #------------------------------------------------------------------------------- lbessard@125: lbessard@125: # Return the data type informations lbessard@249: def GetDataTypeInfos(self, tagname, debug = False): lbessard@249: project = self.GetProject(debug) lbessard@249: if project is not None: lbessard@249: words = tagname.split("::") lbessard@249: if words[0] == "D": lbessard@249: infos = {} lbessard@249: datatype = project.getdataType(words[1]) lbessard@249: basetype_content = datatype.baseType.getcontent() laurent@547: if basetype_content["value"] is None or basetype_content["name"] in ["string", "wstring"]: lbessard@249: infos["type"] = "Directly" laurent@547: infos["base_type"] = basetype_content["name"].upper() lbessard@249: elif basetype_content["name"] == "derived": lbessard@249: infos["type"] = "Directly" lbessard@249: infos["base_type"] = basetype_content["value"].getname() lbessard@249: elif basetype_content["name"] in ["subrangeSigned", "subrangeUnsigned"]: lbessard@249: infos["type"] = "Subrange" lbessard@249: infos["min"] = basetype_content["value"].range.getlower() lbessard@249: infos["max"] = basetype_content["value"].range.getupper() lbessard@249: base_type = basetype_content["value"].baseType.getcontent() lbessard@249: if base_type["value"] is None: lbessard@249: infos["base_type"] = base_type["name"] lbessard@249: else: lbessard@249: infos["base_type"] = base_type["value"].getname() lbessard@249: elif basetype_content["name"] == "enum": lbessard@249: infos["type"] = "Enumerated" lbessard@249: infos["values"] = [] lbessard@249: for value in basetype_content["value"].values.getvalue(): lbessard@249: infos["values"].append(value.getname()) lbessard@249: elif basetype_content["name"] == "array": lbessard@249: infos["type"] = "Array" lbessard@249: infos["dimensions"] = [] lbessard@249: for dimension in basetype_content["value"].getdimension(): lbessard@249: infos["dimensions"].append((dimension.getlower(), dimension.getupper())) lbessard@249: base_type = basetype_content["value"].baseType.getcontent() laurent@552: if base_type["value"] is None or base_type["name"] in ["string", "wstring"]: laurent@547: infos["base_type"] = base_type["name"].upper() lbessard@249: else: lbessard@249: infos["base_type"] = base_type["value"].getname() lbessard@295: elif basetype_content["name"] == "struct": lbessard@295: infos["type"] = "Structure" lbessard@295: infos["elements"] = [] lbessard@295: for element in basetype_content["value"].getvariable(): lbessard@295: element_infos = {} lbessard@295: element_infos["Name"] = element.getname() lbessard@295: element_type = element.type.getcontent() laurent@547: if element_type["value"] is None or element_type["name"] in ["string", "wstring"]: laurent@547: element_infos["Type"] = element_type["name"].upper() lbessard@295: else: lbessard@295: element_infos["Type"] = element_type["value"].getname() lbessard@295: if element.initialValue is not None: lbessard@295: element_infos["Initial Value"] = str(element.initialValue.getvalue()) lbessard@295: else: lbessard@295: element_infos["Initial Value"] = "" lbessard@295: infos["elements"].append(element_infos) lbessard@249: if datatype.initialValue is not None: lbessard@249: infos["initial"] = str(datatype.initialValue.getvalue()) lbessard@125: else: lbessard@249: infos["initial"] = "" lbessard@249: return infos lbessard@125: return None lbessard@125: lbessard@125: # Change the data type informations lbessard@125: def SetDataTypeInfos(self, tagname, infos): lbessard@125: words = tagname.split("::") lbessard@249: if self.Project is not None and words[0] == "D": lbessard@151: datatype = self.Project.getdataType(words[1]) lbessard@125: if infos["type"] == "Directly": lbessard@125: if infos["base_type"] in self.GetBaseTypes(): lbessard@141: if infos["base_type"] == "STRING": lbessard@151: datatype.baseType.setcontent({"name" : "string", "value" : plcopen.elementaryTypes_string()}) lbessard@141: elif infos["base_type"] == "WSTRING": lbessard@151: datatype.baseType.setcontent({"name" : "wstring", "value" : plcopen.elementaryTypes_wstring()}) lbessard@151: else: lbessard@151: datatype.baseType.setcontent({"name" : infos["base_type"], "value" : None}) lbessard@125: else: lbessard@151: derived_datatype = plcopen.derivedTypes_derived() lbessard@151: derived_datatype.setname(infos["base_type"]) lbessard@151: datatype.baseType.setcontent({"name" : "derived", "value" : derived_datatype}) lbessard@125: elif infos["type"] == "Subrange": lbessard@125: if infos["base_type"] in GetSubTypes("ANY_UINT"): lbessard@151: subrange = plcopen.derivedTypes_subrangeUnsigned() lbessard@151: datatype.baseType.setcontent({"name" : "subrangeUnsigned", "value" : subrange}) lbessard@125: else: lbessard@151: subrange = plcopen.derivedTypes_subrangeSigned() lbessard@151: datatype.baseType.setcontent({"name" : "subrangeSigned", "value" : subrange}) lbessard@151: subrange.range.setlower(infos["min"]) lbessard@151: subrange.range.setupper(infos["max"]) lbessard@125: if infos["base_type"] in self.GetBaseTypes(): lbessard@151: subrange.baseType.setcontent({"name" : infos["base_type"], "value" : None}) lbessard@125: else: lbessard@151: derived_datatype = plcopen.derivedTypes_derived() lbessard@151: derived_datatype.setname(infos["base_type"]) lbessard@151: subrange.baseType.setcontent({"name" : "derived", "value" : derived_datatype}) lbessard@125: elif infos["type"] == "Enumerated": lbessard@151: enumerated = plcopen.derivedTypes_enum() lbessard@151: for i, enum_value in enumerate(infos["values"]): lbessard@125: value = plcopen.values_value() lbessard@151: value.setname(enum_value) lbessard@151: if i == 0: lbessard@151: enumerated.values.setvalue([value]) lbessard@151: else: lbessard@151: enumerated.values.appendvalue(value) lbessard@151: datatype.baseType.setcontent({"name" : "enum", "value" : enumerated}) lbessard@125: elif infos["type"] == "Array": lbessard@151: array = plcopen.derivedTypes_array() lbessard@207: for i, dimension in enumerate(infos["dimensions"]): lbessard@125: dimension_range = plcopen.rangeSigned() lbessard@207: dimension_range.setlower(dimension[0]) lbessard@207: dimension_range.setupper(dimension[1]) lbessard@207: if i == 0: lbessard@207: array.setdimension([dimension_range]) lbessard@207: else: lbessard@207: array.appenddimension(dimension_range) lbessard@125: if infos["base_type"] in self.GetBaseTypes(): lbessard@141: if infos["base_type"] == "STRING": lbessard@151: array.baseType.setcontent({"name" : "string", "value" : plcopen.elementaryTypes_string()}) lbessard@141: elif infos["base_type"] == "WSTRING": lbessard@151: array.baseType.setcontent({"name" : "wstring", "value" : plcopen.wstring()}) lbessard@151: else: lbessard@151: array.baseType.setcontent({"name" : infos["base_type"], "value" : None}) lbessard@125: else: lbessard@151: derived_datatype = plcopen.derivedTypes_derived() lbessard@151: derived_datatype.setname(infos["base_type"]) lbessard@151: array.baseType.setcontent({"name" : "derived", "value" : derived_datatype}) lbessard@151: datatype.baseType.setcontent({"name" : "array", "value" : array}) lbessard@295: elif infos["type"] == "Structure": lbessard@295: struct = plcopen.varListPlain() lbessard@295: for i, element_infos in enumerate(infos["elements"]): lbessard@295: element = plcopen.varListPlain_variable() lbessard@295: element.setname(element_infos["Name"]) lbessard@295: if element_infos["Type"] in self.GetBaseTypes(): lbessard@295: if element_infos["Type"] == "STRING": lbessard@295: element.type.setcontent({"name" : "string", "value" : plcopen.elementaryTypes_string()}) lbessard@295: elif element_infos["Type"] == "WSTRING": lbessard@295: element.type.setcontent({"name" : "wstring", "value" : plcopen.wstring()}) lbessard@295: else: lbessard@295: element.type.setcontent({"name" : element_infos["Type"], "value" : None}) lbessard@295: else: lbessard@295: derived_datatype = plcopen.derivedTypes_derived() lbessard@295: derived_datatype.setname(element_infos["Type"]) lbessard@295: element.type.setcontent({"name" : "derived", "value" : derived_datatype}) lbessard@295: if element_infos["Initial Value"] != "": lbessard@295: value = plcopen.value() lbessard@295: value.setvalue(element_infos["Initial Value"]) lbessard@295: element.setinitialValue(value) lbessard@295: if i == 0: lbessard@295: struct.setvariable([element]) lbessard@295: else: lbessard@295: struct.appendvariable(element) lbessard@295: datatype.baseType.setcontent({"name" : "struct", "value" : struct}) lbessard@125: if infos["initial"] != "": lbessard@125: if datatype.initialValue is None: lbessard@125: datatype.initialValue = plcopen.value() lbessard@151: datatype.initialValue.setvalue(infos["initial"]) lbessard@125: else: lbessard@125: datatype.initialValue = None lbessard@226: self.Project.RefreshDataTypeHierarchy() lbessard@295: self.Project.RefreshElementUsingTree() lbessard@125: self.BufferProject() etisserant@0: etisserant@0: #------------------------------------------------------------------------------- etisserant@0: # Project opened Pous management functions etisserant@0: #------------------------------------------------------------------------------- etisserant@0: lbessard@121: # Return edited element lbessard@249: def GetEditedElement(self, tagname, debug = False): lbessard@249: project = self.GetProject(debug) lbessard@249: if project is not None: lbessard@249: words = tagname.split("::") lbessard@249: if words[0] == "D": lbessard@249: return project.getdataType(words[1]) lbessard@249: elif words[0] == "P": lbessard@249: return project.getpou(words[1]) lbessard@249: elif words[0] in ['T', 'A']: lbessard@249: pou = project.getpou(words[1]) lbessard@249: if pou is not None: lbessard@249: if words[0] == 'T': lbessard@249: return pou.gettransition(words[2]) lbessard@249: elif words[0] == 'A': lbessard@249: return pou.getaction(words[2]) lbessard@249: elif words[0] == 'C': lbessard@249: return project.getconfiguration(words[1]) lbessard@249: elif words[0] == 'R': lbessard@249: return project.getconfigurationResource(words[1], words[2]) etisserant@0: return None etisserant@0: lbessard@121: # Return edited element name lbessard@121: def GetEditedElementName(self, tagname): lbessard@121: words = tagname.split("::") lbessard@226: if words[0] in ["P","C","D"]: lbessard@121: return words[1] lbessard@121: else: lbessard@121: return words[2] lbessard@121: return None lbessard@121: lbessard@121: # Return edited element name and type lbessard@249: def GetEditedElementType(self, tagname, debug = False): lbessard@121: words = tagname.split("::") lbessard@121: if words[0] in ["P","T","A"]: lbessard@249: return words[1], self.GetPouType(words[1], debug) lbessard@121: return None, None lbessard@121: lbessard@121: # Return language in which edited element is written lbessard@249: def GetEditedElementBodyType(self, tagname, debug = False): lbessard@121: words = tagname.split("::") lbessard@121: if words[0] == "P": lbessard@249: return self.GetPouBodyType(words[1], debug) lbessard@121: elif words[0] == 'T': lbessard@249: return self.GetTransitionBodyType(words[1], words[2], debug) lbessard@121: elif words[0] == 'A': lbessard@249: return self.GetActionBodyType(words[1], words[2], debug) lbessard@121: return None lbessard@121: lbessard@121: # Return the edited element variables lbessard@249: def GetEditedElementInterfaceVars(self, tagname, debug = False): lbessard@121: words = tagname.split("::") lbessard@121: if words[0] in ["P","T","A"]: lbessard@249: project = self.GetProject(debug) lbessard@249: if project is not None: lbessard@249: pou = project.getpou(words[1]) lbessard@249: if pou is not None: lbessard@295: return self.GetPouInterfaceVars(pou, debug) lbessard@121: return [] lbessard@121: lbessard@121: # Return the edited element return type lbessard@249: def GetEditedElementInterfaceReturnType(self, tagname, debug = False): lbessard@121: words = tagname.split("::") lbessard@121: if words[0] == "P": lbessard@249: project = self.GetProject(debug) lbessard@249: if project is not None: lbessard@249: pou = self.Project.getpou(words[1]) lbessard@249: if pou is not None: lbessard@249: return self.GetPouInterfaceReturnType(pou) lbessard@121: elif words[0] == 'T': lbessard@121: return "BOOL" lbessard@121: return None lbessard@121: lbessard@125: # Change the edited element text lbessard@121: def SetEditedElementText(self, tagname, text): lbessard@249: if self.Project is not None: lbessard@249: element = self.GetEditedElement(tagname) lbessard@249: if element is not None: lbessard@249: element.settext(text) lbessard@249: self.Project.RefreshElementUsingTree() lbessard@121: lbessard@121: # Return the edited element text lbessard@249: def GetEditedElementText(self, tagname, debug = False): lbessard@249: element = self.GetEditedElement(tagname, debug) lbessard@249: if element is not None: lbessard@151: return element.gettext() lbessard@121: return "" lbessard@121: lbessard@121: # Return the edited element transitions lbessard@249: def GetEditedElementTransitions(self, tagname, debug = False): lbessard@249: pou = self.GetEditedElement(tagname, debug) lbessard@249: if pou is not None and pou.getbodyType() == "SFC": lbessard@121: transitions = [] lbessard@151: for transition in pou.gettransitionList(): lbessard@151: transitions.append(transition.getname()) lbessard@121: return transitions lbessard@121: return [] lbessard@121: lbessard@121: # Return edited element transitions lbessard@249: def GetEditedElementActions(self, tagname, debug = False): lbessard@249: pou = self.GetEditedElement(tagname, debug) lbessard@310: if pou is not None and pou.getbodyType() == "SFC": lbessard@121: actions = [] lbessard@151: for action in pou.getactionList(): lbessard@151: actions.append(action.getname()) lbessard@121: return actions lbessard@121: return [] lbessard@121: lbessard@121: # Return the names of the pou elements lbessard@249: def GetEditedElementVariables(self, tagname, debug = False): lbessard@121: words = tagname.split("::") lbessard@121: if words[0] in ["P","T","A"]: lbessard@249: return self.GetProjectPouVariables(words[1], debug) lbessard@121: return [] lbessard@121: laurent@384: def GetEditedElementCopy(self, tagname, debug = False): laurent@384: element = self.GetEditedElement(tagname, debug) laurent@384: if element is not None: laurent@384: name = element.__class__.__name__ laurent@384: return element.generateXMLText(name.split("_")[-1], 0) laurent@384: return "" laurent@384: laurent@384: def GetEditedElementInstancesCopy(self, tagname, blocks_id = None, wires = None, debug = False): laurent@384: element = self.GetEditedElement(tagname, debug) laurent@384: text = "" laurent@384: if element is not None: laurent@384: wires = dict([(wire, True) for wire in wires if wire[0] in blocks_id and wire[1] in blocks_id]) laurent@384: for id in blocks_id: laurent@384: instance = element.getinstance(id) laurent@384: if instance is not None: laurent@384: instance_copy = self.Copy(instance) laurent@384: instance_copy.filterConnections(wires) laurent@384: name = instance_copy.__class__.__name__ laurent@384: text += instance_copy.generateXMLText(name.split("_")[-1], 0) laurent@384: return text laurent@384: laurent@384: def GenerateNewName(self, tagname, name, format, exclude={}, debug=False): laurent@384: names = exclude.copy() Laurent@705: if tagname is not None: Laurent@705: names.update(dict([(varname.upper(), True) for varname in self.GetEditedElementVariables(tagname, debug)])) Laurent@705: element = self.GetEditedElement(tagname, debug) Laurent@705: if element is not None: Laurent@705: for instance in element.getinstances(): Laurent@705: if isinstance(instance, (plcopen.sfcObjects_step, plcopen.commonObjects_connector, plcopen.commonObjects_continuation)): Laurent@705: names[instance.getname().upper()] = True Laurent@705: else: Laurent@705: project = self.GetProject(debug) Laurent@705: if project is not None: Laurent@705: for datatype in project.getdataTypes(): Laurent@705: names[datatype.getname().upper()] = True Laurent@705: for pou in project.getpous(): Laurent@705: names[pou.getname().upper()] = True Laurent@705: for var in self.GetPouInterfaceVars(pou, debug): Laurent@705: names[var["Name"].upper()] = True Laurent@705: for transition in pou.gettransitionList(): Laurent@705: names[transition.getname().upper()] = True Laurent@705: for action in pou.getactionList(): Laurent@705: names[action.getname().upper()] = True Laurent@705: for config in project.getconfigurations(): Laurent@705: names[config.getname().upper()] = True Laurent@705: for resource in config.getresource(): Laurent@705: names[resource.getname().upper()] = True Laurent@705: Laurent@704: i = 0 Laurent@704: while name is None or names.get(name.upper(), False): laurent@384: name = (format%i) laurent@384: i += 1 laurent@384: return name laurent@384: laurent@384: CheckPasteCompatibility = {"SFC": lambda name: True, laurent@384: "LD": lambda name: not name.startswith("sfcObjects"), laurent@384: "FBD": lambda name: name.startswith("fbdObjects") or name.startswith("commonObjects")} laurent@384: laurent@384: def PasteEditedElementInstances(self, tagname, text, new_pos, middle=False, debug=False): laurent@384: element = self.GetEditedElement(tagname, debug) laurent@384: element_name, element_type = self.GetEditedElementType(tagname, debug) laurent@384: if element is not None: laurent@384: bodytype = element.getbodyType() laurent@384: laurent@384: # Get edited element type scaling laurent@384: scaling = None laurent@384: project = self.GetProject(debug) laurent@384: if project is not None: laurent@384: properties = project.getcontentHeader() laurent@384: scaling = properties["scaling"][bodytype] laurent@384: laurent@384: # Get ids already by all the instances in edited element laurent@384: used_id = dict([(instance.getlocalId(), True) for instance in element.getinstances()]) laurent@384: new_id = {} laurent@384: laurent@384: text = "%s"%text laurent@384: laurent@384: try: laurent@384: tree = minidom.parseString(text) laurent@384: except: laurent@384: return _("Invalid plcopen element(s)!!!") laurent@384: instances = [] laurent@384: exclude = {} laurent@384: for root in tree.childNodes: laurent@384: if root.nodeType == tree.ELEMENT_NODE and root.nodeName == "paste": laurent@384: for child in root.childNodes: laurent@384: if child.nodeType == tree.ELEMENT_NODE: b@428: if not child.nodeName in plcopen.ElementNameToClass: b@428: return _("\"%s\" element can't be pasted here!!!")%child.nodeName b@428: laurent@384: classname = plcopen.ElementNameToClass[child.nodeName] laurent@384: if not self.CheckPasteCompatibility[bodytype](classname): b@427: return _("\"%s\" element can't be pasted here!!!")%child.nodeName b@427: laurent@384: classobj = getattr(plcopen, classname, None) laurent@384: if classobj is not None: laurent@384: instance = classobj() laurent@384: instance.loadXMLTree(child) laurent@384: if child.nodeName == "block": laurent@384: blockname = instance.getinstanceName() laurent@384: if blockname is not None: laurent@384: blocktype = instance.gettypeName() laurent@384: if element_type == "function": b@427: return _("FunctionBlock \"%s\" can't be pasted in a Function!!!")%blocktype Laurent@704: blockname = self.GenerateNewName(tagname, blockname, "%s%%d"%blocktype, debug=debug) laurent@384: exclude[blockname] = True laurent@384: instance.setinstanceName(blockname) laurent@384: self.AddEditedElementPouVar(tagname, blocktype, blockname) laurent@384: elif child.nodeName == "step": laurent@384: stepname = self.GenerateNewName(tagname, instance.getname(), "Step%d", exclude, debug) laurent@384: exclude[stepname] = True laurent@384: instance.setname(stepname) laurent@384: localid = instance.getlocalId() laurent@384: if not used_id.has_key(localid): laurent@384: new_id[localid] = True laurent@384: instances.append((child.nodeName, instance)) laurent@384: laurent@384: if len(instances) == 0: laurent@384: return _("Invalid plcopen element(s)!!!") laurent@384: laurent@384: idx = 1 laurent@384: translate_id = {} laurent@384: bbox = plcopen.rect() laurent@384: for name, instance in instances: laurent@384: localId = instance.getlocalId() laurent@384: bbox.union(instance.getBoundingBox()) laurent@384: if used_id.has_key(localId): laurent@384: while used_id.has_key(idx) or new_id.has_key(idx): laurent@384: idx += 1 laurent@384: new_id[idx] = True laurent@384: instance.setlocalId(idx) laurent@384: translate_id[localId] = idx laurent@384: laurent@384: x, y, width, height = bbox.bounding_box() laurent@384: if middle: laurent@384: new_pos[0] -= width / 2 laurent@384: new_pos[1] -= height / 2 laurent@384: else: laurent@384: new_pos = map(lambda x: x + 30, new_pos) laurent@384: if scaling[0] != 0 and scaling[1] != 0: laurent@384: min_pos = map(lambda x: 30 / x, scaling) laurent@384: minx = round(min_pos[0]) laurent@384: if int(min_pos[0]) == round(min_pos[0]): laurent@384: minx += 1 laurent@384: miny = round(min_pos[1]) laurent@384: if int(min_pos[1]) == round(min_pos[1]): laurent@384: miny += 1 laurent@384: minx *= scaling[0] laurent@384: miny *= scaling[1] laurent@384: new_pos = (max(minx, round(new_pos[0] / scaling[0]) * scaling[0]), laurent@384: max(miny, round(new_pos[1] / scaling[1]) * scaling[1])) laurent@384: else: laurent@384: new_pos = (max(30, new_pos[0]), max(30, new_pos[1])) laurent@384: diff = (new_pos[0] - x, new_pos[1] - y) laurent@384: laurent@384: connections = {} laurent@384: for name, instance in instances: laurent@384: connections.update(instance.updateConnectionsId(translate_id)) laurent@384: if getattr(instance, "setexecutionOrderId", None) is not None: laurent@384: instance.setexecutionOrderId(0) laurent@384: instance.translate(*diff) laurent@384: element.addinstance(name, instance) laurent@384: laurent@384: return new_id, connections laurent@384: lbessard@121: # Return the current pou editing informations lbessard@249: def GetEditedElementInstanceInfos(self, tagname, id = None, exclude = [], debug = False): lbessard@121: infos = {} lbessard@121: instance = None lbessard@249: element = self.GetEditedElement(tagname, debug) lbessard@121: if element is not None: lbessard@121: # if id is defined lbessard@121: if id is not None: lbessard@151: instance = element.getinstance(id) etisserant@0: else: lbessard@151: instance = element.getrandomInstance(exclude) lbessard@121: if instance is not None: laurent@383: infos = instance.getinfos() laurent@383: if infos["type"] in ["input", "output", "inout"]: laurent@383: var_type = self.GetEditedElementVarValueType(tagname, infos["specific_values"]["name"], debug) laurent@383: infos["specific_values"]["value_type"] = var_type etisserant@0: return infos lbessard@249: return None etisserant@0: lbessard@121: def ClearEditedElementExecutionOrder(self, tagname): lbessard@121: element = self.GetEditedElement(tagname) lbessard@121: if element is not None: lbessard@151: element.resetexecutionOrder() lbessard@121: lbessard@121: def ResetEditedElementExecutionOrder(self, tagname): lbessard@121: element = self.GetEditedElement(tagname) lbessard@121: if element is not None: lbessard@151: element.compileexecutionOrder() lbessard@118: etisserant@0: # Return the variable type of the given pou lbessard@249: def GetEditedElementVarValueType(self, tagname, varname, debug = False): lbessard@249: project = self.GetProject(debug) lbessard@249: if project is not None: lbessard@249: words = tagname.split("::") lbessard@249: if words[0] in ["P","T","A"]: lbessard@249: pou = self.Project.getpou(words[1]) lbessard@249: if pou is not None: lbessard@256: if words[0] == "T" and varname == words[2]: lbessard@256: return "BOOL" lbessard@256: if words[1] == varname: lbessard@256: return self.GetPouInterfaceReturnType(pou) lbessard@249: for type, varlist in pou.getvars(): lbessard@249: for var in varlist.getvariable(): lbessard@249: if var.getname() == varname: lbessard@249: vartype_content = var.gettype().getcontent() lbessard@249: if vartype_content["name"] == "derived": lbessard@249: return vartype_content["value"].getname() lbessard@249: elif vartype_content["name"] in ["string", "wstring"]: lbessard@249: return vartype_content["name"].upper() lbessard@249: else: lbessard@249: return vartype_content["name"] etisserant@101: return None etisserant@0: etisserant@0: def SetConnectionWires(self, connection, connector): etisserant@0: wires = connector.GetWires() etisserant@0: idx = 0 etisserant@0: for wire, handle in wires: etisserant@0: points = wire.GetPoints(handle != 0) etisserant@0: if handle == 0: lbessard@27: result = wire.GetConnectedInfos(-1) etisserant@0: else: lbessard@27: result = wire.GetConnectedInfos(0) lbessard@27: if result != None: lbessard@27: refLocalId, formalParameter = result lbessard@173: connections = connection.getconnections() lbessard@173: if connections is None or len(connection.getconnections()) <= idx: lbessard@173: connection.addconnection() lbessard@151: connection.setconnectionId(idx, refLocalId) lbessard@151: connection.setconnectionPoints(idx, points) lbessard@27: if formalParameter != "": lbessard@151: connection.setconnectionParameter(idx, formalParameter) lbessard@27: else: lbessard@151: connection.setconnectionParameter(idx, None) etisserant@0: idx += 1 etisserant@0: laurent@435: def AddEditedElementPouVar(self, tagname, type, name, location="", description=""): lbessard@249: if self.Project is not None: lbessard@249: words = tagname.split("::") lbessard@249: if words[0] in ['P', 'T', 'A']: lbessard@249: pou = self.Project.getpou(words[1]) lbessard@249: if pou is not None: laurent@616: pou.addpouLocalVar(type, name, location, description) laurent@616: laurent@616: def AddEditedElementPouExternalVar(self, tagname, type, name): laurent@616: if self.Project is not None: laurent@616: words = tagname.split("::") laurent@616: if words[0] in ['P', 'T', 'A']: laurent@616: pou = self.Project.getpou(words[1]) laurent@616: if pou is not None: laurent@616: pou.addpouExternalVar(type, name) lbessard@145: lbessard@145: def ChangeEditedElementPouVar(self, tagname, old_type, old_name, new_type, new_name): lbessard@249: if self.Project is not None: lbessard@249: words = tagname.split("::") lbessard@249: if words[0] in ['P', 'T', 'A']: lbessard@249: pou = self.Project.getpou(words[1]) lbessard@249: if pou is not None: lbessard@249: pou.changepouVar(old_type, old_name, new_type, new_name) lbessard@145: lbessard@154: def RemoveEditedElementPouVar(self, tagname, type, name): lbessard@249: if self.Project is not None: lbessard@249: words = tagname.split("::") lbessard@249: if words[0] in ['P', 'T', 'A']: lbessard@249: pou = self.Project.getpou(words[1]) lbessard@249: if pou is not None: lbessard@249: pou.removepouVar(type, name) lbessard@154: lbessard@121: def AddEditedElementBlock(self, tagname, id, blocktype, blockname = None): lbessard@121: element = self.GetEditedElement(tagname) lbessard@121: if element is not None: lbessard@151: block = plcopen.fbdObjects_block() lbessard@151: block.setlocalId(id) lbessard@151: block.settypeName(blocktype) lbessard@226: blocktype_infos = self.GetBlockType(blocktype) lbessard@121: if blocktype_infos["type"] != "function" and blockname is not None: lbessard@151: block.setinstanceName(blockname) lbessard@145: self.AddEditedElementPouVar(tagname, blocktype, blockname) lbessard@151: element.addinstance("block", block) lbessard@229: self.Project.RefreshElementUsingTree() lbessard@121: lbessard@121: def SetEditedElementBlockInfos(self, tagname, id, infos): lbessard@121: element = self.GetEditedElement(tagname) lbessard@121: if element is not None: lbessard@151: block = element.getinstance(id) lbessard@208: if block is None: lbessard@208: return lbessard@154: old_name = block.getinstanceName() lbessard@154: old_type = block.gettypeName() lbessard@154: new_name = infos.get("name", old_name) lbessard@154: new_type = infos.get("type", old_type) lbessard@236: if new_type != old_type: lbessard@236: old_typeinfos = self.GetBlockType(old_type) lbessard@236: new_typeinfos = self.GetBlockType(new_type) lbessard@236: if old_typeinfos is None or new_typeinfos is None: lbessard@236: self.ChangeEditedElementPouVar(tagname, old_type, old_name, new_type, new_name) lbessard@236: elif new_typeinfos["type"] != old_typeinfos["type"]: lbessard@236: if new_typeinfos["type"] == "function": lbessard@236: self.RemoveEditedElementPouVar(tagname, old_type, old_name) lbessard@236: else: lbessard@236: self.AddEditedElementPouVar(tagname, new_type, new_name) laurent@646: elif new_typeinfos["type"] != "function": lbessard@236: self.ChangeEditedElementPouVar(tagname, old_type, old_name, new_type, new_name) lbessard@236: elif new_name != old_name: lbessard@154: self.ChangeEditedElementPouVar(tagname, old_type, old_name, new_type, new_name) lbessard@121: for param, value in infos.items(): lbessard@121: if param == "name": lbessard@151: block.setinstanceName(value) lbessard@121: elif param == "type": lbessard@151: block.settypeName(value) lbessard@151: elif param == "executionOrder" and block.getexecutionOrderId() != value: lbessard@162: element.setelementExecutionOrder(block, value) lbessard@121: elif param == "height": lbessard@151: block.setheight(value) lbessard@121: elif param == "width": lbessard@151: block.setwidth(value) lbessard@121: elif param == "x": lbessard@151: block.setx(value) lbessard@121: elif param == "y": lbessard@151: block.sety(value) lbessard@121: elif param == "connectors": lbessard@151: block.inputVariables.setvariable([]) lbessard@151: block.outputVariables.setvariable([]) lbessard@121: for connector in value["inputs"]: lbessard@121: variable = plcopen.inputVariables_variable() lbessard@151: variable.setformalParameter(connector.GetName()) lbessard@121: if connector.IsNegated(): lbessard@151: variable.setnegated(True) lbessard@121: if connector.GetEdge() != "none": lbessard@151: variable.setedge(connector.GetEdge()) lbessard@121: position = connector.GetRelPosition() lbessard@151: variable.connectionPointIn.setrelPositionXY(position.x, position.y) lbessard@121: self.SetConnectionWires(variable.connectionPointIn, connector) lbessard@151: block.inputVariables.appendvariable(variable) lbessard@121: for connector in value["outputs"]: lbessard@121: variable = plcopen.outputVariables_variable() lbessard@151: variable.setformalParameter(connector.GetName()) lbessard@121: if connector.IsNegated(): lbessard@151: variable.setnegated(True) lbessard@121: if connector.GetEdge() != "none": lbessard@151: variable.setedge(connector.GetEdge()) lbessard@121: position = connector.GetRelPosition() lbessard@151: variable.addconnectionPointOut() lbessard@151: variable.connectionPointOut.setrelPositionXY(position.x, position.y) lbessard@151: block.outputVariables.appendvariable(variable) lbessard@229: self.Project.RefreshElementUsingTree() etisserant@0: lbessard@121: def AddEditedElementVariable(self, tagname, id, type): lbessard@121: element = self.GetEditedElement(tagname) lbessard@121: if element is not None: lbessard@121: if type == INPUT: lbessard@121: name = "inVariable" lbessard@151: variable = plcopen.fbdObjects_inVariable() lbessard@121: elif type == OUTPUT: lbessard@121: name = "outVariable" lbessard@151: variable = plcopen.fbdObjects_outVariable() lbessard@121: elif type == INOUT: lbessard@121: name = "inOutVariable" lbessard@151: variable = plcopen.fbdObjects_inOutVariable() lbessard@151: variable.setlocalId(id) lbessard@151: element.addinstance(name, variable) etisserant@0: lbessard@121: def SetEditedElementVariableInfos(self, tagname, id, infos): lbessard@121: element = self.GetEditedElement(tagname) lbessard@121: if element is not None: lbessard@151: variable = element.getinstance(id) lbessard@208: if variable is None: lbessard@208: return lbessard@121: for param, value in infos.items(): lbessard@121: if param == "name": lbessard@151: variable.setexpression(value) lbessard@151: elif param == "executionOrder" and variable.getexecutionOrderId() != value: lbessard@162: element.setelementExecutionOrder(variable, value) lbessard@121: elif param == "height": lbessard@151: variable.setheight(value) lbessard@121: elif param == "width": lbessard@151: variable.setwidth(value) lbessard@121: elif param == "x": lbessard@151: variable.setx(value) lbessard@121: elif param == "y": lbessard@151: variable.sety(value) lbessard@121: elif param == "connectors": laurent@383: if len(value["outputs"]) > 0: laurent@383: output = value["outputs"][0] laurent@383: if len(value["inputs"]) > 0: laurent@383: variable.setnegatedOut(output.IsNegated()) laurent@383: variable.setedgeOut(output.GetEdge()) laurent@383: else: laurent@383: variable.setnegated(output.IsNegated()) laurent@383: variable.setedge(output.GetEdge()) laurent@383: position = output.GetRelPosition() lbessard@151: variable.addconnectionPointOut() lbessard@151: variable.connectionPointOut.setrelPositionXY(position.x, position.y) laurent@383: if len(value["inputs"]) > 0: laurent@383: input = value["inputs"][0] laurent@383: if len(value["outputs"]) > 0: laurent@383: variable.setnegatedIn(input.IsNegated()) laurent@383: variable.setedgeIn(input.GetEdge()) laurent@383: else: laurent@383: variable.setnegated(input.IsNegated()) laurent@383: variable.setedge(input.GetEdge()) laurent@383: position = input.GetRelPosition() lbessard@151: variable.addconnectionPointIn() lbessard@151: variable.connectionPointIn.setrelPositionXY(position.x, position.y) laurent@383: self.SetConnectionWires(variable.connectionPointIn, input) lbessard@121: lbessard@121: def AddEditedElementConnection(self, tagname, id, type): lbessard@121: element = self.GetEditedElement(tagname) lbessard@121: if element is not None: lbessard@121: if type == CONNECTOR: lbessard@121: name = "connector" lbessard@151: connection = plcopen.commonObjects_connector() lbessard@121: elif type == CONTINUATION: lbessard@121: name = "continuation" lbessard@151: connection = plcopen.commonObjects_continuation() lbessard@151: connection.setlocalId(id) lbessard@151: element.addinstance(name, connection) etisserant@0: lbessard@121: def SetEditedElementConnectionInfos(self, tagname, id, infos): lbessard@121: element = self.GetEditedElement(tagname) lbessard@121: if element is not None: lbessard@151: connection = element.getinstance(id) lbessard@208: if connection is None: lbessard@208: return lbessard@121: for param, value in infos.items(): lbessard@121: if param == "name": lbessard@151: connection.setname(value) lbessard@121: elif param == "height": lbessard@151: connection.setheight(value) lbessard@121: elif param == "width": lbessard@151: connection.setwidth(value) lbessard@121: elif param == "x": lbessard@151: connection.setx(value) lbessard@121: elif param == "y": lbessard@151: connection.sety(value) lbessard@121: elif param == "connector": lbessard@121: position = value.GetRelPosition() lbessard@151: if isinstance(connection, plcopen.commonObjects_continuation): lbessard@151: connection.addconnectionPointOut() lbessard@151: connection.connectionPointOut.setrelPositionXY(position.x, position.y) lbessard@151: elif isinstance(connection, plcopen.commonObjects_connector): lbessard@151: connection.addconnectionPointIn() lbessard@151: connection.connectionPointIn.setrelPositionXY(position.x, position.y) lbessard@121: self.SetConnectionWires(connection.connectionPointIn, value) lbessard@121: lbessard@121: def AddEditedElementComment(self, tagname, id): lbessard@121: element = self.GetEditedElement(tagname) lbessard@121: if element is not None: lbessard@151: comment = plcopen.commonObjects_comment() lbessard@151: comment.setlocalId(id) lbessard@151: element.addinstance("comment", comment) lbessard@121: lbessard@121: def SetEditedElementCommentInfos(self, tagname, id, infos): lbessard@121: element = self.GetEditedElement(tagname) lbessard@121: if element is not None: lbessard@151: comment = element.getinstance(id) lbessard@121: for param, value in infos.items(): lbessard@121: if param == "content": lbessard@151: comment.setcontentText(value) lbessard@121: elif param == "height": lbessard@151: comment.setheight(value) lbessard@121: elif param == "width": lbessard@151: comment.setwidth(value) lbessard@121: elif param == "x": lbessard@151: comment.setx(value) lbessard@121: elif param == "y": lbessard@151: comment.sety(value) lbessard@121: lbessard@121: def AddEditedElementPowerRail(self, tagname, id, type): lbessard@121: element = self.GetEditedElement(tagname) lbessard@121: if element is not None: lbessard@121: if type == LEFTRAIL: lbessard@121: name = "leftPowerRail" lbessard@151: powerrail = plcopen.ldObjects_leftPowerRail() lbessard@121: elif type == RIGHTRAIL: lbessard@121: name = "rightPowerRail" lbessard@151: powerrail = plcopen.ldObjects_rightPowerRail() lbessard@151: powerrail.setlocalId(id) lbessard@151: element.addinstance(name, powerrail) lbessard@121: lbessard@121: def SetEditedElementPowerRailInfos(self, tagname, id, infos): lbessard@121: element = self.GetEditedElement(tagname) lbessard@121: if element is not None: lbessard@151: powerrail = element.getinstance(id) lbessard@208: if powerrail is None: lbessard@208: return lbessard@121: for param, value in infos.items(): lbessard@121: if param == "height": lbessard@151: powerrail.setheight(value) lbessard@121: elif param == "width": lbessard@151: powerrail.setwidth(value) lbessard@121: elif param == "x": lbessard@151: powerrail.setx(value) lbessard@121: elif param == "y": lbessard@151: powerrail.sety(value) lbessard@121: elif param == "connectors": lbessard@151: if isinstance(powerrail, plcopen.ldObjects_leftPowerRail): lbessard@151: powerrail.setconnectionPointOut([]) laurent@383: for connector in value["outputs"]: lbessard@121: position = connector.GetRelPosition() lbessard@121: connection = plcopen.leftPowerRail_connectionPointOut() lbessard@151: connection.setrelPositionXY(position.x, position.y) lbessard@121: powerrail.connectionPointOut.append(connection) lbessard@151: elif isinstance(powerrail, plcopen.ldObjects_rightPowerRail): lbessard@151: powerrail.setconnectionPointIn([]) laurent@383: for connector in value["inputs"]: lbessard@121: position = connector.GetRelPosition() lbessard@121: connection = plcopen.connectionPointIn() lbessard@151: connection.setrelPositionXY(position.x, position.y) lbessard@121: self.SetConnectionWires(connection, connector) lbessard@121: powerrail.connectionPointIn.append(connection) lbessard@121: lbessard@128: def AddEditedElementContact(self, tagname, id): lbessard@121: element = self.GetEditedElement(tagname) lbessard@121: if element is not None: lbessard@151: contact = plcopen.ldObjects_contact() lbessard@151: contact.setlocalId(id) lbessard@151: element.addinstance("contact", contact) lbessard@121: lbessard@121: def SetEditedElementContactInfos(self, tagname, id, infos): lbessard@121: element = self.GetEditedElement(tagname) lbessard@121: if element is not None: lbessard@151: contact = element.getinstance(id) lbessard@208: if contact is None: lbessard@208: return lbessard@121: for param, value in infos.items(): lbessard@121: if param == "name": lbessard@151: contact.setvariable(value) lbessard@121: elif param == "type": lbessard@121: if value == CONTACT_NORMAL: lbessard@151: contact.setnegated(False) lbessard@151: contact.setedge("none") lbessard@121: elif value == CONTACT_REVERSE: lbessard@151: contact.setnegated(True) lbessard@151: contact.setedge("none") lbessard@121: elif value == CONTACT_RISING: lbessard@151: contact.setnegated(False) lbessard@151: contact.setedge("rising") lbessard@121: elif value == CONTACT_FALLING: lbessard@151: contact.setnegated(False) lbessard@151: contact.setedge("falling") lbessard@121: elif param == "height": lbessard@151: contact.setheight(value) lbessard@121: elif param == "width": lbessard@151: contact.setwidth(value) lbessard@121: elif param == "x": lbessard@151: contact.setx(value) lbessard@121: elif param == "y": lbessard@151: contact.sety(value) lbessard@121: elif param == "connectors": laurent@383: input_connector = value["inputs"][0] etisserant@0: position = input_connector.GetRelPosition() lbessard@151: contact.addconnectionPointIn() lbessard@151: contact.connectionPointIn.setrelPositionXY(position.x, position.y) lbessard@121: self.SetConnectionWires(contact.connectionPointIn, input_connector) laurent@383: output_connector = value["outputs"][0] etisserant@0: position = output_connector.GetRelPosition() lbessard@151: contact.addconnectionPointOut() lbessard@151: contact.connectionPointOut.setrelPositionXY(position.x, position.y) lbessard@121: lbessard@121: def AddEditedElementCoil(self, tagname, id): lbessard@121: element = self.GetEditedElement(tagname) lbessard@121: if element is not None: lbessard@151: coil = plcopen.ldObjects_coil() lbessard@151: coil.setlocalId(id) lbessard@151: element.addinstance("coil", coil) lbessard@121: lbessard@121: def SetEditedElementCoilInfos(self, tagname, id, infos): lbessard@121: element = self.GetEditedElement(tagname) lbessard@121: if element is not None: lbessard@151: coil = element.getinstance(id) lbessard@208: if coil is None: lbessard@208: return lbessard@121: for param, value in infos.items(): lbessard@121: if param == "name": lbessard@151: coil.setvariable(value) lbessard@121: elif param == "type": lbessard@121: if value == COIL_NORMAL: lbessard@151: coil.setnegated(False) lbessard@151: coil.setstorage("none") lbessard@269: coil.setedge("none") lbessard@121: elif value == COIL_REVERSE: lbessard@151: coil.setnegated(True) lbessard@151: coil.setstorage("none") lbessard@269: coil.setedge("none") lbessard@121: elif value == COIL_SET: lbessard@151: coil.setnegated(False) lbessard@151: coil.setstorage("set") lbessard@269: coil.setedge("none") lbessard@121: elif value == COIL_RESET: lbessard@151: coil.setnegated(False) lbessard@151: coil.setstorage("reset") lbessard@269: coil.setedge("none") lbessard@269: elif value == COIL_RISING: lbessard@269: coil.setnegated(False) lbessard@269: coil.setstorage("none") lbessard@269: coil.setedge("rising") lbessard@269: elif value == COIL_FALLING: lbessard@269: coil.setnegated(False) lbessard@269: coil.setstorage("none") lbessard@269: coil.setedge("falling") lbessard@121: elif param == "height": lbessard@151: coil.setheight(value) lbessard@121: elif param == "width": lbessard@151: coil.setwidth(value) lbessard@121: elif param == "x": lbessard@151: coil.setx(value) lbessard@121: elif param == "y": lbessard@151: coil.sety(value) lbessard@121: elif param == "connectors": laurent@383: input_connector = value["inputs"][0] lbessard@121: position = input_connector.GetRelPosition() lbessard@151: coil.addconnectionPointIn() lbessard@151: coil.connectionPointIn.setrelPositionXY(position.x, position.y) lbessard@121: self.SetConnectionWires(coil.connectionPointIn, input_connector) laurent@383: output_connector = value["outputs"][0] lbessard@121: position = output_connector.GetRelPosition() lbessard@151: coil.addconnectionPointOut() lbessard@151: coil.connectionPointOut.setrelPositionXY(position.x, position.y) lbessard@121: lbessard@121: def AddEditedElementStep(self, tagname, id): lbessard@121: element = self.GetEditedElement(tagname) lbessard@121: if element is not None: lbessard@151: step = plcopen.sfcObjects_step() lbessard@151: step.setlocalId(id) lbessard@151: element.addinstance("step", step) lbessard@121: lbessard@121: def SetEditedElementStepInfos(self, tagname, id, infos): lbessard@121: element = self.GetEditedElement(tagname) lbessard@121: if element is not None: lbessard@151: step = element.getinstance(id) lbessard@208: if step is None: lbessard@208: return lbessard@121: for param, value in infos.items(): lbessard@121: if param == "name": lbessard@151: step.setname(value) lbessard@121: elif param == "initial": lbessard@151: step.setinitialStep(value) lbessard@121: elif param == "height": lbessard@151: step.setheight(value) lbessard@121: elif param == "width": lbessard@151: step.setwidth(value) lbessard@121: elif param == "x": lbessard@151: step.setx(value) lbessard@121: elif param == "y": lbessard@151: step.sety(value) lbessard@121: elif param == "connectors": laurent@383: if len(value["inputs"]) > 0: laurent@383: input_connector = value["inputs"][0] etisserant@0: position = input_connector.GetRelPosition() lbessard@151: step.addconnectionPointIn() lbessard@151: step.connectionPointIn.setrelPositionXY(position.x, position.y) lbessard@121: self.SetConnectionWires(step.connectionPointIn, input_connector) lbessard@121: else: lbessard@151: step.deleteconnectionPointIn() laurent@383: if len(value["outputs"]) > 0: laurent@383: output_connector = value["outputs"][0] etisserant@0: position = output_connector.GetRelPosition() lbessard@151: step.addconnectionPointOut() lbessard@151: step.connectionPointOut.setrelPositionXY(position.x, position.y) lbessard@151: else: lbessard@151: step.deleteconnectionPointOut() laurent@383: elif param == "action": laurent@383: if value: laurent@383: position = value.GetRelPosition() lbessard@151: step.addconnectionPointOutAction() lbessard@151: step.connectionPointOutAction.setrelPositionXY(position.x, position.y) lbessard@151: else: lbessard@151: step.deleteconnectionPointOutAction() lbessard@121: lbessard@121: def AddEditedElementTransition(self, tagname, id): lbessard@121: element = self.GetEditedElement(tagname) lbessard@121: if element is not None: lbessard@151: transition = plcopen.sfcObjects_transition() lbessard@151: transition.setlocalId(id) lbessard@151: element.addinstance("transition", transition) lbessard@121: lbessard@121: def SetEditedElementTransitionInfos(self, tagname, id, infos): lbessard@121: element = self.GetEditedElement(tagname) lbessard@121: if element is not None: lbessard@151: transition = element.getinstance(id) lbessard@208: if transition is None: lbessard@208: return lbessard@121: for param, value in infos.items(): lbessard@121: if param == "type" and value != "connection": lbessard@151: transition.setconditionContent(value, infos["condition"]) lbessard@121: elif param == "height": lbessard@151: transition.setheight(value) lbessard@121: elif param == "width": lbessard@151: transition.setwidth(value) lbessard@121: elif param == "x": lbessard@151: transition.setx(value) lbessard@121: elif param == "y": lbessard@151: transition.sety(value) lbessard@121: elif param == "priority": lbessard@121: if value != 0: lbessard@151: transition.setpriority(value) lbessard@151: else: lbessard@151: transition.setpriority(None) lbessard@121: elif param == "connectors": laurent@383: input_connector = value["inputs"][0] lbessard@121: position = input_connector.GetRelPosition() lbessard@151: transition.addconnectionPointIn() lbessard@151: transition.connectionPointIn.setrelPositionXY(position.x, position.y) lbessard@121: self.SetConnectionWires(transition.connectionPointIn, input_connector) laurent@383: output_connector = value["outputs"][0] lbessard@121: position = output_connector.GetRelPosition() lbessard@151: transition.addconnectionPointOut() lbessard@151: transition.connectionPointOut.setrelPositionXY(position.x, position.y) laurent@383: elif infos.get("type", None) == "connection" and param == "connection" and value: laurent@383: transition.setconditionContent("connection", None) laurent@389: self.SetConnectionWires(transition.condition.content["value"], value) lbessard@121: lbessard@121: def AddEditedElementDivergence(self, tagname, id, type): lbessard@121: element = self.GetEditedElement(tagname) lbessard@121: if element is not None: lbessard@121: if type == SELECTION_DIVERGENCE: lbessard@121: name = "selectionDivergence" lbessard@151: divergence = plcopen.sfcObjects_selectionDivergence() lbessard@121: elif type == SELECTION_CONVERGENCE: lbessard@121: name = "selectionConvergence" lbessard@151: divergence = plcopen.sfcObjects_selectionConvergence() lbessard@121: elif type == SIMULTANEOUS_DIVERGENCE: lbessard@121: name = "simultaneousDivergence" lbessard@151: divergence = plcopen.sfcObjects_simultaneousDivergence() lbessard@121: elif type == SIMULTANEOUS_CONVERGENCE: lbessard@121: name = "simultaneousConvergence" lbessard@151: divergence = plcopen.sfcObjects_simultaneousConvergence() lbessard@151: divergence.setlocalId(id) lbessard@151: element.addinstance(name, divergence) lbessard@121: lbessard@121: def SetEditedElementDivergenceInfos(self, tagname, id, infos): lbessard@121: element = self.GetEditedElement(tagname) lbessard@121: if element is not None: lbessard@151: divergence = element.getinstance(id) lbessard@208: if divergence is None: lbessard@208: return lbessard@121: for param, value in infos.items(): lbessard@121: if param == "height": lbessard@151: divergence.setheight(value) lbessard@121: elif param == "width": lbessard@151: divergence.setwidth(value) lbessard@121: elif param == "x": lbessard@151: divergence.setx(value) lbessard@121: elif param == "y": lbessard@151: divergence.sety(value) lbessard@121: elif param == "connectors": lbessard@121: input_connectors = value["inputs"] lbessard@151: if isinstance(divergence, (plcopen.sfcObjects_selectionDivergence, plcopen.sfcObjects_simultaneousDivergence)): lbessard@121: position = input_connectors[0].GetRelPosition() lbessard@151: divergence.addconnectionPointIn() lbessard@151: divergence.connectionPointIn.setrelPositionXY(position.x, position.y) lbessard@121: self.SetConnectionWires(divergence.connectionPointIn, input_connectors[0]) lbessard@121: else: lbessard@151: divergence.setconnectionPointIn([]) lbessard@121: for input_connector in input_connectors: lbessard@121: position = input_connector.GetRelPosition() lbessard@151: if isinstance(divergence, plcopen.sfcObjects_selectionConvergence): lbessard@121: connection = plcopen.selectionConvergence_connectionPointIn() lbessard@121: else: lbessard@121: connection = plcopen.connectionPointIn() lbessard@151: connection.setrelPositionXY(position.x, position.y) lbessard@121: self.SetConnectionWires(connection, input_connector) lbessard@151: divergence.appendconnectionPointIn(connection) lbessard@121: output_connectors = value["outputs"] lbessard@151: if isinstance(divergence, (plcopen.sfcObjects_selectionConvergence, plcopen.sfcObjects_simultaneousConvergence)): lbessard@121: position = output_connectors[0].GetRelPosition() lbessard@151: divergence.addconnectionPointOut() lbessard@151: divergence.connectionPointOut.setrelPositionXY(position.x, position.y) lbessard@151: else: lbessard@151: divergence.setconnectionPointOut([]) lbessard@121: for output_connector in output_connectors: lbessard@121: position = output_connector.GetRelPosition() lbessard@151: if isinstance(divergence, plcopen.sfcObjects_selectionDivergence): lbessard@121: connection = plcopen.selectionDivergence_connectionPointOut() lbessard@121: else: lbessard@121: connection = plcopen.simultaneousDivergence_connectionPointOut() lbessard@151: connection.setrelPositionXY(position.x, position.y) lbessard@151: divergence.appendconnectionPointOut(connection) lbessard@121: lbessard@121: def AddEditedElementJump(self, tagname, id): lbessard@121: element = self.GetEditedElement(tagname) lbessard@121: if element is not None: lbessard@151: jump = plcopen.sfcObjects_jumpStep() lbessard@151: jump.setlocalId(id) lbessard@151: element.addinstance("jumpStep", jump) lbessard@121: lbessard@121: def SetEditedElementJumpInfos(self, tagname, id, infos): lbessard@121: element = self.GetEditedElement(tagname) lbessard@121: if element is not None: lbessard@151: jump = element.getinstance(id) lbessard@208: if jump is None: lbessard@208: return lbessard@121: for param, value in infos.items(): lbessard@121: if param == "target": lbessard@151: jump.settargetName(value) lbessard@121: elif param == "height": lbessard@151: jump.setheight(value) lbessard@121: elif param == "width": lbessard@151: jump.setwidth(value) lbessard@121: elif param == "x": lbessard@151: jump.setx(value) lbessard@121: elif param == "y": lbessard@151: jump.sety(value) lbessard@121: elif param == "connector": lbessard@121: position = value.GetRelPosition() lbessard@151: jump.addconnectionPointIn() lbessard@151: jump.connectionPointIn.setrelPositionXY(position.x, position.y) lbessard@121: self.SetConnectionWires(jump.connectionPointIn, value) etisserant@0: lbessard@121: def AddEditedElementActionBlock(self, tagname, id): lbessard@121: element = self.GetEditedElement(tagname) lbessard@121: if element is not None: lbessard@151: actionBlock = plcopen.commonObjects_actionBlock() lbessard@151: actionBlock.setlocalId(id) lbessard@151: element.addinstance("actionBlock", actionBlock) lbessard@121: lbessard@121: def SetEditedElementActionBlockInfos(self, tagname, id, infos): lbessard@121: element = self.GetEditedElement(tagname) lbessard@121: if element is not None: lbessard@151: actionBlock = element.getinstance(id) lbessard@208: if actionBlock is None: lbessard@208: return lbessard@121: for param, value in infos.items(): lbessard@121: if param == "actions": lbessard@151: actionBlock.setactions(value) lbessard@121: elif param == "height": lbessard@151: actionBlock.setheight(value) lbessard@121: elif param == "width": lbessard@151: actionBlock.setwidth(value) lbessard@121: elif param == "x": lbessard@151: actionBlock.setx(value) lbessard@121: elif param == "y": lbessard@151: actionBlock.sety(value) lbessard@121: elif param == "connector": lbessard@121: position = value.GetRelPosition() lbessard@151: actionBlock.addconnectionPointIn() lbessard@151: actionBlock.connectionPointIn.setrelPositionXY(position.x, position.y) lbessard@121: self.SetConnectionWires(actionBlock.connectionPointIn, value) lbessard@121: lbessard@121: def RemoveEditedElementInstance(self, tagname, id): lbessard@121: element = self.GetEditedElement(tagname) lbessard@121: if element is not None: lbessard@151: instance = element.getinstance(id) lbessard@151: if isinstance(instance, plcopen.fbdObjects_block): lbessard@154: self.RemoveEditedElementPouVar(tagname, instance.gettypeName(), instance.getinstanceName()) lbessard@151: element.removeinstance(id) lbessard@229: self.Project.RefreshElementUsingTree() lbessard@121: lbessard@249: def GetEditedResourceVariables(self, tagname, debug = False): etisserant@0: varlist = [] lbessard@121: words = tagname.split("::") lbessard@249: for var in self.GetConfigurationGlobalVars(words[1], debug): etisserant@0: if var["Type"] == "BOOL": etisserant@0: varlist.append(var["Name"]) lbessard@249: for var in self.GetConfigurationResourceGlobalVars(words[1], words[2], debug): etisserant@0: if var["Type"] == "BOOL": etisserant@0: varlist.append(var["Name"]) etisserant@0: return varlist etisserant@0: lbessard@137: def SetEditedResourceInfos(self, tagname, tasks, instances): lbessard@121: resource = self.GetEditedElement(tagname) lbessard@121: if resource is not None: lbessard@151: resource.settask([]) lbessard@151: resource.setpouInstance([]) lbessard@121: task_list = {} lbessard@121: for task in tasks: lbessard@121: new_task = plcopen.resource_task() lbessard@151: new_task.setname(task["Name"]) laurent@560: if task["Triggering"] == "Interrupt": lbessard@151: new_task.setsingle(task["Single"]) laurent@389: ## result = duration_model.match(task["Interval"]).groups() laurent@389: ## if reduce(lambda x, y: x or y != None, result): laurent@389: ## values = [] laurent@389: ## for value in result[:-1]: laurent@389: ## if value != None: laurent@389: ## values.append(int(value)) laurent@389: ## else: laurent@389: ## values.append(0) laurent@389: ## if result[-1] is not None: laurent@389: ## values.append(int(float(result[-1]) * 1000)) laurent@389: ## new_task.setinterval(datetime.time(*values)) laurent@560: if task["Triggering"] == "Cyclic": laurent@389: new_task.setinterval(task["Interval"]) lbessard@151: new_task.setpriority(int(task["Priority"])) lbessard@121: if task["Name"] != "": lbessard@121: task_list[task["Name"]] = new_task lbessard@151: resource.appendtask(new_task) lbessard@121: for instance in instances: lbessard@121: new_instance = plcopen.pouInstance() lbessard@151: new_instance.setname(instance["Name"]) laurent@389: new_instance.settypeName(instance["Type"]) laurent@407: task_list.get(instance["Task"], resource).appendpouInstance(new_instance) lbessard@121: lbessard@249: def GetEditedResourceInfos(self, tagname, debug = False): lbessard@249: resource = self.GetEditedElement(tagname, debug) lbessard@121: if resource is not None: lbessard@151: tasks = resource.gettask() lbessard@151: instances = resource.getpouInstance() lbessard@121: tasks_data = [] lbessard@121: instances_data = [] lbessard@121: for task in tasks: lbessard@121: new_task = {} lbessard@151: new_task["Name"] = task.getname() lbessard@151: single = task.getsingle() laurent@560: if single is not None: lbessard@121: new_task["Single"] = single lbessard@121: else: lbessard@121: new_task["Single"] = "" lbessard@151: interval = task.getinterval() laurent@560: if interval is not None: laurent@389: ## text = "" laurent@389: ## if interval.hour != 0: laurent@389: ## text += "%dh"%interval.hour laurent@389: ## if interval.minute != 0: laurent@389: ## text += "%dm"%interval.minute laurent@389: ## if interval.second != 0: laurent@389: ## text += "%ds"%interval.second laurent@389: ## if interval.microsecond != 0: laurent@389: ## if interval.microsecond % 1000 != 0: laurent@389: ## text += "%.3fms"%(float(interval.microsecond) / 1000) laurent@389: ## else: laurent@389: ## text += "%dms"%(interval.microsecond / 1000) laurent@389: ## new_task["Interval"] = text laurent@389: new_task["Interval"] = interval lbessard@121: else: lbessard@121: new_task["Interval"] = "" laurent@560: if single is not None and interval is None: laurent@560: new_task["Triggering"] = "Interrupt" laurent@560: elif interval is not None and single is None: laurent@560: new_task["Triggering"] = "Cyclic" laurent@560: else: laurent@560: new_task["Triggering"] = "" lbessard@151: new_task["Priority"] = str(task.getpriority()) lbessard@121: tasks_data.append(new_task) lbessard@151: for instance in task.getpouInstance(): lbessard@121: new_instance = {} lbessard@151: new_instance["Name"] = instance.getname() laurent@389: new_instance["Type"] = instance.gettypeName() lbessard@151: new_instance["Task"] = task.getname() lbessard@121: instances_data.append(new_instance) lbessard@121: for instance in instances: etisserant@0: new_instance = {} lbessard@151: new_instance["Name"] = instance.getname() laurent@389: new_instance["Type"] = instance.gettypeName() lbessard@121: new_instance["Task"] = "" etisserant@0: instances_data.append(new_instance) lbessard@121: return tasks_data, instances_data etisserant@0: etisserant@0: def OpenXMLFile(self, filepath): lbessard@151: xmlfile = open(filepath, 'r') lbessard@151: tree = minidom.parse(xmlfile) lbessard@151: xmlfile.close() etisserant@0: etisserant@0: self.Project = plcopen.project() lbessard@116: for child in tree.childNodes: lbessard@116: if child.nodeType == tree.ELEMENT_NODE and child.nodeName == "project": laurent@500: try: laurent@684: result = self.Project.loadXMLTree(child) laurent@500: except ValueError, e: laurent@500: return _("Project file syntax error:\n\n") + str(e) lbessard@116: self.SetFilePath(filepath) lbessard@226: self.Project.RefreshElementUsingTree() lbessard@226: self.Project.RefreshDataTypeHierarchy() lbessard@226: self.Project.RefreshCustomBlockTypes() greg@349: self.CreateProjectBuffer(True) lbessard@249: self.ProgramChunks = [] greg@369: self.ProgramOffset = 0 lbessard@252: self.NextCompiledProject = self.Copy(self.Project) lbessard@249: self.CurrentCompiledProject = None lbessard@116: self.Buffering = False lbessard@116: self.CurrentElementEditing = None lbessard@117: return None laurent@391: return _("No PLC project found") etisserant@0: etisserant@0: def SaveXMLFile(self, filepath = None): etisserant@0: if not filepath and self.FilePath == "": etisserant@0: return False etisserant@0: else: Laurent@702: contentheader = {"modificationDateTime": datetime.datetime(*localtime()[:6])} lbessard@151: self.Project.setcontentHeader(contentheader) lbessard@145: etisserant@0: text = "\n" etisserant@0: extras = {"xmlns" : "http://www.plcopen.org/xml/tc6.xsd", etisserant@0: "xmlns:xhtml" : "http://www.w3.org/1999/xhtml", etisserant@0: "xmlns:xsi" : "http://www.w3.org/2001/XMLSchema-instance", lbessard@274: "xsi:schemaLocation" : "http://www.plcopen.org/xml/tc6.xsd"} etisserant@0: text += self.Project.generateXMLText("project", 0, extras) lbessard@125: etisserant@0: if filepath: etisserant@0: xmlfile = open(filepath,"w") etisserant@0: else: etisserant@0: xmlfile = open(self.FilePath,"w") laurent@452: xmlfile.write(text.encode("utf-8")) etisserant@0: xmlfile.close() greg@351: self.MarkProjectAsSaved() etisserant@0: if filepath: etisserant@0: self.SetFilePath(filepath) etisserant@0: return True etisserant@0: etisserant@0: #------------------------------------------------------------------------------- laurent@566: # Search in Current Project Functions laurent@566: #------------------------------------------------------------------------------- laurent@566: laurent@566: def SearchInProject(self, criteria): laurent@566: return self.Project.Search(criteria) laurent@566: Laurent@738: def SearchInPou(self, tagname, criteria, debug=False): Laurent@738: pou = self.GetEditedElement(tagname, debug) Laurent@738: if pou is not None: Laurent@738: return pou.Search(criteria) Laurent@738: return [] Laurent@738: laurent@566: #------------------------------------------------------------------------------- etisserant@0: # Current Buffering Management Functions etisserant@0: #------------------------------------------------------------------------------- etisserant@0: etisserant@0: """ etisserant@0: Return a copy of the project etisserant@0: """ etisserant@0: def Copy(self, model): etisserant@0: return cPickle.loads(cPickle.dumps(model)) etisserant@0: greg@349: def CreateProjectBuffer(self, saved): greg@349: if self.ProjectBufferEnabled: laurent@530: self.ProjectBuffer = UndoBuffer(cPickle.dumps(self.Project), saved) greg@349: else: greg@349: self.ProjectBuffer = None greg@349: self.ProjectSaved = saved greg@349: greg@349: def IsProjectBufferEnabled(self): greg@349: return self.ProjectBufferEnabled greg@349: greg@349: def EnableProjectBuffer(self, enable): greg@349: self.ProjectBufferEnabled = enable greg@349: if self.Project is not None: greg@349: if enable: greg@349: current_saved = self.ProjectSaved greg@349: else: greg@349: current_saved = self.ProjectBuffer.IsCurrentSaved() greg@349: self.CreateProjectBuffer(current_saved) greg@349: etisserant@0: def BufferProject(self): greg@349: if self.ProjectBuffer is not None: laurent@530: self.ProjectBuffer.Buffering(cPickle.dumps(self.Project)) greg@349: else: greg@349: self.ProjectSaved = False lbessard@56: lbessard@56: def StartBuffering(self): greg@349: if self.ProjectBuffer is not None: greg@349: self.Buffering = True greg@349: else: greg@349: self.ProjectSaved = False lbessard@56: lbessard@56: def EndBuffering(self): greg@349: if self.ProjectBuffer is not None and self.Buffering: laurent@530: self.ProjectBuffer.Buffering(cPickle.dumps(self.Project)) lbessard@56: self.Buffering = False etisserant@0: greg@351: def MarkProjectAsSaved(self): laurent@545: self.EndBuffering() greg@349: if self.ProjectBuffer is not None: greg@349: self.ProjectBuffer.CurrentSaved() greg@349: else: greg@349: self.ProjectSaved = True greg@349: lbessard@249: # Return if project is saved etisserant@0: def ProjectIsSaved(self): lbessard@249: if self.ProjectBuffer is not None: laurent@530: return self.ProjectBuffer.IsCurrentSaved() and not self.Buffering lbessard@58: else: greg@349: return self.ProjectSaved etisserant@0: etisserant@0: def LoadPrevious(self): laurent@545: self.EndBuffering() greg@349: if self.ProjectBuffer is not None: laurent@531: self.Project = cPickle.loads(self.ProjectBuffer.Previous()) etisserant@0: etisserant@0: def LoadNext(self): greg@349: if self.ProjectBuffer is not None: laurent@530: self.Project = cPickle.loads(self.ProjectBuffer.Next()) etisserant@0: etisserant@0: def GetBufferState(self): greg@349: if self.ProjectBuffer is not None: laurent@545: first = self.ProjectBuffer.IsFirst() and not self.Buffering laurent@545: last = self.ProjectBuffer.IsLast() greg@349: return not first, not last greg@349: return False, False