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