need sikuli to loop, can't figure out how

Asked by sikulihelp

Hi!

just tried to script a solution to a problem I have here with an unstable internet connection. The WLAN is w/o password, I need to autorise myself via a browser page. I'd like to:

(1) -let sikuli check every 5 minutes or so whether I'm online
(2) -if yes, nothing should be done except wait for another 5 minutes
(3) -if not, enter my log in data and then GOTO line 1

As far as I can tell, that is not really possible, but I don't have any python skills =(

Here is my solution, that is extremly unelegant because I have to enter my password in the script in plain text for I cannot use <<pw = input("Password?")>> in the beginning because I'm telling sikuli to restart itself via the Finder (using 10.2 in Mac OS X 10.6.4)

openApp ("Safari")
wait(5)
if exists ( ): # the image searched for is the login screen that is shown when the internet connection has dropped
 click ( )
 type (">>MYUSERNAME>>")
 click ( )
 type ("<<MYPASSWORD>>")
 click ( )
 wait(5)
 closeApp ("Safari")
 click( ) #opens spotlight, the mac finding routine
 type ("KCL") #name of the executable script (this one)
 type ("\n")
else: #if the image is not found, my computer has an internet connection
 closeApp ("Safari")
 click( ) #opens spotlight, the mac finding routine
 type ("KCL") #name of the executable script (this one)
 type ("\n")

I have to have sikuli keep looking even if it found the login screen (the <<if exists>> command found what it was looking for) and the sikuli script logged me in because after a successful login, the connection might drop soon after

EDIT: I am away when this script is running, so it doesn't bother me to be unable to work with the computer while the script is running. And I know the times in <<wait()>> are wrong, I put them this way for testing.

Question information

Language:
English Edit question
Status:
Solved
For:
SikuliX Edit question
Assignee:
No assignee Edit question
Solved by:
sikulihelp
Solved:
Last query:
Last reply:
Revision history for this message
sikulihelp (berobispo) said :
#1

I found the solution in the answer to question #120530. I added the

while True:

to the beginning. The

continue

statement wouldn't work because it was the last line in the loop. Can someone explain to a code-naive person (me=) what <<while True:>> means?

Revision history for this message
RaiMan (raimund-hocke) said :
#2

So if its possible, to leave your Mac alone, the script could look like this:

# rem x denote comments later on

Safari should be open with the respective url.

username = "some-text"
password = input("Give me the password")
# rem 1
switchApp("Safari") # rem 2
wait(1)

while True: # rem 3
   if exists(<image-of-login-dialog>):
      click(getLastMatch()) # rem 4
      paste(username) # rem 5
      type(Key.TAB) # should position on password field
      paste(password)
      type(Key.ENTER)
      # you should check here for a successful login somehow, otherwise exit(1)
   wait(300) # wait 5 minutes

--- rem 1
username and password are stored in variables at the beginning of the script

--- rem 2
on Mac I always use switchApp(), since it includes openApp() on Mac

--- rem 3
while and if expect an expression that evaluates either to True or False. If you need something that always is true (e.g. for an endless loop), the expression simply is True, since it always evaluates to True ;-)

--- rem 4
with finding <image-of-login-dialog> you have already the position of your login dialog. just use the preview feature <target offset> to set the relative position of the input field username. So after the exists() you just click on getLastMatch() which returns the match of the last find operation. No need for more images and searches.

--- rem 5
for typing text into input fields I always use paste(), since type() has problems with many characters and keys, because of the internal usage of the en-US keyboard layout.

You could enhance your script by opening the url and work fullscreen:
switchApp("Safari")
wait(5)
type("n", KEY_CMD) # new window
wait(0.5)
type("f", KEY_CTRL+KEY_CMD)
wait(0.5)
paste("the-url-of-your-webapp")
type(Key.ENTER)

One more thing:
A WhileTrue: should always have some code to terminate the loop, since otherwise you would have to kill Sikuli (ctrl-cmd-c).
In your case, you could e.g. say, that it should run for 4 hours:

at the beginning say:
actual = 0
maxrun = 48 (12 * 5 minutes)

say:
while actual < maxrun: instead of while True:

and add:
actual += 1 after the wait(300) inside the loop, which increments actual by 1

Last thing: (since you name yourself a code naive person ;-)
You may have already noticed, that indentation/dedentation is a vital feature in the Python language to group statements that belong together to blocks. So be sure you know what it means and how it is used
In the IDE its supported by TAB and SHIFT-TAB even for a bunch of selected lines and it keeps the indent, when you press newline.

Revision history for this message
sikulihelp (berobispo) said :
#3

Hi!

thanks for your help! Script is running now. Though I miss the GOTO LINE X command from my BASIC class ages ago in school ;-)

Revision history for this message
LP81 (pjbreen) said :
#4

Forgive my personal naivety...

But the original script above assumes that the login will will show up within 5 minutes every time doesn't it? If the login take 6 minutes to show up, for example, the script would have already thrown up a False, therefore it woudl never execute and

I used it as an example for a loop of my own but chose 30 seconds time out. Sometimes the process would take 5 seconds others up to 2 minutes to complete...

Since I want it to be as efficient as possible to only wait 30 second increments, and it if it doesn't find it the one time, how do I ensure that it will find a true statement to continue looping? (I am fine letting it run til I kill it myself as it is for work and i have to keep an eye on it's progress)

Revision history for this message
RaiMan (raimund-hocke) said :
#5

@ LP81

The original request was, to look every 5 minutes, wether a login has to be made again (to be recognized by the fact, that the login dialog was visible again). the login itself was just typed through, no wait for a successful login. There is no function around, that could bring up a FindFailed.
So this is a "check for something from time to time loop" and not a "wait for something to come up or vanish loop".

A waiting loop, that both has a max waiting time and a steptime could look like this:

maxTime = 600 # max 10 minutes
stepTime = 5 # check every 5 seconds
isFound = False
for runTime in range(0, maxTime, stepTime):
   if exists("img-we-are-waiting-for", 0): # only one try to find
      isFound = True
      break
   else:
      wait(steptime)
if not isFound:
   popup(str(int(maxTime/60))+" was not enough!")
   exit()