plugger.py
changeset 355 e257fe074a90
parent 351 89eca146bee0
child 356 e9698d0ee5f3
equal deleted inserted replaced
354:ff721067a75c 355:e257fe074a90
  1426                "Broken": [("_Run", True),
  1426                "Broken": [("_Run", True),
  1427                           ("_Debug", True),
  1427                           ("_Debug", True),
  1428                           ("_Stop", False)],
  1428                           ("_Stop", False)],
  1429                "Disconnected":  [("_Run", False),
  1429                "Disconnected":  [("_Run", False),
  1430                                  ("_Debug", False),
  1430                                  ("_Debug", False),
  1431                                  ("_Stop", False)],
  1431                                  ("_Stop", False),
       
  1432                                  ("_Transfer", False),
       
  1433                                  ("_Connect", True),
       
  1434                                  ("_Disconnect", False)],
  1432                }.get(status,[]):
  1435                }.get(status,[]):
  1433             self.ShowMethod(*args)
  1436             self.ShowMethod(*args)
  1434         return status
  1437         return status
  1435     
  1438     
  1436     def PullPLCStatusProc(self, event): 
  1439     def PullPLCStatusProc(self, event): 
       
  1440         if self._connector is None:
       
  1441             self.StatusTimer.Stop()
  1437         current_status = self.UpdateMethodsFromPLCStatus()
  1442         current_status = self.UpdateMethodsFromPLCStatus()
  1438         if current_status != self.previous_plcstate:
  1443         if current_status != self.previous_plcstate:
  1439             self.previous_plcstate = current_status
  1444             self.previous_plcstate = current_status
  1440             self.StatusPrint.get(current_status, self.logger.write)("PLC is %s\n"%current_status)
  1445             self.StatusPrint.get(current_status, self.logger.write)("PLC is %s\n"%current_status)
  1441             self.AppFrame.RefreshAll()
  1446             self.AppFrame.RefreshAll()
  1442             
  1447         
  1443     def _Run(self):
  1448     def _Run(self):
  1444         """
  1449         """
  1445         Start PLC
  1450         Start PLC
  1446         """
  1451         """
  1447         self._connector.StartPLC()
  1452         self._connector.StartPLC()
  1459                 if len(WeakCallableDict) == 0:
  1464                 if len(WeakCallableDict) == 0:
  1460                     # Callable Dict is empty.
  1465                     # Callable Dict is empty.
  1461                     # This variable is not needed anymore!
  1466                     # This variable is not needed anymore!
  1462                     #print "Unused : " + IECPath
  1467                     #print "Unused : " + IECPath
  1463                     IECPathsToPop.append(IECPath)
  1468                     IECPathsToPop.append(IECPath)
  1464                 else:
  1469                 elif IECPath != "__tick__":
  1465                     # Convert 
  1470                     # Convert 
  1466                     Idx = self._IECPathToIdx.get(IECPath,None)
  1471                     Idx = self._IECPathToIdx.get(IECPath,None)
  1467                     if Idx is not None:
  1472                     if Idx is not None:
  1468                         Idxs.append(Idx)
  1473                         Idxs.append(Idx)
  1469                         self.TracedIECPath.append(IECPath)
  1474                         self.TracedIECPath.append(IECPath)
  1493         """
  1498         """
  1494         Dispatching use a dictionnary linking IEC variable paths
  1499         Dispatching use a dictionnary linking IEC variable paths
  1495         to a WeakKeyDictionary linking 
  1500         to a WeakKeyDictionary linking 
  1496         weakly referenced callables to optionnal args
  1501         weakly referenced callables to optionnal args
  1497         """
  1502         """
  1498         if self._IECPathToIdx.get(IECPath, None) is None:
  1503         if IECPath != "__tick__" and self._IECPathToIdx.get(IECPath, None) is None:
  1499             return None
  1504             return None
  1500         
  1505         
  1501         self.IECdebug_lock.acquire()
  1506         self.IECdebug_lock.acquire()
  1502         # If no entry exist, create a new one with a fresh WeakKeyDictionary
  1507         # If no entry exist, create a new one with a fresh WeakKeyDictionary
  1503         IECdebug_data = self.IECdebug_datas.get(IECPath, None)
  1508         IECdebug_data = self.IECdebug_datas.get(IECPath, None)
  1529     def UnsubscribeAllDebugIECVariable(self):
  1534     def UnsubscribeAllDebugIECVariable(self):
  1530         self.IECdebug_lock.acquire()
  1535         self.IECdebug_lock.acquire()
  1531         IECdebug_data = {}
  1536         IECdebug_data = {}
  1532         self.IECdebug_lock.release()
  1537         self.IECdebug_lock.release()
  1533 
  1538 
  1534         self.ReArmDebugRegisterTimer()        
  1539         self.ReArmDebugRegisterTimer()
       
  1540 
       
  1541     def CallWeakcallables(self, IECPath, function_name, *cargs):
       
  1542         data_tuple = self.IECdebug_datas.get(IECPath, None)
       
  1543         if data_tuple is not None:
       
  1544             WeakCallableDict, data_log, status = data_tuple
       
  1545             #data_log.append((debug_tick, value))
       
  1546             for weakcallable,(args,kwargs) in WeakCallableDict.iteritems():
       
  1547                 #print weakcallable, value, args, kwargs
       
  1548                 function = getattr(weakcallable, function_name, None)
       
  1549                 if function is not None:
       
  1550                     function(*(cargs + args), **kwargs)
       
  1551                 # This will block thread if more than one call is waiting
  1535 
  1552 
  1536     def DebugThreadProc(self):
  1553     def DebugThreadProc(self):
  1537         """
  1554         """
  1538         This thread waid PLC debug data, and dispatch them to subscribers
  1555         This thread waid PLC debug data, and dispatch them to subscribers
  1539         """
  1556         """
  1540         # This lock is used to avoid flooding wx event stack calling callafter
  1557         # This lock is used to avoid flooding wx event stack calling callafter
  1541         self.DebugThreadSlowDownLock = Semaphore(0)
       
  1542         self.debug_break = False
  1558         self.debug_break = False
  1543         while (not self.debug_break) and (self._connector is not None):
  1559         while (not self.debug_break) and (self._connector is not None):
  1544             debug_tick, debug_vars = self._connector.GetTraceVariables()
  1560             debug_tick, debug_vars = self._connector.GetTraceVariables()
  1545             #print debug_tick, debug_vars
  1561             #print debug_tick, debug_vars
  1546             self.IECdebug_lock.acquire()
  1562             self.IECdebug_lock.acquire()
  1547             if debug_vars is not None and \
  1563             if debug_vars is not None and \
  1548                len(debug_vars) == len(self.TracedIECPath):
  1564                len(debug_vars) == len(self.TracedIECPath):
  1549                 for IECPath,value in zip(self.TracedIECPath, debug_vars):
  1565                 for IECPath,value in zip(self.TracedIECPath, debug_vars):
  1550                     if value is not None:
  1566                     if value is not None:
  1551 	                    data_tuple = self.IECdebug_datas.get(IECPath, None)
  1567                         self.CallWeakcallables(IECPath, "NewValue", debug_tick, value)
  1552 	                    if data_tuple is not None:
  1568                 self.CallWeakcallables("__tick__", "NewDataAvailable")
  1553 	                        WeakCallableDict, data_log, status = data_tuple
       
  1554 	                        #data_log.append((debug_tick, value))
       
  1555 	                        for weakcallable,(args,kwargs) in WeakCallableDict.iteritems():
       
  1556 	                            # delegate call to wx event loop
       
  1557 	                            #print weakcallable, value, args, kwargs
       
  1558 	                            if getattr(weakcallable, "SetValue", None) is not None:
       
  1559 	                                wx.CallAfter(weakcallable.SetValue, value, *args, **kwargs)
       
  1560 	                            elif getattr(weakcallable, "AddPoint", None) is not None:
       
  1561 	                                wx.CallAfter(weakcallable.AddPoint, debug_tick, value, *args, **kwargs)
       
  1562 	                            # This will block thread if more than one call is waiting
       
  1563             elif debug_vars is not None:
  1569             elif debug_vars is not None:
  1564                 wx.CallAfter(self.logger.write_warning, 
  1570                 wx.CallAfter(self.logger.write_warning, 
  1565                              "Debug data not coherent %d != %d\n"%(len(debug_vars), len(self.TracedIECPath)))
  1571                              "Debug data not coherent %d != %d\n"%(len(debug_vars), len(self.TracedIECPath)))
  1566             elif debug_tick == -1:
  1572             elif debug_tick == -1:
  1567                 #wx.CallAfter(self.logger.write, "Debugger unavailable\n")
  1573                 #wx.CallAfter(self.logger.write, "Debugger unavailable\n")
  1568                 pass
  1574                 pass
  1569             else:
  1575             else:
  1570                 wx.CallAfter(self.logger.write, "Debugger disabled\n")
  1576                 wx.CallAfter(self.logger.write, "Debugger disabled\n")
  1571                 self.debug_break = True
  1577                 self.debug_break = True
  1572             self.IECdebug_lock.release()
  1578             self.IECdebug_lock.release()
  1573             wx.CallAfter(self.DebugThreadSlowDownLock.release)
       
  1574             self.DebugThreadSlowDownLock.acquire()
       
  1575 
  1579 
  1576     def KillDebugThread(self):
  1580     def KillDebugThread(self):
  1577         self.debug_break = True
  1581         self.debug_break = True
  1578         self.DebugThreadSlowDownLock.release()
       
  1579         self.DebugThread.join(timeout=1)
  1582         self.DebugThread.join(timeout=1)
  1580         if self.DebugThread.isAlive():
  1583         if self.DebugThread.isAlive():
  1581             self.logger.write_warning("Debug Thread couldn't be killed")
  1584             self.logger.write_warning("Debug Thread couldn't be killed")
  1582         self.DebugThread = None
  1585         self.DebugThread = None
  1583 
  1586 
  1706             self.EnableMethod("_Transfer", False)
  1709             self.EnableMethod("_Transfer", False)
  1707 
  1710 
  1708 
  1711 
  1709     def _Disconnect(self):
  1712     def _Disconnect(self):
  1710         self._connector = None
  1713         self._connector = None
  1711         self.ShowMethod("_Transfer", False)
       
  1712         self.ShowMethod("_Connect", True)
       
  1713         self.ShowMethod("_Disconnect", False)
       
  1714         self.StatusTimer.Stop()
  1714         self.StatusTimer.Stop()
  1715         self.UpdateMethodsFromPLCStatus()
  1715         self.UpdateMethodsFromPLCStatus()
  1716         
  1716         
  1717     def _Transfer(self):
  1717     def _Transfer(self):
  1718         # Get the last build PLC's 
  1718         # Get the last build PLC's