Laurent@814: #!/usr/bin/env python Laurent@814: # -*- coding: utf-8 -*- Laurent@814: andrej@1571: # This file is part of Beremiz, a Integrated Development Environment for andrej@1571: # programming IEC 61131-3 automates supporting plcopen standard and CanFestival. Laurent@814: # andrej@1571: # Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD andrej@1680: # Copyright (C) 2017: Andrey Skvortsov Laurent@814: # andrej@1571: # See COPYING file for copyrights details. Laurent@814: # andrej@1571: # This program is free software; you can redistribute it and/or andrej@1571: # modify it under the terms of the GNU General Public License andrej@1571: # as published by the Free Software Foundation; either version 2 andrej@1571: # of the License, or (at your option) any later version. Laurent@814: # andrej@1571: # This program is distributed in the hope that it will be useful, andrej@1571: # but WITHOUT ANY WARRANTY; without even the implied warranty of andrej@1571: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the andrej@1571: # GNU General Public License for more details. Laurent@814: # andrej@1571: # You should have received a copy of the GNU General Public License andrej@1571: # along with this program; if not, write to the Free Software andrej@1571: # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Laurent@814: andrej@1850: Laurent@1299: from copy import deepcopy andrej@1732: import os andrej@1732: import re Laurent@814: import datetime Laurent@814: from time import localtime andrej@2456: from functools import reduce andrej@1832: andrej@1832: import util.paths as paths Laurent@1313: from plcopen import * edouard@1944: from plcopen.types_enums import * edouard@1942: from plcopen.InstancesPathCollector import InstancesPathCollector edouard@1943: from plcopen.POUVariablesCollector import POUVariablesCollector Edouard@1950: from plcopen.InstanceTagnameCollector import InstanceTagnameCollector Edouard@1957: from plcopen.BlockInstanceCollector import BlockInstanceCollector Edouard@1951: from plcopen.VariableInfoCollector import VariableInfoCollector Laurent@814: from graphics.GraphicCommons import * Laurent@814: from PLCGenerator import * Laurent@814: andrej@2439: duration_model = re.compile(r"(?:([0-9]{1,2})h)?(?:([0-9]{1,2})m(?!s))?(?:([0-9]{1,2})s)?(?:([0-9]{1,3}(?:\.[0-9]*)?)ms)?") andrej@2439: VARIABLE_NAME_SUFFIX_MODEL = re.compile(r'(\d+)$') Laurent@814: andrej@1680: ScriptDirectory = paths.AbsDir(__file__) Laurent@814: Laurent@814: # Length of the buffer Laurent@814: UNDO_BUFFER_LENGTH = 20 Laurent@814: andrej@1736: andrej@1831: class UndoBuffer(object): andrej@1736: """ andrej@1782: Undo Buffer for PLCOpenEditor andrej@1736: Class implementing a buffer of changes made on the current editing model andrej@1736: """ andrej@1736: andrej@1744: def __init__(self, currentstate, issaved=False): andrej@1736: """ andrej@1736: Constructor initialising buffer andrej@1736: """ Laurent@814: self.Buffer = [] Laurent@814: self.CurrentIndex = -1 Laurent@814: self.MinIndex = -1 Laurent@814: self.MaxIndex = -1 Laurent@814: # if current state is defined Laurent@814: if currentstate: Laurent@814: self.CurrentIndex = 0 Laurent@814: self.MinIndex = 0 Laurent@814: self.MaxIndex = 0 Laurent@814: # Initialising buffer with currentstate at the first place kinsamanka@3750: for i in range(UNDO_BUFFER_LENGTH): Laurent@814: if i == 0: Laurent@814: self.Buffer.append(currentstate) Laurent@814: else: Laurent@814: self.Buffer.append(None) Laurent@814: # Initialising index of state saved Laurent@814: if issaved: Laurent@814: self.LastSave = 0 Laurent@814: else: Laurent@814: self.LastSave = -1 Edouard@1411: Laurent@814: def Buffering(self, currentstate): andrej@1736: """ andrej@1736: Add a new state in buffer andrej@1736: """ Laurent@814: self.CurrentIndex = (self.CurrentIndex + 1) % UNDO_BUFFER_LENGTH Laurent@814: self.Buffer[self.CurrentIndex] = currentstate Laurent@814: # Actualising buffer limits Laurent@814: self.MaxIndex = self.CurrentIndex Laurent@814: if self.MinIndex == self.CurrentIndex: Laurent@814: # If the removed state was the state saved, there is no state saved in the buffer Laurent@814: if self.LastSave == self.MinIndex: Laurent@814: self.LastSave = -1 Laurent@814: self.MinIndex = (self.MinIndex + 1) % UNDO_BUFFER_LENGTH Laurent@814: self.MinIndex = max(self.MinIndex, 0) Edouard@1411: Laurent@814: def Current(self): andrej@1736: """ andrej@1736: Return current state of buffer andrej@1736: """ Laurent@814: return self.Buffer[self.CurrentIndex] Edouard@1411: Laurent@814: # Change current state to previous in buffer and return new current state Laurent@814: def Previous(self): Laurent@814: if self.CurrentIndex != self.MinIndex: Laurent@814: self.CurrentIndex = (self.CurrentIndex - 1) % UNDO_BUFFER_LENGTH Laurent@814: return self.Buffer[self.CurrentIndex] Laurent@814: return None Edouard@1411: Laurent@814: # Change current state to next in buffer and return new current state Laurent@814: def Next(self): Laurent@814: if self.CurrentIndex != self.MaxIndex: Laurent@814: self.CurrentIndex = (self.CurrentIndex + 1) % UNDO_BUFFER_LENGTH Laurent@814: return self.Buffer[self.CurrentIndex] Laurent@814: return None Edouard@1411: Laurent@814: # Return True if current state is the first in buffer Laurent@814: def IsFirst(self): Laurent@814: return self.CurrentIndex == self.MinIndex Edouard@1411: Laurent@814: # Return True if current state is the last in buffer Laurent@814: def IsLast(self): Laurent@814: return self.CurrentIndex == self.MaxIndex Laurent@814: Laurent@814: # Note that current state is saved Laurent@814: def CurrentSaved(self): Laurent@814: self.LastSave = self.CurrentIndex Edouard@1411: Laurent@814: # Return True if current state is saved Laurent@814: def IsCurrentSaved(self): Laurent@814: return self.LastSave == self.CurrentIndex Laurent@814: Laurent@814: andrej@1831: class PLCControler(object): andrej@1736: """ andrej@1782: Controler for PLCOpenEditor andrej@1736: Class which controls the operations made on the plcopen model and answers to view requests andrej@1736: """ Edouard@1411: Laurent@814: # Create a new PLCControler Laurent@814: def __init__(self): Laurent@814: self.LastNewIndex = 0 Laurent@814: self.Reset() Edouard@1935: self.InstancesPathCollector = InstancesPathCollector(self) edouard@1943: self.POUVariablesCollector = POUVariablesCollector(self) Edouard@1950: self.InstanceTagnameCollector = InstanceTagnameCollector(self) Edouard@1957: self.BlockInstanceCollector = BlockInstanceCollector(self) Edouard@1951: self.VariableInfoCollector = VariableInfoCollector(self) Edouard@1411: Laurent@814: # Reset PLCControler internal variables Laurent@814: def Reset(self): Laurent@814: self.Project = None Laurent@814: self.ProjectBufferEnabled = True Laurent@814: self.ProjectBuffer = None Laurent@814: self.ProjectSaved = True Laurent@814: self.Buffering = False Laurent@814: self.FilePath = "" Laurent@814: self.FileName = "" Laurent@814: self.ProgramChunks = [] Laurent@814: self.ProgramOffset = 0 Laurent@814: self.NextCompiledProject = None Laurent@814: self.CurrentCompiledProject = None Laurent@814: self.ConfNodeTypes = [] Edouard@1283: self.TotalTypesDict = StdBlckDct.copy() Edouard@1283: self.TotalTypes = StdBlckLst[:] Laurent@1284: self.ProgramFilePath = "" Edouard@1411: Laurent@814: def GetQualifierTypes(self): Laurent@1298: return QualifierList Laurent@814: andrej@1744: def GetProject(self, debug=False): Laurent@814: if debug and self.CurrentCompiledProject is not None: Laurent@814: return self.CurrentCompiledProject Laurent@814: else: Laurent@814: return self.Project Laurent@814: andrej@1782: # ------------------------------------------------------------------------------- andrej@1782: # Project management functions andrej@1782: # ------------------------------------------------------------------------------- Laurent@814: Laurent@814: # Return if a project is opened Laurent@814: def HasOpenedProject(self): Laurent@814: return self.Project is not None Laurent@814: Laurent@814: # Create a new project by replacing the current one Laurent@814: def CreateNewProject(self, properties): Laurent@814: # Create the project Laurent@1290: self.Project = PLCOpenParser.CreateRoot() Laurent@814: properties["creationDateTime"] = datetime.datetime(*localtime()[:6]) Laurent@814: self.Project.setfileHeader(properties) Laurent@814: self.Project.setcontentHeader(properties) Laurent@814: self.SetFilePath("") Edouard@1411: Laurent@814: # Initialize the project buffer Laurent@814: self.CreateProjectBuffer(False) Laurent@814: self.ProgramChunks = [] Laurent@814: self.ProgramOffset = 0 Laurent@1299: self.NextCompiledProject = self.Copy(self.Project) Laurent@814: self.CurrentCompiledProject = None Laurent@814: self.Buffering = False Edouard@1411: Laurent@814: # Return project data type names andrej@1744: def GetProjectDataTypeNames(self, debug=False): Laurent@814: project = self.GetProject(debug) Laurent@814: if project is not None: Laurent@814: return [datatype.getname() for datatype in project.getdataTypes()] Laurent@814: return [] Edouard@1411: Laurent@814: # Return project pou names andrej@1744: def GetProjectPouNames(self, debug=False): Laurent@814: project = self.GetProject(debug) Laurent@814: if project is not None: Laurent@814: return [pou.getname() for pou in project.getpous()] Laurent@814: return [] Edouard@1411: Laurent@814: # Return project pou names andrej@1744: def GetProjectConfigNames(self, debug=False): Laurent@814: project = self.GetProject(debug) Laurent@814: if project is not None: Laurent@814: return [config.getname() for config in project.getconfigurations()] Laurent@814: return [] Edouard@1411: Laurent@1171: # Return project pou variable names andrej@1744: def GetProjectPouVariableNames(self, pou_name=None, debug=False): Laurent@814: variables = [] Laurent@814: project = self.GetProject(debug) Laurent@814: if project is not None: Laurent@814: for pou in project.getpous(): Laurent@814: if pou_name is None or pou_name == pou.getname(): Laurent@1347: variables.extend([var.Name for var in self.GetPouInterfaceVars(pou, debug=debug)]) Laurent@814: for transition in pou.gettransitionList(): Laurent@814: variables.append(transition.getname()) Laurent@814: for action in pou.getactionList(): Laurent@814: variables.append(action.getname()) Laurent@814: return variables Edouard@1411: Laurent@814: # Return file path if project is an open file Laurent@814: def GetFilePath(self): Laurent@814: return self.FilePath Edouard@1411: Laurent@814: # Return file path if project is an open file Laurent@814: def GetProgramFilePath(self): Laurent@814: return self.ProgramFilePath Edouard@1411: Laurent@814: # Return file name and point out if file is up to date Laurent@814: def GetFilename(self): Laurent@814: if self.Project is not None: Laurent@814: if self.ProjectIsSaved(): Laurent@814: return self.FileName Laurent@814: else: andrej@1734: return "~%s~" % self.FileName Laurent@814: return "" Edouard@1411: Laurent@814: # Change file path and save file name or create a default one if file path not defined Laurent@814: def SetFilePath(self, filepath): Laurent@814: self.FilePath = filepath Laurent@814: if filepath == "": Laurent@814: self.LastNewIndex += 1 andrej@1734: self.FileName = _("Unnamed%d") % self.LastNewIndex Laurent@814: else: Laurent@814: self.FileName = os.path.splitext(os.path.basename(filepath))[0] Edouard@1411: Laurent@814: # Change project properties andrej@1744: def SetProjectProperties(self, name=None, properties=None, buffer=True): Laurent@814: if self.Project is not None: Laurent@814: if name is not None: Laurent@814: self.Project.setname(name) Laurent@814: if properties is not None: Laurent@814: self.Project.setfileHeader(properties) Laurent@814: self.Project.setcontentHeader(properties) Laurent@814: if buffer and (name is not None or properties is not None): Laurent@814: self.BufferProject() Edouard@1411: Laurent@814: # Return project name Laurent@814: def GetProjectName(self, debug=False): Laurent@814: project = self.GetProject(debug) Laurent@814: if project is not None: Laurent@814: return project.getname() Laurent@814: return None Edouard@1411: Laurent@814: # Return project properties andrej@1744: def GetProjectProperties(self, debug=False): Laurent@814: project = self.GetProject(debug) Laurent@814: if project is not None: Laurent@814: properties = project.getfileHeader() Laurent@814: properties.update(project.getcontentHeader()) Laurent@814: return properties Laurent@814: return None Edouard@1411: Laurent@814: # Return project informations andrej@1744: def GetProjectInfos(self, debug=False): Laurent@814: project = self.GetProject(debug) Laurent@814: if project is not None: Laurent@814: infos = {"name": project.getname(), "type": ITEM_PROJECT} andrej@1740: datatypes = {"name": DATA_TYPES, "type": ITEM_DATATYPES, "values": []} Laurent@814: for datatype in project.getdataTypes(): andrej@1768: datatypes["values"].append({ andrej@1768: "name": datatype.getname(), andrej@1768: "type": ITEM_DATATYPE, Edouard@1948: "tagname": ComputeDataTypeName(datatype.getname()), andrej@1768: "values": []}) andrej@1740: pou_types = { andrej@1740: "function": { andrej@1740: "name": FUNCTIONS, andrej@1740: "type": ITEM_FUNCTION, andrej@1740: "values": [] andrej@1740: }, andrej@1740: "functionBlock": { andrej@1740: "name": FUNCTION_BLOCKS, andrej@1740: "type": ITEM_FUNCTIONBLOCK, andrej@1740: "values": [] andrej@1740: }, andrej@1740: "program": { andrej@1740: "name": PROGRAMS, andrej@1740: "type": ITEM_PROGRAM, andrej@1740: "values": [] andrej@1740: } andrej@1740: } Laurent@814: for pou in project.getpous(): Laurent@814: pou_type = pou.getpouType() Laurent@814: pou_infos = {"name": pou.getname(), "type": ITEM_POU, Edouard@1948: "tagname": ComputePouName(pou.getname())} Laurent@814: pou_values = [] Laurent@814: if pou.getbodyType() == "SFC": Laurent@814: transitions = [] Laurent@814: for transition in pou.gettransitionList(): andrej@1768: transitions.append({ andrej@1768: "name": transition.getname(), andrej@1768: "type": ITEM_TRANSITION, Edouard@1948: "tagname": ComputePouTransitionName(pou.getname(), transition.getname()), Laurent@814: "values": []}) Laurent@814: pou_values.append({"name": TRANSITIONS, "type": ITEM_TRANSITIONS, "values": transitions}) Laurent@814: actions = [] Laurent@814: for action in pou.getactionList(): andrej@1768: actions.append({ andrej@1768: "name": action.getname(), andrej@1768: "type": ITEM_ACTION, Edouard@1948: "tagname": ComputePouActionName(pou.getname(), action.getname()), Laurent@814: "values": []}) Laurent@814: pou_values.append({"name": ACTIONS, "type": ITEM_ACTIONS, "values": actions}) Laurent@814: if pou_type in pou_types: Laurent@814: pou_infos["values"] = pou_values Laurent@814: pou_types[pou_type]["values"].append(pou_infos) Laurent@814: configurations = {"name": CONFIGURATIONS, "type": ITEM_CONFIGURATIONS, "values": []} Laurent@814: for config in project.getconfigurations(): Laurent@814: config_name = config.getname() andrej@1768: config_infos = { andrej@1768: "name": config_name, andrej@1768: "type": ITEM_CONFIGURATION, Edouard@1948: "tagname": ComputeConfigurationName(config.getname()), Laurent@814: "values": []} Laurent@814: resources = {"name": RESOURCES, "type": ITEM_RESOURCES, "values": []} Laurent@814: for resource in config.getresource(): Laurent@814: resource_name = resource.getname() andrej@1768: resource_infos = { andrej@1768: "name": resource_name, andrej@1768: "type": ITEM_RESOURCE, Edouard@1948: "tagname": ComputeConfigurationResourceName(config.getname(), resource.getname()), Laurent@814: "values": []} Laurent@814: resources["values"].append(resource_infos) Laurent@814: config_infos["values"] = [resources] Laurent@814: configurations["values"].append(config_infos) Edouard@1411: infos["values"] = [datatypes, pou_types["function"], pou_types["functionBlock"], Laurent@814: pou_types["program"], configurations] Laurent@814: return infos Laurent@814: return None Laurent@814: andrej@1744: def GetPouVariables(self, tagname, debug=False): Laurent@814: project = self.GetProject(debug) Laurent@814: if project is not None: Laurent@1348: obj = None Laurent@814: words = tagname.split("::") Laurent@814: if words[0] == "P": Laurent@1319: obj = self.GetPou(words[1], debug) Laurent@1348: elif words[0] != "D": Laurent@1319: obj = self.GetEditedElement(tagname, debug) Laurent@1319: if obj is not None: edouard@1943: return self.POUVariablesCollector.Collect(obj, debug) Edouard@1411: Laurent@1321: return None Laurent@1319: andrej@1744: def GetInstanceList(self, root, name, debug=False): edouard@1939: return self.InstancesPathCollector.Collect(root, name, debug) Edouard@1411: andrej@1744: def SearchPouInstances(self, tagname, debug=False): Laurent@1319: project = self.GetProject(debug) Laurent@1319: if project is not None: Laurent@1319: words = tagname.split("::") Laurent@1319: if words[0] == "P": Laurent@1350: return self.GetInstanceList(project, words[1]) Laurent@814: elif words[0] == 'C': Laurent@814: return [words[1]] Laurent@814: elif words[0] == 'R': Laurent@814: return ["%s.%s" % (words[1], words[2])] laurent@826: elif words[0] in ['T', 'A']: laurent@826: return ["%s.%s" % (instance, words[2]) laurent@826: for instance in self.SearchPouInstances( Edouard@1948: ComputePouName(words[1]), debug)] Laurent@814: return [] Edouard@1411: andrej@1744: def GetPouInstanceTagName(self, instance_path, debug=False): Laurent@1254: project = self.GetProject(debug) Edouard@1953: if project is not None: Edouard@1950: return self.InstanceTagnameCollector.Collect(project, Edouard@1950: debug, Edouard@1950: instance_path) Edouard@1411: andrej@1744: def GetInstanceInfos(self, instance_path, debug=False): Laurent@814: tagname = self.GetPouInstanceTagName(instance_path) Laurent@814: if tagname is not None: laurent@827: infos = self.GetPouVariables(tagname, debug) Laurent@1360: infos.type = tagname laurent@827: return infos Laurent@814: else: Laurent@814: pou_path, var_name = instance_path.rsplit(".", 1) Laurent@814: tagname = self.GetPouInstanceTagName(pou_path) Laurent@814: if tagname is not None: Laurent@814: pou_infos = self.GetPouVariables(tagname, debug) Laurent@1360: for var_infos in pou_infos.variables: Laurent@1360: if var_infos.name == var_name: Laurent@814: return var_infos Laurent@814: return None Edouard@1411: Laurent@814: # Return if data type given by name is used by another data type or pou andrej@1744: def DataTypeIsUsed(self, name, debug=False): Laurent@1319: project = self.GetProject(debug) Laurent@1319: if project is not None: Laurent@1354: return len(self.GetInstanceList(project, name, debug)) > 0 Laurent@814: return False Laurent@814: Laurent@814: # Return if pou given by name is used by another pou andrej@1744: def PouIsUsed(self, name, debug=False): Laurent@1319: project = self.GetProject(debug) Laurent@1319: if project is not None: Laurent@1354: return len(self.GetInstanceList(project, name, debug)) > 0 Laurent@814: return False Laurent@814: Laurent@814: # Return if pou given by name is directly or undirectly used by the reference pou andrej@1744: def PouIsUsedBy(self, name, reference, debug=False): Laurent@1319: pou_infos = self.GetPou(reference, debug) Laurent@1319: if pou_infos is not None: Laurent@1354: return len(self.GetInstanceList(pou_infos, name, debug)) > 0 Laurent@814: return False Laurent@814: Edouard@3704: def GenerateProgram(self, filepath=None, **kwargs): Laurent@814: errors = [] Laurent@814: warnings = [] Laurent@814: if self.Project is not None: Laurent@814: try: Edouard@3704: self.ProgramChunks = GenerateCurrentProgram(self, self.Project, errors, warnings,**kwargs) Laurent@1299: self.NextCompiledProject = self.Copy(self.Project) Laurent@901: program_text = "".join([item[0] for item in self.ProgramChunks]) Laurent@814: if filepath is not None: kinsamanka@3755: programfile = open(filepath, "w", encoding='utf-8') kinsamanka@3755: programfile.write(program_text) Laurent@814: programfile.close() Laurent@814: self.ProgramFilePath = filepath Laurent@814: return program_text, errors, warnings andrej@2418: except PLCGenException as ex: andrej@2520: errors.append(ex) Laurent@814: else: Laurent@814: errors.append("No project opened") Laurent@814: return "", errors, warnings Laurent@814: Laurent@814: def DebugAvailable(self): Laurent@814: return self.CurrentCompiledProject is not None Laurent@814: Laurent@814: def ProgramTransferred(self): Laurent@814: if self.NextCompiledProject is None: Laurent@814: self.CurrentCompiledProject = self.NextCompiledProject Laurent@814: else: Laurent@814: self.CurrentCompiledProject = self.Copy(self.Project) Laurent@814: Laurent@814: def GetChunkInfos(self, from_location, to_location): Laurent@814: row = self.ProgramOffset + 1 Laurent@814: col = 1 Laurent@814: infos = [] Laurent@814: for chunk, chunk_infos in self.ProgramChunks: Laurent@814: lines = chunk.split("\n") Laurent@814: if len(lines) > 1: Laurent@814: next_row = row + len(lines) - 1 Laurent@814: next_col = len(lines[-1]) + 1 Laurent@814: else: Laurent@814: next_row = row Laurent@814: next_col = col + len(chunk) Laurent@814: if (next_row > from_location[0] or next_row == from_location[0] and next_col >= from_location[1]) and len(chunk_infos) > 0: Laurent@814: infos.append((chunk_infos, (row, col))) Laurent@814: if next_row == to_location[0] and next_col > to_location[1] or next_row > to_location[0]: Laurent@814: return infos Laurent@814: row, col = next_row, next_col Laurent@814: return infos Edouard@1411: andrej@1782: # ------------------------------------------------------------------------------- andrej@1782: # Project Pous management functions andrej@1782: # ------------------------------------------------------------------------------- Edouard@1411: Laurent@814: # Add a Data Type to Project Laurent@814: def ProjectAddDataType(self, datatype_name=None): Laurent@814: if self.Project is not None: Laurent@814: if datatype_name is None: Laurent@814: datatype_name = self.GenerateNewName(None, None, "datatype%d") Laurent@814: # Add the datatype to project Laurent@814: self.Project.appenddataType(datatype_name) Laurent@814: self.BufferProject() Edouard@1948: return ComputeDataTypeName(datatype_name) Laurent@814: return None Edouard@1411: Laurent@814: # Remove a Data Type from project Laurent@814: def ProjectRemoveDataType(self, datatype_name): Laurent@814: if self.Project is not None: Laurent@814: self.Project.removedataType(datatype_name) Laurent@814: self.BufferProject() Edouard@1411: Laurent@814: # Add a Pou to Project Laurent@814: def ProjectAddPou(self, pou_name, pou_type, body_type): Laurent@814: if self.Project is not None: Laurent@814: # Add the pou to project Laurent@814: self.Project.appendpou(pou_name, pou_type, body_type) Laurent@814: if pou_type == "function": Laurent@814: self.SetPouInterfaceReturnType(pou_name, "BOOL") Laurent@814: self.BufferProject() Edouard@1948: return ComputePouName(pou_name) Laurent@814: return None Edouard@1411: Laurent@814: def ProjectChangePouType(self, name, pou_type): Laurent@814: if self.Project is not None: Laurent@814: pou = self.Project.getpou(name) Laurent@814: if pou is not None: Edouard@2614: new_pou = self.Copy(pou) Edouard@2614: idx = 0 Edouard@2614: new_name = name + "_" + pou_type Edouard@2614: while self.Project.getpou(new_name) is not None: Edouard@2614: idx += 1 Edouard@2614: new_name = "%s%d" % (name, idx) Edouard@2614: new_pou.setname(new_name) Edouard@2614: Edouard@2614: orig_type = pou.getpouType() Edouard@2614: if orig_type == 'function' and pou_type in ['functionBlock', 'program']: edouard@2625: # delete return type Edouard@2614: return_type_obj = new_pou.interface.getreturnType() Edouard@2614: new_pou.interface.remove(return_type_obj) edouard@2625: # To be ultimately correct we could re-create an edouard@2625: # output variable with same name+_out or so edouard@2625: # but in any case user will have to connect/assign Edouard@2614: # this output, so better leave it as-is Edouard@2614: Edouard@2614: new_pou.setpouType(pou_type) Edouard@2614: self.Project.insertpou(0, new_pou) Laurent@814: self.BufferProject() Edouard@1411: Laurent@814: def GetPouXml(self, pou_name): Laurent@814: if self.Project is not None: Laurent@814: pou = self.Project.getpou(pou_name) Laurent@814: if pou is not None: Laurent@1299: return pou.tostring() Laurent@814: return None Edouard@1411: Laurent@814: def PastePou(self, pou_type, pou_xml): Laurent@814: ''' Laurent@814: Adds the POU defined by 'pou_xml' to the current project with type 'pou_type' Laurent@814: ''' Laurent@814: try: Laurent@1330: new_pou, error = LoadPou(pou_xml) andrej@1780: except Exception: Laurent@1330: error = "" Laurent@1330: if error is not None: Laurent@814: return _("Couldn't paste non-POU object.") Edouard@1411: Laurent@1299: name = new_pou.getname() Edouard@1411: Laurent@1299: idx = 0 Laurent@1299: new_name = name Edouard@1411: while self.Project.getpou(new_name) is not None: Laurent@1299: # a POU with that name already exists. Laurent@1299: # make a new name and test if a POU with that name exists. Laurent@1299: # append an incrementing numeric suffix to the POU name. Laurent@1299: idx += 1 Laurent@1299: new_name = "%s%d" % (name, idx) Edouard@1411: Laurent@1299: # we've found a name that does not already exist, use it Laurent@1299: new_pou.setname(new_name) Edouard@1411: Laurent@1299: if pou_type is not None: Laurent@1299: orig_type = new_pou.getpouType() Laurent@1299: Laurent@1299: # prevent violations of POU content restrictions: Laurent@1299: # function blocks cannot be pasted as functions, Laurent@1299: # programs cannot be pasted as functions or function blocks Laurent@1299: if orig_type == 'functionBlock' and pou_type == 'function' or \ Laurent@1299: orig_type == 'program' and pou_type in ['function', 'functionBlock']: andrej@1744: msg = _('''{a1} "{a2}" can't be pasted as a {a3}.''').format(a1=orig_type, a2=name, a3=pou_type) andrej@1581: return msg Edouard@1411: Laurent@1299: new_pou.setpouType(pou_type) Laurent@1299: Edouard@1411: self.Project.insertpou(0, new_pou) Laurent@1299: self.BufferProject() Edouard@1411: Edouard@1948: return ComputePouName(new_name), Laurent@814: Laurent@814: # Remove a Pou from project Laurent@814: def ProjectRemovePou(self, pou_name): Laurent@814: if self.Project is not None: Laurent@814: self.Project.removepou(pou_name) Laurent@814: self.BufferProject() Edouard@1411: Laurent@814: # Return the name of the configuration if only one exist Laurent@814: def GetProjectMainConfigurationName(self): Laurent@814: if self.Project is not None: Laurent@814: # Found the configuration corresponding to old name and change its name to new name Laurent@814: configurations = self.Project.getconfigurations() Laurent@814: if len(configurations) == 1: Laurent@814: return configurations[0].getname() Laurent@814: return None Edouard@1411: Laurent@814: # Add a configuration to Project Laurent@814: def ProjectAddConfiguration(self, config_name=None): Laurent@814: if self.Project is not None: Laurent@814: if config_name is None: Laurent@814: config_name = self.GenerateNewName(None, None, "configuration%d") Laurent@814: self.Project.addconfiguration(config_name) Laurent@814: self.BufferProject() Edouard@1948: return ComputeConfigurationName(config_name) Laurent@814: return None Edouard@1411: Laurent@814: # Remove a configuration from project Laurent@814: def ProjectRemoveConfiguration(self, config_name): Laurent@814: if self.Project is not None: Laurent@814: self.Project.removeconfiguration(config_name) Laurent@814: self.BufferProject() Edouard@1411: Laurent@814: # Add a resource to a configuration of the Project Laurent@814: def ProjectAddConfigurationResource(self, config_name, resource_name=None): Laurent@814: if self.Project is not None: Laurent@814: if resource_name is None: Laurent@814: resource_name = self.GenerateNewName(None, None, "resource%d") Laurent@814: self.Project.addconfigurationResource(config_name, resource_name) Laurent@814: self.BufferProject() Edouard@1948: return ComputeConfigurationResourceName(config_name, resource_name) Laurent@814: return None Edouard@1411: Laurent@814: # Remove a resource from a configuration of the project Laurent@814: def ProjectRemoveConfigurationResource(self, config_name, resource_name): Laurent@814: if self.Project is not None: Laurent@814: self.Project.removeconfigurationResource(config_name, resource_name) Laurent@814: self.BufferProject() Edouard@1411: Laurent@814: # Add a Transition to a Project Pou Laurent@814: def ProjectAddPouTransition(self, pou_name, transition_name, transition_type): Laurent@814: if self.Project is not None: Laurent@814: pou = self.Project.getpou(pou_name) Laurent@814: if pou is not None: Laurent@814: pou.addtransition(transition_name, transition_type) Laurent@814: self.BufferProject() Edouard@1948: return ComputePouTransitionName(pou_name, transition_name) Laurent@814: return None Edouard@1411: Laurent@814: # Remove a Transition from a Project Pou Laurent@814: def ProjectRemovePouTransition(self, pou_name, transition_name): Laurent@814: # Search if the pou removed is currently opened Laurent@814: if self.Project is not None: Laurent@814: pou = self.Project.getpou(pou_name) Laurent@814: if pou is not None: Laurent@814: pou.removetransition(transition_name) Laurent@814: self.BufferProject() Edouard@1411: Laurent@814: # Add an Action to a Project Pou Laurent@814: def ProjectAddPouAction(self, pou_name, action_name, action_type): Laurent@814: if self.Project is not None: Laurent@814: pou = self.Project.getpou(pou_name) Laurent@814: if pou is not None: Laurent@814: pou.addaction(action_name, action_type) Laurent@814: self.BufferProject() Edouard@1948: return ComputePouActionName(pou_name, action_name) Laurent@814: return None Edouard@1411: Laurent@814: # Remove an Action from a Project Pou Laurent@814: def ProjectRemovePouAction(self, pou_name, action_name): Laurent@814: # Search if the pou removed is currently opened Laurent@814: if self.Project is not None: Laurent@814: pou = self.Project.getpou(pou_name) Laurent@814: if pou is not None: Laurent@814: pou.removeaction(action_name) Laurent@814: self.BufferProject() Edouard@1411: Laurent@814: # Change the name of a pou Laurent@814: def ChangeDataTypeName(self, old_name, new_name): Laurent@814: if self.Project is not None: Laurent@814: # Found the pou corresponding to old name and change its name to new name Laurent@814: datatype = self.Project.getdataType(old_name) Laurent@814: if datatype is not None: Laurent@814: datatype.setname(new_name) Laurent@814: self.Project.updateElementName(old_name, new_name) Laurent@814: self.BufferProject() Edouard@1411: Laurent@814: # Change the name of a pou Laurent@814: def ChangePouName(self, old_name, new_name): Laurent@814: if self.Project is not None: Laurent@814: # Found the pou corresponding to old name and change its name to new name Laurent@814: pou = self.Project.getpou(old_name) Laurent@814: if pou is not None: Laurent@814: pou.setname(new_name) Laurent@814: self.Project.updateElementName(old_name, new_name) Laurent@814: self.BufferProject() Edouard@1411: Laurent@814: # Change the name of a pou transition Laurent@814: def ChangePouTransitionName(self, pou_name, old_name, new_name): Laurent@814: if self.Project is not None: Laurent@814: # Found the pou transition corresponding to old name and change its name to new name Laurent@814: pou = self.Project.getpou(pou_name) Laurent@814: if pou is not None: Laurent@814: transition = pou.gettransition(old_name) Laurent@814: if transition is not None: Laurent@814: transition.setname(new_name) Laurent@814: pou.updateElementName(old_name, new_name) Laurent@814: self.BufferProject() Edouard@1411: Laurent@814: # Change the name of a pou action Laurent@814: def ChangePouActionName(self, pou_name, old_name, new_name): Laurent@814: if self.Project is not None: Laurent@814: # Found the pou action corresponding to old name and change its name to new name Laurent@814: pou = self.Project.getpou(pou_name) Laurent@814: if pou is not None: Laurent@814: action = pou.getaction(old_name) Laurent@814: if action is not None: Laurent@814: action.setname(new_name) Laurent@814: pou.updateElementName(old_name, new_name) Laurent@814: self.BufferProject() Edouard@1411: Laurent@814: # Change the name of a pou variable Laurent@814: def ChangePouVariableName(self, pou_name, old_name, new_name): Laurent@814: if self.Project is not None: Laurent@814: # Found the pou action corresponding to old name and change its name to new name Laurent@814: pou = self.Project.getpou(pou_name) Laurent@814: if pou is not None: andrej@1847: for _type, varlist in pou.getvars(): Laurent@814: for var in varlist.getvariable(): Laurent@814: if var.getname() == old_name: Laurent@814: var.setname(new_name) Laurent@814: self.BufferProject() Edouard@1411: Laurent@814: # Change the name of a configuration Laurent@814: def ChangeConfigurationName(self, old_name, new_name): Laurent@814: if self.Project is not None: Laurent@814: # Found the configuration corresponding to old name and change its name to new name Laurent@814: configuration = self.Project.getconfiguration(old_name) Laurent@814: if configuration is not None: Laurent@814: configuration.setname(new_name) Laurent@814: self.BufferProject() Edouard@1411: Laurent@814: # Change the name of a configuration resource Laurent@814: def ChangeConfigurationResourceName(self, config_name, old_name, new_name): Laurent@814: if self.Project is not None: Laurent@814: # Found the resource corresponding to old name and change its name to new name Laurent@814: resource = self.Project.getconfigurationResource(config_name, old_name) Laurent@814: if resource is not None: Laurent@814: resource.setname(new_name) Laurent@814: self.BufferProject() Edouard@1411: Laurent@814: # Return the description of the pou given by its name andrej@1744: def GetPouDescription(self, name, debug=False): Laurent@814: project = self.GetProject(debug) Laurent@814: if project is not None: Laurent@814: # Found the pou correponding to name and return its type Laurent@814: pou = project.getpou(name) Laurent@814: if pou is not None: Laurent@814: return pou.getdescription() Laurent@814: return "" Edouard@1411: Laurent@814: # Return the description of the pou given by its name andrej@1744: def SetPouDescription(self, name, description, debug=False): Laurent@814: project = self.GetProject(debug) Laurent@814: if project is not None: Laurent@814: # Found the pou correponding to name and return its type Laurent@814: pou = project.getpou(name) Laurent@814: if pou is not None: Laurent@814: pou.setdescription(description) Laurent@814: self.BufferProject() Edouard@1411: Laurent@814: # Return the type of the pou given by its name andrej@1744: def GetPouType(self, name, debug=False): Laurent@814: project = self.GetProject(debug) Laurent@814: if project is not None: Laurent@814: # Found the pou correponding to name and return its type Laurent@814: pou = project.getpou(name) Laurent@814: if pou is not None: Laurent@814: return pou.getpouType() Laurent@814: return None Edouard@1411: Laurent@814: # Return pous with SFC language andrej@1744: def GetSFCPous(self, debug=False): Laurent@814: list = [] Laurent@814: project = self.GetProject(debug) Laurent@814: if project is not None: Laurent@814: for pou in project.getpous(): Laurent@814: if pou.getBodyType() == "SFC": Laurent@814: list.append(pou.getname()) Laurent@814: return list Edouard@1411: Laurent@814: # Return the body language of the pou given by its name andrej@1744: def GetPouBodyType(self, name, debug=False): Laurent@814: project = self.GetProject(debug) Laurent@814: if project is not None: Laurent@814: # Found the pou correponding to name and return its body language Laurent@814: pou = project.getpou(name) Laurent@814: if pou is not None: Laurent@814: return pou.getbodyType() Laurent@814: return None Edouard@1411: Laurent@814: # Return the actions of a pou andrej@1744: def GetPouTransitions(self, pou_name, debug=False): Laurent@814: transitions = [] Laurent@814: project = self.GetProject(debug) Laurent@814: if project is not None: Laurent@814: # Found the pou correponding to name and return its transitions if SFC Laurent@814: pou = project.getpou(pou_name) Laurent@814: if pou is not None and pou.getbodyType() == "SFC": Laurent@814: for transition in pou.gettransitionList(): Laurent@814: transitions.append(transition.getname()) Laurent@814: return transitions Edouard@1411: Laurent@814: # Return the body language of the transition given by its name andrej@1744: def GetTransitionBodyType(self, pou_name, pou_transition, debug=False): Laurent@814: project = self.GetProject(debug) Laurent@814: if project is not None: Laurent@814: # Found the pou correponding to name Laurent@814: pou = project.getpou(pou_name) Laurent@814: if pou is not None: Laurent@814: # Found the pou transition correponding to name and return its body language Laurent@814: transition = pou.gettransition(pou_transition) Laurent@814: if transition is not None: Laurent@814: return transition.getbodyType() Laurent@814: return None Edouard@1411: Laurent@814: # Return the actions of a pou andrej@1744: def GetPouActions(self, pou_name, debug=False): Laurent@814: actions = [] Laurent@814: project = self.GetProject(debug) Laurent@814: if project is not None: Laurent@814: # Found the pou correponding to name and return its actions if SFC Laurent@814: pou = project.getpou(pou_name) Laurent@814: if pou.getbodyType() == "SFC": Laurent@814: for action in pou.getactionList(): Laurent@814: actions.append(action.getname()) Laurent@814: return actions Edouard@1411: Laurent@814: # Return the body language of the pou given by its name andrej@1744: def GetActionBodyType(self, pou_name, pou_action, debug=False): Laurent@814: project = self.GetProject(debug) Laurent@814: if project is not None: Laurent@814: # Found the pou correponding to name and return its body language Laurent@814: pou = project.getpou(pou_name) Laurent@814: if pou is not None: Laurent@814: action = pou.getaction(pou_action) Laurent@814: if action is not None: Laurent@814: return action.getbodyType() Laurent@814: return None Edouard@1411: Laurent@814: # Extract varlists from a list of vars Laurent@814: def ExtractVarLists(self, vars): Laurent@814: varlist_list = [] Laurent@814: current_varlist = None Laurent@814: current_type = None Laurent@814: for var in vars: Edouard@1411: next_type = (var.Class, Edouard@1411: var.Option, Edouard@1411: var.Location in ["", None] or Edouard@1411: # When declaring globals, located Edouard@1411: # and not located variables are Laurent@814: # in the same declaration block Laurent@1347: var.Class == "Global") Laurent@814: if current_type != next_type: Laurent@814: current_type = next_type Laurent@1347: infos = VAR_CLASS_INFOS.get(var.Class, None) Laurent@814: if infos is not None: Laurent@1291: current_varlist = PLCOpenParser.CreateElement(infos[0], "interface") Laurent@814: else: Laurent@1291: current_varlist = PLCOpenParser.CreateElement("varList") Laurent@1347: varlist_list.append((var.Class, current_varlist)) Laurent@1347: if var.Option == "Constant": Laurent@814: current_varlist.setconstant(True) Laurent@1347: elif var.Option == "Retain": Laurent@814: current_varlist.setretain(True) Laurent@1347: elif var.Option == "Non-Retain": Laurent@814: current_varlist.setnonretain(True) Laurent@814: # Create variable and change its properties Laurent@1291: tempvar = PLCOpenParser.CreateElement("variable", "varListPlain") Laurent@1347: tempvar.setname(var.Name) Edouard@1411: Laurent@1291: var_type = PLCOpenParser.CreateElement("type", "variable") andrej@2450: if isinstance(var.Type, tuple): Laurent@1347: if var.Type[0] == "array": andrej@1847: _array_type, base_type_name, dimensions = var.Type Laurent@1291: array = PLCOpenParser.CreateElement("array", "dataType") Laurent@1306: baseType = PLCOpenParser.CreateElement("baseType", "array") Laurent@1306: array.setbaseType(baseType) Laurent@814: for i, dimension in enumerate(dimensions): Laurent@1306: dimension_range = PLCOpenParser.CreateElement("dimension", "array") Laurent@814: if i == 0: Laurent@814: array.setdimension([dimension_range]) Laurent@814: else: Laurent@814: array.appenddimension(dimension_range) Laurent@1298: dimension_range.setlower(dimension[0]) Laurent@1298: dimension_range.setupper(dimension[1]) Laurent@814: if base_type_name in self.GetBaseTypes(): Laurent@1306: baseType.setcontent(PLCOpenParser.CreateElement( Laurent@1291: base_type_name.lower() Laurent@1291: if base_type_name in ["STRING", "WSTRING"] Laurent@1291: else base_type_name, "dataType")) Laurent@814: else: Laurent@1291: derived_datatype = PLCOpenParser.CreateElement("derived", "dataType") Laurent@814: derived_datatype.setname(base_type_name) Laurent@1306: baseType.setcontent(derived_datatype) Laurent@1291: var_type.setcontent(array) Laurent@1347: elif var.Type in self.GetBaseTypes(): Laurent@1291: var_type.setcontent(PLCOpenParser.CreateElement( Laurent@1347: var.Type.lower() Laurent@1347: if var.Type in ["STRING", "WSTRING"] Laurent@1347: else var.Type, "dataType")) Laurent@814: else: Laurent@1291: derived_type = PLCOpenParser.CreateElement("derived", "dataType") Laurent@1347: derived_type.setname(var.Type) Laurent@1291: var_type.setcontent(derived_type) Laurent@814: tempvar.settype(var_type) Laurent@814: Laurent@1347: if var.InitialValue != "": Laurent@1291: value = PLCOpenParser.CreateElement("initialValue", "variable") Laurent@1347: value.setvalue(var.InitialValue) Laurent@814: tempvar.setinitialValue(value) Laurent@1347: if var.Location != "": Laurent@1347: tempvar.setaddress(var.Location) Laurent@814: else: Laurent@814: tempvar.setaddress(None) Laurent@1347: if var.Documentation != "": Laurent@1294: ft = PLCOpenParser.CreateElement("documentation", "variable") Laurent@1347: ft.setanyText(var.Documentation) Laurent@814: tempvar.setdocumentation(ft) Laurent@814: Laurent@814: # Add variable to varList Laurent@814: current_varlist.appendvariable(tempvar) Laurent@814: return varlist_list Edouard@1411: Laurent@1347: def GetVariableDictionary(self, object_with_vars, tree=False, debug=False): Laurent@1308: variables = [] Edouard@1953: self.VariableInfoCollector.Collect(object_with_vars, Edouard@1953: debug, variables, tree) Laurent@1308: return variables Edouard@1411: Laurent@1171: # Add a global var to configuration to configuration Edouard@1411: def AddConfigurationGlobalVar(self, config_name, var_type, var_name, andrej@1767: location="", description=""): Laurent@1171: if self.Project is not None: Laurent@1171: # Found the configuration corresponding to name Laurent@1171: configuration = self.Project.getconfiguration(config_name) Laurent@1171: if configuration is not None: Laurent@1171: # Set configuration global vars Laurent@1313: configuration.addglobalVar( Edouard@1411: self.GetVarTypeObject(var_type), Laurent@1313: var_name, location, description) Laurent@814: Laurent@814: # Replace the configuration globalvars by those given Laurent@814: def SetConfigurationGlobalVars(self, name, vars): Laurent@814: if self.Project is not None: Laurent@814: # Found the configuration corresponding to name Laurent@814: configuration = self.Project.getconfiguration(name) Laurent@814: if configuration is not None: Laurent@814: # Set configuration global vars Laurent@1291: configuration.setglobalVars([ andrej@1847: varlist for _vartype, varlist Laurent@1291: in self.ExtractVarLists(vars)]) Edouard@1411: Laurent@814: # Return the configuration globalvars andrej@1744: def GetConfigurationGlobalVars(self, name, debug=False): Laurent@814: project = self.GetProject(debug) Laurent@814: if project is not None: Laurent@814: # Found the configuration corresponding to name Laurent@814: configuration = project.getconfiguration(name) Laurent@814: if configuration is not None: Laurent@1308: # Extract variables defined in configuration Laurent@1319: return self.GetVariableDictionary(configuration, debug) Edouard@1411: Laurent@1308: return [] Laurent@814: Laurent@1171: # Return configuration variable names andrej@1744: def GetConfigurationVariableNames(self, config_name=None, debug=False): Laurent@1171: variables = [] Laurent@1171: project = self.GetProject(debug) Laurent@1171: if project is not None: Laurent@1171: for configuration in self.Project.getconfigurations(): Laurent@1171: if config_name is None or config_name == configuration.getname(): Laurent@1171: variables.extend( Laurent@1171: [var.getname() for var in reduce( andrej@1768: lambda x, y: x + y, [ andrej@1768: varlist.getvariable() Laurent@1171: for varlist in configuration.globalVars], Laurent@1171: [])]) Laurent@1171: return variables Laurent@1171: Laurent@814: # Replace the resource globalvars by those given Laurent@814: def SetConfigurationResourceGlobalVars(self, config_name, name, vars): Laurent@814: if self.Project is not None: Laurent@814: # Found the resource corresponding to name Laurent@814: resource = self.Project.getconfigurationResource(config_name, name) Laurent@814: # Set resource global vars Laurent@814: if resource is not None: Laurent@1291: resource.setglobalVars([ andrej@1847: varlist for _vartype, varlist Laurent@1291: in self.ExtractVarLists(vars)]) Edouard@1411: Laurent@814: # Return the resource globalvars andrej@1744: def GetConfigurationResourceGlobalVars(self, config_name, name, debug=False): Laurent@814: project = self.GetProject(debug) Laurent@814: if project is not None: Laurent@814: # Found the resource corresponding to name Laurent@814: resource = project.getconfigurationResource(config_name, name) Laurent@1294: if resource is not None: Laurent@1308: # Extract variables defined in configuration Laurent@1319: return self.GetVariableDictionary(resource, debug) Edouard@1411: Laurent@1308: return [] Edouard@1411: Laurent@1171: # Return resource variable names andrej@1768: def GetConfigurationResourceVariableNames( andrej@1768: self, config_name=None, resource_name=None, debug=False): Laurent@1171: variables = [] Laurent@1171: project = self.GetProject(debug) Laurent@1171: if project is not None: Laurent@1171: for configuration in self.Project.getconfigurations(): Laurent@1171: if config_name is None or config_name == configuration.getname(): Laurent@1171: for resource in configuration.getresource(): Laurent@1171: if resource_name is None or resource.getname() == resource_name: Laurent@1171: variables.extend( Laurent@1171: [var.getname() for var in reduce( andrej@1768: lambda x, y: x + y, [ andrej@1768: varlist.getvariable() Laurent@1171: for varlist in resource.globalVars], Laurent@1171: [])]) Laurent@1171: return variables Laurent@814: Laurent@814: # Return the interface for the given pou andrej@1744: def GetPouInterfaceVars(self, pou, tree=False, debug=False): Laurent@1308: interface = pou.interface Laurent@814: # Verify that the pou has an interface Laurent@1308: if interface is not None: Laurent@1308: # Extract variables defined in interface Laurent@1347: return self.GetVariableDictionary(interface, tree, debug) Laurent@1308: return [] Laurent@814: Laurent@814: # Replace the Pou interface by the one given Laurent@814: def SetPouInterfaceVars(self, name, vars): Laurent@814: if self.Project is not None: Laurent@814: # Found the pou corresponding to name and add interface if there isn't one yet Laurent@814: pou = self.Project.getpou(name) Laurent@814: if pou is not None: Laurent@814: if pou.interface is None: Laurent@1291: pou.interface = PLCOpenParser.CreateElement("interface", "pou") Laurent@814: # Set Pou interface andrej@1847: pou.setvars([varlist for _varlist_type, varlist in self.ExtractVarLists(vars)]) Edouard@1411: Laurent@814: # Replace the return type of the pou given by its name (only for functions) Laurent@1291: def SetPouInterfaceReturnType(self, name, return_type): Laurent@814: if self.Project is not None: Laurent@814: pou = self.Project.getpou(name) Laurent@814: if pou is not None: Laurent@814: if pou.interface is None: Laurent@1291: pou.interface = PLCOpenParser.CreateElement("interface", "pou") Laurent@814: # If there isn't any return type yet, add it Laurent@1291: return_type_obj = pou.interface.getreturnType() Laurent@1294: if return_type_obj is None: Laurent@1291: return_type_obj = PLCOpenParser.CreateElement("returnType", "interface") Laurent@1291: pou.interface.setreturnType(return_type_obj) Laurent@814: # Change return type Laurent@1291: if return_type in self.GetBaseTypes(): Laurent@1291: return_type_obj.setcontent(PLCOpenParser.CreateElement( Laurent@1291: return_type.lower() Laurent@1291: if return_type in ["STRING", "WSTRING"] Laurent@1291: else return_type, "dataType")) Laurent@814: else: Laurent@1291: derived_type = PLCOpenParser.CreateElement("derived", "dataType") Laurent@1291: derived_type.setname(return_type) Edouard@1418: return_type_obj.setcontent(derived_type) Edouard@1411: Laurent@814: def UpdateProjectUsedPous(self, old_name, new_name): Laurent@1294: if self.Project is not None: Laurent@814: self.Project.updateElementName(old_name, new_name) Edouard@1411: Laurent@814: def UpdateEditedElementUsedVariable(self, tagname, old_name, new_name): Laurent@814: pou = self.GetEditedElement(tagname) Laurent@1294: if pou is not None: Laurent@814: pou.updateElementName(old_name, new_name) Edouard@1411: Laurent@814: # Return the return type of the given pou Laurent@1347: def GetPouInterfaceReturnType(self, pou, tree=False, debug=False): Laurent@814: # Verify that the pou has an interface Laurent@814: if pou.interface is not None: Laurent@814: # Return the return type if there is one Laurent@814: return_type = pou.interface.getreturnType() Laurent@1291: if return_type is not None: Edouard@1953: factory = self.VariableInfoCollector.Collect(return_type, Edouard@1951: debug, [], tree) Laurent@1347: if tree: Laurent@1347: return [factory.GetType(), factory.GetTree()] Laurent@1347: return factory.GetType() Edouard@1411: Laurent@1347: if tree: Laurent@1347: return [None, ([], [])] Laurent@1347: return None Laurent@814: Laurent@814: # Function that add a new confnode to the confnode list Laurent@814: def AddConfNodeTypesList(self, typeslist): Laurent@814: self.ConfNodeTypes.extend(typeslist) Edouard@1283: addedcat = [{"name": _("%s POUs") % confnodetypes["name"], Laurent@1302: "list": [pou.getblockInfos() Laurent@1302: for pou in confnodetypes["types"].getpous()]} andrej@1767: for confnodetypes in typeslist] Edouard@1283: self.TotalTypes.extend(addedcat) Edouard@1283: for cat in addedcat: Edouard@1283: for desc in cat["list"]: andrej@1740: BlkLst = self.TotalTypesDict.setdefault(desc["name"], []) Edouard@1283: BlkLst.append((section["name"], desc)) Edouard@1411: Laurent@814: # Function that clear the confnode list Laurent@814: def ClearConfNodeTypes(self): Edouard@1283: self.ConfNodeTypes = [] Edouard@1283: self.TotalTypesDict = StdBlckDct.copy() Edouard@1283: self.TotalTypes = StdBlckLst[:] Laurent@814: andrej@1744: def GetConfNodeDataTypes(self, exclude=None, only_locatables=False): Laurent@814: return [{"name": _("%s Data Types") % confnodetypes["name"], Laurent@1302: "list": [ andrej@1878: datatype.getname() andrej@1878: for datatype in confnodetypes["types"].getdataTypes() andrej@1878: if not only_locatables or self.IsLocatableDataType(datatype)]} Laurent@814: for confnodetypes in self.ConfNodeTypes] Edouard@1411: Laurent@814: def GetVariableLocationTree(self): Laurent@814: return [] Laurent@814: Laurent@883: def GetConfNodeGlobalInstances(self): Laurent@883: return [] Laurent@883: Laurent@883: def GetConfigurationExtraVariables(self): Laurent@883: global_vars = [] Edouard@3704: for global_instance in self.GetConfNodeGlobalInstances(): Edouard@3704: if type(global_instance)==tuple: Edouard@3704: # usual global without modifier from a CTN or a library Edouard@3704: var_name, var_type, var_initial = global_instance Edouard@3704: tempvar = PLCOpenParser.CreateElement("variable", "globalVars") Edouard@3704: tempvar.setname(var_name) Edouard@3704: Edouard@3704: tempvartype = PLCOpenParser.CreateElement("type", "variable") Edouard@3704: if var_type in self.GetBaseTypes(): Edouard@3704: tempvartype.setcontent(PLCOpenParser.CreateElement( Edouard@3704: var_type.lower() Edouard@3704: if var_type in ["STRING", "WSTRING"] Edouard@3704: else var_type, "dataType")) Edouard@3704: else: Edouard@3704: tempderivedtype = PLCOpenParser.CreateElement("derived", "dataType") Edouard@3704: tempderivedtype.setname(var_type) Edouard@3704: tempvartype.setcontent(tempderivedtype) Edouard@3704: tempvar.settype(tempvartype) Edouard@3704: Edouard@3704: if var_initial != "": Edouard@3704: value = PLCOpenParser.CreateElement("initialValue", "variable") Edouard@3704: value.setvalue(var_initial) Edouard@3704: tempvar.setinitialValue(value) Edouard@3704: Edouard@3704: global_vars.append(tempvar) Laurent@883: else: Edouard@3704: # case of varlists from a TC6 library Edouard@3704: global_vars.append(global_instance) Edouard@3704: Laurent@883: return global_vars Laurent@883: Laurent@814: # Function that returns the block definition associated to the block type given andrej@1744: def GetBlockType(self, typename, inputs=None, debug=False): andrej@1879: result_blocktype = {} andrej@1847: for _sectioname, blocktype in self.TotalTypesDict.get(typename, []): Edouard@1283: if inputs is not None and inputs != "undefined": andrej@1847: block_inputs = tuple([var_type for _name, var_type, _modifier in blocktype["inputs"]]) kinsamanka@3750: if reduce(lambda x, y: x and y, [x[0] == "ANY" or self.IsOfType(*x) for x in zip(inputs, block_inputs)], True): Edouard@1283: return blocktype Edouard@1283: else: andrej@1879: if result_blocktype: Edouard@1283: if inputs == "undefined": Edouard@1283: return None Laurent@814: else: Edouard@1283: result_blocktype["inputs"] = [(i[0], "ANY", i[2]) for i in result_blocktype["inputs"]] Edouard@1283: result_blocktype["outputs"] = [(o[0], "ANY", o[2]) for o in result_blocktype["outputs"]] Edouard@1283: return result_blocktype Edouard@1283: result_blocktype = blocktype.copy() andrej@1879: if result_blocktype: Laurent@814: return result_blocktype Laurent@814: project = self.GetProject(debug) Laurent@814: if project is not None: Laurent@1302: blocktype = project.getpou(typename) Laurent@1302: if blocktype is not None: Laurent@1302: blocktype_infos = blocktype.getblockInfos() Laurent@1302: if inputs in [None, "undefined"]: Laurent@1302: return blocktype_infos Edouard@1411: Edouard@1411: if inputs == tuple([var_type andrej@1847: for _name, var_type, _modifier in blocktype_infos["inputs"]]): Laurent@1302: return blocktype_infos Edouard@1411: Laurent@814: return None Laurent@814: Laurent@814: # Return Block types checking for recursion andrej@1744: def GetBlockTypes(self, tagname="", debug=False): Laurent@814: words = tagname.split("::") Edouard@1283: name = None Edouard@1283: project = self.GetProject(debug) Edouard@1283: if project is not None: Laurent@1284: pou_type = None andrej@1740: if words[0] in ["P", "T", "A"]: Laurent@814: name = words[1] Laurent@1284: pou_type = self.GetPouType(name, debug) Edouard@1411: filter = (["function"] Edouard@1411: if pou_type == "function" or words[0] == "T" Laurent@1302: else ["functionBlock", "function"]) Laurent@1302: blocktypes = [ Laurent@1302: {"name": category["name"], Laurent@1302: "list": [block for block in category["list"] Laurent@1302: if block["type"] in filter]} Laurent@1302: for category in self.TotalTypes] andrej@1768: blocktypes.append({ andrej@1768: "name": USER_DEFINED_POUS, Laurent@1302: "list": [pou.getblockInfos() Laurent@1319: for pou in project.getpous(name, filter) Edouard@1411: if (name is None or andrej@1768: len(self.GetInstanceList(pou, name, debug)) == 0)] andrej@1768: }) Laurent@1284: return blocktypes Edouard@1283: return self.TotalTypes Laurent@814: Laurent@814: # Return Function Block types checking for recursion andrej@1744: def GetFunctionBlockTypes(self, tagname="", debug=False): Laurent@1319: project = self.GetProject(debug) Laurent@1319: words = tagname.split("::") Laurent@1319: name = None andrej@1740: if project is not None and words[0] in ["P", "T", "A"]: Laurent@1319: name = words[1] Laurent@814: blocktypes = [] kinsamanka@3750: for blocks in self.TotalTypesDict.values(): andrej@1847: for _sectioname, block in blocks: Laurent@814: if block["type"] == "functionBlock": Laurent@814: blocktypes.append(block["name"]) Laurent@1319: if project is not None: andrej@1768: blocktypes.extend([ andrej@1768: pou.getname() Laurent@1319: for pou in project.getpous(name, ["functionBlock"]) Edouard@1411: if (name is None or Laurent@1372: len(self.GetInstanceList(pou, name, debug)) == 0)]) Laurent@814: return blocktypes Laurent@814: Laurent@814: # Return Block types checking for recursion andrej@1744: def GetBlockResource(self, debug=False): Laurent@814: blocktypes = [] Edouard@1283: for category in StdBlckLst[:-1]: Laurent@814: for blocktype in category["list"]: Laurent@814: if blocktype["type"] == "program": Laurent@814: blocktypes.append(blocktype["name"]) Laurent@814: project = self.GetProject(debug) Laurent@814: if project is not None: Laurent@1302: blocktypes.extend( Laurent@1328: [pou.getname() Laurent@1302: for pou in project.getpous(filter=["program"])]) Laurent@814: return blocktypes Laurent@814: Laurent@814: # Return Data Types checking for recursion andrej@1744: def GetDataTypes(self, tagname="", basetypes=True, confnodetypes=True, only_locatables=False, debug=False): Laurent@814: if basetypes: Laurent@814: datatypes = self.GetBaseTypes() Laurent@814: else: Laurent@814: datatypes = [] Laurent@814: project = self.GetProject(debug) Edouard@1283: name = None Edouard@1283: if project is not None: Laurent@814: words = tagname.split("::") Laurent@814: if words[0] in ["D"]: Laurent@814: name = words[1] Laurent@1302: datatypes.extend([ Edouard@1411: datatype.getname() Laurent@1302: for datatype in project.getdataTypes(name) andrej@1785: if ((not only_locatables or self.IsLocatableDataType(datatype, debug)) and andrej@1785: (name is None or len(self.GetInstanceList(datatype, name, debug)) == 0))]) Laurent@863: if confnodetypes: Laurent@863: for category in self.GetConfNodeDataTypes(name, only_locatables): Laurent@863: datatypes.extend(category["list"]) Laurent@814: return datatypes Laurent@814: Laurent@1301: # Return Data Type Object andrej@1744: def GetPou(self, typename, debug=False): Laurent@1308: project = self.GetProject(debug) Laurent@1308: if project is not None: Laurent@1308: result = project.getpou(typename) Laurent@1308: if result is not None: Laurent@1308: return result kinsamanka@3750: for standardlibrary in list(StdBlckLibs.values()): Laurent@1313: result = standardlibrary.getpou(typename) Laurent@1313: if result is not None: Laurent@1313: return result Laurent@1308: for confnodetype in self.ConfNodeTypes: Laurent@1308: result = confnodetype["types"].getpou(typename) Laurent@1308: if result is not None: Laurent@1308: return result Laurent@1308: return None Laurent@1308: Laurent@1308: # Return Data Type Object andrej@1744: def GetDataType(self, typename, debug=False): Laurent@1301: project = self.GetProject(debug) Laurent@1301: if project is not None: Laurent@1301: result = project.getdataType(typename) Laurent@814: if result is not None: Laurent@814: return result Laurent@814: for confnodetype in self.ConfNodeTypes: Laurent@1301: result = confnodetype["types"].getdataType(typename) Laurent@814: if result is not None: Laurent@814: return result Laurent@814: return None Laurent@814: Laurent@1301: # Return Data Type Object Base Type Laurent@1301: def GetDataTypeBaseType(self, datatype): Laurent@1301: basetype_content = datatype.baseType.getcontent() Laurent@1301: basetype_content_type = basetype_content.getLocalTag() Laurent@1301: if basetype_content_type in ["array", "subrangeSigned", "subrangeUnsigned"]: Laurent@1301: basetype = basetype_content.baseType.getcontent() Laurent@1301: basetype_type = basetype.getLocalTag() Laurent@1301: return (basetype.getname() if basetype_type == "derived" Laurent@1301: else basetype_type.upper()) Laurent@1338: return (basetype_content.getname() if basetype_content_type == "derived" Laurent@1338: else basetype_content_type.upper()) Laurent@1301: Laurent@1301: # Return Base Type of given possible derived type andrej@1744: def GetBaseType(self, typename, debug=False): andrej@1763: if typename in TypeHierarchy: Laurent@1301: return typename Edouard@1411: Laurent@1301: datatype = self.GetDataType(typename, debug) Laurent@1301: if datatype is not None: Laurent@1301: basetype = self.GetDataTypeBaseType(datatype) Laurent@1301: if basetype is not None: Laurent@1301: return self.GetBaseType(basetype, debug) Laurent@1301: return typename Edouard@1411: Laurent@1301: return None Laurent@1301: Laurent@814: def GetBaseTypes(self): Laurent@814: ''' Laurent@814: return the list of datatypes defined in IEC 61131-3. Laurent@814: TypeHierarchy_list has a rough order to it (e.g. SINT, INT, DINT, ...), Laurent@814: which makes it easy for a user to find a type in a menu. Laurent@814: ''' andrej@1847: return [x for x, _y in TypeHierarchy_list if not x.startswith("ANY")] Laurent@814: andrej@1744: def IsOfType(self, typename, reference, debug=False): edouard@4059: if typename is None or reference is None: edouard@4059: return True edouard@4059: edouard@4059: typename = typename.upper() edouard@4059: reference = reference.upper() edouard@4059: if typename == reference: Laurent@814: return True Edouard@1411: Laurent@1301: basetype = TypeHierarchy.get(typename) Laurent@1301: if basetype is not None: Laurent@1301: return self.IsOfType(basetype, reference) Edouard@1411: Laurent@1301: datatype = self.GetDataType(typename, debug) Laurent@1301: if datatype is not None: Laurent@1301: basetype = self.GetDataTypeBaseType(datatype) Laurent@1301: if basetype is not None: Laurent@1301: return self.IsOfType(basetype, reference, debug) Edouard@1411: Laurent@814: return False Edouard@1411: Laurent@1301: def IsEndType(self, typename): edouard@3968: # Check if the type is a base type edouard@3968: if type(typename) == str: Laurent@1301: return not typename.startswith("ANY") Laurent@814: return True Laurent@814: andrej@1744: def IsLocatableDataType(self, datatype, debug=False): Laurent@1302: basetype_content = datatype.baseType.getcontent() Laurent@1302: basetype_content_type = basetype_content.getLocalTag() edouard@4008: if basetype_content_type in ["enum"]: Laurent@1302: return False Laurent@1302: elif basetype_content_type == "derived": Laurent@1302: return self.IsLocatableType(basetype_content.getname()) Laurent@1321: elif basetype_content_type == "array": Laurent@1302: array_base_type = basetype_content.baseType.getcontent() Laurent@1302: if array_base_type.getLocalTag() == "derived": Laurent@1302: return self.IsLocatableType(array_base_type.getname(), debug) Laurent@1302: return True Edouard@1411: andrej@1744: def IsLocatableType(self, typename, debug=False): andrej@2450: if isinstance(typename, tuple) or self.GetBlockType(typename) is not None: Laurent@884: return False Edouard@1411: andrej@1686: # the size of these types is implementation dependend andrej@1686: if typename in ["TIME", "DATE", "DT", "TOD"]: andrej@1686: return False andrej@1735: Laurent@1301: datatype = self.GetDataType(typename, debug) Laurent@1301: if datatype is not None: Laurent@1302: return self.IsLocatableDataType(datatype) Laurent@814: return True Edouard@1411: andrej@1744: def IsEnumeratedType(self, typename, debug=False): andrej@2450: if isinstance(typename, tuple): Laurent@1306: typename = typename[1] Laurent@1301: datatype = self.GetDataType(typename, debug) Laurent@1301: if datatype is not None: Laurent@1301: basetype_content = datatype.baseType.getcontent() Laurent@1301: basetype_content_type = basetype_content.getLocalTag() Laurent@1301: if basetype_content_type == "derived": Laurent@1301: return self.IsEnumeratedType(basetype_content_type, debug) Laurent@1301: return basetype_content_type == "enum" Laurent@814: return False Laurent@814: andrej@1744: def IsSubrangeType(self, typename, exclude=None, debug=False): Laurent@1301: if typename == exclude: Laurent@1301: return False andrej@2450: if isinstance(typename, tuple): Laurent@1306: typename = typename[1] Laurent@1301: datatype = self.GetDataType(typename, debug) Laurent@1301: if datatype is not None: Laurent@1301: basetype_content = datatype.baseType.getcontent() Laurent@1301: basetype_content_type = basetype_content.getLocalTag() Laurent@1301: if basetype_content_type == "derived": Laurent@1301: return self.IsSubrangeType(basetype_content_type, exclude, debug) Laurent@1301: elif basetype_content_type in ["subrangeSigned", "subrangeUnsigned"]: Laurent@1301: return not self.IsOfType( Laurent@1301: self.GetDataTypeBaseType(datatype), exclude) Laurent@1301: return False Laurent@1301: andrej@1744: def IsNumType(self, typename, debug=False): Laurent@1301: return self.IsOfType(typename, "ANY_NUM", debug) or\ Laurent@1301: self.IsOfType(typename, "ANY_BIT", debug) Edouard@1411: andrej@1744: def GetDataTypeRange(self, typename, debug=False): Laurent@1301: range = DataTypeRange.get(typename) Laurent@1301: if range is not None: Laurent@1301: return range Laurent@1301: datatype = self.GetDataType(typename, debug) Laurent@1301: if datatype is not None: Laurent@1301: basetype_content = datatype.baseType.getcontent() Laurent@1301: basetype_content_type = basetype_content.getLocalTag() Laurent@1301: if basetype_content_type in ["subrangeSigned", "subrangeUnsigned"]: Laurent@1301: return (basetype_content.range.getlower(), Laurent@1301: basetype_content.range.getupper()) Laurent@1301: elif basetype_content_type == "derived": Laurent@1301: return self.GetDataTypeRange(basetype_content.getname(), debug) Laurent@1301: return None Edouard@1411: Laurent@1301: # Return Subrange types andrej@1744: def GetSubrangeBaseTypes(self, exclude, debug=False): kinsamanka@3750: subrange_basetypes = list(DataTypeRange.keys()) Laurent@1301: project = self.GetProject(debug) Laurent@1301: if project is not None: Laurent@1301: subrange_basetypes.extend( Laurent@1301: [datatype.getname() for datatype in project.getdataTypes() Laurent@1301: if self.IsSubrangeType(datatype.getname(), exclude, debug)]) Laurent@1301: for confnodetype in self.ConfNodeTypes: Laurent@1301: subrange_basetypes.extend( Laurent@1301: [datatype.getname() for datatype in confnodetype["types"].getdataTypes() Laurent@1301: if self.IsSubrangeType(datatype.getname(), exclude, debug)]) Laurent@1301: return subrange_basetypes Edouard@1411: Laurent@1301: # Return Enumerated Values andrej@1744: def GetEnumeratedDataValues(self, typename=None, debug=False): Laurent@1301: values = [] Laurent@1301: if typename is not None: Laurent@1301: datatype_obj = self.GetDataType(typename, debug) Laurent@1301: if datatype_obj is not None: Laurent@1301: basetype_content = datatype_obj.baseType.getcontent() Laurent@1301: basetype_content_type = basetype_content.getLocalTag() Laurent@1301: if basetype_content_type == "enum": Edouard@1411: return [value.getname() Laurent@1301: for value in basetype_content.xpath( Laurent@1301: "ppx:values/ppx:value", Laurent@1301: namespaces=PLCOpenParser.NSMAP)] Laurent@1301: elif basetype_content_type == "derived": Laurent@1301: return self.GetEnumeratedDataValues(basetype_content.getname(), debug) Laurent@814: else: Laurent@814: project = self.GetProject(debug) Laurent@814: if project is not None: Laurent@1301: values.extend(project.GetEnumeratedDataTypeValues()) Laurent@814: for confnodetype in self.ConfNodeTypes: Laurent@1301: values.extend(confnodetype["types"].GetEnumeratedDataTypeValues()) Laurent@814: return values Laurent@814: andrej@1782: # ------------------------------------------------------------------------------- andrej@1782: # Project opened Data types management functions andrej@1782: # ------------------------------------------------------------------------------- Laurent@814: Laurent@814: # Return the data type informations andrej@1744: def GetDataTypeInfos(self, tagname, debug=False): Laurent@814: project = self.GetProject(debug) Laurent@814: if project is not None: Laurent@814: words = tagname.split("::") Laurent@814: if words[0] == "D": Laurent@814: infos = {} Laurent@814: datatype = project.getdataType(words[1]) Laurent@883: if datatype is None: Laurent@883: return None Laurent@814: basetype_content = datatype.baseType.getcontent() Laurent@1291: basetype_content_type = basetype_content.getLocalTag() Laurent@1291: if basetype_content_type in ["subrangeSigned", "subrangeUnsigned"]: Laurent@814: infos["type"] = "Subrange" Laurent@1291: infos["min"] = basetype_content.range.getlower() Laurent@1291: infos["max"] = basetype_content.range.getupper() Laurent@1291: base_type = basetype_content.baseType.getcontent() Laurent@1291: base_type_type = base_type.getLocalTag() Laurent@1291: infos["base_type"] = (base_type.getname() andrej@1768: if base_type_type == "derived" andrej@1768: else base_type_type) Laurent@1291: elif basetype_content_type == "enum": Laurent@814: infos["type"] = "Enumerated" Laurent@814: infos["values"] = [] Laurent@1291: for value in basetype_content.xpath("ppx:values/ppx:value", namespaces=PLCOpenParser.NSMAP): Laurent@814: infos["values"].append(value.getname()) Laurent@1291: elif basetype_content_type == "array": Laurent@814: infos["type"] = "Array" Laurent@814: infos["dimensions"] = [] Laurent@1291: for dimension in basetype_content.getdimension(): Laurent@814: infos["dimensions"].append((dimension.getlower(), dimension.getupper())) Laurent@1291: base_type = basetype_content.baseType.getcontent() Laurent@1291: base_type_type = base_type.getLocalTag() Laurent@1291: infos["base_type"] = (base_type.getname() andrej@1768: if base_type_type == "derived" andrej@1768: else base_type_type.upper()) Laurent@1291: elif basetype_content_type == "struct": Laurent@814: infos["type"] = "Structure" Laurent@814: infos["elements"] = [] Laurent@1291: for element in basetype_content.getvariable(): Laurent@814: element_infos = {} Laurent@814: element_infos["Name"] = element.getname() Laurent@814: element_type = element.type.getcontent() Laurent@1291: element_type_type = element_type.getLocalTag() Laurent@1291: if element_type_type == "array": Laurent@864: dimensions = [] Laurent@1291: for dimension in element_type.getdimension(): Laurent@864: dimensions.append((dimension.getlower(), dimension.getupper())) Laurent@1291: base_type = element_type.baseType.getcontent() andrej@1502: base_type_type = base_type.getLocalTag() Edouard@1411: element_infos["Type"] = ("array", andrej@1768: base_type.getname() andrej@1768: if base_type_type == "derived" andrej@1768: else base_type_type.upper(), andrej@1768: dimensions) Laurent@1291: elif element_type_type == "derived": Laurent@1291: element_infos["Type"] = element_type.getname() Laurent@814: else: Laurent@1291: element_infos["Type"] = element_type_type.upper() Laurent@814: if element.initialValue is not None: andrej@1508: element_infos["Initial Value"] = element.initialValue.getvalue() Laurent@814: else: Laurent@814: element_infos["Initial Value"] = "" Laurent@814: infos["elements"].append(element_infos) Laurent@1291: else: Laurent@1291: infos["type"] = "Directly" Laurent@1291: infos["base_type"] = (basetype_content.getname() andrej@1768: if basetype_content_type == "derived" andrej@1768: else basetype_content_type.upper()) Edouard@1411: Laurent@814: if datatype.initialValue is not None: andrej@1508: infos["initial"] = datatype.initialValue.getvalue() Laurent@814: else: Laurent@814: infos["initial"] = "" Laurent@814: return infos Laurent@814: return None Edouard@1411: Laurent@814: # Change the data type informations Laurent@814: def SetDataTypeInfos(self, tagname, infos): Laurent@814: words = tagname.split("::") Laurent@814: if self.Project is not None and words[0] == "D": Laurent@814: datatype = self.Project.getdataType(words[1]) Laurent@814: if infos["type"] == "Directly": Laurent@814: if infos["base_type"] in self.GetBaseTypes(): Laurent@1291: datatype.baseType.setcontent(PLCOpenParser.CreateElement( Laurent@1291: infos["base_type"].lower() Laurent@1291: if infos["base_type"] in ["STRING", "WSTRING"] Laurent@1291: else infos["base_type"], "dataType")) Laurent@814: else: Laurent@1291: derived_datatype = PLCOpenParser.CreateElement("derived", "dataType") Laurent@814: derived_datatype.setname(infos["base_type"]) Laurent@1291: datatype.baseType.setcontent(derived_datatype) Laurent@814: elif infos["type"] == "Subrange": Laurent@1294: subrange = PLCOpenParser.CreateElement( Edouard@1411: "subrangeUnsigned" Laurent@1291: if infos["base_type"] in GetSubTypes("ANY_UINT") Laurent@1294: else "subrangeSigned", "dataType") Laurent@1294: datatype.baseType.setcontent(subrange) Laurent@814: subrange.range.setlower(infos["min"]) Laurent@814: subrange.range.setupper(infos["max"]) Laurent@814: if infos["base_type"] in self.GetBaseTypes(): Laurent@1291: subrange.baseType.setcontent( Laurent@1294: PLCOpenParser.CreateElement(infos["base_type"], "dataType")) Laurent@814: else: Laurent@1291: derived_datatype = PLCOpenParser.CreateElement("derived", "dataType") Laurent@814: derived_datatype.setname(infos["base_type"]) Laurent@1291: subrange.baseType.setcontent(derived_datatype) Laurent@814: elif infos["type"] == "Enumerated": Laurent@1291: enumerated = PLCOpenParser.CreateElement("enum", "dataType") Laurent@1294: datatype.baseType.setcontent(enumerated) Laurent@1291: values = PLCOpenParser.CreateElement("values", "enum") Laurent@1291: enumerated.setvalues(values) Laurent@814: for i, enum_value in enumerate(infos["values"]): Laurent@1291: value = PLCOpenParser.CreateElement("value", "values") Laurent@814: value.setname(enum_value) Laurent@814: if i == 0: Laurent@1291: values.setvalue([value]) Laurent@814: else: Laurent@1291: values.appendvalue(value) Laurent@814: elif infos["type"] == "Array": Laurent@1291: array = PLCOpenParser.CreateElement("array", "dataType") Laurent@1294: datatype.baseType.setcontent(array) Laurent@814: for i, dimension in enumerate(infos["dimensions"]): Laurent@1291: dimension_range = PLCOpenParser.CreateElement("dimension", "array") Laurent@814: dimension_range.setlower(dimension[0]) Laurent@814: dimension_range.setupper(dimension[1]) Laurent@814: if i == 0: Laurent@814: array.setdimension([dimension_range]) Laurent@814: else: Laurent@814: array.appenddimension(dimension_range) Laurent@814: if infos["base_type"] in self.GetBaseTypes(): Laurent@1291: array.baseType.setcontent(PLCOpenParser.CreateElement( Laurent@1291: infos["base_type"].lower() Laurent@1291: if infos["base_type"] in ["STRING", "WSTRING"] Laurent@1291: else infos["base_type"], "dataType")) Laurent@814: else: Laurent@1291: derived_datatype = PLCOpenParser.CreateElement("derived", "dataType") Laurent@814: derived_datatype.setname(infos["base_type"]) Laurent@1291: array.baseType.setcontent(derived_datatype) Laurent@814: elif infos["type"] == "Structure": Laurent@1291: struct = PLCOpenParser.CreateElement("struct", "dataType") Laurent@1294: datatype.baseType.setcontent(struct) Laurent@814: for i, element_infos in enumerate(infos["elements"]): Laurent@1291: element = PLCOpenParser.CreateElement("variable", "struct") Laurent@814: element.setname(element_infos["Name"]) Laurent@1291: element_type = PLCOpenParser.CreateElement("type", "variable") andrej@2450: if isinstance(element_infos["Type"], tuple): Laurent@864: if element_infos["Type"][0] == "array": andrej@1847: _array_type, base_type_name, dimensions = element_infos["Type"] Laurent@1291: array = PLCOpenParser.CreateElement("array", "dataType") andrej@1477: baseType = PLCOpenParser.CreateElement("baseType", "array") andrej@1477: array.setbaseType(baseType) Laurent@1294: element_type.setcontent(array) Laurent@864: for j, dimension in enumerate(dimensions): Laurent@1291: dimension_range = PLCOpenParser.CreateElement("dimension", "array") Laurent@864: dimension_range.setlower(dimension[0]) Laurent@864: dimension_range.setupper(dimension[1]) Laurent@864: if j == 0: Laurent@864: array.setdimension([dimension_range]) Laurent@864: else: Laurent@864: array.appenddimension(dimension_range) Laurent@864: if base_type_name in self.GetBaseTypes(): andrej@1477: baseType.setcontent(PLCOpenParser.CreateElement( Laurent@1291: base_type_name.lower() Laurent@1291: if base_type_name in ["STRING", "WSTRING"] Laurent@1291: else base_type_name, "dataType")) Laurent@864: else: Laurent@1291: derived_datatype = PLCOpenParser.CreateElement("derived", "dataType") Laurent@864: derived_datatype.setname(base_type_name) Laurent@1291: array.baseType.setcontent(derived_datatype) Laurent@864: elif element_infos["Type"] in self.GetBaseTypes(): Laurent@1291: element_type.setcontent( Laurent@1291: PLCOpenParser.CreateElement( Laurent@1291: element_infos["Type"].lower() Laurent@1291: if element_infos["Type"] in ["STRING", "WSTRING"] Laurent@1291: else element_infos["Type"], "dataType")) Laurent@814: else: Laurent@1291: derived_datatype = PLCOpenParser.CreateElement("derived", "dataType") Laurent@814: derived_datatype.setname(element_infos["Type"]) Laurent@1291: element_type.setcontent(derived_datatype) Laurent@1291: element.settype(element_type) Laurent@814: if element_infos["Initial Value"] != "": Laurent@1291: value = PLCOpenParser.CreateElement("initialValue", "variable") Laurent@814: value.setvalue(element_infos["Initial Value"]) Laurent@814: element.setinitialValue(value) Laurent@814: if i == 0: Laurent@814: struct.setvariable([element]) Laurent@814: else: Laurent@814: struct.appendvariable(element) Laurent@814: if infos["initial"] != "": Laurent@814: if datatype.initialValue is None: Laurent@1291: datatype.initialValue = PLCOpenParser.CreateElement("initialValue", "dataType") Laurent@814: datatype.initialValue.setvalue(infos["initial"]) Laurent@814: else: Laurent@814: datatype.initialValue = None Laurent@814: self.BufferProject() Edouard@1411: andrej@1782: # ------------------------------------------------------------------------------- andrej@1782: # Project opened Pous management functions andrej@1782: # ------------------------------------------------------------------------------- Laurent@814: Laurent@814: # Return edited element andrej@1744: def GetEditedElement(self, tagname, debug=False): Laurent@814: project = self.GetProject(debug) Laurent@814: if project is not None: Laurent@814: words = tagname.split("::") Laurent@814: if words[0] == "D": Laurent@814: return project.getdataType(words[1]) Laurent@814: elif words[0] == "P": Laurent@814: return project.getpou(words[1]) Laurent@814: elif words[0] in ['T', 'A']: Laurent@814: pou = project.getpou(words[1]) Laurent@814: if pou is not None: Laurent@814: if words[0] == 'T': Laurent@814: return pou.gettransition(words[2]) Laurent@814: elif words[0] == 'A': Laurent@814: return pou.getaction(words[2]) Laurent@814: elif words[0] == 'C': Laurent@814: return project.getconfiguration(words[1]) Laurent@814: elif words[0] == 'R': Laurent@814: return project.getconfigurationResource(words[1], words[2]) Laurent@814: return None Edouard@1411: Laurent@814: # Return edited element name Laurent@814: def GetEditedElementName(self, tagname): Laurent@814: words = tagname.split("::") andrej@1740: if words[0] in ["P", "C", "D"]: Laurent@814: return words[1] Laurent@814: else: Laurent@814: return words[2] Laurent@814: return None Edouard@1411: Laurent@814: # Return edited element name and type andrej@1744: def GetEditedElementType(self, tagname, debug=False): Laurent@814: words = tagname.split("::") andrej@1740: if words[0] in ["P", "T", "A"]: Laurent@814: return words[1], self.GetPouType(words[1], debug) Laurent@814: return None, None Laurent@814: Laurent@814: # Return language in which edited element is written andrej@1744: def GetEditedElementBodyType(self, tagname, debug=False): Laurent@814: words = tagname.split("::") Laurent@814: if words[0] == "P": Laurent@814: return self.GetPouBodyType(words[1], debug) Laurent@814: elif words[0] == 'T': Laurent@814: return self.GetTransitionBodyType(words[1], words[2], debug) Laurent@814: elif words[0] == 'A': Laurent@814: return self.GetActionBodyType(words[1], words[2], debug) Laurent@814: return None Laurent@814: Laurent@814: # Return the edited element variables andrej@1744: def GetEditedElementInterfaceVars(self, tagname, tree=False, debug=False): Laurent@814: words = tagname.split("::") andrej@1740: if words[0] in ["P", "T", "A"]: Laurent@814: project = self.GetProject(debug) Laurent@814: if project is not None: Laurent@814: pou = project.getpou(words[1]) Laurent@814: if pou is not None: Laurent@1347: return self.GetPouInterfaceVars(pou, tree, debug) Laurent@814: return [] Laurent@814: Laurent@814: # Return the edited element return type andrej@1744: def GetEditedElementInterfaceReturnType(self, tagname, tree=False, debug=False): Laurent@814: words = tagname.split("::") Laurent@814: if words[0] == "P": Laurent@814: project = self.GetProject(debug) Laurent@814: if project is not None: Laurent@814: pou = self.Project.getpou(words[1]) Laurent@814: if pou is not None: Laurent@1347: return self.GetPouInterfaceReturnType(pou, tree, debug) Laurent@814: elif words[0] == 'T': andrej@1616: return ["BOOL", ([], [])] Laurent@814: return None Edouard@1411: Laurent@814: # Change the edited element text Laurent@814: def SetEditedElementText(self, tagname, text): Laurent@814: if self.Project is not None: Laurent@814: element = self.GetEditedElement(tagname) Laurent@814: if element is not None: Laurent@814: element.settext(text) Edouard@1411: Laurent@814: # Return the edited element text andrej@1744: def GetEditedElementText(self, tagname, debug=False): Laurent@814: element = self.GetEditedElement(tagname, debug) Laurent@814: if element is not None: Laurent@814: return element.gettext() Laurent@814: return "" Laurent@814: Laurent@814: # Return the edited element transitions andrej@1744: def GetEditedElementTransitions(self, tagname, debug=False): Laurent@814: pou = self.GetEditedElement(tagname, debug) Laurent@814: if pou is not None and pou.getbodyType() == "SFC": Laurent@814: transitions = [] Laurent@814: for transition in pou.gettransitionList(): Laurent@814: transitions.append(transition.getname()) Laurent@814: return transitions Laurent@814: return [] Laurent@814: Laurent@814: # Return edited element transitions andrej@1744: def GetEditedElementActions(self, tagname, debug=False): Laurent@814: pou = self.GetEditedElement(tagname, debug) Laurent@814: if pou is not None and pou.getbodyType() == "SFC": Laurent@814: actions = [] Laurent@814: for action in pou.getactionList(): Laurent@814: actions.append(action.getname()) Laurent@814: return actions Laurent@814: return [] Laurent@814: Laurent@814: # Return the names of the pou elements andrej@1744: def GetEditedElementVariables(self, tagname, debug=False): Laurent@814: words = tagname.split("::") andrej@1740: if words[0] in ["P", "T", "A"]: Laurent@1171: return self.GetProjectPouVariableNames(words[1], debug) Laurent@1171: elif words[0] in ["C", "R"]: Laurent@1171: names = self.GetConfigurationVariableNames(words[1], debug) Laurent@1171: if words[0] == "R": Laurent@1171: names.extend(self.GetConfigurationResourceVariableNames( Laurent@1171: words[1], words[2], debug)) Laurent@1171: return names Laurent@814: return [] Laurent@814: andrej@1744: def GetEditedElementCopy(self, tagname, debug=False): Laurent@814: element = self.GetEditedElement(tagname, debug) Laurent@814: if element is not None: Laurent@1299: return element.tostring() Laurent@814: return "" Edouard@1411: andrej@1744: def GetEditedElementInstancesCopy(self, tagname, blocks_id=None, wires=None, debug=False): Laurent@814: element = self.GetEditedElement(tagname, debug) Laurent@814: text = "" Laurent@814: if element is not None: Edouard@1411: wires = dict([(wire, True) Edouard@1411: for wire in wires Laurent@1299: if wire[0] in blocks_id and wire[1] in blocks_id]) Laurent@1299: copy_body = PLCOpenParser.CreateElement("body", "pou") Laurent@1299: element.append(copy_body) Laurent@1299: copy_body.setcontent( Laurent@1299: PLCOpenParser.CreateElement(element.getbodyType(), "body")) Laurent@814: for id in blocks_id: Laurent@814: instance = element.getinstance(id) Laurent@814: if instance is not None: Laurent@1299: copy_body.appendcontentInstance(self.Copy(instance)) Laurent@1299: instance_copy = copy_body.getcontentInstance(id) Laurent@814: instance_copy.filterConnections(wires) Laurent@1299: text += instance_copy.tostring() Laurent@1299: element.remove(copy_body) Laurent@814: return text Edouard@1411: andrej@1852: def GenerateNewName(self, tagname, name, format, start_idx=0, exclude=None, debug=False): surkovsv93@1968: if name is not None: surkovsv93@1968: result = re.search(VARIABLE_NAME_SUFFIX_MODEL, name) surkovsv93@1968: if result is not None: surkovsv93@1968: format = name[:result.start(1)] + '%d' surkovsv93@1968: start_idx = int(result.group(1)) surkovsv93@1968: else: surkovsv93@1968: format = name + '%d' surkovsv93@1968: andrej@1852: names = {} if exclude is None else exclude.copy() Laurent@814: if tagname is not None: Edouard@1411: names.update(dict([(varname.upper(), True) Laurent@1122: for varname in self.GetEditedElementVariables(tagname, debug)])) Laurent@1127: words = tagname.split("::") andrej@1740: if words[0] in ["P", "T", "A"]: Laurent@1127: element = self.GetEditedElement(tagname, debug) Laurent@1127: if element is not None and element.getbodyType() not in ["ST", "IL"]: Laurent@1127: for instance in element.getinstances(): andrej@1768: if isinstance( andrej@1768: instance, andrej@1768: (PLCOpenParser.GetElementClass("step", "sfcObjects"), andrej@1768: PLCOpenParser.GetElementClass("connector", "commonObjects"), andrej@1768: PLCOpenParser.GetElementClass("continuation", "commonObjects"))): Laurent@1127: names[instance.getname().upper()] = True surkovsv93@1968: elif words[0] == 'R': surkovsv93@1968: element = self.GetEditedElement(tagname, debug) surkovsv93@1968: for task in element.gettask(): surkovsv93@1968: names[task.getname().upper()] = True surkovsv93@1968: for instance in task.getpouInstance(): surkovsv93@1968: names[instance.getname().upper()] = True surkovsv93@1968: for instance in element.getpouInstance(): surkovsv93@1968: names[instance.getname().upper()] = True Laurent@814: else: Laurent@814: project = self.GetProject(debug) Laurent@814: if project is not None: Laurent@814: for datatype in project.getdataTypes(): Laurent@814: names[datatype.getname().upper()] = True Laurent@814: for pou in project.getpous(): Laurent@814: names[pou.getname().upper()] = True Laurent@1347: for var in self.GetPouInterfaceVars(pou, debug=debug): Laurent@1347: names[var.Name.upper()] = True Laurent@814: for transition in pou.gettransitionList(): Laurent@814: names[transition.getname().upper()] = True Laurent@814: for action in pou.getactionList(): Laurent@814: names[action.getname().upper()] = True Laurent@814: for config in project.getconfigurations(): Laurent@814: names[config.getname().upper()] = True Laurent@814: for resource in config.getresource(): Laurent@814: names[resource.getname().upper()] = True Edouard@1411: Laurent@1122: i = start_idx Laurent@814: while name is None or names.get(name.upper(), False): andrej@1734: name = (format % i) Laurent@814: i += 1 Laurent@814: return name Edouard@1411: Laurent@814: def PasteEditedElementInstances(self, tagname, text, new_pos, middle=False, debug=False): Laurent@814: element = self.GetEditedElement(tagname, debug) andrej@1847: _element_name, element_type = self.GetEditedElementType(tagname, debug) Laurent@814: if element is not None: Laurent@814: bodytype = element.getbodyType() Edouard@1411: Laurent@814: # Get edited element type scaling Laurent@814: scaling = None Laurent@814: project = self.GetProject(debug) Laurent@814: if project is not None: Laurent@814: properties = project.getcontentHeader() Laurent@814: scaling = properties["scaling"][bodytype] Edouard@1411: Laurent@814: # Get ids already by all the instances in edited element Laurent@814: used_id = dict([(instance.getlocalId(), True) for instance in element.getinstances()]) Laurent@814: new_id = {} Edouard@1411: Laurent@814: try: andrej@1505: instances, error = LoadPouInstances(text, bodytype) andrej@1780: except Exception: Laurent@1330: instances, error = [], "" Laurent@1330: if error is not None or len(instances) == 0: Laurent@814: return _("Invalid plcopen element(s)!!!") Edouard@1411: Laurent@814: exclude = {} Laurent@1299: for instance in instances: Laurent@1299: element.addinstance(instance) Laurent@1299: instance_type = instance.getLocalTag() Laurent@1299: if instance_type == "block": Laurent@1337: blocktype = instance.gettypeName() Laurent@1337: blocktype_infos = self.GetBlockType(blocktype) Laurent@1299: blockname = instance.getinstanceName() Laurent@1337: if blocktype_infos["type"] != "function" and blockname is not None: Laurent@1299: if element_type == "function": andrej@1734: return _("FunctionBlock \"%s\" can't be pasted in a Function!!!") % blocktype Edouard@1411: blockname = self.GenerateNewName(tagname, Edouard@1411: blockname, andrej@1734: "%s%%d" % blocktype, Laurent@1299: debug=debug) Laurent@1299: exclude[blockname] = True Laurent@1299: instance.setinstanceName(blockname) Laurent@1299: self.AddEditedElementPouVar(tagname, blocktype, blockname) Laurent@1299: elif instance_type == "step": Edouard@1411: stepname = self.GenerateNewName(tagname, Edouard@1411: instance.getname(), Edouard@1411: "Step%d", Edouard@1411: exclude=exclude, Laurent@1299: debug=debug) Laurent@1299: exclude[stepname] = True Laurent@1299: instance.setname(stepname) Laurent@1299: localid = instance.getlocalId() andrej@1775: if localid not in used_id: Laurent@1299: new_id[localid] = True Edouard@1411: Laurent@814: idx = 1 Laurent@814: translate_id = {} Laurent@1299: bbox = rect() Laurent@1299: for instance in instances: Laurent@814: localId = instance.getlocalId() Laurent@814: bbox.union(instance.getBoundingBox()) andrej@1763: if localId in used_id: andrej@1763: while (idx in used_id) or (idx in new_id): Laurent@814: idx += 1 Laurent@814: new_id[idx] = True Laurent@814: instance.setlocalId(idx) Laurent@814: translate_id[localId] = idx Edouard@1411: Laurent@814: x, y, width, height = bbox.bounding_box() Laurent@814: if middle: andrej@2437: new_pos[0] -= width // 2 andrej@2437: new_pos[1] -= height // 2 Laurent@814: else: kinsamanka@3750: new_pos = [x + 30 for x in new_pos] Laurent@814: if scaling[0] != 0 and scaling[1] != 0: kinsamanka@3750: min_pos = [30 / x for x in scaling] Laurent@814: minx = round(min_pos[0]) Laurent@814: if int(min_pos[0]) == round(min_pos[0]): Laurent@814: minx += 1 Laurent@814: miny = round(min_pos[1]) Laurent@814: if int(min_pos[1]) == round(min_pos[1]): Laurent@814: miny += 1 Laurent@814: minx *= scaling[0] Laurent@814: miny *= scaling[1] Laurent@814: new_pos = (max(minx, round(new_pos[0] / scaling[0]) * scaling[0]), Laurent@814: max(miny, round(new_pos[1] / scaling[1]) * scaling[1])) Laurent@814: else: Laurent@814: new_pos = (max(30, new_pos[0]), max(30, new_pos[1])) Laurent@1367: diff = (int(new_pos[0] - x), int(new_pos[1] - y)) Edouard@1411: Laurent@814: connections = {} Laurent@1299: for instance in instances: Laurent@814: connections.update(instance.updateConnectionsId(translate_id)) Laurent@814: if getattr(instance, "setexecutionOrderId", None) is not None: Laurent@814: instance.setexecutionOrderId(0) Laurent@814: instance.translate(*diff) Edouard@1411: Laurent@814: return new_id, connections Edouard@1411: andrej@1744: def GetEditedElementInstancesInfos(self, tagname, debug=False): Laurent@1331: element = self.GetEditedElement(tagname, debug) Laurent@1331: if element is not None: Edouard@1957: return self.BlockInstanceCollector.Collect(element, debug) Edouard@1957: return {} Edouard@1411: Laurent@814: def ClearEditedElementExecutionOrder(self, tagname): Laurent@814: element = self.GetEditedElement(tagname) Laurent@814: if element is not None: Laurent@814: element.resetexecutionOrder() Edouard@1411: Laurent@814: def ResetEditedElementExecutionOrder(self, tagname): Laurent@814: element = self.GetEditedElement(tagname) Laurent@814: if element is not None: Laurent@814: element.compileexecutionOrder() Edouard@1411: Laurent@814: def SetConnectionWires(self, connection, connector): Laurent@814: wires = connector.GetWires() Laurent@814: idx = 0 Laurent@814: for wire, handle in wires: Laurent@814: points = wire.GetPoints(handle != 0) Laurent@814: if handle == 0: Laurent@814: result = wire.GetConnectedInfos(-1) Laurent@814: else: Laurent@814: result = wire.GetConnectedInfos(0) andrej@1743: if result is not None: Laurent@814: refLocalId, formalParameter = result Laurent@814: connections = connection.getconnections() Laurent@814: if connections is None or len(connection.getconnections()) <= idx: Laurent@814: connection.addconnection() Laurent@814: connection.setconnectionId(idx, refLocalId) Laurent@814: connection.setconnectionPoints(idx, points) Laurent@814: if formalParameter != "": Laurent@814: connection.setconnectionParameter(idx, formalParameter) Laurent@814: else: Laurent@814: connection.setconnectionParameter(idx, None) Laurent@814: idx += 1 Edouard@1411: Laurent@1313: def GetVarTypeObject(self, var_type): Laurent@1313: var_type_obj = PLCOpenParser.CreateElement("type", "variable") Laurent@1313: if not var_type.startswith("ANY") and TypeHierarchy.get(var_type): Laurent@1313: var_type_obj.setcontent(PLCOpenParser.CreateElement( Laurent@1313: var_type.lower() if var_type in ["STRING", "WSTRING"] Laurent@1313: else var_type, "dataType")) Laurent@1313: else: Laurent@1313: derived_type = PLCOpenParser.CreateElement("derived", "dataType") Laurent@1313: derived_type.setname(var_type) Laurent@1313: var_type_obj.setcontent(derived_type) Laurent@1313: return var_type_obj Edouard@1411: andrej@1740: def AddEditedElementPouVar(self, tagname, var_type, name, **args): Laurent@814: if self.Project is not None: Laurent@814: words = tagname.split("::") Laurent@814: if words[0] in ['P', 'T', 'A']: Laurent@814: pou = self.Project.getpou(words[1]) Laurent@814: if pou is not None: Laurent@1313: pou.addpouLocalVar( Edouard@1411: self.GetVarTypeObject(var_type), Edouard@1406: name, **args) Edouard@1411: Edouard@2739: def AddEditedElementPouExternalVar(self, tagname, var_type, name, **args): Laurent@814: if self.Project is not None: Laurent@814: words = tagname.split("::") Laurent@814: if words[0] in ['P', 'T', 'A']: Laurent@814: pou = self.Project.getpou(words[1]) Laurent@814: if pou is not None: Laurent@1313: pou.addpouExternalVar( Edouard@2739: self.GetVarTypeObject(var_type), Edouard@2739: name, **args) Edouard@1411: Laurent@814: def ChangeEditedElementPouVar(self, tagname, old_type, old_name, new_type, new_name): Laurent@814: if self.Project is not None: Laurent@814: words = tagname.split("::") Laurent@814: if words[0] in ['P', 'T', 'A']: Laurent@814: pou = self.Project.getpou(words[1]) Laurent@814: if pou is not None: Laurent@814: pou.changepouVar(old_type, old_name, new_type, new_name) Edouard@1411: Laurent@814: def RemoveEditedElementPouVar(self, tagname, type, name): Laurent@814: if self.Project is not None: Laurent@814: words = tagname.split("::") Laurent@814: if words[0] in ['P', 'T', 'A']: Laurent@814: pou = self.Project.getpou(words[1]) Laurent@814: if pou is not None: Laurent@814: pou.removepouVar(type, name) Edouard@1411: andrej@1744: def AddEditedElementBlock(self, tagname, id, blocktype, blockname=None): Laurent@814: element = self.GetEditedElement(tagname) Laurent@814: if element is not None: Laurent@1291: block = PLCOpenParser.CreateElement("block", "fbdObjects") Laurent@814: block.setlocalId(id) Laurent@814: block.settypeName(blocktype) Laurent@814: blocktype_infos = self.GetBlockType(blocktype) Laurent@814: if blocktype_infos["type"] != "function" and blockname is not None: Laurent@814: block.setinstanceName(blockname) Laurent@814: self.AddEditedElementPouVar(tagname, blocktype, blockname) Laurent@1293: element.addinstance(block) Edouard@1411: Laurent@814: def SetEditedElementBlockInfos(self, tagname, id, infos): Laurent@814: element = self.GetEditedElement(tagname) Laurent@814: if element is not None: Laurent@814: block = element.getinstance(id) Laurent@814: if block is None: Edouard@1411: return Laurent@814: old_name = block.getinstanceName() Laurent@814: old_type = block.gettypeName() Laurent@814: new_name = infos.get("name", old_name) Laurent@814: new_type = infos.get("type", old_type) Laurent@814: if new_type != old_type: Laurent@814: old_typeinfos = self.GetBlockType(old_type) Laurent@814: new_typeinfos = self.GetBlockType(new_type) Laurent@814: if old_typeinfos is None or new_typeinfos is None: Laurent@814: self.ChangeEditedElementPouVar(tagname, old_type, old_name, new_type, new_name) Laurent@814: elif new_typeinfos["type"] != old_typeinfos["type"]: Laurent@814: if new_typeinfos["type"] == "function": Laurent@814: self.RemoveEditedElementPouVar(tagname, old_type, old_name) Laurent@814: else: Laurent@814: self.AddEditedElementPouVar(tagname, new_type, new_name) Laurent@814: elif new_typeinfos["type"] != "function": Laurent@814: self.ChangeEditedElementPouVar(tagname, old_type, old_name, new_type, new_name) Laurent@814: elif new_name != old_name: Laurent@814: self.ChangeEditedElementPouVar(tagname, old_type, old_name, new_type, new_name) kinsamanka@3750: for param, value in list(infos.items()): Laurent@814: if param == "name": Laurent@1337: if value != "": Laurent@1337: block.setinstanceName(value) Laurent@1337: else: Laurent@1337: block.attrib.pop("instanceName", None) Laurent@814: elif param == "type": Laurent@814: block.settypeName(value) Laurent@814: elif param == "executionOrder" and block.getexecutionOrderId() != value: Laurent@814: element.setelementExecutionOrder(block, value) Laurent@814: elif param == "height": Laurent@814: block.setheight(value) Laurent@814: elif param == "width": Laurent@814: block.setwidth(value) Laurent@814: elif param == "x": Laurent@814: block.setx(value) Laurent@814: elif param == "y": Laurent@814: block.sety(value) Laurent@814: elif param == "connectors": Laurent@814: block.inputVariables.setvariable([]) Laurent@814: block.outputVariables.setvariable([]) Laurent@814: for connector in value["inputs"]: Laurent@1293: variable = PLCOpenParser.CreateElement("variable", "inputVariables") Laurent@1293: block.inputVariables.appendvariable(variable) Laurent@814: variable.setformalParameter(connector.GetName()) Laurent@814: if connector.IsNegated(): Laurent@814: variable.setnegated(True) Laurent@814: if connector.GetEdge() != "none": Laurent@814: variable.setedge(connector.GetEdge()) Laurent@814: position = connector.GetRelPosition() Laurent@814: variable.connectionPointIn.setrelPositionXY(position.x, position.y) Laurent@814: self.SetConnectionWires(variable.connectionPointIn, connector) Laurent@814: for connector in value["outputs"]: Laurent@1293: variable = PLCOpenParser.CreateElement("variable", "outputVariables") Laurent@1293: block.outputVariables.appendvariable(variable) Laurent@814: variable.setformalParameter(connector.GetName()) Laurent@814: if connector.IsNegated(): Laurent@814: variable.setnegated(True) Laurent@814: if connector.GetEdge() != "none": Laurent@814: variable.setedge(connector.GetEdge()) Laurent@814: position = connector.GetRelPosition() Laurent@814: variable.addconnectionPointOut() Laurent@814: variable.connectionPointOut.setrelPositionXY(position.x, position.y) Laurent@1293: block.tostring() Edouard@1411: Laurent@1293: def AddEditedElementVariable(self, tagname, id, var_type): Laurent@814: element = self.GetEditedElement(tagname) Laurent@1293: if element is not None: Laurent@1293: variable = PLCOpenParser.CreateElement( Laurent@1293: {INPUT: "inVariable", Laurent@1293: OUTPUT: "outVariable", Laurent@1293: INOUT: "inOutVariable"}[var_type], "fbdObjects") Laurent@814: variable.setlocalId(id) Laurent@1293: element.addinstance(variable) Edouard@1411: Laurent@814: def SetEditedElementVariableInfos(self, tagname, id, infos): Laurent@814: element = self.GetEditedElement(tagname) Laurent@814: if element is not None: Laurent@814: variable = element.getinstance(id) Laurent@814: if variable is None: Edouard@1411: return kinsamanka@3750: for param, value in list(infos.items()): Laurent@814: if param == "name": Laurent@1322: variable.setexpression(value) Laurent@814: elif param == "executionOrder" and variable.getexecutionOrderId() != value: Laurent@814: element.setelementExecutionOrder(variable, value) Laurent@814: elif param == "height": Laurent@814: variable.setheight(value) Laurent@814: elif param == "width": Laurent@814: variable.setwidth(value) Laurent@814: elif param == "x": Laurent@814: variable.setx(value) Laurent@814: elif param == "y": Laurent@814: variable.sety(value) Laurent@814: elif param == "connectors": Laurent@814: if len(value["outputs"]) > 0: Laurent@814: output = value["outputs"][0] Laurent@814: if len(value["inputs"]) > 0: Laurent@814: variable.setnegatedOut(output.IsNegated()) Laurent@814: variable.setedgeOut(output.GetEdge()) Laurent@814: else: Laurent@814: variable.setnegated(output.IsNegated()) Laurent@814: variable.setedge(output.GetEdge()) Laurent@814: position = output.GetRelPosition() Laurent@814: variable.addconnectionPointOut() Laurent@814: variable.connectionPointOut.setrelPositionXY(position.x, position.y) Laurent@814: if len(value["inputs"]) > 0: Laurent@814: input = value["inputs"][0] Laurent@814: if len(value["outputs"]) > 0: Laurent@814: variable.setnegatedIn(input.IsNegated()) Laurent@814: variable.setedgeIn(input.GetEdge()) Laurent@814: else: Laurent@814: variable.setnegated(input.IsNegated()) Laurent@814: variable.setedge(input.GetEdge()) Laurent@814: position = input.GetRelPosition() Laurent@814: variable.addconnectionPointIn() Laurent@814: variable.connectionPointIn.setrelPositionXY(position.x, position.y) Laurent@814: self.SetConnectionWires(variable.connectionPointIn, input) Laurent@814: Laurent@1293: def AddEditedElementConnection(self, tagname, id, connection_type): Laurent@814: element = self.GetEditedElement(tagname) Laurent@814: if element is not None: Laurent@1293: connection = PLCOpenParser.CreateElement( Laurent@1293: {CONNECTOR: "connector", Laurent@1293: CONTINUATION: "continuation"}[connection_type], "commonObjects") Laurent@814: connection.setlocalId(id) Laurent@1293: element.addinstance(connection) Edouard@1411: Laurent@814: def SetEditedElementConnectionInfos(self, tagname, id, infos): Laurent@814: element = self.GetEditedElement(tagname) Laurent@814: if element is not None: Laurent@814: connection = element.getinstance(id) Laurent@814: if connection is None: Laurent@814: return kinsamanka@3750: for param, value in list(infos.items()): Laurent@814: if param == "name": Edouard@1411: connection.setname(value) Laurent@814: elif param == "height": Laurent@814: connection.setheight(value) Laurent@814: elif param == "width": Laurent@814: connection.setwidth(value) Laurent@814: elif param == "x": Laurent@814: connection.setx(value) Laurent@814: elif param == "y": Laurent@814: connection.sety(value) Laurent@814: elif param == "connector": Laurent@814: position = value.GetRelPosition() Laurent@1293: if isinstance(connection, PLCOpenParser.GetElementClass("continuation", "commonObjects")): Laurent@814: connection.addconnectionPointOut() Laurent@814: connection.connectionPointOut.setrelPositionXY(position.x, position.y) Laurent@1293: elif isinstance(connection, PLCOpenParser.GetElementClass("connector", "commonObjects")): Laurent@814: connection.addconnectionPointIn() Laurent@814: connection.connectionPointIn.setrelPositionXY(position.x, position.y) Laurent@814: self.SetConnectionWires(connection.connectionPointIn, value) Laurent@814: Laurent@814: def AddEditedElementComment(self, tagname, id): Laurent@814: element = self.GetEditedElement(tagname) Laurent@814: if element is not None: Laurent@1293: comment = PLCOpenParser.CreateElement("comment", "commonObjects") Laurent@814: comment.setlocalId(id) Laurent@1293: element.addinstance(comment) Edouard@1411: Laurent@814: def SetEditedElementCommentInfos(self, tagname, id, infos): Laurent@814: element = self.GetEditedElement(tagname) Laurent@814: if element is not None: Laurent@814: comment = element.getinstance(id) kinsamanka@3750: for param, value in list(infos.items()): Laurent@814: if param == "content": Laurent@814: comment.setcontentText(value) Laurent@814: elif param == "height": Laurent@814: comment.setheight(value) Laurent@814: elif param == "width": Laurent@814: comment.setwidth(value) Laurent@814: elif param == "x": Laurent@814: comment.setx(value) Laurent@814: elif param == "y": Laurent@814: comment.sety(value) Laurent@814: Laurent@1293: def AddEditedElementPowerRail(self, tagname, id, powerrail_type): Laurent@814: element = self.GetEditedElement(tagname) Laurent@814: if element is not None: Laurent@1293: powerrail = PLCOpenParser.CreateElement( Laurent@1293: {LEFTRAIL: "leftPowerRail", Laurent@1293: RIGHTRAIL: "rightPowerRail"}[powerrail_type], "ldObjects") Laurent@814: powerrail.setlocalId(id) Laurent@1293: element.addinstance(powerrail) Edouard@1411: Laurent@814: def SetEditedElementPowerRailInfos(self, tagname, id, infos): Laurent@814: element = self.GetEditedElement(tagname) Laurent@814: if element is not None: Laurent@814: powerrail = element.getinstance(id) Laurent@814: if powerrail is None: Laurent@814: return kinsamanka@3750: for param, value in list(infos.items()): Laurent@814: if param == "height": Laurent@814: powerrail.setheight(value) Laurent@814: elif param == "width": Laurent@814: powerrail.setwidth(value) Laurent@814: elif param == "x": Laurent@814: powerrail.setx(value) Laurent@814: elif param == "y": Laurent@814: powerrail.sety(value) Laurent@814: elif param == "connectors": Laurent@1293: if isinstance(powerrail, PLCOpenParser.GetElementClass("leftPowerRail", "ldObjects")): Laurent@814: powerrail.setconnectionPointOut([]) Laurent@814: for connector in value["outputs"]: Laurent@814: position = connector.GetRelPosition() Laurent@1293: connection = PLCOpenParser.CreateElement("connectionPointOut", "leftPowerRail") Laurent@1293: powerrail.appendconnectionPointOut(connection) Laurent@814: connection.setrelPositionXY(position.x, position.y) Laurent@1293: elif isinstance(powerrail, PLCOpenParser.GetElementClass("rightPowerRail", "ldObjects")): Laurent@814: powerrail.setconnectionPointIn([]) Laurent@814: for connector in value["inputs"]: Laurent@814: position = connector.GetRelPosition() Laurent@1293: connection = PLCOpenParser.CreateElement("connectionPointIn", "rightPowerRail") Laurent@1293: powerrail.appendconnectionPointIn(connection) Laurent@814: connection.setrelPositionXY(position.x, position.y) Laurent@814: self.SetConnectionWires(connection, connector) Edouard@1411: Laurent@814: def AddEditedElementContact(self, tagname, id): Laurent@814: element = self.GetEditedElement(tagname) Laurent@814: if element is not None: Laurent@1293: contact = PLCOpenParser.CreateElement("contact", "ldObjects") Laurent@814: contact.setlocalId(id) Laurent@1293: element.addinstance(contact) Laurent@814: Laurent@814: def SetEditedElementContactInfos(self, tagname, id, infos): Laurent@814: element = self.GetEditedElement(tagname) Laurent@814: if element is not None: Laurent@814: contact = element.getinstance(id) Laurent@814: if contact is None: Laurent@814: return kinsamanka@3750: for param, value in list(infos.items()): Laurent@814: if param == "name": Laurent@1322: contact.setvariable(value) Laurent@814: elif param == "type": Laurent@1294: negated, edge = { Laurent@1294: CONTACT_NORMAL: (False, "none"), Laurent@1294: CONTACT_REVERSE: (True, "none"), Laurent@1294: CONTACT_RISING: (False, "rising"), Laurent@1294: CONTACT_FALLING: (False, "falling")}[value] Laurent@1294: contact.setnegated(negated) Laurent@1294: contact.setedge(edge) Laurent@814: elif param == "height": Laurent@814: contact.setheight(value) Laurent@814: elif param == "width": Laurent@814: contact.setwidth(value) Laurent@814: elif param == "x": Laurent@814: contact.setx(value) Laurent@814: elif param == "y": Laurent@814: contact.sety(value) Laurent@814: elif param == "connectors": Laurent@814: input_connector = value["inputs"][0] Laurent@814: position = input_connector.GetRelPosition() Laurent@814: contact.addconnectionPointIn() Laurent@814: contact.connectionPointIn.setrelPositionXY(position.x, position.y) Laurent@814: self.SetConnectionWires(contact.connectionPointIn, input_connector) Laurent@814: output_connector = value["outputs"][0] Laurent@814: position = output_connector.GetRelPosition() Laurent@814: contact.addconnectionPointOut() Laurent@814: contact.connectionPointOut.setrelPositionXY(position.x, position.y) Laurent@814: Laurent@814: def AddEditedElementCoil(self, tagname, id): Laurent@814: element = self.GetEditedElement(tagname) Laurent@814: if element is not None: Laurent@1293: coil = PLCOpenParser.CreateElement("coil", "ldObjects") Laurent@814: coil.setlocalId(id) Laurent@1293: element.addinstance(coil) Laurent@814: Laurent@814: def SetEditedElementCoilInfos(self, tagname, id, infos): Laurent@814: element = self.GetEditedElement(tagname) Laurent@814: if element is not None: Laurent@814: coil = element.getinstance(id) Laurent@814: if coil is None: Laurent@814: return kinsamanka@3750: for param, value in list(infos.items()): Laurent@814: if param == "name": Laurent@1322: coil.setvariable(value) Laurent@814: elif param == "type": Laurent@1294: negated, storage, edge = { Laurent@1294: COIL_NORMAL: (False, "none", "none"), Laurent@1294: COIL_REVERSE: (True, "none", "none"), Laurent@1294: COIL_SET: (False, "set", "none"), Laurent@1294: COIL_RESET: (False, "reset", "none"), Laurent@1294: COIL_RISING: (False, "none", "rising"), Laurent@1294: COIL_FALLING: (False, "none", "falling")}[value] Laurent@1294: coil.setnegated(negated) Laurent@1294: coil.setstorage(storage) Laurent@1294: coil.setedge(edge) Laurent@814: elif param == "height": Laurent@814: coil.setheight(value) Laurent@814: elif param == "width": Laurent@814: coil.setwidth(value) Laurent@814: elif param == "x": Laurent@814: coil.setx(value) Laurent@814: elif param == "y": Laurent@814: coil.sety(value) Laurent@814: elif param == "connectors": Laurent@814: input_connector = value["inputs"][0] Laurent@814: position = input_connector.GetRelPosition() Laurent@814: coil.addconnectionPointIn() Laurent@814: coil.connectionPointIn.setrelPositionXY(position.x, position.y) Laurent@814: self.SetConnectionWires(coil.connectionPointIn, input_connector) Laurent@814: output_connector = value["outputs"][0] Laurent@814: position = output_connector.GetRelPosition() Laurent@814: coil.addconnectionPointOut() Laurent@814: coil.connectionPointOut.setrelPositionXY(position.x, position.y) Laurent@814: Laurent@814: def AddEditedElementStep(self, tagname, id): Laurent@814: element = self.GetEditedElement(tagname) Laurent@814: if element is not None: Laurent@1293: step = PLCOpenParser.CreateElement("step", "sfcObjects") Laurent@814: step.setlocalId(id) Laurent@1293: element.addinstance(step) Edouard@1411: Laurent@814: def SetEditedElementStepInfos(self, tagname, id, infos): Laurent@814: element = self.GetEditedElement(tagname) Laurent@814: if element is not None: Laurent@814: step = element.getinstance(id) Laurent@814: if step is None: Laurent@814: return kinsamanka@3750: for param, value in list(infos.items()): Laurent@814: if param == "name": Laurent@814: step.setname(value) Laurent@814: elif param == "initial": Laurent@814: step.setinitialStep(value) Laurent@814: elif param == "height": Laurent@814: step.setheight(value) Laurent@814: elif param == "width": Laurent@814: step.setwidth(value) Laurent@814: elif param == "x": Laurent@814: step.setx(value) Laurent@814: elif param == "y": Laurent@814: step.sety(value) Laurent@814: elif param == "connectors": Laurent@814: if len(value["inputs"]) > 0: Laurent@814: input_connector = value["inputs"][0] Laurent@814: position = input_connector.GetRelPosition() Laurent@814: step.addconnectionPointIn() Laurent@814: step.connectionPointIn.setrelPositionXY(position.x, position.y) Laurent@814: self.SetConnectionWires(step.connectionPointIn, input_connector) Laurent@814: else: Laurent@814: step.deleteconnectionPointIn() Laurent@814: if len(value["outputs"]) > 0: Laurent@814: output_connector = value["outputs"][0] Laurent@814: position = output_connector.GetRelPosition() Laurent@814: step.addconnectionPointOut() Laurent@814: step.connectionPointOut.setrelPositionXY(position.x, position.y) Laurent@814: else: Laurent@814: step.deleteconnectionPointOut() Laurent@814: elif param == "action": Laurent@814: if value: Laurent@814: position = value.GetRelPosition() Laurent@814: step.addconnectionPointOutAction() Laurent@814: step.connectionPointOutAction.setrelPositionXY(position.x, position.y) Laurent@814: else: Laurent@814: step.deleteconnectionPointOutAction() Edouard@1411: Laurent@814: def AddEditedElementTransition(self, tagname, id): Laurent@814: element = self.GetEditedElement(tagname) Laurent@814: if element is not None: Laurent@1293: transition = PLCOpenParser.CreateElement("transition", "sfcObjects") Laurent@814: transition.setlocalId(id) Laurent@1293: element.addinstance(transition) Edouard@1411: Laurent@814: def SetEditedElementTransitionInfos(self, tagname, id, infos): Laurent@814: element = self.GetEditedElement(tagname) Laurent@814: if element is not None: Laurent@814: transition = element.getinstance(id) Laurent@814: if transition is None: Laurent@814: return kinsamanka@3750: for param, value in list(infos.items()): Laurent@814: if param == "type" and value != "connection": Laurent@814: transition.setconditionContent(value, infos["condition"]) Laurent@814: elif param == "height": Laurent@814: transition.setheight(value) Laurent@814: elif param == "width": Laurent@814: transition.setwidth(value) Laurent@814: elif param == "x": Laurent@814: transition.setx(value) Laurent@814: elif param == "y": Laurent@814: transition.sety(value) Laurent@814: elif param == "priority": Laurent@814: if value != 0: Laurent@814: transition.setpriority(value) Laurent@814: else: Laurent@814: transition.setpriority(None) Laurent@814: elif param == "connectors": Laurent@814: input_connector = value["inputs"][0] Laurent@814: position = input_connector.GetRelPosition() Laurent@814: transition.addconnectionPointIn() Laurent@814: transition.connectionPointIn.setrelPositionXY(position.x, position.y) Laurent@814: self.SetConnectionWires(transition.connectionPointIn, input_connector) Laurent@814: output_connector = value["outputs"][0] Laurent@814: position = output_connector.GetRelPosition() Laurent@814: transition.addconnectionPointOut() Laurent@814: transition.connectionPointOut.setrelPositionXY(position.x, position.y) Laurent@814: elif infos.get("type", None) == "connection" and param == "connection" and value: Laurent@814: transition.setconditionContent("connection", None) Laurent@1293: self.SetConnectionWires(transition.condition.content, value) Edouard@1411: Laurent@1293: def AddEditedElementDivergence(self, tagname, id, divergence_type): Laurent@814: element = self.GetEditedElement(tagname) Laurent@814: if element is not None: Laurent@1293: divergence = PLCOpenParser.CreateElement( Laurent@1293: {SELECTION_DIVERGENCE: "selectionDivergence", Laurent@1293: SELECTION_CONVERGENCE: "selectionConvergence", Laurent@1293: SIMULTANEOUS_DIVERGENCE: "simultaneousDivergence", Laurent@1293: SIMULTANEOUS_CONVERGENCE: "simultaneousConvergence"}.get( andrej@1878: divergence_type), "sfcObjects") Laurent@814: divergence.setlocalId(id) Laurent@1293: element.addinstance(divergence) Edouard@1411: Laurent@1293: DivergenceTypes = [ Edouard@1411: (divergence_type, Laurent@1293: PLCOpenParser.GetElementClass(divergence_type, "sfcObjects")) Laurent@1293: for divergence_type in ["selectionDivergence", "simultaneousDivergence", Laurent@1293: "selectionConvergence", "simultaneousConvergence"]] Edouard@1411: Laurent@1293: def GetDivergenceType(self, divergence): Laurent@1293: for divergence_type, divergence_class in self.DivergenceTypes: Laurent@1293: if isinstance(divergence, divergence_class): Laurent@1293: return divergence_type Laurent@1293: return None Edouard@1411: Laurent@814: def SetEditedElementDivergenceInfos(self, tagname, id, infos): Laurent@814: element = self.GetEditedElement(tagname) Laurent@814: if element is not None: Laurent@814: divergence = element.getinstance(id) Laurent@814: if divergence is None: Laurent@814: return kinsamanka@3750: for param, value in list(infos.items()): Laurent@814: if param == "height": Laurent@814: divergence.setheight(value) Laurent@814: elif param == "width": Laurent@814: divergence.setwidth(value) Laurent@814: elif param == "x": Laurent@814: divergence.setx(value) Laurent@814: elif param == "y": Laurent@814: divergence.sety(value) Laurent@814: elif param == "connectors": Laurent@814: input_connectors = value["inputs"] Laurent@1293: divergence_type = self.GetDivergenceType(divergence) Laurent@1293: if divergence_type in ["selectionDivergence", "simultaneousDivergence"]: Laurent@814: position = input_connectors[0].GetRelPosition() Laurent@814: divergence.addconnectionPointIn() Laurent@814: divergence.connectionPointIn.setrelPositionXY(position.x, position.y) Laurent@814: self.SetConnectionWires(divergence.connectionPointIn, input_connectors[0]) Laurent@814: else: Laurent@814: divergence.setconnectionPointIn([]) Laurent@814: for input_connector in input_connectors: Laurent@814: position = input_connector.GetRelPosition() Laurent@1293: connection = PLCOpenParser.CreateElement("connectionPointIn", divergence_type) Laurent@1293: divergence.appendconnectionPointIn(connection) Laurent@814: connection.setrelPositionXY(position.x, position.y) Laurent@814: self.SetConnectionWires(connection, input_connector) Laurent@814: output_connectors = value["outputs"] Laurent@1293: if divergence_type in ["selectionConvergence", "simultaneousConvergence"]: Laurent@814: position = output_connectors[0].GetRelPosition() Laurent@814: divergence.addconnectionPointOut() Laurent@814: divergence.connectionPointOut.setrelPositionXY(position.x, position.y) Laurent@814: else: Laurent@814: divergence.setconnectionPointOut([]) Laurent@814: for output_connector in output_connectors: Laurent@814: position = output_connector.GetRelPosition() Laurent@1293: connection = PLCOpenParser.CreateElement("connectionPointOut", divergence_type) Laurent@1293: divergence.appendconnectionPointOut(connection) Laurent@814: connection.setrelPositionXY(position.x, position.y) Edouard@1411: Laurent@814: def AddEditedElementJump(self, tagname, id): Laurent@814: element = self.GetEditedElement(tagname) Laurent@814: if element is not None: Laurent@1293: jump = PLCOpenParser.CreateElement("jumpStep", "sfcObjects") Laurent@814: jump.setlocalId(id) Laurent@1293: element.addinstance(jump) Edouard@1411: Laurent@814: def SetEditedElementJumpInfos(self, tagname, id, infos): Laurent@814: element = self.GetEditedElement(tagname) Laurent@814: if element is not None: Laurent@814: jump = element.getinstance(id) Laurent@814: if jump is None: Laurent@814: return kinsamanka@3750: for param, value in list(infos.items()): Laurent@814: if param == "target": Laurent@814: jump.settargetName(value) Laurent@814: elif param == "height": Laurent@814: jump.setheight(value) Laurent@814: elif param == "width": Laurent@814: jump.setwidth(value) Laurent@814: elif param == "x": Laurent@814: jump.setx(value) Laurent@814: elif param == "y": Laurent@814: jump.sety(value) Laurent@814: elif param == "connector": Laurent@814: position = value.GetRelPosition() Laurent@814: jump.addconnectionPointIn() Laurent@814: jump.connectionPointIn.setrelPositionXY(position.x, position.y) Laurent@814: self.SetConnectionWires(jump.connectionPointIn, value) Edouard@1411: Laurent@814: def AddEditedElementActionBlock(self, tagname, id): Laurent@814: element = self.GetEditedElement(tagname) Laurent@814: if element is not None: Laurent@1293: actionBlock = PLCOpenParser.CreateElement("actionBlock", "commonObjects") Laurent@814: actionBlock.setlocalId(id) Laurent@1293: element.addinstance(actionBlock) Edouard@1411: Laurent@814: def SetEditedElementActionBlockInfos(self, tagname, id, infos): Laurent@814: element = self.GetEditedElement(tagname) Laurent@814: if element is not None: Laurent@814: actionBlock = element.getinstance(id) Laurent@814: if actionBlock is None: Laurent@814: return kinsamanka@3750: for param, value in list(infos.items()): Laurent@814: if param == "actions": Laurent@814: actionBlock.setactions(value) Laurent@814: elif param == "height": Laurent@814: actionBlock.setheight(value) Laurent@814: elif param == "width": Laurent@814: actionBlock.setwidth(value) Laurent@814: elif param == "x": Laurent@814: actionBlock.setx(value) Laurent@814: elif param == "y": Laurent@814: actionBlock.sety(value) Laurent@814: elif param == "connector": Laurent@814: position = value.GetRelPosition() Laurent@814: actionBlock.addconnectionPointIn() Laurent@814: actionBlock.connectionPointIn.setrelPositionXY(position.x, position.y) Laurent@814: self.SetConnectionWires(actionBlock.connectionPointIn, value) Edouard@1411: Laurent@814: def RemoveEditedElementInstance(self, tagname, id): Laurent@814: element = self.GetEditedElement(tagname) Laurent@814: if element is not None: Laurent@814: instance = element.getinstance(id) Laurent@1293: if isinstance(instance, PLCOpenParser.GetElementClass("block", "fbdObjects")): Laurent@814: self.RemoveEditedElementPouVar(tagname, instance.gettypeName(), instance.getinstanceName()) Laurent@814: element.removeinstance(id) Laurent@814: andrej@1744: def GetEditedResourceVariables(self, tagname, debug=False): Laurent@814: varlist = [] Laurent@814: words = tagname.split("::") Laurent@814: for var in self.GetConfigurationGlobalVars(words[1], debug): Laurent@1361: if var.Type == "BOOL": Laurent@1361: varlist.append(var.Name) Laurent@814: for var in self.GetConfigurationResourceGlobalVars(words[1], words[2], debug): Laurent@1361: if var.Type == "BOOL": Laurent@1361: varlist.append(var.Name) Laurent@814: return varlist Laurent@814: Laurent@814: def SetEditedResourceInfos(self, tagname, tasks, instances): Laurent@814: resource = self.GetEditedElement(tagname) Laurent@814: if resource is not None: Laurent@814: resource.settask([]) Laurent@814: resource.setpouInstance([]) Laurent@814: task_list = {} Laurent@814: for task in tasks: Laurent@1294: new_task = PLCOpenParser.CreateElement("task", "resource") Laurent@1294: resource.appendtask(new_task) Laurent@814: new_task.setname(task["Name"]) Laurent@814: if task["Triggering"] == "Interrupt": Laurent@814: new_task.setsingle(task["Single"]) andrej@1753: # result = duration_model.match(task["Interval"]).groups() andrej@1753: # if reduce(lambda x, y: x or y != None, result): andrej@1753: # values = [] andrej@1753: # for value in result[:-1]: andrej@1753: # if value != None: andrej@1753: # values.append(int(value)) andrej@1753: # else: andrej@1753: # values.append(0) andrej@1753: # if result[-1] is not None: andrej@1753: # values.append(int(float(result[-1]) * 1000)) andrej@1753: # new_task.setinterval(datetime.time(*values)) Laurent@814: if task["Triggering"] == "Cyclic": Laurent@814: new_task.setinterval(task["Interval"]) Laurent@814: new_task.setpriority(int(task["Priority"])) Laurent@814: if task["Name"] != "": Laurent@814: task_list[task["Name"]] = new_task Laurent@814: for instance in instances: Laurent@1294: task = task_list.get(instance["Task"]) Laurent@1294: if task is not None: Laurent@1294: new_instance = PLCOpenParser.CreateElement("pouInstance", "task") Laurent@1294: task.appendpouInstance(new_instance) Laurent@1294: else: Laurent@1294: new_instance = PLCOpenParser.CreateElement("pouInstance", "resource") Laurent@1294: resource.appendpouInstance(new_instance) Laurent@814: new_instance.setname(instance["Name"]) Laurent@814: new_instance.settypeName(instance["Type"]) Laurent@814: andrej@1744: def GetEditedResourceInfos(self, tagname, debug=False): Laurent@814: resource = self.GetEditedElement(tagname, debug) Laurent@814: if resource is not None: Laurent@814: tasks = resource.gettask() Laurent@814: instances = resource.getpouInstance() Laurent@814: tasks_data = [] Laurent@814: instances_data = [] Laurent@814: for task in tasks: Laurent@814: new_task = {} Laurent@814: new_task["Name"] = task.getname() Laurent@814: single = task.getsingle() Laurent@814: if single is not None: Laurent@814: new_task["Single"] = single Laurent@814: else: Laurent@814: new_task["Single"] = "" Laurent@814: interval = task.getinterval() Laurent@814: if interval is not None: andrej@1779: # text = "" andrej@1779: # if interval.hour != 0: andrej@1779: # text += "%dh"%interval.hour andrej@1779: # if interval.minute != 0: andrej@1779: # text += "%dm"%interval.minute andrej@1779: # if interval.second != 0: andrej@1779: # text += "%ds"%interval.second andrej@1779: # if interval.microsecond != 0: andrej@1779: # if interval.microsecond % 1000 != 0: andrej@1779: # text += "%.3fms"%(float(interval.microsecond) / 1000) andrej@1779: # else: andrej@1779: # text += "%dms"%(interval.microsecond / 1000) andrej@1779: # new_task["Interval"] = text Laurent@814: new_task["Interval"] = interval Laurent@814: else: Laurent@814: new_task["Interval"] = "" Laurent@814: if single is not None and interval is None: Laurent@814: new_task["Triggering"] = "Interrupt" Laurent@814: elif interval is not None and single is None: Laurent@814: new_task["Triggering"] = "Cyclic" Laurent@814: else: Laurent@814: new_task["Triggering"] = "" Laurent@814: new_task["Priority"] = str(task.getpriority()) Laurent@814: tasks_data.append(new_task) Laurent@814: for instance in task.getpouInstance(): Laurent@814: new_instance = {} Laurent@814: new_instance["Name"] = instance.getname() Laurent@814: new_instance["Type"] = instance.gettypeName() Laurent@814: new_instance["Task"] = task.getname() Laurent@814: instances_data.append(new_instance) Laurent@814: for instance in instances: Laurent@814: new_instance = {} Laurent@814: new_instance["Name"] = instance.getname() Laurent@814: new_instance["Type"] = instance.gettypeName() Laurent@814: new_instance["Task"] = "" Laurent@814: instances_data.append(new_instance) Laurent@814: return tasks_data, instances_data Laurent@814: Laurent@814: def OpenXMLFile(self, filepath): Laurent@1330: self.Project, error = LoadProject(filepath) Laurent@1330: if self.Project is None: Laurent@1330: return _("Project file syntax error:\n\n") + error Laurent@1290: self.SetFilePath(filepath) Laurent@1290: self.CreateProjectBuffer(True) Laurent@1290: self.ProgramChunks = [] Laurent@1290: self.ProgramOffset = 0 Laurent@1299: self.NextCompiledProject = self.Copy(self.Project) Laurent@1290: self.CurrentCompiledProject = None Laurent@1290: self.Buffering = False Laurent@1290: self.CurrentElementEditing = None Laurent@1330: return error Edouard@1411: andrej@1744: def SaveXMLFile(self, filepath=None): Laurent@814: if not filepath and self.FilePath == "": Laurent@814: return False Laurent@814: else: Laurent@814: contentheader = {"modificationDateTime": datetime.datetime(*localtime()[:6])} Laurent@814: self.Project.setcontentHeader(contentheader) Edouard@1411: Laurent@1290: if filepath: Laurent@1290: SaveProject(self.Project, filepath) Laurent@1290: else: Laurent@1290: SaveProject(self.Project, self.FilePath) Edouard@1411: Laurent@814: self.MarkProjectAsSaved() Laurent@814: if filepath: Laurent@814: self.SetFilePath(filepath) Laurent@814: return True Laurent@814: andrej@1782: # ------------------------------------------------------------------------------- andrej@1782: # Search in Current Project Functions andrej@1782: # ------------------------------------------------------------------------------- Laurent@814: Laurent@814: def SearchInProject(self, criteria): Edouard@2551: project_matches = self.Project.Search(criteria) Edouard@2551: ctn_matches = self.CTNSearch(criteria) Edouard@2523: return project_matches + ctn_matches Laurent@814: Laurent@814: def SearchInPou(self, tagname, criteria, debug=False): Laurent@814: pou = self.GetEditedElement(tagname, debug) Laurent@814: if pou is not None: surkovsv93@1619: search_results = pou.Search(criteria, [tagname]) surkovsv93@1619: if tagname.split("::")[0] in ['A', 'T']: surkovsv93@1619: parent_pou_tagname = "P::%s" % (tagname.split("::")[-2]) surkovsv93@1619: parent_pou = self.GetEditedElement(parent_pou_tagname, debug) surkovsv93@1619: for infos, start, end, text in parent_pou.Search(criteria): surkovsv93@1619: if infos[1] in ["var_local", "var_input", "var_output", "var_inout"]: surkovsv93@1619: search_results.append((infos, start, end, text)) surkovsv93@1619: return search_results Laurent@814: return [] Laurent@814: andrej@1782: # ------------------------------------------------------------------------------- andrej@1782: # Current Buffering Management Functions andrej@1782: # ------------------------------------------------------------------------------- andrej@1782: Laurent@814: def Copy(self, model): andrej@1782: """Return a copy of the project""" Laurent@1299: return deepcopy(model) Laurent@814: Laurent@814: def CreateProjectBuffer(self, saved): Laurent@814: if self.ProjectBufferEnabled: Laurent@1304: self.ProjectBuffer = UndoBuffer(PLCOpenParser.Dumps(self.Project), saved) Laurent@814: else: Laurent@814: self.ProjectBuffer = None Laurent@814: self.ProjectSaved = saved Laurent@814: Laurent@814: def IsProjectBufferEnabled(self): Laurent@814: return self.ProjectBufferEnabled Laurent@814: Laurent@814: def EnableProjectBuffer(self, enable): Laurent@814: self.ProjectBufferEnabled = enable Laurent@814: if self.Project is not None: Laurent@814: if enable: Laurent@814: current_saved = self.ProjectSaved Laurent@814: else: Laurent@814: current_saved = self.ProjectBuffer.IsCurrentSaved() Laurent@814: self.CreateProjectBuffer(current_saved) Laurent@814: Laurent@814: def BufferProject(self): Laurent@814: if self.ProjectBuffer is not None: Laurent@1304: self.ProjectBuffer.Buffering(PLCOpenParser.Dumps(self.Project)) Laurent@814: else: Laurent@814: self.ProjectSaved = False Laurent@814: Laurent@814: def StartBuffering(self): Laurent@814: if self.ProjectBuffer is not None: Laurent@814: self.Buffering = True Laurent@814: else: Laurent@814: self.ProjectSaved = False Edouard@1411: Laurent@814: def EndBuffering(self): Laurent@814: if self.ProjectBuffer is not None and self.Buffering: Laurent@1304: self.ProjectBuffer.Buffering(PLCOpenParser.Dumps(self.Project)) Laurent@814: self.Buffering = False Laurent@814: Laurent@814: def MarkProjectAsSaved(self): Laurent@814: self.EndBuffering() Laurent@814: if self.ProjectBuffer is not None: Laurent@814: self.ProjectBuffer.CurrentSaved() Laurent@814: else: Laurent@814: self.ProjectSaved = True Edouard@1411: Laurent@814: # Return if project is saved Laurent@814: def ProjectIsSaved(self): Laurent@814: if self.ProjectBuffer is not None: Laurent@814: return self.ProjectBuffer.IsCurrentSaved() and not self.Buffering Laurent@814: else: Laurent@814: return self.ProjectSaved Laurent@814: Laurent@814: def LoadPrevious(self): Laurent@814: self.EndBuffering() Laurent@814: if self.ProjectBuffer is not None: Laurent@1304: self.Project = PLCOpenParser.Loads(self.ProjectBuffer.Previous()) Edouard@1411: Laurent@814: def LoadNext(self): Laurent@814: if self.ProjectBuffer is not None: Laurent@1304: self.Project = PLCOpenParser.Loads(self.ProjectBuffer.Next()) Edouard@1411: Laurent@814: def GetBufferState(self): Laurent@814: if self.ProjectBuffer is not None: Laurent@814: first = self.ProjectBuffer.IsFirst() and not self.Buffering Laurent@814: last = self.ProjectBuffer.IsLast() Laurent@814: return not first, not last Laurent@814: return False, False