# Timer script executing multiple times

**URL:** <https://forum.inductiveautomation.com/t/timer-script-executing-multiple-times/110492>\
**Category:** Ignition\
**Tags:** scripting\
**Created:** [September 9, 2025, 4:58pm UTC](https://forum.inductiveautomation.com/t/timer-script-executing-multiple-times/110492 "2025-09-09T16:58:00Z")\
**Posts on this page:** 1\
**Showing post:** 4

<div class="post-metadata">

**Author:** ![Transistor](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/transistor/32/3380_2.png) [@Transistor](https://forum.inductiveautomation.com/u/Transistor)\
**Post date:** [September 9, 2025, 5:56pm UTC](https://forum.inductiveautomation.com/t/timer-script-executing-multiple-times/110492/4 "2025-09-09T17:56:58Z")

</div>

> **Script with syntax highlighting**
>
> ```python
> ##########################################################
> # 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](https://forum.inductiveautomation.com/t/wiki-how-to-post-code-on-this-forum/77831).

---

_[View the full topic](https://forum.inductiveautomation.com/t/timer-script-executing-multiple-times/110492)._
