--- a/Beremiz.py Fri Sep 18 14:58:22 2009 +0200
+++ b/Beremiz.py Mon Sep 21 12:12:08 2009 +0200
@@ -66,7 +66,6 @@
app = wx.PySimpleApp()
app.SetAppName('beremiz')
- config = wx.ConfigBase.Get()
wx.InitAllImageHandlers()
bmp = wx.Image(Bpath("images","splash.png")).ConvertToBitmap()
@@ -100,15 +99,20 @@
if __name__ == '__main__':
__builtin__.__dict__['_'] = wx.GetTranslation#unicode_translation
+#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(base_folder)
+sys.path.append(os.path.join(base_folder, "plcopeneditor"))
+sys.path.append(os.path.join(base_folder, "docutils"))
+
import wx.lib.buttons, wx.lib.statbmp
import TextCtrlAutoComplete, cPickle
import types, time, re, platform, time, traceback, commands
from plugger import PluginsRoot, MATIEC_ERROR_MODEL
from wxPopen import ProcessLogger
-base_folder = os.path.split(sys.path[0])[0]
-sys.path.append(base_folder)
from docutils import *
+from PLCOpenEditor import IDEFrame, Viewer, AppendMenu, TITLE, TOOLBAR, FILEMENU, EDITMENU, DISPLAYMENU, TYPESTREE, INSTANCESTREE, LIBRARYTREE, SCALING
SCROLLBAR_UNIT = 10
WINDOW_COLOUR = wx.Colour(240,240,240)
@@ -279,61 +283,43 @@
ID_BEREMIZRUNMENURUN, ID_BEREMIZRUNMENUSAVELOG,
] = [wx.NewId() for _init_coll_EditMenu_Items in range(4)]
-class Beremiz(wx.Frame):
+class Beremiz(IDEFrame):
def _init_coll_FileMenu_Items(self, parent):
- parent.Append(help='', id=wx.ID_NEW,
+ AppendMenu(parent, help='', id=wx.ID_NEW,
kind=wx.ITEM_NORMAL, text=_(u'New\tCTRL+N'))
- parent.Append(help='', id=wx.ID_OPEN,
+ AppendMenu(parent, help='', id=wx.ID_OPEN,
kind=wx.ITEM_NORMAL, text=_(u'Open\tCTRL+O'))
- parent.Append(help='', id=wx.ID_SAVE,
+ AppendMenu(parent, help='', id=wx.ID_SAVE,
kind=wx.ITEM_NORMAL, text=_(u'Save\tCTRL+S'))
- parent.Append(help='', id=wx.ID_CLOSE_ALL,
+ AppendMenu(parent, help='', id=wx.ID_CLOSE,
+ kind=wx.ITEM_NORMAL, text=_(u'Close Tab\tCTRL+W'))
+ AppendMenu(parent, help='', id=wx.ID_CLOSE_ALL,
kind=wx.ITEM_NORMAL, text=_(u'Close Project'))
parent.AppendSeparator()
- parent.Append(help='', id=wx.ID_PROPERTIES,
+ AppendMenu(parent, help='', id=wx.ID_PAGE_SETUP,
+ kind=wx.ITEM_NORMAL, text=_(u'Page Setup'))
+ AppendMenu(parent, help='', id=wx.ID_PREVIEW,
+ kind=wx.ITEM_NORMAL, text=_(u'Preview'))
+ AppendMenu(parent, help='', id=wx.ID_PRINT,
+ kind=wx.ITEM_NORMAL, text=_(u'Print'))
+ parent.AppendSeparator()
+ AppendMenu(parent, help='', id=wx.ID_PROPERTIES,
kind=wx.ITEM_NORMAL, text=_(u'Properties'))
parent.AppendSeparator()
- parent.Append(help='', id=wx.ID_EXIT,
+ AppendMenu(parent, help='', id=wx.ID_EXIT,
kind=wx.ITEM_NORMAL, text=_(u'Quit\tCTRL+Q'))
+
self.Bind(wx.EVT_MENU, self.OnNewProjectMenu, id=wx.ID_NEW)
self.Bind(wx.EVT_MENU, self.OnOpenProjectMenu, id=wx.ID_OPEN)
self.Bind(wx.EVT_MENU, self.OnSaveProjectMenu, id=wx.ID_SAVE)
+ self.Bind(wx.EVT_MENU, self.OnCloseTabMenu, id=wx.ID_CLOSE)
self.Bind(wx.EVT_MENU, self.OnCloseProjectMenu, id=wx.ID_CLOSE_ALL)
+ self.Bind(wx.EVT_MENU, self.OnPageSetupMenu, id=wx.ID_PAGE_SETUP)
+ self.Bind(wx.EVT_MENU, self.OnPreviewMenu, id=wx.ID_PREVIEW)
+ self.Bind(wx.EVT_MENU, self.OnPrintMenu, id=wx.ID_PRINT)
self.Bind(wx.EVT_MENU, self.OnPropertiesMenu, id=wx.ID_PROPERTIES)
self.Bind(wx.EVT_MENU, self.OnQuitMenu, id=wx.ID_EXIT)
-
- def _init_coll_EditMenu_Items(self, parent):
- parent.Append(help='', id=wx.ID_EDIT,
- kind=wx.ITEM_NORMAL, text=_(u'Edit PLC\tCTRL+R'))
- parent.AppendSeparator()
- parent.Append(help='', id=wx.ID_ADD,
- kind=wx.ITEM_NORMAL, text=_(u'Add Plugin'))
- parent.Append(help='', id=wx.ID_DELETE,
- kind=wx.ITEM_NORMAL, text=_(u'Delete Plugin'))
- self.Bind(wx.EVT_MENU, self.OnEditPLCMenu, id=wx.ID_EDIT)
- self.Bind(wx.EVT_MENU, self.OnAddMenu, id=wx.ID_ADD)
- self.Bind(wx.EVT_MENU, self.OnDeleteMenu, id=wx.ID_DELETE)
-
- def _init_coll_RunMenu_Items(self, parent):
- parent.Append(help='', id=ID_BEREMIZRUNMENUBUILD,
- kind=wx.ITEM_NORMAL, text=_(u'Build\tCTRL+R'))
- parent.AppendSeparator()
- parent.Append(help='', id=ID_BEREMIZRUNMENUSIMULATE,
- kind=wx.ITEM_NORMAL, text=_(u'Simulate'))
- parent.Append(help='', id=ID_BEREMIZRUNMENURUN,
- kind=wx.ITEM_NORMAL, text=_(u'Run'))
- parent.AppendSeparator()
- parent.Append(help='', id=ID_BEREMIZRUNMENUSAVELOG,
- kind=wx.ITEM_NORMAL, text=_(u'Save Log'))
- self.Bind(wx.EVT_MENU, self.OnBuildMenu,
- id=ID_BEREMIZRUNMENUBUILD)
- self.Bind(wx.EVT_MENU, self.OnSimulateMenu,
- id=ID_BEREMIZRUNMENUSIMULATE)
- self.Bind(wx.EVT_MENU, self.OnRunMenu,
- id=ID_BEREMIZRUNMENURUN)
- self.Bind(wx.EVT_MENU, self.OnSaveLogMenu,
- id=ID_BEREMIZRUNMENUSAVELOG)
def _init_coll_HelpMenu_Items(self, parent):
parent.Append(help='', id=wx.ID_HELP,
@@ -343,25 +329,6 @@
self.Bind(wx.EVT_MENU, self.OnBeremizMenu, id=wx.ID_HELP)
self.Bind(wx.EVT_MENU, self.OnAboutMenu, id=wx.ID_ABOUT)
- def _init_coll_MenuBar_Menus(self, parent):
- parent.Append(menu=self.FileMenu, title=_(u'File'))
- #parent.Append(menu=self.EditMenu, title=u'Edit')
- #parent.Append(menu=self.RunMenu, title=u'Run')
- parent.Append(menu=self.HelpMenu, title=_(u'Help'))
-
- def _init_utils(self):
- self.MenuBar = wx.MenuBar()
- self.FileMenu = wx.Menu(title=u'')
- #self.EditMenu = wx.Menu(title=u'')
- #self.RunMenu = wx.Menu(title=u'')
- self.HelpMenu = wx.Menu(title=u'')
-
- self._init_coll_MenuBar_Menus(self.MenuBar)
- self._init_coll_FileMenu_Items(self.FileMenu)
- #self._init_coll_EditMenu_Items(self.EditMenu)
- #self._init_coll_RunMenu_Items(self.RunMenu)
- self._init_coll_HelpMenu_Items(self.HelpMenu)
-
def _init_coll_PLCConfigMainSizer_Items(self, parent):
parent.AddSizer(self.PLCParamsSizer, 0, border=10, flag=wx.GROW|wx.TOP|wx.LEFT|wx.RIGHT)
parent.AddSizer(self.PluginTreeSizer, 0, border=10, flag=wx.BOTTOM|wx.LEFT|wx.RIGHT)
@@ -374,7 +341,7 @@
parent.AddGrowableCol(0)
parent.AddGrowableCol(1)
- def _init_sizers(self):
+ def _init_beremiz_sizers(self):
self.PLCConfigMainSizer = wx.FlexGridSizer(cols=1, hgap=2, rows=2, vgap=2)
self.PLCParamsSizer = wx.BoxSizer(wx.VERTICAL)
#self.PluginTreeSizer = wx.FlexGridSizer(cols=3, hgap=0, rows=0, vgap=2)
@@ -387,82 +354,68 @@
self.PLCConfig.SetSizer(self.PLCConfigMainSizer)
def _init_ctrls(self, prnt):
- wx.Frame.__init__(self, id=ID_BEREMIZ, name=u'Beremiz',
- parent=prnt, pos=wx.Point(0, 0), size=wx.Size(1000, 600),
- style=wx.DEFAULT_FRAME_STYLE|wx.CLIP_CHILDREN, title=_(u'Beremiz'))
- self._init_utils()
- self.SetClientSize(wx.Size(1000, 600))
- self.SetMenuBar(self.MenuBar)
- self.Bind(wx.EVT_ACTIVATE, self.OnFrameActivated)
- self.Bind(wx.EVT_CLOSE, self.OnCloseFrame)
-
+ IDEFrame._init_ctrls(self, prnt)
+
self.Bind(wx.EVT_MENU, self.OnOpenWidgetInspector, id=ID_BEREMIZINSPECTOR)
accel = wx.AcceleratorTable([wx.AcceleratorEntry(wx.ACCEL_CTRL|wx.ACCEL_ALT, ord('I'), ID_BEREMIZINSPECTOR)])
self.SetAcceleratorTable(accel)
- if wx.VERSION < (2, 8, 0):
- self.MainSplitter = wx.SplitterWindow(id=ID_BEREMIZMAINSPLITTER,
- name='MainSplitter', parent=self, point=wx.Point(0, 0),
- size=wx.Size(0, 0), style=wx.SP_3D)
- self.MainSplitter.SetNeedUpdating(True)
- self.MainSplitter.SetMinimumPaneSize(1)
-
- parent = self.MainSplitter
- else:
- parent = self
-
self.PLCConfig = wx.ScrolledWindow(id=ID_BEREMIZPLCCONFIG,
- name='PLCConfig', parent=parent, pos=wx.Point(0, 0),
+ name='PLCConfig', parent=self.LeftNoteBook, pos=wx.Point(0, 0),
size=wx.Size(-1, -1), style=wx.TAB_TRAVERSAL|wx.SUNKEN_BORDER|wx.HSCROLL|wx.VSCROLL)
self.PLCConfig.SetBackgroundColour(wx.WHITE)
self.PLCConfig.Bind(wx.EVT_LEFT_DOWN, self.OnPanelLeftDown)
self.PLCConfig.Bind(wx.EVT_SIZE, self.OnMoveWindow)
+ self.LeftNoteBook.AddPage(self.PLCConfig, _("Topology"))
self.LogConsole = wx.TextCtrl(id=ID_BEREMIZLOGCONSOLE, value='',
- name='LogConsole', parent=parent, pos=wx.Point(0, 0),
+ name='LogConsole', parent=self.BottomNoteBook, pos=wx.Point(0, 0),
size=wx.Size(0, 0), style=wx.TE_MULTILINE|wx.TE_RICH2)
self.LogConsole.Bind(wx.EVT_LEFT_DCLICK, self.OnLogConsoleDClick)
-
- if wx.VERSION < (2, 8, 0):
- self.MainSplitter.SplitHorizontally(self.PLCConfig, self.LogConsole, -250)
- else:
- self.AUIManager = wx.aui.AuiManager(self)
- self.AUIManager.SetDockSizeConstraint(0.5, 0.5)
-
- self.AUIManager.AddPane(self.PLCConfig, wx.aui.AuiPaneInfo().CenterPane())
-
- self.AUIManager.AddPane(self.LogConsole, wx.aui.AuiPaneInfo().
- Caption(_("Log Console")).Bottom().Layer(1).
- BestSize(wx.Size(800, 200)).CloseButton(False))
-
- self.AUIManager.Update()
-
- self._init_sizers()
-
- def __init__(self, parent, projectOpen, buildpath):
- self._init_ctrls(parent)
+ self.BottomNoteBook.AddPage(self.LogConsole, _("Log Console"))
+
+ self._init_beremiz_sizers()
+
+ def __init__(self, parent, projectOpen, buildpath, debug=True):
+ IDEFrame.__init__(self, parent, debug)
+ self.Config = wx.ConfigBase.Get()
self.Log = LogPseudoFile(self.LogConsole)
-
+
self.local_runtime = None
self.runtime_port = None
self.local_runtime_tmpdir = None
- # Add beremiz's icon in top left corner of the frame
- self.SetIcon(wx.Icon(Bpath( "images", "brz.ico"), wx.BITMAP_TYPE_ICO))
-
self.DisableEvents = False
self.PluginInfos = {}
if projectOpen:
self.PluginRoot = PluginsRoot(self, self.Log)
+ self.Controler = self.PluginRoot
self.PluginRoot.LoadProject(projectOpen, buildpath)
+ self._Refresh(TYPESTREE, INSTANCESTREE, LIBRARYTREE)
self.RefreshAll()
else:
self.PluginRoot = None
-
- self.RefreshMainMenu()
+ self.Controler = None
+
+ # Add beremiz's icon in top left corner of the frame
+ self.SetIcon(wx.Icon(Bpath( "images", "brz.ico"), wx.BITMAP_TYPE_ICO))
+
+ self.Bind(wx.EVT_CLOSE, self.OnCloseFrame)
+
+ self._Refresh(TITLE, TOOLBAR, FILEMENU, EDITMENU, DISPLAYMENU)
+
+ def RefreshTitle(self):
+ name = _("Beremiz")
+ if self.PluginRoot is not None:
+ projectname = self.PluginRoot.GetProjectName()
+ if self.PluginRoot.PlugTestModified():
+ projectname = "~%s~" % projectname
+ self.SetTitle("%s - %s" % (name, projectname))
+ else:
+ self.SetTitle(name)
def StartLocalRuntime(self, taskbaricon = True):
if self.local_runtime is None or self.local_runtime.finished:
@@ -544,29 +497,45 @@
self.RefreshScrollBars()
event.Skip()
- def OnFrameActivated(self, event):
- if not event.GetActive() and self.PluginRoot is not None:
- self.PluginRoot.RefreshPluginsBlockLists()
-
def OnPanelLeftDown(self, event):
focused = self.FindFocus()
if isinstance(focused, TextCtrlAutoComplete.TextCtrlAutoComplete):
focused._showDropDown(False)
event.Skip()
- def RefreshMainMenu(self):
+ def RefreshFileMenu(self):
if self.PluginRoot is not None:
-## self.MenuBar.EnableTop(1, True)
-## self.MenuBar.EnableTop(2, True)
+ selected = self.TabsOpened.GetSelection()
+ if selected >= 0:
+ graphic_viewer = isinstance(self.TabsOpened.GetPage(selected), Viewer)
+ else:
+ graphic_viewer = False
+ if self.TabsOpened.GetPageCount() > 0:
+ self.FileMenu.Enable(wx.ID_CLOSE, True)
+ if graphic_viewer:
+ self.FileMenu.Enable(wx.ID_PREVIEW, True)
+ self.FileMenu.Enable(wx.ID_PRINT, True)
+ else:
+ self.FileMenu.Enable(wx.ID_PREVIEW, False)
+ self.FileMenu.Enable(wx.ID_PRINT, False)
+ else:
+ self.FileMenu.Enable(wx.ID_CLOSE, False)
+ self.FileMenu.Enable(wx.ID_PREVIEW, False)
+ self.FileMenu.Enable(wx.ID_PRINT, False)
+ self.FileMenu.Enable(wx.ID_PAGE_SETUP, True)
self.FileMenu.Enable(wx.ID_SAVE, True)
+ self.FileMenu.Enable(wx.ID_PROPERTIES, True)
self.FileMenu.Enable(wx.ID_CLOSE_ALL, True)
- self.FileMenu.Enable(wx.ID_PROPERTIES, True)
+ self.FileMenu.Enable(wx.ID_SAVEAS, True)
else:
-## self.MenuBar.EnableTop(1, False)
-## self.MenuBar.EnableTop(2, False)
+ self.FileMenu.Enable(wx.ID_CLOSE, False)
+ self.FileMenu.Enable(wx.ID_PAGE_SETUP, False)
+ self.FileMenu.Enable(wx.ID_PREVIEW, False)
+ self.FileMenu.Enable(wx.ID_PRINT, False)
self.FileMenu.Enable(wx.ID_SAVE, False)
+ self.FileMenu.Enable(wx.ID_PROPERTIES, False)
self.FileMenu.Enable(wx.ID_CLOSE_ALL, False)
- self.FileMenu.Enable(wx.ID_PROPERTIES, False)
+ self.FileMenu.Enable(wx.ID_SAVEAS, False)
def RefreshScrollBars(self):
xstart, ystart = self.PLCConfig.GetViewStart()
@@ -1225,7 +1194,7 @@
spinctrl.SetValue(element_infos["value"])
spinctrl.Bind(wx.EVT_SPINCTRL, self.GetTextCtrlCallBackFunction(spinctrl, plugin, element_path), id=id)
else:
- choices = cPickle.loads(str(config.Read(element_path, cPickle.dumps([""]))))
+ choices = cPickle.loads(str(self.Config.Read(element_path, cPickle.dumps([""]))))
textctrl = TextCtrlAutoComplete.TextCtrlAutoComplete(id=id,
name=element_infos["name"],
parent=parent,
@@ -1240,60 +1209,63 @@
textctrl.Bind(wx.EVT_TEXT, self.GetTextCtrlCallBackFunction(textctrl, plugin, element_path))
first = False
+ def ResetView(self):
+ IDEFrame.ResetView(self)
+ self.PluginInfos = {}
+ self.PluginRoot = None
+ self.Log.flush()
+ self.DebugVariablePanel.SetDataProducer(None)
+
def OnNewProjectMenu(self, event):
- if not config.HasEntry("lastopenedfolder"):
+ if not self.Config.HasEntry("lastopenedfolder"):
defaultpath = os.path.expanduser("~")
else:
- defaultpath = config.Read("lastopenedfolder")
+ defaultpath = self.Config.Read("lastopenedfolder")
dialog = wx.DirDialog(self , _("Choose a project"), defaultpath, wx.DD_NEW_DIR_BUTTON)
if dialog.ShowModal() == wx.ID_OK:
projectpath = dialog.GetPath()
dialog.Destroy()
- config.Write("lastopenedfolder", os.path.dirname(projectpath))
- config.Flush()
- self.PluginInfos = {}
- if self.PluginRoot is not None:
- self.PluginRoot.CloseProject()
+ self.Config.Write("lastopenedfolder", os.path.dirname(projectpath))
+ self.Config.Flush()
+ self.ResetView()
self.PluginRoot = PluginsRoot(self, self.Log)
- res = self.PluginRoot.NewProject(projectpath)
- if not res :
+ self.Controler = self.PluginRoot
+ result = self.PluginRoot.NewProject(projectpath)
+ if not result:
+ self.DebugVariablePanel.SetDataProducer(self.PluginRoot)
+ self._Refresh(TYPESTREE, INSTANCESTREE, LIBRARYTREE)
self.RefreshAll()
- self.RefreshMainMenu()
else:
- message = wx.MessageDialog(self, res, _("ERROR"), wx.OK|wx.ICON_ERROR)
- message.ShowModal()
- message.Destroy()
+ self.ShowErrorMessage(result)
+ self._Refresh(TITLE, TOOLBAR, FILEMENU, EDITMENU)
event.Skip()
def OnOpenProjectMenu(self, event):
- if not config.HasEntry("lastopenedfolder"):
+ if not self.Config.HasEntry("lastopenedfolder"):
defaultpath = os.path.expanduser("~")
else:
- defaultpath = config.Read("lastopenedfolder")
+ defaultpath = self.Config.Read("lastopenedfolder")
dialog = wx.DirDialog(self , _("Choose a project"), defaultpath, wx.DD_NEW_DIR_BUTTON)
if dialog.ShowModal() == wx.ID_OK:
projectpath = dialog.GetPath()
if os.path.isdir(projectpath):
- config.Write("lastopenedfolder", os.path.dirname(projectpath))
- config.Flush()
- self.PluginInfos = {}
- if self.PluginRoot is not None:
- self.PluginRoot.CloseProject()
+ self.Config.Write("lastopenedfolder", os.path.dirname(projectpath))
+ self.Config.Flush()
+ self.ResetView()
self.PluginRoot = PluginsRoot(self, self.Log)
+ self.Controler = self.PluginRoot
result = self.PluginRoot.LoadProject(projectpath)
if not result:
+ self.DebugVariablePanel.SetDataProducer(self.PluginRoot)
+ self._Refresh(TYPESTREE, INSTANCESTREE, LIBRARYTREE)
self.RefreshAll()
- self.RefreshMainMenu()
else:
- message = wx.MessageDialog(self, result, _("Error"), wx.OK|wx.ICON_ERROR)
- message.ShowModal()
- message.Destroy()
+ self.ShowErrorMessage(result)
else:
- message = wx.MessageDialog(self, _("\"%s\" folder is not a valid Beremiz project\n")%projectpath, _("Error"), wx.OK|wx.ICON_ERROR)
- message.ShowModal()
- message.Destroy()
+ self.ShowErrorMessage(_("\"%s\" folder is not a valid Beremiz project\n") % projectpath)
+ self._Refresh(TITLE, TOOLBAR, FILEMENU, EDITMENU)
dialog.Destroy()
event.Skip()
@@ -1310,18 +1282,16 @@
self.PluginRoot.SaveProject()
elif answer == wx.ID_CANCEL:
return
- self.PluginInfos = {}
- self.PluginRoot.CloseProject()
- self.PluginRoot = None
- self.Log.flush()
+ self.ResetView()
+ self._Refresh(TITLE, TOOLBAR, FILEMENU, EDITMENU)
self.RefreshAll()
- self.RefreshMainMenu()
event.Skip()
def OnSaveProjectMenu(self, event):
if self.PluginRoot is not None:
self.PluginRoot.SaveProject()
self.RefreshAll()
+ self.RefreshTitle()
event.Skip()
def OnPropertiesMenu(self, event):
@@ -1330,32 +1300,7 @@
def OnQuitMenu(self, event):
self.Close()
event.Skip()
-
- def OnEditPLCMenu(self, event):
- self.EditPLC()
- event.Skip()
-
- def OnAddMenu(self, event):
- self.AddPlugin()
- event.Skip()
-
- def OnDeleteMenu(self, event):
- self.DeletePlugin()
- event.Skip()
-
- def OnBuildMenu(self, event):
- #self.BuildAutom()
- event.Skip()
-
- def OnSimulateMenu(self, event):
- event.Skip()
-
- def OnRunMenu(self, event):
- event.Skip()
-
- def OnSaveLogMenu(self, event):
- event.Skip()
-
+
def OnBeremizMenu(self, event):
open_pdf(Bpath( "doc", "manual_beremiz.pdf"))
event.Skip()
@@ -1364,16 +1309,6 @@
OpenHtmlFrame(self,_("About Beremiz"), Bpath("doc","about.html"), wx.Size(550, 500))
event.Skip()
- def OnAddButton(self, event):
- PluginType = self.PluginChilds.GetStringSelection()
- if PluginType != "":
- self.AddPlugin(PluginType)
- event.Skip()
-
- def OnDeleteButton(self, event):
- self.DeletePlugin()
- event.Skip()
-
def GetAddButtonFunction(self, plugin, window):
def AddButtonFunction(event):
if plugin and len(plugin.PlugChildsTypes) > 0:
@@ -1399,6 +1334,7 @@
PluginName = dialog.GetValue()
plugin.PlugAddChild(PluginName, PluginType)
self.RefreshPluginTree()
+ self.PluginRoot.RefreshPluginsBlockLists()
dialog.Destroy()
def DeletePlugin(self, plugin):
@@ -1407,6 +1343,7 @@
self.PluginInfos.pop(plugin)
plugin.PlugRemove()
del plugin
+ self.PluginRoot.RefreshPluginsBlockLists()
self.RefreshPluginTree()
dialog.Destroy()
--- a/Beremiz_service.py Fri Sep 18 14:58:22 2009 +0200
+++ b/Beremiz_service.py Mon Sep 21 12:12:08 2009 +0200
@@ -526,9 +526,9 @@
class PLCStoppedHMI(PLCHMI):
docFactory = loaders.stan(tags.div(render=tags.directive('liveElement'))[
- tags.h1["PLC IS STOPPED"]
+ tags.h1["PLC IS STOPPED"],
])
-
+
class MainPage(athena.LiveElement):
jsClass = u"WebInterface.PLC"
docFactory = loaders.stan(tags.div(render=tags.directive('liveElement'))[
@@ -582,7 +582,7 @@
def detachFragmentChildren(self):
for child in self.liveFragmentChildren[:]:
child.detach()
-
+
class WebInterface(athena.LivePage):
docFactory = loaders.stan([tags.raw(xhtml_header),
@@ -594,7 +594,7 @@
]]]])
MainPage = MainPage()
PLCHMI = PLCHMI
-
+
def __init__(self, plcState=False, *a, **kw):
super(WebInterface, self).__init__(*a, **kw)
self.jsModules.mapping[u'WebInterface'] = util.sibpath(__file__, 'webinterface.js')
@@ -645,7 +645,7 @@
self.MainPage.resetHMI()
#print reason
#print "We will be called back when the client disconnects"
-
+
if havewx:
reactor.registerWxApp(app)
res = WebInterface()
--- a/discovery.py Fri Sep 18 14:58:22 2009 +0200
+++ b/discovery.py Mon Sep 21 12:12:08 2009 +0200
@@ -27,188 +27,185 @@
import wx.lib.mixins.listctrl as listmix
class AutoWidthListCtrl(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin):
- def __init__(self, parent, ID, pos=wx.DefaultPosition,
+ def __init__(self, parent, id, name, pos=wx.DefaultPosition,
size=wx.DefaultSize, style=0):
- wx.ListCtrl.__init__(self, parent, ID, pos, size, style)
+ wx.ListCtrl.__init__(self, parent, id, pos, size, style, name=name)
listmix.ListCtrlAutoWidthMixin.__init__(self)
+[ID_DISCOVERYDIALOG, ID_DISCOVERYDIALOGSTATICTEXT1,
+ ID_DISCOVERYDIALOGSERVICESLIST, ID_DISCOVERYDIALOGREFRESHBUTTON,
+ ID_DISCOVERYDIALOGLOCALBUTTON,
+] = [wx.NewId() for _init_ctrls in range(5)]
+
class DiscoveryDialog(wx.Dialog, listmix.ColumnSorterMixin):
- def __init__(self, parent, id=-1, title=_('Service Discovery')):
- self.my_result=None
- wx.Dialog.__init__(self, parent, id, title, size=(600,600), style=wx.DEFAULT_DIALOG_STYLE)
-
- # set up dialog sizer
-
- sizer = wx.FlexGridSizer(2, 1, 2, 2) # rows, cols, vgap, hgap
- sizer.AddGrowableRow(0)
- sizer.AddGrowableCol(0)
-
- # set up list control
-
- self.list = AutoWidthListCtrl(self, -1,
- #pos=(50,20),
- #size=(500,300),
- style=wx.LC_REPORT
- | wx.LC_EDIT_LABELS
- | wx.LC_SORT_ASCENDING
- | wx.LC_SINGLE_SEL
- )
- sizer.Add(self.list, 1, wx.EXPAND)
-
- btsizer = wx.FlexGridSizer(1, 6, 2, 2) # rows, cols, vgap, hgap
-
- sizer.Add(btsizer, 1, wx.EXPAND)
-
- self.PopulateList()
-
- self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected, self.list)
- self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnItemActivated, self.list)
-
- # set up buttons
-
- local_id = wx.NewId()
- b = wx.Button(self, local_id, _("Refresh"))
- self.Bind(wx.EVT_BUTTON, self.OnRefreshButton, b)
- btsizer.Add(b)
-
- btsizer.AddSpacer(0)
- btsizer.AddGrowableCol(1)
-
- local_id = wx.NewId()
- b = wx.Button(self, local_id, _("Local"))
- self.Bind(wx.EVT_BUTTON, self.ChooseLocalID, b)
- btsizer.Add(b)
-
- btsizer.AddSpacer(0)
- btsizer.AddGrowableCol(3)
-
- b = wx.Button(self, wx.ID_CANCEL, _("Cancel"))
- self.Bind(wx.EVT_BUTTON, self.OnCancel, b)
- btsizer.Add(b)
-
- b = wx.Button(self, wx.ID_OK, _("OK"))
- self.Bind(wx.EVT_BUTTON, self.OnOk, b)
- b.SetDefault()
- btsizer.Add(b)
-
- self.SetSizer(sizer)
-
+
+ def _init_coll_MainSizer_Items(self, parent):
+ parent.AddWindow(self.staticText1, 0, border=20, flag=wx.TOP|wx.LEFT|wx.RIGHT|wx.GROW)
+ parent.AddWindow(self.ServicesList, 0, border=20, flag=wx.LEFT|wx.RIGHT|wx.GROW)
+ parent.AddSizer(self.ButtonGridSizer, 0, border=20, flag=wx.LEFT|wx.RIGHT|wx.BOTTOM|wx.GROW)
+
+ def _init_coll_MainSizer_Growables(self, parent):
+ parent.AddGrowableCol(0)
+ parent.AddGrowableRow(1)
+
+ def _init_coll_ButtonGridSizer_Items(self, parent):
+ parent.AddWindow(self.RefreshButton, 0, border=0, flag=0)
+ parent.AddWindow(self.LocalButton, 0, border=0, flag=0)
+ parent.AddSizer(self.ButtonSizer, 0, border=0, flag=0)
+
+ def _init_coll_ButtonGridSizer_Growables(self, parent):
+ parent.AddGrowableCol(0)
+ parent.AddGrowableCol(1)
+ parent.AddGrowableRow(1)
+
+ def _init_sizers(self):
+ self.MainSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=3, vgap=10)
+ self.ButtonGridSizer = wx.FlexGridSizer(cols=3, hgap=5, rows=1, vgap=0)
+
+ self._init_coll_MainSizer_Items(self.MainSizer)
+ self._init_coll_MainSizer_Growables(self.MainSizer)
+ self._init_coll_ButtonGridSizer_Items(self.ButtonGridSizer)
+ self._init_coll_ButtonGridSizer_Growables(self.ButtonGridSizer)
+
+ self.SetSizer(self.MainSizer)
+
+ def _init_ctrls(self, prnt):
+ wx.Dialog.__init__(self, id=ID_DISCOVERYDIALOG,
+ name='DiscoveryDialog', parent=prnt,
+ size=wx.Size(600, 600), style=wx.DEFAULT_DIALOG_STYLE,
+ title='Service Discovery')
+
+ self.staticText1 = wx.StaticText(id=ID_DISCOVERYDIALOGSTATICTEXT1,
+ label=_('Services available:'), name='staticText1', parent=self,
+ pos=wx.Point(0, 0), size=wx.DefaultSize, style=0)
+
+ # Set up list control
+ self.ServicesList = AutoWidthListCtrl(id=ID_DISCOVERYDIALOGSERVICESLIST,
+ name='ServicesList', parent=self, pos=wx.Point(0, 0), size=wx.Size(0, 0),
+ style=wx.LC_REPORT|wx.LC_EDIT_LABELS|wx.LC_SORT_ASCENDING|wx.LC_SINGLE_SEL)
+ self.ServicesList.InsertColumn(0, 'NAME')
+ self.ServicesList.InsertColumn(1, 'TYPE')
+ self.ServicesList.InsertColumn(2, 'IP')
+ self.ServicesList.InsertColumn(3, 'PORT')
+ self.ServicesList.SetColumnWidth(0, 150)
+ self.ServicesList.SetColumnWidth(1, 150)
+ self.ServicesList.SetColumnWidth(2, 150)
+ self.ServicesList.SetColumnWidth(3, 150)
+ self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected, id=ID_DISCOVERYDIALOGSERVICESLIST)
+ self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnItemActivated, id=ID_DISCOVERYDIALOGSERVICESLIST)
+
listmix.ColumnSorterMixin.__init__(self, 4)
-
- # Used by the ColumnSorterMixin, see wx/lib/mixins/listctrl.py
+
+ self.RefreshButton = wx.Button(id=ID_DISCOVERYDIALOGREFRESHBUTTON,
+ label=_('Refresh'), name='RefreshButton', parent=self,
+ pos=wx.Point(0, 0), size=wx.DefaultSize, style=0)
+ self.Bind(wx.EVT_BUTTON, self.OnRefreshButton, id=ID_DISCOVERYDIALOGREFRESHBUTTON)
+
+ self.LocalButton = wx.Button(id=ID_DISCOVERYDIALOGLOCALBUTTON,
+ label=_('Local'), name='LocalButton', parent=self,
+ pos=wx.Point(0, 0), size=wx.DefaultSize, style=0)
+ self.Bind(wx.EVT_BUTTON, self.OnLocalButton, id=ID_DISCOVERYDIALOGLOCALBUTTON)
+
+ self.ButtonSizer = self.CreateButtonSizer(wx.OK|wx.CANCEL|wx.CENTER)
+
+ self._init_sizers()
+
+ def __init__(self, parent):
+ self._init_ctrls(parent)
+
self.itemDataMap = {}
-
- # a counter used to assign a unique id to each listctrl item
self.nextItemId = 0
-
- self.browser = None
- self.zConfInstance = Zeroconf()
+
+ self.URI = None
+ self.Browser = None
+
+ self.ZeroConfInstance = Zeroconf()
self.RefreshList()
-
- self.Bind(wx.EVT_CLOSE, self.OnClose)
-
+
+ def __del__(self):
+ self.Browser.cancel()
+ self.ZeroConfInstance.close()
+
def RefreshList(self):
- type = "_PYRO._tcp.local."
- self.browser = ServiceBrowser(self.zConfInstance, type, self)
+ self.Browser = ServiceBrowser(self.ZeroConfInstance, "_PYRO._tcp.local.", self)
def OnRefreshButton(self, event):
- self.list.DeleteAllItems()
- self.browser.cancel()
+ self.ServicesList.DeleteAllItems()
+ self.Browser.cancel()
self.RefreshList()
- def OnClose(self, event):
- self.zConfInstance.close()
- event.Skip()
-
- def OnCancel(self, event):
- self.zConfInstance.close()
- event.Skip()
-
- def OnOk(self, event):
- self.zConfInstance.close()
+ def OnLocalButton(self, event):
+ self.URI = "LOCAL://"
+ self.EndModal(wx.ID_OK)
event.Skip()
# Used by the ColumnSorterMixin, see wx/lib/mixins/listctrl.py
def GetListCtrl(self):
- return self.list
-
- def PopulateList(self):
- self.list.InsertColumn(0, 'NAME')
- self.list.InsertColumn(1, 'TYPE')
- self.list.InsertColumn(2, 'IP')
- self.list.InsertColumn(3, 'PORT')
- self.list.SetColumnWidth(0, 150)
- self.list.SetColumnWidth(1, 150)
- self.list.SetColumnWidth(2, 150)
- self.list.SetColumnWidth(3, 150)
+ return self.ServicesList
def getColumnText(self, index, col):
- item = self.list.GetItem(index, col)
+ item = self.ServicesList.GetItem(index, col)
return item.GetText()
def OnItemSelected(self, event):
- self.currentItem = event.m_itemIndex
- self.setresult()
+ self.SetURI(event.m_itemIndex)
event.Skip()
def OnItemActivated(self, event):
- self.currentItem = event.m_itemIndex
- self.setresult()
- self.Close()
+ self.SetURI(event.m_itemIndex)
+ self.EndModal(wx.ID_OK)
event.Skip()
- def setresult(self):
- connect_type = self.getColumnText(self.currentItem, 1)
- connect_address = self.getColumnText(self.currentItem, 2)
- connect_port = self.getColumnText(self.currentItem, 3)
-
- uri = self.CreateURI(connect_type, connect_address, connect_port)
- self.my_result=uri
-
- def GetResult(self):
- return self.my_result
+ def SetURI(self, idx):
+ connect_type = self.getColumnText(idx, 1)
+ connect_address = self.getColumnText(idx, 2)
+ connect_port = self.getColumnText(idx, 3)
+
+ self.URI = "%s://%s:%s"%(connect_type, connect_address, connect_port)
+
+ def GetURI(self):
+ return self.URI
def removeService(self, zeroconf, type, name):
'''
called when a service with the desired type goes offline.
'''
-
+
# loop through the list items looking for the service that went offline
- for idx in xrange(self.list.GetItemCount()):
+ for idx in xrange(self.ServicesList.GetItemCount()):
# this is the unique identifier assigned to the item
- item_id = self.list.GetItemData(idx)
+ item_id = self.ServicesList.GetItemData(idx)
# this is the full typename that was received by addService
item_name = self.itemDataMap[item_id][4]
if item_name == name:
- self.list.DeleteItem(idx)
+ self.ServicesList.DeleteItem(idx)
break
-
+
def addService(self, zeroconf, type, name):
'''
called when a service with the desired type is discovered.
'''
-
- info = self.zConfInstance.getServiceInfo(type, name)
+ info = self.ZeroConfInstance.getServiceInfo(type, name)
svcname = name.split(".")[0]
typename = type.split(".")[0][1:]
ip = str(socket.inet_ntoa(info.getAddress()))
port = info.getPort()
- num_items = self.list.GetItemCount()
+ num_items = self.ServicesList.GetItemCount()
# display the new data in the list
- new_item = self.list.InsertStringItem(num_items, svcname)
- self.list.SetStringItem(new_item, 1, "%s" % typename)
- self.list.SetStringItem(new_item, 2, "%s" % ip)
- self.list.SetStringItem(new_item, 3, "%s" % port)
+ new_item = self.ServicesList.InsertStringItem(num_items, svcname)
+ self.ServicesList.SetStringItem(new_item, 1, "%s" % typename)
+ self.ServicesList.SetStringItem(new_item, 2, "%s" % ip)
+ self.ServicesList.SetStringItem(new_item, 3, "%s" % port)
# record the new data for the ColumnSorterMixin
# we assign every list item a unique id (that won't change when items
# are added or removed)
- self.list.SetItemData(new_item, self.nextItemId)
+ self.ServicesList.SetItemData(new_item, self.nextItemId)
# the value of each column has to be stored in the itemDataMap
# so that ColumnSorterMixin knows how to sort the column.
@@ -218,11 +215,4 @@
self.itemDataMap[self.nextItemId] = [ svcname, typename, ip, port, name ]
self.nextItemId += 1
-
- def CreateURI(self, connect_type, connect_address, connect_port):
- uri = "%s://%s:%s"%(connect_type, connect_address, connect_port)
- return uri
-
- def ChooseLocalID(self, event):
- self.my_result = "LOCAL://"
- self.Close()
+
\ No newline at end of file
--- a/plugger.py Fri Sep 18 14:58:22 2009 +0200
+++ b/plugger.py Mon Sep 21 12:12:08 2009 +0200
@@ -11,8 +11,6 @@
#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"))
-sys.path.append(os.path.join(base_folder, "docutils"))
from docpdf import *
from xmlclass import GenerateClassesFromXSDstring
@@ -178,6 +176,9 @@
self.PlugParams[1].setElementValue(parts[1], value)
return value, False
+ def PlugMakeDir(self):
+ os.mkdir(self.PlugPath())
+
def PlugRequestSave(self):
# If plugin do not have corresponding directory
plugpath = self.PlugPath()
@@ -533,7 +534,7 @@
_self.ChangesToSave = False
else:
# If plugin do not have corresponding file/dirs - they will be created on Save
- os.mkdir(_self.PlugPath())
+ _self.PlugMakeDir()
# Find an IEC number
_self.FindNewIEC_Channel(0)
# Call the plugin real __init__
@@ -722,6 +723,7 @@
self.logger = logger
self._builder = None
self._connector = None
+ self.Deleting = False
# Setup debug information
self.IECdebug_datas = {}
@@ -748,8 +750,6 @@
# After __init__ root plugin is not valid
self.ProjectPath = None
self.BuildPath = None
- self.PLCEditor = None
- self.PLCDebug = None
self.DebugThread = None
self.debug_break = False
self.previous_plcstate = None
@@ -759,6 +759,9 @@
self.PluginMethods = [dic.copy() for dic in self.PluginMethods]
self.LoadSTLibrary()
+ def __del__(self):
+ self.Deleting = True
+
def PluginLibraryFilePath(self):
return os.path.join(os.path.split(__file__)[0], "pous.xml")
@@ -864,26 +867,18 @@
def SaveProject(self):
if not self.SaveXMLFile():
self.SaveXMLFile(os.path.join(self.ProjectPath, 'plc.xml'))
- if self.PLCEditor:
- self.PLCEditor.RefreshTitle()
result = self.PlugRequestSave()
if result:
self.logger.write_error(result)
- def CloseProject(self):
- if self.PLCEditor is not None:
- self.PLCEditor.Close()
- if self.PLCDebug is not None:
- self.PLCDebug.Close()
-
-
# Update PLCOpenEditor Plugin Block types from loaded plugins
def RefreshPluginsBlockLists(self):
if getattr(self, "PluggedChilds", None) is not None:
self.ClearPluginTypes()
self.AddPluginBlockList(self.PluginsBlockTypesFactory())
- if self.PLCEditor is not None:
- self.PLCEditor.RefreshEditor()
+ if self.AppFrame is not None:
+ self.AppFrame.RefreshLibraryTree()
+ self.AppFrame.RefreshEditor()
def PluginPath(self):
return os.path.join(os.path.split(__file__)[0], "plugins")
@@ -1233,8 +1228,8 @@
"""
Method called by user to (re)build SoftPLC and plugin tree
"""
- if self.PLCEditor is not None:
- self.PLCEditor.ClearErrors()
+ if self.AppFrame is not None:
+ self.AppFrame.ClearErrors()
buildpath = self._getBuildPath()
@@ -1330,11 +1325,11 @@
def ShowError(self, logger, from_location, to_location):
chunk_infos = self.GetChunkInfos(from_location, to_location)
- self._EditPLC()
for infos, (start_row, start_col) in chunk_infos:
start = (from_location[0] - start_row, from_location[1] - start_col)
end = (to_location[0] - start_row, to_location[1] - start_col)
- self.PLCEditor.ShowError(infos, start, end)
+ if self.AppFrame is not None:
+ self.AppFrame.ShowError(infos, start, end)
def _showIECcode(self):
plc_file = self._getIECcodepath()
@@ -1361,18 +1356,6 @@
new_dialog.Show()
- def _EditPLC(self):
- if self.PLCEditor is None:
- self.RefreshPluginsBlockLists()
- def _onclose():
- self.PLCEditor = None
- def _onsave():
- self.SaveProject()
- self.PLCEditor = PLCOpenEditor(self.AppFrame, self)
- self.PLCEditor._onclose = _onclose
- self.PLCEditor._onsave = _onsave
- self.PLCEditor.Show()
-
def _Clean(self):
if os.path.isdir(os.path.join(self._getBuildPath())):
self.logger.write(_("Cleaning the build directory\n"))
@@ -1475,11 +1458,12 @@
if self.DebugTimer is not None:
self.DebugTimer.cancel()
- # Timer to prevent rapid-fire when registering many variables
- # use wx.CallAfter use keep using same thread. TODO : use wx.Timer instead
- self.DebugTimer=Timer(0.5,wx.CallAfter,args = [self.RegisterDebugVarToConnector])
- # Rearm anti-rapid-fire timer
- self.DebugTimer.start()
+ if not self.Deleting:
+ # Timer to prevent rapid-fire when registering many variables
+ # use wx.CallAfter use keep using same thread. TODO : use wx.Timer instead
+ self.DebugTimer=Timer(0.5,wx.CallAfter,args = [self.RegisterDebugVarToConnector])
+ # Rearm anti-rapid-fire timer
+ self.DebugTimer.start()
def SubscribeDebugIECVariable(self, IECPath, callableobj, *args, **kwargs):
@@ -1579,15 +1563,8 @@
if self.GetIECProgramsAndVariables():
self._connector.StartPLC(debug=True)
self.logger.write(_("Starting PLC (debug mode)\n"))
- if self.PLCDebug is None:
- self.RefreshPluginsBlockLists()
- def _onclose():
- self.PLCDebug = None
- self.PLCDebug = PLCOpenEditor(self.AppFrame, self, debug=True)
- self.PLCDebug._onclose = _onclose
- self.PLCDebug.Show()
- else:
- self.PLCDebug.ResetGraphicViewers()
+ if self.AppFrame:
+ self.AppFrame.ResetGraphicViewers()
self.DebugThread = Thread(target=self.DebugThreadProc)
self.DebugThread.start()
else:
@@ -1639,11 +1616,14 @@
# if uri is empty launch discovery dialog
if uri == "":
# Launch Service Discovery dialog
- dia = DiscoveryDialog(self.AppFrame)
- dia.ShowModal()
- uri = dia.GetResult()
+ dialog = DiscoveryDialog(self.AppFrame)
+ answer = dialog.ShowModal()
+ uri = dialog.GetURI()
+ dialog.Destroy()
+
# Nothing choosed or cancel button
- if uri is None:
+ if uri is None or answer == wx.ID_CANCEL:
+ self.logger.write_error(_("Connection canceled!\n"))
return
else:
self.\
@@ -1733,9 +1713,9 @@
data = builder.GetBinaryCode()
if data is not None :
if self._connector.NewPLC(MD5, data, extrafiles):
- if self.PLCDebug is not None:
- self.PLCDebug.Close()
- self.PLCDebug = None
+ if self.AppFrame is not None:
+ self.AppFrame.CloseDebugTabs()
+ self.AppFrame.RefreshInstanceTree()
self.UnsubscribeAllDebugIECVariable()
self.ProgramTransferred()
self.logger.write(_("Transfer completed successfully.\n"))
@@ -1746,10 +1726,6 @@
self.UpdateMethodsFromPLCStatus()
PluginMethods = [
- {"bitmap" : opjimg("editPLC"),
- "name" : _("Edit PLC"),
- "tooltip" : _("Edit PLC program with PLCOpenEditor"),
- "method" : "_EditPLC"},
{"bitmap" : opjimg("Build"),
"name" : _("Build"),
"tooltip" : _("Build project into build folder"),
--- a/runtime/PLCObject.py Fri Sep 18 14:58:22 2009 +0200
+++ b/runtime/PLCObject.py Mon Sep 21 12:12:08 2009 +0200
@@ -111,6 +111,7 @@
else:
def DummyIterator(res):
self.DummyIteratorLock.acquire()
+ self.DummyIteratorLock.release()
return None
self._PythonIterator = DummyIterator
@@ -171,36 +172,10 @@
self.PLClibraryHandle = None
# Unload library explicitely
if getattr(self,"_PLClibraryHandle",None) is not None:
- PLCprint("Unload PLC")
dlclose(self._PLClibraryHandle)
- res = self._DetectDirtyLibs()
- else:
- res = False
-
- self._PLClibraryHandle = None
+ self._PLClibraryHandle = None
+
self.PLClibraryLock.release()
- return res
-
- def _DetectDirtyLibs(self):
- # Detect dirty libs
- # Get lib dependencies (for dirty lib detection)
- if os.name == "posix":
- # parasiting libs listed with ldd
- badlibs = [ toks.split()[0] for toks in commands.getoutput(
- "ldd "+self._GetLibFileName()).splitlines() ]
- for badlib in badlibs:
- if badlib[:6] in ["libwx_",
- "libwxs",
- "libgtk",
- "libgdk",
- "libatk",
- "libpan",
- "libX11",
- ]:
- #badhandle = dlopen(badlib, dl.RTLD_NOLOAD)
- PLCprint("Dirty lib detected :" + badlib)
- #dlclose(badhandle)
- return True
return False
def PrepareRuntimePy(self):
@@ -308,7 +283,7 @@
def NewPLC(self, md5sum, data, extrafiles):
PLCprint("NewPLC (%s)"%md5sum)
- if self.PLCStatus in ["Stopped", "Empty", "Dirty", "Broken"]:
+ if self.PLCStatus in ["Stopped", "Empty", "Broken"]:
NewFileName = md5sum + lib_ext
extra_files_log = os.path.join(self.workingdir,"extra_files.txt")
try:
--- a/targets/Linux/plc_Linux_main.c Fri Sep 18 14:58:22 2009 +0200
+++ b/targets/Linux/plc_Linux_main.c Mon Sep 21 12:12:08 2009 +0200
@@ -64,7 +64,7 @@
}
-static int __debug_tick;
+static unsigned long __debug_tick;
static pthread_mutex_t python_wait_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t python_mutex = PTHREAD_MUTEX_INITIALIZER;
@@ -75,8 +75,8 @@
int startPLC(int argc,char **argv)
{
struct sigevent sigev;
- /* Translate PLC's microseconds to Ttick nanoseconds */
- Ttick = 1000000 * maxval(common_ticktime__,1);
+ /* Define Ttick to 1ms if common_ticktime not defined */
+ Ttick = common_ticktime__?common_ticktime__:1000000;
memset (&sigev, 0, sizeof (struct sigevent));
sigev.sigev_value.sival_int = 0;
@@ -97,6 +97,8 @@
/* install signal handler for manual break */
// signal(SIGTERM, catch_signal);
signal(SIGINT, catch_signal);
+
+ pthread_mutex_trylock(&debug_mutex);
}else{
return 1;
}
@@ -120,6 +122,7 @@
timer_delete (PLC_timer);
__cleanup();
__debug_tick = -1;
+ pthread_mutex_unlock(&debug_mutex);
pthread_mutex_unlock(&debug_wait_mutex);
pthread_mutex_destroy(&debug_wait_mutex);
pthread_mutex_unlock(&python_wait_mutex);
@@ -127,9 +130,9 @@
return 0;
}
-extern int __tick;
+extern unsigned long __tick;
/* from plc_debugger.c */
-int WaitDebugData()
+unsigned long WaitDebugData()
{
/* Wait signal from PLC thread */
if(pthread_mutex_lock(&debug_wait_mutex)) return -1;
--- a/targets/Win32/plc_Win32_main.c Fri Sep 18 14:58:22 2009 +0200
+++ b/targets/Win32/plc_Win32_main.c Mon Sep 21 12:12:08 2009 +0200
@@ -8,7 +8,7 @@
#include <windows.h>
/* provided by POUS.C */
-extern int common_ticktime__;
+extern unsigned long common_ticktime__;
long AtomicCompareExchange(long* atomicvar, long compared, long exchange)
{
@@ -74,8 +74,8 @@
int startPLC(int argc,char **argv)
{
unsigned long thread_id = 0;
- /* Translate PLC's microseconds to Ttick nanoseconds */
- Ttick = 1000000 * maxval(common_ticktime__,1);
+ /* Define Ttick to 1ms if common_ticktime not defined */
+ Ttick = common_ticktime__?common_ticktime__:1000000;
debug_sem = CreateSemaphore(
NULL, // default security attributes
@@ -142,7 +142,7 @@
}
return 0;
}
-static int __debug_tick;
+static unsigned long __debug_tick;
int TryEnterDebugSection(void)
{
@@ -170,7 +170,7 @@
}
/* from plc_debugger.c */
-int WaitDebugData()
+unsigned long WaitDebugData()
{
if(WaitForSingleObject(debug_wait_sem, INFINITE) != WAIT_OBJECT_0) return -1;
return __debug_tick;
--- a/targets/Xenomai/plc_Xenomai_main.c Fri Sep 18 14:58:22 2009 +0200
+++ b/targets/Xenomai/plc_Xenomai_main.c Mon Sep 21 12:12:08 2009 +0200
@@ -29,7 +29,7 @@
#define WAITDEBUG_PIPE_SIZE 500
/* provided by POUS.C */
-extern int common_ticktime__;
+extern unsigned long common_ticktime__;
long AtomicCompareExchange(long* atomicvar,long compared, long exchange)
{
@@ -72,7 +72,7 @@
}
}
-static int __debug_tick;
+static unsigned long __debug_tick;
RT_SEM python_wait_sem;
RT_MUTEX python_mutex;
@@ -142,8 +142,8 @@
/* ne-memory-swapping for this program */
mlockall(MCL_CURRENT | MCL_FUTURE);
- /* Translate PLC's microseconds to Ttick nanoseconds */
- Ttick = 1000000 * max_val(common_ticktime__,1);
+ /* Define Ttick to 1ms if common_ticktime not defined */
+ Ttick = common_ticktime__?common_ticktime__:1000000;
/* create python_wait_sem */
ret = rt_sem_create(&python_wait_sem, "python_wait_sem", 0, S_FIFO);
@@ -203,9 +203,9 @@
rt_mutex_release(&debug_mutex);
}
-extern int __tick;
+extern unsigned long __tick;
/* from plc_debugger.c */
-int WaitDebugData()
+unsigned long WaitDebugData()
{
char message;
int res;
--- a/targets/plc_common_main.c Fri Sep 18 14:58:22 2009 +0200
+++ b/targets/plc_common_main.c Mon Sep 21 12:12:08 2009 +0200
@@ -5,13 +5,13 @@
#include <locale.h>
#include "iec_types.h"
/*
- * Prototypes of functions provied by generated C softPLC
+ * Prototypes of functions provided by generated C softPLC
**/
-void config_run__(int tick);
+void config_run__(unsigned long tick);
void config_init__(void);
/*
- * Prototypes of functions provied by generated target C code
+ * Prototypes of functions provided by generated target C code
* */
void __init_debug(void);
void __cleanup_debug(void);
@@ -22,8 +22,13 @@
* Variables used by generated C softPLC and plugins
**/
IEC_TIME __CURRENT_TIME;
-IEC_BOOL __DEBUG;
-int __tick = -1;
+IEC_BOOL __DEBUG = 0;
+unsigned long __tick = -1;
+
+/*
+ * Variable generated by C softPLC and plugins
+ **/
+extern unsigned long greatest_tick_count__;
/* Help to quit cleanly when init fail at a certain level */
static int init_level = 0;
@@ -39,6 +44,8 @@
void __run()
{
__tick++;
+ if (greatest_tick_count__)
+ __tick %%= greatest_tick_count__;
%(retrieve_calls)s
@@ -53,7 +60,7 @@
}
/*
- * Initialize variables according to PLC's defalut values,
+ * Initialize variables according to PLC's default values,
* and then init plugins with that values
**/
int __init(int argc,char **argv)
@@ -85,7 +92,7 @@
static long long Tsync = 0;
static long long FreqCorr = 0;
static int Nticks = 0;
-static int last_tick = 0;
+static unsigned long last_tick = 0;
static long long Ttick = 0;
#define mod %%
/*
--- a/targets/plc_debug.c Fri Sep 18 14:58:22 2009 +0200
+++ b/targets/plc_debug.c Mon Sep 21 12:12:08 2009 +0200
@@ -70,7 +70,7 @@
extern long AtomicCompareExchange(long*, long, long);
extern void InitiateDebugTransfer(void);
-extern int __tick;
+extern unsigned long __tick;
void __publish_debug()
{
/* Check there is no running debugger re-configuration */
@@ -102,7 +102,7 @@
/* compute next cursor positon*/
next_cursor = buffer_cursor + size;
/* if buffer not full */
- if(next_cursor < debug_buffer + BUFFER_SIZE)
+ if(next_cursor <= debug_buffer + BUFFER_SIZE)
{
/* copy data to the buffer */
memcpy(buffer_cursor, my_var->ptrvalue, size);