diff -r 077bcba2d485 -r e87e0166d0a7 ProjectController.py --- a/ProjectController.py Sat Oct 12 10:10:30 2013 +0900 +++ b/ProjectController.py Mon Oct 14 10:31:32 2013 +0200 @@ -22,7 +22,7 @@ from editors.FileManagementPanel import FileManagementPanel from editors.ProjectNodeEditor import ProjectNodeEditor from editors.IECCodeViewer import IECCodeViewer -from editors.DebugViewer import DebugViewer +from editors.DebugViewer import DebugViewer, REFRESH_PERIOD from dialogs import DiscoveryDialog from PLCControler import PLCControler from plcopen.structures import IEC_KEYWORDS @@ -110,6 +110,9 @@ self.MandatoryParams = None self._builder = None self._connector = None + self.DispatchDebugValuesTimer = None + self.DebugValuesBuffers = [] + self.DebugTicks = [] self.SetAppFrame(frame, logger) self.iec2c_path = os.path.join(base_folder, "matiec", "iec2c"+(".exe" if wx.Platform == '__WXMSW__' else "")) @@ -157,15 +160,23 @@ self.AppFrame = frame self.logger = logger self.StatusTimer = None + if self.DispatchDebugValuesTimer is not None: + self.DispatchDebugValuesTimer.Stop() + self.DispatchDebugValuesTimer = None if frame is not None: frame.LogViewer.SetLogSource(self._connector) # Timer to pull PLC status - ID_STATUSTIMER = wx.NewId() - self.StatusTimer = wx.Timer(self.AppFrame, ID_STATUSTIMER) - self.AppFrame.Bind(wx.EVT_TIMER, self.PullPLCStatusProc, self.StatusTimer) - + self.StatusTimer = wx.Timer(self.AppFrame, -1) + self.AppFrame.Bind(wx.EVT_TIMER, + self.PullPLCStatusProc, self.StatusTimer) + + # Timer to dispatch debug values to consumers + self.DispatchDebugValuesTimer = wx.Timer(self.AppFrame, -1) + self.AppFrame.Bind(wx.EVT_TIMER, + self.DispatchDebugValuesProc, self.DispatchDebugValuesTimer) + self.RefreshConfNodesBlockLists() def ResetAppFrame(self, logger): @@ -1177,6 +1188,12 @@ def PullPLCStatusProc(self, event): self.UpdateMethodsFromPLCStatus() + def SnapshotAndResetDebugValuesBuffers(self): + buffers, self.DebugValuesBuffers = (self.DebugValuesBuffers, + [list() for iec_path in self.TracedIECPath]) + ticks, self.DebugTicks = self.DebugTicks, [] + return ticks, buffers + def RegisterDebugVarToConnector(self): self.DebugTimer=None Idxs = [] @@ -1210,11 +1227,12 @@ else: self.TracedIECPath = [] self._connector.SetTraceVariablesList([]) + self.SnapshotAndResetDebugValuesBuffers() self.IECdebug_lock.release() def IsPLCStarted(self): return self.previous_plcstate == "Started" - + def ReArmDebugRegisterTimer(self): if self.DebugTimer is not None: self.DebugTimer.cancel() @@ -1233,7 +1251,7 @@ Idx, IEC_Type = self._IECPathToIdx.get(IECPath,(None,None)) return IEC_Type - def SubscribeDebugIECVariable(self, IECPath, callableobj, *args, **kwargs): + def SubscribeDebugIECVariable(self, IECPath, callableobj, buffer_list=False, *args, **kwargs): """ Dispatching use a dictionnary linking IEC variable paths to a WeakKeyDictionary linking @@ -1250,7 +1268,8 @@ WeakKeyDictionary(), # Callables [], # Data storage [(tick, data),...] "Registered", # Variable status - None] # Forced value + None, + buffer_list] # Forced value self.IECdebug_datas[IECPath] = IECdebug_data IECdebug_data[0][callableobj]=(args, kwargs) @@ -1347,14 +1366,14 @@ #print [dict.keys() for IECPath, (dict, log, status, fvalue) in self.IECdebug_datas.items()] if plc_status == "Started": self.IECdebug_lock.acquire() - if len(debug_vars) == len(self.TracedIECPath): + if len(debug_vars) == len(self.DebugValuesBuffers): if debug_getvar_retry > DEBUG_RETRIES_WARN: self.logger.write(_("... debugger recovered\n")) debug_getvar_retry = 0 - for IECPath,value in zip(self.TracedIECPath, debug_vars): + for values_buffer, value in zip(self.DebugValuesBuffers, debug_vars): if value is not None: - self.CallWeakcallables(IECPath, "NewValue", debug_tick, value) - self.CallWeakcallables("__tick__", "NewDataAvailable", debug_tick) + values_buffer.append(value) + self.DebugTicks.append(debug_tick) self.IECdebug_lock.release() if debug_getvar_retry == DEBUG_RETRIES_WARN: self.logger.write(_("Waiting debugger to recover...\n")) @@ -1368,6 +1387,20 @@ self.debug_break = True self.logger.write(_("Debugger disabled\n")) self.DebugThread = None + if self.DispatchDebugValuesTimer is not None: + self.DispatchDebugValuesTimer.Stop() + + def DispatchDebugValuesProc(self, event): + self.IECdebug_lock.acquire() + debug_ticks, buffers = self.SnapshotAndResetDebugValuesBuffers() + self.IECdebug_lock.release() + if len(self.TracedIECPath) == len(buffers): + for IECPath, values in zip(self.TracedIECPath, buffers): + if len(values) > 0: + self.CallWeakcallables(IECPath, "NewValues", debug_ticks, values) + if len(debug_ticks) > 0: + self.CallWeakcallables("__tick__", "NewDataAvailable", debug_ticks) + event.Skip() def KillDebugThread(self): tmp_debugthread = self.DebugThread @@ -1380,12 +1413,16 @@ else: self.logger.write(_("Debugger stopped.\n")) self.DebugThread = None + if self.DispatchDebugValuesTimer is not None: + self.DispatchDebugValuesTimer.Stop() def _connect_debug(self): self.previous_plcstate = None if self.AppFrame: self.AppFrame.ResetGraphicViewers() self.RegisterDebugVarToConnector() + if self.DispatchDebugValuesTimer is not None: + self.DispatchDebugValuesTimer.Start(int(REFRESH_PERIOD * 1000)) if self.DebugThread is None: self.DebugThread = Thread(target=self.DebugThreadProc) self.DebugThread.start()