Laurent@814: #!/usr/bin/env python Laurent@814: # -*- coding: utf-8 -*- Laurent@814: Laurent@814: #This file is part of PLCOpenEditor, a library implementing an IEC 61131-3 editor Laurent@814: #based on the plcopen standard. Laurent@814: # Laurent@814: #Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD Laurent@814: # Laurent@814: #See COPYING file for copyrights details. Laurent@814: # Laurent@814: #This library is free software; you can redistribute it and/or Laurent@814: #modify it under the terms of the GNU General Public Laurent@814: #License as published by the Free Software Foundation; either Laurent@814: #version 2.1 of the License, or (at your option) any later version. Laurent@814: # Laurent@814: #This library is distributed in the hope that it will be useful, Laurent@814: #but WITHOUT ANY WARRANTY; without even the implied warranty of Laurent@814: #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Laurent@814: #General Public License for more details. Laurent@814: # Laurent@814: #You should have received a copy of the GNU General Public Laurent@814: #License along with this library; if not, write to the Free Software Laurent@814: #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Laurent@814: Laurent@814: from xml.dom import minidom Laurent@814: from types import StringType, UnicodeType, TupleType Laurent@1308: from lxml import etree Laurent@1299: from copy import deepcopy Laurent@814: import os,sys,re Laurent@814: import datetime Laurent@814: from time import localtime Laurent@1338: from collections import OrderedDict, namedtuple Laurent@814: Laurent@1313: from plcopen import * Laurent@814: from graphics.GraphicCommons import * Laurent@814: from PLCGenerator import * Laurent@814: Laurent@814: duration_model = re.compile("(?:([0-9]{1,2})h)?(?:([0-9]{1,2})m(?!s))?(?:([0-9]{1,2})s)?(?:([0-9]{1,3}(?:\.[0-9]*)?)ms)?") Laurent@814: Laurent@814: ITEMS_EDITABLE = [ITEM_PROJECT, Laurent@814: ITEM_POU, Laurent@814: ITEM_VARIABLE, Laurent@814: ITEM_TRANSITION, Laurent@814: ITEM_ACTION, Laurent@814: ITEM_CONFIGURATION, Laurent@814: ITEM_RESOURCE, Laurent@814: ITEM_DATATYPE Laurent@814: ] = range(8) Laurent@814: Laurent@814: ITEMS_UNEDITABLE = [ITEM_DATATYPES, Laurent@814: ITEM_FUNCTION, Laurent@814: ITEM_FUNCTIONBLOCK, Laurent@814: ITEM_PROGRAM, Laurent@814: ITEM_TRANSITIONS, Laurent@814: ITEM_ACTIONS, Laurent@814: ITEM_CONFIGURATIONS, Laurent@814: ITEM_RESOURCES, Laurent@814: ITEM_PROPERTIES Laurent@814: ] = range(8, 17) Laurent@814: Laurent@814: ITEMS_VARIABLE = [ITEM_VAR_LOCAL, Laurent@814: ITEM_VAR_GLOBAL, Laurent@814: ITEM_VAR_EXTERNAL, Laurent@814: ITEM_VAR_TEMP, Laurent@814: ITEM_VAR_INPUT, Laurent@814: ITEM_VAR_OUTPUT, Laurent@814: ITEM_VAR_INOUT Laurent@814: ] = range(17, 24) Laurent@814: Laurent@1291: VAR_CLASS_INFOS = { Laurent@1291: "Local": ("localVars", ITEM_VAR_LOCAL), Laurent@1291: "Global": ("globalVars", ITEM_VAR_GLOBAL), Laurent@1291: "External": ("externalVars", ITEM_VAR_EXTERNAL), Laurent@1291: "Temp": ("tempVars", ITEM_VAR_TEMP), Laurent@1291: "Input": ("inputVars", ITEM_VAR_INPUT), Laurent@1291: "Output": ("outputVars", ITEM_VAR_OUTPUT), Laurent@1291: "InOut": ("inOutVars", ITEM_VAR_INOUT)} Laurent@814: Laurent@814: POU_TYPES = {"program": ITEM_PROGRAM, Laurent@814: "functionBlock": ITEM_FUNCTIONBLOCK, Laurent@814: "function": ITEM_FUNCTION, Laurent@814: } Laurent@814: Laurent@814: LOCATIONS_ITEMS = [LOCATION_CONFNODE, Laurent@814: LOCATION_MODULE, Laurent@814: LOCATION_GROUP, Laurent@814: LOCATION_VAR_INPUT, Laurent@814: LOCATION_VAR_OUTPUT, Laurent@814: LOCATION_VAR_MEMORY] = range(6) Laurent@814: Laurent@814: ScriptDirectory = os.path.split(os.path.realpath(__file__))[0] Laurent@814: Laurent@814: def GetUneditableNames(): Laurent@814: _ = lambda x:x Laurent@814: return [_("User-defined POUs"), _("Functions"), _("Function Blocks"), Laurent@814: _("Programs"), _("Data Types"), _("Transitions"), _("Actions"), Laurent@814: _("Configurations"), _("Resources"), _("Properties")] Laurent@814: UNEDITABLE_NAMES = GetUneditableNames() Laurent@814: [USER_DEFINED_POUS, FUNCTIONS, FUNCTION_BLOCKS, PROGRAMS, Laurent@814: DATA_TYPES, TRANSITIONS, ACTIONS, CONFIGURATIONS, Laurent@814: RESOURCES, PROPERTIES] = UNEDITABLE_NAMES Laurent@814: Laurent@814: #------------------------------------------------------------------------------- Laurent@1347: # Helper object for loading library in xslt stylesheets Laurent@1347: #------------------------------------------------------------------------------- Laurent@1347: Laurent@1347: class LibraryResolver(etree.Resolver): Laurent@1347: Laurent@1347: def __init__(self, controller, debug=False): Laurent@1347: self.Controller = controller Laurent@1347: self.Debug = debug Laurent@1347: Laurent@1347: def resolve(self, url, pubid, context): Laurent@1347: lib_name = os.path.basename(url) Laurent@1347: if lib_name in ["project", "stdlib", "extensions"]: Laurent@1347: lib_el = etree.Element(lib_name) Laurent@1347: if lib_name == "project": Laurent@1347: lib_el.append(deepcopy(self.Controller.GetProject(self.Debug))) Laurent@1347: elif lib_name == "stdlib": Edouard@1390: for lib in StdBlckLibs.values(): Laurent@1347: lib_el.append(deepcopy(lib)) Laurent@1347: else: Laurent@1347: for ctn in self.Controller.ConfNodeTypes: Laurent@1347: lib_el.append(deepcopy(ctn["types"])) Laurent@1347: return self.resolve_string(etree.tostring(lib_el), context) Laurent@1347: Laurent@1347: #------------------------------------------------------------------------------- Laurent@1347: # Helpers functions for translating list of arguments Laurent@1347: # from xslt to valid arguments Laurent@1347: #------------------------------------------------------------------------------- Laurent@1347: Laurent@1378: _StringValue = lambda x: x Laurent@1347: _BoolValue = lambda x: x in ["true", "0"] Laurent@1347: Laurent@1347: def _translate_args(translations, args): Laurent@1347: return [translate(arg[0]) if len(arg) > 0 else None Laurent@1347: for translate, arg in Laurent@1347: zip(translations, args)] Laurent@1347: Laurent@1347: #------------------------------------------------------------------------------- Laurent@1308: # Helpers object for generating pou var list Laurent@1308: #------------------------------------------------------------------------------- Laurent@1308: Laurent@1347: class _VariableInfos(object): Laurent@1347: __slots__ = ["Name", "Class", "Option", "Location", "InitialValue", Laurent@1347: "Edit", "Documentation", "Type", "Tree", "Number"] Laurent@1347: def __init__(self, *args): Laurent@1347: for attr, value in zip(self.__slots__, args): Laurent@1347: setattr(self, attr, value if value is not None else "") Laurent@1347: def copy(self): Laurent@1347: return _VariableInfos(*[getattr(self, attr) for attr in self.__slots__]) Laurent@1347: Laurent@1347: class VariablesInfosFactory: Laurent@1308: Laurent@1308: def __init__(self, variables): Laurent@1308: self.Variables = variables Laurent@1347: self.TreeStack = [] Laurent@1347: self.Type = None Laurent@1347: self.Dimensions = None Laurent@1347: Laurent@1347: def SetType(self, context, *args): Laurent@1347: self.Type = args[0][0] Laurent@1347: Laurent@1347: def GetType(self): Laurent@1347: if len(self.Dimensions) > 0: Laurent@1347: return ("array", self.Type, self.Dimensions) Laurent@1347: return self.Type Laurent@1347: Laurent@1347: def GetTree(self): Laurent@1347: return (self.TreeStack.pop(-1), self.Dimensions) Laurent@1347: Laurent@1347: def AddDimension(self, context, *args): Laurent@1347: self.Dimensions.append(tuple( Laurent@1378: _translate_args([_StringValue] * 2, args))) Laurent@1347: Laurent@1347: def AddTree(self, context, *args): Laurent@1347: self.TreeStack.append([]) Laurent@1347: self.Dimensions = [] Laurent@1347: Laurent@1347: def AddVarToTree(self, context, *args): Laurent@1347: var = (args[0][0], self.Type, self.GetTree()) Laurent@1347: self.TreeStack[-1].append(var) Laurent@1347: Laurent@1347: def AddVariable(self, context, *args): Laurent@1347: self.Variables.append(_VariableInfos(*(_translate_args( Laurent@1378: [_StringValue] * 5 + [_BoolValue] + [_StringValue], args) + Laurent@1347: [self.GetType(), self.GetTree()]))) Laurent@1308: Laurent@1308: #------------------------------------------------------------------------------- Laurent@1316: # Helpers object for generating pou variable instance list Laurent@1316: #------------------------------------------------------------------------------- Laurent@1316: Laurent@1348: def class_extraction(value): Laurent@1348: class_type = { Laurent@1316: "configuration": ITEM_CONFIGURATION, Laurent@1316: "resource": ITEM_RESOURCE, Laurent@1316: "action": ITEM_ACTION, Laurent@1316: "transition": ITEM_TRANSITION, Laurent@1348: "program": ITEM_PROGRAM}.get(value) Laurent@1348: if class_type is not None: Laurent@1348: return class_type Laurent@1348: Laurent@1348: pou_type = POU_TYPES.get(value) Laurent@1348: if pou_type is not None: Laurent@1348: return pou_type Laurent@1348: Laurent@1348: var_type = VAR_CLASS_INFOS.get(value) Laurent@1348: if var_type is not None: Laurent@1348: return var_type[1] Laurent@1348: Laurent@1348: return None Laurent@1348: Laurent@1348: class _VariablesTreeItemInfos(object): Laurent@1348: __slots__ = ["name", "var_class", "type", "edit", "debug", "variables"] Laurent@1348: def __init__(self, *args): Laurent@1348: for attr, value in zip(self.__slots__, args): Laurent@1348: setattr(self, attr, value if value is not None else "") Laurent@1348: def copy(self): Laurent@1348: return _VariableTreeItem(*[getattr(self, attr) for attr in self.__slots__]) Laurent@1348: Laurent@1348: class VariablesTreeInfosFactory: Laurent@1348: Laurent@1348: def __init__(self): Laurent@1348: self.Root = None Laurent@1348: Laurent@1348: def GetRoot(self): Laurent@1348: return self.Root Laurent@1348: Laurent@1348: def SetRoot(self, context, *args): Laurent@1348: self.Root = _VariablesTreeItemInfos( Laurent@1348: *([''] + _translate_args( Laurent@1378: [class_extraction, _StringValue] + [_BoolValue] * 2, Laurent@1348: args) + [[]])) Laurent@1348: Laurent@1348: def AddVariable(self, context, *args): Laurent@1348: if self.Root is not None: Laurent@1348: self.Root.variables.append(_VariablesTreeItemInfos( Laurent@1348: *(_translate_args( Laurent@1378: [_StringValue, class_extraction, _StringValue] + Laurent@1378: [_BoolValue] * 2, args) + [[]]))) Laurent@1316: Laurent@1316: #------------------------------------------------------------------------------- Laurent@1319: # Helpers object for generating instances path list Laurent@1319: #------------------------------------------------------------------------------- Laurent@1319: Laurent@1350: class InstancesPathFactory: Laurent@1350: Laurent@1350: def __init__(self, instances): Laurent@1350: self.Instances = instances Laurent@1350: Laurent@1350: def AddInstance(self, context, *args): Laurent@1350: self.Instances.append(args[0][0]) Laurent@1319: Laurent@1319: #------------------------------------------------------------------------------- Laurent@1321: # Helpers object for generating instance tagname Laurent@1321: #------------------------------------------------------------------------------- Laurent@1321: Laurent@1351: class InstanceTagName: Laurent@1321: Laurent@1321: def __init__(self, controller): Laurent@1321: self.Controller = controller Laurent@1351: self.TagName = None Laurent@1351: Laurent@1351: def GetTagName(self): Laurent@1351: return self.TagName Laurent@1351: Laurent@1351: def ConfigTagName(self, context, *args): Laurent@1351: self.TagName = self.Controller.ComputeConfigurationName(args[0][0]) Laurent@1351: Laurent@1351: def ResourceTagName(self, context, *args): Laurent@1351: self.TagName = self.Controller.ComputeConfigurationResourceName(args[0][0], args[1][0]) Laurent@1351: Laurent@1351: def PouTagName(self, context, *args): Laurent@1351: self.TagName = self.Controller.ComputePouName(args[0][0]) Laurent@1351: Laurent@1351: def ActionTagName(self, context, *args): Laurent@1351: self.TagName = self.Controller.ComputePouActionName(args[0][0], args[0][1]) Laurent@1351: Laurent@1351: def TransitionTagName(self, context, *args): Laurent@1351: self.TagName = self.Controller.ComputePouTransitionName(args[0][0], args[0][1]) Laurent@1321: Laurent@1321: #------------------------------------------------------------------------------- Laurent@1338: # Helpers object for generating pou block instances list Laurent@1338: #------------------------------------------------------------------------------- Laurent@1338: Laurent@1338: _Point = namedtuple("Point", ["x", "y"]) Laurent@1338: Laurent@1338: _BlockInstanceInfos = namedtuple("BlockInstanceInfos", Laurent@1338: ["type", "id", "x", "y", "width", "height", "specific_values", "inputs", "outputs"]) Laurent@1338: Laurent@1338: _BlockSpecificValues = ( Laurent@1338: namedtuple("BlockSpecificValues", Laurent@1338: ["name", "execution_order"]), Laurent@1378: [_StringValue, int]) Laurent@1338: _VariableSpecificValues = ( Laurent@1338: namedtuple("VariableSpecificValues", Laurent@1338: ["name", "value_type", "execution_order"]), Laurent@1378: [_StringValue, _StringValue, int]) Laurent@1338: _ConnectionSpecificValues = ( Laurent@1338: namedtuple("ConnectionSpecificValues", ["name"]), Laurent@1378: [_StringValue]) Laurent@1338: Laurent@1338: _PowerRailSpecificValues = ( Laurent@1338: namedtuple("PowerRailSpecificValues", ["connectors"]), Laurent@1338: [int]) Laurent@1338: Laurent@1338: _LDElementSpecificValues = ( Laurent@1338: namedtuple("LDElementSpecificValues", Laurent@1338: ["name", "negated", "edge", "storage", "execution_order"]), Laurent@1378: [_StringValue, _BoolValue, _StringValue, _StringValue, int]) Laurent@1338: Laurent@1338: _DivergenceSpecificValues = ( Laurent@1338: namedtuple("DivergenceSpecificValues", ["connectors"]), Laurent@1338: [int]) Laurent@1338: Laurent@1338: _SpecificValuesTuples = { Laurent@1338: "comment": ( Laurent@1338: namedtuple("CommentSpecificValues", ["content"]), Laurent@1378: [_StringValue]), Laurent@1338: "input": _VariableSpecificValues, Laurent@1338: "output": _VariableSpecificValues, Laurent@1338: "inout": _VariableSpecificValues, Laurent@1338: "connector": _ConnectionSpecificValues, Laurent@1338: "continuation": _ConnectionSpecificValues, Laurent@1338: "leftPowerRail": _PowerRailSpecificValues, Laurent@1338: "rightPowerRail": _PowerRailSpecificValues, Laurent@1338: "contact": _LDElementSpecificValues, Laurent@1338: "coil": _LDElementSpecificValues, Laurent@1338: "step": ( Laurent@1338: namedtuple("StepSpecificValues", ["name", "initial", "action"]), Laurent@1378: [_StringValue, _BoolValue, lambda x: x]), Laurent@1338: "transition": ( Laurent@1338: namedtuple("TransitionSpecificValues", Laurent@1338: ["priority", "condition_type", "condition", "connection"]), Laurent@1378: [int, _StringValue, _StringValue, lambda x: x]), Laurent@1338: "selectionDivergence": _DivergenceSpecificValues, Laurent@1338: "selectionConvergence": _DivergenceSpecificValues, Laurent@1338: "simultaneousDivergence": _DivergenceSpecificValues, Laurent@1338: "simultaneousConvergence": _DivergenceSpecificValues, Laurent@1338: "jump": ( Laurent@1338: namedtuple("JumpSpecificValues", ["target"]), Laurent@1378: [_StringValue]), Laurent@1338: "actionBlock": ( Laurent@1338: namedtuple("ActionBlockSpecificValues", ["actions"]), Laurent@1338: [lambda x: x]), Laurent@1338: } Laurent@1338: Laurent@1338: _InstanceConnectionInfos = namedtuple("InstanceConnectionInfos", Laurent@1338: ["name", "negated", "edge", "position", "links"]) Laurent@1338: Laurent@1338: _ConnectionLinkInfos = namedtuple("ConnectionLinkInfos", Laurent@1338: ["refLocalId", "formalParameter", "points"]) Laurent@1338: Laurent@1341: class _ActionInfos(object): Laurent@1339: __slots__ = ["qualifier", "type", "value", "duration", "indicator"] Laurent@1339: def __init__(self, *args): Laurent@1339: for attr, value in zip(self.__slots__, args): Laurent@1339: setattr(self, attr, value if value is not None else "") Laurent@1339: def copy(self): Laurent@1339: return _ActionInfos(*[getattr(self, attr) for attr in self.__slots__]) Laurent@1338: Laurent@1338: class BlockInstanceFactory: Laurent@1338: Laurent@1338: def __init__(self, block_instances): Laurent@1338: self.BlockInstances = block_instances Laurent@1338: self.CurrentInstance = None Laurent@1338: self.SpecificValues = None Laurent@1338: self.CurrentConnection = None Laurent@1338: self.CurrentLink = None Laurent@1338: Laurent@1338: def SetSpecificValues(self, context, *args): Laurent@1338: self.SpecificValues = list(args) Laurent@1338: self.CurrentInstance = None Laurent@1338: self.CurrentConnection = None Laurent@1338: self.CurrentLink = None Laurent@1338: Laurent@1338: def AddBlockInstance(self, context, *args): Laurent@1338: specific_values_tuple, specific_values_translation = \ Laurent@1338: _SpecificValuesTuples.get(args[0][0], _BlockSpecificValues) Laurent@1338: Laurent@1338: if (args[0][0] == "step" and len(self.SpecificValues) < 3 or Laurent@1338: args[0][0] == "transition" and len(self.SpecificValues) < 4): Laurent@1338: self.SpecificValues.append([None]) Laurent@1338: elif args[0][0] == "actionBlock" and len(self.SpecificValues) < 1: Laurent@1338: self.SpecificValues.append([[]]) Laurent@1338: specific_values = specific_values_tuple(*_translate_args( Laurent@1338: specific_values_translation, self.SpecificValues)) Laurent@1338: self.SpecificValues = None Laurent@1338: Laurent@1338: self.CurrentInstance = _BlockInstanceInfos( Laurent@1378: *(_translate_args([_StringValue, int] + [float] * 4, args) + Laurent@1338: [specific_values, [], []])) Laurent@1338: Laurent@1338: self.BlockInstances[self.CurrentInstance.id] = self.CurrentInstance Laurent@1338: Laurent@1338: def AddInstanceConnection(self, context, *args): Laurent@1338: connection_args = _translate_args( Laurent@1378: [_StringValue] * 2 + [_BoolValue, _StringValue] + [float] * 2, args) Laurent@1338: Laurent@1338: self.CurrentConnection = _InstanceConnectionInfos( Laurent@1338: *(connection_args[1:4] + [ Laurent@1338: _Point(*connection_args[4:6]), []])) Laurent@1338: Laurent@1338: if self.CurrentInstance is not None: Laurent@1338: if connection_args[0] == "input": Laurent@1338: self.CurrentInstance.inputs.append(self.CurrentConnection) Laurent@1338: else: Laurent@1338: self.CurrentInstance.outputs.append(self.CurrentConnection) Laurent@1338: else: Laurent@1338: self.SpecificValues.append([self.CurrentConnection]) Laurent@1338: Laurent@1338: def AddConnectionLink(self, context, *args): Laurent@1338: self.CurrentLink = _ConnectionLinkInfos( Laurent@1378: *(_translate_args([int, _StringValue], args) + [[]])) Laurent@1338: self.CurrentConnection.links.append(self.CurrentLink) Laurent@1338: Laurent@1338: def AddLinkPoint(self, context, *args): Laurent@1338: self.CurrentLink.points.append(_Point( Laurent@1373: *_translate_args([float] * 2, args))) Laurent@1338: Laurent@1338: def AddAction(self, context, *args): Laurent@1338: if len(self.SpecificValues) == 0: Laurent@1338: self.SpecificValues.append([[]]) Laurent@1378: translated_args = _translate_args([_StringValue] * 5, args) Laurent@1338: self.SpecificValues[0][0].append(_ActionInfos(*translated_args)) Laurent@1338: Laurent@1338: pou_block_instances_xslt = etree.parse( Laurent@1338: os.path.join(ScriptDirectory, "plcopen", "pou_block_instances.xslt")) Laurent@1338: Laurent@1338: #------------------------------------------------------------------------------- Laurent@814: # Undo Buffer for PLCOpenEditor Laurent@814: #------------------------------------------------------------------------------- Laurent@814: Laurent@814: # Length of the buffer Laurent@814: UNDO_BUFFER_LENGTH = 20 Laurent@814: Laurent@814: """ Laurent@814: Class implementing a buffer of changes made on the current editing model Laurent@814: """ Laurent@814: class UndoBuffer: Laurent@814: Laurent@814: # Constructor initialising buffer Laurent@814: def __init__(self, currentstate, issaved = False): 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 Laurent@814: for i in xrange(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 Laurent@814: Laurent@814: # Add a new state in buffer Laurent@814: def Buffering(self, currentstate): 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) Laurent@814: Laurent@814: # Return current state of buffer Laurent@814: def Current(self): Laurent@814: return self.Buffer[self.CurrentIndex] Laurent@814: 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 Laurent@814: 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 Laurent@814: Laurent@814: # Return True if current state is the first in buffer Laurent@814: def IsFirst(self): Laurent@814: return self.CurrentIndex == self.MinIndex Laurent@814: 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 Laurent@814: 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: Laurent@814: #------------------------------------------------------------------------------- Laurent@814: # Controler for PLCOpenEditor Laurent@814: #------------------------------------------------------------------------------- Laurent@814: Laurent@814: """ Laurent@814: Class which controls the operations made on the plcopen model and answers to view requests Laurent@814: """ Laurent@814: class PLCControler: Laurent@814: Laurent@814: # Create a new PLCControler Laurent@814: def __init__(self): Laurent@814: self.LastNewIndex = 0 Laurent@814: self.Reset() Laurent@814: 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 = "" Laurent@1284: Laurent@814: def GetQualifierTypes(self): Laurent@1298: return QualifierList Laurent@814: Laurent@814: 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: Laurent@814: #------------------------------------------------------------------------------- Laurent@814: # Project management functions Laurent@814: #------------------------------------------------------------------------------- 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("") Laurent@1291: 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 Laurent@814: Laurent@814: # Return project data type names Laurent@814: 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 [] Laurent@814: Laurent@814: # Return project pou names Laurent@814: 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 [] Laurent@814: Laurent@814: # Return project pou names Laurent@814: 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 [] Laurent@814: Laurent@1171: # Return project pou variable names Laurent@1171: 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 Laurent@814: Laurent@814: # Return file path if project is an open file Laurent@814: def GetFilePath(self): Laurent@814: return self.FilePath Laurent@814: Laurent@814: # Return file path if project is an open file Laurent@814: def GetProgramFilePath(self): Laurent@814: return self.ProgramFilePath Laurent@814: 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: Laurent@814: return "~%s~"%self.FileName Laurent@814: return "" Laurent@814: 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 Laurent@814: self.FileName = _("Unnamed%d")%self.LastNewIndex Laurent@814: else: Laurent@814: self.FileName = os.path.splitext(os.path.basename(filepath))[0] Laurent@814: Laurent@814: # Change project properties Laurent@814: 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() Laurent@814: 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 Laurent@814: Laurent@814: # Return project properties Laurent@814: 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 Laurent@814: Laurent@814: # Return project informations Laurent@814: 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} Laurent@814: datatypes = {"name": DATA_TYPES, "type": ITEM_DATATYPES, "values":[]} Laurent@814: for datatype in project.getdataTypes(): Laurent@814: datatypes["values"].append({"name": datatype.getname(), "type": ITEM_DATATYPE, Laurent@814: "tagname": self.ComputeDataTypeName(datatype.getname()), "values": []}) Laurent@814: pou_types = {"function": {"name": FUNCTIONS, "type": ITEM_FUNCTION, "values":[]}, Laurent@814: "functionBlock": {"name": FUNCTION_BLOCKS, "type": ITEM_FUNCTIONBLOCK, "values":[]}, Laurent@814: "program": {"name": PROGRAMS, "type": ITEM_PROGRAM, "values":[]}} Laurent@814: for pou in project.getpous(): Laurent@814: pou_type = pou.getpouType() Laurent@814: pou_infos = {"name": pou.getname(), "type": ITEM_POU, Laurent@814: "tagname": self.ComputePouName(pou.getname())} Laurent@814: pou_values = [] Laurent@814: if pou.getbodyType() == "SFC": Laurent@814: transitions = [] Laurent@814: for transition in pou.gettransitionList(): Laurent@814: transitions.append({"name": transition.getname(), "type": ITEM_TRANSITION, Laurent@814: "tagname": self.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(): Laurent@814: actions.append({"name": action.getname(), "type": ITEM_ACTION, Laurent@814: "tagname": self.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() Laurent@814: config_infos = {"name": config_name, "type": ITEM_CONFIGURATION, Laurent@814: "tagname": self.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() Laurent@814: resource_infos = {"name": resource_name, "type": ITEM_RESOURCE, Laurent@814: "tagname": self.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) Laurent@814: 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: Laurent@814: def GetPouVariables(self, tagname, debug = False): Laurent@814: pou_type = None Laurent@814: project = self.GetProject(debug) Laurent@814: if project is not None: Laurent@1348: factory = VariablesTreeInfosFactory() Laurent@1348: Laurent@1348: parser = etree.XMLParser() Laurent@1348: parser.resolvers.add(LibraryResolver(self, debug)) Laurent@1348: Laurent@1316: pou_variable_xslt_tree = etree.XSLT( Laurent@1348: etree.parse( Laurent@1348: os.path.join(ScriptDirectory, "plcopen", "pou_variables.xslt"), Laurent@1348: parser), Laurent@1348: extensions = {("pou_vars_ns", name): getattr(factory, name) Laurent@1348: for name in ["SetRoot", "AddVariable"]}) Laurent@1319: 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: Laurent@1348: pou_variable_xslt_tree(obj) Laurent@1348: return factory.GetRoot() Laurent@1348: Laurent@1321: return None Laurent@1319: Laurent@1319: def GetInstanceList(self, root, name, debug = False): Laurent@1354: instances = [] Laurent@1354: project = self.GetProject(debug) Laurent@1354: if project is not None: Laurent@1350: factory = InstancesPathFactory(instances) Laurent@1350: Laurent@1350: parser = etree.XMLParser() Laurent@1350: parser.resolvers.add(LibraryResolver(self, debug)) Laurent@1350: Laurent@1319: instances_path_xslt_tree = etree.XSLT( Laurent@1350: etree.parse( Laurent@1350: os.path.join(ScriptDirectory, "plcopen", "instances_path.xslt"), Laurent@1350: parser), Laurent@1319: extensions = { Laurent@1350: ("instances_ns", "AddInstance"): factory.AddInstance}) Laurent@1319: Laurent@1350: instances_path_xslt_tree(root, Laurent@1350: instance_type=etree.XSLT.strparam(name)) Laurent@1350: Laurent@1354: return instances Laurent@1354: Laurent@1319: 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( laurent@826: self.ComputePouName(words[1]), debug)] Laurent@814: return [] Laurent@814: Laurent@814: def GetPouInstanceTagName(self, instance_path, debug = False): Laurent@1254: project = self.GetProject(debug) Laurent@1351: factory = InstanceTagName(self) Laurent@1351: Laurent@1351: parser = etree.XMLParser() Laurent@1351: parser.resolvers.add(LibraryResolver(self, debug)) Laurent@1321: Laurent@1321: instance_tagname_xslt_tree = etree.XSLT( Laurent@1351: etree.parse( Laurent@1351: os.path.join(ScriptDirectory, "plcopen", "instance_tagname.xslt"), Laurent@1351: parser), Laurent@1351: extensions = {("instance_tagname_ns", name): getattr(factory, name) Laurent@1351: for name in ["ConfigTagName", "ResourceTagName", Laurent@1351: "PouTagName", "ActionTagName", Laurent@1351: "TransitionTagName"]}) Laurent@1351: Laurent@1351: instance_tagname_xslt_tree(project, Laurent@1351: instance_path=etree.XSLT.strparam(instance_path)) Laurent@1351: Laurent@1351: return factory.GetTagName() Laurent@814: Laurent@814: 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 Laurent@814: Laurent@814: # Return if data type given by name is used by another data type or pou Laurent@814: 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 Laurent@814: 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 Laurent@814: 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: Laurent@814: def GenerateProgram(self, filepath=None): Laurent@814: errors = [] Laurent@814: warnings = [] Laurent@814: if self.Project is not None: Laurent@814: try: Laurent@814: self.ProgramChunks = GenerateCurrentProgram(self, self.Project, errors, warnings) 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: Laurent@814: programfile = open(filepath, "w") Laurent@814: programfile.write(program_text.encode("utf-8")) Laurent@814: programfile.close() Laurent@814: self.ProgramFilePath = filepath Laurent@814: return program_text, errors, warnings Laurent@814: except PLCGenException, e: Laurent@814: errors.append(e.message) 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 Laurent@814: Laurent@814: #------------------------------------------------------------------------------- Laurent@814: # Project Pous management functions Laurent@814: #------------------------------------------------------------------------------- Laurent@814: 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() Laurent@814: return self.ComputeDataTypeName(datatype_name) Laurent@814: return None Laurent@814: 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() Laurent@814: 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() Laurent@814: return self.ComputePouName(pou_name) Laurent@814: return None Laurent@814: 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: Laurent@814: pou.setpouType(pou_type) Laurent@814: self.BufferProject() Laurent@814: 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 Laurent@814: 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) Laurent@814: except: Laurent@1330: error = "" Laurent@1330: if error is not None: Laurent@814: return _("Couldn't paste non-POU object.") Laurent@1299: Laurent@1299: name = new_pou.getname() Laurent@1299: Laurent@1299: idx = 0 Laurent@1299: new_name = name Laurent@1299: while self.Project.getpou(new_name): 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) Laurent@814: Laurent@1299: # we've found a name that does not already exist, use it Laurent@1299: new_pou.setname(new_name) Laurent@1299: 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']: Laurent@1299: return _('''%s "%s" can't be pasted as a %s.''') % (orig_type, name, pou_type) Laurent@814: Laurent@1299: new_pou.setpouType(pou_type) Laurent@1299: Laurent@1299: self.Project.insertpou(-1, new_pou) Laurent@1299: self.BufferProject() Laurent@1299: Laurent@1299: return self.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() Laurent@814: 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 Laurent@814: 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() Laurent@814: return self.ComputeConfigurationName(config_name) Laurent@814: return None Laurent@814: 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() Laurent@814: 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() Laurent@814: return self.ComputeConfigurationResourceName(config_name, resource_name) Laurent@814: return None Laurent@814: 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() Laurent@814: 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() Laurent@814: return self.ComputePouTransitionName(pou_name, transition_name) Laurent@814: return None Laurent@814: 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() Laurent@814: 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() Laurent@814: return self.ComputePouActionName(pou_name, action_name) Laurent@814: return None Laurent@814: 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() Laurent@814: 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() Laurent@814: 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() Laurent@814: 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() Laurent@814: 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() Laurent@814: 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: Laurent@814: 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() Laurent@814: 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() Laurent@814: 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() Laurent@814: Laurent@814: # Return the description of the pou given by its name Laurent@814: 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 "" Laurent@814: Laurent@814: # Return the description of the pou given by its name Laurent@814: 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() Laurent@814: Laurent@814: # Return the type of the pou given by its name Laurent@814: 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 Laurent@814: Laurent@814: # Return pous with SFC language Laurent@814: 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 Laurent@814: Laurent@814: # Return the body language of the pou given by its name Laurent@814: 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 Laurent@814: Laurent@814: # Return the actions of a pou Laurent@814: 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 Laurent@814: Laurent@814: # Return the body language of the transition given by its name Laurent@814: 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 Laurent@814: Laurent@814: # Return the actions of a pou Laurent@814: 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 Laurent@814: Laurent@814: # Return the body language of the pou given by its name Laurent@814: 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 Laurent@814: 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: Laurent@1347: next_type = (var.Class, Laurent@1347: var.Option, Laurent@1347: var.Location in ["", None] or Laurent@814: # When declaring globals, located Laurent@814: # 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) Laurent@814: Laurent@1291: var_type = PLCOpenParser.CreateElement("type", "variable") Laurent@1347: if isinstance(var.Type, TupleType): Laurent@1347: if var.Type[0] == "array": Laurent@1347: 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 Laurent@814: Laurent@1347: def GetVariableDictionary(self, object_with_vars, tree=False, debug=False): Laurent@1308: variables = [] Laurent@1347: factory = VariablesInfosFactory(variables) Laurent@1347: Laurent@1347: parser = etree.XMLParser() Laurent@1368: parser.resolvers.add(LibraryResolver(self, debug)) Laurent@1291: Laurent@1308: variables_infos_xslt_tree = etree.XSLT( Laurent@1347: etree.parse( Laurent@1347: os.path.join(ScriptDirectory, "plcopen", "variables_infos.xslt"), Laurent@1347: parser), Laurent@1347: extensions = {("var_infos_ns", name): getattr(factory, name) Laurent@1347: for name in ["SetType", "AddDimension", "AddTree", Laurent@1347: "AddVarToTree", "AddVariable"]}) Laurent@1347: variables_infos_xslt_tree(object_with_vars, Laurent@1347: tree=etree.XSLT.strparam(str(tree))) Laurent@1293: Laurent@1308: return variables Laurent@1308: Laurent@1171: # Add a global var to configuration to configuration Laurent@1313: def AddConfigurationGlobalVar(self, config_name, var_type, var_name, Laurent@1171: 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( Laurent@1313: 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([ Laurent@1291: varlist for vartype, varlist Laurent@1291: in self.ExtractVarLists(vars)]) Laurent@814: Laurent@814: # Return the configuration globalvars Laurent@814: 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) Laurent@1308: Laurent@1308: return [] Laurent@814: Laurent@1171: # Return configuration variable names Laurent@1171: 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( Laurent@1171: lambda x, y: x + y, [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([ Laurent@1291: varlist for vartype, varlist Laurent@1291: in self.ExtractVarLists(vars)]) Laurent@814: Laurent@814: # Return the resource globalvars Laurent@814: 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) Laurent@1308: Laurent@1308: return [] Laurent@814: Laurent@1171: # Return resource variable names Laurent@1171: def GetConfigurationResourceVariableNames(self, Laurent@1171: 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( Laurent@1171: lambda x, y: x + y, [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 Laurent@1347: 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 Laurent@1291: pou.setvars([varlist for varlist_type, varlist in self.ExtractVarLists(vars)]) Laurent@1302: 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) Laurent@1291: return_type.setcontent(derived_type) Laurent@1302: 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) Laurent@814: 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) Laurent@814: 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: Laurent@1347: factory = VariablesInfosFactory([]) Laurent@1347: Laurent@1347: parser = etree.XMLParser() Laurent@1379: parser.resolvers.add(LibraryResolver(self)) Laurent@1347: Laurent@1308: return_type_infos_xslt_tree = etree.XSLT( Laurent@1347: etree.parse( Laurent@1347: os.path.join(ScriptDirectory, "plcopen", "variables_infos.xslt"), Laurent@1347: parser), Laurent@1347: extensions = {("var_infos_ns", name): getattr(factory, name) Laurent@1347: for name in ["SetType", "AddDimension", Laurent@1347: "AddTree", "AddVarToTree"]}) Laurent@1347: return_type_infos_xslt_tree(return_type, Laurent@1347: tree=etree.XSLT.strparam(str(tree))) Laurent@1347: if tree: Laurent@1347: return [factory.GetType(), factory.GetTree()] Laurent@1347: return factory.GetType() Laurent@1347: 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()]} Edouard@1283: for confnodetypes in typeslist] Edouard@1283: self.TotalTypes.extend(addedcat) Edouard@1283: for cat in addedcat: Edouard@1283: for desc in cat["list"]: Edouard@1283: BlkLst = self.TotalTypesDict.setdefault(desc["name"],[]) Edouard@1283: BlkLst.append((section["name"], desc)) Laurent@814: 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: Edouard@1283: def GetConfNodeDataTypes(self, exclude = None, only_locatables = False): Laurent@814: return [{"name": _("%s Data Types") % confnodetypes["name"], Laurent@1302: "list": [ Laurent@1302: datatype.getname() Laurent@1302: for datatype in confnodetypes["types"].getdataTypes() Laurent@1302: if not only_locatables or self.IsLocatableDataType(datatype, debug)]} Laurent@814: for confnodetypes in self.ConfNodeTypes] Laurent@814: 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 = [] Laurent@1096: for var_name, var_type, var_initial in self.GetConfNodeGlobalInstances(): Laurent@1291: tempvar = PLCOpenParser.CreateElement("variable", "globalVars") Laurent@883: tempvar.setname(var_name) Laurent@883: Laurent@1315: tempvartype = PLCOpenParser.CreateElement("type", "variable") Laurent@883: if var_type in self.GetBaseTypes(): Laurent@1315: tempvartype.setcontent(PLCOpenParser.CreateElement( Laurent@1291: var_type.lower() Laurent@1291: if var_type in ["STRING", "WSTRING"] Laurent@1291: else var_type, "dataType")) Laurent@883: else: Laurent@1291: tempderivedtype = PLCOpenParser.CreateElement("derived", "dataType") Laurent@883: tempderivedtype.setname(var_type) Laurent@1291: tempvartype.setcontent(tempderivedtype) Laurent@883: tempvar.settype(tempvartype) Laurent@883: Laurent@1096: if var_initial != "": Laurent@1291: value = PLCOpenParser.CreateElement("initialValue", "variable") Laurent@1096: value.setvalue(var_initial) Laurent@1096: tempvar.setinitialValue(value) Laurent@1096: Laurent@883: global_vars.append(tempvar) Laurent@883: return global_vars Laurent@883: Laurent@814: # Function that returns the block definition associated to the block type given Edouard@1283: def GetBlockType(self, typename, inputs = None, debug = False): Laurent@814: result_blocktype = None Edouard@1283: for sectioname, blocktype in self.TotalTypesDict.get(typename,[]): Edouard@1283: if inputs is not None and inputs != "undefined": Edouard@1283: block_inputs = tuple([var_type for name, var_type, modifier in blocktype["inputs"]]) Edouard@1283: if reduce(lambda x, y: x and y, map(lambda x: x[0] == "ANY" or self.IsOfType(*x), zip(inputs, block_inputs)), True): Edouard@1283: return blocktype Edouard@1283: else: Edouard@1283: if result_blocktype is not None: 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() Laurent@814: if result_blocktype is not None: 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 Laurent@1302: Laurent@1302: if inputs == tuple([var_type Laurent@1302: for name, var_type, modifier in blocktype_infos["inputs"]]): Laurent@1302: return blocktype_infos Laurent@1302: Laurent@814: return None Laurent@814: Laurent@814: # Return Block types checking for recursion Laurent@814: def GetBlockTypes(self, tagname = "", debug = False): Edouard@1283: typename = None 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 Laurent@814: if words[0] in ["P","T","A"]: Laurent@814: name = words[1] Laurent@1284: pou_type = self.GetPouType(name, debug) Laurent@1302: filter = (["function"] Laurent@1302: 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] Laurent@1284: blocktypes.append({"name" : USER_DEFINED_POUS, Laurent@1302: "list": [pou.getblockInfos() Laurent@1319: for pou in project.getpous(name, filter) Laurent@1319: if (name is None or Laurent@1372: len(self.GetInstanceList(pou, name, debug)) == 0)]}) Laurent@1284: return blocktypes Edouard@1283: return self.TotalTypes Laurent@814: Laurent@814: # Return Function Block types checking for recursion Laurent@814: def GetFunctionBlockTypes(self, tagname = "", debug = False): Laurent@1319: project = self.GetProject(debug) Laurent@1319: words = tagname.split("::") Laurent@1319: name = None Laurent@1319: if project is not None and words[0] in ["P","T","A"]: Laurent@1319: name = words[1] Laurent@814: blocktypes = [] Edouard@1283: for blocks in self.TotalTypesDict.itervalues(): Edouard@1283: for sectioname,block in blocks: Laurent@814: if block["type"] == "functionBlock": Laurent@814: blocktypes.append(block["name"]) Laurent@1319: if project is not None: Laurent@1302: blocktypes.extend([pou.getname() Laurent@1319: for pou in project.getpous(name, ["functionBlock"]) Laurent@1319: 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 Laurent@814: 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 Laurent@863: 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([ Laurent@1302: datatype.getname() Laurent@1302: for datatype in project.getdataTypes(name) Laurent@1319: if (not only_locatables or self.IsLocatableDataType(datatype, debug)) Laurent@1319: and (name is None or Laurent@1372: 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 Laurent@1308: 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 Edouard@1390: for standardlibrary in 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: Laurent@1308: # Return Data Type Object Laurent@1301: 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: return None Laurent@1301: Laurent@1301: # Return Base Type of given possible derived type Laurent@1301: def GetBaseType(self, typename, debug = False): Laurent@1301: if TypeHierarchy.has_key(typename): Laurent@1301: return typename Laurent@1301: 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 Laurent@1301: 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: ''' Laurent@814: return [x for x,y in TypeHierarchy_list if not x.startswith("ANY")] Laurent@814: Laurent@1301: def IsOfType(self, typename, reference, debug = False): Laurent@1301: if reference is None or typename == reference: Laurent@814: return True Laurent@1301: Laurent@1301: basetype = TypeHierarchy.get(typename) Laurent@1301: if basetype is not None: Laurent@1301: return self.IsOfType(basetype, reference) Laurent@1301: 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) Laurent@1301: Laurent@814: return False Laurent@814: Laurent@1301: def IsEndType(self, typename): Laurent@1301: if typename is not None: Laurent@1301: return not typename.startswith("ANY") Laurent@814: return True Laurent@814: Laurent@1302: def IsLocatableDataType(self, datatype, debug = False): Laurent@1302: basetype_content = datatype.baseType.getcontent() Laurent@1302: basetype_content_type = basetype_content.getLocalTag() Laurent@1302: if basetype_content_type in ["enum", "struct"]: 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 Laurent@1302: Laurent@1301: def IsLocatableType(self, typename, debug = False): Laurent@1302: if isinstance(typename, TupleType) or self.GetBlockType(typename) is not None: Laurent@884: return False Laurent@1301: Laurent@1301: datatype = self.GetDataType(typename, debug) Laurent@1301: if datatype is not None: Laurent@1302: return self.IsLocatableDataType(datatype) Laurent@814: return True Laurent@814: Laurent@1301: def IsEnumeratedType(self, typename, debug = False): Laurent@1306: if isinstance(typename, TupleType): 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: Laurent@1301: def IsSubrangeType(self, typename, exclude=None, debug = False): Laurent@1301: if typename == exclude: Laurent@1301: return False Laurent@1306: if isinstance(typename, TupleType): 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: Laurent@1301: def IsNumType(self, typename, debug = False): Laurent@1301: return self.IsOfType(typename, "ANY_NUM", debug) or\ Laurent@1301: self.IsOfType(typename, "ANY_BIT", debug) Laurent@887: Laurent@1301: 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 Laurent@1301: Laurent@1301: # Return Subrange types Laurent@1301: def GetSubrangeBaseTypes(self, exclude, debug = False): Laurent@1301: subrange_basetypes = 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 Laurent@1301: Laurent@1301: # Return Enumerated Values Laurent@1301: 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": Laurent@1301: 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: Laurent@814: #------------------------------------------------------------------------------- Laurent@814: # Project Element tag name computation functions Laurent@814: #------------------------------------------------------------------------------- Laurent@814: Laurent@814: # Compute a data type name Laurent@814: def ComputeDataTypeName(self, datatype): Laurent@814: return "D::%s" % datatype Laurent@814: Laurent@814: # Compute a pou name Laurent@814: def ComputePouName(self, pou): Laurent@814: return "P::%s" % pou Laurent@814: Laurent@814: # Compute a pou transition name Laurent@814: def ComputePouTransitionName(self, pou, transition): Laurent@814: return "T::%s::%s" % (pou, transition) Laurent@814: Laurent@814: # Compute a pou action name Laurent@814: def ComputePouActionName(self, pou, action): Laurent@814: return "A::%s::%s" % (pou, action) Laurent@814: Laurent@814: # Compute a pou name Laurent@814: def ComputeConfigurationName(self, config): Laurent@814: return "C::%s" % config Laurent@814: Laurent@814: # Compute a pou name Laurent@814: def ComputeConfigurationResourceName(self, config, resource): Laurent@814: return "R::%s::%s" % (config, resource) Laurent@814: Laurent@814: def GetElementType(self, tagname): Laurent@814: words = tagname.split("::") Laurent@814: return {"D" : ITEM_DATATYPE, "P" : ITEM_POU, Laurent@814: "T" : ITEM_TRANSITION, "A" : ITEM_ACTION, Laurent@814: "C" : ITEM_CONFIGURATION, "R" : ITEM_RESOURCE}[words[0]] Laurent@814: Laurent@814: #------------------------------------------------------------------------------- Laurent@814: # Project opened Data types management functions Laurent@814: #------------------------------------------------------------------------------- Laurent@814: Laurent@814: # Return the data type informations Laurent@814: 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() Laurent@1291: if base_type_type == "derived" Laurent@1291: 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() Laurent@1291: if base_type_type == "derived" Laurent@1291: 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() Laurent@1291: base_type_type = element_type.getLocalTag() Laurent@1291: element_infos["Type"] = ("array", Laurent@1291: base_type.getname() Laurent@1291: if base_type_type == "derived" Laurent@1291: else base_type_type.upper(), 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: Laurent@814: element_infos["Initial Value"] = str(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() Laurent@1291: if basetype_content_type == "derived" Laurent@1291: else basetype_content_type.upper()) Laurent@1291: Laurent@814: if datatype.initialValue is not None: Laurent@814: infos["initial"] = str(datatype.initialValue.getvalue()) Laurent@814: else: Laurent@814: infos["initial"] = "" Laurent@814: return infos Laurent@814: return None Laurent@814: 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( Laurent@1291: "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") Laurent@864: if isinstance(element_infos["Type"], TupleType): Laurent@864: if element_infos["Type"][0] == "array": Laurent@864: array_type, base_type_name, dimensions = element_infos["Type"] Laurent@1291: array = PLCOpenParser.CreateElement("array", "dataType") 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(): Laurent@1291: array.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() Laurent@814: Laurent@814: #------------------------------------------------------------------------------- Laurent@814: # Project opened Pous management functions Laurent@814: #------------------------------------------------------------------------------- Laurent@814: Laurent@814: # Return edited element Laurent@814: 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 Laurent@814: Laurent@814: # Return edited element name Laurent@814: def GetEditedElementName(self, tagname): Laurent@814: words = tagname.split("::") Laurent@814: if words[0] in ["P","C","D"]: Laurent@814: return words[1] Laurent@814: else: Laurent@814: return words[2] Laurent@814: return None Laurent@814: Laurent@814: # Return edited element name and type Laurent@814: def GetEditedElementType(self, tagname, debug = False): Laurent@814: words = tagname.split("::") Laurent@814: 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 Laurent@814: 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 Laurent@1347: def GetEditedElementInterfaceVars(self, tagname, tree=False, debug = False): Laurent@814: words = tagname.split("::") Laurent@814: 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 Laurent@1347: 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': Laurent@814: return "BOOL" Laurent@814: return None Laurent@814: 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) Laurent@814: Laurent@814: # Return the edited element text Laurent@814: 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 Laurent@814: 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 Laurent@814: 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 Laurent@814: def GetEditedElementVariables(self, tagname, debug = False): Laurent@814: words = tagname.split("::") Laurent@814: 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: Laurent@814: 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 "" Laurent@814: Laurent@814: 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: Laurent@1299: wires = dict([(wire, True) Laurent@1299: 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 Laurent@814: Laurent@1122: def GenerateNewName(self, tagname, name, format, start_idx=0, exclude={}, debug=False): Laurent@814: names = exclude.copy() Laurent@814: if tagname is not None: Laurent@1122: names.update(dict([(varname.upper(), True) Laurent@1122: for varname in self.GetEditedElementVariables(tagname, debug)])) Laurent@1127: words = tagname.split("::") Laurent@1127: 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(): Laurent@1291: if isinstance(instance, Laurent@1291: (PLCOpenParser.GetElementClass("step", "sfcObjects"), Laurent@1291: PLCOpenParser.GetElementClass("connector", "commonObjects"), Laurent@1291: PLCOpenParser.GetElementClass("continuation", "commonObjects"))): Laurent@1127: 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 Laurent@814: Laurent@1122: i = start_idx Laurent@814: while name is None or names.get(name.upper(), False): Laurent@814: name = (format%i) Laurent@814: i += 1 Laurent@814: return name Laurent@814: Laurent@814: def PasteEditedElementInstances(self, tagname, text, new_pos, middle=False, debug=False): Laurent@814: element = self.GetEditedElement(tagname, debug) Laurent@814: element_name, element_type = self.GetEditedElementType(tagname, debug) Laurent@814: if element is not None: Laurent@814: bodytype = element.getbodyType() Laurent@814: 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] Laurent@814: 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 = {} Laurent@814: Laurent@814: try: Laurent@1330: instances, error = LoadPouInstances(text.encode("utf-8"), bodytype) Laurent@814: except: Laurent@1330: instances, error = [], "" Laurent@1330: if error is not None or len(instances) == 0: Laurent@814: return _("Invalid plcopen element(s)!!!") Laurent@1299: 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": Laurent@1299: return _("FunctionBlock \"%s\" can't be pasted in a Function!!!")%blocktype Laurent@1299: blockname = self.GenerateNewName(tagname, Laurent@1299: blockname, Laurent@1299: "%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": Laurent@1299: stepname = self.GenerateNewName(tagname, Laurent@1299: instance.getname(), Laurent@1299: "Step%d", Laurent@1299: exclude=exclude, Laurent@1299: debug=debug) Laurent@1299: exclude[stepname] = True Laurent@1299: instance.setname(stepname) Laurent@1299: localid = instance.getlocalId() Laurent@1299: if not used_id.has_key(localid): Laurent@1299: new_id[localid] = True Laurent@814: 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()) Laurent@814: if used_id.has_key(localId): Laurent@814: while used_id.has_key(idx) or new_id.has_key(idx): Laurent@814: idx += 1 Laurent@814: new_id[idx] = True Laurent@814: instance.setlocalId(idx) Laurent@814: translate_id[localId] = idx Laurent@814: Laurent@814: x, y, width, height = bbox.bounding_box() Laurent@814: if middle: Laurent@814: new_pos[0] -= width / 2 Laurent@814: new_pos[1] -= height / 2 Laurent@814: else: Laurent@814: new_pos = map(lambda x: x + 30, new_pos) Laurent@814: if scaling[0] != 0 and scaling[1] != 0: Laurent@814: min_pos = map(lambda x: 30 / x, 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)) Laurent@814: 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) Laurent@814: Laurent@814: return new_id, connections Laurent@1331: Laurent@1338: def GetEditedElementInstancesInfos(self, tagname, debug = False): Laurent@1338: element_instances = OrderedDict() Laurent@1331: element = self.GetEditedElement(tagname, debug) Laurent@1331: if element is not None: Laurent@1338: factory = BlockInstanceFactory(element_instances) Laurent@1338: Laurent@1338: pou_block_instances_xslt_tree = etree.XSLT( Laurent@1338: pou_block_instances_xslt, Laurent@1338: extensions = { Laurent@1338: ("pou_block_instances_ns", name): getattr(factory, name) Laurent@1338: for name in ["AddBlockInstance", "SetSpecificValues", Laurent@1338: "AddInstanceConnection", "AddConnectionLink", Laurent@1338: "AddLinkPoint", "AddAction"]}) Laurent@1338: Laurent@1338: pou_block_instances_xslt_tree(element) Laurent@1338: return element_instances Laurent@814: Laurent@814: def ClearEditedElementExecutionOrder(self, tagname): Laurent@814: element = self.GetEditedElement(tagname) Laurent@814: if element is not None: Laurent@814: element.resetexecutionOrder() Laurent@814: Laurent@814: def ResetEditedElementExecutionOrder(self, tagname): Laurent@814: element = self.GetEditedElement(tagname) Laurent@814: if element is not None: Laurent@814: element.compileexecutionOrder() Laurent@814: 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) Laurent@814: if result != 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 Laurent@814: 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 Laurent@1313: Laurent@1313: def AddEditedElementPouVar(self, tagname, var_type, name, location="", description=""): 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( Laurent@1313: self.GetVarTypeObject(var_type), Laurent@1313: name, location, description) Laurent@1313: Laurent@1313: def AddEditedElementPouExternalVar(self, tagname, var_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@1313: pou.addpouExternalVar( Laurent@1313: self.GetVarTypeObject(var_type), name) Laurent@814: 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) Laurent@814: 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) Laurent@814: Laurent@814: 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) Laurent@814: 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: Laurent@814: 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) Laurent@814: for param, value in 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() Laurent@814: 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) Laurent@814: 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: Laurent@814: return Laurent@814: for param, value in 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) Laurent@814: 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 Laurent@814: for param, value in infos.items(): Laurent@814: if param == "name": Laurent@814: 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) Laurent@814: 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) Laurent@814: for param, value in 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) Laurent@814: 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 Laurent@814: for param, value in 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) Laurent@1293: 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 Laurent@814: for param, value in 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 Laurent@814: for param, value in 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) Laurent@814: 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 Laurent@814: for param, value in 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() Laurent@814: 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) Laurent@814: 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 Laurent@814: for param, value in 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) Laurent@1293: 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( Laurent@1293: divergence_type), "sfcObjects") Laurent@814: divergence.setlocalId(id) Laurent@1293: element.addinstance(divergence) Laurent@1293: Laurent@1293: DivergenceTypes = [ Laurent@1293: (divergence_type, Laurent@1293: PLCOpenParser.GetElementClass(divergence_type, "sfcObjects")) Laurent@1293: for divergence_type in ["selectionDivergence", "simultaneousDivergence", Laurent@1293: "selectionConvergence", "simultaneousConvergence"]] Laurent@1293: 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 Laurent@814: 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 Laurent@814: for param, value in 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) Laurent@1293: 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) Laurent@814: 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 Laurent@814: for param, value in 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) Laurent@814: 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) Laurent@814: 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 Laurent@814: for param, value in 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) Laurent@814: 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: Laurent@814: 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"]) Laurent@814: ## result = duration_model.match(task["Interval"]).groups() Laurent@814: ## if reduce(lambda x, y: x or y != None, result): Laurent@814: ## values = [] Laurent@814: ## for value in result[:-1]: Laurent@814: ## if value != None: Laurent@814: ## values.append(int(value)) Laurent@814: ## else: Laurent@814: ## values.append(0) Laurent@814: ## if result[-1] is not None: Laurent@814: ## values.append(int(float(result[-1]) * 1000)) Laurent@814: ## 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: Laurent@814: 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: Laurent@814: ## text = "" Laurent@814: ## if interval.hour != 0: Laurent@814: ## text += "%dh"%interval.hour Laurent@814: ## if interval.minute != 0: Laurent@814: ## text += "%dm"%interval.minute Laurent@814: ## if interval.second != 0: Laurent@814: ## text += "%ds"%interval.second Laurent@814: ## if interval.microsecond != 0: Laurent@814: ## if interval.microsecond % 1000 != 0: Laurent@814: ## text += "%.3fms"%(float(interval.microsecond) / 1000) Laurent@814: ## else: Laurent@814: ## text += "%dms"%(interval.microsecond / 1000) Laurent@814: ## 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 Laurent@1290: Laurent@814: 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) Laurent@814: Laurent@1290: if filepath: Laurent@1290: SaveProject(self.Project, filepath) Laurent@1290: else: Laurent@1290: SaveProject(self.Project, self.FilePath) Laurent@814: Laurent@814: self.MarkProjectAsSaved() Laurent@814: if filepath: Laurent@814: self.SetFilePath(filepath) Laurent@814: return True Laurent@814: Laurent@814: #------------------------------------------------------------------------------- Laurent@814: # Search in Current Project Functions Laurent@814: #------------------------------------------------------------------------------- Laurent@814: Laurent@814: def SearchInProject(self, criteria): Laurent@814: return self.Project.Search(criteria) 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: Laurent@814: return pou.Search(criteria) Laurent@814: return [] Laurent@814: Laurent@814: #------------------------------------------------------------------------------- Laurent@814: # Current Buffering Management Functions Laurent@814: #------------------------------------------------------------------------------- Laurent@814: Laurent@814: """ Laurent@814: Return a copy of the project Laurent@814: """ Laurent@814: def Copy(self, model): 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 Laurent@814: 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 Laurent@814: 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()) Laurent@814: Laurent@814: def LoadNext(self): Laurent@814: if self.ProjectBuffer is not None: Laurent@1304: self.Project = PLCOpenParser.Loads(self.ProjectBuffer.Next()) Laurent@814: 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