2026-01-30 11:47:32 +08:00
|
|
|
|
package com.aros.apron.manager;
|
|
|
|
|
|
|
|
|
|
|
|
import static com.aros.apron.tools.Utils.getIDJIErrorMsg;
|
|
|
|
|
|
import static dji.sdk.keyvalue.key.KeyTools.createKey;
|
|
|
|
|
|
|
|
|
|
|
|
import android.os.Environment;
|
|
|
|
|
|
import android.os.Handler;
|
|
|
|
|
|
import android.os.Looper;
|
|
|
|
|
|
import android.text.TextUtils;
|
|
|
|
|
|
|
|
|
|
|
|
import androidx.annotation.NonNull;
|
|
|
|
|
|
import androidx.annotation.Nullable;
|
|
|
|
|
|
|
|
|
|
|
|
import com.aros.apron.app.ApronApp;
|
|
|
|
|
|
import com.aros.apron.base.BaseManager;
|
|
|
|
|
|
import com.aros.apron.constant.ErrorCode;
|
|
|
|
|
|
import com.aros.apron.entity.CurrentWayline;
|
|
|
|
|
|
import com.aros.apron.entity.MessageDown;
|
|
|
|
|
|
import com.aros.apron.entity.Movement;
|
2026-03-12 14:57:34 +08:00
|
|
|
|
import com.aros.apron.entity.Synchronizedstatus;
|
2026-01-30 11:47:32 +08:00
|
|
|
|
import com.aros.apron.tools.LogUtil;
|
|
|
|
|
|
import com.aros.apron.tools.PreferenceUtils;
|
|
|
|
|
|
import com.aros.apron.tools.RestartAPPTool;
|
2026-02-27 10:18:56 +08:00
|
|
|
|
import com.aros.apron.tools.TakeoffProgressScheduler;
|
2026-01-30 11:47:32 +08:00
|
|
|
|
import com.dji.wpmzsdk.common.data.KMZInfo;
|
|
|
|
|
|
import com.dji.wpmzsdk.manager.WPMZManager;
|
|
|
|
|
|
import com.google.gson.Gson;
|
|
|
|
|
|
|
|
|
|
|
|
import java.io.File;
|
|
|
|
|
|
import java.io.FileOutputStream;
|
|
|
|
|
|
import java.io.IOException;
|
|
|
|
|
|
import java.io.InputStream;
|
|
|
|
|
|
import java.util.List;
|
|
|
|
|
|
|
2026-02-27 10:18:56 +08:00
|
|
|
|
import dji.sdk.keyvalue.key.CameraKey;
|
2026-01-30 11:47:32 +08:00
|
|
|
|
import dji.sdk.keyvalue.key.FlightControllerKey;
|
|
|
|
|
|
import dji.sdk.keyvalue.key.KeyTools;
|
|
|
|
|
|
import dji.sdk.keyvalue.value.flightcontroller.RemoteControllerFlightMode;
|
|
|
|
|
|
import dji.sdk.wpmz.value.mission.Wayline;
|
|
|
|
|
|
import dji.sdk.wpmz.value.mission.WaylineExecuteWaypoint;
|
|
|
|
|
|
import dji.sdk.wpmz.value.mission.WaylineWaylinesParseInfo;
|
|
|
|
|
|
import dji.v5.common.callback.CommonCallbacks;
|
|
|
|
|
|
import dji.v5.common.error.IDJIError;
|
|
|
|
|
|
import dji.v5.manager.KeyManager;
|
|
|
|
|
|
import dji.v5.manager.aircraft.waypoint3.WaylineExecutingInfoListener;
|
|
|
|
|
|
import dji.v5.manager.aircraft.waypoint3.WaypointActionListener;
|
|
|
|
|
|
import dji.v5.manager.aircraft.waypoint3.WaypointMissionExecuteStateListener;
|
|
|
|
|
|
import dji.v5.manager.aircraft.waypoint3.WaypointMissionManager;
|
|
|
|
|
|
import dji.v5.manager.aircraft.waypoint3.model.BreakPointInfo;
|
|
|
|
|
|
import dji.v5.manager.aircraft.waypoint3.model.WaylineExecutingInfo;
|
|
|
|
|
|
import dji.v5.manager.aircraft.waypoint3.model.WaypointMissionExecuteState;
|
|
|
|
|
|
import dji.v5.manager.interfaces.IWaypointMissionManager;
|
|
|
|
|
|
import okhttp3.Call;
|
|
|
|
|
|
import okhttp3.Callback;
|
|
|
|
|
|
import okhttp3.OkHttpClient;
|
|
|
|
|
|
import okhttp3.Request;
|
|
|
|
|
|
import okhttp3.Response;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public class MissionV3Manager extends BaseManager {
|
|
|
|
|
|
|
|
|
|
|
|
final Handler mainHandler = new Handler(Looper.getMainLooper());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private MissionV3Manager() {
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private static class MissionHolder {
|
|
|
|
|
|
private static final MissionV3Manager INSTANCE = new MissionV3Manager();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static MissionV3Manager getInstance() {
|
|
|
|
|
|
return MissionHolder.INSTANCE;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public boolean isReceiverMission = false;
|
|
|
|
|
|
//在ENTER_WAYLINE后10秒,航线状态变为FINISH,此时无人机不起飞/悬停
|
|
|
|
|
|
private long enterWayLineTime;
|
|
|
|
|
|
private long finishWayLineTime;
|
2026-03-12 14:57:34 +08:00
|
|
|
|
private boolean istakeoff_ok = false;
|
|
|
|
|
|
private int taskRestartFailTimes = 0;
|
2026-01-30 11:47:32 +08:00
|
|
|
|
|
2026-03-12 14:57:34 +08:00
|
|
|
|
private int totalretryStartMissiontimes = 0;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 重试启动任务
|
|
|
|
|
|
*/
|
|
|
|
|
|
private void retryStartMission() {
|
|
|
|
|
|
if (totalretryStartMissiontimes > 51) {
|
|
|
|
|
|
LogUtil.log(TAG, "尝试重启总次数大于50");
|
|
|
|
|
|
sendEvent2Server("尝试重启总次数大于50", 2);
|
|
|
|
|
|
if (!Movement.getInstance().isPlaneWing() || !Movement.getInstance().isMotorsOn()) {
|
|
|
|
|
|
TaskFailManager.getInstance().sendTaskFailMsg2Server(-1);
|
|
|
|
|
|
}
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (taskRestartFailTimes >= 50) {
|
|
|
|
|
|
LogUtil.log(TAG, "任务重启失败次数达到上限,发送任务失败");
|
|
|
|
|
|
sendEvent2Server("任务非正常结束,重启失败", 2);
|
|
|
|
|
|
TaskFailManager.getInstance().sendTaskFailMsg2Server(-1);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
taskRestartFailTimes++;
|
|
|
|
|
|
LogUtil.log(TAG, "任务非正常结束,第" + taskRestartFailTimes + "次尝试重新启动");
|
|
|
|
|
|
sendEvent2Server("任务非正常结束,第" + taskRestartFailTimes + "次尝试重新启动", 1);
|
|
|
|
|
|
|
|
|
|
|
|
WaypointMissionManager.getInstance().startMission(Movement.getInstance().getWaylinename(), new CommonCallbacks.CompletionCallback() {
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public void onSuccess() {
|
|
|
|
|
|
isMissionStart = true;
|
|
|
|
|
|
taskRestartFailTimes = 0;
|
|
|
|
|
|
LogUtil.log(TAG, "任务非正常结束,重启成功");
|
|
|
|
|
|
sendEvent2Server("任务非正常结束,重启成功", 1);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public void onFailure(@NonNull IDJIError idjiError) {
|
|
|
|
|
|
LogUtil.log(TAG, "任务非正常结束,第" + taskRestartFailTimes + "次重启失败:" + idjiError.toString());
|
|
|
|
|
|
sendEvent2Server("任务非正常结束,第" + taskRestartFailTimes + "次重启失败", 1);
|
|
|
|
|
|
|
|
|
|
|
|
// 延迟后再次尝试
|
|
|
|
|
|
mainHandler.postDelayed(new Runnable() {
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public void run() {
|
|
|
|
|
|
retryStartMission();
|
|
|
|
|
|
}
|
|
|
|
|
|
}, 3000);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
2026-01-30 11:47:32 +08:00
|
|
|
|
|
2026-03-12 14:57:34 +08:00
|
|
|
|
public void initMissionManager() {
|
2026-01-30 11:47:32 +08:00
|
|
|
|
Boolean isConnect = KeyManager.getInstance().getValue(KeyTools.createKey(FlightControllerKey.
|
|
|
|
|
|
KeyConnection));
|
2026-03-12 14:57:34 +08:00
|
|
|
|
WaypointMissionManager waypointMissionManager = WaypointMissionManager.getInstance();
|
|
|
|
|
|
waypointMissionManager.init();
|
|
|
|
|
|
|
|
|
|
|
|
// 延迟2s后注册监听
|
|
|
|
|
|
new Handler(Looper.getMainLooper()).postDelayed(() -> {
|
|
|
|
|
|
|
2026-01-30 11:47:32 +08:00
|
|
|
|
waypointMissionManager.addWaypointMissionExecuteStateListener(new WaypointMissionExecuteStateListener() {
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public void onMissionStateUpdate(WaypointMissionExecuteState missionState) {
|
|
|
|
|
|
if (missionState != null) {
|
|
|
|
|
|
switch (missionState) {
|
|
|
|
|
|
case DISCONNECTED:
|
|
|
|
|
|
sendEvent2Server("任务状态:未连接", 1);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case IDLE:
|
|
|
|
|
|
sendEvent2Server("任务状态:初始化", 1);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case NOT_SUPPORTED:
|
|
|
|
|
|
sendEvent2Server("任务状态:此机型不支持航线任务3.0", 1);
|
|
|
|
|
|
Movement.getInstance().setTask_status("rejected");
|
|
|
|
|
|
|
|
|
|
|
|
Movement.getInstance().setMissionFinish(false);
|
|
|
|
|
|
//这个是原来可控制那个发送最终状态的逻辑
|
|
|
|
|
|
Movement.getInstance().setMissionFinish1(false);
|
|
|
|
|
|
|
2026-03-12 14:57:34 +08:00
|
|
|
|
|
2026-01-30 11:47:32 +08:00
|
|
|
|
break;
|
|
|
|
|
|
case READY:
|
2026-03-12 14:57:34 +08:00
|
|
|
|
if (Movement.getInstance().getFlightmode() == 2 && istakeoff_ok == false) {
|
2026-02-27 10:18:56 +08:00
|
|
|
|
Movement.getInstance().setTakeoff_status("task_ready");
|
|
|
|
|
|
}
|
2026-03-12 14:57:34 +08:00
|
|
|
|
if (PreferenceUtils.getInstance().getMissionType() == 2
|
2026-01-30 11:47:32 +08:00
|
|
|
|
) {
|
|
|
|
|
|
Movement.getInstance().setTask_status("paused");
|
|
|
|
|
|
} else {
|
|
|
|
|
|
Movement.getInstance().setTask_status("in_progress");
|
|
|
|
|
|
}
|
|
|
|
|
|
sendEvent2Server("任务状态:准备中", 1);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case UPLOADING:
|
2026-03-12 14:57:34 +08:00
|
|
|
|
if (PreferenceUtils.getInstance().getMissionType() == 2
|
2026-01-30 11:47:32 +08:00
|
|
|
|
) {
|
|
|
|
|
|
Movement.getInstance().setTask_status("paused");
|
|
|
|
|
|
} else {
|
2026-03-12 14:57:34 +08:00
|
|
|
|
Movement.getInstance().setTask_status("in_progress");
|
2026-01-30 11:47:32 +08:00
|
|
|
|
}
|
|
|
|
|
|
sendEvent2Server("任务状态:上传中", 1);
|
|
|
|
|
|
Movement.getInstance().setVirtualStickQuitMission(false);
|
|
|
|
|
|
Movement.getInstance().setMissionFinish(false);
|
|
|
|
|
|
|
|
|
|
|
|
//这个是原来可控制那个发送最终状态的逻辑
|
|
|
|
|
|
Movement.getInstance().setMissionFinish1(false);
|
|
|
|
|
|
|
2026-03-12 14:57:34 +08:00
|
|
|
|
|
2026-01-30 11:47:32 +08:00
|
|
|
|
break;
|
|
|
|
|
|
case PREPARING:
|
2026-03-12 14:57:34 +08:00
|
|
|
|
if (PreferenceUtils.getInstance().getMissionType() == 2
|
2026-01-30 11:47:32 +08:00
|
|
|
|
) {
|
|
|
|
|
|
Movement.getInstance().setTask_status("paused");
|
|
|
|
|
|
} else {
|
|
|
|
|
|
Movement.getInstance().setTask_status("in_progress");
|
|
|
|
|
|
}
|
|
|
|
|
|
sendEvent2Server("任务状态:执行准备中", 1);
|
|
|
|
|
|
Movement.getInstance().setVirtualStickQuitMission(false);
|
|
|
|
|
|
Movement.getInstance().setMissionFinish(false);
|
|
|
|
|
|
|
|
|
|
|
|
//这个是原来可控制那个发送最终状态的逻辑
|
|
|
|
|
|
Movement.getInstance().setMissionFinish1(false);
|
|
|
|
|
|
|
2026-03-12 14:57:34 +08:00
|
|
|
|
|
2026-01-30 11:47:32 +08:00
|
|
|
|
break;
|
|
|
|
|
|
case ENTER_WAYLINE:
|
|
|
|
|
|
enterWayLineTime = System.currentTimeMillis();
|
2026-03-12 14:57:34 +08:00
|
|
|
|
if (Movement.getInstance().getFlightmode() == 2) {
|
2026-02-27 10:18:56 +08:00
|
|
|
|
Movement.getInstance().setTakeoff_status("wayline_progress");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-12 14:57:34 +08:00
|
|
|
|
if (PreferenceUtils.getInstance().getMissionType() == 2
|
2026-01-30 11:47:32 +08:00
|
|
|
|
) {
|
|
|
|
|
|
Movement.getInstance().setTask_status("paused");
|
|
|
|
|
|
} else {
|
|
|
|
|
|
Movement.getInstance().setTask_status("in_progress");
|
|
|
|
|
|
}
|
2026-03-12 14:57:34 +08:00
|
|
|
|
|
2026-01-30 11:47:32 +08:00
|
|
|
|
Movement.getInstance().setVirtualStickQuitMission(false);
|
|
|
|
|
|
sendEvent2Server("任务状态:进入航线飞行,飞往指定航线的第一个航点", 1);
|
2026-03-12 14:57:34 +08:00
|
|
|
|
|
2026-01-30 11:47:32 +08:00
|
|
|
|
Movement.getInstance().setMissionFinish(false);
|
|
|
|
|
|
|
|
|
|
|
|
//这个是原来可控制那个发送最终状态的逻辑
|
|
|
|
|
|
Movement.getInstance().setMissionFinish1(false);
|
2026-03-12 14:57:34 +08:00
|
|
|
|
|
2026-01-30 11:47:32 +08:00
|
|
|
|
|
|
|
|
|
|
//航线飞行
|
2026-03-12 14:57:34 +08:00
|
|
|
|
if (Movement.getInstance().getFlightmode() == 1) {
|
2026-02-11 10:06:54 +08:00
|
|
|
|
|
|
|
|
|
|
Movement.getInstance().setMode_code(5);
|
2026-03-12 14:57:34 +08:00
|
|
|
|
} else if (Movement.getInstance().getFlightmode() == 2) {
|
2026-02-11 10:06:54 +08:00
|
|
|
|
//指令飞行
|
|
|
|
|
|
Movement.getInstance().setMode_code(17);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-30 11:47:32 +08:00
|
|
|
|
break;
|
|
|
|
|
|
case EXECUTING:
|
|
|
|
|
|
sendEvent2Server("任务状态:航线任务执行中", 1);
|
|
|
|
|
|
|
2026-03-12 14:57:34 +08:00
|
|
|
|
if (PreferenceUtils.getInstance().getMissionType() == 2
|
2026-01-30 11:47:32 +08:00
|
|
|
|
) {
|
|
|
|
|
|
Movement.getInstance().setTask_status("paused");
|
|
|
|
|
|
} else {
|
|
|
|
|
|
Movement.getInstance().setTask_status("in_progress");
|
|
|
|
|
|
}
|
|
|
|
|
|
Movement.getInstance().setVirtualStickQuitMission(false);
|
|
|
|
|
|
Movement.getInstance().setMissionFinish(false);
|
|
|
|
|
|
|
|
|
|
|
|
//这个是原来可控制那个发送最终状态的逻辑
|
|
|
|
|
|
Movement.getInstance().setMissionFinish1(false);
|
2026-03-12 14:57:34 +08:00
|
|
|
|
|
2026-01-30 11:47:32 +08:00
|
|
|
|
break;
|
|
|
|
|
|
case INTERRUPTED:
|
2026-03-12 14:57:34 +08:00
|
|
|
|
if (Movement.getInstance().getFlightmode() == 2) {
|
2026-02-27 10:18:56 +08:00
|
|
|
|
Movement.getInstance().setTakeoff_status("wayline_cancel");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-30 11:47:32 +08:00
|
|
|
|
Movement.getInstance().setVirtualStickQuitMission(false);
|
|
|
|
|
|
sendEvent2Server("任务状态:航线任务执行中断", 1);
|
|
|
|
|
|
Movement.getInstance().setTask_status("paused");
|
|
|
|
|
|
Movement.getInstance().setMissionFinish(false);
|
|
|
|
|
|
|
|
|
|
|
|
//这个是原来可控制那个发送最终状态的逻辑
|
|
|
|
|
|
Movement.getInstance().setMissionFinish1(false);
|
2026-03-12 14:57:34 +08:00
|
|
|
|
|
2026-01-30 11:47:32 +08:00
|
|
|
|
|
|
|
|
|
|
//切换成手动飞行
|
|
|
|
|
|
//Movement.getInstance().setMode_code(3);
|
|
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
case RECOVERING:
|
|
|
|
|
|
Movement.getInstance().setVirtualStickQuitMission(false);
|
|
|
|
|
|
sendEvent2Server("任务状态:航线任务恢复中", 1);
|
2026-03-12 14:57:34 +08:00
|
|
|
|
if (PreferenceUtils.getInstance().getMissionType() == 2
|
2026-01-30 11:47:32 +08:00
|
|
|
|
) {
|
|
|
|
|
|
Movement.getInstance().setTask_status("paused");
|
|
|
|
|
|
} else {
|
|
|
|
|
|
Movement.getInstance().setTask_status("in_progress");
|
|
|
|
|
|
}
|
|
|
|
|
|
Movement.getInstance().setMissionFinish(false);
|
|
|
|
|
|
|
|
|
|
|
|
//这个是原来可控制那个发送最终状态的逻辑
|
|
|
|
|
|
Movement.getInstance().setMissionFinish1(false);
|
2026-03-12 14:57:34 +08:00
|
|
|
|
|
2026-01-30 11:47:32 +08:00
|
|
|
|
break;
|
|
|
|
|
|
case FINISHED:
|
2026-03-12 14:57:34 +08:00
|
|
|
|
//释放锁
|
|
|
|
|
|
Synchronizedstatus.setFlighttaskExecuteStatus(false);
|
|
|
|
|
|
|
|
|
|
|
|
|
2026-01-30 11:47:32 +08:00
|
|
|
|
|
|
|
|
|
|
//如果是虚拟摇杆导致的退出应该要可恢复
|
2026-03-12 14:57:34 +08:00
|
|
|
|
if (Movement.getInstance().getMode_code() == 16) {
|
2026-01-30 11:47:32 +08:00
|
|
|
|
PreferenceUtils.getInstance().setMissionType(2);
|
2026-03-12 14:57:34 +08:00
|
|
|
|
} else {
|
2026-01-30 11:47:32 +08:00
|
|
|
|
|
|
|
|
|
|
}
|
2026-02-27 10:18:56 +08:00
|
|
|
|
|
2026-03-12 14:57:34 +08:00
|
|
|
|
if (Movement.getInstance().getFlightmode() == 2) {
|
|
|
|
|
|
//
|
|
|
|
|
|
LogUtil.log(TAG, "设置成mode3");
|
|
|
|
|
|
Movement.getInstance().setMode_code(3);
|
|
|
|
|
|
istakeoff_ok = true;
|
|
|
|
|
|
Movement.getInstance().setTakeoff_status("wayline_ok");
|
2026-02-27 10:18:56 +08:00
|
|
|
|
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public void run() {
|
|
|
|
|
|
TakeoffProgressScheduler.getInstance().stopReporting();
|
|
|
|
|
|
}
|
2026-03-12 14:57:34 +08:00
|
|
|
|
}, 2000); // 1000ms = 1秒
|
2026-02-27 10:18:56 +08:00
|
|
|
|
}
|
2026-01-30 11:47:32 +08:00
|
|
|
|
|
|
|
|
|
|
finishWayLineTime = System.currentTimeMillis();
|
2026-03-12 14:57:34 +08:00
|
|
|
|
|
2026-01-30 11:47:32 +08:00
|
|
|
|
mainHandler.postDelayed(new Runnable() {
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public void run() {
|
2026-03-12 14:57:34 +08:00
|
|
|
|
if (finishWayLineTime - enterWayLineTime <= 8000 && !Movement.getInstance().isPlaneWing()
|
2026-01-30 11:47:32 +08:00
|
|
|
|
) {
|
2026-03-12 14:57:34 +08:00
|
|
|
|
isMissionStart = false;
|
|
|
|
|
|
totalretryStartMissiontimes++;
|
|
|
|
|
|
retryStartMission();
|
2026-01-30 11:47:32 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}, 5000);
|
2026-03-12 14:57:34 +08:00
|
|
|
|
|
2026-01-30 11:47:32 +08:00
|
|
|
|
//需要在这里保存下来机头角度,index等断点,在降落后若查询到断点,在拼接起来
|
2026-03-12 14:57:34 +08:00
|
|
|
|
PreferenceUtils.getInstance().setAttitudeHead(Movement.getInstance().getAttitude_head() + "");
|
|
|
|
|
|
PreferenceUtils.getInstance().setWaypointIndex(Movement.getInstance().getCurrentWaypointIndex() + "");
|
2026-01-30 11:47:32 +08:00
|
|
|
|
queryBreakPoint();
|
2026-03-12 14:57:34 +08:00
|
|
|
|
|
2026-01-30 11:47:32 +08:00
|
|
|
|
break;
|
|
|
|
|
|
case RETURN_TO_START_POINT:
|
|
|
|
|
|
//自动返航
|
|
|
|
|
|
Movement.getInstance().setMode_code(9);
|
|
|
|
|
|
|
2026-03-12 14:57:34 +08:00
|
|
|
|
if (PreferenceUtils.getInstance().getMissionType() == 2
|
2026-01-30 11:47:32 +08:00
|
|
|
|
) {
|
|
|
|
|
|
Movement.getInstance().setTask_status("paused");
|
|
|
|
|
|
} else {
|
|
|
|
|
|
Movement.getInstance().setTask_status("in_progress");
|
|
|
|
|
|
}
|
|
|
|
|
|
Movement.getInstance().setMissionFinish(false);
|
|
|
|
|
|
|
|
|
|
|
|
//这个是原来可控制那个发送最终状态的逻辑
|
|
|
|
|
|
Movement.getInstance().setMissionFinish1(false);
|
2026-03-12 14:57:34 +08:00
|
|
|
|
|
2026-01-30 11:47:32 +08:00
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
LogUtil.log(TAG, "WaypointMissionExecuteState:" + missionState.name());
|
|
|
|
|
|
Movement.getInstance().setWaypointMissionExecuteState(missionState.name());
|
|
|
|
|
|
Movement.getInstance().setTask_wayline_mission_state(missionState.value());
|
|
|
|
|
|
Movement.getInstance().setMissionStateCode(missionState.value());
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
2026-03-12 14:57:34 +08:00
|
|
|
|
|
2026-01-30 11:47:32 +08:00
|
|
|
|
waypointMissionManager.addWaylineExecutingInfoListener(new WaylineExecutingInfoListener() {
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public void onWaylineExecutingInfoUpdate(WaylineExecutingInfo excutingWaylineInfo) {
|
|
|
|
|
|
if (excutingWaylineInfo != null) {
|
|
|
|
|
|
//状态等执行完发送再更新(测试暂停时不改变index为0)
|
|
|
|
|
|
if (excutingWaylineInfo.getCurrentWaypointIndex() != 0) {
|
|
|
|
|
|
Movement.getInstance().setCurrentWaypointIndex(excutingWaylineInfo.getCurrentWaypointIndex());
|
|
|
|
|
|
Movement.getInstance().setTask_current_waypoint_index(excutingWaylineInfo.getCurrentWaypointIndex());
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public void onWaylineExecutingInterruptReasonUpdate(IDJIError error) {
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
waypointMissionManager.addWaypointActionListener(new WaypointActionListener() {
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public void onExecutionStart(int actionId) {
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public void onExecutionFinish(int actionId, @Nullable IDJIError error) {
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public void onExecutionStart(int actionGroup, int actionId) {
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public void onExecutionFinish(int actionGroup, int actionId, @Nullable IDJIError error) {
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2026-03-12 14:57:34 +08:00
|
|
|
|
}, 2000); // 参数别改:2s延迟
|
2026-01-30 11:47:32 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//收到航线
|
|
|
|
|
|
public void taskExecute(MessageDown message) {
|
|
|
|
|
|
|
|
|
|
|
|
PreferenceUtils.getInstance().setMissionType(0);
|
2026-03-12 14:57:34 +08:00
|
|
|
|
Movement.getInstance().setMission_type(0);
|
2026-01-30 11:47:32 +08:00
|
|
|
|
PreferenceUtils.getInstance().setFlightId(message.getData().getFlight_id());
|
|
|
|
|
|
PreferenceUtils.getInstance().setAlternatePointLon(message.getData().getAlternate_land_point().getLongitude() + "");
|
|
|
|
|
|
PreferenceUtils.getInstance().setAlternatePointLat(message.getData().getAlternate_land_point().getLatitude() + "");
|
|
|
|
|
|
PreferenceUtils.getInstance().setAlternatePointSecurityHeight(message.getData().getAlternate_land_point().getSafe_land_height() + "");
|
|
|
|
|
|
|
2026-03-04 11:20:07 +08:00
|
|
|
|
//设置全局返航高度
|
|
|
|
|
|
KeyManager.getInstance().setValue(KeyTools.createKey(FlightControllerKey.KeyGoHomeHeight), message.getData().getRth_altitude(), new CommonCallbacks.CompletionCallback() {
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public void onSuccess() {
|
2026-03-12 14:57:34 +08:00
|
|
|
|
LogUtil.log(TAG, "设置全局返航高度成功");
|
2026-03-04 11:20:07 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public void onFailure(@NonNull IDJIError idjiError) {
|
2026-03-12 14:57:34 +08:00
|
|
|
|
LogUtil.log(TAG, "设置全局返航高度失败");
|
2026-03-04 11:20:07 +08:00
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2026-01-30 11:47:32 +08:00
|
|
|
|
Movement.getInstance().setTask_current_step(5);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//1.检查图传是否连接
|
|
|
|
|
|
checkVtxWithDelay(() -> {
|
|
|
|
|
|
//避免重复执行
|
|
|
|
|
|
if (isReceiverMission == false) {
|
|
|
|
|
|
isReceiverMission = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
//2.回复收到指令
|
2026-03-12 14:57:34 +08:00
|
|
|
|
|
2026-01-30 11:47:32 +08:00
|
|
|
|
//3.检查飞机状态(不满足条件直接taskFail入库)
|
|
|
|
|
|
boolean statusOk = verifyAircraftStatus(message);
|
|
|
|
|
|
//4.信号收敛(等待GPS搜星)
|
|
|
|
|
|
if (statusOk) {
|
2026-03-12 14:57:34 +08:00
|
|
|
|
sendEvent2Server("条件满足进入自建和下发航线", 1);
|
2026-01-30 11:47:32 +08:00
|
|
|
|
verifyGpsAndMissionState(message);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 1.校验飞机状态
|
|
|
|
|
|
*/
|
|
|
|
|
|
private boolean verifyAircraftStatus(MessageDown message) {
|
|
|
|
|
|
Boolean isConnect = KeyManager.getInstance().getValue(createKey(FlightControllerKey.KeyConnection));
|
|
|
|
|
|
if (isConnect != null && isConnect) {
|
|
|
|
|
|
//1.若当前处于虚拟摇杆状态,取消虚拟摇杆
|
|
|
|
|
|
if (Movement.getInstance().getIsVirtualStickEnable() == 1) {
|
|
|
|
|
|
StickManager.getInstance().disableVirtualStick(null);
|
|
|
|
|
|
}
|
|
|
|
|
|
//2.关闭避障
|
|
|
|
|
|
PerceptionManager.getInstance().setPerceptionEnable(false);
|
2026-03-12 14:57:34 +08:00
|
|
|
|
|
2026-02-27 10:18:56 +08:00
|
|
|
|
PerceptionManager.getInstance().setObstacleAvoidanceHorizontalEnabled(false);
|
2026-01-30 11:47:32 +08:00
|
|
|
|
//3.清空sd卡
|
|
|
|
|
|
CameraManager.getInstance().formatStorage(null);
|
|
|
|
|
|
//4.返航或降落状态无法执行航线
|
|
|
|
|
|
if (Movement.getInstance().getGoHomeState() == 1 || Movement.getInstance().getGoHomeState() == 2) {
|
|
|
|
|
|
sendFailMsg2Server(message, "返航中,无法执行航线任务");
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
//5.检查航线备降点参数
|
|
|
|
|
|
if (message.getData().getAlternate_land_point() == null) {
|
|
|
|
|
|
sendEvent2Server("备降点参数异常", 2);
|
|
|
|
|
|
TaskFailManager.getInstance().sendTaskFailMsg2Server(-1);
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
//6.检查航线参数
|
|
|
|
|
|
if (message.getData().getFile() == null) {
|
|
|
|
|
|
sendEvent2Server("航线参数异常", 2);
|
|
|
|
|
|
TaskFailManager.getInstance().sendTaskFailMsg2Server(-1);
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
//7.检查电池电量
|
|
|
|
|
|
Integer value = KeyManager.getInstance().getValue(createKey(FlightControllerKey.
|
|
|
|
|
|
KeyBatteryPowerPercent, 0));
|
|
|
|
|
|
if (value != null && value < Integer.parseInt(PreferenceUtils.getInstance().getMinumumBattery())) {
|
|
|
|
|
|
sendEvent2Server("任务执行失败,电量过低", 2);
|
|
|
|
|
|
TaskFailManager.getInstance().sendTaskFailMsg2Server(ErrorCode.DEVICE_BATTERY_LEVEL_TOO_LOW);
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
RemoteControllerFlightMode remoteControllerFlightMode =
|
|
|
|
|
|
KeyManager.getInstance().getValue(KeyTools.createKey(FlightControllerKey.KeyRemoteControllerFlightMode));
|
|
|
|
|
|
if (remoteControllerFlightMode != null && remoteControllerFlightMode != RemoteControllerFlightMode.P) {
|
|
|
|
|
|
sendEvent2Server("任务执行失败,请将遥控器切换为P/N挡", 2);
|
|
|
|
|
|
TaskFailManager.getInstance().sendTaskFailMsg2Server(-1);
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
sendFailMsg2Server(message, "无人机未连接");
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private int verifyGpsAndMissionStateTimes;
|
|
|
|
|
|
private boolean verifyGpsAndMissionStateSuccess;
|
|
|
|
|
|
private final int maxRetries = 100;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 3.GPS信号校验
|
|
|
|
|
|
*/
|
|
|
|
|
|
private void verifyGpsAndMissionState(MessageDown message) {
|
|
|
|
|
|
int missionStateCode = Movement.getInstance().getMissionStateCode();
|
|
|
|
|
|
String planeMessage = Movement.getInstance().getPlaneMessage();
|
|
|
|
|
|
int quality = Movement.getInstance().getQuality();
|
2026-03-12 14:57:34 +08:00
|
|
|
|
int GPSSatelliteCount = Movement.getInstance().getGPSSatelliteCount();
|
2026-01-30 11:47:32 +08:00
|
|
|
|
|
|
|
|
|
|
boolean isMissionStateValid = (missionStateCode == 2 || missionStateCode == 0 || missionStateCode == 7);
|
|
|
|
|
|
boolean isPlaneMessageValid = !TextUtils.isEmpty(planeMessage) && !planeMessage.equals("无法起飞");
|
|
|
|
|
|
boolean isGpsQualityValid = (quality == 4 || quality == 5 || quality == 10);
|
2026-03-12 14:57:34 +08:00
|
|
|
|
boolean GPSSatelliteCountValid = GPSSatelliteCount > 15;
|
2026-01-30 11:47:32 +08:00
|
|
|
|
|
2026-03-12 14:57:34 +08:00
|
|
|
|
LogUtil.log(TAG, "isMissionStateValid" + isMissionStateValid + "isPlaneMessageValid" + isPlaneMessageValid + "isGpsQualityValid" + isGpsQualityValid);
|
2026-01-30 11:47:32 +08:00
|
|
|
|
// if (isMissionStateValid && isPlaneMessageValid && isGpsQualityValid) {
|
2026-02-10 20:46:40 +08:00
|
|
|
|
|
2026-03-12 14:57:34 +08:00
|
|
|
|
sendEvent2Server("卫星数量" + GPSSatelliteCount + "gps是否ok" + GPSSatelliteCountValid, 1);
|
|
|
|
|
|
if (isGpsQualityValid || GPSSatelliteCountValid) {
|
2026-01-30 11:47:32 +08:00
|
|
|
|
//5.下载航线
|
|
|
|
|
|
downLoadKMZFile(message);
|
2026-03-12 14:57:34 +08:00
|
|
|
|
sendEvent2Server("执行下载航线成功", 1);
|
2026-01-30 11:47:32 +08:00
|
|
|
|
verifyGpsAndMissionStateSuccess = true;
|
2026-03-12 14:57:34 +08:00
|
|
|
|
Movement.getInstance().setIs_fixed(2);
|
2026-01-30 11:47:32 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
|
|
if (!verifyGpsAndMissionStateSuccess) {
|
|
|
|
|
|
if (verifyGpsAndMissionStateTimes < maxRetries) {
|
|
|
|
|
|
mainHandler.postDelayed(new Runnable() {
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public void run() {
|
|
|
|
|
|
verifyGpsAndMissionStateTimes++;
|
|
|
|
|
|
verifyGpsAndMissionState(message);
|
|
|
|
|
|
sendEvent2Server("航线状态第" + verifyGpsAndMissionStateTimes + "次检索失败:" +
|
|
|
|
|
|
WaypointMissionExecuteState.find(missionStateCode).name() +
|
|
|
|
|
|
"-RTK:" + Movement.getInstance().getIs_fixed() + "-飞行器状态:" +
|
|
|
|
|
|
Movement.getInstance().getPlaneMessage() +
|
|
|
|
|
|
"-GPS信号等级:" + Movement.getInstance().getQuality(), 1);
|
|
|
|
|
|
}
|
2026-03-12 14:57:34 +08:00
|
|
|
|
}, 2000);
|
2026-01-30 11:47:32 +08:00
|
|
|
|
|
2026-03-12 14:57:34 +08:00
|
|
|
|
} else {
|
2026-01-30 11:47:32 +08:00
|
|
|
|
sendEvent2Server("飞行器自检异常:" + WaypointMissionExecuteState.find(missionStateCode).name() +
|
|
|
|
|
|
"-RTK:" + Movement.getInstance().getIs_fixed() + "-飞行器状态:" +
|
|
|
|
|
|
Movement.getInstance().getPlaneMessage() +
|
|
|
|
|
|
"-GPS信号等级:" + Movement.getInstance().getQuality(), 2);
|
|
|
|
|
|
|
|
|
|
|
|
TaskFailManager.getInstance().sendTaskFailMsg2Server(-1);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 5.下载航线
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param message
|
|
|
|
|
|
*/
|
|
|
|
|
|
public void downLoadKMZFile(MessageDown message) {
|
|
|
|
|
|
Movement.getInstance().setTask_current_step(16);
|
|
|
|
|
|
Request request = new Request.Builder().url(message.getData().getFile().getUrl()).build();
|
|
|
|
|
|
new OkHttpClient().newCall(request).enqueue(new Callback() {
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public void onFailure(Call call, IOException e) {
|
|
|
|
|
|
sendEvent2Server("任务下载失败:" + e.toString(), 2);
|
|
|
|
|
|
TaskFailManager.getInstance().sendTaskFailMsg2Server(-1);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public void onResponse(Call call, Response response) throws IOException {
|
|
|
|
|
|
if (response != null) {
|
|
|
|
|
|
InputStream is = null;
|
|
|
|
|
|
byte[] buf = new byte[2048];
|
|
|
|
|
|
int len = 0;
|
|
|
|
|
|
FileOutputStream fos = null;
|
|
|
|
|
|
// 储存下载文件的目录
|
|
|
|
|
|
File dir = new File(Environment.getExternalStorageDirectory().getPath());
|
|
|
|
|
|
if (!dir.exists()) {
|
|
|
|
|
|
dir.mkdirs();
|
|
|
|
|
|
}
|
|
|
|
|
|
File file = new File(dir, "aros.kmz");
|
|
|
|
|
|
try {
|
|
|
|
|
|
is = response.body().byteStream();
|
|
|
|
|
|
fos = new FileOutputStream(file);
|
|
|
|
|
|
while ((len = is.read(buf)) != -1) {
|
|
|
|
|
|
fos.write(buf, 0, len);
|
|
|
|
|
|
}
|
|
|
|
|
|
fos.flush();
|
|
|
|
|
|
sendEvent2Server("航线下载成功 ", 1);
|
|
|
|
|
|
mainHandler.post(new Runnable() {
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public void run() {
|
|
|
|
|
|
pushKMZFileToAircraft(message);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
|
sendEvent2Server("任务下载失败,网络异常:" + e.toString(), 2);
|
|
|
|
|
|
TaskFailManager.getInstance().sendTaskFailMsg2Server(-1);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private int pushKMZFileTimes = 0;
|
|
|
|
|
|
public static long pushKMZFailTimeMillis;
|
|
|
|
|
|
public boolean isPushKMZSuccess;
|
|
|
|
|
|
|
|
|
|
|
|
public boolean isPushKMZFailTimes() {
|
|
|
|
|
|
long time = System.currentTimeMillis();
|
|
|
|
|
|
if (time - pushKMZFailTimeMillis > 3000) {
|
|
|
|
|
|
pushKMZFailTimeMillis = time;
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 6.上传航线
|
2026-03-12 14:57:34 +08:00
|
|
|
|
*
|
2026-01-30 11:47:32 +08:00
|
|
|
|
* @param message
|
|
|
|
|
|
*/
|
|
|
|
|
|
private void pushKMZFileToAircraft(MessageDown message) {
|
|
|
|
|
|
Boolean isConnect = KeyManager.getInstance().getValue(KeyTools.createKey(FlightControllerKey.
|
|
|
|
|
|
KeyConnection));
|
|
|
|
|
|
if (isConnect != null && isConnect) {
|
|
|
|
|
|
|
|
|
|
|
|
KMZInfo kmzInfo = WPMZManager.getInstance().getKMZInfo(
|
|
|
|
|
|
Environment.getExternalStorageDirectory().getPath() + "/" + "aros.kmz");
|
|
|
|
|
|
if (kmzInfo != null) {
|
|
|
|
|
|
// Utils.printJson(TAG,"航点详情:"+new Gson().toJson(kmzInfo));
|
|
|
|
|
|
WaylineWaylinesParseInfo waylineWaylinesParseInfo = kmzInfo.getWaylineWaylinesParseInfo();
|
|
|
|
|
|
if (waylineWaylinesParseInfo != null) {
|
|
|
|
|
|
List<Wayline> waylines = waylineWaylinesParseInfo.getWaylines();
|
|
|
|
|
|
if (waylines != null && waylines.size() > 0) {
|
|
|
|
|
|
List<WaylineExecuteWaypoint> waypoints = waylines.get(0).getWaypoints();
|
2026-03-12 14:57:34 +08:00
|
|
|
|
if (waypoints != null && waypoints.size() > 0) {
|
2026-01-30 11:47:32 +08:00
|
|
|
|
|
2026-03-12 14:57:34 +08:00
|
|
|
|
CurrentWayline.getInstance().setWaypoints(waypoints);
|
2026-01-30 11:47:32 +08:00
|
|
|
|
|
|
|
|
|
|
LogUtil.log(TAG, "该航线有" + waypoints.size() + "个航点");
|
|
|
|
|
|
} else {
|
|
|
|
|
|
LogUtil.log(TAG, "WPMZManager getWaypointInfo有误");
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
LogUtil.log(TAG, "WPMZManager getTemplates有误");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
LogUtil.log(TAG, "WPMZManager getKMZInfo有误");
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
LogUtil.log(TAG, "WPMZManager getKMZInfo有误");
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
WaypointMissionManager.getInstance().pushKMZFileToAircraft(Environment.getExternalStorageDirectory().getPath() + "/" + "aros.kmz", new CommonCallbacks.CompletionCallbackWithProgress<Double>() {
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public void onProgressUpdate(Double progress) {
|
|
|
|
|
|
sendEvent2Server("航线上传进度:" + progress, 1);
|
|
|
|
|
|
Movement.getInstance().setTask_current_step(17);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public void onSuccess() {
|
2026-03-12 14:57:34 +08:00
|
|
|
|
Movement.getInstance().setWaylinename("aros");
|
|
|
|
|
|
|
2026-01-30 11:47:32 +08:00
|
|
|
|
// "2": "起飞准备完毕",
|
|
|
|
|
|
Movement.getInstance().setMode_code(2);
|
2026-03-12 14:57:34 +08:00
|
|
|
|
LogUtil.log(TAG, "航线上传成功,准备执行任务");
|
2026-01-30 11:47:32 +08:00
|
|
|
|
sendEvent2Server("航线上传成功,准备执行任务", 1);
|
|
|
|
|
|
isPushKMZSuccess = true;
|
|
|
|
|
|
mainHandler.postDelayed(new Runnable() {
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public void run() {
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 7.开始任务
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
//自主起飞
|
|
|
|
|
|
Movement.getInstance().setMode_code(4);
|
2026-03-12 14:57:34 +08:00
|
|
|
|
|
2026-01-30 11:47:32 +08:00
|
|
|
|
Movement.getInstance().setTask_current_step(22);
|
2026-02-27 10:18:56 +08:00
|
|
|
|
//关闭避障
|
|
|
|
|
|
PerceptionManager.getInstance().setPerceptionEnable(false);
|
|
|
|
|
|
PerceptionManager.getInstance().setObstacleAvoidanceHorizontalEnabled(false);
|
2026-01-30 11:47:32 +08:00
|
|
|
|
|
|
|
|
|
|
startMission(message);
|
|
|
|
|
|
pushKMZFileTimes = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
}, 2000);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public void onFailure(@NonNull IDJIError error) {
|
|
|
|
|
|
|
|
|
|
|
|
if (!isPushKMZSuccess) {
|
|
|
|
|
|
if (pushKMZFileTimes < 10) {
|
|
|
|
|
|
if (isPushKMZFailTimes()) {
|
|
|
|
|
|
mainHandler.postDelayed(new Runnable() {
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public void run() {
|
|
|
|
|
|
LogUtil.log(TAG, "上传航线第" + pushKMZFileTimes + "次失败,重新上传" + ":" + new Gson().toJson(error));
|
|
|
|
|
|
pushKMZFileTimes++;
|
|
|
|
|
|
pushKMZFileToAircraft(message);
|
|
|
|
|
|
}
|
|
|
|
|
|
}, 3000);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
LogUtil.log(TAG, "上传航线只处理一次回调" + ":" + new Gson().toJson(error));
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
//待机
|
|
|
|
|
|
Movement.getInstance().setMode_code(0);
|
2026-03-12 14:57:34 +08:00
|
|
|
|
|
2026-01-30 11:47:32 +08:00
|
|
|
|
|
|
|
|
|
|
sendEvent2Server("航线第" + pushKMZFileTimes + "次上传失败,直接关机", 2);
|
|
|
|
|
|
TaskFailManager.getInstance().sendTaskFailMsg2Server(-1);
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
sendEvent2Server("航线上传已经执行onSuccess回调:" + WaypointMissionExecuteState.find(Movement.getInstance().getMissionStateCode()).name(), 1);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private int startMissionFailTimes = 0;
|
|
|
|
|
|
private boolean isMissionStart = false;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 6.开始航线
|
2026-03-12 14:57:34 +08:00
|
|
|
|
*
|
2026-01-30 11:47:32 +08:00
|
|
|
|
* @param message
|
|
|
|
|
|
*/
|
|
|
|
|
|
public void startMission(MessageDown message) {
|
|
|
|
|
|
Boolean isConnect = KeyManager.getInstance().getValue(KeyTools.createKey(FlightControllerKey.
|
|
|
|
|
|
KeyConnection));
|
|
|
|
|
|
if (isConnect != null && isConnect) {
|
|
|
|
|
|
int missionStateCode = Movement.getInstance().getMissionStateCode();
|
|
|
|
|
|
//每次航线开始时,重置是否需要识别二维码状态,避免刚起飞就识别二维码/并确保不是飞向备降点的航线
|
|
|
|
|
|
PreferenceUtils.getInstance().setNeedTriggerApronArucoLand(false);
|
|
|
|
|
|
PreferenceUtils.getInstance().setNeedTriggerAlterArucoLand(false);
|
|
|
|
|
|
PreferenceUtils.getInstance().setTriggerToAlternatePoint(false);
|
|
|
|
|
|
PreferenceUtils.getInstance().setFlightId(message.getData().getFlight_id());
|
2026-03-12 14:57:34 +08:00
|
|
|
|
CommonCallbacks.CompletionCallback callback = new CommonCallbacks.CompletionCallback() {
|
2026-01-30 11:47:32 +08:00
|
|
|
|
@Override
|
|
|
|
|
|
public void onSuccess() {
|
|
|
|
|
|
isMissionStart = true;
|
|
|
|
|
|
LogUtil.log(TAG, "航线第" + startMissionFailTimes + "次开始成功");
|
|
|
|
|
|
Movement.getInstance().setTask_status("in_progress");
|
|
|
|
|
|
startMissionFailTimes = 0;
|
|
|
|
|
|
sendEvent2Server("任务开始执行", 1);
|
|
|
|
|
|
Movement.getInstance().setTask_current_step(23);
|
2026-03-12 14:57:34 +08:00
|
|
|
|
|
2026-01-30 11:47:32 +08:00
|
|
|
|
// Movement.getInstance().setMode_code(5);
|
|
|
|
|
|
|
|
|
|
|
|
// // 自动起飞
|
|
|
|
|
|
// Movement.getInstance().setMode_code(4);
|
|
|
|
|
|
//
|
|
|
|
|
|
// new android.os.Handler(android.os.Looper.getMainLooper()).postDelayed(() -> {
|
|
|
|
|
|
// Movement.getInstance().setMode_code(5);
|
|
|
|
|
|
// }, 2000);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public void onFailure(@NonNull IDJIError error) {
|
|
|
|
|
|
LogUtil.log(TAG, "航线执行失败:" + new Gson().toJson(error));
|
|
|
|
|
|
if (!isMissionStart) {
|
|
|
|
|
|
if (missionStateCode != 3 && missionStateCode != 4 && missionStateCode != 5 && missionStateCode != 6
|
|
|
|
|
|
&& missionStateCode != 7 && missionStateCode != 8 && missionStateCode != 9 && missionStateCode != 10) {
|
|
|
|
|
|
if (startMissionFailTimes < 50) {
|
|
|
|
|
|
mainHandler.postDelayed(new Runnable() {
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public void run() {
|
|
|
|
|
|
startMission(message);
|
|
|
|
|
|
sendEvent2Server("航线第" + startMissionFailTimes + "次开始失败" + "---" + new Gson().toJson(error) + "--" + Movement.getInstance().getQuality(), 2);
|
|
|
|
|
|
startMissionFailTimes++;
|
|
|
|
|
|
}
|
|
|
|
|
|
}, 2000);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
if (!Movement.getInstance().isPlaneWing()) {
|
|
|
|
|
|
|
|
|
|
|
|
//待机
|
|
|
|
|
|
Movement.getInstance().setMode_code(0);
|
2026-03-12 14:57:34 +08:00
|
|
|
|
|
2026-01-30 11:47:32 +08:00
|
|
|
|
|
|
|
|
|
|
sendEvent2Server("航线第" + startMissionFailTimes + "次开始失败,直接关机:" + "---" + new Gson().toJson(error) + "--" + Movement.getInstance().getQuality(), 2);
|
|
|
|
|
|
TaskFailManager.getInstance().sendTaskFailMsg2Server(-1);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
sendEvent2Server("航线已经执行:" + WaypointMissionExecuteState.find(missionStateCode).name(), 1);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2026-03-12 14:57:34 +08:00
|
|
|
|
if (message.getData() != null && message.getData().getBreak_point() != null && message.getData().getBreak_point().getIndex() > 0) {
|
|
|
|
|
|
BreakPointInfo breakPointInfo = new BreakPointInfo
|
2026-01-30 11:47:32 +08:00
|
|
|
|
(message.getData().getBreak_point().getWayline_id(),
|
|
|
|
|
|
message.getData().getBreak_point().getIndex(),
|
|
|
|
|
|
message.getData().getBreak_point().getProgress());
|
2026-03-12 14:57:34 +08:00
|
|
|
|
WaypointMissionManager.getInstance().startMission("aros", breakPointInfo,
|
2026-01-30 11:47:32 +08:00
|
|
|
|
callback);
|
2026-03-12 14:57:34 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
WaypointMissionManager.getInstance().startMission("aros", callback);
|
2026-01-30 11:47:32 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
sendEvent2Server("任务开始失败,设备未连接", 2);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 暂停航线
|
2026-03-12 14:57:34 +08:00
|
|
|
|
*
|
2026-01-30 11:47:32 +08:00
|
|
|
|
* @param message
|
|
|
|
|
|
*/
|
|
|
|
|
|
public void pauseMission(MessageDown message) {
|
|
|
|
|
|
|
|
|
|
|
|
Boolean isConnect = KeyManager.getInstance().getValue(KeyTools.createKey(FlightControllerKey.
|
|
|
|
|
|
KeyConnection));
|
|
|
|
|
|
if (isConnect != null && isConnect) {
|
|
|
|
|
|
IWaypointMissionManager missionManager = WaypointMissionManager.getInstance();
|
|
|
|
|
|
missionManager.pauseMission(new CommonCallbacks.CompletionCallback() {
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public void onSuccess() {
|
|
|
|
|
|
sendMsg2Server(message);
|
|
|
|
|
|
Movement.getInstance().setTask_status("paused");
|
2026-03-12 14:57:34 +08:00
|
|
|
|
|
2026-01-30 11:47:32 +08:00
|
|
|
|
|
|
|
|
|
|
//暂停成功就是手动飞行
|
|
|
|
|
|
Movement.getInstance().setMode_code(3);
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public void onFailure(@NonNull IDJIError error) {
|
2026-03-12 14:57:34 +08:00
|
|
|
|
sendFailMsg2Server(message, "航线任务暂停失败:" + getIDJIErrorMsg(error));
|
2026-01-30 11:47:32 +08:00
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
} else {
|
|
|
|
|
|
LogUtil.log(TAG, "航线任务暂停失败:飞控未连接");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//恢复航线
|
|
|
|
|
|
public void resumeMission(MessageDown message) {
|
|
|
|
|
|
Boolean isConnect = KeyManager.getInstance().getValue(KeyTools.createKey(FlightControllerKey.
|
|
|
|
|
|
KeyConnection));
|
|
|
|
|
|
if (isConnect != null && isConnect) {
|
|
|
|
|
|
IWaypointMissionManager missionManager = WaypointMissionManager.getInstance();
|
|
|
|
|
|
//如果航线是暂停状态,直接恢复航线,否则查询断点信息
|
|
|
|
|
|
|
|
|
|
|
|
if (Movement.getInstance().getMissionStateCode() == 7) {
|
|
|
|
|
|
missionManager.resumeMission(new CommonCallbacks.CompletionCallback() {
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public void onSuccess() {
|
|
|
|
|
|
sendMsg2Server(message);
|
|
|
|
|
|
Movement.getInstance().setTask_status("in_progress");
|
2026-03-12 14:57:34 +08:00
|
|
|
|
|
2026-01-30 11:47:32 +08:00
|
|
|
|
//继续就是指令 或者 航线
|
2026-03-12 14:57:34 +08:00
|
|
|
|
if (Movement.getInstance().getFlightmode() == 1) {
|
2026-01-30 11:47:32 +08:00
|
|
|
|
Movement.getInstance().setMode_code(5);
|
2026-03-12 14:57:34 +08:00
|
|
|
|
} else if (Movement.getInstance().getFlightmode() == 2) {
|
2026-01-30 11:47:32 +08:00
|
|
|
|
Movement.getInstance().setMode_code(17);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public void onFailure(@NonNull IDJIError error) {
|
|
|
|
|
|
sendFailMsg2Server(message, "航线继续失败:" + getIDJIErrorMsg(error));
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
} else {
|
|
|
|
|
|
missionManager.queryBreakPointInfoFromAircraft("aros", new CommonCallbacks.CompletionCallbackWithParam<BreakPointInfo>() {
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public void onSuccess(BreakPointInfo breakPointInfo) {
|
|
|
|
|
|
if (breakPointInfo != null) {
|
|
|
|
|
|
LogUtil.log(TAG, "查询断点成功:" + new Gson().toJson(breakPointInfo));
|
|
|
|
|
|
mainHandler.postDelayed(new Runnable() {
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public void run() {
|
|
|
|
|
|
WaypointMissionManager.getInstance().startMission("aros", breakPointInfo,
|
|
|
|
|
|
new CommonCallbacks.CompletionCallback() {
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public void onSuccess() {
|
|
|
|
|
|
sendMsg2Server(message);
|
|
|
|
|
|
PreferenceUtils.getInstance().setIsNewRoute(false);
|
|
|
|
|
|
LogUtil.log(TAG, "恢复断点航线成功");
|
|
|
|
|
|
Movement.getInstance().setTask_status("in_progress");
|
2026-03-12 14:57:34 +08:00
|
|
|
|
|
2026-01-30 11:47:32 +08:00
|
|
|
|
}
|
2026-03-12 14:57:34 +08:00
|
|
|
|
|
2026-01-30 11:47:32 +08:00
|
|
|
|
@Override
|
|
|
|
|
|
public void onFailure(@NonNull IDJIError idjiError) {
|
|
|
|
|
|
LogUtil.log(TAG, "恢复断点航线失败:" + getIDJIErrorMsg(idjiError));
|
|
|
|
|
|
sendFailMsg2Server(message, "恢复断点航线失败:" + getIDJIErrorMsg(idjiError));
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
}, 500);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
LogUtil.log(TAG, "未查询到断点信息");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-03-12 14:57:34 +08:00
|
|
|
|
|
2026-01-30 11:47:32 +08:00
|
|
|
|
@Override
|
|
|
|
|
|
public void onFailure(@NonNull IDJIError idjiError) {
|
|
|
|
|
|
LogUtil.log(TAG, "查询断点失败:" + getIDJIErrorMsg(idjiError));
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
LogUtil.log(TAG, "设备未连接");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void checkVtxWithDelay(Runnable onVtxReady) {
|
|
|
|
|
|
|
|
|
|
|
|
if (Movement.getInstance().isVtx()) {
|
|
|
|
|
|
// 图传正常,直接继续后面的流程
|
|
|
|
|
|
PreferenceUtils.getInstance().setRestartAMSTimes(0);
|
|
|
|
|
|
LogUtil.log(TAG, "图传正常,继续执行任务流程");
|
|
|
|
|
|
onVtxReady.run();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
LogUtil.log(TAG, "未检测到图传,5 秒后再次确认...");
|
|
|
|
|
|
|
|
|
|
|
|
mainHandler.postDelayed(() -> {
|
|
|
|
|
|
if (!Movement.getInstance().isVtx()) {
|
|
|
|
|
|
// 图传仍未恢复 → 执行重启逻辑
|
|
|
|
|
|
int times = PreferenceUtils.getInstance().getRestartAMSTimes();
|
|
|
|
|
|
if (times < 5) {
|
|
|
|
|
|
PreferenceUtils.getInstance().setRestartAMSTimes(times + 1);
|
|
|
|
|
|
LogUtil.log(TAG, "图传仍未恢复,重启 AMS 第 " + (times + 1) + " 次");
|
|
|
|
|
|
RestartAPPTool.INSTANCE.restartApp(ApronApp.Companion.getContext());
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// 图传恢复 → 执行后续逻辑
|
|
|
|
|
|
PreferenceUtils.getInstance().setRestartAMSTimes(0);
|
|
|
|
|
|
LogUtil.log(TAG, "图传在延迟期间恢复,继续执行任务流程");
|
|
|
|
|
|
onVtxReady.run();
|
|
|
|
|
|
}
|
|
|
|
|
|
}, 5000);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|