# HG changeset patch # User etisserant # Date 1231947674 -3600 # Node ID 3bd617ae7a05835b547ed5dea1b5fd0caa3177c7 # Parent d17bd2f00a87c4a519ddbc4fece5f78545e3141f Local Runtime (LOCAL://) now launched "on demand" Added Graphical Python shell in Tray Icon menu Fixed some missing __DEBUG variable assignement More generic per target LDFLAGS and CFLAGS diff -r d17bd2f00a87 -r 3bd617ae7a05 Beremiz.py --- a/Beremiz.py Fri Jan 09 17:08:31 2009 +0100 +++ b/Beremiz.py Wed Jan 14 16:41:14 2009 +0100 @@ -416,18 +416,10 @@ self._init_ctrls(parent) self.Log = LogPseudoFile(self.LogConsole) - - # create temporary directory for runtime working directory - self.local_runtime_tmpdir = tempfile.mkdtemp() - # choose an arbitrary random port for runtime - self.runtime_port = int(random.random() * 1000) + 61131 - # launch local runtime - self.local_runtime = ProcessLogger(self.Log, - "\"%s\" \"%s\" -p %s -i localhost -x 0 %s"%(sys.executable, - Bpath("Beremiz_service.py"), - self.runtime_port, - self.local_runtime_tmpdir), - no_gui=False) + + 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)) @@ -437,7 +429,7 @@ self.PluginInfos = {} if projectOpen: - self.PluginRoot = PluginsRoot(self, self.Log, self.runtime_port) + self.PluginRoot = PluginsRoot(self, self.Log) self.PluginRoot.LoadProject(projectOpen, buildpath) self.RefreshAll() else: @@ -445,6 +437,30 @@ self.RefreshMainMenu() + def StartLocalRuntime(self, taskbaricon = True): + if self.local_runtime is None or self.local_runtime.finished: + # create temporary directory for runtime working directory + self.local_runtime_tmpdir = tempfile.mkdtemp() + # choose an arbitrary random port for runtime + self.runtime_port = int(random.random() * 1000) + 61131 + # launch local runtime + self.local_runtime = ProcessLogger(self.Log, + "\"%s\" \"%s\" -p %s -i localhost %s %s"%(sys.executable, + Bpath("Beremiz_service.py"), + self.runtime_port, + {False : "-x 0", True :"-x 1"}[taskbaricon], + self.local_runtime_tmpdir), + no_gui=False) + self.local_runtime.spin(timeout=500, keyword = "working", kill_it = False) + return self.runtime_port + + def KillLocalRuntime(self): + if self.local_runtime is not None: + # shutdown local runtime + self.local_runtime.kill(gently=False) + # clear temp dir + shutil.rmtree(self.local_runtime_tmpdir) + def OnOpenWidgetInspector(self, evt): # Activate the widget inspection tool from wx.lib.inspection import InspectionTool @@ -492,11 +508,8 @@ event.Veto() return - # shutdown local runtime - self.local_runtime.kill(gently=False) - # clear temp dir - shutil.rmtree(self.local_runtime_tmpdir) - + self.KillLocalRuntime() + event.Skip() def OnMoveWindow(self, event): diff -r d17bd2f00a87 -r 3bd617ae7a05 Beremiz_service.py --- a/Beremiz_service.py Fri Jan 09 17:08:31 2009 +0100 +++ b/Beremiz_service.py Wed Jan 14 16:41:14 2009 +0100 @@ -215,6 +215,7 @@ message.Destroy() return self.EndModal(wx.ID_OK) + event.Skip() def GetValue(self): return self.GetSizer().GetItem(1).GetWindow().GetValue() @@ -222,21 +223,24 @@ def SetTests(self, tests): self.Tests = tests - class DemoTaskBarIcon(wx.TaskBarIcon): + class BeremizTaskBarIcon(wx.TaskBarIcon): TBMENU_CHANGE_NAME = wx.NewId() TBMENU_CHANGE_PORT = wx.NewId() TBMENU_CHANGE_INTERFACE = wx.NewId() + TBMENU_LIVE_SHELL = wx.NewId() TBMENU_CHANGE_WD = wx.NewId() TBMENU_QUIT = wx.NewId() def __init__(self, pyroserver): wx.TaskBarIcon.__init__(self) + self.pyroserver = pyroserver # Set the image self.UpdateIcon(None) # bind some events self.Bind(wx.EVT_MENU, self.OnTaskBarChangeName, id=self.TBMENU_CHANGE_NAME) self.Bind(wx.EVT_MENU, self.OnTaskBarChangeInterface, id=self.TBMENU_CHANGE_INTERFACE) + self.Bind(wx.EVT_MENU, self.OnTaskBarLiveShell, id=self.TBMENU_LIVE_SHELL) self.Bind(wx.EVT_MENU, self.OnTaskBarChangePort, id=self.TBMENU_CHANGE_PORT) self.Bind(wx.EVT_MENU, self.OnTaskBarChangeWorkingDir, id=self.TBMENU_CHANGE_WD) self.Bind(wx.EVT_MENU, self.OnTaskBarQuit, id=self.TBMENU_QUIT) @@ -251,6 +255,7 @@ menu = wx.Menu() menu.Append(self.TBMENU_CHANGE_NAME, "Change Name") menu.Append(self.TBMENU_CHANGE_INTERFACE, "Change IP of interface to bind") + menu.Append(self.TBMENU_LIVE_SHELL, "Launch a live Python shell") menu.Append(self.TBMENU_CHANGE_PORT, "Change Port Number") menu.AppendSeparator() menu.Append(self.TBMENU_CHANGE_WD, "Change working directory") @@ -276,34 +281,47 @@ ( lambda ip :len([x for x in ip.split(".") if 0 <= int(x) <= 255]) == 4, "Ip is not valid!") ]) if dlg.ShowModal() == wx.ID_OK: - pyroserver.ip = dlg.GetValue() - pyroserver.Stop() + self.pyroserver.ip = dlg.GetValue() + self.pyroserver.Stop() + evt.Skip() def OnTaskBarChangePort(self,evt): dlg = ParamsEntryDialog(None, "Enter a port number ", defaultValue=str(pyroserver.port)) dlg.SetTests([(UnicodeType.isdigit, "Port number must be an integer!"), (lambda port : 0 <= int(port) <= 65535 , "Port number must be 0 <= port <= 65535!")]) if dlg.ShowModal() == wx.ID_OK: - pyroserver.port = int(dlg.GetValue()) - pyroserver.Stop() - + self.pyroserver.port = int(dlg.GetValue()) + self.pyroserver.Stop() + evt.Skip() def OnTaskBarChangeWorkingDir(self,evt): dlg = wx.DirDialog(None, "Choose a working directory ", pyroserver.workdir, wx.DD_NEW_DIR_BUTTON) if dlg.ShowModal() == wx.ID_OK: - pyroserver.workdir = dlg.GetPath() - pyroserver.Stop() + self.pyroserver.workdir = dlg.GetPath() + self.pyroserver.Stop() + evt.Skip() def OnTaskBarChangeName(self,evt): dlg = ParamsEntryDialog(None, "Enter a name ", defaultValue=pyroserver.name) dlg.SetTests([(lambda name : len(name) is not 0 , "Name must not be null!")]) if dlg.ShowModal() == wx.ID_OK: - pyroserver.name = dlg.GetValue() - pyroserver.Restart() - + self.pyroserver.name = dlg.GetValue() + self.pyroserver.Restart() + evt.Skip() + + def OnTaskBarLiveShell(self,evt): + if self.pyroserver.plcobj is not None and self.pyroserver.plcobj.python_threads_vars is not None: + from wx import py + frame = py.shell.ShellFrame(locals=self.pyroserver.plcobj.python_threads_vars) + frame.Show() + else: + wx.MessageBox("No runnning PLC","Error") + evt.Skip() + def OnTaskBarQuit(self,evt): pyroserver.Quit() self.RemoveIcon() wx.GetApp().ExitMainLoop() + evt.Skip() def UpdateIcon(self, plcstatus): if plcstatus is "Started" : @@ -376,7 +394,7 @@ if havewx: app=wx.App(redirect=False) - taskbar_instance = DemoTaskBarIcon(pyroserver) + taskbar_instance = BeremizTaskBarIcon(pyroserver) def statuschange(status): wx.CallAfter(taskbar_instance.UpdateIcon,status) pyro_thread=Thread(target=pyroserver.Loop, args=[statuschange]) diff -r d17bd2f00a87 -r 3bd617ae7a05 connectors/__init__.py --- a/connectors/__init__.py Fri Jan 09 17:08:31 2009 +0100 +++ b/connectors/__init__.py Wed Jan 14 16:41:14 2009 +0100 @@ -39,9 +39,12 @@ factoryname = servicetype + "_connector_factory" return getattr(connectormodule, factoryname)(uri, pluginsroot) elif servicetype == "LOCAL": + #handle incompatibility with tray icon and svgui... + no_poisoned_plugin = pluginsroot.GetChildByType("svgui") is None + runtime_port = pluginsroot.AppFrame.StartLocalRuntime(taskbaricon = no_poisoned_plugin) import PYRO return PYRO.PYRO_connector_factory( - "PYRO://127.0.0.1:"+str(pluginsroot.runtime_port), + "PYRO://127.0.0.1:"+str(runtime_port), pluginsroot) else : return None diff -r d17bd2f00a87 -r 3bd617ae7a05 plugger.py --- a/plugger.py Fri Jan 09 17:08:31 2009 +0100 +++ b/plugger.py Wed Jan 14 16:41:14 2009 +0100 @@ -313,6 +313,12 @@ else: return self + def GetChildByType(self, TypeName): + if TypeName: + return self._GetChildBySomething("PlugType", TypeName) + else: + return self + def GetChildByIECLocation(self, Location): if Location: return self._GetChildBySomething("IEC_Channel", Location) @@ -668,10 +674,9 @@ """ - def __init__(self, frame, logger, runtime_port): + def __init__(self, frame, logger): PLCControler.__init__(self) - self.runtime_port = runtime_port self.MandatoryParams = None self.AppFrame = frame self.logger = logger diff -r d17bd2f00a87 -r 3bd617ae7a05 runtime/PLCObject.py --- a/runtime/PLCObject.py Fri Jan 09 17:08:31 2009 +0100 +++ b/runtime/PLCObject.py Wed Jan 14 16:41:14 2009 +0100 @@ -51,6 +51,7 @@ self._FreePLC() self.daemon = daemon self.statuschange = statuschange + self.python_threads_vars = None # Get the last transfered PLC if connector must be restart try: @@ -174,28 +175,29 @@ def PythonThreadProc(self): print "PythonThreadProc started" - my_globs = globals().copy() + self.python_threads_vars = globals().copy() pyfile = os.path.join(self.workingdir, "runtime.py") if os.path.exists(pyfile): # TODO handle exceptions in runtime.py # pyfile may redefine _runtime_cleanup # or even call _PythonThreadProc itself. - execfile(pyfile, my_globs) + execfile(pyfile, self.python_threads_vars) res,cmd = "None","None" while self.PLCStatus == "Started": - print "_PythonIterator(", res, ")", + #print "_PythonIterator(", res, ")", cmd = self._PythonIterator(res) - print " -> ", cmd + #print " -> ", cmd if cmd is None: break try : - res = str(eval(cmd,my_globs)) + res = str(eval(cmd,self.python_threads_vars)) except Exception,e: res = "#EXCEPTION : "+str(e) print res print "PythonThreadProc interrupted" - if my_globs.get("_runtime_cleanup",None) is not None: - my_globs["_runtime_cleanup"]() + if self.python_threads_vars.get("_runtime_cleanup",None) is not None: + self.python_threads_vars["_runtime_cleanup"]() + self.python_threads_vars = None print "PythonThreadProc cleaned up" def StartPLC(self, debug=False): diff -r d17bd2f00a87 -r 3bd617ae7a05 targets/Linux/__init__.py --- a/targets/Linux/__init__.py Fri Jan 09 17:08:31 2009 +0100 +++ b/targets/Linux/__init__.py Wed Jan 14 16:41:14 2009 +0100 @@ -2,4 +2,5 @@ class Linux_target(toolchain_gcc): extension = ".so" - CustomLDFLAGS = ["-shared", "-lrt"] + def getBuilderLDFLAGS(self): + return toolchain_gcc.getBuilderLDFLAGS(self) + ["-shared", "-lrt"] diff -r d17bd2f00a87 -r 3bd617ae7a05 targets/Linux/plc_Linux_main.c --- a/targets/Linux/plc_Linux_main.c Fri Jan 09 17:08:31 2009 +0100 +++ b/targets/Linux/plc_Linux_main.c Wed Jan 14 16:41:14 2009 +0100 @@ -141,12 +141,14 @@ void suspendDebug(void) { + __DEBUG = 0; /* Prevent PLC to enter debug code */ pthread_mutex_lock(&debug_mutex); } void resumeDebug(void) { + __DEBUG = 1; /* Let PLC enter debug code */ pthread_mutex_unlock(&debug_mutex); } diff -r d17bd2f00a87 -r 3bd617ae7a05 targets/Win32/__init__.py --- a/targets/Win32/__init__.py Fri Jan 09 17:08:31 2009 +0100 +++ b/targets/Win32/__init__.py Wed Jan 14 16:41:14 2009 +0100 @@ -2,7 +2,8 @@ class Win32_target(toolchain_gcc): extension = ".dll" - CustomLDFLAGS = ["-shared", + def getBuilderLDFLAGS(self): + return toolchain_gcc.getBuilderLDFLAGS(self) + ["-shared", "-Wl,--export-all-symbols", "-Wl,--enable-auto-import", "-Wl,--whole-archive", diff -r d17bd2f00a87 -r 3bd617ae7a05 targets/Win32/plc_Win32_main.c --- a/targets/Win32/plc_Win32_main.c Fri Jan 09 17:08:31 2009 +0100 +++ b/targets/Win32/plc_Win32_main.c Wed Jan 14 16:41:14 2009 +0100 @@ -188,12 +188,14 @@ void suspendDebug() { + __DEBUG = 0; /* Prevent PLC to enter debug code */ WaitForSingleObject(debug_sem, INFINITE); } void resumeDebug() { + __DEBUG = 1; /* Let PLC enter debug code */ ReleaseSemaphore(debug_sem, 1, NULL); } diff -r d17bd2f00a87 -r 3bd617ae7a05 targets/toolchain_gcc.py --- a/targets/toolchain_gcc.py Fri Jan 09 17:08:31 2009 +0100 +++ b/targets/toolchain_gcc.py Wed Jan 14 16:41:14 2009 +0100 @@ -19,6 +19,19 @@ self.md5key = None self.srcmd5 = {} + def getBuilderLDFLAGS(self): + """ + Returns list of builder specific CFLAGS + """ + return [self.PuginsRootInstance.BeremizRoot.getTargetType().getcontent()["value"].getCFLAGS()] + + def getBuilderCFLAGS(self): + """ + Returns list of builder specific LDFLAGS + """ + return self.PuginsRootInstance.LDFLAGS + \ + [self.PuginsRootInstance.BeremizRoot.getTargetType().getcontent()["value"].getLDFLAGS()] + def GetBinaryCode(self): try: return open(self.exe_path, "rb").read() @@ -67,9 +80,9 @@ # Retrieve toolchain user parameters toolchain_params = self.PuginsRootInstance.BeremizRoot.getTargetType().getcontent()["value"] self.compiler = toolchain_params.getCompiler() - self._CFLAGS = toolchain_params.getCFLAGS() self.linker = toolchain_params.getLinker() - self._LDFLAGS = toolchain_params.getLDFLAGS() + + Builder_CFLAGS = ' '.join(self.getBuilderCFLAGS()) ######### GENERATE OBJECT FILES ######################################## obns = [] @@ -98,7 +111,7 @@ status, result, err_result = ProcessLogger( self.logger, "\"%s\" -c \"%s\" -o \"%s\" %s %s"% - (self.compiler, CFile, objectfilename, self._CFLAGS, CFLAGS) + (self.compiler, CFile, objectfilename, Builder_CFLAGS, CFLAGS) ).spin() if status : @@ -117,7 +130,7 @@ # Generate list .o files listobjstring = '"' + '" "'.join(objs) + '"' - ALLldflags = ' '.join(self.CustomLDFLAGS+self.PuginsRootInstance.LDFLAGS+[self._LDFLAGS]) + ALLldflags = ' '.join(self.getBuilderLDFLAGS()) self.logger.write(" [CC] " + ' '.join(obns)+" -> " + self.exe + "\n")