"Notify with Timeout" project vision update mode

Vision projects have three update options; "Notify", "Push", or "None". "Push" is convenient for keeping all clients up to date all the time without having to click the "Project update available" banner on every single client. But "Notify" is needed to ensure no interruptions while users are holding "jog" buttons and similar.

It would be nice to have a fourth mode which shows the update banner with a 10-minute timer (configurable length). Users can click the banner to immediately update the client, or ignore it if they're in the middle of jogging something. Seems to me that'd be the best of both worlds, with all clients updating themselves automatically but avoiding interrupting people who are currently using the HMI.

Not necessary. You can use a client timer event script to impose any timing/policy you like, in conjunction with system.vision.updateProject().


[System]Client/System/LastProjectUpdate on my client appears to be the last time the client was updated.

The docs say it should be the "Date of the last received update notification." So isn't that behavior incorrect?

Not the end of the world since I can set up a client script to record the current time when [System]Client/System/ProjectUpdateAvailable triggers, and that seems to be re-triggering when multiple updates are pushed in a row without client updating in between. Just pointing out that this behavior seems strange to me.

I think you're misreading it as having something to do directly with the project update mode 'notify' (which, admittedly, it's confusingly worded).

I would expect "LastProjectUpdate" to change every time the project actually updated. Not every time a new update was pushed from the designer; only when those update(s) actually applied to the currently running local project.

Okie-dokie, I agree it's confusingly worded but whatever, it is working now. For reference this is what I did:

Client Tag Change Script
Trigger tag:



if newValue.getValue():

	import random
	# Restart client "X" minutes after update triggered.
	# Random interval avoids overload on network switches, 
	# tag server, etc., from clients all updating simultaneously
	tagPath = "[Client]ClientAutoUpdate/MinutesToTrigger"
	value = random.SystemRandom().uniform(10, 30)
	system.tag.write(tagPath, value)
	# When project is first launch, only set RandomMinutesToTrigger
	# but not CurrentDateTime. That causes Trigger to become active
	# and next Designer update would result in client immediately updating.
	if not initialChange:
		# LastProjectUpdateNotification already updates itself when 
		# project update it NOT available.
		# Additionally update here so that multiple published updates 
		# will delay the inevitable client update, and NOT trigger
		# unnecessary multiple client updates.
		tagPath = "[Client]ClientAutoUpdate/LastProjectUpdateNotification"
		value = system.tag.read("[System]Client/System/CurrentDateTime")
		system.tag.write(tagPath, value)

Client tags

Tags Properties
DateTimeToTrigger Expression: addMinutes({[.]LastProjectUpdateNotification}, {[.]MinutesToTrigger})
LastProjectUpdateNotification Expression: if({[System]Client/System/ProjectUpdateAvailable}, {[.]LastProjectUpdateNotification}, now())
MinutesToTrigger Memory tag
Trigger Expression: now() > {[.]DateTimeToTrigger} Script: if currentValue: system.vision.updateProject()

Header button
Visibility property binding:


Text property expression:

	"Project update available. Auto update in ",
	if( 60 < dateDiff(now(), {[client]ClientAutoUpdate/DateTimeToTrigger}, "second"),
		concat(round(dateDiff(now(), {[client]ClientAutoUpdate/DateTimeToTrigger}, "minute"), 1), " min(s)"), // true
		concat(toInteger(dateDiff(now(), {[client]ClientAutoUpdate/DateTimeToTrigger}, "second")), " sec(s)")	// false
	". Or click here to update now."
1 Like

Edited script in post above to fix two things:

  • MinutesToTrigger wasn't getting randomly set when client first launched, so all clients would start with the same delay time instead of random.
  • Use random.SystemRandom().uniform(10,30) instead of random.uniform(10,30). Otherwise all clients will pick random times -- but they will all pick the same random time if they were restarted at the same time.