harmony掉线agent会不停的启动、harmony计划、harmony断线重连不出现转圈的情况

hz_1122
yineng.huang 2025-05-15 11:51:57 +08:00
parent 16a86df98e
commit 974ef9cf1a
13 changed files with 179 additions and 58 deletions

View File

@ -2801,6 +2801,7 @@ public class AtuPlanInfoApiServiceImpl extends AbstractExcelService<AtuPlanInfo>
break;
case PlanConstant.SCRIPT_TYPE_ANDROID:
case PlanConstant.SCRIPT_TYPE_IOS:
case PlanConstant.SCRIPT_TYPE_HARMONY:
caseMap.put(MsgConstant.CASEMAP_HAS_MOB, true);
break;
case PlanConstant.SCRIPT_TYPE_SCENE:

View File

@ -290,6 +290,7 @@ public class AtuPlanTaskApiServiceImpl extends AbstractExcelService<AtuPlanTask>
break;
case PlanConstant.SCRIPT_TYPE_ANDROID:
case PlanConstant.SCRIPT_TYPE_IOS:
case PlanConstant.SCRIPT_TYPE_HARMONY:
node.setDeviceType(PlanConstant.DEVICE_TYPE_MOBILE);
break;
default:
@ -311,6 +312,7 @@ public class AtuPlanTaskApiServiceImpl extends AbstractExcelService<AtuPlanTask>
break;
case PlanConstant.SCRIPT_TYPE_ANDROID:
case PlanConstant.SCRIPT_TYPE_IOS:
case PlanConstant.SCRIPT_TYPE_HARMONY:
node.setDeviceType(PlanConstant.DEVICE_TYPE_MOBILE);
break;
}
@ -613,7 +615,8 @@ public class AtuPlanTaskApiServiceImpl extends AbstractExcelService<AtuPlanTask>
@Override
public String queryAppId(String planId, String platformType, String appPackage, String caseType) {
if (ObjectUtil.equal(PlanConstant.SCRIPT_TYPE_ANDROID, caseType)
|| ObjectUtil.equal(PlanConstant.SCRIPT_TYPE_IOS, caseType)) {
|| ObjectUtil.equal(PlanConstant.SCRIPT_TYPE_IOS, caseType)
|| ObjectUtil.equal(PlanConstant.SCRIPT_TYPE_HARMONY, caseType)) {
// 根据计划ID应用包名应用平台类型查询应用ID
AtuPlanAppLink planAppLink = new AtuPlanAppLink();
planAppLink.setPlanId(planId);
@ -841,6 +844,7 @@ public class AtuPlanTaskApiServiceImpl extends AbstractExcelService<AtuPlanTask>
break;
case PlanConstant.SCRIPT_TYPE_ANDROID:
case PlanConstant.SCRIPT_TYPE_IOS:
case PlanConstant.SCRIPT_TYPE_HARMONY:
node.setDeviceType(PlanConstant.DEVICE_TYPE_MOBILE);
break;
}
@ -860,6 +864,7 @@ public class AtuPlanTaskApiServiceImpl extends AbstractExcelService<AtuPlanTask>
break;
case PlanConstant.SCRIPT_TYPE_ANDROID:
case PlanConstant.SCRIPT_TYPE_IOS:
case PlanConstant.SCRIPT_TYPE_HARMONY:
node.setDeviceType(PlanConstant.DEVICE_TYPE_MOBILE);
break;
}
@ -1275,6 +1280,9 @@ public class AtuPlanTaskApiServiceImpl extends AbstractExcelService<AtuPlanTask>
case PlanConstant.SCRIPT_TYPE_IOS:
queueName = RabbitConstant.TASK_EXEC_QUEUE_MOB_KEY + MsgConstant.IOS + "." + batchId;
break;
case PlanConstant.SCRIPT_TYPE_HARMONY:
queueName = RabbitConstant.TASK_EXEC_QUEUE_MOB_KEY + MsgConstant.HARMONY + "." + batchId;
break;
default:
break;
}

View File

