Delaying a script with popup displayed after in Perspective

There has ample discussion on NOT using time.sleep() in scripts, so I wanted to ask this question to see if anyone could (would) guide me to the proper solution.
We are using Perspective in this project and considerable development has been done, QA’d, Validated, and deployed into the production system. Being in a regulated environment, making modifications and additions is difficult at best. So rewriting working features is next to impossible to get approved.
The existing content communicates with a handful of laser markers via OPC UA connections. The communications done by issuing commands in the form of strings and waiting for a response back from the device, also as strings. This is triggered from a view but the logic exists in Project Library Script files. Essentially we disable the machine, write configuration to it, then re-enable. The disable/enable was setup to try and stop operators from triggering the print (from the machine control panel) prior to the configuration being complete. Unfortunately, the markers take a few extra seconds after the last of the configuration is sent (and after the triggering is re-enabled) before it has completely finished posting the configuration data. When Ignition has completed its part of sending the configuration to the marker, a popup is displayed to the operator to inform them of this. Since the machine is still configuring itself, this is causing erroneous markings on the parts.
To counter this, I’ve been asked to add a 4 second delay between finishing sending the configuration data and re-enabling the marker. Since this is in Perspective, there’s no access to the invokeLater function. How can I have the view or project script wait for 4 seconds, display a popup, and then re-enable the machine?
I had thought about expanding the UDTs for the devices to add tags to handle this, but to open the PU I’d have to have the Session ID and Page ID. I suppose those could be contained in additional tags within the UDT instances, but I’d would rather not have to do that since several operators, using tablets, interact with these machines. My concern there is that the sessions will be changing in unpredictable ways, which could cause unforeseen issues.

Any input would be greatly appreciated.

Try @pturmel solution with later.py
Ignition 8 invokeLater function doesn’t seem to exist - Ignition - Inductive Automation Forum

When I’ve had to do something similar, I use invokeAsynchronous like this:

# not tested in live environment - only provided as quick example of structure
def openPopupLater(sessionId, pageId):
    from time import sleep
    sleep(4)
    system.perspective.openPopup(id="DeviceReady", view="ViewToUse", sessionId=sessionId, pageId=pageId)

sessionId = self.session.props.id
pageId = self.page.pageId
# logic for resetting device goes somewhere before this line
system.util.invokeAsynchronous(openPopupLater, [sessionId, pageId])

It’s been explained to me that invokeAsynchronous is executed in its own thread, so you don’t risk blocking the current thread. As long as you’re not invoking this in a manner were you are sleeping on all available threads you should be fine.

2 Likes