plugger.py
changeset 243 90db933fe956
parent 239 112b4bc523b3
child 244 85e92d9e34a8
equal deleted inserted replaced
242:fc6d1988e4da 243:90db933fe956
   681         # Keep track of the plugin type name
   681         # Keep track of the plugin type name
   682         self.PlugType = "Beremiz"
   682         self.PlugType = "Beremiz"
   683         # After __init__ root plugin is not valid
   683         # After __init__ root plugin is not valid
   684         self.ProjectPath = None
   684         self.ProjectPath = None
   685         self.PLCEditor = None
   685         self.PLCEditor = None
       
   686         self.PLCDebug = None
   686         # copy PluginMethods so that it can be later customized
   687         # copy PluginMethods so that it can be later customized
   687         self.PluginMethods = [dic.copy() for dic in self.PluginMethods]
   688         self.PluginMethods = [dic.copy() for dic in self.PluginMethods]
   688 
   689 
   689     def PlugTestModified(self):
   690     def PlugTestModified(self):
   690          return self.ChangesToSave or not self.ProjectIsSaved()
   691          return self.ChangesToSave or not self.ProjectIsSaved()
  1306             for IECPathToPop in IECPathsToPop:
  1307             for IECPathToPop in IECPathsToPop:
  1307                 self.IECdebug_datas.pop(IECPathToPop)
  1308                 self.IECdebug_datas.pop(IECPathToPop)
  1308 
  1309 
  1309             self._connector.SetTraceVariablesList(Idxs)
  1310             self._connector.SetTraceVariablesList(Idxs)
  1310             self.IECdebug_lock.release()
  1311             self.IECdebug_lock.release()
       
  1312             
       
  1313             #for IEC_path, IECdebug_data in self.IECdebug_datas.iteritems():
       
  1314             #    print IEC_path, IECdebug_data[0].keys()
       
  1315 
       
  1316     def ReArmDebugRegisterTimer(self):
       
  1317         if self.DebugTimer is not None:
       
  1318             self.DebugTimer.cancel()
       
  1319 
       
  1320         # Timer to prevent rapid-fire when registering many variables
       
  1321         # use wx.CallAfter use keep using same thread. TODO : use wx.Timer instead
       
  1322         self.DebugTimer=Timer(0.5,wx.CallAfter,args = [self.RegisterDebugVarToConnector])
       
  1323         # Rearm anti-rapid-fire timer
       
  1324         self.DebugTimer.start()
       
  1325 
  1311         
  1326         
  1312     def SubscribeDebugIECVariable(self, IECPath, callableobj, *args, **kwargs):
  1327     def SubscribeDebugIECVariable(self, IECPath, callableobj, *args, **kwargs):
  1313         """
  1328         """
  1314         Dispatching use a dictionnary linking IEC variable paths
  1329         Dispatching use a dictionnary linking IEC variable paths
  1315         to a WeakKeyDictionary linking 
  1330         to a WeakKeyDictionary linking 
  1326             self.IECdebug_datas[IECPath] = IECdebug_data
  1341             self.IECdebug_datas[IECPath] = IECdebug_data
  1327         
  1342         
  1328         IECdebug_data[0][callableobj]=(args, kwargs)
  1343         IECdebug_data[0][callableobj]=(args, kwargs)
  1329 
  1344 
  1330         self.IECdebug_lock.release()
  1345         self.IECdebug_lock.release()
  1331 
  1346         
  1332         if self.DebugTimer is not None:
  1347         self.ReArmDebugRegisterTimer()
  1333             self.DebugTimer.cancel()
  1348         
  1334 
       
  1335         # Timer to prevent rapid-fire when registering many variables
       
  1336         # use wx.CallAfter use keep using same thread. TODO : use wx.Timer instead
       
  1337         self.DebugTimer=Timer(0.5,wx.CallAfter,args = [self.RegisterDebugVarToConnector])
       
  1338         # Rearm anti-rapid-fire timer
       
  1339         self.DebugTimer.start()
       
  1340 
       
  1341         return IECdebug_data[1]
  1349         return IECdebug_data[1]
  1342 
  1350 
  1343     def UnsubscribeDebugIECVariable(self, IECPath, callableobj):
  1351     def UnsubscribeDebugIECVariable(self, IECPath, callableobj):
       
  1352         #print "Unsubscribe", IECPath, callableobj
       
  1353         self.IECdebug_lock.acquire()
  1344         IECdebug_data = self.IECdebug_datas.get(IECPath, None)
  1354         IECdebug_data = self.IECdebug_datas.get(IECPath, None)
  1345         if IECdebug_data is None:
  1355         if IECdebug_data is not None:
  1346             IECdebug_data[0].pop(callableobj,None)
  1356             IECdebug_data[0].pop(callableobj,None)
       
  1357         self.IECdebug_lock.release()
       
  1358 
       
  1359         self.ReArmDebugRegisterTimer()
  1347 
  1360 
  1348     def DebugCallerFunc(self, weakcallable, value, *args, **kwargs):
  1361     def DebugCallerFunc(self, weakcallable, value, *args, **kwargs):
  1349         # do the call
  1362         # do the call
  1350         weakcallable.SetValue(value, *args, **kwargs)
  1363         weakcallable.SetValue(value, *args, **kwargs)
  1351         # will unlock debug thread
  1364         # will unlock debug thread
  1358         # This lock is used to avoid flooding wx event stack calling callafter
  1371         # This lock is used to avoid flooding wx event stack calling callafter
  1359         self.DebugThreadSlowDownLock = Semaphore(0)
  1372         self.DebugThreadSlowDownLock = Semaphore(0)
  1360         while self._connector is not None:
  1373         while self._connector is not None:
  1361             debug_tick, debug_vars = self._connector.GetTraceVariables()
  1374             debug_tick, debug_vars = self._connector.GetTraceVariables()
  1362             #print debug_tick, debug_vars
  1375             #print debug_tick, debug_vars
       
  1376             self.IECdebug_lock.acquire()
  1363             if debug_vars is not None and \
  1377             if debug_vars is not None and \
  1364                len(debug_vars) == len(self.TracedIECPath):
  1378                len(debug_vars) == len(self.TracedIECPath):
  1365                 for IECPath,value in zip(self.TracedIECPath, debug_vars):
  1379                 for IECPath,value in zip(self.TracedIECPath, debug_vars):
  1366                     data_tuple = self.IECdebug_datas.get(IECPath, None)
  1380                     data_tuple = self.IECdebug_datas.get(IECPath, None)
  1367                     if data_tuple is not None:
  1381                     if data_tuple is not None:
  1373                             # This will block thread if more than one call is waiting
  1387                             # This will block thread if more than one call is waiting
  1374                             self.DebugThreadSlowDownLock.acquire()
  1388                             self.DebugThreadSlowDownLock.acquire()
  1375             elif debug_vars is not None:
  1389             elif debug_vars is not None:
  1376                 wx.CallAfter(self.logger.write_warning, 
  1390                 wx.CallAfter(self.logger.write_warning, 
  1377                              "debug data not coherent %d != %d"%(len(debug_vars), len(self.TracedIECPath)))
  1391                              "debug data not coherent %d != %d"%(len(debug_vars), len(self.TracedIECPath)))
  1378             #elif debug_tick == -1:
  1392             elif debug_tick == -1:
  1379                 #wx.CallAfter(self.logger.write, "Debugger unavailable\n")
  1393                 #wx.CallAfter(self.logger.write, "Debugger unavailable\n")
  1380             #    pass
  1394                 pass
  1381             else:
  1395             else:
  1382                 wx.CallAfter(self.logger.write, "Debugger disabled\n")
  1396                 wx.CallAfter(self.logger.write, "Debugger disabled\n")
  1383                 break
  1397                 break
       
  1398             self.IECdebug_lock.release()
  1384 
  1399 
  1385     def _Debug(self):
  1400     def _Debug(self):
  1386         """
  1401         """
  1387         Start PLC (Debug Mode)
  1402         Start PLC (Debug Mode)
  1388         """
  1403         """
  1389         if self.GetIECProgramsAndVariables() and \
  1404         if self.GetIECProgramsAndVariables() and \
  1390            self._connector.StartPLC(debug=True):
  1405            self._connector.StartPLC(debug=True):
  1391             self.logger.write("Starting PLC (debug mode)\n")
  1406             self.logger.write("Starting PLC (debug mode)\n")
  1392             self.TracedIECPath = []
  1407             self.TracedIECPath = []
  1393             # TODO : laucnch PLCOpenEditor in Debug Mode
  1408             if self.PLCDebug is None:
       
  1409                 self.RefreshPluginsBlockLists()
       
  1410                 def _onclose():
       
  1411                     self.PLCDebug = None
       
  1412                 self.PLCDebug = PLCOpenEditor(self.AppFrame, self, debug=True)
       
  1413                 self.PLCDebug._onclose = _onclose
       
  1414                 self.PLCDebug.Show()
  1394             self.DebugThread = Thread(target=self.DebugThreadProc)
  1415             self.DebugThread = Thread(target=self.DebugThreadProc)
  1395             self.DebugThread.start()
  1416             self.DebugThread.start()
  1396         else:
  1417         else:
  1397             self.logger.write_error("Couldn't start PLC debug !\n")
  1418             self.logger.write_error("Couldn't start PLC debug !\n")
  1398         self.UpdateMethodsFromPLCStatus()
  1419         self.UpdateMethodsFromPLCStatus()