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() |
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 |