#!/usr/bin/env python
# -*- coding: utf-8 -*-
#This file is part of PLCOpenEditor, a library implementing an IEC 61131-3 editor
#based on the plcopen standard.
#
#Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD
#
#See COPYING file for copyrights details.
#
#This library is free software; you can redistribute it and/or
#modify it under the terms of the GNU General Public
#License as published by the Free Software Foundation; either
#version 2.1 of the License, or (at your option) any later version.
#
#This library is distributed in the hope that it will be useful,
#but WITHOUT ANY WARRANTY; without even the implied warranty of
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
#General Public License for more details.
#
#You should have received a copy of the GNU General Public
#License along with this library; if not, write to the Free Software
#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
from minixsv import pyxsval
from xml.dom import minidom
from types import StringType, UnicodeType
import cPickle
import os,sys,re
from time import localtime
from datetime import *
from plcopen import plcopen
from plcopen.structures import *
from graphics.GraphicCommons import *
from PLCGenerator import *
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)?")
[ITEM_UNEDITABLE, ITEM_PROJECT, ITEM_POU, ITEM_CLASS, ITEM_VARIABLE,
ITEM_TRANSITION, ITEM_ACTION, ITEM_CONFIGURATION, ITEM_RESOURCE,
ITEM_DATATYPE] = range(10)
ScriptDirectory = os.path.split(os.path.realpath(__file__))[0]
"""
pyxsval is not complete and the parts that are not supported print some error
reports. This class is used for not displaying them
"""
class HolePseudoFile:
""" Base class for file like objects to facilitate StdOut for the Shell."""
def __init__(self, output = None):
if output is None: output = []
self.output = output
def writelines(self, l):
map(self.write, l)
def write(self, s):
pass
def flush(self):
pass
def isatty(self):
return false
#-------------------------------------------------------------------------------
# Undo Buffer for PLCOpenEditor
#-------------------------------------------------------------------------------
# Length of the buffer
UNDO_BUFFER_LENGTH = 20
"""
Class implementing a buffer of changes made on the current editing Object Dictionary
"""
class UndoBuffer:
# Constructor initialising buffer
def __init__(self, currentstate, issaved = False):
self.Buffer = []
self.CurrentIndex = -1
self.MinIndex = -1
self.MaxIndex = -1
# if current state is defined
if currentstate:
self.CurrentIndex = 0
self.MinIndex = 0
self.MaxIndex = 0
# Initialising buffer with currentstate at the first place
for i in xrange(UNDO_BUFFER_LENGTH):
if i == 0:
self.Buffer.append(currentstate)
else:
self.Buffer.append(None)
# Initialising index of state saved
if issaved:
self.LastSave = 0
else:
self.LastSave = -1
# Add a new state in buffer
def Buffering(self, currentstate):
self.CurrentIndex = (self.CurrentIndex + 1) % UNDO_BUFFER_LENGTH
self.Buffer[self.CurrentIndex] = currentstate
# Actualising buffer limits
self.MaxIndex = self.CurrentIndex
if self.MinIndex == self.CurrentIndex:
# If the removed state was the state saved, there is no state saved in the buffer
if self.LastSave == self.MinIndex:
self.LastSave = -1
self.MinIndex = (self.MinIndex + 1) % UNDO_BUFFER_LENGTH
self.MinIndex = max(self.MinIndex, 0)
# Return current state of buffer
def Current(self):
return self.Buffer[self.CurrentIndex]
# Change current state to previous in buffer and return new current state
def Previous(self):
if self.CurrentIndex != self.MinIndex:
self.CurrentIndex = (self.CurrentIndex - 1) % UNDO_BUFFER_LENGTH
return self.Buffer[self.CurrentIndex]
return None
# Change current state to next in buffer and return new current state
def Next(self):
if self.CurrentIndex != self.MaxIndex:
self.CurrentIndex = (self.CurrentIndex + 1) % UNDO_BUFFER_LENGTH
return self.Buffer[self.CurrentIndex]
return None
# Return True if current state is the first in buffer
def IsFirst(self):
return self.CurrentIndex == self.MinIndex
# Return True if current state is the last in buffer
def IsLast(self):
return self.CurrentIndex == self.MaxIndex
# Note that current state is saved
def CurrentSaved(self):
self.LastSave = self.CurrentIndex
# Return True if current state is saved
def IsCurrentSaved(self):
return self.LastSave == self.CurrentIndex
#-------------------------------------------------------------------------------
# Controler for PLCOpenEditor
#-------------------------------------------------------------------------------
"""
Class which controls the operations made on the plcopen model and answers to view requests
"""
class PLCControler:
# Create a new PLCControler
def __init__(self):
self.LastNewIndex = 0
self.Reset()
# Reset PLCControler internal variables
def Reset(self):
self.VerifyXML = False
self.Project = None
self.ProjectBuffer = None
self.Buffering = False
self.FilePath = ""
self.FileName = ""
self.ProgramFilePath = ""
self.RefreshDataTypeUsingTree()
self.RefreshDataTypes()
self.RefreshPouUsingTree()
self.RefreshBlockTypes()
def GetQualifierTypes(self):
return plcopen.QualifierList
#-------------------------------------------------------------------------------
# Project management functions
#-------------------------------------------------------------------------------
# Return if a project is opened
def HasOpenedProject(self):
return self.Project != None
# Create a new project by replacing the current one
def CreateNewProject(self, properties):
# Create the project
self.Project = plcopen.project()
properties["creationDateTime"] = datetime(*localtime()[:6])
self.Project.setFileHeader(properties)
self.Project.setContentHeader(properties)
self.SetFilePath("")
# Initialize the project buffer
self.ProjectBuffer = UndoBuffer(self.Copy(self.Project), False)
self.Buffering = False
# Return project data type names
def GetProjectDataTypeNames(self):
if self.Project:
return [datatype.getName() for datatype in self.Project.getDataTypes()]
return []
# Return project pou names
def GetProjectPouNames(self):
if self.Project:
return [pou.getName() for pou in self.Project.getPous()]
return []
# Return project pou names
def GetProjectConfigNames(self):
if self.Project:
return [config.getName() for config in self.Project.getConfigurations()]
return []
# Return project pou variables
def GetProjectPouVariables(self, pou_name=None):
variables = []
for pou in self.Project.getPous():
if not pou_name or pou_name == pou.getName():
variables.extend([var["Name"] for var in self.GetPouInterfaceVars(pou)])
for transition in pou.getTransitionList():
variables.append(transition.getName())
for action in pou.getActionList():
variables.append(action.getName())
return variables
# Return if project is saved
def ProjectIsSaved(self):
return self.ProjectBuffer.IsCurrentSaved()
# Return file path if project is an open file
def GetFilePath(self):
return self.FilePath
# Return file path if project is an open file
def GetProgramFilePath(self):
return self.ProgramFilePath
# Return file name and point out if file is up to date
def GetFilename(self):
if self.ProjectBuffer.IsCurrentSaved():
return self.FileName
else:
return "~%s~"%self.FileName
# Change file path and save file name or create a default one if file path not defined
def SetFilePath(self, filepath):
self.FilePath = filepath
if filepath == "":
self.LastNewIndex += 1
self.FileName = "Unnamed%d"%self.LastNewIndex
else:
self.FileName = os.path.splitext(os.path.basename(filepath))[0]
# Change project properties
def SetProjectProperties(self, name = None, properties = None):
if name != None:
self.Project.setName(name)
if properties != None:
self.Project.setFileHeader(properties)
self.Project.setContentHeader(properties)
if name != None or properties != None:
self.BufferProject()
# Return project properties
def GetProjectProperties(self):
properties = self.Project.getFileHeader()
properties.update(self.Project.getContentHeader())
return properties
# Return project informations
def GetProjectInfos(self):
if self.Project:
infos = {"name": self.Project.getName(), "type": ITEM_PROJECT}
datatypes = {"name": "Data Types", "type": ITEM_UNEDITABLE, "values":[]}
for datatype in self.Project.getDataTypes():
datatypes["values"].append({"name": datatype.getName(), "type": ITEM_DATATYPE, "values": []})
pou_types = {"function": {"name": "Functions", "type": ITEM_UNEDITABLE, "values":[]},
"functionBlock": {"name": "Function Blocks", "type": ITEM_UNEDITABLE, "values":[]},
"program": {"name": "Programs", "type": ITEM_UNEDITABLE, "values":[]}}
for pou in self.Project.getPous():
pou_type = pou.getPouType().getValue()
pou_infos = {"name": pou.getName(), "type": ITEM_POU}
pou_values = []
if pou.getBodyType() == "SFC":
transitions = []
for transition in pou.getTransitionList():
transitions.append({"name": transition.getName(), "type": ITEM_TRANSITION, "values": []})
pou_values.append({"name": "Transitions", "type": ITEM_UNEDITABLE, "values": transitions})
actions = []
for action in pou.getActionList():
actions.append({"name": action.getName(), "type": ITEM_ACTION, "values": []})
pou_values.append({"name": "Actions", "type": ITEM_UNEDITABLE, "values": actions})
if pou_type in pou_types:
pou_infos["values"] = pou_values
pou_types[pou_type]["values"].append(pou_infos)
configurations = {"name": "Configurations", "type": ITEM_UNEDITABLE, "values": []}
for config in self.Project.getConfigurations():
config_name = config.getName()
config_infos = {"name": config_name, "type": ITEM_CONFIGURATION, "values": []}
resources = {"name": "Resources", "type": ITEM_UNEDITABLE, "values": []}
for resource in config.getResource():
resource_name = resource.getName()
resource_infos = {"name": resource_name, "type": ITEM_RESOURCE, "values": []}
resources["values"].append(resource_infos)
config_infos["values"] = [resources]
configurations["values"].append(config_infos)
infos["values"] = [{"name": "Properties", "type": ITEM_UNEDITABLE, "values": []},
datatypes, pou_types["function"], pou_types["functionBlock"],
pou_types["program"], configurations]
return infos
return None
# Refresh the tree of user-defined data type cross-use
def RefreshDataTypeUsingTree(self):
# Reset the tree of user-defined pou cross-use
self.DataTypeUsingTree = {}
if self.Project:
datatypes = self.Project.getDataTypes()
# Reference all the user-defined data type names and initialize the tree of
# user-defined data type cross-use
datatypenames = [datatype.getName() for datatype in datatypes]
for name in datatypenames:
self.DataTypeUsingTree[name] = []
# Analyze each data type
for datatype in datatypes:
name = datatype.getName()
basetype_content = datatype.getBaseType().getContent()
if basetype_content["name"] == "derived":
basetype_name = basetype_content["value"].getName()
if basetype_name in datatypenames and name not in self.DataTypeUsingTree[basetype_name]:
self.DataTypeUsingTree[basetype_name].append(name)
elif basetype_content["name"] in ["subrangeSigned", "subrangeUnsigned", "array"]:
base_type = basetype_content["value"].baseType.getContent()
if base_type["value"] is not None:
basetype_name = base_type["value"].getName()
if basetype_name in datatypenames and name not in self.DataTypeUsingTree[basetype_name]:
self.DataTypeUsingTree[basetype_name].append(name)
# Refresh the tree of user-defined pou cross-use
def RefreshPouUsingTree(self):
# Reset the tree of user-defined pou cross-use
self.PouUsingTree = {}
if self.Project:
pous = self.Project.getPous()
# Reference all the user-defined pou names and initialize the tree of
# user-defined pou cross-use
pounames = [pou.getName() for pou in pous]
for name in pounames:
self.PouUsingTree[name] = []
# Analyze each pou
for pou in pous:
name = pou.getName()
if pou.interface:
# Extract variables from every varLists
for type, varlist in pou.getVars():
for var in varlist.getVariable():
vartype_content = var.getType().getContent()
if vartype_content["name"] == "derived":
typename = vartype_content["value"].getName()
if typename in pounames and name not in self.PouUsingTree[typename]:
self.PouUsingTree[typename].append(name)
bodytype = pou.getBodyType()
# If pou is written in a graphical language
if bodytype in ["FBD","LD","SFC"]:
# Analyze each instance of the pou
for instance in pou.getInstances():
if isinstance(instance, plcopen.block):
typename = instance.getTypeName()
# Update tree if there is a cross-use
if typename in pounames and name not in self.PouUsingTree[typename]:
self.PouUsingTree[typename].append(name)
# If pou is written in a textual language
elif bodytype in ["IL", "ST"]:
text = pou.getText()
# Search if each pou is mentioned in the pou text
for typename in pounames:
typename_model = re.compile("[ \t\n]%s[ \t\n]"%typename)
# Update tree if there is a cross-use
if typename != name and typename_model.search(text):
self.PouUsingTree[typename].append(name)
# Return if data type given by name is used by another data type or pou
def DataTypeIsUsed(self, name):
if name in self.DataTypeUsingTree:
return len(self.DataTypeUsingTree[name]) > 0
return False
# Return if pou given by name is used by another pou
def PouIsUsed(self, name):
if name in self.PouUsingTree:
return len(self.PouUsingTree[name]) > 0
return False
# Return if data type given by name is directly or undirectly used by the reference data type
def DataTypeIsUsedBy(self, name, reference):
if name in self.DataTypeUsingTree:
list = self.DataTypeUsingTree[name]
# Test if data type is directly used by reference
if reference in list:
return True
else:
# Test if data type is undirectly used by reference, by testing if data types
# that directly use data type is directly or undirectly used by reference
used = False
for element in list:
used |= self.DataTypeIsUsedBy(element, reference)
return used
return False
# Return if pou given by name is directly or undirectly used by the reference pou
def PouIsUsedBy(self, name, reference):
if name in self.PouUsingTree:
list = self.PouUsingTree[name]
# Test if pou is directly used by reference
if reference in list:
return True
else:
# Test if pou is undirectly used by reference, by testing if pous
# that directly use pou is directly or undirectly used by reference
used = False
for element in list:
used |= self.PouIsUsedBy(element, reference)
return used
return False
def GenerateProgram(self, filepath):
if self.Project:
try:
program = GenerateCurrentProgram(self.Project)
programfile = open(filepath, "w")
programfile.write(program)
programfile.close()
self.ProgramFilePath = filepath
return True
except:
pass
return False
#-------------------------------------------------------------------------------
# Project Pous management functions
#-------------------------------------------------------------------------------
# Add a Data Type to Project
def ProjectAddDataType(self, datatype_name):
# Add the pou to project
self.Project.appendDataType(datatype_name)
self.RefreshDataTypeUsingTree()
self.RefreshDataTypes()
self.BufferProject()
# Remove a Data Type from project
def ProjectRemoveDataType(self, datatype_name):
self.Project.removeDataType(datatype_name)
self.RefreshDataTypeUsingTree()
self.RefreshDataTypes()
self.BufferProject()
# Add a Pou to Project
def ProjectAddPou(self, pou_name, pou_type, body_type):
# Add the pou to project
self.Project.appendPou(pou_name, pou_type, body_type)
if pou_type == "function":
self.SetPouInterfaceReturnType(pou_name, "BOOL")
self.RefreshPouUsingTree()
self.RefreshBlockTypes()
self.BufferProject()
# Remove a Pou from project
def ProjectRemovePou(self, pou_name):
self.Project.removePou(pou_name)
self.RefreshPouUsingTree()
self.RefreshBlockTypes()
self.BufferProject()
# Add a configuration to Project
def ProjectAddConfiguration(self, config_name):
self.Project.addConfiguration(config_name)
self.BufferProject()
# Remove a configuration from project
def ProjectRemoveConfiguration(self, config_name):
self.Project.removeConfiguration(config_name)
self.BufferProject()
# Add a resource to a configuration of the Project
def ProjectAddConfigurationResource(self, config_name, resource_name):
self.Project.addConfigurationResource(config_name, resource_name)
self.BufferProject()
# Remove a resource from a configuration of the project
def ProjectRemoveConfigurationResource(self, config_name, resource_name):
self.Project.removeConfigurationResource(config_name, resource_name)
self.BufferProject()
# Add a Transition to a Project Pou
def ProjectAddPouTransition(self, pou_name, transition_name, transition_type):
pou = self.Project.getPou(pou_name)
pou.addTransition(transition_name, transition_type)
self.BufferProject()
# Remove a Transition from a Project Pou
def ProjectRemovePouTransition(self, pou_name, transition_name):
pou = self.Project.getPou(pou_name)
pou.removeTransition(transition_name)
self.BufferProject()
# Add an Action to a Project Pou
def ProjectAddPouAction(self, pou_name, action_name, action_type):
pou = self.Project.getPou(pou_name)
pou.addAction(action_name, action_type)
self.BufferProject()
# Remove an Action from a Project Pou
def ProjectRemovePouAction(self, pou_name, action_name):
# Search if the pou removed is currently opened
for i, element in enumerate(self.ElementsOpened):
words = element.split("::")
if words[0] == "A" and words[1] == pou_name and words[2] == action_name:
self.RemoveElementEditing(i)
pou = self.Project.getPou(pou_name)
pou.removeAction(action_name)
self.BufferProject()
# Change the name of a pou
def ChangeDataTypeName(self, old_name, new_name):
# Found the pou corresponding to old name and change its name to new name
datatype = self.Project.getDataType(old_name)
datatype.setName(new_name)
self.Project.updateElementName(old_name, new_name)
self.BufferProject()
# Change the name of a pou
def ChangePouName(self, old_name, new_name):
# Found the pou corresponding to old name and change its name to new name
pou = self.Project.getPou(old_name)
pou.setName(new_name)
self.Project.updateElementName(old_name, new_name)
self.RefreshPouUsingTree()
self.RefreshBlockTypes()
self.BufferProject()
# Change the name of a pou transition
def ChangePouTransitionName(self, pou_name, old_name, new_name):
# Found the pou transition corresponding to old name and change its name to new name
pou = self.Project.getPou(pou_name)
transition = pou.getTransition(old_name)
transition.setName(new_name)
pou.updateElementName(old_name, new_name)
self.BufferProject()
# Change the name of a pou action
def ChangePouActionName(self, pou_name, old_name, new_name):
# Found the pou action corresponding to old name and change its name to new name
pou = self.Project.getPou(pou_name)
action = pou.getAction(old_name)
action.setName(new_name)
pou.updateElementName(old_name, new_name)
self.BufferProject()
# Change the name of a pou variable
def ChangePouVariableName(self, pou_name, old_name, new_name):
# Found the pou action corresponding to old name and change its name to new name
pou = self.Project.getPou(pou_name)
for type, varlist in pou.getVars():
for var in varlist.getVariable():
if var.getName() == old_name:
var.setName(new_name)
self.RefreshBlockTypes()
self.BufferProject()
# Change the name of a configuration
def ChangeConfigurationName(self, old_name, new_name):
# Found the configuration corresponding to old name and change its name to new name
configuration = self.Project.getConfiguration(old_name)
configuration.setName(new_name)
self.BufferProject()
# Change the name of a configuration resource
def ChangeConfigurationResourceName(self, config_name, old_name, new_name):
# Found the resource corresponding to old name and change its name to new name
resource = self.Project.getConfigurationResource(config_name)
resource.setName(new_name)
self.BufferProject()
# Return the type of the pou given by its name
def GetPouType(self, name):
# Found the pou correponding to name and return its type
pou = self.Project.getPou(name)
return pou.pouType.getValue()
# Return pous with SFC language
def GetSFCPous(self):
list = []
if self.Project:
for pou in self.Project.getPous():
if pou.getBodyType() == "SFC":
list.append(pou.getName())
return list
# Return the body language of the pou given by its name
def GetPouBodyType(self, name):
# Found the pou correponding to name and return its body language
pou = self.Project.getPou(name)
return pou.getBodyType()
# Return the actions of a pou
def GetPouTransitions(self, pou_name):
transitions = []
pou = self.Project.getPou(pou_name)
if pou.getBodyType() == "SFC":
for transition in pou.getTransitionList():
transitions.append(transition.getName())
return transitions
# Return the body language of the transition given by its name
def GetTransitionBodyType(self, pou_name, pou_transition):
# Found the pou correponding to name and return its body language
pou = self.Project.getPou(pou_name)
transition = pou.getTransition(pou_transition)
return transition.getBodyType()
# Return the actions of a pou
def GetPouActions(self, pou_name):
actions = []
pou = self.Project.getPou(pou_name)
if pou.getBodyType() == "SFC":
for action in pou.getActionList():
actions.append(action.getName())
return actions
# Return the body language of the pou given by its name
def GetActionBodyType(self, pou_name, pou_action):
# Found the pou correponding to name and return its body language
pou = self.Project.getPou(pou_name)
action = pou.getAction(pou_action)
return action.getBodyType()
# Extract varlists from a list of vars
def ExtractVarLists(self, vars):
varlist_list = []
current_varlist = None
current_type = None
for var in vars:
if current_type != (var["Class"], var["Retain"], var["Constant"], var["Location"] in ["", None]):
current_type = (var["Class"], var["Retain"], var["Constant"], var["Location"] in ["", None])
current_varlist = plcopen.varList()
varlist_list.append((var["Class"], current_varlist))
if var["Retain"] == "Yes":
varlist.setRetain(True)
if var["Constant"] == "Yes":
varlist.setConstant(True)
# Create variable and change its properties
tempvar = plcopen.varListPlain_variable()
tempvar.setName(var["Name"])
var_type = plcopen.dataType()
if var["Type"] not in var_type.getChoices():
if var["Type"] == "STRING":
var_type.setContent("string", plcopen.string())
elif var["Type"] == "WSTRING":
var_type.setContent("wstring", plcopen.wstring())
else:
derived_type = plcopen.derived()
derived_type.setName(var["Type"])
var_type.setContent("derived", derived_type)
else:
var_type.setContent(var["Type"], None)
tempvar.setType(var_type)
if var["Initial Value"] != "":
value = plcopen.value()
value.setValue(var["Initial Value"])
tempvar.setInitialValue(value)
if var["Location"] != "":
tempvar.setAddress(var["Location"])
else:
tempvar.setAddress(None)
# Add variable to varList
current_varlist.appendVariable(tempvar)
return varlist_list
# Replace the configuration globalvars by those given
def SetConfigurationGlobalVars(self, name, vars):
# Found the configuration corresponding to name
configuration = self.Project.getConfiguration(name)
if configuration:
# Set configuration global vars
configuration.setGlobalVars([])
for vartype, varlist in self.ExtractVarLists(vars):
configuration.globalVars.append(varlist)
self.RefreshBlockTypes()
# Return the configuration globalvars
def GetConfigurationGlobalVars(self, name):
vars = []
# Found the configuration corresponding to name
configuration = self.Project.getConfiguration(name)
if configuration:
# Extract variables from every varLists
for varlist in configuration.getGlobalVars():
for var in varlist.getVariable():
tempvar = {"Name":var.getName(),"Class":"Global"}
vartype_content = var.getType().getContent()
if vartype_content["name"] == "derived":
tempvar["Type"] = vartype_content["value"].getName()
elif vartype_content["name"] in ["string", "wstring"]:
tempvar["Type"] = vartype_content["name"].upper()
else:
tempvar["Type"] = vartype_content["name"]
tempvar["Edit"] = True
initial = var.getInitialValue()
if initial:
tempvar["Initial Value"] = initial.getValue()
else:
tempvar["Initial Value"] = ""
address = var.getAddress()
if address:
tempvar["Location"] = address
else:
tempvar["Location"] = ""
if varlist.getRetain():
tempvar["Retain"] = "Yes"
else:
tempvar["Retain"] = "No"
if varlist.getConstant():
tempvar["Constant"] = "Yes"
else:
tempvar["Constant"] = "No"
vars.append(tempvar)
return vars
# Replace the resource globalvars by those given
def SetConfigurationResourceGlobalVars(self, config_name, name, vars):
# Found the resource corresponding to name
resource = self.Project.getConfigurationResource(config_name, name)
# Set resource global vars
if resource:
resource.setGlobalVars([])
for vartype, varlist in self.ExtractVarLists(vars):
resource.globalVars.append(varlist)
self.RefreshBlockTypes()
# Return the resource globalvars
def GetConfigurationResourceGlobalVars(self, config_name, name):
vars = []
# Found the resource corresponding to name
resource = self.Project.getConfigurationResource(config_name, name)
if resource:
# Extract variables from every varLists
for varlist in resource.getGlobalVars():
for var in varlist.getVariable():
tempvar = {"Name":var.getName(),"Class":"Global"}
vartype_content = var.getType().getContent()
if vartype_content["name"] == "derived":
tempvar["Type"] = vartype_content["value"].getName()
elif vartype_content["name"] in ["string", "wstring"]:
tempvar["Type"] = vartype_content["name"].upper()
else:
tempvar["Type"] = vartype_content["name"]
tempvar["Edit"] = True
initial = var.getInitialValue()
if initial:
tempvar["Initial Value"] = initial.getValue()
else:
tempvar["Initial Value"] = ""
address = var.getAddress()
if address:
tempvar["Location"] = address
else:
tempvar["Location"] = ""
if varlist.getRetain():
tempvar["Retain"] = "Yes"
else:
tempvar["Retain"] = "No"
if varlist.getConstant():
tempvar["Constant"] = "Yes"
else:
tempvar["Constant"] = "No"
vars.append(tempvar)
return vars
# Return the interface of the pou given by its name
def GetPouInterfaceVarsByName(self, name):
# Found the pou correponding to name and return the interface
return self.GetPouInterfaceVars(self.Project.getPou(name))
# Return the interface for the given pou
def GetPouInterfaceVars(self, pou):
vars = []
# Verify that the pou has an interface
if pou.interface:
# Extract variables from every varLists
for type, varlist in pou.getVars():
for var in varlist.getVariable():
tempvar = {"Name":var.getName(),"Class":type}
vartype_content = var.getType().getContent()
if vartype_content["name"] == "derived":
tempvar["Type"] = vartype_content["value"].getName()
tempvar["Edit"] = not pou.hasBlock(tempvar["Name"])
else:
if vartype_content["name"] in ["string", "wstring"]:
tempvar["Type"] = vartype_content["name"].upper()
else:
tempvar["Type"] = vartype_content["name"]
tempvar["Edit"] = True
initial = var.getInitialValue()
if initial:
tempvar["Initial Value"] = initial.getValue()
else:
tempvar["Initial Value"] = ""
address = var.getAddress()
if address:
tempvar["Location"] = address
else:
tempvar["Location"] = ""
if varlist.getRetain():
tempvar["Retain"] = "Yes"
else:
tempvar["Retain"] = "No"
if varlist.getConstant():
tempvar["Constant"] = "Yes"
else:
tempvar["Constant"] = "No"
vars.append(tempvar)
return vars
# Replace the Pou interface by the one given
def SetPouInterfaceVars(self, name, vars):
# Found the pou corresponding to name and add interface if there isn't one yet
pou = self.Project.getPou(name)
if not pou.interface:
pou.interface = plcopen.pou_interface()
# Set Pou interface
pou.setVars(self.ExtractVarLists(vars))
self.RefreshPouUsingTree()
self.RefreshBlockTypes()
# Replace the return type of the pou given by its name (only for functions)
def SetPouInterfaceReturnType(self, name, type):
pou = self.Project.getPou(name)
if not pou.interface:
pou.interface = plcopen.pou_interface()
# If there isn't any return type yet, add it
return_type = pou.interface.getReturnType()
if not return_type:
return_type = plcopen.dataType()
pou.interface.setReturnType(return_type)
# Change return type
if type in self.GetBaseTypes():
return_type.setContent(type, None)
else:
derived_type = plcopen.derived()
derived_type.setName(type)
return_type.setContent("derived", derived_type)
self.RefreshBlockTypes()
def UpdateProjectUsedPous(self, old_name, new_name):
if self.Project:
self.Project.updateElementName(old_name, new_name)
def UpdateEditedElementUsedVariable(self, tagname, old_name, new_name):
pou = self.GetEditedElement(tagname)
if pou:
pou.updateElementName(old_name, new_name)
# Return the return type of the pou given by its name
def GetPouInterfaceReturnTypeByName(self, name):
# Found the pou correponding to name and return the return type
return self.GetPouInterfaceReturnType(self.Project.getPou(name))
# Return the return type of the given pou
def GetPouInterfaceReturnType(self, pou):
# Verify that the pou has an interface
if pou.interface:
# Return the return type if there is one
return_type = pou.interface.getReturnType()
if return_type:
returntype_content = return_type.getContent()
if returntype_content["name"] == "derived":
return returntype_content["value"].getName()
elif returntype_content["name"] in ["string", "wstring"]:
return returntype_content["name"].upper()
else:
return returntype_content["name"]
return None
# Update data types with user-defined data types added
def RefreshDataTypes(self):
ResetTypeHierarchy()
ResetEnumeratedDataValues()
if self.Project:
for datatype in self.Project.getDataTypes():
name = datatype.getName()
basetype_content = datatype.getBaseType().getContent()
if basetype_content["value"] is None:
AddDataTypeHierarchy(name, basetype_content["name"])
elif basetype_content["name"] in ["string", "wstring"]:
AddDataTypeHierarchy(name, basetype_content["name"].upper())
elif basetype_content["name"] == "derived":
AddDataTypeHierarchy(name, basetype_content["value"].getName())
elif basetype_content["name"] in ["subrangeSigned", "subrangeUnsigned"]:
base_type = basetype_content["value"].baseType.getContent()
if base_type["value"] is None:
AddDataTypeHierarchy(name, base_type["name"])
else:
AddDataTypeHierarchy(name, base_type["value"].getName())
else:
if basetype_content["name"] == "enum":
values = []
for value in basetype_content["value"].values.getValue():
values.append(value.getName())
AddEnumeratedDataValues(values)
AddDataTypeHierarchy(name, "ANY_DERIVED")
# Update Block types with user-defined pou added
def RefreshBlockTypes(self):
if BlockTypes[-1]["name"] == "User-defined POUs":
BlockTypes[-1]["list"] = []
else:
BlockTypes.append({"name" : "User-defined POUs", "list": []})
if self.Project:
for pou in self.Project.getPous():
pou_name = pou.getName()
pou_type = pou.pouType.getValue()
if pou_type != "program":
block_infos = {"name" : pou_name, "type" : pou_type, "extensible" : False,
"inputs" : [], "outputs" : [], "comment" : "",
"generate" : generate_block, "initialise" : initialise_block }
if pou.getInterface():
for type, varlist in pou.getVars():
if type == "InOut":
for var in varlist.getVariable():
var_type = var.type.getContent()
if var_type["name"] == "derived":
block_infos["inputs"].append((var.getName(),var_type["value"].getName(),"none"))
block_infos["outputs"].append((var.getName(),var_type["value"].getName(),"none"))
elif var_type["name"] in ["string", "wstring"]:
block_infos["inputs"].append((var.getName(),var_type["name"].upper(),"none"))
block_infos["outputs"].append((var.getName(),var_type["name"].upper(),"none"))
else:
block_infos["inputs"].append((var.getName(),var_type["name"],"none"))
block_infos["outputs"].append((var.getName(),var_type["name"],"none"))
elif type == "Input":
for var in varlist.getVariable():
var_type = var.type.getContent()
if var_type["name"] == "derived":
block_infos["inputs"].append((var.getName(),var_type["value"].getName(),"none"))
elif var_type["name"] in ["string", "wstring"]:
block_infos["inputs"].append((var.getName(),var_type["name"].upper(),"none"))
else:
block_infos["inputs"].append((var.getName(),var_type["name"],"none"))
elif type == "Output":
for var in varlist.getVariable():
var_type = var.type.getContent()
if var_type["name"] == "derived":
block_infos["outputs"].append((var.getName(),var_type["value"].getName(),"none"))
elif var_type["name"] in ["string", "wstring"]:
block_infos["outputs"].append((var.getName(),var_type["name"].upper(),"none"))
else:
block_infos["outputs"].append((var.getName(),var_type["name"],"none"))
return_type = pou.interface.getReturnType()
if return_type:
var_type = return_type.getContent()
if var_type["name"] == "derived":
block_infos["outputs"].append(("",var_type["value"].getName(),"none"))
elif var_type["name"] in ["string", "wstring"]:
block_infos["outputs"].append(("",var_type["name"].upper(),"none"))
else:
block_infos["outputs"].append(("",var_type["name"],"none"))
if pou.getBodyType() in ["FBD","LD","SFC"]:
for instance in pou.getInstances():
if isinstance(instance, plcopen.comment):
block_infos["comment"] = instance.getContentText()
BlockTypes[-1]["list"].append(block_infos)
# Return Block types checking for recursion
def GetBlockTypes(self, tagname = ""):
name = ""
type = None
if self.Project:
words = tagname.split("::")
if words[0] in ["P","T","A"]:
name = words[1]
type = self.GetPouType(name)
if type == "function":
blocktypes = []
for category in BlockTypes[:-1] + PluginTypes:
cat = {"name" : category["name"], "list" : []}
for block in category["list"]:
if block["type"] == "function":
cat["list"].append(block)
if len(cat["list"]) > 0:
blocktypes.append(cat)
else:
blocktypes = [category for category in BlockTypes[:-1] + PluginTypes]
if self.Project:
blocktypes.append({"name" : "User-defined POUs", "list": []})
for blocktype in BlockTypes[-1]["list"]:
if blocktype["name"] != name and not self.PouIsUsedBy(name, blocktype["name"]) and not (type == "function" and blocktype["type"] != "function"):
blocktypes[-1]["list"].append(blocktype)
return blocktypes
# Return Function Block types checking for recursion
def GetFunctionBlockTypes(self, tagname = ""):
name = ""
type = None
if self.Project:
words = tagname.split("::")
if words[0] in ["P","T","A"]:
name = words[1]
type = self.GetPouType(name)
blocktypes = []
for category in BlockTypes[:-1]:
for block in category["list"]:
if block["type"] != "function":
blocktypes.append(block["name"])
if self.Project:
for blocktype in BlockTypes[-1]["list"]:
if blocktype["name"] != name and not self.PouIsUsedBy(name, blocktype["name"]) and not (type == "function" and blocktype["type"] != "function"):
blocktypes.append(blocktype["name"])
return blocktypes
# Return Block types checking for recursion
def GetBlockResource(self):
blocktypes = []
for category in BlockTypes[:-1]:
for blocktype in category["list"]:
if blocktype["type"] == "program":
blocktypes.append(blocktype["name"])
if self.Project:
for pou in self.Project.getPous():
if pou.pouType.getValue() == "program":
blocktypes.append(pou.getName())
return blocktypes
# Return Data Types checking for recursion
def GetDataTypes(self, tagname = "", basetypes = True):
if basetypes:
datatypes = self.GetBaseTypes()
else:
datatypes = []
if self.Project:
words = tagname.split("::")
if words[0] in ["D"]:
name = words[1]
else:
name = ""
for datatype in self.Project.getDataTypes():
datatype_name = datatype.getName()
if datatype_name != name and not self.DataTypeIsUsedBy(name, datatype_name):
datatypes.append(datatype_name)
return datatypes
# Return Base Types
def GetBaseTypes(self):
return [value for value, parent in TypeHierarchy_list if not value.startswith("ANY")]
# Return Subrange types
def GetSubrangeTypes(self):
return [value for value, range in DataTypeRange_list]
# Return Enumerated Values
def GetEnumeratedDataValues(self):
return EnumeratedDataValues
#-------------------------------------------------------------------------------
# Project Element tag name computation functions
#-------------------------------------------------------------------------------
# Compute a data type name
def ComputeDataTypeName(self, datatype):
return "D::%s" % datatype
# Compute a pou name
def ComputePouName(self, pou):
return "P::%s" % pou
# Compute a pou transition name
def ComputePouTransitionName(self, pou, transition):
return "T::%s::%s" % (pou, transition)
# Compute a pou action name
def ComputePouActionName(self, pou, action):
return "A::%s::%s" % (pou, action)
# Compute a pou name
def ComputeConfigurationName(self, config):
return "C::%s" % config
# Compute a pou name
def ComputeConfigurationResourceName(self, config, resource):
return "R::%s::%s" % (config, resource)
#-------------------------------------------------------------------------------
# Project opened Data types management functions
#-------------------------------------------------------------------------------
# Return the data type informations
def GetDataTypeInfos(self, tagname):
words = tagname.split("::")
if words[0] == "D":
infos = {}
datatype = self.Project.getDataType(words[1])
basetype_content = datatype.baseType.getContent()
if basetype_content["value"] is None:
infos["type"] = "Directly"
infos["base_type"] = basetype_content["name"]
elif basetype_content["name"] == "derived":
infos["type"] = "Directly"
infos["base_type"] = basetype_content["value"].getName()
elif basetype_content["name"] in ["subrangeSigned", "subrangeUnsigned"]:
infos["type"] = "Subrange"
infos["min"] = basetype_content["value"].range.getLower()
infos["max"] = basetype_content["value"].range.getUpper()
base_type = basetype_content["value"].baseType.getContent()
if base_type["value"] is None:
infos["base_type"] = base_type["name"]
else:
infos["base_type"] = base_type["value"].getName()
elif basetype_content["name"] == "enum":
infos["type"] = "Enumerated"
infos["values"] = []
for value in basetype_content["value"].values.getValue():
infos["values"].append(value.getName())
elif basetype_content["name"] == "array":
infos["type"] = "Array"
infos["dimensions"] = []
for dimension in basetype_content["value"].getDimension():
infos["dimensions"].append(str(dimension.getUpper()))
base_type = basetype_content["value"].baseType.getContent()
if base_type["value"] is None:
infos["base_type"] = base_type["name"]
else:
infos["base_type"] = base_type["value"].getName()
if datatype.initialValue is not None:
infos["initial"] = str(datatype.initialValue.getValue())
else:
infos["initial"] = ""
return infos
return None
# Change the data type informations
def SetDataTypeInfos(self, tagname, infos):
words = tagname.split("::")
if words[0] == "D":
datatype = self.Project.getDataType(words[1])
if infos["type"] == "Directly":
if infos["base_type"] in self.GetBaseTypes():
if infos["base_type"] == "STRING":
datatype.baseType.setContent("string", plcopen.string())
elif infos["base_type"] == "WSTRING":
datatype.baseType.setContent("wstring", plcopen.wstring())
else:
datatype.baseType.setContent(infos["base_type"], None)
else:
derived_datatype = plcopen.derived()
derived_datatype.setName(infos["base_type"])
datatype.baseType.setContent("derived", derived_datatype)
elif infos["type"] == "Subrange":
if infos["base_type"] in GetSubTypes("ANY_UINT"):
subrange = plcopen.subrangeUnsigned()
datatype.baseType.setContent("subrangeUnsigned", subrange)
else:
subrange = plcopen.subrangeSigned()
datatype.baseType.setContent("subrangeSigned", subrange)
subrange.range.setLower(infos["min"])
subrange.range.setUpper(infos["max"])
if infos["base_type"] in self.GetBaseTypes():
subrange.baseType.setContent(infos["base_type"], None)
else:
derived_datatype = plcopen.derived()
derived_datatype.setName(infos["base_type"])
subrange.baseType.setContent("derived", derived_datatype)
elif infos["type"] == "Enumerated":
enumerated = plcopen.enum()
for enum_value in infos["values"]:
value = plcopen.values_value()
value.setName(enum_value)
enumerated.values.appendValue(value)
datatype.baseType.setContent("enum", enumerated)
elif infos["type"] == "Array":
array = plcopen.array()
for dimension in infos["dimensions"]:
dimension_range = plcopen.rangeSigned()
dimension_range.setLower(1)
dimension_range.setUpper(int(dimension))
array.appendDimension(dimension_range)
if infos["base_type"] in self.GetBaseTypes():
if infos["base_type"] == "STRING":
array.baseType.setContent("string", plcopen.string())
elif infos["base_type"] == "WSTRING":
array.baseType.setContent("wstring", plcopen.wstring())
else:
array.baseType.setContent(infos["base_type"], None)
else:
derived_datatype = plcopen.derived()
derived_datatype.setName(infos["base_type"])
array.baseType.setContent("derived", derived_datatype)
datatype.baseType.setContent("array", array)
if infos["initial"] != "":
if datatype.initialValue is None:
datatype.initialValue = plcopen.value()
datatype.initialValue.setValue(infos["initial"])
else:
datatype.initialValue = None
self.RefreshDataTypeUsingTree()
self.RefreshDataTypes()
self.BufferProject()
#-------------------------------------------------------------------------------
# Project opened Pous management functions
#-------------------------------------------------------------------------------
# Return edited element
def GetEditedElement(self, tagname):
words = tagname.split("::")
if words[0] == "P":
return self.Project.getPou(words[1])
if words[0] in ['T', 'A']:
pou = self.Project.getPou(words[1])
if words[0] == 'T':
return pou.getTransition(words[2])
elif words[0] == 'A':
return pou.getAction(words[2])
elif words[0] == 'C':
return self.Project.getConfiguration(words[1])
elif words[0] == 'R':
return self.Project.getConfigurationResource(words[1], words[2])
return None
# Return edited element name
def GetEditedElementName(self, tagname):
words = tagname.split("::")
if words[0] in ["P","C"]:
return words[1]
else:
return words[2]
return None
# Return edited element name and type
def GetEditedElementType(self, tagname):
words = tagname.split("::")
if words[0] in ["P","T","A"]:
return words[1], self.GetPouType(words[1])
return None, None
# Return language in which edited element is written
def GetEditedElementBodyType(self, tagname):
words = tagname.split("::")
if words[0] == "P":
return self.GetPouBodyType(words[1])
elif words[0] == 'T':
return self.GetTransitionBodyType(words[1], words[2])
elif words[0] == 'A':
return self.GetActionBodyType(words[1], words[2])
return None
# Return the edited element variables
def GetEditedElementInterfaceVars(self, tagname):
words = tagname.split("::")
if words[0] in ["P","T","A"]:
pou = self.Project.getPou(words[1])
return self.GetPouInterfaceVars(pou)
return []
# Return the edited element return type
def GetEditedElementInterfaceReturnType(self, tagname):
words = tagname.split("::")
if words[0] == "P":
pou = self.Project.getPou(words[1])
return self.GetPouInterfaceReturnType(pou)
elif words[0] == 'T':
return "BOOL"
return None
# Change the edited element text
def SetEditedElementText(self, tagname, text):
element = self.GetEditedElement(tagname)
if element != None:
element.setText(text)
self.RefreshPouUsingTree()
# Return the edited element text
def GetEditedElementText(self, tagname):
element = self.GetEditedElement(tagname)
if element != None:
return element.getText()
return ""
# Return the edited element transitions
def GetEditedElementTransitions(self, tagname):
pou = self.GetEditedElement(tagname)
if pou != None and pou.getBodyType() == "SFC":
transitions = []
for transition in pou.getTransitionList():
transitions.append(transition.getName())
return transitions
return []
# Return edited element transitions
def GetEditedElementActions(self, tagname):
pou = self.GetEditedElement(tagname)
if pou != None and pou.getBodyType() == "SFC":
actions = []
for action in pou.getActionList():
actions.append(action.getName())
return actions
return []
# Return the names of the pou elements
def GetEditedElementVariables(self, tagname):
words = tagname.split("::")
if words[0] in ["P","T","A"]:
return self.GetProjectPouVariables(words[1])
return []
# Return the current pou editing informations
def GetEditedElementInstanceInfos(self, tagname, id = None, exclude = []):
infos = {}
instance = None
element = self.GetEditedElement(tagname)
if element is not None:
# if id is defined
if id is not None:
instance = element.getInstance(id)
else:
instance = element.getRandomInstance(exclude)
if instance is not None:
if id is not None:
infos["id"] = id
else:
infos["id"] = instance.getLocalId()
infos["x"] = instance.getX()
infos["y"] = instance.getY()
infos["height"] = instance.getHeight()
infos["width"] = instance.getWidth()
if isinstance(instance, plcopen.block):
infos["name"] = instance.getInstanceName()
infos["type"] = instance.getTypeName()
executionOrder = instance.getExecutionOrderId()
if executionOrder is not None:
infos["executionOrder"] = executionOrder
else:
infos["executionOrder"] = 0
infos["connectors"] = {"inputs":[],"outputs":[]}
for variable in instance.inputVariables.getVariable():
connector = {}
connector["name"] = variable.getFormalParameter()
connector["position"] = variable.connectionPointIn.getRelPosition()
connector["negated"] = variable.getNegated()
connector["edge"] = variable.getConnectorEdge()
connector["links"] = []
connections = variable.connectionPointIn.getConnections()
if connections:
for link in connections:
dic = {"refLocalId":link.getRefLocalId(),"points":link.getPoints(),"formalParameter":link.getFormalParameter()}
connector["links"].append(dic)
infos["connectors"]["inputs"].append(connector)
for variable in instance.outputVariables.getVariable():
connector = {}
connector["name"] = variable.getFormalParameter()
connector["position"] = variable.connectionPointOut.getRelPosition()
connector["negated"] = variable.getNegated()
connector["edge"] = variable.getConnectorEdge()
infos["connectors"]["outputs"].append(connector)
elif isinstance(instance, plcopen.inVariable):
infos["name"] = instance.getExpression()
infos["value_type"] = self.GetEditedElementVarValueType(tagname, infos["name"])
infos["type"] = "input"
executionOrder = instance.getExecutionOrderId()
if executionOrder is not None:
infos["executionOrder"] = executionOrder
else:
infos["executionOrder"] = 0
infos["connector"] = {}
infos["connector"]["position"] = instance.connectionPointOut.getRelPosition()
infos["connector"]["negated"] = instance.getNegated()
infos["connector"]["edge"] = instance.getConnectorEdge()
elif isinstance(instance, plcopen.outVariable):
infos["name"] = instance.getExpression()
infos["value_type"] = self.GetEditedElementVarValueType(tagname, infos["name"])
infos["type"] = "output"
executionOrder = instance.getExecutionOrderId()
if executionOrder is not None:
infos["executionOrder"] = executionOrder
else:
infos["executionOrder"] = 0
infos["connector"] = {}
infos["connector"]["position"] = instance.connectionPointIn.getRelPosition()
infos["connector"]["negated"] = instance.getNegated()
infos["connector"]["edge"] = instance.getConnectorEdge()
infos["connector"]["links"] = []
connections = instance.connectionPointIn.getConnections()
if connections:
for link in connections:
dic = {"refLocalId":link.getRefLocalId(),"points":link.getPoints(),"formalParameter":link.getFormalParameter()}
infos["connector"]["links"].append(dic)
elif isinstance(instance, plcopen.inOutVariable):
infos["name"] = instance.getExpression()
infos["value_type"] = self.GetEditedElementVarValueType(tagname, infos["name"])
infos["type"] = "inout"
executionOrder = instance.getExecutionOrderId()
if executionOrder is not None:
infos["executionOrder"] = executionOrder
else:
infos["executionOrder"] = 0
infos["connectors"] = {"input":{},"output":{}}
infos["connectors"]["output"]["position"] = instance.connectionPointOut.getRelPosition()
infos["connectors"]["output"]["negated"] = instance.getNegatedOut()
infos["connectors"]["output"]["edge"] = instance.getOutputEdge()
infos["connectors"]["input"]["position"] = instance.connectionPointIn.getRelPosition()
infos["connectors"]["input"]["negated"] = instance.getNegatedIn()
infos["connectors"]["input"]["edge"] = instance.getInputEdge()
infos["connectors"]["input"]["links"] = []
connections = instance.connectionPointIn.getConnections()
if connections:
for link in connections:
dic = {"refLocalId":link.getRefLocalId(),"points":link.getPoints(),"formalParameter":link.getFormalParameter()}
infos["connectors"]["input"]["links"].append(dic)
elif isinstance(instance, plcopen.continuation):
infos["name"] = instance.getName()
infos["type"] = "continuation"
infos["connector"] = {}
infos["connector"]["position"] = instance.connectionPointOut.getRelPosition()
elif isinstance(instance, plcopen.connector):
infos["name"] = instance.getName()
infos["type"] = "connection"
infos["connector"] = {}
infos["connector"]["position"] = instance.connectionPointIn.getRelPosition()
infos["connector"]["links"] = []
connections = instance.connectionPointIn.getConnections()
if connections:
for link in connections:
dic = {"refLocalId":link.getRefLocalId(),"points":link.getPoints(),"formalParameter":link.getFormalParameter()}
infos["connector"]["links"].append(dic)
elif isinstance(instance, plcopen.comment):
infos["type"] = "comment"
infos["content"] = instance.getContentText()
elif isinstance(instance, plcopen.leftPowerRail):
infos["type"] = "leftPowerRail"
infos["connectors"] = []
for connection in instance.getConnectionPointOut():
connector = {}
connector["position"] = connection.getRelPosition()
infos["connectors"].append(connector)
elif isinstance(instance, plcopen.rightPowerRail):
infos["type"] = "rightPowerRail"
infos["connectors"] = []
for connection in instance.getConnectionPointIn():
connector = {}
connector["position"] = connection.getRelPosition()
connector["links"] = []
connections = connection.getConnections()
if connections:
for link in connection.getConnections():
dic = {"refLocalId":link.getRefLocalId(),"points":link.getPoints(),"formalParameter":link.getFormalParameter()}
connector["links"].append(dic)
infos["connectors"].append(connector)
elif isinstance(instance, plcopen.contact):
infos["name"] = instance.getVariable()
infos["type"] = "contact"
executionOrder = instance.getExecutionOrderId()
if executionOrder is not None:
infos["executionOrder"] = executionOrder
else:
infos["executionOrder"] = 0
infos["negated"] = instance.getNegated()
infos["edge"] = instance.getContactEdge()
infos["connectors"] = {"input":{},"output":{}}
infos["connectors"]["input"]["position"] = instance.connectionPointIn.getRelPosition()
infos["connectors"]["input"]["links"] = []
connections = instance.connectionPointIn.getConnections()
if connections:
for link in connections:
dic = {"refLocalId":link.getRefLocalId(),"points":link.getPoints(),"formalParameter":link.getFormalParameter()}
infos["connectors"]["input"]["links"].append(dic)
infos["connectors"]["output"]["position"] = instance.connectionPointOut.getRelPosition()
elif isinstance(instance, plcopen.coil):
infos["name"] = instance.getVariable()
infos["type"] = "coil"
executionOrder = instance.getExecutionOrderId()
if executionOrder is not None:
infos["executionOrder"] = executionOrder
else:
infos["executionOrder"] = 0
infos["negated"] = instance.getNegated()
infos["storage"] = instance.getCoilStorage()
infos["connectors"] = {"input":{},"output":{}}
infos["connectors"]["input"]["position"] = instance.connectionPointIn.getRelPosition()
infos["connectors"]["input"]["links"] = []
connections = instance.connectionPointIn.getConnections()
if connections:
for link in connections:
dic = {"refLocalId":link.getRefLocalId(),"points":link.getPoints(),"formalParameter":link.getFormalParameter()}
infos["connectors"]["input"]["links"].append(dic)
infos["connectors"]["output"]["position"] = instance.connectionPointOut.getRelPosition()
elif isinstance(instance, plcopen.step):
infos["name"] = instance.getName()
infos["type"] = "step"
infos["initial"] = instance.getInitialStep()
infos["connectors"] = {}
if instance.connectionPointIn:
infos["connectors"]["input"] = {}
infos["connectors"]["input"]["position"] = instance.connectionPointIn.getRelPosition()
infos["connectors"]["input"]["links"] = []
connections = instance.connectionPointIn.getConnections()
if connections:
for link in connections:
dic = {"refLocalId":link.getRefLocalId(),"points":link.getPoints(),"formalParameter":link.getFormalParameter()}
infos["connectors"]["input"]["links"].append(dic)
if instance.connectionPointOut:
infos["connectors"]["output"] = {"position" : instance.connectionPointOut.getRelPosition()}
if instance.connectionPointOutAction:
infos["connectors"]["action"] = {"position" : instance.connectionPointOutAction.getRelPosition()}
elif isinstance(instance, plcopen.transition):
infos["type"] = "transition"
condition = instance.getConditionContent()
priority = instance.getPriority()
if priority == None:
infos["priority"] = 0
else:
infos["priority"] = priority
infos["condition_type"] = condition["type"]
infos["connectors"] = {"input":{},"output":{}}
infos["connectors"]["input"]["position"] = instance.connectionPointIn.getRelPosition()
infos["connectors"]["input"]["links"] = []
connections = instance.connectionPointIn.getConnections()
if connections:
for link in connections:
dic = {"refLocalId":link.getRefLocalId(),"points":link.getPoints(),"formalParameter":link.getFormalParameter()}
infos["connectors"]["input"]["links"].append(dic)
infos["connectors"]["output"]["position"] = instance.connectionPointOut.getRelPosition()
if infos["condition_type"] == "connection":
infos["connectors"]["connection"] = {}
infos["connectors"]["connection"]["links"] = []
connections = instance.getConnections()
if connections:
for link in connections:
dic = {"refLocalId":link.getRefLocalId(),"points":link.getPoints(),"formalParameter":link.getFormalParameter()}
infos["connectors"]["connection"]["links"].append(dic)
infos["condition"] = None
else:
infos["condition"] = condition["value"]
elif isinstance(instance, (plcopen.selectionDivergence, plcopen.simultaneousDivergence)):
if isinstance(instance, plcopen.selectionDivergence):
infos["type"] = "selectionDivergence"
else:
infos["type"] = "simultaneousDivergence"
infos["connectors"] = {"inputs":[],"outputs":[]}
connector = {}
connector["position"] = instance.connectionPointIn.getRelPosition()
connector["links"] = []
connections = instance.connectionPointIn.getConnections()
if connections:
for link in connections:
dic = {"refLocalId":link.getRefLocalId(),"points":link.getPoints(),"formalParameter":link.getFormalParameter()}
connector["links"].append(dic)
infos["connectors"]["inputs"].append(connector)
for sequence in instance.getConnectionPointOut():
connector = {}
connector["position"] = sequence.getRelPosition()
infos["connectors"]["outputs"].append(connector)
elif isinstance(instance, (plcopen.selectionConvergence, plcopen.simultaneousConvergence)):
if isinstance(instance, plcopen.selectionConvergence):
infos["type"] = "selectionConvergence"
else:
infos["type"] = "simultaneousConvergence"
infos["connectors"] = {"inputs":[],"outputs":[]}
for sequence in instance.getConnectionPointIn():
connector = {}
connector["position"] = sequence.getRelPosition()
connector["links"] = []
connections = sequence.getConnections()
if connections:
for link in connections:
dic = {"refLocalId":link.getRefLocalId(),"points":link.getPoints(),"formalParameter":link.getFormalParameter()}
connector["links"].append(dic)
infos["connectors"]["inputs"].append(connector)
connector = {}
connector["position"] = instance.connectionPointOut.getRelPosition()
infos["connectors"]["outputs"].append(connector)
elif isinstance(instance, plcopen.jumpStep):
infos["type"] = "jump"
infos["target"] = instance.getTargetName()
infos["connector"] = {}
infos["connector"]["position"] = instance.connectionPointIn.getRelPosition()
infos["connector"]["links"] = []
connections = instance.connectionPointIn.getConnections()
if connections:
for link in connections:
dic = {"refLocalId":link.getRefLocalId(),"points":link.getPoints(),"formalParameter":link.getFormalParameter()}
infos["connector"]["links"].append(dic)
elif isinstance(instance, plcopen.actionBlock):
infos["type"] = "actionBlock"
infos["actions"] = instance.getActions()
infos["connector"] = {}
infos["connector"]["position"] = instance.connectionPointIn.getRelPosition()
infos["connector"]["links"] = []
connections = instance.connectionPointIn.getConnections()
if connections:
for link in connections:
dic = {"refLocalId":link.getRefLocalId(),"points":link.getPoints(),"formalParameter":link.getFormalParameter()}
infos["connector"]["links"].append(dic)
return infos
return False
def ClearEditedElementExecutionOrder(self, tagname):
element = self.GetEditedElement(tagname)
if element is not None:
element.resetExecutionOrder()
def ResetEditedElementExecutionOrder(self, tagname):
element = self.GetEditedElement(tagname)
if element is not None:
element.compileExecutionOrder()
# Return the variable type of the given pou
def GetEditedElementVarValueType(self, tagname, varname):
words = tagname.split("::")
if words[0] in ["P","T","A"]:
pou = self.Project.getPou(words[1])
for type, varlist in pou.getVars():
for var in varlist.getVariable():
if var.getName() == varname:
vartype_content = var.getType().getContent()
if vartype_content["name"] == "derived":
return vartype_content["value"].getName()
elif vartype_content["name"] in ["string", "wstring"]:
return vartype_content["name"].upper()
else:
return vartype_content["name"]
return None
def SetConnectionWires(self, connection, connector):
wires = connector.GetWires()
idx = 0
for wire, handle in wires:
points = wire.GetPoints(handle != 0)
if handle == 0:
result = wire.GetConnectedInfos(-1)
else:
result = wire.GetConnectedInfos(0)
if result != None:
refLocalId, formalParameter = result
connection.addConnection()
connection.setConnectionId(idx, refLocalId)
connection.setConnectionPoints(idx, points)
if formalParameter != "":
connection.setConnectionParameter(idx, formalParameter)
else:
connection.setConnectionParameter(idx, None)
idx += 1
def AddEditedElementPouVar(self, tagname, type, name):
words = tagname.split("::")
if words[0] in ['P', 'T', 'A']:
pou = self.Project.getPou(words[1])
pou.addPouVar(type, name)
def ChangeEditedElementPouVar(self, tagname, old_type, old_name, new_type, new_name):
words = tagname.split("::")
if words[0] in ['P', 'T', 'A']:
pou = self.Project.getPou(words[1])
pou.changePouVar(old_type, old_name, new_type, new_name)
def AddEditedElementBlock(self, tagname, id, blocktype, blockname = None):
element = self.GetEditedElement(tagname)
if element is not None:
block = plcopen.block()
block.setLocalId(id)
block.setTypeName(blocktype)
blocktype_infos = GetBlockType(blocktype)
if blocktype_infos["type"] != "function" and blockname is not None:
block.setInstanceName(blockname)
self.AddEditedElementPouVar(tagname, blocktype, blockname)
element.addInstance("block", block)
self.RefreshPouUsingTree()
def SetEditedElementBlockInfos(self, tagname, id, infos):
element = self.GetEditedElement(tagname)
if element is not None:
block = element.getInstance(id)
blocktype = infos.get("type", block.getTypeName())
blocktype_infos = GetBlockType(blocktype)
if blocktype_infos["type"] != "function":
if "name" in infos or "type" in infos:
old_name = block.getInstanceName()
old_type = block.getTypeName()
new_name = infos.get("name", old_name)
new_type = infos.get("type", old_type)
self.ChangeEditedElementPouVar(tagname, old_type, old_name, new_type, new_name)
for param, value in infos.items():
if param == "name":
block.setInstanceName(value)
elif param == "type":
block.setTypeName(value)
elif param == "executionOrder" and block.getExecutionOrderId() != value:
self.GetEditedElement(tagname).setElementExecutionOrder(block, value)
elif param == "height":
block.setHeight(value)
elif param == "width":
block.setWidth(value)
elif param == "x":
block.setX(value)
elif param == "y":
block.setY(value)
elif param == "connectors":
block.inputVariables.setVariable([])
block.outputVariables.setVariable([])
for connector in value["inputs"]:
variable = plcopen.inputVariables_variable()
variable.setFormalParameter(connector.GetName())
if connector.IsNegated():
variable.setNegated(True)
if connector.GetEdge() != "none":
variable.setConnectorEdge(connector.GetEdge())
position = connector.GetRelPosition()
variable.connectionPointIn.setRelPosition(position.x, position.y)
self.SetConnectionWires(variable.connectionPointIn, connector)
block.inputVariables.appendVariable(variable)
for connector in value["outputs"]:
variable = plcopen.outputVariables_variable()
variable.setFormalParameter(connector.GetName())
if connector.IsNegated():
variable.setNegated(True)
if connector.GetEdge() != "none":
variable.setConnectorEdge(connector.GetEdge())
position = connector.GetRelPosition()
variable.addConnectionPointOut()
variable.connectionPointOut.setRelPosition(position.x, position.y)
block.outputVariables.appendVariable(variable)
self.RefreshPouUsingTree()
def AddEditedElementVariable(self, tagname, id, type):
element = self.GetEditedElement(tagname)
if element is not None:
if type == INPUT:
name = "inVariable"
variable = plcopen.inVariable()
elif type == OUTPUT:
name = "outVariable"
variable = plcopen.outVariable()
elif type == INOUT:
name = "inOutVariable"
variable = plcopen.inOutVariable()
variable.setLocalId(id)
element.addInstance(name, variable)
def SetEditedElementVariableInfos(self, tagname, id, infos):
element = self.GetEditedElement(tagname)
if element is not None:
variable = element.getInstance(id)
for param, value in infos.items():
if param == "name":
variable.setExpression(value)
elif param == "executionOrder" and variable.getExecutionOrderId() != value:
self.GetEditedElement(tagname).setElementExecutionOrder(variable, value)
elif param == "height":
variable.setHeight(value)
elif param == "width":
variable.setWidth(value)
elif param == "x":
variable.setX(value)
elif param == "y":
variable.setY(value)
elif param == "connectors":
if isinstance(variable, plcopen.inVariable):
if value["output"].IsNegated():
variable.setNegated(True)
if value["output"].GetEdge() != "none":
variable.setConnectorEdge(value["output"].GetEdge())
position = value["output"].GetRelPosition()
variable.addConnectionPointOut()
variable.connectionPointOut.setRelPosition(position.x, position.y)
elif isinstance(variable, plcopen.outVariable):
if value["input"].IsNegated():
variable.setNegated(True)
if value["input"].GetEdge() != "none":
variable.setConnectorEdge(value["input"].GetEdge())
position = value["input"].GetRelPosition()
variable.addConnectionPointIn()
variable.connectionPointIn.setRelPosition(position.x, position.y)
self.SetConnectionWires(variable.connectionPointIn, value["input"])
elif isinstance(variable, plcopen.inOutVariable):
if value["input"].IsNegated():
variable.setNegatedIn(True)
if value["input"].GetEdge() != "none":
variable.setInputEdge(value["input"].GetEdge())
if value["output"].IsNegated():
variable.setNegatedOut(True)
if value["output"].GetEdge() != "none":
variable.setOutputEdge(value["output"].GetEdge())
position = value["output"].GetRelPosition()
variable.addConnectionPointOut()
variable.connectionPointOut.setRelPosition(position.x, position.y)
position = value["input"].GetRelPosition()
variable.addConnectionPointIn()
variable.connectionPointIn.setRelPosition(position.x, position.y)
self.SetConnectionWires(variable.connectionPointIn, value["input"])
def AddEditedElementConnection(self, tagname, id, type):
element = self.GetEditedElement(tagname)
if element is not None:
if type == CONNECTOR:
name = "connector"
connection = plcopen.connector()
elif type == CONTINUATION:
name = "continuation"
connection = plcopen.continuation()
connection.setLocalId(id)
element.addInstance(name, connection)
def SetEditedElementConnectionInfos(self, tagname, id, infos):
element = self.GetEditedElement(tagname)
if element is not None:
connection = element.getInstance(id)
for param, value in infos.items():
if param == "name":
connection.setName(value)
elif param == "height":
connection.setHeight(value)
elif param == "width":
connection.setWidth(value)
elif param == "x":
connection.setX(value)
elif param == "y":
connection.setY(value)
elif param == "connector":
position = value.GetRelPosition()
if isinstance(connection, plcopen.continuation):
connection.addConnectionPointOut()
connection.connectionPointOut.setRelPosition(position.x, position.y)
elif isinstance(connection, plcopen.connector):
connection.addConnectionPointIn()
connection.connectionPointIn.setRelPosition(position.x, position.y)
self.SetConnectionWires(connection.connectionPointIn, value)
def AddEditedElementComment(self, tagname, id):
element = self.GetEditedElement(tagname)
if element is not None:
comment = plcopen.comment()
comment.setLocalId(id)
element.addInstance("comment", comment)
def SetEditedElementCommentInfos(self, tagname, id, infos):
element = self.GetEditedElement(tagname)
if element is not None:
comment = element.getInstance(id)
for param, value in infos.items():
if param == "content":
comment.setContentText(value)
elif param == "height":
comment.setHeight(value)
elif param == "width":
comment.setWidth(value)
elif param == "x":
comment.setX(value)
elif param == "y":
comment.setY(value)
def AddEditedElementPowerRail(self, tagname, id, type):
element = self.GetEditedElement(tagname)
if element is not None:
if type == LEFTRAIL:
name = "leftPowerRail"
powerrail = plcopen.leftPowerRail()
elif type == RIGHTRAIL:
name = "rightPowerRail"
powerrail = plcopen.rightPowerRail()
powerrail.setLocalId(id)
element.addInstance(name, powerrail)
def SetEditedElementPowerRailInfos(self, tagname, id, infos):
element = self.GetEditedElement(tagname)
if element is not None:
powerrail = element.getInstance(id)
for param, value in infos.items():
if param == "height":
powerrail.setHeight(value)
elif param == "width":
powerrail.setWidth(value)
elif param == "x":
powerrail.setX(value)
elif param == "y":
powerrail.setY(value)
elif param == "connectors":
if isinstance(powerrail, plcopen.leftPowerRail):
powerrail.setConnectionPointOut([])
for connector in value:
position = connector.GetRelPosition()
connection = plcopen.leftPowerRail_connectionPointOut()
connection.setRelPosition(position.x, position.y)
powerrail.connectionPointOut.append(connection)
elif isinstance(powerrail, plcopen.rightPowerRail):
powerrail.setConnectionPointIn([])
for connector in value:
position = connector.GetRelPosition()
connection = plcopen.connectionPointIn()
connection.setRelPosition(position.x, position.y)
self.SetConnectionWires(connection, connector)
powerrail.connectionPointIn.append(connection)
def AddEditedElementContact(self, tagname, id):
element = self.GetEditedElement(tagname)
if element is not None:
contact = plcopen.contact()
contact.setLocalId(id)
element.addInstance("contact", contact)
def SetEditedElementContactInfos(self, tagname, id, infos):
element = self.GetEditedElement(tagname)
if element is not None:
contact = element.getInstance(id)
for param, value in infos.items():
if param == "name":
contact.setVariable(value)
elif param == "type":
if value == CONTACT_NORMAL:
contact.setNegated(False)
contact.setContactEdge("none")
elif value == CONTACT_REVERSE:
contact.setNegated(True)
contact.setContactEdge("none")
elif value == CONTACT_RISING:
contact.setNegated(False)
contact.setContactEdge("rising")
elif value == CONTACT_FALLING:
contact.setNegated(False)
contact.setContactEdge("falling")
elif param == "height":
contact.setHeight(value)
elif param == "width":
contact.setWidth(value)
elif param == "x":
contact.setX(value)
elif param == "y":
contact.setY(value)
elif param == "connectors":
input_connector = value["input"]
position = input_connector.GetRelPosition()
contact.addConnectionPointIn()
contact.connectionPointIn.setRelPosition(position.x, position.y)
self.SetConnectionWires(contact.connectionPointIn, input_connector)
output_connector = value["output"]
position = output_connector.GetRelPosition()
contact.addConnectionPointOut()
contact.connectionPointOut.setRelPosition(position.x, position.y)
def AddEditedElementCoil(self, tagname, id):
element = self.GetEditedElement(tagname)
if element is not None:
coil = plcopen.coil()
coil.setLocalId(id)
element.addInstance("coil", coil)
def SetEditedElementCoilInfos(self, tagname, id, infos):
element = self.GetEditedElement(tagname)
if element is not None:
coil = element.getInstance(id)
for param, value in infos.items():
if param == "name":
coil.setVariable(value)
elif param == "type":
if value == COIL_NORMAL:
coil.setNegated(False)
coil.setCoilStorage("none")
elif value == COIL_REVERSE:
coil.setNegated(True)
coil.setCoilStorage("none")
elif value == COIL_SET:
coil.setNegated(False)
coil.setCoilStorage("set")
elif value == COIL_RESET:
coil.setNegated(False)
coil.setCoilStorage("reset")
elif param == "height":
coil.setHeight(value)
elif param == "width":
coil.setWidth(value)
elif param == "x":
coil.setX(value)
elif param == "y":
coil.setY(value)
elif param == "connectors":
input_connector = value["input"]
position = input_connector.GetRelPosition()
coil.addConnectionPointIn()
coil.connectionPointIn.setRelPosition(position.x, position.y)
self.SetConnectionWires(coil.connectionPointIn, input_connector)
output_connector = value["output"]
position = output_connector.GetRelPosition()
coil.addConnectionPointOut()
coil.connectionPointOut.setRelPosition(position.x, position.y)
def AddEditedElementStep(self, tagname, id):
element = self.GetEditedElement(tagname)
if element is not None:
step = plcopen.step()
step.setLocalId(id)
element.addInstance("step", step)
def SetEditedElementStepInfos(self, tagname, id, infos):
element = self.GetEditedElement(tagname)
if element is not None:
step = element.getInstance(id)
for param, value in infos.items():
if param == "name":
step.setName(value)
elif param == "initial":
step.setInitialStep(value)
elif param == "height":
step.setHeight(value)
elif param == "width":
step.setWidth(value)
elif param == "x":
step.setX(value)
elif param == "y":
step.setY(value)
elif param == "connectors":
input_connector = value["input"]
if input_connector:
position = input_connector.GetRelPosition()
step.addConnectionPointIn()
step.connectionPointIn.setRelPosition(position.x, position.y)
self.SetConnectionWires(step.connectionPointIn, input_connector)
else:
step.deleteConnectionPointIn()
output_connector = value["output"]
if output_connector:
position = output_connector.GetRelPosition()
step.addConnectionPointOut()
step.connectionPointOut.setRelPosition(position.x, position.y)
else:
step.deleteConnectionPointOut()
action_connector = value["action"]
if action_connector:
position = action_connector.GetRelPosition()
step.addConnectionPointOutAction()
step.connectionPointOutAction.setRelPosition(position.x, position.y)
else:
step.deleteConnectionPointOutAction()
def AddEditedElementTransition(self, tagname, id):
element = self.GetEditedElement(tagname)
if element is not None:
transition = plcopen.transition()
transition.setLocalId(id)
element.addInstance("transition", transition)
def SetEditedElementTransitionInfos(self, tagname, id, infos):
element = self.GetEditedElement(tagname)
if element is not None:
transition = element.getInstance(id)
for param, value in infos.items():
if param == "type" and value != "connection":
transition.setConditionContent(value, infos["condition"])
elif param == "height":
transition.setHeight(value)
elif param == "width":
transition.setWidth(value)
elif param == "x":
transition.setX(value)
elif param == "y":
transition.setY(value)
elif param == "priority":
if value != 0:
transition.setPriority(value)
else:
transition.setPriority(None)
elif param == "connectors":
input_connector = value["input"]
position = input_connector.GetRelPosition()
transition.addConnectionPointIn()
transition.connectionPointIn.setRelPosition(position.x, position.y)
self.SetConnectionWires(transition.connectionPointIn, input_connector)
output_connector = value["output"]
position = output_connector.GetRelPosition()
transition.addConnectionPointOut()
transition.connectionPointOut.setRelPosition(position.x, position.y)
if infos.get("type", None) == "connection":
transition.setConditionContent("connection", None)
connection_connector = value["connection"]
self.SetConnectionWires(transition, connection_connector)
def AddEditedElementDivergence(self, tagname, id, type):
element = self.GetEditedElement(tagname)
if element is not None:
if type == SELECTION_DIVERGENCE:
name = "selectionDivergence"
divergence = plcopen.selectionDivergence()
elif type == SELECTION_CONVERGENCE:
name = "selectionConvergence"
divergence = plcopen.selectionConvergence()
elif type == SIMULTANEOUS_DIVERGENCE:
name = "simultaneousDivergence"
divergence = plcopen.simultaneousDivergence()
elif type == SIMULTANEOUS_CONVERGENCE:
name = "simultaneousConvergence"
divergence = plcopen.simultaneousConvergence()
divergence.setLocalId(id)
element.addInstance(name, divergence)
def SetEditedElementDivergenceInfos(self, tagname, id, infos):
element = self.GetEditedElement(tagname)
if element is not None:
divergence = element.getInstance(id)
for param, value in infos.items():
if param == "height":
divergence.setHeight(value)
elif param == "width":
divergence.setWidth(value)
elif param == "x":
divergence.setX(value)
elif param == "y":
divergence.setY(value)
elif param == "connectors":
input_connectors = value["inputs"]
if isinstance(divergence, (plcopen.selectionDivergence, plcopen.simultaneousDivergence)):
position = input_connectors[0].GetRelPosition()
divergence.addConnectionPointIn()
divergence.connectionPointIn.setRelPosition(position.x, position.y)
self.SetConnectionWires(divergence.connectionPointIn, input_connectors[0])
else:
divergence.setConnectionPointIn([])
for input_connector in input_connectors:
position = input_connector.GetRelPosition()
if isinstance(divergence, plcopen.selectionConvergence):
connection = plcopen.selectionConvergence_connectionPointIn()
else:
connection = plcopen.connectionPointIn()
connection.setRelPosition(position.x, position.y)
self.SetConnectionWires(connection, input_connector)
divergence.appendConnectionPointIn(connection)
output_connectors = value["outputs"]
if isinstance(divergence, (plcopen.selectionConvergence, plcopen.simultaneousConvergence)):
position = output_connectors[0].GetRelPosition()
divergence.addConnectionPointOut()
divergence.connectionPointOut.setRelPosition(position.x, position.y)
else:
divergence.setConnectionPointOut([])
for output_connector in output_connectors:
position = output_connector.GetRelPosition()
if isinstance(divergence, plcopen.selectionDivergence):
connection = plcopen.selectionDivergence_connectionPointOut()
else:
connection = plcopen.simultaneousDivergence_connectionPointOut()
connection.setRelPosition(position.x, position.y)
divergence.appendConnectionPointOut(connection)
def AddEditedElementJump(self, tagname, id):
element = self.GetEditedElement(tagname)
if element is not None:
jump = plcopen.jumpStep()
jump.setLocalId(id)
element.addInstance("jumpStep", jump)
def SetEditedElementJumpInfos(self, tagname, id, infos):
element = self.GetEditedElement(tagname)
if element is not None:
jump = element.getInstance(id)
for param, value in infos.items():
if param == "target":
jump.setTargetName(value)
elif param == "height":
jump.setHeight(value)
elif param == "width":
jump.setWidth(value)
elif param == "x":
jump.setX(value)
elif param == "y":
jump.setY(value)
elif param == "connector":
position = value.GetRelPosition()
jump.addConnectionPointIn()
jump.connectionPointIn.setRelPosition(position.x, position.y)
self.SetConnectionWires(jump.connectionPointIn, value)
def AddEditedElementActionBlock(self, tagname, id):
element = self.GetEditedElement(tagname)
if element is not None:
actionBlock = plcopen.actionBlock()
actionBlock.setLocalId(id)
element.addInstance("actionBlock", actionBlock)
def SetEditedElementActionBlockInfos(self, tagname, id, infos):
element = self.GetEditedElement(tagname)
if element is not None:
actionBlock = element.getInstance(id)
for param, value in infos.items():
if param == "actions":
actionBlock.setActions(value)
elif param == "height":
actionBlock.setHeight(value)
elif param == "width":
actionBlock.setWidth(value)
elif param == "x":
actionBlock.setX(value)
elif param == "y":
actionBlock.setY(value)
elif param == "connector":
position = value.GetRelPosition()
actionBlock.addConnectionPointIn()
actionBlock.connectionPointIn.setRelPosition(position.x, position.y)
self.SetConnectionWires(actionBlock.connectionPointIn, value)
def RemoveEditedElementInstance(self, tagname, id):
element = self.GetEditedElement(tagname)
if element is not None:
instance = element.getInstance(id)
if isinstance(instance, plcopen.block):
blocktype = instance.getTypeName()
element.removePouVar(blocktype, instance.getInstanceName())
element.removeInstance(id)
self.RefreshPouUsingTree()
def GetEditedResourceVariables(self, tagname):
varlist = []
words = tagname.split("::")
for var in self.GetConfigurationGlobalVars(words[1]):
if var["Type"] == "BOOL":
varlist.append(var["Name"])
for var in self.GetConfigurationResourceGlobalVars(words[1], words[2]):
if var["Type"] == "BOOL":
varlist.append(var["Name"])
return varlist
def SetEditedResourceInfos(self, tagname, tasks, instances):
resource = self.GetEditedElement(tagname)
if resource is not None:
resource.setTask([])
resource.setPouInstance([])
task_list = {}
for task in tasks:
new_task = plcopen.resource_task()
new_task.setName(task["Name"])
if task["Single"] != "":
new_task.setSingle(task["Single"])
result = duration_model.match(task["Interval"]).groups()
if reduce(lambda x, y: x or y != None, result):
values = []
for value in result[:-1]:
if value != None:
values.append(int(value))
else:
values.append(0)
values.append(int(float(result[-1]) * 1000))
new_task.setInterval(time(*values))
new_task.priority.setValue(int(task["Priority"]))
if task["Name"] != "":
task_list[task["Name"]] = new_task
resource.appendTask(new_task)
for instance in instances:
new_instance = plcopen.pouInstance()
new_instance.setName(instance["Name"])
new_instance.setType(instance["Type"])
if instance["Task"] != "":
task_list[instance["Task"]].appendPouInstance(new_instance)
else:
resource.appendPouInstance(new_instance)
def GetEditedResourceInfos(self, tagname):
resource = self.GetEditedElement(tagname)
if resource is not None:
tasks = resource.getTask()
instances = resource.getPouInstance()
tasks_data = []
instances_data = []
for task in tasks:
new_task = {}
new_task["Name"] = task.getName()
single = task.getSingle()
if single:
new_task["Single"] = single
else:
new_task["Single"] = ""
interval = task.getInterval()
if interval:
text = ""
if interval.hour != 0:
text += "%dh"%interval.hour
if interval.minute != 0:
text += "%dm"%interval.minute
if interval.second != 0:
text += "%ds"%interval.second
if interval.microsecond != 0:
if interval.microsecond % 1000 != 0:
text += "%.3fms"%(float(interval.microsecond) / 1000)
else:
text += "%dms"%(interval.microsecond / 1000)
new_task["Interval"] = text
else:
new_task["Interval"] = ""
new_task["Priority"] = str(task.priority.getValue())
tasks_data.append(new_task)
for instance in task.getPouInstance():
new_instance = {}
new_instance["Name"] = instance.getName()
new_instance["Type"] = instance.getType()
new_instance["Task"] = task.getName()
instances_data.append(new_instance)
for instance in instances:
new_instance = {}
new_instance["Name"] = instance.getName()
new_instance["Type"] = instance.getType()
new_instance["Task"] = ""
instances_data.append(new_instance)
return tasks_data, instances_data
def OpenXMLFile(self, filepath):
if self.VerifyXML:
if sys:
sys.stdout = HolePseudoFile()
result = pyxsval.parseAndValidate(filepath, os.path.join(ScriptDirectory, "plcopen", "TC6_XML_V10_B.xsd"))
if sys:
sys.stdout = sys.__stdout__
tree = result.getTree()
else:
xmlfile = open(filepath, 'r')
tree = minidom.parse(xmlfile)
xmlfile.close()
self.Project = plcopen.project()
for child in tree.childNodes:
if child.nodeType == tree.ELEMENT_NODE and child.nodeName == "project":
self.Project.loadXMLTree(child)
self.SetFilePath(filepath)
self.ProjectBuffer = UndoBuffer(self.Copy(self.Project), True)
self.Buffering = False
self.ElementsOpened = []
self.CurrentElementEditing = None
self.RefreshDataTypeUsingTree()
self.RefreshDataTypes()
self.RefreshPouUsingTree()
self.RefreshBlockTypes()
return None
return "No PLC project found"
def SaveXMLFile(self, filepath = None):
if not filepath and self.FilePath == "":
return False
else:
contentheader = self.Project.getContentHeader()
contentheader["modificationDateTime"] = datetime(*localtime()[:6])
self.Project.setContentHeader(contentheader)
text = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
extras = {"xmlns" : "http://www.plcopen.org/xml/tc6.xsd",
"xmlns:xhtml" : "http://www.w3.org/1999/xhtml",
"xmlns:xsi" : "http://www.w3.org/2001/XMLSchema-instance",
"xsi:schemaLocation" : "http://www.plcopen.org/xml/tc6.xsd http://www.plcopen.org/xml/tc6.xsd"}
text += self.Project.generateXMLText("project", 0, extras)
if self.VerifyXML:
if sys:
sys.stdout = HolePseudoFile()
pyxsval.parseAndValidateString(text, open(os.path.join(ScriptDirectory, "plcopen", "TC6_XML_V10_B.xsd"),"r").read())
if sys:
sys.stdout = sys.__stdout__
if filepath:
xmlfile = open(filepath,"w")
else:
xmlfile = open(self.FilePath,"w")
xmlfile.write(text)
xmlfile.close()
self.ProjectBuffer.CurrentSaved()
if filepath:
self.SetFilePath(filepath)
return True
#-------------------------------------------------------------------------------
# Current Buffering Management Functions
#-------------------------------------------------------------------------------
"""
Return a copy of the project
"""
def Copy(self, model):
return cPickle.loads(cPickle.dumps(model))
def BufferProject(self):
self.ProjectBuffer.Buffering(self.Copy(self.Project))
def StartBuffering(self):
self.ProjectBuffer.Buffering(self.Project)
self.Buffering = True
def EndBuffering(self):
if self.Buffering:
self.Project = self.Copy(self.Project)
self.Buffering = False
def ProjectIsSaved(self):
if self.ProjectBuffer:
return self.ProjectBuffer.IsCurrentSaved()
else:
return True
def LoadPrevious(self):
self.Project = self.Copy(self.ProjectBuffer.Previous())
def LoadNext(self):
self.Project = self.Copy(self.ProjectBuffer.Next())
def GetBufferState(self):
first = self.ProjectBuffer.IsFirst()
last = self.ProjectBuffer.IsLast()
return not first, not last