增加飞行日志
This commit is contained in:
parent
ec9e18163b
commit
b3090457a4
|
|
@ -53,6 +53,11 @@ public interface BusinessConstant {
|
||||||
String FLY_TO_POINT_PROGRESS = "fly_to_point_progress";
|
String FLY_TO_POINT_PROGRESS = "fly_to_point_progress";
|
||||||
String FILE_UPLOAD_CALLBACK = "file_upload_callback";
|
String FILE_UPLOAD_CALLBACK = "file_upload_callback";
|
||||||
String FILEUPLOAD_PROGRESS = "fileupload_progress";
|
String FILEUPLOAD_PROGRESS = "fileupload_progress";
|
||||||
|
String FLIGHTTASK_READY = "flighttask_ready";
|
||||||
|
String RETURN_HOME_INFO = "return_home_info";
|
||||||
|
String DEVICE_EXIT_HOMING_NOTIFY = "device_exit_homing_notify";
|
||||||
|
String IN_FLIGHT_WAYLINE_PROGRESS = "in_flight_wayline_progress";
|
||||||
|
String OBSTACLE_AVOIDANCE_NOTIFY = "obstacle_avoidance_notify";
|
||||||
String OTA_PROGRESS = "ota_progress";
|
String OTA_PROGRESS = "ota_progress";
|
||||||
String HMS = "hms";
|
String HMS = "hms";
|
||||||
//********************************* dj status topic method *********************************//
|
//********************************* dj status topic method *********************************//
|
||||||
|
|
|
||||||
|
|
@ -83,6 +83,15 @@ public class FlightTaskController {
|
||||||
return new Result<List<JSONObject>>().ok(data);
|
return new Result<List<JSONObject>>().ok(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/getFlightLog/{taskId}")
|
||||||
|
@Operation(summary = "飞行日志")
|
||||||
|
@RequiresPermissions("bus:task:flightLog")
|
||||||
|
public Result<List<JSONObject>> getFlightLog(@PathVariable("taskId") String taskId) {
|
||||||
|
List<JSONObject> data = flightTaskService.getFlightLog(taskId);
|
||||||
|
|
||||||
|
return new Result<List<JSONObject>>().ok(data);
|
||||||
|
}
|
||||||
|
|
||||||
@GetMapping("/getTaskMedia/{taskId}")
|
@GetMapping("/getTaskMedia/{taskId}")
|
||||||
@Operation(summary = "媒体文件")
|
@Operation(summary = "媒体文件")
|
||||||
@RequiresPermissions("bus:task:taskMedia")
|
@RequiresPermissions("bus:task:taskMedia")
|
||||||
|
|
|
||||||
|
|
@ -6,15 +6,14 @@ import cn.hutool.json.JSONObject;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
import com.multictrl.common.config.MinioConfig;
|
import com.multictrl.common.config.MinioConfig;
|
||||||
import com.multictrl.common.constant.BusinessConstant;
|
import com.multictrl.common.constant.BusinessConstant;
|
||||||
import com.multictrl.common.utils.CacheUtils;
|
import com.multictrl.common.utils.*;
|
||||||
import com.multictrl.common.utils.FfmpegUtils;
|
|
||||||
import com.multictrl.common.utils.JsonUtils;
|
|
||||||
import com.multictrl.common.utils.Utils;
|
|
||||||
import com.multictrl.modules.business.dao.HmsDao;
|
import com.multictrl.modules.business.dao.HmsDao;
|
||||||
import com.multictrl.modules.business.dto.MediaFileDTO;
|
import com.multictrl.modules.business.dto.MediaFileDTO;
|
||||||
import com.multictrl.modules.business.entity.HmsEntity;
|
import com.multictrl.modules.business.entity.HmsEntity;
|
||||||
import com.multictrl.modules.business.entity.RemoteLogEntity;
|
import com.multictrl.modules.business.entity.RemoteLogEntity;
|
||||||
|
import com.multictrl.modules.business.influxdb.FlightLog;
|
||||||
import com.multictrl.modules.business.service.CommandService;
|
import com.multictrl.modules.business.service.CommandService;
|
||||||
|
import com.multictrl.modules.business.service.InfluxService;
|
||||||
import com.multictrl.modules.business.service.MediaFileService;
|
import com.multictrl.modules.business.service.MediaFileService;
|
||||||
import com.multictrl.modules.business.service.MqttPushService;
|
import com.multictrl.modules.business.service.MqttPushService;
|
||||||
import com.multictrl.modules.business.service.RemoteLogService;
|
import com.multictrl.modules.business.service.RemoteLogService;
|
||||||
|
|
@ -22,6 +21,7 @@ import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
import java.time.OffsetDateTime;
|
import java.time.OffsetDateTime;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
@ -43,6 +43,7 @@ public class EventsHandler implements MessageHandler {
|
||||||
private final RemoteLogService remoteLogService;
|
private final RemoteLogService remoteLogService;
|
||||||
private final MinioConfig minioConfig;
|
private final MinioConfig minioConfig;
|
||||||
private final HmsDao hmsDao;
|
private final HmsDao hmsDao;
|
||||||
|
private final InfluxService influxService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleMessage(String topic, String payload, String gateway) {
|
public void handleMessage(String topic, String payload, String gateway) {
|
||||||
|
|
@ -89,6 +90,8 @@ public class EventsHandler implements MessageHandler {
|
||||||
CacheUtils.set(BusinessConstant.FLIGHT_TASK_PROGRESS_FLIGHT_ID + gateway, ext.getStr("flight_id"));
|
CacheUtils.set(BusinessConstant.FLIGHT_TASK_PROGRESS_FLIGHT_ID + gateway, ext.getStr("flight_id"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//飞行日志
|
||||||
|
saveFlightTaskProgressLog(message, data, gateway);
|
||||||
} else if (BusinessConstant.TAKEOFF_TO_POINT_PROGRESS.equals(method)) {
|
} else if (BusinessConstant.TAKEOFF_TO_POINT_PROGRESS.equals(method)) {
|
||||||
log.debug("events --> 一键起飞结果上报: {}", payload);
|
log.debug("events --> 一键起飞结果上报: {}", payload);
|
||||||
JSONObject data = message.getJSONObject(BusinessConstant.DATA);
|
JSONObject data = message.getJSONObject(BusinessConstant.DATA);
|
||||||
|
|
@ -193,6 +196,22 @@ public class EventsHandler implements MessageHandler {
|
||||||
hmsList.add(hmsEntity);
|
hmsList.add(hmsEntity);
|
||||||
}
|
}
|
||||||
hmsDao.insert(hmsList);
|
hmsDao.insert(hmsList);
|
||||||
|
//飞行日志
|
||||||
|
for (HmsEntity hmsEntity : hmsList) {
|
||||||
|
FlightLog flightLog = new FlightLog();
|
||||||
|
flightLog.setDockSn(hmsEntity.getDockSn());
|
||||||
|
flightLog.setTime(hmsEntity.getReportDate().toInstant());
|
||||||
|
flightLog.setMethod("健康告警\n" + BusinessConstant.HMS);
|
||||||
|
flightLog.setLevel(hmsEntity.getLevel());
|
||||||
|
flightLog.setMessage(
|
||||||
|
"模块: " + hmsEntity.getModule() + "\n" +
|
||||||
|
"告警码: " + hmsEntity.getCode() + "\n" +
|
||||||
|
"告警信息: " + HmsUtils.getHmsText(hmsEntity.getCode()) + "\n" +
|
||||||
|
"设备类型: " + hmsEntity.getDeviceType() + "\n" +
|
||||||
|
"即时性: " + hmsEntity.getImminent() + "\n" +
|
||||||
|
"飞行状态: " + hmsEntity.getInTheSky());
|
||||||
|
influxService.addRecord(flightLog);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (BusinessConstant.FILEUPLOAD_PROGRESS.equals(method)) {
|
} else if (BusinessConstant.FILEUPLOAD_PROGRESS.equals(method)) {
|
||||||
|
|
@ -241,9 +260,368 @@ public class EventsHandler implements MessageHandler {
|
||||||
}
|
}
|
||||||
} else if (BusinessConstant.OTA_PROGRESS.equals(method)) {
|
} else if (BusinessConstant.OTA_PROGRESS.equals(method)) {
|
||||||
log.debug("events --> 固件升级进度: {}", payload);
|
log.debug("events --> 固件升级进度: {}", payload);
|
||||||
|
} else if (BusinessConstant.FLIGHTTASK_READY.equals(method)) {
|
||||||
|
log.debug("events --> 航线任务准备就绪: {}", payload);
|
||||||
|
JSONObject data = message.getJSONObject(BusinessConstant.DATA);
|
||||||
|
if (data != null) {
|
||||||
|
JSONArray flightIds = data.getJSONArray("flight_ids");
|
||||||
|
//飞行日志
|
||||||
|
FlightLog flightLog = new FlightLog();
|
||||||
|
flightLog.setDockSn(gateway);
|
||||||
|
flightLog.setLevel(0);
|
||||||
|
flightLog.setMethod("任务准备就绪\n" + BusinessConstant.FLIGHTTASK_READY);
|
||||||
|
flightLog.setTime(Instant.ofEpochMilli(message.getLong("timestamp")));
|
||||||
|
flightLog.setMessage("航线任务准备就绪:" + flightIds.toString());
|
||||||
|
influxService.addRecord(flightLog);
|
||||||
|
}
|
||||||
|
} else if (BusinessConstant.RETURN_HOME_INFO.equals(method)) {
|
||||||
|
log.debug("events --> 返航信息: {}", payload);
|
||||||
|
//飞行日志
|
||||||
|
JSONObject data = message.getJSONObject(BusinessConstant.DATA);
|
||||||
|
if (data != null) {
|
||||||
|
FlightLog flightLog = new FlightLog();
|
||||||
|
flightLog.setDockSn(gateway);
|
||||||
|
flightLog.setTime(Instant.ofEpochMilli(message.getLong("timestamp")));
|
||||||
|
flightLog.setMethod("返航信息\n" + BusinessConstant.RETURN_HOME_INFO);
|
||||||
|
flightLog.setLevel(0);
|
||||||
|
|
||||||
|
int lastPointType = data.getInt("last_point_type", -1);
|
||||||
|
String lastPointTypeCn = lastPointType == 0 ? "轨迹最后一个点在返航点的上空"
|
||||||
|
: lastPointType == 1 ? "轨迹最后一个点不在返航点上空" : String.valueOf(lastPointType);
|
||||||
|
|
||||||
|
StringBuilder msg = new StringBuilder();
|
||||||
|
msg.append("任务ID: ").append(data.getStr("flight_id", "")).append("\n");
|
||||||
|
msg.append("最后轨迹点类型: ").append(lastPointTypeCn).append("\n");
|
||||||
|
if (data.containsKey("home_dock_sn")) {
|
||||||
|
msg.append("Home点机场SN: ").append(data.getStr("home_dock_sn")).append("\n");
|
||||||
|
}
|
||||||
|
JSONArray points = data.getJSONArray("planned_path_points");
|
||||||
|
if (points != null && !points.isEmpty()) {
|
||||||
|
msg.append("规划轨迹点(").append(points.size()).append("个):\n");
|
||||||
|
for (int i = 0; i < points.size(); i++) {
|
||||||
|
JSONObject point = points.getJSONObject(i);
|
||||||
|
msg.append(i + 1).append(". 纬度: ").append(point.getDouble("latitude", 0d))
|
||||||
|
.append(" 经度: ").append(point.getDouble("longitude", 0d))
|
||||||
|
.append(" 高度: ").append(point.getDouble("height", 0d)).append("m\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
JSONArray homeInfo = data.getJSONArray("multi_dock_home_info");
|
||||||
|
if (homeInfo != null && !homeInfo.isEmpty()) {
|
||||||
|
msg.append("蛙跳任务返航信息:\n");
|
||||||
|
for (int i = 0; i < homeInfo.size(); i++) {
|
||||||
|
JSONObject info = homeInfo.getJSONObject(i);
|
||||||
|
int planStatus = info.getInt("plan_status", -1);
|
||||||
|
String planStatusCn = planStatus == 0 ? "规划失败或正在规划中"
|
||||||
|
: planStatus == 1 ? "规划路径不可达"
|
||||||
|
: planStatus == 2 ? "规划路径因电量不可达"
|
||||||
|
: planStatus == 3 ? "目标可达" : String.valueOf(planStatus);
|
||||||
|
msg.append(" 机场SN: ").append(info.getStr("sn", "")).append("\n");
|
||||||
|
msg.append(" 路径规划状态: ").append(planStatusCn).append("\n");
|
||||||
|
msg.append(" 预估电量消耗: ").append(info.getInt("estimated_battery_consumption", 0)).append("%\n");
|
||||||
|
msg.append(" Home点距离: ").append(info.getDouble("home_distance", 0d)).append("m\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
flightLog.setMessage(msg.toString());
|
||||||
|
influxService.addRecord(flightLog);
|
||||||
|
}
|
||||||
|
} else if (BusinessConstant.DEVICE_EXIT_HOMING_NOTIFY.equals(method)) {
|
||||||
|
log.debug("events --> 设备返航退出状态通知: {}", payload);
|
||||||
|
JSONObject data = message.getJSONObject(BusinessConstant.DATA);
|
||||||
|
//飞行日志
|
||||||
|
if (data != null) {
|
||||||
|
Long timestamp = message.getLong("timestamp");
|
||||||
|
String dockSn = data.getStr("sn");
|
||||||
|
String action = data.getInt("action") == 0 ? "退出返航退出状态" : "进入返航退出状态";
|
||||||
|
Integer reason = data.getInt("reason");
|
||||||
|
String reasonCn = switch (reason) {
|
||||||
|
case 0 -> "操纵杆油门添加";
|
||||||
|
case 1 -> "操纵杆间距添加";
|
||||||
|
case 2 -> "行为树初始化失败";
|
||||||
|
case 3 -> "被障碍物包围";
|
||||||
|
case 4 -> "触发限飞限制";
|
||||||
|
case 5 -> "障碍物距离太近";
|
||||||
|
case 6 -> "无 GPS 信号";
|
||||||
|
case 7 -> "GPS 和 VIO 位置输出标志为 false";
|
||||||
|
case 8 -> "GPS 和 VIO 融合位置误差太大";
|
||||||
|
case 9 -> "短距离回溯";
|
||||||
|
case 10 -> "近距离触发返航";
|
||||||
|
default -> reason + "";
|
||||||
|
};
|
||||||
|
FlightLog flightLog = new FlightLog();
|
||||||
|
flightLog.setDockSn(dockSn);
|
||||||
|
flightLog.setLevel(0);
|
||||||
|
flightLog.setTime(Instant.ofEpochMilli(timestamp));
|
||||||
|
flightLog.setMethod("设备返航退出状态通知\n" + BusinessConstant.DEVICE_EXIT_HOMING_NOTIFY);
|
||||||
|
flightLog.setMessage(
|
||||||
|
"消息类型: " + action + "\n" +
|
||||||
|
"退出返航原因: " + reasonCn
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else if (BusinessConstant.IN_FLIGHT_WAYLINE_PROGRESS.equals(method)) {
|
||||||
|
log.debug("events --> 空中下发航线状态上报: {}", payload);
|
||||||
|
String inFlightWaylineId = message.getStr("in_flight_wayline_id");
|
||||||
|
Integer percent = null;
|
||||||
|
JSONObject progress = message.getJSONObject("progress");
|
||||||
|
if (progress != null) {
|
||||||
|
percent = progress.getInt("percent");
|
||||||
|
}
|
||||||
|
Integer status = message.getInt("status");
|
||||||
|
String statusCn = switch (status) {
|
||||||
|
case 1 -> "上传文件中";
|
||||||
|
case 2 -> "文件上传成功";
|
||||||
|
case 3 -> "执行任务中";
|
||||||
|
case 4 -> "任务暂停";
|
||||||
|
case 5 -> "任务取消";
|
||||||
|
case 6 -> "任务成功";
|
||||||
|
case 7 -> "任务失败";
|
||||||
|
case 8 -> "任务超时";
|
||||||
|
default -> status + "";
|
||||||
|
};
|
||||||
|
Integer result = message.getInt("result");
|
||||||
|
Integer wayPointIndex = message.getInt("way_point_index");
|
||||||
|
FlightLog flightLog = new FlightLog();
|
||||||
|
flightLog.setDockSn(gateway);
|
||||||
|
flightLog.setLevel(0);
|
||||||
|
flightLog.setMethod("空中下发航线状态上报\n" + BusinessConstant.IN_FLIGHT_WAYLINE_PROGRESS);
|
||||||
|
flightLog.setMessage(
|
||||||
|
"航线任务ID: " + inFlightWaylineId + "\n" +
|
||||||
|
"任务进度: " + percent + "\n" +
|
||||||
|
"任务状态: " + statusCn + "\n" +
|
||||||
|
"错误原因码: " + result + "\n" +
|
||||||
|
"当前航点索引: " + wayPointIndex
|
||||||
|
);
|
||||||
|
influxService.addRecord(flightLog);
|
||||||
|
}else if(BusinessConstant.OBSTACLE_AVOIDANCE_NOTIFY.equals(method)){
|
||||||
|
log.debug("events --> 避障记录上报事件通知: {}", payload);
|
||||||
|
//飞行日志
|
||||||
|
JSONObject data = message.getJSONObject(BusinessConstant.DATA);
|
||||||
|
if (data != null) {
|
||||||
|
String waylineUuid = data.getStr("wayline_uuid", "");
|
||||||
|
String flightId = data.getStr("flight_id", "");
|
||||||
|
boolean isFinalReport = data.getBool("is_final_report", false);
|
||||||
|
JSONArray obstacles = data.getJSONArray("obstacles");
|
||||||
|
StringBuilder msg = new StringBuilder();
|
||||||
|
msg.append("航线ID: ").append(waylineUuid).append("\n");
|
||||||
|
msg.append("任务ID: ").append(flightId).append("\n");
|
||||||
|
if (obstacles != null && !obstacles.isEmpty()) {
|
||||||
|
msg.append("避障记录(").append(obstacles.size()).append("条):\n");
|
||||||
|
for (int i = 0; i < obstacles.size(); i++) {
|
||||||
|
JSONObject obstacle = obstacles.getJSONObject(i);
|
||||||
|
int type = obstacle.getInt("type", -1);
|
||||||
|
String typeCn = switch (type) {
|
||||||
|
case 0 -> "绕行开始(飞控映射到航线上)";
|
||||||
|
case 1 -> "绕行结束(飞控映射到航线上)";
|
||||||
|
case 2 -> "避障刹停(真实物理坐标)";
|
||||||
|
default -> String.valueOf(type);
|
||||||
|
};
|
||||||
|
msg.append(i + 1).append(". 障碍物ID: ").append(obstacle.getInt("id", -1))
|
||||||
|
.append(" 类型: ").append(typeCn)
|
||||||
|
.append(" 时间戳: ").append(obstacle.getLong("timestamp", 0L))
|
||||||
|
.append("\n 纬度: ").append(obstacle.getDouble("latitude", 0d))
|
||||||
|
.append(" 经度: ").append(obstacle.getDouble("longitude", 0d))
|
||||||
|
.append(" 高度: ").append(obstacle.getDouble("height", 0d)).append("m")
|
||||||
|
.append("\n 航段ID: ").append(obstacle.getInt("wayline_id", -1))
|
||||||
|
.append(" 航点索引: ").append(obstacle.getInt("waypoint_index", -1))
|
||||||
|
.append("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
msg.append("是否最后一条: ").append(isFinalReport ? "是" : "否");
|
||||||
|
FlightLog flightLog = new FlightLog();
|
||||||
|
flightLog.setDockSn(gateway);
|
||||||
|
flightLog.setLevel(0);
|
||||||
|
flightLog.setMethod("避障记录上报\n" + BusinessConstant.OBSTACLE_AVOIDANCE_NOTIFY);
|
||||||
|
flightLog.setTime(Instant.ofEpochMilli(message.getLong("timestamp")));
|
||||||
|
flightLog.setMessage(msg.toString());
|
||||||
|
influxService.addRecord(flightLog);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log.debug("events --> payload解析失败,解析后为null");
|
log.debug("events --> payload解析失败,解析后为null");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存航线任务进度飞行日志
|
||||||
|
*/
|
||||||
|
private void saveFlightTaskProgressLog(JSONObject message, JSONObject data, String gateway) {
|
||||||
|
if (data == null || !data.containsKey("output")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
JSONObject output = data.getJSONObject("output");
|
||||||
|
FlightLog flightLog = new FlightLog();
|
||||||
|
flightLog.setDockSn(gateway);
|
||||||
|
flightLog.setTime(Instant.ofEpochMilli(message.getLong("timestamp")));
|
||||||
|
flightLog.setMethod("航线任务进度\n" + BusinessConstant.FLIGHTTASK_PROGRESS);
|
||||||
|
flightLog.setLevel(0);
|
||||||
|
|
||||||
|
String status = output.getStr("status", "");
|
||||||
|
String statusCn = switch (status) {
|
||||||
|
case "canceled" -> "取消或终止";
|
||||||
|
case "failed" -> "失败";
|
||||||
|
case "in_progress" -> "执行中";
|
||||||
|
case "ok" -> "执行成功";
|
||||||
|
case "partially_done" -> "部分完成";
|
||||||
|
case "paused" -> "暂停";
|
||||||
|
case "rejected" -> "拒绝";
|
||||||
|
case "sent" -> "已下发";
|
||||||
|
case "timeout" -> "超时";
|
||||||
|
default -> status;
|
||||||
|
};
|
||||||
|
int currentStep = -1, percent = -1;
|
||||||
|
if (output.containsKey("progress")) {
|
||||||
|
JSONObject progress = output.getJSONObject("progress");
|
||||||
|
currentStep = progress.getInt("current_step", -1);
|
||||||
|
percent = progress.getInt("percent", -1);
|
||||||
|
}
|
||||||
|
String[] stepCn = {
|
||||||
|
"初始状态", "启动前检查,飞行器是否在执行航线中", "启动前检查,机场是否退出工作模式",
|
||||||
|
"启动前检查,航线执行中", "启动前检查,返航中", "航线执行进入准备状态,开始等待任务下发",
|
||||||
|
"机场进入工作状态", "进入开机检查准备工作和开盖准备工作", "图传远程对频",
|
||||||
|
"等待飞行系统准备就绪,推送连接建立", "等待 RTK 源监听有值上报",
|
||||||
|
"检查 RTK 源是否是机场源,如果不是要重新设置", "等待飞行控制权通知",
|
||||||
|
"机场无控制权,抢夺飞行器控制权", "自定义飞行区一致性检查", "离线地图一致性检查",
|
||||||
|
"获取最新 KMZ URL", "下载 KMZ", "KMZ 上传中", "染色配置",
|
||||||
|
"飞行器起飞参数设置,备降点设置,起飞高度设置,染色设置",
|
||||||
|
"飞行器 flyto 起飞参数设置", "起飞机场检查降落机场准备状态", "Home 点设置",
|
||||||
|
"触发执行航线", "航线执行中", "进入返航的检查准备工作", "飞行器降落机场",
|
||||||
|
"降落以后的关盖", "机场退出工作模式", "机场异常恢复", "机场上传飞行系统日志",
|
||||||
|
"相机录像状态检查", "获取媒体文件数量", "机场起飞开盖的异常恢复", "通知任务结果",
|
||||||
|
"日志列表拉取 - 飞行器列表", "日志列表拉取 - 拉取机场列表",
|
||||||
|
"日志列表拉取 - 上传日志列表结果", "日志拉取-拉取飞行器日志",
|
||||||
|
"日志拉取-拉取机场日志", "日志拉取-压缩飞行器日志", "日志拉取-压缩机场日志",
|
||||||
|
"日志拉取-上传飞行器日志", "日志拉取-上传机场日志", "日志拉取-通知结果",
|
||||||
|
"自定义飞行区文件更新准备中", "自定义飞行区更新中", "离线地图更新准备中", "离线地图更新中"
|
||||||
|
};
|
||||||
|
String stepStr = currentStep >= 0 && currentStep < stepCn.length ? stepCn[currentStep] : String.valueOf(currentStep);
|
||||||
|
|
||||||
|
StringBuilder msg = new StringBuilder();
|
||||||
|
msg.append("任务状态: ").append(statusCn).append("\n");
|
||||||
|
msg.append("执行步骤: ").append(stepStr).append("\n");
|
||||||
|
msg.append("进度: ").append(percent).append("%\n");
|
||||||
|
if (output.containsKey("ext")) {
|
||||||
|
JSONObject ext = output.getJSONObject("ext");
|
||||||
|
int missionState = ext.getInt("wayline_mission_state", -1);
|
||||||
|
String[] missionStateCn = {"断连", "不支持该航点", "航线准备状态", "航线文件上传中",
|
||||||
|
"触发开始命令", "进入航线", "航线执行", "航线中断", "航线恢复", "航线停止"};
|
||||||
|
msg.append("航线任务状态: ").append(missionState >= 0 && missionState < missionStateCn.length ? missionStateCn[missionState] : missionState).append("\n");
|
||||||
|
msg.append("当前航点: ").append(ext.getInt("current_waypoint_index", -1)).append("\n");
|
||||||
|
msg.append("航线ID: ").append(ext.getInt("wayline_id", -1)).append("\n");
|
||||||
|
msg.append("任务ID: ").append(ext.getStr("flight_id", "")).append("\n");
|
||||||
|
msg.append("航迹ID: ").append(ext.getStr("track_id", "")).append("\n");
|
||||||
|
msg.append("媒体文件数: ").append(ext.getInt("media_count", 0)).append("\n");
|
||||||
|
if (ext.containsKey("break_point")) {
|
||||||
|
appendBreakPointInfo(msg, ext.getJSONObject("break_point"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
flightLog.setMessage(msg.toString());
|
||||||
|
influxService.addRecord(flightLog);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 拼接断点信息
|
||||||
|
*/
|
||||||
|
private void appendBreakPointInfo(StringBuilder msg, JSONObject bp) {
|
||||||
|
int bpState = bp.getInt("state", -1);
|
||||||
|
int breakReason = bp.getInt("break_reason", 0);
|
||||||
|
msg.append("断点信息:\n");
|
||||||
|
msg.append(" 断点序号: ").append(bp.getInt("index", -1)).append("\n");
|
||||||
|
msg.append(" 断点状态: ").append(bpState == 0 ? "在航段上" : bpState == 1 ? "在航点上" : bpState).append("\n");
|
||||||
|
msg.append(" 航段进度: ").append(bp.getDouble("progress", 0d)).append("\n");
|
||||||
|
msg.append(" 航线ID: ").append(bp.getInt("wayline_id", -1)).append("\n");
|
||||||
|
msg.append(" 中断原因: ").append(getBreakReasonCn(breakReason)).append("\n");
|
||||||
|
msg.append(" 纬度: ").append(bp.getDouble("latitude", 0d)).append("\n");
|
||||||
|
msg.append(" 经度: ").append(bp.getDouble("longitude", 0d)).append("\n");
|
||||||
|
msg.append(" 高度: ").append(bp.getDouble("height", 0d)).append("m\n");
|
||||||
|
msg.append(" 偏航角: ").append(bp.getDouble("attitude_head", 0d));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 中断原因枚举转中文
|
||||||
|
*/
|
||||||
|
private static String getBreakReasonCn(int breakReason) {
|
||||||
|
return switch (breakReason) {
|
||||||
|
case 0 -> "无异常";
|
||||||
|
case 1 -> "Mission ID 不存在,该航线任务未执行";
|
||||||
|
case 2 -> "不常见错误,建议联系技术支持";
|
||||||
|
case 4 -> "请求开始/恢复航线任务时,航线文件加载出错,请重新尝试上传文件开始或联系技术支持";
|
||||||
|
case 5 -> "请求查询断点信息时,查询断点文件失败。请求恢复航线任务时,解析断点类型失败";
|
||||||
|
case 6 -> "请求开始/结束航线任务时,cmd参数有误,协议请求的指令有误。请求恢复航线任务时,解析断点类型失败";
|
||||||
|
case 7 -> "请求开始/恢复航线任务时,解析 wpmz 文件超时,请重试";
|
||||||
|
case 257 -> "航线已经开始,不能再次开始";
|
||||||
|
case 258 -> "此状态下无法中断航线,只允许在航线执行状态时暂停航线";
|
||||||
|
case 259 -> "航线未开始,不能结束航线";
|
||||||
|
case 261 -> "飞行任务冲突,无法获取飞行器控制权,不允许在降落和返航中开始航线";
|
||||||
|
case 262 -> "该状态下无法恢复航线,只允许在航线暂停状态时恢复航线";
|
||||||
|
case 513 -> "飞行器超过限高高度";
|
||||||
|
case 514 -> "飞行器超过限远距离";
|
||||||
|
case 515 -> "航线穿过限飞区,机场无法执行飞行任务";
|
||||||
|
case 516 -> "飞行器触发限低";
|
||||||
|
case 517 -> "飞行器触发避障";
|
||||||
|
case 518 -> "RTK 信号差";
|
||||||
|
case 519 -> "接近禁飞区边界";
|
||||||
|
case 521 -> "超过机场限飞区限高";
|
||||||
|
case 522 -> "航线请求起飞失败";
|
||||||
|
case 523 -> "起飞任务执行失败";
|
||||||
|
case 524 -> "请求航线任务失败";
|
||||||
|
case 526 -> "请求航线 RTK 收敛任务失败";
|
||||||
|
case 527 -> "航线 RTK 收敛任务运行失败";
|
||||||
|
case 769 -> "GPS 信号弱";
|
||||||
|
case 770 -> "遥控器档位不在 N 档";
|
||||||
|
case 771 -> "返航点未刷新";
|
||||||
|
case 772 -> "当前电量过低无法开始任务";
|
||||||
|
case 773 -> "低电量返航导致航线中断";
|
||||||
|
case 775 -> "遥控器与飞行器失联";
|
||||||
|
case 778 -> "飞行器在地面起桨,不允许开始航线";
|
||||||
|
case 779 -> "实时仿地过程中,相机状态异常(如过亮,过暗,两侧亮度不一致)";
|
||||||
|
case 780 -> "实时仿地用户设置的仿地高度不合法(大于 200 m 或者小于 30 m)";
|
||||||
|
case 781 -> "实时仿地过程中全局地图计算出错";
|
||||||
|
case 784 -> "大风返航导致航线中断";
|
||||||
|
case 1281 -> "用户退出";
|
||||||
|
case 1282 -> "用户中断";
|
||||||
|
case 1283 -> "用户触发返航";
|
||||||
|
case 1539 -> "开始信息(航点 index 或者 progress)错误";
|
||||||
|
case 1540 -> "使用不支持的坐标系";
|
||||||
|
case 1541 -> "使用不支持的高度模式";
|
||||||
|
case 1542 -> "使用不支持的过渡航线模式";
|
||||||
|
case 1543 -> "使用不支持的 yaw 模式";
|
||||||
|
case 1544 -> "使用不支持的 yaw 方向调转模式";
|
||||||
|
case 1545 -> "使用不支持的航点类型";
|
||||||
|
case 1546 -> "首尾点不能使用协调转弯类型";
|
||||||
|
case 1547 -> "航线全局速度超过合理范围";
|
||||||
|
case 1548 -> "航点数量异常";
|
||||||
|
case 1549 -> "经纬度数据异常";
|
||||||
|
case 1550 -> "转弯截距异常";
|
||||||
|
case 1551 -> "航段最大速度超过合理范围";
|
||||||
|
case 1552 -> "航段目标速度超过合理范围";
|
||||||
|
case 1553 -> "航点 yaw 角度超过合理范围";
|
||||||
|
case 1555 -> "断点续飞的 mission_id 输入错误";
|
||||||
|
case 1556 -> "断点续飞的 progress 信息输入错误";
|
||||||
|
case 1557 -> "断点续飞的任务状态异常";
|
||||||
|
case 1558 -> "断点续飞的航点 index 信息输入错误";
|
||||||
|
case 1559 -> "断点续飞的经纬度信息输入错误";
|
||||||
|
case 1560 -> "断点续飞的航点 yaw 输入错误";
|
||||||
|
case 1561 -> "断点续飞的标志位设置错误";
|
||||||
|
case 1563 -> "航线生成失败";
|
||||||
|
case 1564 -> "航线运行失败";
|
||||||
|
case 1565 -> "航线避障紧急刹停";
|
||||||
|
case 1588 -> "无法识别的动作类型";
|
||||||
|
case 1595 -> "动作 ID 不能重复";
|
||||||
|
case 1598 -> "动作 ID 值不能为 65535";
|
||||||
|
case 1602 -> "动作组数量超过合理范围";
|
||||||
|
case 1603 -> "动作组生效范围错误";
|
||||||
|
case 1606 -> "断点续飞中动作 index 超过合理范围";
|
||||||
|
case 1608 -> "断点信息中触发器运行结果异常";
|
||||||
|
case 1609 -> "断点续飞中动作组 ID 信息不能重复";
|
||||||
|
case 1610 -> "断点续飞中动作组位置不能重复";
|
||||||
|
case 1611 -> "断点续飞中动作组位置超过合理范围";
|
||||||
|
case 1612 -> "续飞中动作 ID 不在断点信息中";
|
||||||
|
case 1613 -> "断点续飞中不能修改动作状态为中断";
|
||||||
|
case 1614 -> "断点信息错误导致续飞失败";
|
||||||
|
case 1634 -> "无法识别的动作类型";
|
||||||
|
case 1649 -> "无法识别的触发器类型";
|
||||||
|
case 65534 -> "未知内部错误";
|
||||||
|
case 65535 -> "未知内部错误";
|
||||||
|
default -> String.valueOf(breakReason);
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
package com.multictrl.modules.business.influxdb;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import com.influxdb.annotations.Column;
|
||||||
|
import com.influxdb.annotations.Measurement;
|
||||||
|
import com.multictrl.common.utils.DateUtils;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 飞行日志
|
||||||
|
*
|
||||||
|
* @author Sdy
|
||||||
|
* @since 1.0.0 2026/6/1
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Schema(name = "飞行日志")
|
||||||
|
@Measurement(name = "flight_log")
|
||||||
|
public class FlightLog {
|
||||||
|
|
||||||
|
@Schema(description = "主控sn")
|
||||||
|
@Column(tag = true)
|
||||||
|
private String dockSn;
|
||||||
|
|
||||||
|
@Schema(hidden = true)
|
||||||
|
@Column(timestamp = true)
|
||||||
|
@JsonProperty("_time")
|
||||||
|
private Instant time;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
private String method;
|
||||||
|
|
||||||
|
//{"0":"通知","1":"提醒","2":"警告"}
|
||||||
|
@Column
|
||||||
|
private Integer level;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
private String message;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 时间字符串
|
||||||
|
*/
|
||||||
|
private String timeStr;
|
||||||
|
|
||||||
|
public void setTime(Instant time) {
|
||||||
|
this.time = time;
|
||||||
|
this.timeStr = DateUtils.utcToTime(time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -39,6 +39,9 @@ public interface FlightTaskService extends CrudService<FlightTaskEntity, FlightT
|
||||||
//获取飞行轨迹
|
//获取飞行轨迹
|
||||||
List<JSONObject> getFlightTrack(String taskId);
|
List<JSONObject> getFlightTrack(String taskId);
|
||||||
|
|
||||||
|
//获取飞行日志
|
||||||
|
List<JSONObject> getFlightLog(String taskId);
|
||||||
|
|
||||||
//获取架次媒体
|
//获取架次媒体
|
||||||
List<MediaFileDTO> getTaskMedia(String taskId);
|
List<MediaFileDTO> getTaskMedia(String taskId);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -273,6 +273,26 @@ public class FlightTaskServiceImpl extends CrudServiceImpl<FlightTaskDao, Flight
|
||||||
return filledList;
|
return filledList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<JSONObject> getFlightLog(String taskId) {
|
||||||
|
FlightTaskEntity entity = selectById(taskId);
|
||||||
|
if (entity == null) {
|
||||||
|
throw new RenException(ErrorCode.ROUTE_TASK_NOT_EXIST);
|
||||||
|
}
|
||||||
|
Date outboundDate = entity.getOutboundDate();
|
||||||
|
Date inboundDate = entity.getInboundDate();
|
||||||
|
String dockSn = entity.getDockSn();
|
||||||
|
if (outboundDate == null || inboundDate == null || StrUtil.isBlank(dockSn)) {
|
||||||
|
return List.of();
|
||||||
|
}
|
||||||
|
HashMap<String, Object> condition = Maps.newHashMap();
|
||||||
|
condition.put("dockSn", dockSn);
|
||||||
|
|
||||||
|
return influxService.queryData(DateUtils.format(outboundDate, DateUtils.DATE_TIME_PATTERN),
|
||||||
|
DateUtils.format(inboundDate, DateUtils.DATE_TIME_PATTERN), "flight_log", condition, JSONObject.class,
|
||||||
|
"dockSn", "_time", "method", "level", "message");
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<MediaFileDTO> getTaskMedia(String taskId) {
|
public List<MediaFileDTO> getTaskMedia(String taskId) {
|
||||||
Map<String, Object> params = new HashMap<>();
|
Map<String, Object> params = new HashMap<>();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue