Screen Based Automation
Screen Based Automation
This is the example of automating Windows 10 calclator using screen based automation.
Steps include:
- Open calculator using start menu
- Maximize calculator window and switch to scientific mode
- Calculate logarithm
- Extract result from screen using OCR
- Close calculator window
Application class returns WindowsPage object which provides access to Windows 10 desktop.
WindowsScreenApplication .java
package eu.ibagroup.easyrpa.calculator;
import eu.ibagroup.easyrpa.calculator.page.WindowsPage;
import eu.ibagroup.easyrpa.engine.rpa.Application;
import eu.ibagroup.easyrpa.engine.rpa.driver.ScreenDriver;
import eu.ibagroup.easyrpa.engine.rpa.element.ScreenElement;
public class WindowsScreenApplication extends Application<ScreenDriver, ScreenElement> {
public WindowsScreenApplication(ScreenDriver driver) {
super(driver);
}
@Override
public WindowsPage open(String... args) {
return createPage(WindowsPage.class);
}
} WindowsPage.java
package eu.ibagroup.easyrpa.calculator.page;
import eu.ibagroup.easyrpa.engine.rpa.element.ScreenElement;
import eu.ibagroup.easyrpa.engine.rpa.page.ScreenPage;
import eu.ibagroup.easyrpa.engine.rpa.po.annotation.FindBy;
import eu.ibagroup.easyrpa.engine.rpa.po.annotation.Wait;
import lombok.extern.slf4j.Slf4j;
import org.sikuli.script.Key;
@Slf4j
public class WindowsPage extends ScreenPage {
private static final long ANIMATION_TIMEOUT = 1000;
@FindBy(image = "images/windows-start-1.png")
@Wait(3)
private ScreenElement start;
public CalculatorMainPage openCalcApp() {
launchFromStart("calculator");
sleep(ANIMATION_TIMEOUT);
return createPage(CalculatorMainPage.class);
}
private void launchFromStart(String appName) {
start.click();
sleep(ANIMATION_TIMEOUT);
getDriver().sendKeys(appName);
sleep(ANIMATION_TIMEOUT);
getDriver().sendKeys(Key.ENTER);
}
private static void sleep(long millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
log.error(e.getMessage(), e);
}
}
}CalculatorMainPage can potentially provide handles for all the buttons and menus rendered on calculator window, but we restricted those to demo purposes.
CalculatorMainPage.java
package eu.ibagroup.easyrpa.calculator.page;
import eu.ibagroup.easyrpa.engine.rpa.element.ScreenElement;
import eu.ibagroup.easyrpa.engine.rpa.page.ScreenPage;
import eu.ibagroup.easyrpa.engine.rpa.po.annotation.FindBy;
import eu.ibagroup.easyrpa.engine.rpa.po.annotation.Wait;
import lombok.extern.slf4j.Slf4j;
import org.sikuli.script.Key;
import org.sikuli.script.Region;
@Slf4j
public class CalculatorMainPage extends ScreenPage {
private static final double CALC_DISPLAY_HEIGHT_RATIO = 0.14;
private static final double CALC_DISPLAY_WIDTH_RATIO = 0.85;
private static final double CALC_DISPLAY_Y_RATIO = 0.12;
@FindBy(image = "images/btn-navigation.png")
@Wait(3)
private ScreenElement navigation;
@FindBy(image = "images/btn-four.png")
@Wait(3)
private ScreenElement fourBtn;
@FindBy(image = "images/btn-six.png")
@Wait(3)
private ScreenElement sixBtn;
@FindBy(image = "images/btn-eight.png")
@Wait(3)
private ScreenElement eightBtn;
@FindBy(image = "images/btn-plus.png")
@Wait(3)
private ScreenElement plusBtn;
@FindBy(image = "images/btn-equals.png")
@Wait(3)
private ScreenElement equalsBtn;
public void four() {
fourBtn.click();
}
public void six() {
sixBtn.click();
}
public void eight() {
eightBtn.click();
}
public void plus() {
plusBtn.click();
}
public void equals() {
equalsBtn.click();
}
public String getDisplayText() {
int h = (int) (CALC_DISPLAY_HEIGHT_RATIO * getDriver().getScreen().h);
int w = (int) (CALC_DISPLAY_WIDTH_RATIO * getDriver().getScreen().w);
int y = (int) (CALC_DISPLAY_Y_RATIO * getDriver().getScreen().h);
int x = 5;
log.debug("Reading region: x={} y={} w={} h={}", x, y, w, h);
return getRegionText(x, y, w, h);
}
private String getRegionText(int x, int y, int w, int h) {
Region regResult = getDriver().getScreen().newRegion(x, y, w, h);
regResult.highlight(2);
return regResult.text();
}
public void exit() {
getDriver().getScreen().keyDown(Key.ALT);
getDriver().getScreen().keyDown(Key.F4);
getDriver().getScreen().keyUp();
}
public void maximizeWindow() {
getDriver().getScreen().keyDown(Key.ALT);
getDriver().getScreen().keyDown(Key.SPACE);
getDriver().getScreen().keyDown("x");
getDriver().getScreen().keyUp();
}
}
getDisplayText() is worth a specific mention since it employs OCR to read a certain region on screen. This region is basically a rectangular defined by upper left vertex (x, y), height (h) and width (w).