Resettable runtime counter

Well, no. Not accurately. Tag execution intervals are approximate, and heavy load on the gateway will add to the inaccuracy.

Plus, your expression's use of itself makes a circular reference that will almost certainly choke on gateway restart.

The reliable way to have such a timer is to use a single datetime memory tag that holds the timestamp of the most recent reset.

Wherever you need to display the seconds since that timestamp, use:

dateDiff({[provider]path/to/memory/tag}, now(), 'second')

Whatever script you are using to write to your reset tag, change to simply write the current timestamp (from system.date.now()) to the memory tag.

Precise, zero gateway workload, simple reset. Even "counts" during gateway restarts.

Edit: Hmmm. The above doesn't handle the run indicator. A more complicated solution is needed for accuracy and robustness for such:

  • A memory tag of type double to hold "Prior Runtime Seconds"

  • Two memory tags of type datetime to hold the last "On" and "Off" timestamps of the run indicator.

  • A valueChange event script on the run indicator tag to intelligently update those memory tags (presumably all in the same tag folder). Something like this:

def valueChange(....):
	prior, onTS, offTS = [x.value for x in readBlocking(['[.]PriorSeconds', '[.]OnTimestamp', '[.]OffTimestamp'])]
	if currentValue.value:
		# Run Indicator is ON
		if offTS.after(onTS):
			# Really is transition to ON
			system.tag.writeBlocking(['[.]OnTimestamp'], [system.date.now()])
	else:
		# Run Indicator is OFF
		if not offTS.after(onTS):
			# Really is transition to OFF
			now = system.date.now()
			interval = 0.001 * (now.time - onTS.time)
			system.tag.writeBlocking([['[.]PriorSeconds', '[.]OffTimestamp'], [prior + interval, now])
  • Your reset operation simultaneously writes now() to the OnTimestamp and 0.0 to the PriorSeconds tags.

  • Your display expression becomes:

if(
	{[provider]path/to/run/indicator},
	{[provider]path/to/PriorSeconds} + dateDiff({[provider]path/to/OnTimestamp}, now(), 'second'),
	{[provider]path/to/PriorSeconds}
)
4 Likes