Beremiz plugins definitions.
--- a/Beremiz.py Tue Sep 04 17:16:42 2007 +0200
+++ b/Beremiz.py Tue Sep 04 17:58:29 2007 +0200
@@ -26,22 +26,10 @@
import wx
-from time import localtime
-from datetime import datetime
import types
import os, re, platform, sys, time, traceback, getopt, commands
-base_folder = os.path.split(sys.path[0])[0]
-sys.path.append(os.path.join(base_folder, "plcopeneditor"))
-sys.path.append(os.path.join(base_folder, "CanFestival-3", "objdictgen"))
-sys.path.append(os.path.join(base_folder, "wxsvg", "svgui", "defeditor"))
-
-iec2cc_path = os.path.join(base_folder, "matiec", "iec2cc")
-ieclib_path = os.path.join(base_folder, "matiec", "lib")
-
-from PLCOpenEditor import PLCOpenEditor, ProjectDialog
-from TextViewer import TextViewer
-from plcopen.structures import IEC_KEYWORDS#, AddPlugin
+
from plugger import PluginsRoot
class LogPseudoFile:
@@ -80,6 +68,41 @@
def isatty(self):
return false
+ def LogCommand(self, Command, sz_limit = 100):
+
+ import os, popen2, fcntl, select, signal
+
+ child = popen2.Popen3(Command, 1) # capture stdout and stderr from command
+ child.tochild.close() # don't need to talk to child
+ outfile = child.fromchild
+ outfd = outfile.fileno()
+ errfile = child.childerr
+ errfd = errfile.fileno()
+ outdata = errdata = ''
+ outeof = erreof = 0
+ outlen = errlen = 0
+ while 1:
+ ready = select.select([outfd,errfd],[],[]) # wait for input
+ if outfd in ready[0]:
+ outchunk = outfile.readline()
+ if outchunk == '': outeof = 1
+ else : outlen += 1
+ outdata += outchunk
+ self.write(outchunk)
+ if errfd in ready[0]:
+ errchunk = errfile.readline()
+ if errchunk == '': erreof = 1
+ else : errlen += 1
+ errdata += errchunk
+ self.write_warning(errchunk)
+ if outeof and erreof : break
+ if errlen > sz_limit or outlen > sz_limit :
+ os.kill(child.pid, signal.SIGTERM)
+ self.write_error("Output size reached limit -- killed\n")
+ break
+ err = child.wait()
+ return (err, outdata, errdata)
+
[ID_BEREMIZ, ID_BEREMIZMAINSPLITTER,
ID_BEREMIZSECONDSPLITTER, ID_BEREMIZLEFTPANEL,
ID_BEREMIZPARAMSPANEL, ID_BEREMIZLOGCONSOLE,
@@ -299,14 +322,12 @@
self.Log = LogPseudoFile(self.LogConsole)
- self.PluginRoot = PluginsRoot()
+ self.PluginRoot = PluginsRoot(self)
if projectOpen:
self.PluginRoot.LoadProject(projectOpen)
self.RefreshPluginTree()
- self.PLCEditor = None
-
self.RefreshPluginParams()
self.RefreshButtons()
self.RefreshMainMenu()
@@ -588,123 +609,6 @@
textctrl.SetValue(str(element_infos["value"]))
first = False
- def UpdateAttributesTreeParts(self, tree, new_tree):
- tree_leafs = [(element_infos["name"], element_infos["type"]) for element_infos in tree["children"]]
- new_tree_leafs = [(element_infos["name"], element_infos["type"]) for element_infos in new_tree["children"]]
- if tree_leafs != new_tree_leafs:
- tree["children"] = new_tree["children"]
- for child in tree["children"]:
- self.PrepareAttributesTree(child)
- else:
- for idx, new_element_infos in enumerate(new_tree["children"]):
- tree["children"][idx]["value"] = new_element_infos["value"]
- if len(new_element_infos["children"]) > 0:
- self.UpdateAttributesTreeParts(tree["children"][idx], new_element_infos)
-
- def PrepareAttributesTree(self, tree):
- if len(tree["children"]) > 0:
- tree["open"] = False
- for child in tree["children"]:
- self.PrepareAttributesTree(child)
-
- def GenerateTable(self, data, tree, path, indent):
- if path:
- tree_path = "%s.%s"%(path, tree["name"])
- infos = {"Attribute" : " " * indent + tree["name"], "Value" : tree["value"], "Type" : tree["type"], "Open" : "", "Path" : tree_path}
- data.append(infos)
- indent += 1
- else:
- tree_path = tree["name"]
- if len(tree["children"]) > 0:
- if tree["open"] or not path:
- if path:
- infos["Open"] = "v"
- for child in tree["children"]:
- self.GenerateTable(data, child, tree_path, indent)
- elif path:
- infos["Open"] = ">"
-
- def RefreshAttributesGrid(self):
- plugin = self.GetSelectedPlugin()
- if not plugin:
- self.AttributesTree = []
- self.Table.Empty()
- else:
- new_params = plugin.GetParamsAttributes()
- for idx, child in enumerate(new_params):
- if len(self.AttributesTree) > idx:
- if self.AttributesTree[idx]["name"] == child["name"]:
- self.UpdateAttributesTreeParts(self.AttributesTree[idx], child)
- else:
- self.AttributesTree[idx] = child
- self.PrepareAttributesTree(child)
- else:
- self.AttributesTree.append(child)
- self.PrepareAttributesTree(child)
- while len(self.AttributesTree) > len(new_params):
- self.AttributesTree.pop(-1)
- data = []
- for child in self.AttributesTree:
- self.GenerateTable(data, child, None, 0)
- self.Table.SetData(data)
- self.Table.ResetView(self.AttributesGrid)
-
- def OpenClose(self, tree, path):
- parts = path.split(".", 1)
- for child in tree["children"]:
- if child["name"] == parts[0]:
- if len(parts) > 1:
- return self.OpenClose(child, parts[1])
- elif len(child["children"]) > 0:
- child["open"] = not child["open"]
- return True
- return False
-
- def OpenCloseAttribute(self):
- if self.AttributesGrid.GetGridCursorCol() == 0:
- row = self.AttributesGrid.GetGridCursorRow()
- path = self.Table.GetValueByName(row, "Path")
- parts = path.split(".", 1)
- for child in self.AttributesTree:
- if child["name"] == parts[0] and len(parts) > 1:
- result = self.OpenClose(child, parts[1])
- if result:
- self.RefreshAttributesGrid()
-
- def OnParamsEnableChanged(self, event):
- plugin = self.GetSelectedPlugin()
- if plugin and plugin != self.PluginRoot:
- plugin.BaseParams.setEnabled(event.Checked())
- event.Skip()
-
- def OnParamsIECChannelChanged(self, event):
- plugin = self.GetSelectedPlugin()
- if plugin and plugin != self.PluginRoot:
- plugin.BaseParams.setIEC_Channel(self.ParamsIECChannel.GetValue())
- event.Skip()
-
- def OnParamsTargetTypeChanged(self, event):
- plugin = self.GetSelectedPlugin()
- if plugin and plugin == self.PluginRoot:
- self.PluginRoot.ChangeTargetType(self.ParamsTargetType.GetStringSelection())
- self.RefreshAttributesGrid()
- event.Skip()
-
- def OnAttributesGridCellChange(self, event):
- row = event.GetRow()
- plugin = self.GetSelectedPlugin()
- if plugin:
- path = self.Table.GetValueByName(row, "Path")
- value = self.Table.GetValueByName(row, "Value")
- plugin.SetParamsAttribute(path, value)
- print plugin.GetParamsAttributes(path)
- self.RefreshAttributesGrid()
- event.Skip()
-
- def OnAttributesGridCellLeftClick(self, event):
- wx.CallAfter(self.OpenCloseAttribute)
- event.Skip()
-
def OnNewProjectMenu(self, event):
defaultpath = self.PluginRoot.GetProjectPath()
if defaultpath == "":
@@ -713,25 +617,20 @@
if dialog.ShowModal() == wx.ID_OK:
projectpath = dialog.GetPath()
dialog.Destroy()
- if os.path.isdir(projectpath) and len(os.listdir(projectpath)) == 0:
- dialog = ProjectDialog(self)
- if dialog.ShowModal() == wx.ID_OK:
- values = dialog.GetValues()
- values["creationDateTime"] = datetime(*localtime()[:6])
- self.PluginRoot.NewProject(projectpath, values)
- self.RefreshPluginTree()
- self.RefreshButtons()
- self.RefreshMainMenu()
- dialog.Destroy()
+ res = self.PluginRoot.NewProject(projectpath)
+ if not res :
+ self.RefreshPluginTree()
+ self.RefreshButtons()
+ self.RefreshMainMenu()
else:
- message = wx.MessageDialog(self, "Folder choosen isn't empty. You can't use it for a new project!", "ERROR", wx.OK|wx.ICON_ERROR)
+ message = wx.MessageDialog(self, res, "ERROR", wx.OK|wx.ICON_ERROR)
message.ShowModal()
message.Destroy()
event.Skip()
def OnOpenProjectMenu(self, event):
defaultpath = self.PluginRoot.GetProjectPath()
- if defaultpath == "":
+ if not defaultpath:
defaultpath = os.getcwd()
dialog = wx.DirDialog(self , "Choose a project", defaultpath, wx.DD_NEW_DIR_BUTTON)
if dialog.ShowModal() == wx.ID_OK:
@@ -785,7 +684,7 @@
event.Skip()
def OnBuildMenu(self, event):
- self.BuildAutom()
+ #self.BuildAutom()
event.Skip()
def OnSimulateMenu(self, event):
@@ -828,50 +727,6 @@
def DeletePlugin(self):
pass
-
- def EditPLC(self):
- if not self.PLCEditor:
- self.PLCEditor = PLCOpenEditor(self, self.PluginRoot.PLCManager)
- self.PLCEditor.RefreshProjectTree()
- self.PLCEditor.RefreshFileMenu()
- self.PLCEditor.RefreshEditMenu()
- self.PLCEditor.RefreshToolBar()
- self.PLCEditor.Show()
-
- def LogCommand(self, Command, sz_limit = 100):
-
- import os, popen2, fcntl, select, signal
-
- child = popen2.Popen3(Command, 1) # capture stdout and stderr from command
- child.tochild.close() # don't need to talk to child
- outfile = child.fromchild
- outfd = outfile.fileno()
- errfile = child.childerr
- errfd = errfile.fileno()
- outdata = errdata = ''
- outeof = erreof = 0
- outlen = errlen = 0
- while 1:
- ready = select.select([outfd,errfd],[],[]) # wait for input
- if outfd in ready[0]:
- outchunk = outfile.readline()
- if outchunk == '': outeof = 1
- else : outlen += 1
- outdata += outchunk
- self.Log.write(outchunk)
- if errfd in ready[0]:
- errchunk = errfile.readline()
- if errchunk == '': erreof = 1
- else : errlen += 1
- errdata += errchunk
- self.Log.write_warning(errchunk)
- if outeof and erreof : break
- if errlen > sz_limit or outlen > sz_limit :
- os.kill(child.pid, signal.SIGTERM)
- self.Log.write_error("Output size reached limit -- killed\n")
- break
- err = child.wait()
- return (err, outdata, errdata)
#-------------------------------------------------------------------------------
# Add Bus Dialog
--- a/plugger.py Tue Sep 04 17:16:42 2007 +0200
+++ b/plugger.py Tue Sep 04 17:58:29 2007 +0200
@@ -2,15 +2,18 @@
Base definitions for beremiz plugins
"""
-import os
+import os,sys
import plugins
import types
import shutil
from xml.dom import minidom
+
+#Quick hack to be able to find Beremiz IEC tools. Should be config params.
+base_folder = os.path.split(sys.path[0])[0]
+sys.path.append(os.path.join(base_folder, "plcopeneditor"))
+
from xmlclass import GenerateClassesFromXSDstring
-from PLCControler import PLCControler
-
_BaseParamsClass = GenerateClassesFromXSDstring("""<?xml version="1.0" encoding="ISO-8859-1" ?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="BaseParams">
@@ -66,6 +69,7 @@
return False
def OnPlugSave(self):
+ #Default, do nothing and return success
return True
def GetParamsAttributes(self, path = None):
@@ -98,17 +102,15 @@
os.mkdir(plugpath)
# generate XML for base XML parameters controller of the plugin
- basexmlfilepath = self.PluginBaseXmlFilePath()
- if basexmlfilepath:
- BaseXMLFile = open(basexmlfilepath,'w')
+ if self.MandatoryParams:
+ BaseXMLFile = open(self.PluginBaseXmlFilePath(),'w')
BaseXMLFile.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
BaseXMLFile.write(self.MandatoryParams[1].generateXMLText(self.MandatoryParams[0], 0))
BaseXMLFile.close()
# generate XML for XML parameters controller of the plugin
- xmlfilepath = self.PluginXmlFilePath()
- if xmlfilepath:
- XMLFile = open(xmlfilepath,'w')
+ if self.PlugParams:
+ XMLFile = open(self.PluginXmlFilePath(),'w')
XMLFile.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
XMLFile.write(self.PlugParams[1].generateXMLText(self.PlugParams[0], 0))
XMLFile.close()
@@ -292,8 +294,14 @@
if os.path.isdir(_self.PlugPath(PlugName)) and os.path.isfile(_self.PluginXmlFilePath(PlugName)):
#Load the plugin.xml file into parameters members
_self.LoadXMLParams(PlugName)
+ # Basic check. Better to fail immediately.
+ if (_self.BaseParams.getName() != PlugName):
+ raise Exception, "Project tree layout do not match plugin.xml %s!=%s "%(PlugName, _self.BaseParams.getName())
+
+ # Now, self.PlugPath() should be OK
+
# Check that IEC_Channel is not already in use.
- self.FindNewIEC_Channel(self.BaseParams.getIEC_Channel())
+ _self.FindNewIEC_Channel(_self.BaseParams.getIEC_Channel())
# Call the plugin real __init__
if getattr(PlugClass, "__init__", None):
PlugClass.__init__(_self)
@@ -319,31 +327,21 @@
return newPluginOpj
- def LoadXMLParams(self, PlugName = None, test = True):
+ def LoadXMLParams(self, PlugName = None):
# Get the base xml tree
- basexmlfilepath = self.PluginBaseXmlFilePath(PlugName)
- if basexmlfilepath:
- basexmlfile = open(basexmlfilepath, 'r')
+ if self.MandatoryParams:
+ basexmlfile = open(self.PluginBaseXmlFilePath(PlugName), 'r')
basetree = minidom.parse(basexmlfile)
self.MandatoryParams[1].loadXMLTree(basetree.childNodes[0])
basexmlfile.close()
# Get the xml tree
- xmlfilepath = self.PluginXmlFilePath(PlugName)
- if xmlfilepath:
- xmlfile = open(xmlfilepath, 'r')
+ if self.PlugParams:
+ xmlfile = open(self.PluginXmlFilePath(PlugName), 'r')
tree = minidom.parse(xmlfile)
self.PlugParams[1].loadXMLTree(tree.childNodes[0])
xmlfile.close()
- if test:
- # Basic check. Better to fail immediately.
- if not PlugName:
- PlugName = os.path.split(self.PlugPath())[1].split(NameTypeSeparator)[0]
- if (self.BaseParams.getName() != PlugName):
- raise Exception, "Project tree layout do not match plugin.xml %s!=%s "%(PlugName, self.BaseParams.getName())
- # Now, self.PlugPath() should be OK
-
def LoadChilds(self):
# Iterate over all PlugName@PlugType in plugin directory, and try to open them
for PlugDir in os.listdir(self.PlugPath()):
@@ -359,7 +357,38 @@
return getattr(__import__("plugins." + name), name).RootClass
return GetRootClass
+
+####################################################################################
+####################################################################################
+####################################################################################
+################################### ROOT ######################################
+####################################################################################
+####################################################################################
+####################################################################################
+
+iec2cc_path = os.path.join(base_folder, "matiec", "iec2cc")
+ieclib_path = os.path.join(base_folder, "matiec", "lib")
+
+# import for project creation timestamping
+from time import localtime
+from datetime import datetime
+# import necessary stuff from PLCOpenEditor
+from PLCControler import PLCControler
+from PLCOpenEditor import PLCOpenEditor, ProjectDialog
+from TextViewer import TextViewer
+from plcopen.structures import IEC_KEYWORDS
+
class PluginsRoot(PlugTemplate):
+ """
+ This class define Root object of the plugin tree.
+ It is responsible of :
+ - Managing project directory
+ - Building project
+ - Handling PLCOpenEditor controler and view
+ - Loading user plugins and instanciante them as childs
+ - ...
+
+ """
# For root object, available Childs Types are modules of the plugin packages.
PlugChildsTypes = [(name, _GetClassFunction(name)) for name in plugins.__all__]
@@ -418,26 +447,43 @@
</xsd:schema>
"""
- def __init__(self):
- PlugTemplate.__init__(self)
+ def __init__(self, frame):
+
+ self.MandatoryParams = None
+ self.AppFrame = frame
+
+ """
+ This method are not called here... but in NewProject and OpenProject
+ self._AddParamsMembers()
+ self.PluggedChilds = {}
+ """
+
# self is the parent
self.PlugParent = None
# Keep track of the plugin type name
self.PlugType = "Beremiz"
- self.ProjectPath = ""
+ # After __init__ root plugin is not valid
+ self.ProjectPath = None
self.PLCManager = None
+ self.PLCEditor = None
def HasProjectOpened(self):
"""
Return if a project is actually opened
"""
- return self.ProjectPath != ""
+ return self.ProjectPath != None
def GetProjectPath(self):
return self.ProjectPath
- def NewProject(self, ProjectPath, PLCParams):
+ def GetPlugInfos(self):
+ childs = []
+ for child in self.IterChilds():
+ childs.append(child.GetPlugInfos())
+ return {"name" : os.path.split(self.ProjectPath)[1], "type" : None, "values" : childs}
+
+ def NewProject(self, ProjectPath):
"""
Create a new project in an empty folder
@param ProjectPath: path of the folder where project have to be created
@@ -446,6 +492,16 @@
# Verify that choosen folder is empty
if not os.path.isdir(ProjectPath) or len(os.listdir(ProjectPath)) > 0:
return "Folder choosen isn't empty. You can't use it for a new project!"
+
+ dialog = ProjectDialog(self.AppFrame)
+ if dialog.ShowModal() == wx.ID_OK:
+ values = dialog.GetValues()
+ values["creationDateTime"] = datetime(*localtime()[:6])
+ dialog.Destroy()
+ else:
+ dialog.Destroy()
+ return "Project not created"
+
# Create Controler for PLCOpen program
self.PLCManager = PLCControler()
self.PLCManager.CreateNewProject(PLCParams.pop("projectName"))
@@ -453,11 +509,8 @@
# Change XSD into class members
self._AddParamsMembers()
self.PluggedChilds = {}
- # No IEC channel, name, etc...
- self.MandatoryParams = []
# Keep track of the root plugin (i.e. project path)
self.ProjectPath = ProjectPath
- self.BaseParams.setName(os.path.split(ProjectPath)[1])
return None
def LoadProject(self, ProjectPath):
@@ -478,19 +531,16 @@
# Change XSD into class members
self._AddParamsMembers()
self.PluggedChilds = {}
- # No IEC channel, name, etc...
- self.MandatoryParams = None
# Keep track of the root plugin (i.e. project path)
self.ProjectPath = ProjectPath
# If dir have already be made, and file exist
if os.path.isdir(self.PlugPath()) and os.path.isfile(self.PluginXmlFilePath()):
#Load the plugin.xml file into parameters members
- result = self.LoadXMLParams(test = False)
+ result = self.LoadXMLParams()
if result:
return result
#Load and init all the childs
self.LoadChilds()
- self.BaseParams.setName(os.path.split(ProjectPath)[1])
return None
def SaveProject(self):
@@ -501,9 +551,6 @@
def PlugPath(self, PlugName=None):
return self.ProjectPath
- def PluginBaseXmlFilePath(self, PlugName=None):
- return None
-
def PluginXmlFilePath(self, PlugName=None):
return os.path.join(self.PlugPath(PlugName), "beremiz.xml")
@@ -517,61 +564,93 @@
@return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
"""
return [(C_file_name, "") for C_file_name in self.PLCGeneratedCFiles ] , ""
-
- def _Generate_SoftPLC(self, buildpath, logger):
-
+
+ def _getBuildPath(self):
+ return os.path.join(self.ProjectPath, "build")
+
+ def _getIECcodepath(self):
+ # define name for IEC code file
+ return os.path.join(self._getBuildPath(), "plc.st")
+
+ def _Generate_SoftPLC(self, logger):
+ """
+ Generate SoftPLC ST/IL/SFC code out of PLCOpenEditor controller, and compile it with IEC2CC
+ @param buildpath: path where files should be created
+ @param logger: the log pseudo file
+ """
+
+ logger.write("Generating SoftPLC IEC-61131 ST/IL/SFC code...\n")
+ buildpath = self._getBuildPath()
+ # define name for IEC code file
+ plc_file = self._getIECcodepath()
+ # ask PLCOpenEditor controller to write ST/IL/SFC code file
+ result = self.PLCManager.GenerateProgram(plc_file)
+ if not result:
+ # Failed !
+ logger.write_error("Error : ST/IL/SFC code generator returned %d"%result)
+ return False
+ logger.write("Compiling ST Program in to C Program...\n")
+ # Now compile IEC code into many C files
+ # files are listed to stdout, and errors to stderr.
+ status, result, err_result = logger.LogCommand("%s %s -I %s %s"%(iec2cc_path, plc_file, ieclib_path, self.TargetDir))
+ if status:
+ # Failed !
+ logger.write_error("Error : IEC to C compiler returned %d"%status)
+ return False
+ # Now extract C files of stdout
+ C_files = result.splitlines()
+ # remove those that are not to be compiled because included by others
+ C_files.remove("POUS.c")
+ C_files.remove("LOCATED_VARIABLES.h")
+ # transform those base names to full names with path
+ C_files = map(lambda filename:os.path.join(self.TargetDir, filename), C_files)
+ logger.write("Extracting Located Variables...\n")
+ # IEC2CC compiler generate a list of located variables : LOCATED_VARIABLES.h
+ location_file = open(os.path.join(buildpath,"LOCATED_VARIABLES.h"))
+ locations = []
+ # each line of LOCATED_VARIABLES.h declares a located variable
+ lines = [line.strip() for line in location_file.readlines()]
+ # This regular expression parses the lines genereated by IEC2CC
LOCATED_MODEL = re.compile("__LOCATED_VAR\((?P<IEC_TYPE>[A-Z]*),(?P<NAME>[_A-Za-z0-9]*),(?P<DIR>[QMI])(?:,(?P<SIZE>[XBWD]))?,(?P<LOC>[,0-9]*)\)")
-
- if self.PLCManager:
- logger.write("Generating SoftPLC IEC-61131 ST/IL/SFC code...\n")
- plc_file = os.path.join(self.TargetDir, "plc.st")
- result = self.PLCManager.GenerateProgram(plc_file)
- if not result:
- logger.write_error("Error : ST/IL/SFC code generator returned %d"%result)
- return False
- logger.write("Compiling ST Program in to C Program...\n")
- status, result, err_result = self.LogCommand("%s %s -I %s %s"%(iec2cc_path, plc_file, ieclib_path, self.TargetDir))
- if status:
- new_dialog = wx.Frame(None)
- ST_viewer = TextViewer(new_dialog, None, None)
- #ST_viewer.Enable(False)
- ST_viewer.SetKeywords(IEC_KEYWORDS)
- ST_viewer.SetText(file(plc_file).read())
- new_dialog.Show()
- raise Exception, "Error : IEC to C compiler returned %d"%status
- C_files = result.splitlines()
- C_files.remove("POUS.c")
- C_files = map(lambda filename:os.path.join(self.TargetDir, filename), C_files)
- logger.write("Extracting Located Variables...\n")
- location_file = open(os.path.join(self.TargetDir,"LOCATED_VARIABLES.h"))
- locations = []
- lines = [line.strip() for line in location_file.readlines()]
- for line in lines:
- result = LOCATED_MODEL.match(line)
- if result:
- resdict = result.groupdict()
- # rewrite location as a tuple of integers
- resdict['LOC'] = tuple(map(int,resdict['LOC'].split(',')))
- if not resdict['SIZE']:
- resdict['SIZE'] = 'X'
- locations.append(resdict)
+ for line in lines:
+ # If line match RE,
+ result = LOCATED_MODEL.match(line)
+ if result:
+ # Get the resulting dict
+ resdict = result.groupdict()
+ # rewrite string for variadic location as a tuple of integers
+ resdict['LOC'] = tuple(map(int,resdict['LOC'].split(',')))
+ # set located size to 'X' if not given
+ if not resdict['SIZE']:
+ resdict['SIZE'] = 'X'
+ # finally store into located variable list
+ locations.append(resdict)
+ # Keep track of generated C files for later use by self.PlugGenerate_C
self.PLCGeneratedCFiles = C_files
+ # Keep track of generated located variables for later use by self._Generate_C
self.PLCGeneratedLocatedVars = locations
return True
def _build(self, logger):
- buildpath = os.path.join(self.ProjectPath, "build")
+ """
+ Method called by user to (re)build SoftPLC and plugin tree
+ """
+ buildpath = self._getBuildPath()
+
+ # Eventually create build dir
if not os.path.exists(buildpath):
os.mkdir(buildpath)
logger.write("Start build in %s" % buildpath)
- if not self._Generate_SoftPLC(buildpath, logger):
- logger.write("SoftPLC code generation failed !")
- return
-
+ # Generate SoftPLC code
+ if not self._Generate_SoftPLC(logger):
+ logger.write_error("SoftPLC code generation failed !")
+ return False
+
logger.write("SoftPLC code generation successfull")
+ # Generate C code and compilation params from plugin hierarchy
try:
CFilesAndCFLAGS, LDFLAGS = self._Generate_C(
buildpath,
@@ -581,14 +660,39 @@
except Exception, msg:
logger.write_error("Plugins code generation Failed !")
logger.write_error(str(msg))
- return
+ return False
logger.write_error("Plugins code generation successfull")
-
+
+ # Compile the resulting code into object files.
for CFile, CFLAG in CFilesAndCFLAGS:
print CFile,CFLAG
- LDFLAGS
-
- PluginMethods = [("Build",_build), ("Clean",None), ("Run",None), ("EditPLC",None), ("Simulate",None)]
-
+ # Link object files into something that can be executed on target
+ print LDFLAGS
+
+ def _showIECcode(self, logger):
+ plc_file = self._getIECcodepath()
+ new_dialog = wx.Frame(None)
+ ST_viewer = TextViewer(new_dialog, None, None)
+ #ST_viewer.Enable(False)
+ ST_viewer.SetKeywords(IEC_KEYWORDS)
+ try:
+ text = file(plc_file).read()
+ except:
+ text = '(* No IEC code have been generated at that time ! *)'
+ ST_viewer.SetText(text)
+
+ new_dialog.Show()
+
+ def _EditPLC(self, logger):
+ if not self.PLCEditor:
+ self.PLCEditor = PLCOpenEditor(self, self.PLCManager)
+ self.PLCEditor.RefreshProjectTree()
+ self.PLCEditor.RefreshFileMenu()
+ self.PLCEditor.RefreshEditMenu()
+ self.PLCEditor.RefreshToolBar()
+ self.PLCEditor.Show()
+
+ PluginMethods = [("Build",_build), ("Clean",None), ("Run",None), ("EditPLC",None), ("Show IEC code",_showIECcode)]
+
--- a/plugins/canfestival/canfestival.py Tue Sep 04 17:16:42 2007 +0200
+++ b/plugins/canfestival/canfestival.py Tue Sep 04 17:58:29 2007 +0200
@@ -1,4 +1,7 @@
-import os
+import os, sys
+base_folder = os.path.split(sys.path[0])[0]
+sys.path.append(os.path.join(base_folder, "CanFestival-3", "objdictgen"))
+
from nodelist import NodeList
from nodemanager import NodeManager
import config_utils, gen_cfile
--- a/plugins/svgui/svgui.py Tue Sep 04 17:16:42 2007 +0200
+++ b/plugins/svgui/svgui.py Tue Sep 04 17:58:29 2007 +0200
@@ -1,4 +1,7 @@
-import os
+import os, sys
+base_folder = os.path.split(sys.path[0])[0]
+sys.path.append(os.path.join(base_folder, "wxsvg", "defeditor"))
+
from DEFControler import DEFControler
from defeditor import EditorFrame