--- a/editors/DebugViewer.py Mon Aug 21 20:17:19 2017 +0000
+++ b/editors/DebugViewer.py Mon Aug 21 23:22:58 2017 +0300
@@ -27,20 +27,20 @@
import wx
-REFRESH_PERIOD = 0.1 # Minimum time between 2 refresh
-DEBUG_REFRESH_LOCK = Lock() # Common refresh lock for all debug viewers
-
-#-------------------------------------------------------------------------------
+REFRESH_PERIOD = 0.1 # Minimum time between 2 refresh
+DEBUG_REFRESH_LOCK = Lock() # Common refresh lock for all debug viewers
+
+# -------------------------------------------------------------------------------
# Debug Viewer Class
-#-------------------------------------------------------------------------------
-
-"""
-Class that implements common behavior of every viewers able to display debug
-values
-"""
+# -------------------------------------------------------------------------------
+
class DebugViewer:
-
+ """
+ Class that implements common behavior of every viewers able to display debug
+ values
+ """
+
def __init__(self, producer, debug, subscribe_tick=True):
"""
Constructor
@@ -52,49 +52,49 @@
"""
self.Debug = debug
self.SubscribeTick = subscribe_tick
-
+
# Flag indicating that consumer value update inhibited
# (DebugViewer is refreshing)
self.Inhibited = False
-
+
# List of data consumers subscribed to DataProducer
self.DataConsumers = {}
-
+
# Time stamp indicating when last refresh have been initiated
self.LastRefreshTime = gettime()
# Flag indicating that DebugViewer has acquire common debug lock
self.HasAcquiredLock = False
# Lock for access to the two preceding variable
self.AccessLock = Lock()
-
+
# Timer to refresh Debug Viewer one last time in the case that a new
# value have been received during refresh was inhibited and no one
# after refresh was activated
self.LastRefreshTimer = None
# Lock for access to the timer
self.TimerAccessLock = Lock()
-
+
# Set DataProducer and subscribe tick if needed
self.SetDataProducer(producer)
-
+
def __del__(self):
"""
Destructor
"""
# Unsubscribe all data consumers
self.UnsubscribeAllDataConsumers()
-
+
# Delete reference to DataProducer
self.DataProducer = None
-
+
# Stop last refresh timer
if self.LastRefreshTimer is not None:
self.LastRefreshTimer.cancel()
-
+
# Release Common debug lock if DebugViewer has acquired it
if self.HasAcquiredLock:
DEBUG_REFRESH_LOCK.release()
-
+
def SetDataProducer(self, producer):
"""
Set Data Producer
@@ -103,25 +103,25 @@
# In the case that tick need to be subscribed and DebugViewer is
# debugging
if self.SubscribeTick and self.Debug:
-
+
# Subscribe tick to new data producer
if producer is not None:
producer.SubscribeDebugIECVariable("__tick__", self, True)
-
+
# Unsubscribe tick from old data producer
if getattr(self, "DataProducer", None) is not None:
self.DataProducer.UnsubscribeDebugIECVariable("__tick__", self)
-
+
# Save new data producer
self.DataProducer = producer
-
+
def IsDebugging(self):
"""
Get flag indicating if Debug Viewer is debugging
@return: Debugging flag
"""
return self.Debug
-
+
def Inhibit(self, inhibit):
"""
Set consumer value update inhibit flag
@@ -130,10 +130,10 @@
# Inhibit every data consumers in list
for consumer, iec_path in self.DataConsumers.iteritems():
consumer.Inhibit(inhibit)
-
+
# Save inhibit flag
self.Inhibited = inhibit
-
+
def AddDataConsumer(self, iec_path, consumer, buffer_list=False):
"""
Subscribe data consumer to DataProducer
@@ -145,19 +145,19 @@
# Return immediately if no DataProducer defined
if self.DataProducer is None:
return None
-
+
# Subscribe data consumer to DataProducer
result = self.DataProducer.SubscribeDebugIECVariable(
iec_path, consumer, buffer_list)
if result is not None and consumer != self:
-
+
# Store data consumer if successfully subscribed and inform
# consumer of variable data type
self.DataConsumers[consumer] = iec_path
consumer.SetDataType(self.GetDataType(iec_path))
-
+
return result
-
+
def RemoveDataConsumer(self, consumer):
"""
Unsubscribe data consumer from DataProducer
@@ -165,12 +165,12 @@
"""
# Remove consumer from data consumer list
iec_path = self.DataConsumers.pop(consumer, None)
-
+
# Unsubscribe consumer from DataProducer
if iec_path is not None:
self.DataProducer.UnsubscribeDebugIECVariable(
iec_path, consumer)
-
+
def SubscribeAllDataConsumers(self):
"""
Called to Subscribe all data consumers contained in DebugViewer.
@@ -179,24 +179,24 @@
# Subscribe tick if needed
if self.SubscribeTick and self.Debug and self.DataProducer is not None:
self.DataProducer.SubscribeDebugIECVariable("__tick__", self, True)
-
+
def UnsubscribeAllDataConsumers(self, tick=True):
"""
Called to Unsubscribe all data consumers.
"""
if self.DataProducer is not None:
-
+
# Unscribe tick if needed
if self.SubscribeTick and tick and self.Debug:
self.DataProducer.UnsubscribeDebugIECVariable("__tick__", self)
-
+
# Unsubscribe all data consumers in list
for consumer, iec_path in self.DataConsumers.iteritems():
self.DataProducer.UnsubscribeDebugIECVariable(
iec_path, consumer)
-
+
self.DataConsumers = {}
-
+
def GetDataType(self, iec_path):
"""
Return variable data type.
@@ -204,20 +204,20 @@
@return: variable data type (None if not found)
"""
if self.DataProducer is not None:
-
+
# Search for variable informations in project compilation files
data_type = self.DataProducer.GetDebugIECVariableType(
iec_path.upper())
if data_type is not None:
return data_type
-
+
# Search for variable informations in project data
infos = self.DataProducer.GetInstanceInfos(iec_path)
if infos is not None:
return infos.type
-
+
return None
-
+
def IsNumType(self, data_type):
"""
Indicate if data type given is a numeric data type
@@ -226,9 +226,9 @@
"""
if self.DataProducer is not None:
return self.DataProducer.IsNumType(data_type)
-
+
return False
-
+
def ForceDataValue(self, iec_path, value):
"""
Force PLC variable value
@@ -237,7 +237,7 @@
"""
if self.DataProducer is not None:
self.DataProducer.ForceDebugIECVariable(iec_path, value)
-
+
def ReleaseDataValue(self, iec_path):
"""
Release PLC variable value
@@ -245,40 +245,40 @@
"""
if self.DataProducer is not None:
self.DataProducer.ReleaseDebugIECVariable(iec_path)
-
+
def NewDataAvailable(self, ticks):
"""
Called by DataProducer for each tick captured
@param tick: PLC tick captured
- All other parameters are passed to refresh function
+ All other parameters are passed to refresh function
"""
# Stop last refresh timer
self.TimerAccessLock.acquire()
if self.LastRefreshTimer is not None:
self.LastRefreshTimer.cancel()
- self.LastRefreshTimer=None
+ self.LastRefreshTimer = None
self.TimerAccessLock.release()
-
+
# Only try to refresh DebugViewer if it is visible on screen and not
# already refreshing
if self.IsShown() and not self.Inhibited:
-
+
# Try to get acquire common refresh lock if minimum period between
# two refresh has expired
if gettime() - self.LastRefreshTime > REFRESH_PERIOD and \
DEBUG_REFRESH_LOCK.acquire(False):
self.StartRefreshing()
-
+
# If common lock wasn't acquired for any reason, restart last
# refresh timer
else:
self.StartLastRefreshTimer()
-
+
# In the case that DebugViewer isn't visible on screen and has already
# acquired common refresh lock, reset DebugViewer
elif not self.IsShown() and self.HasAcquiredLock:
DebugViewer.RefreshNewData(self)
-
+
def ShouldRefresh(self):
"""
Callback function called when last refresh timer expired
@@ -286,15 +286,15 @@
"""
# Cancel if DebugViewer is not visible on screen
if self and self.IsShown():
-
+
# Try to acquire common refresh lock
if DEBUG_REFRESH_LOCK.acquire(False):
self.StartRefreshing()
-
+
# Restart last refresh timer if common refresh lock acquired failed
else:
self.StartLastRefreshTimer()
-
+
def StartRefreshing(self):
"""
Called to initiate a refresh of DebugViewer
@@ -306,13 +306,13 @@
self.HasAcquiredLock = True
self.LastRefreshTime = gettime()
self.AccessLock.release()
-
+
# Inhibit data consumer value update
self.Inhibit(True)
-
+
# Initiate DebugViewer refresh
wx.CallAfter(self.RefreshNewData)
-
+
def StartLastRefreshTimer(self):
"""
Called to start last refresh timer for the minimum time between 2
@@ -324,19 +324,19 @@
REFRESH_PERIOD, self.ShouldRefresh)
self.LastRefreshTimer.start()
self.TimerAccessLock.release()
-
+
def RefreshNewData(self):
"""
Called to refresh DebugViewer according to values received by data
consumers
May be overridden by inherited classes
Can receive any parameters depending on what is needed by inherited
- class
+ class
"""
if self:
# Activate data consumer value update
self.Inhibit(False)
-
+
# Release common refresh lock if acquired and update
# last refresh time
self.AccessLock.acquire()