How to fix this race condition correctly with custom property tied to a tag?

I have a custom property with a binding to a UDT. I only want certain events to execute when the user has opened the view with that specific UDT. In other words, the user enters the view, the binding data is loaded, and then certain events happen based on the binding values.

The custom binding has three relevant tags to the problem.

  • InactivityTimerMaxVal is a binding to a memory tag.
  • InactivityTimer is a binding to an expression tag.
  • LastTimeActivityDetected is a binding to a datetime tag.

The expression tag InactivityTimer updates increments once per second until the user interacts with the system. There is also a change script on this tag that writes to the memory tag InactivityTimerMaxVal the currentValue. (This step may not be necessary to the project - just explaining what is happening).

On the view, with the custom property bound to the UDT tag, the following change script occurs on the custom property InactivityTimerMaxVal. When InactivityTimerMaxVal is greater than a setpoint (memory tag) a popup is opened and the user is forced to interact with it.

This is the change script on the custom property InactivityTimerMaxVal.

# Name of this custom property is InactivityTimerMaxVal <- binding to tag InactivityTimerMaxVal
def valueChanged(self, previousValue, currentValue, origin, missedEvents):
	
	if str(self.session.props.device.type) == "browser":

		if currentValue.value >= self.custom.UDT.PLC.PromptDowntimeInSeconds: # Problem here?

			system.perspective.openPopup(id=self.session.props.id, view='Popups/MachineStopped', params = {'MachineName':self.custom.MachineName}, modal = True, showCloseIcon = False)

The popup eventually writes the current time to LastTimeActivityDetected and writes 0 to InactivityTimerMaxVal (Writing 0 is probably pointless here).

Problem: The popup is periodically being triggered again immediately after being executed. I think that the custom properties are not seeing the tag updates quick enough and the script doesn't identify that the tag value has been reset.

I am looking for solutions that allow the view to open a popup when certain criteria are met and prevent duplicate popups from occurring as well. Any advice - or ideas - are welcome.

Does the InactivityTimer tag reset as soon as the user interacts with the popup?

If it does, I'd forgo using the InactivityTimerMaxVal tag and just bind directly to InactivityTimer.

No, the tag is reset when the user hits a "confirm" button on the screen after entering some information (specifically looking for what reason the machine was not running for X time) and I record the InactivityTImer value in a database when they hit the confirm button. So the popup could be open, waiting for user interaction for some time, and then the user interacts with the screen.

What I have attempted so far is add another custom property called "PopupTriggered", set it to True when the Popup gets triggered, and then on the confirm button I have a script run after closing the popup that sends a message handler back to the view to set "PopupTriggered" property back to False.

I'm not happy with this solution but can't think of anything else at this time.

Maybe you could have 2 containers on the view. One being your "main view", and the other your "inactivity message" that's currently on your popup. The display of the "main" one would be bound to InactivityTimer being below the setpoint (+ the UDT requirement), and the display of the second one would be bound to the opposite of the display of the first one (so that only one of the containers is displayed at a time). Everything would be running off of one tag binding. As soon as the binding detects that InactivityTimer has been reset, the container display properties flip and the "inactivity message" disappears.

1 Like

That is pretty smart ... I don't normally like using invisible components but it is a really elegant solution. Let me take a shot here and see if that will work.

1 Like