diff -r aff053bad924 -r a66e150f2888 plugger.py --- a/plugger.py Tue Sep 02 12:24:25 2008 +0200 +++ b/plugger.py Wed Sep 03 17:28:17 2008 +0200 @@ -600,7 +600,7 @@ ieclib_path = os.path.join(base_folder, "matiec", "lib") # import for project creation timestamping -from threading import Timer, Lock +from threading import Timer, Lock, Thread from time import localtime from datetime import datetime # import necessary stuff from PLCOpenEditor @@ -617,6 +617,7 @@ import targets import connectors from discovery import DiscoveryDialog +from weakref import WeakKeyDictionary class PluginsRoot(PlugTemplate, PLCControler): """ @@ -666,10 +667,8 @@ self.IECdebug_datas = {} self.IECdebug_lock = Lock() - # Timer to prevent rapid-fire when registering many variables - self.DebugTimer=Timer(0.5,self.RegisterDebugVarToConnector) + self.DebugTimer=None self.ResetIECProgramsAndVariables() - #This method are not called here... but in NewProject and OpenProject #self._AddParamsMembers() @@ -972,8 +971,8 @@ self._ProgramList = None self._VariablesList = None self._IECPathToIdx = None - self._IdxToIECPath = None - + self.TracedIECPath = [] + def GetIECProgramsAndVariables(self): """ Parse CSV-like file VARIABLES.csv resulting from IEC2C compiler. @@ -989,7 +988,6 @@ self._ProgramList = [] self._VariablesList = [] self._IECPathToIdx = {} - self._IdxToIECPath = {} # Separate sections ListGroup = [] @@ -1023,7 +1021,6 @@ IEC_path=attrs["IEC_path"] Idx=int(attrs["num"]) self._IECPathToIdx[IEC_path]=Idx - self._IdxToIECPath[Idx]=IEC_path except Exception,e: self.logger.write_error("Cannot open/parse VARIABLES.csv!\n") self.logger.write_error(traceback.format_exc()) @@ -1059,28 +1056,31 @@ return debug_code def RegisterDebugVarToConnector(self): + self.DebugTimer=None Idxs = [] + self.TracedIECPath = [] if self._connector is not None: self.IECdebug_lock.acquire() - for IECPath,data_tuple in self.IECdebug_datas: + for IECPath,data_tuple in self.IECdebug_datas.iteritems(): WeakCallableDict, data_log, status = data_tuple if len(WeakCallableDict) == 0: # Callable Dict is empty. # This variable is not needed anymore! # self.IECdebug_callables.pop(IECPath) # TODO - pass + print "Unused : " + IECPath else: # Convert Idx = self._IECPathToIdx.get(IECPath,None) if Idx is not None: Idxs.append(Idx) + self.TracedIECPath.append(IECPath) else: self.logger.write_warning("Debug : Unknown variable %s\n"%IECPath) + self._connector.SetTraceVariablesList(Idxs) self.IECdebug_lock.release() - self._connector.TraceVariables(Idxs) - - def SubscribeDebugIECVariable(self, IECPath, callable, *args, **kwargs): + + def SubscribeDebugIECVariable(self, IECPath, callableobj, *args, **kwargs): """ Dispatching use a dictionnary linking IEC variable paths to a WeakKeyDictionary linking @@ -1096,12 +1096,20 @@ "Registered"] # Variable status self.IECdebug_datas[IECPath] = IECdebug_data - IECdebug_data[0][callable]=(args, kwargs) + IECdebug_data[0][callableobj]=(args, kwargs) self.IECdebug_lock.release() + + 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.cancel() self.DebugTimer.start() + + return IECdebug_data[1] def Generate_plc_common_main(self): """ @@ -1329,19 +1337,58 @@ self.logger.write_error("Couldn't start PLC !\n") self.UpdateMethodsFromPLCStatus() - def _Debug(self): + def DebugThreadProc(self): + while self._connector is not None: + debug_tick, debug_vars = self._connector.GetTraceVariables() + print debug_tick, debug_vars + if debug_vars is not None and \ + len(debug_vars) == len(self.TracedIECPath): + for IECPath,value in zip(self.TracedIECPath, debug_vars): + data_tuple = self.IECdebug_datas.get(IECPath, None) + if data_tuple is not None: + WeakCallableDict, data_log, status = data_tuple + data_log.append((debug_tick, value)) + for weakcallable,(args,kwargs) in WeakCallableDict.iteritems(): + wx.CallAfter(weakcallable, value, *args, **kwargs) + elif debug_vars is not None: + wx.CallAfter(self.logger.write_warning, + "debug data not coherent %d != %d"%(len(debug_vars), len(self.TracedIECPath))) + elif debug_tick == -1: + #wx.CallAfter(self.logger.write, "Debugger unavailable\n") + pass + else: + wx.CallAfter(self.logger.write, "Debugger disabled\n") + break + + def _Debug(self): """ Start PLC (Debug Mode) """ - if self.GetIECProgramsAndVariables() and self._connector.StartPLC(): + if self.GetIECProgramsAndVariables() and \ + self._connector.StartPLC(debug=True): self.logger.write("Starting PLC (debug mode)\n") # TODO : laucnch PLCOpenEditor in Debug Mode - self.logger.write_warning("Debug mode for PLCopenEditor not implemented\n") - self.logger.write_warning("Starting alternative test GUI\n") - # TODO : laucnch PLCOpenEditor in Debug Mode + self.DebugThread = Thread(target=self.DebugThreadProc) + self.DebugThread.start() else: self.logger.write_error("Couldn't start PLC debug !\n") self.UpdateMethodsFromPLCStatus() + +# def _Do_Test_Debug(self): +# # debug code +# self.temporary_non_weak_callable_refs = [] +# for IEC_Path, idx in self._IECPathToIdx.iteritems(): +# class tmpcls: +# def __init__(self): +# self.buf = None +# def setbuf(self,buf): +# self.buf = buf +# def __call__(self, value, idx, name): +# print "debug call:", value, idx, name, self.buf +# a = tmpcls() +# res = self.SubscribeDebugIECVariable(IEC_Path, a, idx, IEC_Path) +# a.setbuf(res) +# self.temporary_non_weak_callable_refs.append(a) def _Stop(self): """ @@ -1485,6 +1532,10 @@ "shown" : False, "tooltip" : "Start PLC (debug mode)", "method" : "_Debug"}, +# {"bitmap" : opjimg("Debug"), +# "name" : "Do_Test_Debug", +# "tooltip" : "Test debug mode)", +# "method" : "_Do_Test_Debug"}, {"bitmap" : opjimg("Stop"), "name" : "Stop", "shown" : False,