@ -236,6 +236,7 @@ public class MsgConstant {
public static final String FILEPATH= "filePath";
public static final String ANDROID= "android";
public static final String IOS= "ios";
public static final String HARMONY= "harmony";
public static final String EMPTY= "无";
public static final String OUTPUT = "output";

View File

@ -26,7 +26,7 @@ public class PlanConstant {
public static final String SCRIPT_TYPE_ANDROID = "3";
public static final String SCRIPT_TYPE_IOS = "4";
public static final String SCRIPT_TYPE_SCENE = "5";
public static final String SCRIPT_TYPE_HARMONY = "6";
/**
* id key
*/

View File

@ -12,8 +12,8 @@ package net.northking.cctp.executePlan.enums;
public enum MobilePlatformEnum {
ANDROID("0", "android"),
IOS("1", "ios");
IOS("1", "ios"),
HARMONY("2", "harmony");
private String type;
private String name;

View File

@ -17,7 +17,6 @@ import org.slf4j.LoggerFactory;
import javax.websocket.Session;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
@ -39,7 +38,7 @@ public class HarmonyDeviceManager extends AbstractDeviceManager {
private static HarmonyDeviceManager instance;
public static HarmonyDeviceManager getInstance() {
public synchronized static HarmonyDeviceManager getInstance() {
if (instance == null) {
instance = new HarmonyDeviceManager();
}
@ -218,7 +217,6 @@ public class HarmonyDeviceManager extends AbstractDeviceManager {
if (!found) {
if (hdcDevice.getConnectStatus() == HDCConnectStatus.CONNECTED) {
HarmonyDevice device = new HarmonyDevice(hdcDevice);
device.enableTestMode();
ableDevice.add(device);
} else {
lostDevice.add(new HarmonyDevice(hdcDevice));
@ -238,7 +236,7 @@ public class HarmonyDeviceManager extends AbstractDeviceManager {
if (device.getHdcDevice().getConnectStatus() == HDCConnectStatus.CONNECTED) {
lostDevice.add(device);
} else if (hdcDevice.getConnectStatus() == HDCConnectStatus.CONNECTED) {
device.enableTestMode();
log.info("设备【{}】又重新上线了",hdcDevice.getConnectKey());
ableDevice.add(device);
}
}
@ -253,22 +251,36 @@ public class HarmonyDeviceManager extends AbstractDeviceManager {
}
}
for (HarmonyDevice device : ableDevice) {
onLineHarmonyDevice(device);
log.debug("开始设置手机【{}】测试模式.......",device.getHdcDevice().getConnectKey());
try {
device.enableTestMode();
} catch (Exception e) {
log.warn("设备【{}】设置开发模式出错",device.getHdcDevice().getConnectKey());
device.getHdcDevice().setConnectStatus(HDCConnectStatus.OFFLINE);
continue;
}
log.debug("完成设置手机【{}】测试模式.......",device.getHdcDevice().getConnectKey());
boolean success = onLineHarmonyDevice(device);
if (!success){
log.warn("设备【{}】agent初始化失败,下一次重新初始化......",device.getHdcDevice().getConnectKey());
device.getHdcDevice().setConnectStatus(HDCConnectStatus.OFFLINE);
lostDevice.add(device);
}
}
for (HarmonyDevice device : lostDevice) {
offlineDevice(device.getHdcDevice().getConnectKey());
}
}
private void onLineHarmonyDevice(HarmonyDevice device) {
private boolean onLineHarmonyDevice(HarmonyDevice device) {
HDCDevice hdcDevice = device.getHdcDevice();
log.info("新上来设备:{}", JSON.toJSONString(hdcDevice));
HarmonyProvider harmonyProvider = null;
try {
harmonyProvider = new HarmonyProvider(device);
} catch (IOException e) {
} catch (Exception e) {
log.error("启动设备【{}】上的agent程序失败",hdcDevice.getConnectKey(),e);
return;
return false;
}
log.info("设备【{}】的初始化环境准备完成",hdcDevice.getConnectKey());
onlineDeviceInitMap.put(hdcDevice.getConnectKey(), harmonyProvider);
@ -280,6 +292,7 @@ public class HarmonyDeviceManager extends AbstractDeviceManager {
screenInfo.setRotation(displayRotation);
setScreenInfo(hdcDevice.getConnectKey(),screenInfo);
publishDeviceOnlineToWebConnection(hdcDevice.getConnectKey());
return true;
}
@Override

View File

@ -141,4 +141,14 @@ public abstract class ImageScreenResponse extends Thread{
}
public abstract void stopFetchPic();
public void noticeToWebScreenDisconnect() {
Map<String, Object> messageMap = new HashMap<>();
messageMap.put(ResponseCmd.DeviceStatus.STATUS, ResponseCmd.DeviceStatus.CONNECTING);
for (Session webSession : webSessions) {
if (webSession.isOpen()) {
SessionUtils.sendMessageInitiative(webSession, ResponseCmd.DEVICE_STATUS, this.deviceId, messageMap, "设备掉线了");
}
}
}
}

View File

@ -9,6 +9,7 @@ import net.northking.cctp.upperComputer.driver.harmony.hdc.HDCConnectStatus;
import net.northking.cctp.upperComputer.driver.harmony.hyppium.HyppiumAgent;
import net.northking.cctp.upperComputer.driver.harmony.hyppium.data.DisplaySize;
import net.northking.cctp.upperComputer.driver.harmony.ui.UiComponent;
import net.northking.cctp.upperComputer.exception.ExecuteException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -84,7 +85,7 @@ public class HarmonyProvider implements Closeable,InitDevice {
/**
* @param harmonyDevice 鸿
*/
public HarmonyProvider(HarmonyDevice harmonyDevice) throws IOException {
public HarmonyProvider(HarmonyDevice harmonyDevice) throws Exception {
this.harmonyDevice = harmonyDevice;
this.requestScope = GLOBAL_PROVIDER_THREAD_SCOPE.createChildScope("hm-" + harmonyDevice.getHdcDevice().getConnectKey());
try {
@ -93,17 +94,28 @@ public class HarmonyProvider implements Closeable,InitDevice {
log.error("初始化设备{}的HyppiumAgent失败", harmonyDevice.getHdcDevice().getConnectKey(), e);
throw e;
}
log.debug("手机【{}】agent启动完成......",harmonyDevice.getHdcDevice().getConnectKey());
if (!createSession()) {
GLOBAL_PROVIDER_THREAD_SCOPE.launch((job) -> {
init();
}, RETRY_DELAY);
log.error("初始化设备{}的HyppiumAgent失败", harmonyDevice.getHdcDevice().getConnectKey());
throw new ExecuteException(String.format("设备【%s】创建session失败稍后再试", harmonyDevice.getHdcDevice().getConnectKey()));
// GLOBAL_PROVIDER_THREAD_SCOPE.launch((job) -> {
// init();
// }, RETRY_DELAY);
}
deviceInfo = getDeviceInfo();
log.debug("手机【{}】信息获取完成......",harmonyDevice.getHdcDevice().getConnectKey());
HarmonyDeviceManager.getInstance().registerDeviceToDeviceManager(deviceInfo); //注册设备到设备管理
}
private void init() {
if (!reinitAgent()) {
boolean startSuccess = false;
try {
startSuccess = reinitAgent();
} catch (Exception e) {
log.warn("重启设备【{}】agent失败",harmonyDevice.getHdcDevice().getConnectKey(), e);
return;
}
if (!startSuccess) {
GLOBAL_PROVIDER_THREAD_SCOPE.launch((job) -> {
init();
}, RETRY_DELAY);
@ -122,7 +134,8 @@ public class HarmonyProvider implements Closeable,InitDevice {
private boolean reinitAgent() {
if (harmonyDevice.getHdcDevice().getConnectStatus() != HDCConnectStatus.CONNECTED) {
return false;
log.warn("设备【{}】已经掉线不重新启动agent直接退出",harmonyDevice.getHdcDevice().getConnectKey());
throw new ExecuteException(String.format("设备【%s】掉线了不重启启动agent了",harmonyDevice.getHdcDevice().getConnectKey()));
}
try {
agent.initAgent();
@ -142,7 +155,9 @@ public class HarmonyProvider implements Closeable,InitDevice {
session = null;
}
session = agent.createSession();
session.setOnCloseListener(this::onSessionClosed);
if (null != session) {
session.setOnCloseListener(this::onSessionClosed);
}
return session != null;
}
@ -154,10 +169,15 @@ public class HarmonyProvider implements Closeable,InitDevice {
log.error("执行鸿蒙设备{}状态回调时发生异常", harmonyDevice.getHdcDevice().getConnectKey(), e);
}
}
if (harmonyDevice.getHdcDevice().getConnectStatus() == HDCConnectStatus.CONNECTED) {
log.debug("设备【{}】的agent的session异常关闭了执行回调重新启动............", harmonyDevice.getHdcDevice().getConnectKey());
GLOBAL_PROVIDER_THREAD_SCOPE.launch((job) -> {
init();
});
} else {
log.debug("设备【{}】的agent的session异常关闭了设备未连接就不执行回调了...........", harmonyDevice.getHdcDevice().getConnectKey());
}
GLOBAL_PROVIDER_THREAD_SCOPE.launch((job) -> {
init();
});
}
@Override
@ -453,6 +473,7 @@ public class HarmonyProvider implements Closeable,InitDevice {
deviceInfo.put("product", "mate60");
//region 平台
deviceInfo.put("platform", "harmony");
deviceInfo.put("version", "5.0");
int rotation = getDisplayRotation();
deviceInfo.put("rotation", rotation);
DisplaySize screenSize = getScreenSize();
@ -465,7 +486,11 @@ public class HarmonyProvider implements Closeable,InitDevice {
@Override
public void exitDeviceInit() {
if (null != session) {
session.setOnCloseListener(null); //不回调了
session.close();
}
session = null;
}
interface DoSessionRequestBlock<T> {

View File

@ -93,7 +93,15 @@ public class HDCDeviceObserver implements Runnable {
}
}
ArrayList<HDCDevice> devices = Hdc.getInstance().listTargets(hdcSession);
ArrayList<HDCDevice> devices = null;
try {
devices = Hdc.getInstance().listTargets(hdcSession);
} catch (IOException e) {
log.warn("与hdc服务的连接关闭。。。。。。。");
hdcSession.close();
hdcSession = null;
continue;
}
if (devices == null) {
log.warn("监控设备动态失败无法与HDC进行通信等待10秒……");
try {
@ -103,28 +111,28 @@ public class HDCDeviceObserver implements Runnable {
}
continue;
}
boolean hasDifferent = devices.size() != lastDevices.size();
if (!hasDifferent) {
for (int i = 0; i < devices.size(); i++) {
if (!devices.get(i).equals(lastDevices.get(i))) {
hasDifferent = true;
break;
// boolean hasDifferent = devices.size() != lastDevices.size();
// if (!hasDifferent) {
// for (int i = 0; i < devices.size(); i++) {
// if (!devices.get(i).equals(lastDevices.get(i))) {
// hasDifferent = true;
// break;
// }
// }
// }
// if (hasDifferent) {
//
// }
// lastDevices = devices;
synchronized (listeners) {
try {
for (HDCDeviceListener l : listeners) {
l.onDeviceChanged(devices);
}
} catch (Exception e) {
log.error("设备变动监听器发生异常", e);
}
}
if (hasDifferent) {
synchronized (listeners) {
try {
for (HDCDeviceListener l : listeners) {
l.onDeviceChanged(devices);
}
} catch (Exception e) {
log.error("设备变动监听器发生异常", e);
}
}
}
lastDevices = devices;
try {
Thread.sleep(500);
} catch (InterruptedException e) {

View File

@ -52,7 +52,10 @@ public class HDCSession implements Closeable {
}
private void ensureOpen() throws IOException {
if (isClosed()) throw new IOException("与HDC的连接已经关闭");
if (isClosed()) {
log.warn("HDC服务已经关闭............................");
throw new IOException("与HDC服务的通道已经关闭");
}
}
/**

View File

@ -33,6 +33,8 @@ public class Hdc {
return instance;
}
private static boolean hdcStatus = false;
/**
* HDC
*/
@ -63,6 +65,31 @@ public class Hdc {
}
}
public synchronized static void restartHdcDaemon() {
log.info("重新启动hdc服务.........");
if (hdcStatus) {
log.info("hdc已经启动无需再启动");
return;
}
ProcessBuilder processBuilder = new ProcessBuilder("hdc", "kill");
Process process;
try {
process = processBuilder.start();
} catch (IOException e) {
log.error("关闭hdc失败", e);
return;
}
boolean runResult = false;
try {
runResult = process.waitFor(10, TimeUnit.SECONDS);
} catch (InterruptedException e) {
log.warn("等待hdc关闭的过程中被中断");
}
if (runResult) {
log.info("hdc已经成功关闭");
}
startHdcDaemon();
}
/**
* HDC
*
@ -87,7 +114,9 @@ public class Hdc {
if (!runResult) {
return false;
}
return process.exitValue() == 0;
hdcStatus = process.exitValue() == 0;
log.info("启动hdc服务结果{}",hdcStatus);
return hdcStatus;
}
/**
@ -101,6 +130,8 @@ public class Hdc {
socket = new Socket(HOST, PORT);
} catch (IOException e) {
log.error("创建HDC会话失败连接到hdc时发生IO错误host:{} port:{}", HOST, PORT, e);
hdcStatus = false;
restartHdcDaemon();
return null;
}
HDCSession session;
@ -138,6 +169,7 @@ public class Hdc {
*/
public String version() {
HDCSession session = createSession();
if (null == session) return null;
String rawVersion = null;
try {
rawVersion = session.sendHdcCommand("version");
@ -155,11 +187,16 @@ public class Hdc {
}
public ArrayList<HDCDevice> listTargets() {
ArrayList<HDCDevice> hdcDevices = new ArrayList<>();
HDCSession session = createSession();
if (session == null) {
return new ArrayList<>();
if (session != null) {
try {
hdcDevices = listTargets(session);
} catch (IOException e) {
log.warn("hdc服务连接失败...",e);
}
}
return listTargets(session);
return hdcDevices;
}
/**
@ -168,14 +205,8 @@ public class Hdc {
* @param session HDC
* @return null
*/
public ArrayList<HDCDevice> listTargets(HDCSession session) {
String replyContent;
try {
replyContent = session.sendHdcCommand("list targets -v");
} catch (IOException e) {
log.error("获取设备列表失败连接到hdc后发生IO错误", e);
return null;
}
public ArrayList<HDCDevice> listTargets(HDCSession session) throws IOException {
String replyContent = session.sendHdcCommand("list targets -v");
if (replyContent.length() < 10) return new ArrayList<>();
replyContent = replyContent.replaceAll("\t", " ");
ArrayList<HDCDevice> result = new ArrayList<HDCDevice>();

View File

@ -726,6 +726,8 @@ public class HyppiumAgent {
@Override
public void close() {
log.info("关闭设备agent连接");
thread.interrupt();
if (closed) {
return;
}
@ -738,6 +740,7 @@ public class HyppiumAgent {
}
if (onCloseListener != null) {
try {
log.error("agent有问题重新启动.....");
onCloseListener.run();
} catch (Exception e) {
log.error("关闭鸿蒙设备{}的一个Agent Session后执行关闭监听回调时发生异常", hdcDevice.getConnectKey());

View File

@ -521,12 +521,30 @@ public class HarmonyMessageHandlerThread extends AbstractMessageHandler{
@Override
public void clearAndCloseDeviceAgentConnection() {
//通知前端设备现在处于掉线的状态,前端开始转圈
HarmonyScreenResponseThread screenThread = HarmonyDeviceManager.getInstance().getScreenThread(this.serial);
if (null != screenThread) {
screenThread.noticeToWebScreenDisconnect();
}
notifyDeviceOfflineToWeb();
}
@Override
public void reConnectDeviceAgent() {
notifyDeviceOnlineToWeb();
//发送前端重连成功消息的标志
HarmonyScreenResponseThread screenThread = HarmonyDeviceManager.getInstance().getScreenThread(this.serial);
if (null != screenThread) {
screenThread.setSendDeviceStatus(true); //发送连接成功消息
HarmonyProvider harmonyProvider = getHarmonyProvider();
boolean success = harmonyProvider.startCaptureScreenImageStream(0.5f, screenThread);
if (!success) {
logger.info("开启设备【{}】的图片流失败", this.serial);
Map<String, Object> result = new HashMap<>();
result.put(ResponseCmd.DeviceStatus.STATUS, ResponseCmd.DeviceStatus.DISCONNECT);
SessionUtils.sendMessageInitiative(session, ResponseCmd.DEVICE_STATUS, this.serial, result, "开启设备的图片流失败,正在重试");
}
}
}
@Override