I have a script that exists in my project library that I use to log tag values to a database. I've tried to incorporate features similar to IA's Tag Historian.
One of these features is the min sample rate and dead band.
To implement these, of course we would need to compare that current time and tag value to the last entry for the tag.
Right now I'm doing this by querying the database to get the last row for the tag and comparing the now time and current value of the tag to the t_stamp and val columns, respectively, to determine if a new row should be added.
It just occurred to me that instead of checking against the database I could use a lastTime
and lastVal
custom property on the tag to record these values so I'm not querying the database every time I need to determine if the tag change should be logged. I would basically be trading a system.db.runNamedQuery()
call each time the tag value changes for a system.tag.writeAsync()
call each time the value has changed enough to log the change.
So, something like this
def logTagChange(tag, currentValue, initialChange):
#logging enabled and not initial change
if (tag.LogEN and not initialChange):
#trim the OPC path to get the tag name
PlcTag = tag.OpcItemPath.replace('ns=1;s=['+tag.Device+']','')
#get the value of the last entry for this tag
lastDBvalue = system.db.runNamedQuery('Project','Last_Tag_Value',{ 'tag_name' : PlcTag })
numRows = lastDBvalue.rowCount()
#at least one row was retrieved
if numRows > 0:
#access the most recent time and value
lastVal = lastDBvalue.getValueAt(0, 'val')
lastTime = lastDBvalue.getValueAt(0, 't_stamp')
#calculate the time between now and the last row
deltaT = system.date.secondsBetween(lastTime, system.date.now())
#no rows in database yet, or large enough change in tag value, or min. sample rate has elapsed
if (not numRows > 0) or ( abs(currentValue.value - lastVal) >= tag.LogDB ) or ( tag.LogSR > 0 and deltaT >= tag.LogSR ):
#log row in the database
system.db.runNamedQuery('Project', 'Store_Tag_Change', {'tag_name' : PlcTag, 'val' : currentValue.value)
would change to something like this:
def logTagChange(tag, tagPath, currentValue, initialChange):
#logging enabled and not initial change
if (tag.LogEN and not initialChange):
#trim the OPC path to get the tag name
PlcTag = tag.OpcItemPath.replace('ns=1;s=['+tag.Device+']','')
#access the most recent time and value
lastVal = tag.lastVal
lastTime = tag.lastTime
now = system.date.now()
deltaT = system.date.secondsBetween(lastTime, now)
#no rows in database yet, or large enough change in tag value, or min. sample rate has elapsed
if ( abs(currentValue.value - lastVal) >= tag.LogDB ) or lastTime == 0 or ( tag.LogSR > 0 and deltaT >= tag.LogSR ):
#log row in the database
system.db.runNamedQuery('Project', 'Store_Tag_Change', {'tag_name' : PlcTag, 'val' : currentValue.value)
#update tag values
system.tag.writeAsync([tagPath+'.lastVal',tagPath+'.lastTime'],[currentValue.value, now])
Thoughts on how the performance might compare?