I design an HMI on ignition vision. When I'm on a specific window, I need to wait that a modbus register changes from 0 to 1 to change to another window. To do this, I created a client tag change script on the modbus register. But I need to know if I'm in the specific waiting window to swap to the desired window (ex : don't swap to that window if the current window is the home page). So, on the event, I check the current opened window with "system.nav.getCurrentWindow()", but the function don't always return the window that is showing in the HMI. If there is other windows that are still opened in background, the function sometimes return one of those windows.
What is happening?
How can I get the "Currently showing window" in the client tag change scripts?
There is the complete script:
print event.tagPath
print initialChange
print newValue.value
current_window = system.nav.getCurrentWindow()
print "this is the current window : "
print current_window
if current_window == "main_windows/rfid_successs" and newValue.value == 1:
system.nav.closeWindow(current_window)
system.nav.openWindow("main_windows/charging_2")
system.tag.writeBlocking("[Sample_Tags]_Intesis OCPP 1_6 Modbus Gateway_/UnitId 0/trans_id0-trans_id0/trans_id0", 321)
system.tag.writeBlocking("[Sample_Tags]_Intesis OCPP 1_6 Modbus Gateway_/UnitId 0/start_proces0-start_proces0/start_proces0", 1)
Tag Change Scripts are in a different scope than the GUI. Thanks for setting me straight @pturmel
You should create a custom property on the root container and bind it to the tag that represents the modbus register you want to wait for the change on. Then in the property change script of the root container you can filter for the custom property and when it changes to 1 execute any script that you want.
Also, notice that I have changed the order of the code so that you write to the tags prior to navigating away from the window. This guarantees that the tag write occurs before the window closes since writeBlocking() blocks the thread until it returns. If you don't want to wait to navigate, then consider using writeAsync() instead.
Since you are closing the current window and opening another, you can just use system.nav.swapTo(), the function closes the current window and opens the window at the provided path.
Emile specifically called out Client Tag Change Scripts, which are very much in client scope in Vision. But "current window" is only for main windows, and if there are more than one of those, the result is unreliable. Popups are not main windows.
Is there a ‘getActiveWindow’ or equivalent? I know that Ignition can differentiate between active windows because the ‘internalFrameActivated’ event listener exists.
from java.awt import Window
def activeWindow():
"""
Returns the currently active window, if any, or else None.
"""
return next(w for w in Window.getWindows() if w.active)
@pturmel the string representation of this object is simply the lowest project tree node of the window. Is there a way to get the full path of the window?
It is the actual window object. Don't stringify it. (If you are opening multiple instances of windows, duplicate names are possible. Use the object, not the name.) But look at the documentation.
Because the system/Client/CurrentWindow tag has the same unpredictable behavior as OP’s code, how would I go about creating a client tag that monitors the focusOwner?
So from the code below we were seeing that the system.nav.getCurrentWindow() was not printing the new opened window if the timeout was active. We changed to swapTo() and now it is updating will the client tag stay in any opened window if we don’t close it? I’m using Vision 8.1.38
print(system.nav.getCurrentWindow())
if system.nav.getCurrentWindow() != 'MainWindows/Login':
# Read Username and User Roles from system client tags
userRole = system.tag.readBlocking(['[System]Client/User/RolesString'])[0].value
userName = system.tag.readBlocking(['[System]Client/User/Username'])[0].value
# only run if not already logged in as default user
# should be redundant now if checking window
if 'default' not in userName.lower():
# set different timeout for operator role
if ('operator' in userRole.lower()) and (userRole.count(',') == 0):
timeInactive = 3600
elif (('engineer' in userRole.lower()) and (userRole.count(',') == 0)) or (('engineer' in userRole.lower()) and ('administrator' in userRole.lower()) and ('operator' not in userRole.lower())):
timeInactive = 180
else:
timeInactive = 60
print(timeInactive)
# if timeout exceeded, switch to default account, go to login window, and close alarm popup
if system.util.getInactivitySeconds() > timeInactive:
system.security.switchUser('default','default')
system.nav.swapTo('MainWindows/Login')
system.nav.closeWindow('Popups/TemplateWindows/activeAlarmPopup')
print(system.nav.getCurrentWindow())
elif system.nav.getCurrentWindow() == 'MainWindows/Login':
if (system.util.getInactivitySeconds() > 10) and (system.tag.readBlocking(['[client]User/Login/username'])[0].value != ''):
print("inactivity: " + str(system.util.getInactivitySeconds()))
system.tag.writeBlocking(['[client]User/Login/username'], [''])
system.nav.getCurrentWindow() returns the same value as the Vision system tag for CurrentWindow. Neither can be used if you allow multiple main windows to be open at the same time. In other words, you must only use system.nav.openWindow() for popups (or docks), not for main windows. You MUST use system.nav.swapTo() for all main windows if you want .getCurrentWindow() to be accurate. That is the whole point of the workarounds in this topic: how to get the focused window even when not constraining main windows.