diff --git a/cctp-atu/atu-mobile-driver/src/main/java/net/northking/cctp/mobile/driver/constans/AutomationRequestCmd.java b/cctp-atu/atu-mobile-driver/src/main/java/net/northking/cctp/mobile/driver/constans/AutomationRequestCmd.java index 2efa09d..73c8868 100644 --- a/cctp-atu/atu-mobile-driver/src/main/java/net/northking/cctp/mobile/driver/constans/AutomationRequestCmd.java +++ b/cctp-atu/atu-mobile-driver/src/main/java/net/northking/cctp/mobile/driver/constans/AutomationRequestCmd.java @@ -48,6 +48,10 @@ public interface AutomationRequestCmd { String PRESS_HOME_KEY = "press_home_key"; //点击home键 + String PRESS_BACK_KEY = "press_back_key"; //点击返回键 + + String PRESS_APP_SWITCH_KEY = "press_app_switch_key"; //点击多任务键 + String INPUT_PASSWORD_BY_OCR = "input_password_by_ocr"; //输入密码(ocr) String GET_ELEMENT_MONEY_TEXT = "get_element_money_text"; //识别金额 diff --git a/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/automation/constants/AutomationRequestCmd.java b/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/automation/constants/AutomationRequestCmd.java index 0a48d73..bbcec8a 100644 --- a/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/automation/constants/AutomationRequestCmd.java +++ b/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/automation/constants/AutomationRequestCmd.java @@ -48,6 +48,10 @@ public interface AutomationRequestCmd { String PRESS_HOME_KEY = "press_home_key"; //点击home键 + String PRESS_BACK_KEY = "press_back_key"; //点击返回键 + + String PRESS_APP_SWITCH_KEY = "press_app_switch_key"; //点击多任务键 + String INPUT_PASSWORD_BY_OCR = "input_password_by_ocr"; //输入密码(ocr) String GET_ELEMENT_MONEY_TEXT = "get_element_money_text"; //识别金额 diff --git a/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/automation/handler/AbstractAutomationHandler.java b/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/automation/handler/AbstractAutomationHandler.java index 142374f..285bb3c 100644 --- a/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/automation/handler/AbstractAutomationHandler.java +++ b/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/automation/handler/AbstractAutomationHandler.java @@ -2,6 +2,7 @@ package net.northking.cctp.upperComputer.automation.handler; import cn.hutool.core.codec.Base64; import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import net.northking.cctp.upperComputer.automation.constants.AutomationRequestCmd; import net.northking.cctp.upperComputer.automation.constants.UpperParamKey; @@ -22,6 +23,7 @@ import net.northking.cctp.upperComputer.utils.deviceHepler.DeviceHelper; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.util.CollectionUtils; import javax.imageio.ImageIO; import javax.websocket.Session; @@ -104,6 +106,10 @@ public abstract class AbstractAutomationHandler implements AutomationMessageHand handleApp(request); } else if (AutomationRequestCmd.PRESS_HOME_KEY.equals(cmd)) { pressHomeKey(request); + } else if (AutomationRequestCmd.PRESS_BACK_KEY.equals(cmd)){ + pressBack(request); + }else if (AutomationRequestCmd.PRESS_APP_SWITCH_KEY.equals(cmd)){ + pressAppSwitch(request); } else if (AutomationRequestCmd.INPUT_PASSWORD_BY_OCR.equals(cmd)) { inputPasswordByOcr(request); } else if (AutomationRequestCmd.GET_ELEMENT_MONEY_TEXT.equals(cmd)) { @@ -486,4 +492,94 @@ public abstract class AbstractAutomationHandler implements AutomationMessageHand } } + @Override + public void getTextDirectionText(CmdAutomationRequest request) { + CmdAutomationResponse response = CmdAutomationResponse.builderFailure(request, "获取指定文字指定方向的内容失败"); + String value = ""; + try { + Map data = request.getData(); + String text = (String) data.get(UpperParamKey.INPUT_TEXT); + Integer index = (Integer) data.get(UpperParamKey.INDEX); + String direction = (String) data.get(UpperParamKey.DIRECTION); + String imgBase64 = getClickTextOcrAreaToBase64(request); + if (StringUtils.isBlank(imgBase64)) { + response = CmdAutomationResponse.builderFailure(request, "未获取到ocr区域"); + } + JSONObject ocrResultMap = ocrHelper.getTextDirectionText(imgBase64, text, direction, index); + if (null != ocrResultMap) { + JSONObject target_boxes = ocrResultMap.getJSONObject("target_boxes"); + logger.info("target_boxes为:{}", JSON.toJSONString(target_boxes)); + if ("右".equals(direction) || "左".equals(direction)) { + if (null != target_boxes) { + String targetText = (String) target_boxes.get("text"); + if (StringUtils.isNotBlank(targetText)) { + int targetIndex = targetText.indexOf(text); + if ("右".equals(direction) && targetIndex < (targetText.length() - text.length())) { + value = targetText.substring(targetIndex + text.length()); + } else if ("左".equals(direction) && targetIndex > 0) { + value = targetText.substring(0, targetIndex); + } + } + } + } + + if (StringUtils.isBlank(value)) { + try { + JSONObject neighbor_boxes = ocrResultMap.getJSONObject("neighbor_boxes"); + logger.info("neighbor_boxes为:{}", JSON.toJSONString(neighbor_boxes)); + if (null != neighbor_boxes) { + String neighborText = (String) neighbor_boxes.get("text"); + value = neighborText; + } + } catch (Exception e) { + JSONArray neighbor_boxes = ocrResultMap.getJSONArray("neighbor_boxes"); + if (!CollectionUtils.isEmpty(neighbor_boxes)) { + value = (String) ((Map) neighbor_boxes.get(0)).get("text"); + } + } + } + } + logger.info("获取指定文字指定方向的内容为:{}", value); + response = CmdAutomationResponse.builderSuccess(request, "获取指定文字指定方向的内容成功").withData(value); + } catch (Exception e) { + logger.error("识别失败,原因:", e); + response = CmdAutomationResponse.builderFailure(request, e.getMessage()); + } finally { + sendResultToEngine(response); + } + } + + @Override + public void getVerificationCodeByOcr(CmdAutomationRequest request) { + CmdAutomationResponse response = CmdAutomationResponse.builderSuccess(request, "根据ocr获取验证码失败").withData(null); + try { + String value = null; + Map requestData = request.getData(); + String targetBase64 = ""; + if (requestData.get(UpperParamKey.X) != null) { + targetBase64 = getOcrAreaToBase64(request); + } else { + targetBase64 = getClickTextOcrAreaToBase64(request); + } + if (StringUtils.isBlank(targetBase64)) { + response = CmdAutomationResponse.builderSuccess(request, "未获取到ocr区域").withData(null); + return; + } + Map data = request.getData(); + Integer codeType = (Integer) data.get(UpperParamKey.CODE_TYPE); + value = ocrHelper.getVerificationCodeByBase64(targetBase64, codeType); + if (StringUtils.isNotBlank(value)) { + response = CmdAutomationResponse.builderSuccess(request, "根据ocr获取控件值成功").withData(value); + } else { + response = CmdAutomationResponse.builderSuccess(request, "根据ocr获取控件值失败").withData(null); + } + } catch (Exception e) { + logger.error("根据ocr获取验证码失败,原因:", e); + response = CmdAutomationResponse.builderSuccess(request, e.getMessage()).withData(null); + } finally { + sendResultToEngine(response); + } + } + + } diff --git a/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/automation/handler/AndroidAutomationHandler.java b/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/automation/handler/AndroidAutomationHandler.java index 779b60c..79b95c0 100644 --- a/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/automation/handler/AndroidAutomationHandler.java +++ b/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/automation/handler/AndroidAutomationHandler.java @@ -111,11 +111,6 @@ public class AndroidAutomationHandler extends AbstractAutomationHandler{ } - @Override - public void getVerificationCodeByOcr(CmdAutomationRequest request) { - - } - @Override public void longPress(CmdAutomationRequest request) { @@ -202,7 +197,12 @@ public class AndroidAutomationHandler extends AbstractAutomationHandler{ } @Override - public void getTextDirectionText(CmdAutomationRequest request) { + public void pressBack(CmdAutomationRequest request) { + + } + + @Override + public void pressAppSwitch(CmdAutomationRequest request) { } diff --git a/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/automation/handler/AutomationMessageHandler.java b/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/automation/handler/AutomationMessageHandler.java index 36f9c7a..5a0f894 100644 --- a/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/automation/handler/AutomationMessageHandler.java +++ b/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/automation/handler/AutomationMessageHandler.java @@ -72,6 +72,10 @@ public interface AutomationMessageHandler { void pressHomeKey(CmdAutomationRequest request); //点击home键 + void pressBack(CmdAutomationRequest request); //点击home键 + + void pressAppSwitch(CmdAutomationRequest request); //点击home键 + void inputPasswordByOcr(CmdAutomationRequest request); //密码输入(ocr) void getElementMoneyText(CmdAutomationRequest request); //识别金额 diff --git a/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/automation/handler/HarmonyAutomationHandler.java b/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/automation/handler/HarmonyAutomationHandler.java index 4163cd8..1f0ba3b 100644 --- a/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/automation/handler/HarmonyAutomationHandler.java +++ b/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/automation/handler/HarmonyAutomationHandler.java @@ -1,5 +1,8 @@ package net.northking.cctp.upperComputer.automation.handler; +import cn.hutool.core.codec.Base64; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; import net.northking.cctp.upperComputer.automation.constants.Command; import net.northking.cctp.upperComputer.automation.constants.UpperParamKey; import net.northking.cctp.upperComputer.automation.entity.CmdAutomationRequest; @@ -20,6 +23,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; +import org.springframework.util.CollectionUtils; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; @@ -30,6 +34,7 @@ import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.xpath.*; +import java.io.File; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -381,12 +386,41 @@ public class HarmonyAutomationHandler extends AbstractAutomationHandler { @Override public void getVerificationCodeByNode(CmdAutomationRequest request) { - - } - - @Override - public void getVerificationCodeByOcr(CmdAutomationRequest request) { - + CmdAutomationResponse response = CmdAutomationResponse.builderSuccess(request, "根据ui节点获取验证码失败").withData(null); + try { + String value = null; + String targetBase64 = ""; + NodeList nodeList = findElementByXml(request); + if (null == nodeList || nodeList.getLength() <= 0 ) { + response = CmdAutomationResponse.builderSuccess(request, "验证码元素不存在").withData(null); + } else { + Element item = (Element) nodeList.item(0); + Integer width = Integer.parseInt(item.getAttribute("width")); + Integer height = Integer.parseInt(item.getAttribute("height")); + Integer realityX = Integer.parseInt(item.getAttribute("x")); + Integer realityY = Integer.parseInt(item.getAttribute("y")); + logger.debug("设备:{},步骤:{}找到验证码元素->x:{},y:{},width:{},height:{}",this.serial,request.getStepToken(),realityX,realityY,width,height); + File screenShotFile = deviceHandleHelper.getScreenShotFile(this.serial, realityX, realityY, width, height); + targetBase64 = Base64.encode(screenShotFile); + } + if (StringUtils.isBlank(targetBase64)) { + response = CmdAutomationResponse.builderSuccess(request, "未获取到ocr区域").withData(null); + return; + } + Map data = request.getData(); + Integer codeType = (Integer) data.get(UpperParamKey.CODE_TYPE); + value = ocrHelper.getVerificationCodeByBase64(targetBase64, codeType); + if (StringUtils.isNotBlank(value)) { + response = CmdAutomationResponse.builderSuccess(request, "根据ocr获取控件值成功").withData(value); + } else { + response = CmdAutomationResponse.builderSuccess(request, "根据ocr获取控件值失败").withData(null); + } + } catch (Exception e) { + logger.error("根据ocr获取验证码失败,原因:", e); + response = CmdAutomationResponse.builderSuccess(request, e.getMessage()).withData(null); + } finally { + sendResultToEngine(response); + } } @Override @@ -674,6 +708,10 @@ public class HarmonyAutomationHandler extends AbstractAutomationHandler { CmdAutomationResponse response = CmdAutomationResponse.builderFailure(request, "点击home键失败").withData(false); try { HarmonyProvider harmonyProvider = getHarmonyProvider(); + if (null == harmonyProvider) { + response = CmdAutomationResponse.builderFailure(request, "设备与上位机连接断开"); + return; + } boolean success = harmonyProvider.pressHome(); if (success) { response = CmdAutomationResponse.builderSuccess(request, "点击home键成功").withData(true); @@ -688,18 +726,184 @@ public class HarmonyAutomationHandler extends AbstractAutomationHandler { } } + @Override + public void pressBack(CmdAutomationRequest request) { + CmdAutomationResponse response = CmdAutomationResponse.builderFailure(request, "点击返回键失败").withData(false); + try { + HarmonyProvider harmonyProvider = getHarmonyProvider(); + if (null == harmonyProvider) { + response = CmdAutomationResponse.builderFailure(request, "设备与上位机连接断开"); + return; + } + boolean success = harmonyProvider.pressBack(); + if (success) { + response = CmdAutomationResponse.builderSuccess(request, "点击返回键成功").withData(true); + } else { + response = CmdAutomationResponse.builderFailure(request, "点击返回键失败"); + } + } catch (Exception e) { + logger.error("点击返回键失败,原因:", e); + response = CmdAutomationResponse.builderFailure(request, e.getMessage()); + } finally { + sendResultToEngine(response); + } + } + @Override + public void pressAppSwitch(CmdAutomationRequest request) { + CmdAutomationResponse response = CmdAutomationResponse.builderFailure(request, "点击多任务键失败").withData(false); + try { + HarmonyProvider harmonyProvider = getHarmonyProvider(); + if (null == harmonyProvider) { + response = CmdAutomationResponse.builderFailure(request, "设备与上位机连接断开"); + return; + } + int height = this.screenInfo.getHeight(); + harmonyProvider.touchDown(200, height-10); + Thread.sleep(200); + for (float i = 0.01f; i <= 1; i +=0.01) { + Float y = height - 10 - i * 300; + harmonyProvider.touchMove(200, y.intValue()); + Thread.sleep(5); + } + Thread.sleep(200); + boolean success = harmonyProvider.touchUp(200, height - 10 - 300); + if (success) { + response = CmdAutomationResponse.builderSuccess(request, "点击多任务键成功").withData(true); + } else { + response = CmdAutomationResponse.builderFailure(request, "点击多任务键失败"); + } + } catch (Exception e) { + logger.error("点击多任务键失败,原因:", e); + response = CmdAutomationResponse.builderFailure(request, e.getMessage()); + } finally { + sendResultToEngine(response); + } + } @Override public void pressAndSwipe(CmdAutomationRequest request) { - + CmdAutomationResponse response = CmdAutomationResponse.builderFailure(request, "滑动解锁失败").withData(false); + boolean success = false; + Map data = request.getData(); + try { + String[] pointXpath = new String[3]; + JSONObject xpathObject = JSON.parseObject((String) data.get(UpperParamKey.FIRST_POINT), JSONObject.class); + pointXpath[0] = xpathObject.getString("selector"); + xpathObject = JSON.parseObject((String) data.get(UpperParamKey.SECOND_POINT), JSONObject.class); + pointXpath[1] = xpathObject.getString("selector"); + xpathObject = JSON.parseObject((String) data.get(UpperParamKey.THIRD_POINT), JSONObject.class); + pointXpath[2] = xpathObject.getString("selector"); + Integer num = (Integer) data.get(UpperParamKey.POINT_NUM); + List passPoint = (List) data.get(UpperParamKey.SWIPE_POINT); + Integer waitTimeOut = (Integer) data.get(UpperParamKey.WAIT_TIMEOUT); + logger.debug("拿到的左上角的点:{}", pointXpath[0]); + logger.debug("拿到的左上角的右边点:{}", pointXpath[1]); + logger.debug("拿到的左上角的下边点:{}", pointXpath[2]); + logger.debug("拿到的每行每列的点数:{}", num); + logger.debug("拿到的经过的点:{}", JSON.toJSONString(passPoint)); + long startTime = System.currentTimeMillis(); + long endTime = startTime; + logger.debug("步骤:{}开始查找控件,超时时间:{}", request.getStepToken(), waitTimeOut); + Map[] point = new Map[3]; + int index = 0; + int findIndex = 1; + HarmonyProvider harmonyProvider = getHarmonyProvider(); + if (null == harmonyProvider) { + response = CmdAutomationResponse.builderFailure(request, "设备与上位机连接断开"); + return; + } + NodeList nodeList = null; + do { + UiComponent uiComponent = harmonyProvider.captureLayout(); + Document document = builder.newDocument(); + Node xmlElement = uiComponent.createXMLElement(document); + document.appendChild(xmlElement); + try { + nodeList = findNode(pointXpath[index], document); + } catch (XPathExpressionException e) { + logger.error("步骤:{},xpath格式不对:{}",request.getStepToken(),pointXpath[index]); + } + logger.debug("步骤:{},第{}次开始查找第{}个元素", request.getStepToken(), findIndex, index + 1); + endTime = System.currentTimeMillis(); + findIndex++; + if (null != nodeList) { + Element node = (Element) nodeList.item(0); + logger.debug("步骤:{},第{}次开始查找第{}个元素已经找到", request.getStepToken(), findIndex, index + 1); + int x = Integer.parseInt(node.getAttribute("x")); + int y = Integer.parseInt(node.getAttribute("y")); + Integer width = Integer.parseInt(node.getAttribute("width")); + Integer height = Integer.parseInt(node.getAttribute("height")); + Map perPoint = new HashMap<>(); + perPoint.put("x", x + width / 2); + perPoint.put("y", y + height / 2); + point[index] = perPoint; + index++; + findIndex = 1; + } + } while ((endTime - startTime) < waitTimeOut * 1000 && index < 3); + for (int i = 0; i < 3; i++) { + if (point[i] == null) { + response = CmdAutomationResponse.builderFailure(request, "定位解锁区域的点不全").withData(false); + return; + } + } + //计算每个点的坐标 + int perWidth = point[1].get("x") - point[0].get("x"); + int perHeight = point[2].get("y") - point[0].get("y"); + List> pointList = new ArrayList<>(); + int n = 1; + for (int i = 0; i < num; i++) { + int pointY = point[0].get("y") + i * perHeight; //每一行的y坐标 + for (int j = 0; j < num; j++) { + int pointX = point[0].get("x") + j * perWidth; + logger.info("第{}个点的坐标x:{},y:{}", n, pointX, pointY); + Map perPoint = new HashMap<>(); + perPoint.put("x", pointX); + perPoint.put("y", pointY); + pointList.add(n - 1, perPoint); + n++; + } + } + logger.info("token:{},滑动解锁的所有坐标集合:{}", request.getStepToken(), JSON.toJSONString(pointList)); + //开始滑动 + if (!CollectionUtils.isEmpty(passPoint)) { + Integer startIndex = passPoint.get(0); + Map startPoint = pointList.get(startIndex - 1); + harmonyProvider.touchDown(startPoint.get("x"), startPoint.get("y")); + for (int i = 1; i < passPoint.size(); i++) { + try { + Thread.sleep(200); + } catch (InterruptedException e) { + return; + } + Integer passIndex = passPoint.get(i); + Map pointMessage = pointList.get(passIndex - 1); + harmonyProvider.touchMove(pointMessage.get("x"), pointMessage.get("y")); + } + try { + Thread.sleep(200); + } catch (InterruptedException e) { + return; + } + Integer endIndex = passPoint.get(passPoint.size() - 1); + Map endPoint = pointList.get(endIndex - 1); + success = harmonyProvider.touchUp(endPoint.get("x"), endPoint.get("y")); + } else { + logger.warn("token:{},没有滑动通过的坐标", request.getStepToken()); + } + logger.info("token:{},滑动解锁的结果:{}", request.getStepToken(), success); + if (success) { + response = CmdAutomationResponse.builderSuccess(request, "滑动解锁成功").withData(success); + } else { + response = CmdAutomationResponse.builderFailure(request, "滑动解锁失败").withData(success); + } + } finally { + sendResultToEngine(response); + } } - @Override - public void getTextDirectionText(CmdAutomationRequest request) { - - } @Override public void inputPasswordByOcr(CmdAutomationRequest request) { @@ -821,9 +1025,6 @@ public class HarmonyAutomationHandler extends AbstractAutomationHandler { private HarmonyProvider getHarmonyProvider() { HarmonyProvider provider = HarmonyDeviceManager.getInstance().getCurrentDeviceProvider(this.serial); - if (null == provider) { - throw new ExecuteException("当前设备已经掉线,请检查设备"); - } return provider; } @@ -902,11 +1103,14 @@ public class HarmonyAutomationHandler extends AbstractAutomationHandler { boolean alreadyFind = false; int screenIndex = 1; NodeList nodeList = null; + HarmonyProvider harmonyProvider = getHarmonyProvider(); + if (null == harmonyProvider) { + return null; + } while (!alreadyFind) { int findIndex = 1; do { logger.debug("步骤:{},第{}屏,第{}次开始查找元素", request.getStepToken(), screenIndex, findIndex); - HarmonyProvider harmonyProvider = getHarmonyProvider(); UiComponent uiComponent = harmonyProvider.captureLayout(); Document document = builder.newDocument(); Node xmlElement = uiComponent.createXMLElement(document); diff --git a/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/automation/handler/IosAutomationHandler.java b/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/automation/handler/IosAutomationHandler.java index fcfe44b..d1a86a9 100644 --- a/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/automation/handler/IosAutomationHandler.java +++ b/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/automation/handler/IosAutomationHandler.java @@ -1699,6 +1699,16 @@ public class IosAutomationHandler extends AbstractAutomationHandler { } + @Override + public void pressBack(CmdAutomationRequest request) { + + } + + @Override + public void pressAppSwitch(CmdAutomationRequest request) { + + } + @Override public void inputPasswordByOcr(CmdAutomationRequest request) { CmdAutomationResponse response = CmdAutomationResponse.builderFailure(request, "密码输入(ocr)失败").withData(false); diff --git a/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/webSocket/thread/HarmonyMessageHandlerThread.java b/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/webSocket/thread/HarmonyMessageHandlerThread.java index a83da6a..aa81133 100644 --- a/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/webSocket/thread/HarmonyMessageHandlerThread.java +++ b/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/webSocket/thread/HarmonyMessageHandlerThread.java @@ -243,7 +243,7 @@ public class HarmonyMessageHandlerThread extends AbstractMessageHandler{ success = harmonyProvider.pressHome(); break; case "appSwitch": - success = harmonyProvider.pressRecentApp(); + success = pressRecentApp(harmonyProvider); break; case "back": success = harmonyProvider.pressBack(); @@ -267,6 +267,24 @@ public class HarmonyMessageHandlerThread extends AbstractMessageHandler{ logger.warn("设备【{}】热键【{}】操控失败............................",this.serial,key); } } + private boolean pressRecentApp(HarmonyProvider harmonyProvider) { + boolean success = false; + int height = catchParam.getRealHeight(); + try { + harmonyProvider.touchDown(200, height-10); + Thread.sleep(200); + for (float i = 0.01f; i <= 1; i +=0.01) { + Float y = height - 10 - i * 300; + harmonyProvider.touchMove(200, y.intValue()); + Thread.sleep(5); + } + Thread.sleep(200); + success = harmonyProvider.touchUp(200, height - 10 - 300); + } catch (InterruptedException e) { + + } + return success; + } @Override public void inputType(CmdRequest request) { diff --git a/cctp-test-element/cctp-test-element-library/cctp-test-element-mobile-hnos/src/main/java/net/northking/cctp/element/mobile/hnos/keywords/HnosTools.java b/cctp-test-element/cctp-test-element-library/cctp-test-element-mobile-hnos/src/main/java/net/northking/cctp/element/mobile/hnos/keywords/HnosTools.java index 884ed9c..dc94858 100644 --- a/cctp-test-element/cctp-test-element-library/cctp-test-element-mobile-hnos/src/main/java/net/northking/cctp/element/mobile/hnos/keywords/HnosTools.java +++ b/cctp-test-element/cctp-test-element-library/cctp-test-element-mobile-hnos/src/main/java/net/northking/cctp/element/mobile/hnos/keywords/HnosTools.java @@ -601,5 +601,392 @@ public class HnosTools { return success; } + /** + *

if存在控件执行点击

+ * + * @param deviceDriver 设备驱动链接 + * @param targets 定位控件的信息 + * @param waitTimeout 默认超时时间 + * @param waitStatusStr 是否等待界面稳定 + * @param swipe 滑动方向 + * @param swipeCount 滑动次数 + * @param preExecuteWait 执行前等待 + * @param sufExecuteWait 执行后等待 + * @return + */ + @Keyword(alias = "if存在控件执行点击", category = "0", attributes = "7", commonlyUse = true) + @Return(name = "result", comment = "点击结果", type = DataType.BOOLEAN) + public boolean clickIfExistElement(IExecuteContext context, + @Argument(name = "__deviceDriver", scope = ParamScope.CONTEXT, comment = "设备连接", type = DataType.OBJECT) DeviceDriver deviceDriver, + @Argument(name = "targets", scope = ParamScope.STEP, comment = "控件位置", type = DataType.LIST, defaultDisplay = false) List targets, + @Argument(name = "timeout", scope = ParamScope.ARGS, comment = "默认超时时间", type = DataType.INTEGER, required = false, defaultValue = "30", defaultDisplay = false) Integer waitTimeout, + @Argument(name = "waitStatus", scope = ParamScope.ARGS, comment = "等待界面稳定", type = DataType.ENUM, enumValues = WhetherOrNotEnum.class, inputType = InputType.select, defaultValue = "1", defaultDisplay = false) String waitStatusStr, + @Argument(name = "swipe", scope = ParamScope.ARGS, comment = "滑动方向", type = DataType.ENUM, enumValues = SwipeDirection.class, required = false, defaultValue = "0", inputType = InputType.select, defaultDisplay = false) String swipe, + @Argument(name = "swipeCount", scope = ParamScope.ARGS, comment = "滑动次数", type = DataType.INTEGER, required = false, defaultValue = "0", defaultDisplay = false) Integer swipeCount, +// @Argument(name = "xMove", scope = ParamScope.ARGS, comment = "水平偏移量", type = DataType.INTEGER, required = false, defaultValue = "0", defaultDisplay = false) Integer xMove, +// @Argument(name = "yMove", scope = ParamScope.ARGS, comment = "垂直偏移量", type = DataType.INTEGER, required = false, defaultValue = "0", defaultDisplay = false) Integer yMove, + @Argument(name = "preExecuteWait", scope = ParamScope.ARGS, comment = "执行前等待(单位:s)", type = DataType.INTEGER, required = false, defaultValue = "0.0", defaultDisplay = false) Float preExecuteWait, + @Argument(name = "sufExecuteWait", scope = ParamScope.ARGS, comment = "执行后等待(单位:s)", type = DataType.INTEGER, required = false, defaultValue = "0.0", defaultDisplay = false) Float sufExecuteWait, + @Argument(name = "value", scope = ParamScope.OUTPUT, comment = "组件返回值", type = DataType.STRING, defaultValue = "", required = false) String value + ) { + // 前端如果不选择元素,抛出异常 + if (CollectionUtils.isEmpty(targets)) { + throw new ExecuteException("元素属性值为空!"); + } + Boolean success = false; + try { + CommonUtils.handlePreExecuteWait(preExecuteWait); //执行前等待 + boolean waitStatus = "1".equals(waitStatusStr); //是否等待界面稳定 + ElementHandleParam param = ElementHandleParam.builder(deviceDriver) + .useContext(context) + .withTargets(targets) + .waitTimeout(waitTimeout) + .searchSwipeDirection(swipe) + .withSwipeCount(swipeCount) + .waitStatus(waitStatus); + success = AutomationHandleUtil.clickElement(param); + CommonUtils.handleSufExecuteWait(sufExecuteWait); //执行后等待 + } catch (InterruptedException ie) { + logger.warn("用户取消查询元素"); + throw new ExecuteException("取消操作"); + } catch (Exception e) { + logger.error("出现了其他的问题。。。。", e); + } + if (success != null && !StringUtils.isEmpty(value)) { + CommonUtils.setParamValue(context,value,success.toString()); + } + return success; + } + + /** + *

if存在控件执行输入文本

+ * + * @param text 输入的文本 + * @param cleanStr 是否清空文本框0-否,1-是 + * @param deviceDriver 设备连接驱动 + * @param targets 定位控件参数 + * @param waitTimeout 超时时间 + * @param waitStatusStr 是否等待屏幕稳定 + * @param swipe 是否滑屏查找控件0-否,up-上滑,down-下滑,left-左滑,right-右滑 + * @param swipeCount 滑屏次数 + * @param preExecuteWait 执行前等待 + * @param sufExecuteWait 执行后等待 + * @return + */ + @Keyword(alias = "if存在控件执行输入文本", category = "0", attributes = "7", commonlyUse = true) + @Return(name = "result", comment = "输入的结果", type = DataType.BOOLEAN) + public boolean inputIfExistElement(IExecuteContext context, + @Argument(name = "text", scope = ParamScope.VARIABLES, comment = "输入的文本", type = DataType.STRING) String text, + @Argument(name = "clean", scope = ParamScope.ARGS, comment = "是否清空输入框", type = DataType.ENUM, enumValues = WhetherOrNotEnum.class, inputType = InputType.select, defaultValue = "1", defaultDisplay = false) String cleanStr, + @Argument(name = "__deviceDriver", scope = ParamScope.CONTEXT, comment = "设备连接", type = DataType.OBJECT) DeviceDriver deviceDriver, + @Argument(name = "targets", scope = ParamScope.STEP, comment = "控件位置", type = DataType.LIST, defaultDisplay = false) List targets, + @Argument(name = "timeout", scope = ParamScope.ARGS, comment = "默认超时时间", type = DataType.INTEGER, required = false, defaultValue = "30", defaultDisplay = false) Integer waitTimeout, + @Argument(name = "waitStatus", scope = ParamScope.ARGS, comment = "等待界面稳定", type = DataType.ENUM, enumValues = WhetherOrNotEnum.class, inputType = InputType.select, defaultValue = "1", defaultDisplay = false) String waitStatusStr, + @Argument(name = "swipe", scope = ParamScope.ARGS, comment = "滑动方向", type = DataType.ENUM, enumValues = SwipeDirection.class, inputType = InputType.select, defaultValue = "0", required = false, defaultDisplay = false) String swipe, + @Argument(name = "swipeCount", scope = ParamScope.ARGS, comment = "滑动次数", type = DataType.INTEGER, required = false, defaultValue = "0", defaultDisplay = false) Integer swipeCount, + @Argument(name = "preExecuteWait", scope = ParamScope.ARGS, comment = "执行前等待(单位:s)", type = DataType.INTEGER, required = false, defaultValue = "1.0", defaultDisplay = false) Float preExecuteWait, + @Argument(name = "sufExecuteWait", scope = ParamScope.ARGS, comment = "执行后等待(单位:s)", type = DataType.INTEGER, required = false, defaultValue = "1.0", defaultDisplay = false) Float sufExecuteWait, + @Argument(name = "value", scope = ParamScope.OUTPUT, comment = "组件返回值", type = DataType.STRING, defaultValue = "", required = false) String value + ) { + // 前端如果不选择元素,抛出异常 + if (CollectionUtils.isEmpty(targets)) { + throw new ExecuteException("元素属性值为空!"); + } + Boolean success = false; + try { + CommonUtils.handlePreExecuteWait(preExecuteWait); //执行前等待 + boolean waitStatus = "1".equals(waitStatusStr); //是否等待界面稳定 + boolean clear = "1".equals(cleanStr); //是否清除文本框 + ElementHandleParam param = ElementHandleParam.builder(deviceDriver) + .useContext(context) + .withTargets(targets) + .waitTimeout(waitTimeout) + .searchSwipeDirection(swipe) + .withSwipeCount(swipeCount) + .clear(clear) + .withInputTextValue(text) + .waitStatus(waitStatus); + success = AutomationHandleUtil.elementInput(param); + CommonUtils.handleSufExecuteWait(sufExecuteWait); //执行后等待 + } catch (InterruptedException ie) { + logger.warn("用户取消查询元素"); + throw new ExecuteException("取消操作"); + } catch (Exception e) { + logger.error("出现了其他的问题。。。。", e); + } + if (success != null && !StringUtils.isEmpty(value)) { + CommonUtils.setParamValue(context,value,success.toString()); + } + return success; + } + + /** + * 滑动查找控件 + * @param context + * @param direction + * @param deviceDriver + * @param targets + * @param referencesStr + * @param waitTimeout + * @param index + * @param waitStatusStr + * @param value + * @param preExecuteWait + * @param sufExecuteWait + * @return + */ + @Keyword(alias = "滑动查找控件", category = "0", attributes = "7",commonlyUse = true) + @Return(name = "result", comment = "滑动的结果", type = DataType.OBJECT) + public boolean swipeAndFindTargetElement(IExecuteContext context, + @Argument(name = "direction", scope = ParamScope.ARGS, comment = "控件滑动方向", type = DataType.ENUM, enumValues = SwipeDirection.class, inputType = InputType.select, defaultValue = "up") String direction, + @Argument(name = "__deviceDriver", scope = ParamScope.CONTEXT, comment = "设备连接", type = DataType.OBJECT) DeviceDriver deviceDriver, + @Argument(name = "targets", scope = ParamScope.STEP, comment = "目标元素", type = DataType.LIST, defaultDisplay = false,inputType = InputType.element) List targets, + @Argument(name = "references", scope = ParamScope.ARGS, comment = "滑动元素", type = DataType.LIST, defaultDisplay = false, required = false,inputType = InputType.element) String referencesStr, + @Argument(name = "timeout", scope = ParamScope.ARGS, comment = "默认超时时间", type = DataType.INTEGER, required = false, defaultValue = "30", defaultDisplay = false) Integer waitTimeout, + @Argument(name = "index", scope = ParamScope.ARGS, comment = "多个时定位第几个", type = DataType.INTEGER, defaultValue = "1",defaultDisplay = false) Integer index, + @Argument(name = "waitStatus", scope = ParamScope.ARGS, comment = "等待界面稳定", type = DataType.ENUM, enumValues = WhetherOrNotEnum.class, inputType = InputType.select, defaultValue = "1", defaultDisplay = false) String waitStatusStr, + @Argument(name = "value", scope = ParamScope.OUTPUT, comment = "组件返回值",required = false, type = DataType.STRING, defaultValue = "") String value, + @Argument(name = "preExecuteWait", scope = ParamScope.ARGS, comment = "执行前等待(单位:s)", type = DataType.INTEGER, required = false, defaultValue = "1.0", defaultDisplay = false) Float preExecuteWait, + @Argument(name = "sufExecuteWait", scope = ParamScope.ARGS, comment = "执行后等待(单位:s)", type = DataType.INTEGER, required = false, defaultValue = "1.0", defaultDisplay = false) Float sufExecuteWait) { + logger.debug("拿到的reference为:{}",referencesStr); + Boolean result = null; + try { + CommonUtils.handlePreExecuteWait(preExecuteWait); //执行前等待 + boolean waitStatus = "1".equals(waitStatusStr); //是否等待界面稳定 + ElementHandleParam param = ElementHandleParam.builder(deviceDriver) + .useContext(context) + .withTargets(targets) + .waitTimeout(waitTimeout) + .searchSwipeDirection("0") //不滑动 + .withSwipeCount(1) + .waitStatus(waitStatus) + .swipeDirection(direction) + .withIndex(index) + .withReferences(referencesStr); + result = AutomationHandleUtil.swipeAndFindTargetElement(param); + CommonUtils.handleSufExecuteWait(sufExecuteWait); //执行后等待 + if (result != null && !StringUtils.isEmpty(value)) { + CommonUtils.setParamValue(context,value,result.toString()); + } + } catch (InterruptedException ie) { + logger.warn("用户取消查询元素"); + throw new ExecuteException("取消操作"); + } catch (Exception e) { + logger.error("出现了其他的问题。。。。", e); + throw new ExecuteException(e.getMessage()); + } + return result; + } + + /** + *

滑动解锁

+ * + * @param context 上下文 + * @param deviceDriver 设备连接 + * @param firstPointStr 左上角点 + * @param secondPointStr 左上角右边的点 + * @param thirdPointStr 左上角下面的点 + * @param pointNum 每一行、列的点数 + * @param passingPoints 经过的点,填[1,3,5,6]数组的形式 + * @param waitTime 等待时间 + * @param preExecuteWait 执行前等待 + * @param sufExecuteWait 执行后等待 + * @return + */ + @Keyword(alias = "滑动解锁", category = "0", attributes = "7", commonlyUse = true) + @Return(name = "result", comment = "是否滑动成功", type = DataType.BOOLEAN) + public Boolean pressAndSwipe( + IExecuteContext context, + @Argument(name = "__deviceDriver", scope = ParamScope.CONTEXT, comment = "设备连接", type = DataType.OBJECT) DeviceDriver deviceDriver, + @Argument(name = "firstPoint", scope = ParamScope.ARGS, comment = "第一排第一个点", type = DataType.LIST, defaultDisplay = true,inputType = InputType.element) String firstPointStr, + @Argument(name = "secondPoint", scope = ParamScope.ARGS, comment = "第一排第二个点", type = DataType.LIST, defaultDisplay = true,inputType = InputType.element) String secondPointStr, + @Argument(name = "thirdPoint", scope = ParamScope.ARGS, comment = "第二排第一个点", type = DataType.LIST, defaultDisplay = true,inputType = InputType.element) String thirdPointStr, + @Argument(name = "pointNum", scope = ParamScope.ARGS, comment = "每一行、列的点数", type = DataType.INTEGER, defaultDisplay = false,defaultValue = "3") Integer pointNum, + @Argument(name = "passingPoints", scope = ParamScope.ARGS, comment = "经过的点", type = DataType.LIST, defaultDisplay = true) List passingPoints, + @Argument(name = "waitTime", scope = ParamScope.ARGS, comment = "等待时间(单位s)", type = DataType.INTEGER, defaultValue = "30") Integer waitTime, + @Argument(name = "preExecuteWait", scope = ParamScope.ARGS, comment = "执行前等待(单位:s)", type = DataType.INTEGER, required = false, defaultValue = "1.0", defaultDisplay = false) Float preExecuteWait, + @Argument(name = "sufExecuteWait", scope = ParamScope.ARGS, comment = "执行后等待(单位:s)", type = DataType.INTEGER, required = false, defaultValue = "1.0", defaultDisplay = false) Float sufExecuteWait + + ) { + Boolean result = false; + try { + CommonUtils.handlePreExecuteWait(preExecuteWait); //执行前等待 + ElementHandleParam param = ElementHandleParam.builder(deviceDriver) + .useContext(context) + .waitTimeout(waitTime) + .withPassingPoints(passingPoints) + .withPointData(firstPointStr, secondPointStr, thirdPointStr) + .withPointNum(pointNum); + result = AutomationHandleUtil.pressAndSwipe(param); + CommonUtils.handleSufExecuteWait(sufExecuteWait); //执行后等待 + } catch (InterruptedException ie) { + logger.warn("用户取消查询元素"); + throw new ExecuteException("取消操作"); + } catch (Exception e) { + logger.error("出现了其他的问题。。。。", e); + throw new ExecuteException(e.getMessage()); + } + return result; + } + + /** + *

获取指定文字指定方向的内容

+ * + * @param direction 滑动方向 + * @param deviceDriver 设备驱动 + * @param waitTimeout 默认超时时间 + * @param text 指定文本 + * @param direction 指定方向 + * @param preExecuteWait 执行前等待 + * @param sufExecuteWait 执行后等待 + * @return + */ + @Keyword(alias = "获取指定文字指定方向的内容", category = "0", attributes = "7") + @Return(name = "result", comment = "返回的结果", type = DataType.BOOLEAN) + public String getTextDirectionText(IExecuteContext context, + @Argument(name = "__deviceDriver", scope = ParamScope.CONTEXT, comment = "设备连接", type = DataType.OBJECT) DeviceDriver deviceDriver, + @Argument(name = "timeout", scope = ParamScope.ARGS, comment = "默认超时时间", type = DataType.INTEGER, required = false, defaultValue = "30", defaultDisplay = false) Integer waitTimeout, + @Argument(name = "index", scope = ParamScope.ARGS, comment = "第几个", type = DataType.INTEGER, defaultValue = "1") Integer index, + @Argument(name = "text", comment = "指定文本", scope = ParamScope.ARGS, type = DataType.STRING) String text, + @Argument(name = "direction", scope = ParamScope.ARGS, comment = "指定方向", type = DataType.ENUM, enumValues = TextDirection.class, inputType = InputType.select, defaultValue = "右") String direction, + @Argument(name = "value", scope = ParamScope.OUTPUT, comment = "组件返回值", type = DataType.STRING, defaultValue = "") String value, + @Argument(name = "preExecuteWait", scope = ParamScope.ARGS, comment = "执行前等待(单位:s)", type = DataType.INTEGER, required = false, defaultValue = "1.0", defaultDisplay = false) Float preExecuteWait, + @Argument(name = "sufExecuteWait", scope = ParamScope.ARGS, comment = "执行后等待(单位:s)", type = DataType.INTEGER, required = false, defaultValue = "1.0", defaultDisplay = false) Float sufExecuteWait) { + String result = ""; + try { + CommonUtils.handlePreExecuteWait(preExecuteWait); //执行前等待 + ElementHandleParam param = ElementHandleParam.builder(deviceDriver) + .useContext(context) + .withText(text) + .withIndex(index) + .waitTimeout(waitTimeout) + .withDirection(direction); + result = AutomationHandleUtil.getTextDirectionText(param); + CommonUtils.handleSufExecuteWait(sufExecuteWait); //执行后等待 + CommonUtils.setParamValue(context, value, result); + } catch (InterruptedException ie) { + logger.warn("用户取消查询元素"); + throw new ExecuteException("取消操作"); + } catch (Exception e) { + logger.error("出现了其他的问题。。。。", e); + throw new ExecuteException(e.getMessage()); + } + return result; + } + + /** + *

识别验证码

+ * + * @param deviceDriver 设备连接驱动 + * @param targets 定位元素参数 + * @param waitTimeout 等待超时时间 + * @param value 赋值变量 + * @param preExecuteWait 执行前等待 + * @param sufExecuteWait 执行后等待 + * @return + */ + @Keyword(alias = "识别验证码", category = "0", attributes = "7") + @Return(name = "result", comment = "验证码识别", type = DataType.STRING) + public String getCodeByOcr( + IExecuteContext context, + @Argument(name = "__deviceDriver", scope = ParamScope.CONTEXT, comment = "设备连接", type = DataType.OBJECT) DeviceDriver deviceDriver, + @Argument(name = "targets", scope = ParamScope.STEP, comment = "控件位置", type = DataType.LIST, defaultDisplay = false) List targets, + @Argument(name = "codeType", scope = ParamScope.ARGS, comment = "验证码类型", type = DataType.INTEGER, required = false, defaultValue = "1", defaultDisplay = false) Integer codeType, + @Argument(name = "timeout", scope = ParamScope.ARGS, comment = "默认超时时间", type = DataType.INTEGER, required = false, defaultValue = "30", defaultDisplay = false) Integer waitTimeout, + @Argument(name = "value", scope = ParamScope.OUTPUT, comment = "组件返回值", type = DataType.STRING, defaultValue = "") String value, + @Argument(name = "waitStatus", scope = ParamScope.ARGS, comment = "等待界面稳定", type = DataType.ENUM, enumValues = WhetherOrNotEnum.class, inputType = InputType.select, defaultValue = "1", defaultDisplay = false) String waitStatusStr, + @Argument(name = "preExecuteWait", scope = ParamScope.ARGS, comment = "执行前等待(单位:s)", type = DataType.INTEGER, required = false, defaultValue = "1.0", defaultDisplay = false) Float preExecuteWait, + @Argument(name = "sufExecuteWait", scope = ParamScope.ARGS, comment = "执行后等待(单位:s)", type = DataType.INTEGER, required = false, defaultValue = "1.0", defaultDisplay = false) Float sufExecuteWait + + ) { + String result = ""; + try { + CommonUtils.handlePreExecuteWait(preExecuteWait); //执行前等待 + boolean waitStatus = "1".equals(waitStatusStr); //是否等待界面稳定 + ElementHandleParam param = ElementHandleParam.builder(deviceDriver) + .useContext(context) + .withTargets(targets) + .waitTimeout(waitTimeout) + .codeType(codeType) + .searchSwipeDirection("0") //不滑动 + .withSwipeCount(1) + .waitStatus(waitStatus); + result = AutomationHandleUtil.getVerificationCode(param); + CommonUtils.handleSufExecuteWait(sufExecuteWait); //执行后等待 + CommonUtils.setParamValue(context, value, result); + } catch (InterruptedException ie) { + logger.warn("用户取消查询元素"); + throw new ExecuteException("取消操作"); + } catch (Exception e) { + logger.error("出现了其他的问题。。。。", e); + throw new ExecuteException(e.getMessage()); + } + return result; + } + + /** + *

点击返回键

+ * + * @param deviceDriver 设备连接驱动 + * @param preExecuteWait 执行前等待 + * @param sufExecuteWait 执行后等待 + * @return + */ + @Keyword(alias = "点击返回键", category = "0", attributes = "7", commonlyUse = true) + @Return(name = "result", comment = "点击返回键", type = DataType.BOOLEAN) + public boolean pressKeyBack(IExecuteContext context, + @Argument(name = "__deviceDriver", scope = ParamScope.CONTEXT, comment = "设备连接", type = DataType.OBJECT) DeviceDriver deviceDriver, + @Argument(name = "preExecuteWait", scope = ParamScope.ARGS, comment = "执行前等待(单位:s)", type = DataType.INTEGER, required = false, defaultValue = "0.0", defaultDisplay = false) Float preExecuteWait, + @Argument(name = "sufExecuteWait", scope = ParamScope.ARGS, comment = "执行后等待(单位:s)", type = DataType.INTEGER, required = false, defaultValue = "0.0", defaultDisplay = false) Float sufExecuteWait) { + boolean success = false; + try { + CommonUtils.handlePreExecuteWait(preExecuteWait); //执行前等待 + ElementHandleParam param = ElementHandleParam.builder(deviceDriver) + .useContext(context) + .waitTimeout(30); + success = AutomationHandleUtil.pressBack(param); + CommonUtils.handleSufExecuteWait(sufExecuteWait); //执行后等待 + } catch (InterruptedException ie) { + logger.warn("用户取消查询元素"); + throw new ExecuteException("取消操作"); + } catch (Exception e) { + logger.error("出现了其他的问题。。。。", e); + throw new ExecuteException(e.getMessage()); + } + return success; + } + + /** + *

点击返回键

+ * + * @param deviceDriver 设备连接驱动 + * @param preExecuteWait 执行前等待 + * @param sufExecuteWait 执行后等待 + * @return + */ + @Keyword(alias = "点击多任务", category = "0", attributes = "7", commonlyUse = true) + @Return(name = "result", comment = "点击多任务", type = DataType.BOOLEAN) + public boolean pressKeyMenu(IExecuteContext context, + @Argument(name = "__deviceDriver", scope = ParamScope.CONTEXT, comment = "设备连接", type = DataType.OBJECT) DeviceDriver deviceDriver, + @Argument(name = "preExecuteWait", scope = ParamScope.ARGS, comment = "执行前等待(单位:s)", type = DataType.INTEGER, required = false, defaultValue = "0.0", defaultDisplay = false) Float preExecuteWait, + @Argument(name = "sufExecuteWait", scope = ParamScope.ARGS, comment = "执行后等待(单位:s)", type = DataType.INTEGER, required = false, defaultValue = "0.0", defaultDisplay = false) Float sufExecuteWait) { + boolean success = false; + try { + CommonUtils.handlePreExecuteWait(preExecuteWait); //执行前等待 + ElementHandleParam param = ElementHandleParam.builder(deviceDriver) + .useContext(context) + .waitTimeout(30); + success = AutomationHandleUtil.pressAppSwitch(param); + CommonUtils.handleSufExecuteWait(sufExecuteWait); //执行后等待 + } catch (InterruptedException ie) { + logger.warn("用户取消查询元素"); + throw new ExecuteException("取消操作"); + } catch (Exception e) { + logger.error("出现了其他的问题。。。。", e); + throw new ExecuteException(e.getMessage()); + } + return success; + } + } diff --git a/cctp-test-element/cctp-test-element-library/cctp-test-element-mobile-hnos/src/main/java/net/northking/cctp/element/mobile/hnos/utils/AutomationHandleUtil.java b/cctp-test-element/cctp-test-element-library/cctp-test-element-mobile-hnos/src/main/java/net/northking/cctp/element/mobile/hnos/utils/AutomationHandleUtil.java index 30add8d..d382b02 100644 --- a/cctp-test-element/cctp-test-element-library/cctp-test-element-mobile-hnos/src/main/java/net/northking/cctp/element/mobile/hnos/utils/AutomationHandleUtil.java +++ b/cctp-test-element/cctp-test-element-library/cctp-test-element-mobile-hnos/src/main/java/net/northking/cctp/element/mobile/hnos/utils/AutomationHandleUtil.java @@ -428,6 +428,10 @@ public class AutomationHandleUtil { logger.warn("不支持的查找元素方式:{}", target.getUsing()); break; } + if (null != point) { + logger.debug("使用【{}】方式找到了控件",target.getUsing()); + break; + } } return point; } @@ -799,6 +803,30 @@ public class AutomationHandleUtil { return success; } + public static boolean pressBack(ElementHandleParam param) throws Exception { + Boolean success = false; + String token = UUID.randomUUID().toString(); + CmdAutomationRequest builder = CmdAutomationRequest.builder(AutomationRequestCmd.PRESS_BACK_KEY, token, new HashMap<>()); + Object o = sendUpperMessageAndWaitReturn(param.getDeviceDriver(), builder, token, param.getWaitTimeout()); + logger.debug("点击返回键的结果:{}",o); + if (null != o) { + success = JSONObject.parseObject(JSONObject.toJSONString(o), Boolean.class); + } + return success; + } + + public static boolean pressAppSwitch(ElementHandleParam param) throws Exception { + Boolean success = false; + String token = UUID.randomUUID().toString(); + CmdAutomationRequest builder = CmdAutomationRequest.builder(AutomationRequestCmd.PRESS_APP_SWITCH_KEY, token, new HashMap<>()); + Object o = sendUpperMessageAndWaitReturn(param.getDeviceDriver(), builder, token, param.getWaitTimeout()); + logger.debug("点击多任务键的结果:{}",o); + if (null != o) { + success = JSONObject.parseObject(JSONObject.toJSONString(o), Boolean.class); + } + return success; + } + private static boolean longPressElementByPoint(DeviceDriver deviceDriver, PointMessage point, Integer waitTimeout) throws Exception{ Boolean success = false; String token = UUID.randomUUID().toString(); @@ -1165,7 +1193,7 @@ public class AutomationHandleUtil { if (null == waitTimeout || waitTimeout <= 0) { param.setWaitTimeout(30); } - + long startTime = System.currentTimeMillis(); String referenceStr = param.getReferences(); logger.debug("执行滑动查找控件的操作,滑动控件:{}", referenceStr); PointMessage point = null; @@ -1182,22 +1210,28 @@ public class AutomationHandleUtil { } } logger.debug("找到要滑动的控件位置:{}",JSON.toJSONString(point)); - PointMessage targetPoint = swipeToFindTargetElement(point, param.getContext(), param.getDeviceDriver(), param.getTargets(), param.getWaitTimeout(), + long endTime = System.currentTimeMillis(); + long remainingTime = param.getWaitTimeout() * 1000 - (endTime - startTime); + PointMessage targetPoint = swipeToFindTargetElement(point, param.getContext(), param.getDeviceDriver(), param.getTargets(), remainingTime, param.getSwipeDirection(), param); getRedDotScreenShotWithPoint(param, point); return targetPoint != null; } - private static PointMessage swipeToFindTargetElement(PointMessage swipePoint, IExecuteContext context, DeviceDriver driver, List targets, Integer waitTimeout, String direction, ElementHandleParam param) throws Exception{ + private static PointMessage swipeToFindTargetElement(PointMessage swipePoint, IExecuteContext context, DeviceDriver driver, List targets, Long waitTimeout, String direction, ElementHandleParam param) throws Exception{ logger.debug("执行滑动查找控件的操作,目标控件:{}", JSON.toJSONString(targets)); long startTime = System.currentTimeMillis(); long endTime = System.currentTimeMillis(); PointMessage targetPoint = null; + Double perWaiTimeOut = waitTimeout.doubleValue() / 1000 / 5; + if (perWaiTimeOut < 3) { + perWaiTimeOut = 3.0; + } int num = 1; do { logger.debug("开始第{}次查找", num); try { - targetPoint = findElementByTargetsForSwipe(param.getDeviceDriver(), param.getTargets(), 30, param.getSwipe(), param.getSwipeCount(), 1); + targetPoint = findElementByTargetsForSwipe(param.getDeviceDriver(), param.getTargets(), perWaiTimeOut.intValue(), param.getSwipe(), param.getSwipeCount(), 1); } catch (Exception ignore) { logger.error(ignore.getMessage()); } @@ -1208,7 +1242,7 @@ public class AutomationHandleUtil { } num++; endTime = System.currentTimeMillis(); - } while (targetPoint == null && endTime - startTime < waitTimeout * 1000); + } while (targetPoint == null && endTime - startTime < waitTimeout); logger.debug("在规定的时间内查找的结果:{}", JSON.toJSONString(targetPoint)); return targetPoint; } @@ -1227,8 +1261,8 @@ public class AutomationHandleUtil { String token = UUID.randomUUID().toString(); Map paramMap = new HashMap<>(); if (swipePoint != null) { - Integer x = swipePoint.getXOriginal(); - Integer y = swipePoint.getYOriginal(); + Integer x = swipePoint.getX(); + Integer y = swipePoint.getY(); paramMap.put(UpperParamKey.X, x); paramMap.put(UpperParamKey.Y, y); paramMap.put(UpperParamKey.SWIPE_DIRECTION, direction);