# HG changeset patch # User laurent # Date 1275489300 -7200 # Node ID 6ff2c1d346406ad1891940f0b3475b290879fb56 # Parent ad05f27222cdcb7b8e06fd9785874089ace5e9ca Modifying LPCBeremiz to launch silently a frame and show or hide it on demand. Adding support for transferring LPC programs. diff -r ad05f27222cd -r 6ff2c1d34640 Beremiz.py --- a/Beremiz.py Wed Jun 02 10:08:58 2010 +0200 +++ b/Beremiz.py Wed Jun 02 16:35:00 2010 +0200 @@ -468,6 +468,8 @@ self.local_runtime.kill(gently=False) # clear temp dir shutil.rmtree(self.local_runtime_tmpdir) + + self.local_runtime = None def OnOpenWidgetInspector(self, evt): # Activate the widget inspection tool diff -r ad05f27222cd -r 6ff2c1d34640 LPCBeremiz.py --- a/LPCBeremiz.py Wed Jun 02 10:08:58 2010 +0200 +++ b/LPCBeremiz.py Wed Jun 02 16:35:00 2010 +0200 @@ -41,7 +41,7 @@ else: projectOpen = None buildpath = None - + class PseudoLocale: LocaleDirs = [] Domains = [] @@ -367,6 +367,8 @@ elif os.path.isfile(srcpath): shutil.copy2(srcpath, dstpath) +[SIMULATION_MODE, TRANSFER_MODE] = range(2) + class LPCPluginsRoot(PluginsRoot): PluginMethods = [ @@ -384,10 +386,6 @@ "shown" : False, "tooltip" : _("Stop Running PLC"), "method" : "_Stop"}, - {"bitmap" : opjimg("Build"), - "name" : _("Build"), - "tooltip" : _("Build project into build folder"), - "method" : "_build"}, {"bitmap" : opjimg("Transfer"), "name" : _("Transfer"), "shown" : False, @@ -400,31 +398,33 @@ self.PlugChildsTypes += [("LPCBus", LPCBus, "LPC bus")] - self.OnlineMode = 0 - self.OnlinePath = None - - self.BuildSimulation = False + self.OnlineMode = "OFF" + self.LPCConnector = False + + self.CurrentMode = None + self.previous_mode = None + self.SimulationBuildPath = None - - self.previous_simulating = False - + + self.AbortTransferTimer = None + def GetProjectName(self): return self.Project.getname() def GetDefaultTargetName(self): - if self.BuildSimulation: + if self.CurrentMode == SIMULATION_MODE: return PluginsRoot.GetDefaultTargetName(self) else: return "LPC" def GetTarget(self): target = PluginsRoot.GetTarget(self) - if not self.BuildSimulation: + if self.CurrentMode != SIMULATION_MODE: target.getcontent()["value"].setBuildPath(self.BuildPath) return target def _getBuildPath(self): - if self.BuildSimulation: + if self.CurrentMode == SIMULATION_MODE: if self.SimulationBuildPath is None: self.SimulationBuildPath = os.path.join(tempfile.mkdtemp(), os.path.basename(self.ProjectPath), "build") return self.SimulationBuildPath @@ -440,54 +440,72 @@ return self.Project.setname(name) def SetOnlineMode(self, mode, path=None): - if self.OnlineMode != mode: - self.OnlineMode = mode - self.KillDebugThread() - - if self.OnlineMode != 0: - if self._connector is None: - uri = "LPC://%s" % path - try: - self._connector = connectors.ConnectorFactory(uri, self) - except Exception, msg: - self.logger.write_error(_("Exception while connecting %s!\n")%uri) - self.logger.write_error(traceback.format_exc()) - - # Did connection success ? - if self._connector is None: - # Oups. - self.logger.write_error(_("Connection failed to %s!\n")%uri) - - if self._connector is not None: - - if self.OnlineMode == 1: - self.CompareLocalAndRemotePLC() - - # Init with actual PLC status and print it - self.UpdateMethodsFromPLCStatus() - if self.previous_plcstate is not None: - status = _(self.previous_plcstate) - else: - status = "" - self.logger.write(_("PLC is %s\n")%status) - - # Start the status Timer - self.StatusTimer.Start(milliseconds=500, oneShot=False) - - if self.previous_plcstate=="Started": - if self.DebugAvailable() and self.GetIECProgramsAndVariables(): - self.logger.write(_("Debug connect matching running PLC\n")) - self._connect_debug() - else: - self.logger.write_warning(_("Debug do not match PLC - stop/transfert/start to re-enable\n")) + if self.OnlineMode != mode.upper(): + self.OnlineMode = mode.upper() + + if self.OnlineMode != "OFF": + uri = "LPC://%s" % path + try: + self.LPCConnector = connectors.ConnectorFactory(uri, self) + except Exception, msg: + self.logger.write_error(_("Exception while connecting %s!\n")%uri) + self.logger.write_error(traceback.format_exc()) + + # Did connection success ? + if self.LPCConnector is None: + # Oups. + self.logger.write_error(_("Connection failed to %s!\n")%uri) else: - self._connector = None + self.LPCConnector = None + + self.ApplyOnlineMode() + + def ApplyOnlineMode(self): + if self.CurrentMode != SIMULATION_MODE: + self.KillDebugThread() + + self._connector = self.LPCConnector + + # Init with actual PLC status and print it + self.UpdateMethodsFromPLCStatus() + + if self.LPCConnector is not None and self.OnlineMode == "APPLICATION": + + self.CompareLocalAndRemotePLC() + + if self.previous_plcstate is not None: + status = _(self.previous_plcstate) + else: + status = "" + self.logger.write(_("PLC is %s\n")%status) + + if not self.StatusTimer.IsRunning(): + # Start the status Timer + self.StatusTimer.Start(milliseconds=500, oneShot=False) + + if self.previous_plcstate=="Started": + if self.DebugAvailable() and self.GetIECProgramsAndVariables(): + self.logger.write(_("Debug connect matching running PLC\n")) + self._connect_debug() + else: + self.logger.write_warning(_("Debug do not match PLC - stop/transfert/start to re-enable\n")) + + elif self.StatusTimer.IsRunning(): self.StatusTimer.Stop() + + if self.CurrentMode == TRANSFER_MODE: - self.OnlinePath = path - self.UpdateMethodsFromPLCStatus() - + if self.OnlineMode == "BOOTLOADER": + self.BeginTransfer() + + elif self.OnlineMode == "APPLICATION": + self.CurrentMode = None + self.AbortTransferTimer.Stop() + self.AbortTransferTimer = None + + self.logger.write(_("PLC transferred successfully\n")) + # Update a PLCOpenEditor Pou variable name def UpdateProjectVariableName(self, old_name, new_name): self.Project.updateElementName(old_name, new_name) @@ -548,7 +566,10 @@ if self.PlugTestModified(): self.SaveProject() - self.RefreshPluginsBlockLists() + if wx.GetApp() is None: + self.RefreshPluginsBlockLists() + else: + wx.CallAfter(self.RefreshPluginsBlockLists) return None @@ -556,46 +577,38 @@ def UpdateMethodsFromPLCStatus(self): # Get PLC state : Running or Stopped # TODO : use explicit status instead of boolean - simulating = False - if self.OnlineMode == 0: - if self._connector is not None: - simulating = self._connector.GetPLCstatus() == "Started" + if self.OnlineMode == "OFF": status = "Disconnected" - elif self.OnlineMode == 2: - if self._connector is not None: - simulating = self._connector.GetPLCstatus() == "Started" + elif self.OnlineMode == "BOOTLOADER": status = "Connected" else: if self._connector is not None: status = self._connector.GetPLCstatus() else: status = "Disconnected" - if self.previous_plcstate != status or self.previous_simulating != simulating: + if self.previous_plcstate != status or self.previous_mode != self.CurrentMode: + simulating = self.CurrentMode == SIMULATION_MODE for args in { "Started" : [("_Simulate", False), ("_Run", False), ("_Stop", True), - ("_build", False), ("_Transfer", False)], - "Stopped" : [("_Simulate", False), + "Stopped" : [("_Simulate", True), ("_Run", True), ("_Stop", False), - ("_build", False), ("_Transfer", False)], "Connected" : [("_Simulate", not simulating), ("_Run", False), ("_Stop", simulating), - ("_build", False), ("_Transfer", True)], "Disconnected" :[("_Simulate", not simulating), ("_Run", False), ("_Stop", simulating), - ("_build", True), ("_Transfer", False)], }.get(status,[]): self.ShowMethod(*args) self.previous_plcstate = status - self.previous_simulating = simulating + self.previous_mode = self.CurrentMode return True return False @@ -619,6 +632,8 @@ """ Method called by user to Simulate PLC """ + self.CurrentMode = SIMULATION_MODE + uri = "LOCAL://" try: self._connector = connectors.ConnectorFactory(uri, self) @@ -630,11 +645,9 @@ if self._connector is None: # Oups. self.logger.write_error(_("Connection failed to %s!\n")%uri) + self.StopSimulation() return False - self.BuildSimulation = True - - buildpath = self._getBuildPath() # Eventually create build dir @@ -647,7 +660,7 @@ # If IEC code gen fail, bail out. if not IECGenRes: self.logger.write_error(_("IEC-61131-3 code generation failed !\n")) - self.BuildSimulation = False + self.StopSimulation() return False # Reset variable and program list that are parsed from @@ -694,26 +707,26 @@ except Exception, exc: self.logger.write_error(name+_(" generation failed !\n")) self.logger.write_error(traceback.format_exc()) - self.BuildSimulation = False + self.StopSimulation() return False # Get simulation builder builder = self.GetBuilder() if builder is None: self.logger.write_error(_("Fatal : cannot get builder.\n")) - self.BuildSimulation = False + self.StopSimulation() return False # Build try: if not builder.build() : self.logger.write_error(_("C Build failed.\n")) - self.BuildSimulation = False + self.StopSimulation() return False except Exception, exc: self.logger.write_error(_("C Build crashed !\n")) self.logger.write_error(traceback.format_exc()) - self.BuildSimulation = False + self.StopSimulation() return False data = builder.GetBinaryCode() @@ -727,16 +740,59 @@ self.logger.write(_("Transfer completed successfully.\n")) else: self.logger.write_error(_("Transfer failed\n")) - self.BuildSimulation = False + self.StopSimulation() return False self._Run() - self.BuildSimulation = False - - # Start the status Timer - self.StatusTimer.Start(milliseconds=500, oneShot=False) - + if not self.StatusTimer.IsRunning(): + # Start the status Timer + self.StatusTimer.Start(milliseconds=500, oneShot=False) + + def StopSimulation(self): + self.CurrentMode = None + self.ApplyOnlineMode() + + def _Stop(self): + PluginsRoot._Stop(self) + + if self.CurrentMode == SIMULATION_MODE: + self.StopSimulation() + + def _Transfer(self): + if self.CurrentMode is None and self.OnlineMode != "OFF": + self.CurrentMode = TRANSFER_MODE + + PluginsRoot._build(self) + + ID_ABORTTRANSFERTIMER = wx.NewId() + self.AbortTransferTimer = wx.Timer(self.AppFrame, ID_ABORTTRANSFERTIMER) + self.AppFrame.Bind(wx.EVT_TIMER, self.AbortTransfer, self.AbortTransferTimer) + + if self.OnlineMode == "BOOTLOADER": + self.BeginTransfer() + + else: + self.logger.write(_("Resetting PLC\n")) + + self.LPCConnector.ResetPLC() + self.AbortTransferTimer.Start(milliseconds=5000, oneShot=True) + + def BeginTransfer(self): + self.logger.write(_("Start PLC transfer\n")) + + self.AbortTransferTimer.Stop() + PluginsRoot._Transfer(self) + self.AbortTransferTimer.Start(milliseconds=5000, oneShot=True) + + def AbortTransfer(self, event): + self.logger.write(_("Transfer failed\n")) + + self.CurrentMode = None + self.AbortTransferTimer.Stop() + self.AbortTransferTimer = None + event.Skip() + #------------------------------------------------------------------------------- # LPCBeremiz Class #------------------------------------------------------------------------------- @@ -795,7 +851,9 @@ def OnCloseFrame(self, event): global frame - frame = None + + frame.Hide() + self.PluginRoot.ResetAppFrame(lpcberemiz_cmd.Log) if self.PluginRoot.OnlineMode == 0: self.PluginRoot._connector = None @@ -806,7 +864,7 @@ print "Closed" sys.stdout.flush() - event.Skip() + event.Veto() def ShowProperties(self): old_values = self.Controler.GetProjectProperties() @@ -996,14 +1054,9 @@ frame = None app = None -def GetApp(): - global app - return app -wx.GetApp = GetApp - -def BeremizStartProc(plugin_root): +def MainLoopProc(plugin_root): global frame, app - + app = wx.PySimpleApp() app.SetAppName('beremiz') wx.InitAllImageHandlers() @@ -1025,17 +1078,11 @@ # Install a exception handle for bug reports AddExceptHook(os.getcwd(),__version__) - + frame = LPCBeremiz(None, plugin_root=plugin_root, debug=True) - plugin_root.SetAppFrame(frame, frame.Log) - frame.Show() - frame.Raise() app.MainLoop() - - frame = None - app = None - + class StdoutPseudoFile: """ Base class for file like objects to facilitate StdOut for the Shell.""" def write(self, s, style = None): @@ -1074,6 +1121,8 @@ print "Error: Invalid project directory", result else: print "Error: No such file or directory" + beremiz_thread=Thread(target=MainLoopProc, args=[self.PluginRoot]) + beremiz_thread.start() def RestartTimer(self): if self.RefreshTimer is not None: @@ -1082,7 +1131,9 @@ self.RefreshTimer.start() def Exit(self): + global frame, app self.Close() + app.ExitMainLoop() return True def do_EOF(self, line): @@ -1090,9 +1141,9 @@ def Show(self): global frame - if frame is None: - beremiz_thread=Thread(target=BeremizStartProc, args=[self.PluginRoot]) - beremiz_thread.start() + if frame is not None: + self.PluginRoot.SetAppFrame(frame, frame.Log) + wx.CallAfter(frame.Show) def Refresh(self): global frame @@ -1106,13 +1157,10 @@ self.PluginRoot.ResetAppFrame(self.Log) if frame is not None: - wx.CallAfter(frame.Close) + wx.CallAfter(frame.Hide) def Compile(self): - if wx.GetApp() is None: - self.PluginRoot._build() - else: - wx.CallAfter(self.PluginRoot._build) + wx.CallAfter(self.PluginRoot._build) def SetProjectProperties(self, projectname, productname, productversion, companyname): properties = self.PluginRoot.GetProjectProperties() @@ -1124,7 +1172,7 @@ self.RestartTimer() def SetOnlineMode(self, mode, path=None): - self.PluginRoot.SetOnlineMode(mode, path) + wx.CallAfter(self.PluginRoot.SetOnlineMode, mode, path) self.RestartTimer() def AddBus(self, iec_channel, name, icon=None): @@ -1156,7 +1204,13 @@ for child in self.PluginRoot.IterChilds(): if child != bus and child.BaseParams.getIEC_Channel() == new_iec_channel: return "Error: A bus with IEC_channel %d already exists" % new_iec_channel - self.PluginRoot.UpdateProjectVariableLocation(str(old_iec_channel), str(new_iec_channel)) + if wx.GetApp() is None: + self.PluginRoot.UpdateProjectVariableLocation(str(old_iec_channel), + str(new_iec_channel)) + else: + wx.CallAfter(self.PluginRoot.UpdateProjectVariableLocation, + str(old_iec_channel), + str(new_iec_channel)) bus.BaseParams.setIEC_Channel(new_iec_channel) self.RestartTimer()