I got a problem when this function take 100 tags as a list with 2500 ms time out setting.
Everytime I read some rows in the PLC. Each row gets 5 tags, the last tag is an incremental log Id.
A trigger tag was used to log those row into mysql database by tag change event.
However after a few successfull log, some rows with all 0 value will ocurr in database.
The log Id indicated those values was read as 0 in the tag change script.
So does anyone get the same problem?
I added a log to calculate the time cost, the whole script took 120~140 ms in total, so the timeout shall not be a problem
My script as bellowing, PLC was rockwell control logix.
def valueChanged(tag, tagPath, previousValue, currentValue, initialChange, missedEvents):
if not initialChange:
logstart = system.date.now()
logger = system.util.getLogger("Heartbeat event trigger")
oktoreadpath = '[default]_tmp/_HeartBeat_event_monitoring/ReadAreaOk2Read'
ReadLengthpath = '[default]_tmp/_HeartBeat_event_monitoring/ReadLength'
dbresultpath = '[default]_tmp/_HeartBeat_event_monitoring/DBResult'
paths = [oktoreadpath,ReadLengthpath]
[oktosend , readlength] = system.tag.readBlocking(paths)
readlength = readlength.value
if oktosend.value == 1 and readlength >0:
eventpaths =[]
for x in range(readlength):
equipID = '[default]_tmp/_HeartBeat_event_monitoring/_HeartBeat_event_read/_DPP_Read_HBEvent_'+str(x)+'_/Integer00'
valueC = '[default]_tmp/_HeartBeat_event_monitoring/_HeartBeat_event_read/_DPP_Read_HBEvent_'+str(x)+'_/Integer01'
valueP = '[default]_tmp/_HeartBeat_event_monitoring/_HeartBeat_event_read/_DPP_Read_HBEvent_'+str(x)+'_/Integer02'
logId = '[default]_tmp/_HeartBeat_event_monitoring/_HeartBeat_event_read/_DPP_Read_HBEvent_'+str(x)+'_/Integer03'
tsC = '[default]_tmp/_HeartBeat_event_monitoring/_HeartBeat_event_read/_DPP_Read_HBEvent_'+str(x)+'_/TimeInBuffer'
eventpaths.extend([equipID,valueC,valueP,logId,tsC])
taglist = system.tag.readBlocking(eventpaths)
querystring = "insert into heartbeat_event (equipid,heartbeatc,heartbeatp,tsc,createdate,logid) values "
valuestring = ""
eventlist =[]
y = 0
for tag in taglist:
if y%5==0:
equipid = tag.value
elif y%5==1:
valuec = tag.value
elif y%5==2:
valuep = tag.value
elif y%5==3:
logid = tag.value
else:
tsc = system.date.addMillis(currentValue.timestamp,tag.value*(-1))
valuestring = valuestring+" ("+str(equipid)+","+str(valuec)+","+str(valuep)+",'"+str(system.date.format(tsc))+"','"+str(system.date.format(currentValue.timestamp))+"',"+str(logid)+"),"
event = [equipid,valuec,valuep,logid,tsc]
eventlist.append(event)
y = y+1
querystring = querystring+valuestring[:-1]+';'
n = system.db.runUpdateQuery(querystring,_dataBase)
logstop = system.date.now()
logger.info("heart beat trigger end successed take %s ms" % str(system.date.millisBetween(logstart,logstop)))
1 Like
First, this appears to be in a tag change event. You should avoid long running scripts in tag change events. I would recommend that you refactor this to be used with a Gateway Tag Change Event.
This is due to the way that Tag Change Events work. You can read more on that here:
Second, you should be using system.runPrepUpdate()
from itertools import chain
if not initialChange:
logstart = system.date.now()
logger = system.util.getLogger("Heartbeat event trigger")
oktoreadpath = '[default]_tmp/_HeartBeat_event_monitoring/ReadAreaOk2Read'
ReadLengthpath = '[default]_tmp/_HeartBeat_event_monitoring/ReadLength'
dbresultpath = '[default]_tmp/_HeartBeat_event_monitoring/DBResult'
paths = [oktoreadpath,ReadLengthpath]
[oktosend , readlength] = system.tag.readBlocking(paths)
readlength = readlength.value
if oktosend.value == 1 and readlength >0:
parentPath = '[default]_tmp/_HeartBeat_event_monitoring/_HeartBeat_event_read/_DPP_Read_HBEvent_{}_/'
eventpaths = [pPath + name for pPath in [parentPath.format(e) for e in range(readlength)] for name in ['Integer00','Integer01','Integer02','Integer03','TimeInBuffer']]
taglist = system.tag.readBlocking(eventpaths)
querystring = "INSERT INTO heartbeat_event (equipid,heartbeatc,heartbeatp,tsc,createdate,logid) values "
querystring += ','.join(['(?,?,?,?,?,?)'] * (readlength / 5))
querystring += ';'
def step(xs):
start = 0
step = 5
for x in xs:
if start > (len(xs)-step):
break
yield (start, xs[start])
start += step
eventlist = list(chain.from_iterable([[taglist[y].value,taglist[y+1].value,taglist[y+2].value,system.date.addMillis(currentValue.timestamp,taglist[y+4].value*(-1),currentValue.timestamp, taglist[y+3].value] for y,tag in step(taglist)]))
system.db.runPrepUpdate(querystring,eventlist,_dataBase)
logstop = system.date.now()
logger.info("heart beat trigger end successed take {}ms".format(system.date.millisBetween(logstart,logstop))
2 Likes