From 64972e9093fa9dde9ce346273b27445bd9d004b9 Mon Sep 17 00:00:00 2001
From: zhaowenyu <35589726@qq.com>
Date: Wed, 24 Dec 2025 15:14:25 +0800
Subject: [PATCH] 2025-12-24 zwy 增加计划任务轨迹功能,将在计划任务执行期间的飞行轨迹数据、任务状态数据保存;同时将计划任务数据保存到计划任务历史表中保存。并提供完整的轨迹提取接口。
---
ard-sample/src/main/java/com/ard/sample/wayline/mapper/IWaylineJobHistoryMapper.java | 10
ard-sample/src/main/java/com/ard/sample/wayline/service/impl/WaylineJobHistoryServiceImpl.java | 235 +++++++++++++++
ard-sample/src/main/java/com/ard/sample/manage/model/dto/WaylineTrajectoryDTO.java | 69 ++++
ard-sample/src/main/java/com/ard/sample/manage/service/impl/DeviceOSDServiceImpl.java | 7
ard-sample/src/main/java/com/ard/sample/wayline/model/entity/WaylineJobHistoryEntity.java | 94 ++++++
ard-sample/src/main/java/com/ard/sample/manage/mapper/IWaylineTrajectoryMapper.java | 12
ard-sample/src/main/java/com/ard/sample/manage/service/impl/WaylineTrajectoryServiceImpl.java | 213 ++++++++++++++
ard-sample/src/main/java/com/ard/sample/manage/model/entity/WaylineTrajectoryEntity.java | 83 +++++
ard-admin/src/main/java/com/ard/web/controller/sample/wayline/WaylineTrajectoryController.java | 40 ++
ard-sample/src/main/java/com/ard/sample/wayline/service/impl/FlightTaskServiceImpl.java | 33 ++
ard-sample/src/main/java/com/ard/sample/wayline/service/IWaylineJobHistoryService.java | 57 +++
ard-sample/src/main/java/com/ard/sample/manage/service/IWaylineTrajectoryService.java | 24 +
12 files changed, 877 insertions(+), 0 deletions(-)
diff --git a/ard-admin/src/main/java/com/ard/web/controller/sample/wayline/WaylineTrajectoryController.java b/ard-admin/src/main/java/com/ard/web/controller/sample/wayline/WaylineTrajectoryController.java
new file mode 100644
index 0000000..4af8443
--- /dev/null
+++ b/ard-admin/src/main/java/com/ard/web/controller/sample/wayline/WaylineTrajectoryController.java
@@ -0,0 +1,40 @@
+package com.ard.web.controller.sample.wayline;
+
+import com.ard.sample.common.model.ResponseResult;
+import com.ard.sample.manage.model.dto.WaylineTrajectoryDTO;
+import com.ard.sample.manage.service.IWaylineTrajectoryService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.Optional;
+
+@Api(tags = "航线历史任务轨迹")
+@RequestMapping("/dock/waylineTrajectory")
+@RestController
+public class WaylineTrajectoryController {
+ @Autowired
+ private IWaylineTrajectoryService _waylineTrajectoryService;
+
+ @ApiOperation("获取航线任务轨迹")
+ @GetMapping("/flight-id")
+ public ResponseResult<WaylineTrajectoryDTO> getJob(@RequestParam(name = "job_id") String jobId) {
+ try {
+ if(jobId == null){
+ return ResponseResult.error(98,"任务ID不能为空");
+ }
+ WaylineTrajectoryDTO waylineJobDTO = _waylineTrajectoryService.getWayLineTrajectorybyJobID(jobId);
+ if(waylineJobDTO==null) {
+ return ResponseResult.error(99,"任务不存在");
+ }
+ return ResponseResult.success(waylineJobDTO);
+ } catch (Exception e) {
+ return ResponseResult.error(97, "获取航线轨迹发生异常:"+e.getMessage());
+ }
+ }
+}
+
diff --git a/ard-sample/src/main/java/com/ard/sample/manage/mapper/IWaylineTrajectoryMapper.java b/ard-sample/src/main/java/com/ard/sample/manage/mapper/IWaylineTrajectoryMapper.java
new file mode 100644
index 0000000..7141fa0
--- /dev/null
+++ b/ard-sample/src/main/java/com/ard/sample/manage/mapper/IWaylineTrajectoryMapper.java
@@ -0,0 +1,12 @@
+package com.ard.sample.manage.mapper;
+
+import com.ard.sample.manage.model.entity.WaylineTrajectoryEntity;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Select;
+
+import java.util.List;
+
+
+public interface IWaylineTrajectoryMapper extends BaseMapper<WaylineTrajectoryEntity> {
+
+}
diff --git a/ard-sample/src/main/java/com/ard/sample/manage/model/dto/WaylineTrajectoryDTO.java b/ard-sample/src/main/java/com/ard/sample/manage/model/dto/WaylineTrajectoryDTO.java
new file mode 100644
index 0000000..794cca6
--- /dev/null
+++ b/ard-sample/src/main/java/com/ard/sample/manage/model/dto/WaylineTrajectoryDTO.java
@@ -0,0 +1,69 @@
+package com.ard.sample.manage.model.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.List;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+public class WaylineTrajectoryDTO {
+ /**
+ * 主建
+ * */
+ private Integer id;
+
+ /**
+ * 计划任务id
+ * */
+ private String jobId;
+
+ /**
+ * 计划任务名称
+ * */
+ private String name;
+
+ /**
+ * 用于此任务的航线文件id。
+ * */
+ private String fileId;
+
+ /**
+ * 航线文件名称
+ * */
+ private String fileName;
+
+ /**
+ * 执行此任务的机场sn。
+ * */
+ private String dockSn;
+
+ /**
+ * 进度为ok时,为一次轨迹的结束
+ * */
+ private String progress;
+
+ /**
+ * 创建时间
+ * */
+ private Long createTime;
+
+ /**
+ * 更新时间
+ * */
+ private Long updateTime;
+
+ /**
+ * 飞行轨迹list
+ * */
+ private List<String> trajectoryList;
+
+ /**
+ * 任务状态list
+ * */
+ private List<String> taskList;
+}
diff --git a/ard-sample/src/main/java/com/ard/sample/manage/model/entity/WaylineTrajectoryEntity.java b/ard-sample/src/main/java/com/ard/sample/manage/model/entity/WaylineTrajectoryEntity.java
new file mode 100644
index 0000000..86b542e
--- /dev/null
+++ b/ard-sample/src/main/java/com/ard/sample/manage/model/entity/WaylineTrajectoryEntity.java
@@ -0,0 +1,83 @@
+package com.ard.sample.manage.model.entity;
+
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+@TableName(value = "wayline_trajectory")
+public class WaylineTrajectoryEntity implements Serializable {
+
+ /**
+ * 主建
+ * */
+ @TableId(type = IdType.AUTO)
+ private Integer id;
+
+ /**
+ * 计划任务id
+ * */
+ @TableField(value = "job_id")
+ private String jobId;
+
+ /**
+ * 计划任务名称
+ * */
+ @TableField("name")
+ private String name;
+
+ /**
+ * 用于此任务的航线文件id。
+ * */
+ @TableField("file_id")
+ private String fileId;
+
+ /**
+ * 航线文件名称
+ * */
+ @TableField("file_name")
+ private String fileName;
+
+ /**
+ * 执行此任务的机场sn。
+ * */
+ @TableField("dock_sn")
+ private String dockSn;
+
+ /**
+ * 进度为ok时,为一次轨迹的结束
+ * */
+ @TableField("progress")
+ private String progress;
+
+ /**
+ * 创建时间
+ * */
+ @TableField(value = "create_time", fill = FieldFill.INSERT)
+ private Long createTime;
+
+ /**
+ * 更新时间
+ * */
+ @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
+ private Long updateTime;
+
+ /**
+ * 飞行轨迹list
+ * */
+ @TableField("trajectory_list")
+ private byte[] trajectoryList;
+
+ /**
+ * 任务状态list
+ * */
+ @TableField("task_list")
+ private byte[] taskList;
+}
diff --git a/ard-sample/src/main/java/com/ard/sample/manage/service/IWaylineTrajectoryService.java b/ard-sample/src/main/java/com/ard/sample/manage/service/IWaylineTrajectoryService.java
new file mode 100644
index 0000000..8a42c5c
--- /dev/null
+++ b/ard-sample/src/main/java/com/ard/sample/manage/service/IWaylineTrajectoryService.java
@@ -0,0 +1,24 @@
+package com.ard.sample.manage.service;
+
+import com.ard.sample.manage.model.dto.WaylineTrajectoryDTO;
+import com.ard.sample.manage.model.entity.WaylineTrajectoryEntity;
+
+import java.util.List;
+
+public interface IWaylineTrajectoryService {
+
+ /**
+ * 增加list数据,type为:0时,表示轨迹点列表;type为:1时,表示任务状态数据。
+ * @param sn 设备序列号
+ * @param type 类型
+ * @param dataJson json数据
+ * */
+ void setList(String sn, String type, String dataJson);
+
+ /**
+ * 返回航线轨迹完整的数据,拼接的轨迹点列表和任务状态数据。
+ * @param jobId 任务ID
+ * @return 航线轨迹完整的数据
+ * */
+ WaylineTrajectoryDTO getWayLineTrajectorybyJobID(String jobId);
+}
diff --git a/ard-sample/src/main/java/com/ard/sample/manage/service/impl/DeviceOSDServiceImpl.java b/ard-sample/src/main/java/com/ard/sample/manage/service/impl/DeviceOSDServiceImpl.java
index 9cd6bde..0dafd41 100644
--- a/ard-sample/src/main/java/com/ard/sample/manage/service/impl/DeviceOSDServiceImpl.java
+++ b/ard-sample/src/main/java/com/ard/sample/manage/service/impl/DeviceOSDServiceImpl.java
@@ -17,6 +17,7 @@
import com.ard.sample.manage.model.receiver.OsdPayloadReceiver;
import com.ard.sample.manage.model.receiver.OsdSubDeviceReceiver;
import com.ard.sample.manage.service.IDeviceService;
+import com.ard.sample.manage.service.IWaylineTrajectoryService;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
@@ -41,6 +42,9 @@
@Autowired
private IDeviceService _deviceService;
+
+ @Autowired
+ private IWaylineTrajectoryService _waylineTrajectoryService;
@Autowired
private DockWebSocketHandler _dockWebSocketHandler;
@@ -118,6 +122,9 @@
// 发送给websocket客户端
_dockWebSocketHandler.sendMessageToSubscribers(device.getDeviceSn(), MessageType.STATUS.getType(), dockOsd, "");
+ // 将飞行器的OSD数据dockOsd入库;
+ _waylineTrajectoryService.setList(device.getDeviceSn(),"0", dockOsd);
+
sendMessageService.sendBatch(webSessions, wsMessage);
this.pushTelemetryData(data, device.getDeviceSn());
}
diff --git a/ard-sample/src/main/java/com/ard/sample/manage/service/impl/WaylineTrajectoryServiceImpl.java b/ard-sample/src/main/java/com/ard/sample/manage/service/impl/WaylineTrajectoryServiceImpl.java
new file mode 100644
index 0000000..63eb534
--- /dev/null
+++ b/ard-sample/src/main/java/com/ard/sample/manage/service/impl/WaylineTrajectoryServiceImpl.java
@@ -0,0 +1,213 @@
+package com.ard.sample.manage.service.impl;
+
+import cn.hutool.core.util.SerializeUtil;
+import com.ard.common.core.text.Convert;
+import com.ard.sample.component.mqtt.model.EventsReceiver;
+import com.ard.sample.manage.mapper.IWaylineTrajectoryMapper;
+import com.ard.sample.manage.model.dto.WaylineTrajectoryDTO;
+import com.ard.sample.manage.model.entity.WaylineTrajectoryEntity;
+import com.ard.sample.manage.service.IWaylineTrajectoryService;
+import com.ard.sample.wayline.model.dto.WaylineJobDTO;
+import com.ard.sample.wayline.model.dto.WaylineTaskProgressReceiver;
+import com.ard.sample.wayline.service.IWaylineJobService;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import java.util.concurrent.ConcurrentHashMap;
+
+@Service
+@Slf4j
+public class WaylineTrajectoryServiceImpl implements IWaylineTrajectoryService {
+
+ @Resource
+ private IWaylineTrajectoryMapper _waylineTrajectoryMapper;
+
+ @Autowired
+ private IWaylineJobService _waylineJobService;
+
+ @Autowired
+ protected ObjectMapper mapper;
+ /**
+ * 轨迹点列表缓存
+ */
+ private final ConcurrentHashMap<String, List<String>> cacheTrajectoryMap = new ConcurrentHashMap<>();
+
+ /**
+ * 任务状态数据缓存
+ */
+ private final ConcurrentHashMap<String, List<String>> cacheTaskMap = new ConcurrentHashMap<>();
+
+ /**
+ * 给数据加个进度
+ */
+ private final ConcurrentHashMap<String, String> cacheProgress = new ConcurrentHashMap<>();
+ /**
+ * 分片保存阈值条数
+ */
+ private static final int CHUNK_SIZE = 300;
+
+ /**
+ * 增加list数据,type为:0时,表示轨迹点列表;type为:1时,表示任务状态数据。
+ * @param sn 设备序列号
+ * @param type 类型
+ * @param dataJson json数据
+ */
+ @Override
+ public void setList(String sn, String type, String dataJson) {
+ List<String> listTrajectory = cacheTrajectoryMap.computeIfAbsent(sn, k -> new ArrayList<>());
+ List<String> listTask = cacheTaskMap.computeIfAbsent(sn, k -> new ArrayList<>());
+ String progress = cacheProgress.computeIfAbsent(sn, k -> "0");
+ // 取进度值,就为了判断ok一个任务的结束
+ Integer pro = Convert.toInt(cacheProgress.get(sn));
+ // 取jobid、status字段值
+ String jobId = "";
+ String isOK = "";
+ if (type.equals("0")) {
+ // 飞行轨迹数据
+ listTrajectory.add(dataJson);
+ log.info("轨迹点数据添加到列表缓存,当前列表数量:{}", listTrajectory.size());
+ }
+ if (type.equals("1")) {
+ // 任务状态数据
+ listTask.add(dataJson);
+ log.info("任务状态数据添加到列表缓存,当前列表数量:{}", listTask.size());
+ }
+ // jobid、status字段赋值
+ if (!listTask.isEmpty()) {
+ String json = listTask.get(listTask.size() - 1);
+ EventsReceiver<WaylineTaskProgressReceiver> eventsReceiver = mapper.convertValue(json,
+ new TypeReference<EventsReceiver<WaylineTaskProgressReceiver>>() {
+ });
+ jobId = eventsReceiver.getOutput().getExt().getFlightId();
+ isOK = eventsReceiver.getOutput().getStatus();
+
+ log.info("当前任务jobId:{},任务执行进度isOK:{}", jobId, isOK);
+ }
+ if (listTrajectory.size() >= CHUNK_SIZE || listTask.size() >= CHUNK_SIZE) {
+ progress = Convert.toStr(pro + 1);
+ // 分片保存
+ save(sn, jobId);
+ log.info("当前任务保存成功,jobId:{},进度:{}",jobId , progress);
+ } else {
+ // 判断任务状态json中的status字段,如果为OK,则保存数据,一条完整的航线数据结束。
+ try {
+ if (isOK.equals("ok")) {
+ progress = "ok";
+ if (getWaylineTrajectoryByProgress(jobId, progress)) {
+ log.info("当前任务已完成,不再保存数据!jobId:{},progress:{}", jobId, progress);
+ return;
+ }
+ save(sn, jobId);
+ log.info("当前任务保存成功,jobId:{},进度:{}",jobId , progress);
+ }
+ } catch (Exception e) {
+ log.error("json解析异常!{}", e.getMessage());
+ }
+ }
+ }
+
+ @Async
+ public void save(String sn, String JobId) {
+ List<String> trajectoryList = cacheTrajectoryMap.get(sn);
+ List<String> taskList = cacheTaskMap.get(sn);
+ String progress = cacheProgress.get(sn);
+
+ if (trajectoryList.isEmpty() && taskList.isEmpty()) {
+ return;
+ }
+ try {
+ byte[] blobTrajectory = SerializeUtil.serialize(trajectoryList);
+ byte[] blobTask = SerializeUtil.serialize(taskList);
+
+ Optional<WaylineJobDTO> waylineJobDTO = _waylineJobService.getJobByJobId(JobId);
+ WaylineTrajectoryEntity TrajectoryEntity = new WaylineTrajectoryEntity();
+ TrajectoryEntity.setJobId(JobId);
+ TrajectoryEntity.setName(waylineJobDTO.get().getJobName());
+ TrajectoryEntity.setFileId(waylineJobDTO.get().getFileId());
+ TrajectoryEntity.setFileName(waylineJobDTO.get().getFileName());
+ TrajectoryEntity.setDockSn(sn);
+ TrajectoryEntity.setProgress(progress);
+ TrajectoryEntity.setCreateTime(System.currentTimeMillis());
+ TrajectoryEntity.setUpdateTime(System.currentTimeMillis());
+ TrajectoryEntity.setTrajectoryList(blobTrajectory);
+ TrajectoryEntity.setTaskList(blobTask);
+ // 保存轨迹点列表数据
+ int i = _waylineTrajectoryMapper.insert(TrajectoryEntity);
+ if (i > 0) {
+ log.info("保存轨迹点列表数据成功!jobId:{}", JobId);
+ // 清空缓存
+ cacheTrajectoryMap.put(sn, new ArrayList<>());
+ cacheTaskMap.put(sn, new ArrayList<>());
+ if (progress.equals("ok")) {
+ cacheProgress.put(sn, "0");
+ }
+ }
+
+ } catch (Exception e) {
+ log.error("保存轨迹点列表数据失败!jobId:{}.{}", JobId, e.getMessage());
+ }
+ }
+
+ /**
+ * 返回航线轨迹完整的数据,拼接的轨迹点列表和任务状态数据。
+ *
+ * @param jobId 任务ID
+ * @return 航线轨迹完整的数据
+ */
+ @Override
+ public WaylineTrajectoryDTO getWayLineTrajectorybyJobID(String jobId) {
+
+ List<WaylineTrajectoryEntity> waylineTrajectoryEntityList = new ArrayList<>(_waylineTrajectoryMapper.selectList(new LambdaQueryWrapper<WaylineTrajectoryEntity>()
+ .eq(jobId != null, WaylineTrajectoryEntity::getJobId, jobId)
+ .orderByAsc(WaylineTrajectoryEntity::getId)));
+
+ return TrajectoryEntityConvertToDTO(waylineTrajectoryEntityList);
+ }
+
+ /**
+ * 根据作业ID和进度获取航线轨迹
+ *
+ * @param jobId 作业ID,可为null
+ * @param progress 进度值,可为null
+ * @return 当存在符合条件的航线轨迹时返回true,否则返回false
+ */
+ public Boolean getWaylineTrajectoryByProgress(String jobId, String progress) {
+ List<WaylineTrajectoryEntity> waylineTrajectoryEntityList = new ArrayList<>(_waylineTrajectoryMapper.selectList(new LambdaQueryWrapper<WaylineTrajectoryEntity>()
+ .eq(jobId != null, WaylineTrajectoryEntity::getJobId, jobId)
+ .eq(progress != null, WaylineTrajectoryEntity::getProgress, progress)
+ .orderByAsc(WaylineTrajectoryEntity::getId)));
+
+ return !waylineTrajectoryEntityList.isEmpty();
+ }
+
+ public WaylineTrajectoryDTO TrajectoryEntityConvertToDTO(List<WaylineTrajectoryEntity> entity) {
+ if (entity == null) {
+ return null;
+ }
+ WaylineTrajectoryDTO dto = new WaylineTrajectoryDTO();
+ dto.setId(entity.get(0).getId());
+ dto.setJobId(entity.get(0).getJobId());
+ dto.setName(entity.get(0).getName());
+ dto.setFileId(entity.get(0).getFileId());
+ dto.setFileName(entity.get(0).getFileName());
+ dto.setDockSn(entity.get(0).getDockSn());
+ dto.setProgress(entity.get(0).getProgress());
+ dto.setCreateTime(entity.get(0).getCreateTime());
+ dto.setUpdateTime(entity.get(0).getUpdateTime());
+ for (WaylineTrajectoryEntity e : entity) {
+ dto.getTrajectoryList().addAll(SerializeUtil.deserialize(e.getTrajectoryList(), List.class));
+ dto.getTaskList().addAll(SerializeUtil.deserialize(e.getTaskList(), List.class));
+ }
+
+ return dto;
+ }
+}
diff --git a/ard-sample/src/main/java/com/ard/sample/wayline/mapper/IWaylineJobHistoryMapper.java b/ard-sample/src/main/java/com/ard/sample/wayline/mapper/IWaylineJobHistoryMapper.java
new file mode 100644
index 0000000..99f08d5
--- /dev/null
+++ b/ard-sample/src/main/java/com/ard/sample/wayline/mapper/IWaylineJobHistoryMapper.java
@@ -0,0 +1,10 @@
+package com.ard.sample.wayline.mapper;
+
+import com.ard.sample.wayline.model.entity.WaylineJobHistoryEntity;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * 任务历史信息
+ * */
+public interface IWaylineJobHistoryMapper extends BaseMapper<WaylineJobHistoryEntity> {
+}
diff --git a/ard-sample/src/main/java/com/ard/sample/wayline/model/entity/WaylineJobHistoryEntity.java b/ard-sample/src/main/java/com/ard/sample/wayline/model/entity/WaylineJobHistoryEntity.java
new file mode 100644
index 0000000..5e2004d
--- /dev/null
+++ b/ard-sample/src/main/java/com/ard/sample/wayline/model/entity/WaylineJobHistoryEntity.java
@@ -0,0 +1,94 @@
+package com.ard.sample.wayline.model.entity;
+
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+@TableName("wayline_job_history")
+public class WaylineJobHistoryEntity implements Serializable {
+ @TableId(type = IdType.AUTO)
+ private Integer id;
+
+ @TableField("job_id")
+ private String jobId;
+
+ @TableField("name")
+ private String name;
+
+ @TableField("file_id")
+ private String fileId;
+
+ @TableField("file_name")
+ private String filename;
+
+ @TableField("dock_sn")
+ private String dockSn;
+
+ @TableField("workspace_id")
+ private String workspaceId;
+
+ @TableField("task_type")
+ private Integer taskType;
+
+ @TableField("wayline_type")
+ private Integer waylineType;
+
+ @TableField("username")
+ private String username;
+
+ /**
+ * 实际开始时间
+ * */
+ @TableField("execute_time")
+ private Long executeTime;
+
+ /**
+ * 计划结束时间
+ * */
+ @TableField("end_time")
+ private Long endTime;
+
+ @TableField("error_code")
+ private Integer errorCode;
+
+ @TableField("status")
+ private Integer status;
+
+ @TableField("rth_altitude")
+ private Integer rthAltitude;
+
+ @TableField("rth_mode")
+ private Integer rthMode;
+
+ @TableField("out_of_control")
+ private Integer outOfControlAction;
+
+ @TableField("media_count")
+ private Integer mediaCount;
+
+ @TableField(value = "create_time", fill = FieldFill.INSERT)
+ private Long createTime;
+
+ @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
+ private Long updateTime;
+
+ @TableField("begin_time")
+ private Long beginTime;
+
+ @TableField("completed_time")
+ private Long completedTime;
+
+ @TableField("parent_id")
+ private String parentId;
+
+ @TableField("loop_sum")
+ private Integer loopSum;
+}
diff --git a/ard-sample/src/main/java/com/ard/sample/wayline/service/IWaylineJobHistoryService.java b/ard-sample/src/main/java/com/ard/sample/wayline/service/IWaylineJobHistoryService.java
new file mode 100644
index 0000000..d3f93d7
--- /dev/null
+++ b/ard-sample/src/main/java/com/ard/sample/wayline/service/IWaylineJobHistoryService.java
@@ -0,0 +1,57 @@
+package com.ard.sample.wayline.service;
+
+import com.ard.sample.common.model.PaginationData;
+import com.ard.sample.wayline.model.dto.WaylineJobDTO;
+import com.ard.sample.wayline.model.entity.WaylineJobHistoryEntity;
+
+import java.util.Optional;
+
+/**
+ * 计划库历史表
+ * */
+public interface IWaylineJobHistoryService {
+
+ /**
+ * 在数据库中创建任务历史数据。
+ * @param entity
+ * @return
+ */
+ Optional<WaylineJobDTO> createWaylineJob(WaylineJobHistoryEntity entity);
+
+ /**
+ * 更新历史数据任务数据。
+ * @param dto
+ * @return
+ */
+ Boolean updateJob(WaylineJobDTO dto);
+
+ /**
+ * 查询历史任务列表
+ * @param page
+ * @param pageSize
+ * @param status
+ * @param startTime
+ * @param endTime
+ * @param taskType
+ * @param name
+ * @param isComplete
+ * */
+ PaginationData<WaylineJobDTO> getJobsList(long page, long pageSize, Integer status,
+ Long startTime, Long endTime, Integer taskType,
+ String name, Boolean isComplete);
+
+ /**
+ * 根据任务ID查询历史数据任务信息。
+ * @param jobId
+ * @return job 信息
+ */
+ Optional<WaylineJobDTO> getJobByJobId(String jobId);
+
+ /**
+ * 将WaylineJobDTO对象转换为WaylineJobHistoryEntity对象
+ *
+ * @param dto WaylineJobDTO对象
+ * @return WaylineJobHistoryEntity对象
+ */
+ WaylineJobHistoryEntity dto2Entity(WaylineJobDTO dto);
+}
diff --git a/ard-sample/src/main/java/com/ard/sample/wayline/service/impl/FlightTaskServiceImpl.java b/ard-sample/src/main/java/com/ard/sample/wayline/service/impl/FlightTaskServiceImpl.java
index 2d3e6a2..1832c0c 100644
--- a/ard-sample/src/main/java/com/ard/sample/wayline/service/impl/FlightTaskServiceImpl.java
+++ b/ard-sample/src/main/java/com/ard/sample/wayline/service/impl/FlightTaskServiceImpl.java
@@ -15,12 +15,15 @@
import com.ard.sample.component.websocket.service.IWebSocketManageService;
import com.ard.sample.manage.model.dto.DeviceDTO;
import com.ard.sample.manage.model.enums.UserTypeEnum;
+import com.ard.sample.manage.service.IWaylineTrajectoryService;
import com.ard.sample.media.model.MediaFileCountDTO;
import com.ard.sample.wayline.model.dto.WaylineJobDTO;
import com.ard.sample.wayline.model.dto.WaylineTaskProgressExt;
import com.ard.sample.wayline.model.dto.WaylineTaskProgressReceiver;
+import com.ard.sample.wayline.model.entity.WaylineJobHistoryEntity;
import com.ard.sample.wayline.model.enums.WaylineJobStatusEnum;
import com.ard.sample.wayline.service.IFlightTaskService;
+import com.ard.sample.wayline.service.IWaylineJobHistoryService;
import com.ard.sample.wayline.service.IWaylineJobService;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -66,6 +69,12 @@
@Autowired
private IWaylineJobService waylineJobService;
+
+ @Autowired
+ private IWaylineTrajectoryService _waylineTrajectoryService;
+
+ @Autowired
+ private IWaylineJobHistoryService _waylineJobHistoryService;
@Override
@ServiceActivator(inputChannel = ChannelName.INBOUND_EVENTS_FLIGHT_TASK_PROGRESS, outputChannel = ChannelName.OUTBOUND)
@@ -143,6 +152,9 @@
// if (eventsReceiver.getOutput().getProgress().getPercent() >= 95) {
// return;
// }
+
+
+
String json = "";
try {
json = mapper.writeValueAsString(eventsReceiver);
@@ -150,6 +162,27 @@
e.printStackTrace();
}
_dockWebSocketHandler.sendMessageToSubscribers(dockSn, MessageType.STATUS.getType(), json, "");
+
+ _waylineTrajectoryService.setList(dockSn,"1",json);
+
+ // 计划任务成功后,保存计划任务到历史记录
+ String status = eventsReceiver.getOutput().getStatus();
+ String jobId = eventsReceiver.getOutput().getExt().getFlightId();
+ if(status.equals("ok") && jobId != null) {
+ Optional<WaylineJobDTO> job = waylineJobService.getJobByJobId(jobId);
+ if(job.isPresent()) {
+ if (_waylineJobHistoryService.getJobByJobId(jobId).isPresent()) {
+ return;
+ }
+ WaylineJobHistoryEntity waylineJobHistoryEntity = _waylineJobHistoryService.dto2Entity(job.get());
+ Optional<WaylineJobDTO> jobHistory = _waylineJobHistoryService.createWaylineJob(waylineJobHistoryEntity);
+ if(jobHistory.isPresent()) {
+ log.info("任务执行成功,保存到历史记录。 {}", jobHistory);
+ }
+
+ }
+
+ }
}
/**
diff --git a/ard-sample/src/main/java/com/ard/sample/wayline/service/impl/WaylineJobHistoryServiceImpl.java b/ard-sample/src/main/java/com/ard/sample/wayline/service/impl/WaylineJobHistoryServiceImpl.java
new file mode 100644
index 0000000..82d72bc
--- /dev/null
+++ b/ard-sample/src/main/java/com/ard/sample/wayline/service/impl/WaylineJobHistoryServiceImpl.java
@@ -0,0 +1,235 @@
+package com.ard.sample.wayline.service.impl;
+
+import com.ard.route.service.IArdRouteInfoService;
+import com.ard.sample.common.model.Pagination;
+import com.ard.sample.common.model.PaginationData;
+import com.ard.sample.manage.model.dto.DeviceDTO;
+import com.ard.sample.manage.service.IDeviceService;
+import com.ard.sample.media.service.IFileService;
+import com.ard.sample.wayline.mapper.IWaylineJobHistoryMapper;
+import com.ard.sample.wayline.model.dto.WaylineJobDTO;
+import com.ard.sample.wayline.model.entity.WaylineJobEntity;
+import com.ard.sample.wayline.model.entity.WaylineJobHistoryEntity;
+import com.ard.sample.wayline.model.enums.WaylineJobStatusEnum;
+import com.ard.sample.wayline.service.IWaylineJobHistoryService;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
+
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+@Service
+@Transactional
+@Slf4j
+@SuppressWarnings("all")
+public class WaylineJobHistoryServiceImpl implements IWaylineJobHistoryService {
+ @Autowired
+ private IWaylineJobHistoryMapper mapper;
+
+ @Autowired
+ private IFileService fileService;
+
+ @Autowired
+ private IDeviceService deviceService;
+
+ @Override
+ public Optional<WaylineJobDTO> createWaylineJob(WaylineJobHistoryEntity entity) {
+ int id = mapper.insert(entity);
+ if (id <= 0) {
+ return Optional.empty();
+ }
+ return Optional.ofNullable(this.entity2Dto(entity));
+ }
+
+ @Override
+ public Boolean updateJob(WaylineJobDTO dto) {
+ int id = mapper.update(dto2Entity(dto),
+ new LambdaQueryWrapper<WaylineJobHistoryEntity>()
+ .eq(WaylineJobHistoryEntity::getJobId, dto.getJobId()
+ ));
+ return id>0;
+ }
+
+ @Override
+ public PaginationData<WaylineJobDTO> getJobsList(long page, long pageSize, Integer status,
+ Long startTime, Long endTime, Integer taskType,
+ String name, Boolean isComplete) {
+ Page<WaylineJobHistoryEntity> pageData = mapper.selectPage(
+ new Page<WaylineJobHistoryEntity>(page, pageSize),
+ new LambdaQueryWrapper<WaylineJobHistoryEntity>()
+ .isNull(WaylineJobHistoryEntity::getParentId)
+ // 实际开始时间筛选,允许为空,为空则不进行筛选
+ .ge(startTime != null, WaylineJobHistoryEntity::getBeginTime, startTime)
+ .le(endTime != null, WaylineJobHistoryEntity::getBeginTime, endTime)
+ // 任务类型筛选,允许为空,为空则不进行筛选
+ .eq(taskType != null, WaylineJobHistoryEntity::getTaskType, taskType)
+ // 任务名称筛选,允许为空,为空则不进行筛选;....模糊查询
+ .like(name != null, WaylineJobHistoryEntity::getName, "%" + name + "%")
+ // 根据是否完成筛选,允许为空,为空则不进行筛选
+ .eq(isComplete != null && isComplete, WaylineJobHistoryEntity::getStatus, 3)
+ .ne(isComplete != null && !isComplete, WaylineJobHistoryEntity::getStatus, 3)
+ // 任务状态筛选,允许为空,为空则不进行筛选
+ .eq(status != null, WaylineJobHistoryEntity::getStatus, status)
+ .orderByDesc(WaylineJobHistoryEntity::getBeginTime));
+ List<WaylineJobDTO> records = pageData.getRecords()
+ .stream()
+ .map(this::entity2Dto)
+ .peek(job -> {
+ List<WaylineJobDTO> childOpt = this.getJobByJobParentId(job.getJobId());
+ job.setChildren(childOpt);
+ })
+ .collect(Collectors.toList());
+
+ return new PaginationData<WaylineJobDTO>(records, new Pagination(pageData));
+ }
+
+ public List<WaylineJobDTO> getJobByJobParentId(String parentId) {
+ List<WaylineJobHistoryEntity> jobEntities = mapper.selectList(
+ new LambdaQueryWrapper<WaylineJobHistoryEntity>()
+ .eq(WaylineJobHistoryEntity::getParentId, parentId));
+ if (CollectionUtils.isEmpty(jobEntities)) {
+ return Collections.emptyList(); // 返回不可变空列表,更安全
+ }
+ return jobEntities.stream()
+ .map(this::entity2Dto) // 调用原有的单个转换方法
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ public Optional<WaylineJobDTO> getJobByJobId(String jobId) {
+ WaylineJobHistoryEntity jobEntities = mapper.selectOne(
+ new LambdaQueryWrapper<WaylineJobHistoryEntity>()
+ .eq(WaylineJobHistoryEntity::getJobId, jobId));
+ return Optional.ofNullable(this.entity2Dto(jobEntities));
+ }
+
+ /**
+ * 将WaylineJobDTO对象转换为WaylineJobHistoryEntity对象
+ *
+ * @param dto WaylineJobDTO对象
+ * @return WaylineJobHistoryEntity对象
+ */
+ @Override
+ public WaylineJobHistoryEntity dto2Entity(WaylineJobDTO dto) {
+ WaylineJobHistoryEntity.WaylineJobHistoryEntityBuilder builder = WaylineJobHistoryEntity.builder();
+
+ if (dto == null) {
+ return builder.build();
+ }
+ if (Objects.nonNull(dto.getBeginTime())) {
+ builder.beginTime(dto.getBeginTime().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
+ }
+ if (Objects.nonNull(dto.getEndTime())) {
+ builder.endTime(dto.getEndTime().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
+ }
+ if (Objects.nonNull(dto.getExecuteTime())) {
+ builder.executeTime(dto.getExecuteTime().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
+ }
+ if (Objects.nonNull(dto.getCompletedTime())) {
+ builder.completedTime(dto.getCompletedTime().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
+ }
+ return builder.status(dto.getStatus())
+ .mediaCount(dto.getMediaCount())
+ .name(dto.getJobName())
+ .errorCode(dto.getCode())
+ .jobId(dto.getJobId())
+ .fileId(dto.getFileId())
+ .filename(dto.getFileName())
+ .dockSn(dto.getDockSn())
+ .taskType(dto.getTaskType())
+ .waylineType(dto.getWaylineType())
+ .username(dto.getUsername())
+ .rthAltitude(dto.getRthAltitude())
+ .outOfControlAction(dto.getOutOfControlAction())
+ .parentId(dto.getParentId())
+ .loopSum(dto.getLoopSum())
+ .build();
+ }
+
+ /**
+ * 将实体对象转换为数据传输对象
+ *
+ * @param entity WaylineJobEntity 实体对象
+ * @return WaylineJobDTO 数据传输对象
+ */
+ private WaylineJobDTO entity2Dto(WaylineJobHistoryEntity entity) {
+ if (entity == null) {
+ return null;
+ }
+ // 修改航线文件名称,从ard_route_info航线表中取;
+ String fileId = entity.getFileId();
+ WaylineJobDTO.WaylineJobDTOBuilder builder = WaylineJobDTO.builder()
+ .jobId(entity.getJobId())
+ .jobName(entity.getName())
+ .fileId(entity.getFileId())
+ .fileName(entity.getFilename())
+ .dockSn(entity.getDockSn())
+ .dockName(deviceService.getDeviceBySn(entity.getDockSn())
+ .orElse(DeviceDTO.builder().build()).getNickname())
+ .username(entity.getUsername())
+ .status(entity.getStatus())
+ .code(entity.getErrorCode())
+ .beginTime(LocalDateTime.ofInstant(Instant.ofEpochMilli(entity.getBeginTime()), ZoneId.systemDefault()))
+ .endTime(Objects.nonNull(entity.getEndTime()) ?
+ LocalDateTime.ofInstant(Instant.ofEpochMilli(entity.getEndTime()), ZoneId.systemDefault()) : null)
+ .executeTime(Objects.nonNull(entity.getExecuteTime()) ?
+ LocalDateTime.ofInstant(Instant.ofEpochMilli(entity.getExecuteTime()), ZoneId.systemDefault()) : null)
+ .completedTime(WaylineJobStatusEnum.find(entity.getStatus()).getEnd() ?
+ LocalDateTime.ofInstant(Instant.ofEpochMilli(entity.getUpdateTime()), ZoneId.systemDefault()) : null)
+ .taskType(entity.getTaskType())
+ .waylineType(entity.getWaylineType())
+ .rthAltitude(entity.getRthAltitude())
+ .rthMode(entity.getRthMode())
+ .outOfControlAction(entity.getOutOfControlAction())
+ .mediaCount(entity.getMediaCount())
+ .loopSum(entity.getLoopSum());
+
+
+// if (Objects.nonNull(entity.getEndTime())) {
+// builder.endTime(LocalDateTime.ofInstant(Instant.ofEpochMilli(entity.getEndTime()), ZoneId.systemDefault()));
+// }
+// if (WaylineJobStatusEnum.IN_PROGRESS.getVal() == entity.getStatus() && RedisOpsUtils.getExpire(entity.getJobId()) > 0) {
+// EventsReceiver<WaylineTaskProgressReceiver> taskProgress = (EventsReceiver<WaylineTaskProgressReceiver>) RedisOpsUtils.get(RedisConst.WAYLINE_JOB_RUNNING_PREFIX + entity.getDockSn());
+// if (Objects.nonNull(taskProgress.getOutput()) && Objects.nonNull(taskProgress.getOutput().getProgress())) {
+// builder.progress(taskProgress.getOutput().getProgress().getPercent());
+// }
+// }
+//
+// if (entity.getMediaCount() == 0) {
+// return builder.build();
+// }
+//
+// // sync the number of media files
+// String key = RedisConst.MEDIA_HIGHEST_PRIORITY_PREFIX + entity.getDockSn();
+// String countKey = RedisConst.MEDIA_FILE_PREFIX + entity.getDockSn();
+// Object mediaFileCount = RedisOpsUtils.hashGet(countKey, entity.getJobId());
+// if (Objects.nonNull(mediaFileCount)) {
+// builder.uploadedCount(((MediaFileCountDTO) mediaFileCount).getUploadedCount())
+// .uploading(RedisOpsUtils.checkExist(key) && entity.getJobId().equals(((MediaFileCountDTO) RedisOpsUtils.get(key)).getJobId()));
+// return builder.build();
+// }
+
+// int uploadedSize = fileService.getFilesByWorkspaceAndJobId(entity.getJobId()).size();
+// // All media for this job have been uploaded.
+// if (uploadedSize >= entity.getMediaCount()) {
+// return builder.uploadedCount(uploadedSize).build();
+// }
+// RedisOpsUtils.hashSet(countKey, entity.getJobId(),
+// MediaFileCountDTO.builder()
+// .jobId(entity.getJobId())
+// .mediaCount(entity.getMediaCount())
+// .uploadedCount(uploadedSize).build());
+ return builder.build();
+ }
+}
--
Gitblit v1.9.3