251 self.SetAppFrame(frame, logger) |
251 self.SetAppFrame(frame, logger) |
252 |
252 |
253 # Setup debug information |
253 # Setup debug information |
254 self.IECdebug_datas = {} |
254 self.IECdebug_datas = {} |
255 |
255 |
256 self.DebugTimer = None |
256 self.DebugUpdatePending = False |
257 self.ResetIECProgramsAndVariables() |
257 self.ResetIECProgramsAndVariables() |
258 |
258 |
259 # In both new or load scenario, no need to save |
259 # In both new or load scenario, no need to save |
260 self.ChangesToSave = False |
260 self.ChangesToSave = False |
261 # root have no parent |
261 # root have no parent |
1534 ticks, self.DebugTicks = self.DebugTicks, [] |
1532 ticks, self.DebugTicks = self.DebugTicks, [] |
1535 |
1533 |
1536 return debug_status, ticks, buffers |
1534 return debug_status, ticks, buffers |
1537 |
1535 |
1538 def RegisterDebugVarToConnector(self): |
1536 def RegisterDebugVarToConnector(self): |
1539 self.DebugTimer = None |
|
1540 Idxs = [] |
1537 Idxs = [] |
1541 self.TracedIECPath = [] |
1538 self.TracedIECPath = [] |
1542 self.TracedIECTypes = [] |
1539 self.TracedIECTypes = [] |
1543 if self._connector is not None and self.debug_status != PlcStatus.Broken: |
1540 if self._connector is not None and self.debug_status != PlcStatus.Broken: |
1544 IECPathsToPop = [] |
1541 IECPathsToPop = [] |
1573 else: |
1570 else: |
1574 self.TracedIECPath = [] |
1571 self.TracedIECPath = [] |
1575 self._connector.SetTraceVariablesList([]) |
1572 self._connector.SetTraceVariablesList([]) |
1576 self.DebugToken = None |
1573 self.DebugToken = None |
1577 self.debug_status, _debug_ticks, _buffers = self.SnapshotAndResetDebugValuesBuffers() |
1574 self.debug_status, _debug_ticks, _buffers = self.SnapshotAndResetDebugValuesBuffers() |
|
1575 self.DebugUpdatePending = False |
1578 |
1576 |
1579 def IsPLCStarted(self): |
1577 def IsPLCStarted(self): |
1580 return self.previous_plcstate == PlcStatus.Started |
1578 return self.previous_plcstate == PlcStatus.Started |
1581 |
1579 |
1582 def ReArmDebugRegisterTimer(self): |
1580 def AppendDebugUpdate(self): |
1583 if self.DebugTimer is not None: |
1581 if not self.DebugUpdatePending : |
1584 self.DebugTimer.cancel() |
1582 wx.CallAfter(self.RegisterDebugVarToConnector) |
1585 |
1583 self.DebugUpdatePending = True |
1586 # Prevent to call RegisterDebugVarToConnector when PLC is not started |
|
1587 # If an output location var is forced it's leads to segmentation fault in runtime |
|
1588 # Links between PLC located variables and real variables are not ready |
|
1589 if self.IsPLCStarted(): |
|
1590 # Timer to prevent rapid-fire when registering many variables |
|
1591 # use wx.CallAfter use keep using same thread. TODO : use wx.Timer |
|
1592 # instead |
|
1593 self.DebugTimer = Timer( |
|
1594 0.5, wx.CallAfter, args=[self.RegisterDebugVarToConnector]) |
|
1595 # Rearm anti-rapid-fire timer |
|
1596 self.DebugTimer.start() |
|
1597 |
1584 |
1598 def GetDebugIECVariableType(self, IECPath): |
1585 def GetDebugIECVariableType(self, IECPath): |
1599 _Idx, IEC_Type = self._IECPathToIdx.get(IECPath, (None, None)) |
1586 _Idx, IEC_Type = self._IECPathToIdx.get(IECPath, (None, None)) |
1600 return IEC_Type |
1587 return IEC_Type |
1601 |
1588 |
1621 else: |
1608 else: |
1622 IECdebug_data[4] |= buffer_list |
1609 IECdebug_data[4] |= buffer_list |
1623 |
1610 |
1624 IECdebug_data[0][callableobj] = buffer_list |
1611 IECdebug_data[0][callableobj] = buffer_list |
1625 |
1612 |
1626 self.ReArmDebugRegisterTimer() |
1613 self.AppendDebugUpdate() |
1627 |
1614 |
1628 return IECdebug_data[1] |
1615 return IECdebug_data[1] |
1629 |
1616 |
1630 def UnsubscribeDebugIECVariable(self, IECPath, callableobj): |
1617 def UnsubscribeDebugIECVariable(self, IECPath, callableobj): |
1631 IECdebug_data = self.IECdebug_datas.get(IECPath, None) |
1618 IECdebug_data = self.IECdebug_datas.get(IECPath, None) |
1637 IECdebug_data[4] = reduce( |
1624 IECdebug_data[4] = reduce( |
1638 lambda x, y: x | y, |
1625 lambda x, y: x | y, |
1639 IECdebug_data[0].itervalues(), |
1626 IECdebug_data[0].itervalues(), |
1640 False) |
1627 False) |
1641 |
1628 |
1642 self.ReArmDebugRegisterTimer() |
1629 self.AppendDebugUpdate() |
1643 |
1630 |
1644 def UnsubscribeAllDebugIECVariable(self): |
1631 def UnsubscribeAllDebugIECVariable(self): |
1645 self.IECdebug_datas = {} |
1632 self.IECdebug_datas = {} |
1646 |
1633 |
1647 self.ReArmDebugRegisterTimer() |
1634 self.AppendDebugUpdate() |
1648 |
1635 |
1649 def ForceDebugIECVariable(self, IECPath, fvalue): |
1636 def ForceDebugIECVariable(self, IECPath, fvalue): |
1650 if IECPath not in self.IECdebug_datas: |
1637 if IECPath not in self.IECdebug_datas: |
1651 return |
1638 return |
1652 |
1639 |
1653 # If no entry exist, create a new one with a fresh WeakKeyDictionary |
1640 # If no entry exist, create a new one with a fresh WeakKeyDictionary |
1654 IECdebug_data = self.IECdebug_datas.get(IECPath, None) |
1641 IECdebug_data = self.IECdebug_datas.get(IECPath, None) |
1655 IECdebug_data[2] = "Forced" |
1642 IECdebug_data[2] = "Forced" |
1656 IECdebug_data[3] = fvalue |
1643 IECdebug_data[3] = fvalue |
1657 |
1644 |
1658 self.ReArmDebugRegisterTimer() |
1645 self.AppendDebugUpdate() |
1659 |
1646 |
1660 def ReleaseDebugIECVariable(self, IECPath): |
1647 def ReleaseDebugIECVariable(self, IECPath): |
1661 if IECPath not in self.IECdebug_datas: |
1648 if IECPath not in self.IECdebug_datas: |
1662 return |
1649 return |
1663 |
1650 |
1664 # If no entry exist, create a new one with a fresh WeakKeyDictionary |
1651 # If no entry exist, create a new one with a fresh WeakKeyDictionary |
1665 IECdebug_data = self.IECdebug_datas.get(IECPath, None) |
1652 IECdebug_data = self.IECdebug_datas.get(IECPath, None) |
1666 IECdebug_data[2] = "Registered" |
1653 IECdebug_data[2] = "Registered" |
1667 IECdebug_data[3] = None |
1654 IECdebug_data[3] = None |
1668 |
1655 |
1669 self.ReArmDebugRegisterTimer() |
1656 self.AppendDebugUpdate() |
1670 |
1657 |
1671 def CallWeakcallables(self, IECPath, function_name, *cargs): |
1658 def CallWeakcallables(self, IECPath, function_name, *cargs): |
1672 data_tuple = self.IECdebug_datas.get(IECPath, None) |
1659 data_tuple = self.IECdebug_datas.get(IECPath, None) |
1673 if data_tuple is not None: |
1660 if data_tuple is not None: |
1674 WeakCallableDict, _data_log, _status, _fvalue, buffer_list = data_tuple |
1661 WeakCallableDict, _data_log, _status, _fvalue, buffer_list = data_tuple |