Interactively change the IP-address on a Mac

(For Sikuli Version 0.10)


The goal is, to first find an entry in the network adapter list of the network pane in the "System Preferences", whose IP-address can be changed. Then we grab the current address, present it to the user and ask him for a change.

The selected one in the image above is such an entry.

Assumptions to keep it simple:

  • the relevant entry can be found among the first 5 ones (otherwise the script terminates without comment)
  • the presence of an IP-address is not checked - it may be empty
  • the IP typed by the user, is not validated at all. A malformed address is not handled by the script.

A general comment about timing - just make your own experiences:
In some situations it seems to be necessary,

  • to add a short wait after a type (reported as bug), since otherwise, the type is not finished correctly or a following action fails (e.g. selecting the next entry with Key.DOWN, typing cmd-c to copy the IP-address to the clipboard).
  • to add an additional wait(), after sikuli states, that an object is visible, to prevent, that a following action does not do, what it should (e.g. the wait() after the network pane is visible, that is necessary, when System Preferences had to start)

The first step is to make the network pane the frontmost window on the screen. The script works wether the "System Preferences" are already running or not and it does not matter, if another pane is already opened.

i = 0; iMax = 5 # limits number of checked entries 
# make System Preferences the frontmost window
switchApp("System Preferences")
mAll = wait(, 5)
# insert setting an ROI at this point 
# (see below at the end of the article)
# to asure that we start with the main pane
click(mAll)
click()
mNet = wait()
# now the Network pane is visible
wait(1)
click(mNet) # activates first adapter in list

in both cases (mAll and mNet) we have already defined click points for the next action using the preview feature "Pattern Settings" in the IDE.

Look for details in the tutorial for using the IDE and in the HowTo  How to click on a particular checkbox?.

Here are the screenshots from the target offset preview pane:

mAll (we want to click "Show All"):

mNet (we want to click on the first entry):


We loop through the entries until either the defined maximum of 5 entries is reached, an entry is defined as "not configured" or defined as manually configurable (which is the one we are looking for). To assure, that only "manually" is matched, we had to raise the minimum similarity to 0.9. If the wanted entry is not found, we just terminate the script.

while not exists(,0) and i < iMax:
    mIP = None
    if exists(,0):
        mIP = getLastMatch()
        break
    type(Key.DOWN); wait(0.3)
    i += 1
if not mIP:
    exit()

If this part of the script is entered, we know, that the click point defined with mIP is positioned on the field containing the current IP-address.

The screenshot from the target offset preview pane:

The IP-address is selected by double clicking and copied to the clipboard. From there we get it by using getClipboard(). We present it to the user using input(). If the user clicks OK, we assume, that he entered a valid address, that we paste into the field, where the current address is still selected. We have to click "Apply", to save the change. We wait for 2 seconds, which allows, to see, that the address is changed. Then we try to quit, which may fail, if any error occurred after clicking "Apply".

# processing the IP address 
doubleClick(mIP)
type("c", KEY_CMD); wait(0.1)
# the actual IP should be in the clipboard now
ipAddr = Env.getClipboard().strip()
# ask the user
switchApp("Sikuli-IDE")
# for readability here as variable
msg = "Your IP is " + ipAddr
msg += "\nType new one or cancel!"
ret = input(msg)
switchApp("System Preferences")
# if user typed something we use it as IP
if ret:
    paste(ret)
    click()
    wait(2)
# we try to quit
wait(2)
type("q", KEY_CMD)

Comment on the switchApp()'s surrounding the input() (special situation for Macs, reported as bug):

When the script is running, the "System Preferences" application has the focus. A plain input() (always displayed at the screen center) is displayed in the context of the Sikuli IDE, that does not have the focus in this moment. When the user clicks on the dialog, "System Preferences" looses focus, that is not automatically restored after the input() is processed, which causes the following actions to fail. The 2 switchApp()'s make this process running smooth without unnecessary user actions needed.


Comment on performance and possible FindFailed situations ( setROI() ):

If you use this script as is, you may be unsatisfied with the performance or may encounter weird find results. This is due to the fact, that the "Region of Interest (ROI)" is the whole screen. Since the "System Preferences" panes at least have a fixed width and the height of the ROI at least in this case can be assumed as fixed, we can set the ROI according to this facts. The pitfall is, that we don't know the position at the time the script is running, before we have found the title area the first time. The solution:

  • we capture the relevant region covered by the network pane in the IDE and so we have the values for width and height (just hover above the thumbnail)
  • after the first find, we set the ROI based on the position of the title area mAll and the width and height of this captured region.
# insert at placeholder (script's first part)
setROI(mAll.getX(), mAll.getY(), 600, 700)

You will realize: beginning with the click on the symbol of the network pane the script runs faster.


Sikuli script provides many more features to handle even complex situations in an elegant way. If you are interested, look at other Examples, Tutorials, HowTo's and especially at  The Complete Guide to Sikuli Script.


Attachments