Script with syntax highlighting
##########################################################
# NAME: goToNextOp
# DESCRIPTION: When an operation has been completed, set that operation
# to "COMPLETE" in the database, signal the PLC to reset the operation
# status and wait until it is finished, then set the next operation in
# the database to "RUNNING". When a running operation has been found, it
# copies the new operation's information from the database to the PLC
# batch program.
# PARAMETERS: PLCbubbleNum (active bubble number in the PLC, if this does
# not match the bubble number from the database, then the
# PLC information needs to be updated.)
# opComplete (trigger from PLC indicating an operation has finished)
# REVISION: 1.3 08/31/17
# REV. NOTE: Added "nextOpStep" to prevent issues where certain functions are
# repeated or triggered out of order.
##########################################################
# send a query to the DB, requesting all running operations
#RU 03/05/2019 -- Update query so that it also obtains all the PAUSED operations
#RU 09/13/2019 -- Update query so that it also obtains all the PAUSED-APP6 operations
table = system.db.runQuery("SELECT * FROM RUNNING WHERE STATUS='RUNNING' or STATUS='PAUSED' or STATUS='PAUSED-APP6'")
commDelay = [False]*75 # if set to true, this means the 'opComplete' bit has
# already been read, so the batch should not be processed again
batchCleared = False # indicates batch has been cleared, so OP_ID should not be modified
# update cycle number for logging/debugging
cycleNum = system.tag.read("IgnitionStatus/GoToNextOpCycle").value
if cycleNum > 9999:
cycleNum = 0
else:
cycleNum = cycleNum + 1
system.tag.write("IgnitionStatus/GoToNextOpCycle",cycleNum)
cycleNum = str(cycleNum)
# CHECK FOR RUNNING OPERATIONS IN THE DATABASE
for row in table: # iterate through all running operations that were found
vesselID = shared.Functions.vesselID(row[0][1:]) # change vessel name to vessel ID
tagPath = "Vessel/Vessel_" + vesselID + "_/Batch/BubbleNum" # set tag path
PLCbubbleNum = system.tag.read(tagPath).value # get current bubble number from PLC
nextOpStep = system.tag.read("IgnitionStatus/NextOp_Step_" + vesselID).value # get nextOp step number
# if current bubble number of the operation does not match the db value
# and steps 1 and 2 have already been completed (or it is the first operation
# in the batch), then start the next operation.
if (PLCbubbleNum != row[2]) and (nextOpStep == 3 or row[2] == 1):
if system.tag.read("Vessel/Vessel_" + vesselID + "_/Batch/OperationComplete" ).value == 0:
print "Cycle:" + cycleNum + " 3. Bubble: " + str(row[2]) + " started on vessel " + row[0][1:] + ". Old bubble number=" + str(PLCbubbleNum)
system.tag.write(tagPath,row[2]) # write new bubble number to PLC
system.tag.write("IgnitionStatus/NextOp_Step_" + vesselID,1) # update nextOp step number
shared.Functions.startOperation(row,vesselID) # start operation function
else: # opComplete has not been cleared, do not start the next operation yet
commDelay[int(vesselID)] = True
print "Cycle:" + cycleNum + ", waiting on opComplete for vessel " + row[0][1:]
tagPath2 = "Vessel/Vessel_" + vesselID + "_/Batch/CurrentStep" # set tag path
if system.tag.read(tagPath2).value == 0: # current step = 0 found, always start on step 1
print "Step 0 found on vessel " + vesselID + " - reassigned to step 1."
system.tag.write(tagPath2,1)
#moved checking for PAUSED operation in a different script
#RU 03/26/2019 Add the following line of code to determine if the lot is an adjustment.
current_OPID = system.tag.read("Vessel/Vessel_" + vesselID + "_/Batch/OP_ID")
if current_OPID.value == 1:
currentLot = system.tag.read("Vessel/Vessel_" + vesselID + "_/Batch/ProductLot/STRING")
currentLotLen = system.tag.read("Vessel/Vessel_" + vesselID + "_/Batch/ProductLot/LEN")
checkAdjPath = "Vessel/Vessel_" + vesselID + "_/Adjusted"
if currentLot.value[currentLotLen.value - 1] == "0":
system.tag.write(checkAdjPath,0)
else:
system.tag.write(checkAdjPath,1)
# CHECK FOR COMPLETED OPERATIONS AND MOVE TO NEXT BUBBLE NUMBER
i = 1 # initialize vessel ID index for searching
while i < 74: # look through each vessel
j = str(i) # convert vessel ID to string
opComplete = system.tag.read("Vessel/Vessel_" + j + "_/Batch/OperationComplete" ).value
opID = system.tag.read("Vessel/Vessel_" + j + "_/Batch/OP_ID" ).value
# if an operation is complete, and the PLC has been changed to "loading",
# and the operation has not already been changed, then continue to next operation
if opComplete == True and opID == 100 and not commDelay[i]:
# reset batch control tags first
system.tag.write("Vessel/Vessel_" + j + "_/Batch/OperationComplete",0) # unlatch op complete
system.tag.write("Vessel/Vessel_" + j + "_/Batch/CurrentStep",1) # reset current step
system.tag.write("Vessel/Vessel_" + j + "_/Workflow/HMI_PB/HMI_PB_0_",0) # unlatch done pb
vessel = shared.Functions.vesselName(j) # load vessel name
# get the currently completed operation to ensure it exists in the database
currentOp = system.db.runQuery("SELECT TOP 1 Operation FROM RUNNING WHERE STATUS='RUNNING' AND VESSEL='V" \
+ vessel +"'") # find the completed operation
nextOpStep = system.tag.read("IgnitionStatus/NextOp_Step_" + j).value # get nextOp step number
if len(currentOp) > 0 and (nextOpStep == 1): # confirm that the operation exists in the database
print "Cycle:" + cycleNum + " 1. Completed operation " + currentOp[0][0] + " found on vessel: " + vessel
# If the completed operation is 'FILL', record filter data
if currentOp[0][0] == "Fill":
print "Fill operation completed, filter data recorded on vessel " + vessel
shared.Functions.recordFilterData(j)
system.db.runUpdateQuery("UPDATE RUNNING SET STATUS='COMPLETE' WHERE STATUS='RUNNING' AND VESSEL='V" \
+ vessel +"'") # update completed operation to COMPLETE
nextOp = system.db.runQuery("SELECT TOP 1 * FROM RUNNING WHERE STATUS='PENDING' AND VESSEL='V" \
+ vessel + "' ORDER BY BUBBLE_NUM ASC") # find next PENDING op
system.tag.write("IgnitionStatus/NextOp_Step_" + j,3) # update nextOp step number
if len(nextOp) > 0: # Additional pending operations exists
nextOpNum = str(nextOp[0][2])
system.db.runUpdateQuery("UPDATE RUNNING SET STATUS='RUNNING' WHERE BUBBLE_NUM='" + nextOpNum + \
"' AND VESSEL='V" + vessel +"'") # set next op to RUNNING
print "Cycle:" + cycleNum + " 2. Set bubble number " + nextOpNum + " to 'Running' on vessel " + vessel + "."
else: # There are no more pending operations, batch is complete
shared.Functions.clearBatchValues(j) # clear batch values
batchCleared = True
system.db.runUpdateQuery("DELETE FROM RUNNING WHERE VESSEL='V" \ # remove the batch
+ vessel + "'")
print "Cycle:" + cycleNum + " No more pending operations for vessel: " + vessel + ", batch removed from DB."
else: # batch does not exist, send error indication to PLC/iFIX
system.tag.write("Vessel/Vessel_" + j + "_/Batch/OP_ID",99) # 99 = operation error condition
opComplete = False
system.tag.write("IgnitionAlarms/IgnitionAlarms_1_",vessel)
print "ERROR: Vessel " + vessel + " has a completed operation but does not exist in the database!"
# set current vessel to 'loading'
elif opComplete == True and opID != 100 and not commDelay[i] and not batchCleared:
system.tag.write("Vessel/Vessel_" + j + "_/Batch/OP_ID",100)
print "Cycle:" + cycleNum + "OP ID set to 100 ('loading') for vessel " + j + "."
i += 1 # increment vessel ID counter
Varsha, please see Wiki - how to post code on this forum.