Commit 94d9ec2a by gdj

空中下发航线功能。

parent 12ad04c9
package com.dji.sdk.cloudapi.wayline;
import com.dji.sdk.annotations.CloudSDKVersion;
import com.dji.sdk.cloudapi.device.ExitWaylineWhenRcLostEnum;
import com.dji.sdk.common.BaseModel;
import com.dji.sdk.config.version.CloudSDKVersionEnum;
import com.dji.sdk.config.version.GatewayTypeEnum;
import javax.validation.Valid;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
/**
* @author sean
* @version 1.7
* @date 2023/6/6
*/
public class InFlightWaylineTaskPrepareRequest extends BaseModel {
/**
* 航线任务ID
*/
@NotNull
@Pattern(regexp = "^[^<>:\"/|?*._\\\\]+$")
private String inFlightWaylineId;
/**
* 返航高度 {min: 20, max: 1500}
*/
@NotNull
@Min(20)
@Max(1500)
private Integer rthAltitude;
/**
* 遥控器失控时的动作 {0: "返航", 1: "悬停", 2: "降落"}
*/
@NotNull
private OutOfControlActionEnum outOfControlAction;
/**
* 航线失联时的动作 {0: "继续执行", 1: "执行飞控失控动作"}
*/
@NotNull
private ExitWaylineWhenRcLostEnum exitWaylineWhenRcLost;
/**
* 返航高度模式 {0: "智能高度", 1: "设定高度"}
*/
@CloudSDKVersion(since = CloudSDKVersionEnum.V1_0_0)
private RthModeEnum rthMode = RthModeEnum.PRESET_HEIGHT;
/**
* 航线精度类型 {0: "GPS任务", 1: "高精度RTK任务"}
*/
@NotNull
@CloudSDKVersion(since = CloudSDKVersionEnum.V1_0_1, include = {GatewayTypeEnum.DOCK2, GatewayTypeEnum.DOCK3})
private WaylinePrecisionTypeEnum waylinePrecisionType;
/**
* 航线文件信息
*/
@NotNull
@Valid
private FlighttaskFile file;
/**
* 草莓自定义流程
*/
private CustomProcess customProcess;
public InFlightWaylineTaskPrepareRequest() {}
@Override
public String toString() {
return "FlighttaskPrepareRequest{" +
"inFlightWaylineId='" + inFlightWaylineId + '\'' +
", file=" + file +
", rthAltitude=" + rthAltitude +
", outOfControlAction=" + outOfControlAction +
", exitWaylineWhenRcLost=" + exitWaylineWhenRcLost +
", rthMode=" + rthMode +
", waylinePrecisionType=" + waylinePrecisionType +
", customProcess=" + customProcess +
'}';
}
public String getInFlightWaylineId() {
return inFlightWaylineId;
}
public InFlightWaylineTaskPrepareRequest setInFlightWaylineId(String inFlightWaylineId) {
this.inFlightWaylineId = inFlightWaylineId;
return this;
}
public FlighttaskFile getFile() {
return file;
}
public InFlightWaylineTaskPrepareRequest setFile(FlighttaskFile file) {
this.file = file;
return this;
}
public Integer getRthAltitude() {
return rthAltitude;
}
public InFlightWaylineTaskPrepareRequest setRthAltitude(Integer rthAltitude) {
this.rthAltitude = rthAltitude;
return this;
}
public OutOfControlActionEnum getOutOfControlAction() {
return outOfControlAction;
}
public InFlightWaylineTaskPrepareRequest setOutOfControlAction(OutOfControlActionEnum outOfControlAction) {
this.outOfControlAction = outOfControlAction;
return this;
}
public ExitWaylineWhenRcLostEnum getExitWaylineWhenRcLost() {
return exitWaylineWhenRcLost;
}
public InFlightWaylineTaskPrepareRequest setExitWaylineWhenRcLost(ExitWaylineWhenRcLostEnum exitWaylineWhenRcLost) {
this.exitWaylineWhenRcLost = exitWaylineWhenRcLost;
return this;
}
public RthModeEnum getRthMode() {
return rthMode;
}
public InFlightWaylineTaskPrepareRequest setRthMode(RthModeEnum rthMode) {
this.rthMode = rthMode;
return this;
}
public CustomProcess getCustomProcess() {
return customProcess;
}
public InFlightWaylineTaskPrepareRequest setCustomProcess(CustomProcess customProcess) {
this.customProcess = customProcess;
return this;
}
public WaylinePrecisionTypeEnum getWaylinePrecisionType() {
return waylinePrecisionType;
}
public InFlightWaylineTaskPrepareRequest setWaylinePrecisionType(WaylinePrecisionTypeEnum waylinePrecisionType) {
this.waylinePrecisionType = waylinePrecisionType;
return this;
}
}
\ No newline at end of file
......@@ -23,7 +23,29 @@ public enum WaylineMethodEnum {
RETURN_HOME("return_home"),
RETURN_HOME_CANCEL("return_home_cancel");
RETURN_HOME_CANCEL("return_home_cancel"),
/**
* 空中下发航线
*/
IN_FLIGHT_WAYLINE_DELIVER("in_flight_wayline_deliver"),
/**
* 暂停空中航线
*/
IN_FLIGHT_WAYLINE_STOP("in_flight_wayline_stop"),
/**
* 恢复空中航线
*/
IN_FLIGHT_WAYLINE_RECOVER("in_flight_wayline_recover"),
/**
* 取消空中航线
*/
IN_FLIGHT_WAYLINE_CANCEL("in_flight_wayline_cancel"),
;
private final String method;
......
......@@ -2,6 +2,7 @@ package com.dji.sdk.cloudapi.wayline.api;
import com.dji.sdk.annotations.CloudSDKVersion;
import com.dji.sdk.cloudapi.wayline.*;
import com.dji.sdk.common.BaseModel;
import com.dji.sdk.config.version.CloudSDKVersionEnum;
import com.dji.sdk.common.Common;
import com.dji.sdk.config.version.GatewayManager;
......@@ -203,4 +204,36 @@ public abstract class AbstractWaylineService {
}
}
/**
* 空中下发航线
* @param gateway
* @return services_reply
*/
@CloudSDKVersion(exclude = {GatewayTypeEnum.RC, GatewayTypeEnum.DOCK})
public TopicServicesResponse<ServicesReplyData> inFlightWaylineTaskPrepare(GatewayManager gateway, InFlightWaylineTaskPrepareRequest request) {
validInFlightWaylineTaskPrepareParam(request);
return servicesPublish.publish(
gateway.getGatewaySn(),
WaylineMethodEnum.IN_FLIGHT_WAYLINE_DELIVER.getMethod(),
request,
request.getInFlightWaylineId());
}
private void validInFlightWaylineTaskPrepareParam(InFlightWaylineTaskPrepareRequest request) {
}
/**
* 取消空中航线
* @param gateway
* @return services_reply
*/
@CloudSDKVersion(exclude = {GatewayTypeEnum.RC, GatewayTypeEnum.DOCK})
public TopicServicesResponse<ServicesReplyData> inFlightWaylineCancel(GatewayManager gateway, BaseModel request) {
return servicesPublish.publish(
gateway.getGatewaySn(),
WaylineMethodEnum.IN_FLIGHT_WAYLINE_CANCEL.getMethod(),
request);
}
}
......@@ -4,6 +4,7 @@ import com.dji.sample.common.model.CustomClaim;
import com.dji.sample.wayline.model.dto.TaskStatisticDTO;
import com.dji.sample.wayline.model.dto.WaylineJobDTO;
import com.dji.sample.wayline.model.entity.WaylineJobEntity;
import com.dji.sample.wayline.model.param.CreateInFlightJobParam;
import com.dji.sample.wayline.model.param.CreateJobParam;
import com.dji.sample.wayline.model.param.UpdateJobParam;
import com.dji.sample.wayline.model.param.WaylineJobSearchParam;
......@@ -146,5 +147,38 @@ public class WaylineJobController {
waylineJobService.exportTaskList(response, workspaceId);
}
/**
* 空中下发航线 in_flight_wayline_deliver
*/
@PostMapping("/{workspace_id}/in-flight-tasks")
public HttpResultResponse createInFlightJob(HttpServletRequest request, @Valid @RequestBody CreateInFlightJobParam param,
@PathVariable(name = "workspace_id") String workspaceId) throws SQLException {
CustomClaim customClaim = (CustomClaim)request.getAttribute(TOKEN_CLAIM);
customClaim.setWorkspaceId(workspaceId);
return flighttaskService.publishInFlightTask(param, customClaim);
}
/**
* 暂停 或者 恢复 空中航线 in_flight_wayline_stop in_flight_wayline_recover
*/
@PutMapping("/{workspace_id}/inFlightJobs/{job_id}")
public HttpResultResponse updateInFlightJobStatus(@PathVariable(name = "workspace_id") String workspaceId,
@PathVariable(name = "job_id") String jobId,
@Valid @RequestBody UpdateJobParam param) {
// todo
// flighttaskService.updateJobStatus(workspaceId, jobId, param);
return HttpResultResponse.success();
}
/**
* 取消空中航线 in_flight_wayline_cancel
*/
@DeleteMapping("/{workspace_id}/inFlightJobs")
public HttpResultResponse publishCanceInFlightlJob(@RequestParam(name = "dockeSn") String dockSn,
@PathVariable(name = "workspace_id") String workspaceId) throws SQLException {
flighttaskService.cancelInFlightTask(workspaceId, dockSn);
return HttpResultResponse.success();
}
}
package com.dji.sample.wayline.model.param;
import com.dji.sdk.cloudapi.wayline.OutOfControlActionEnum;
import com.dji.sdk.cloudapi.wayline.TaskTypeEnum;
import com.dji.sdk.cloudapi.wayline.WaylineTypeEnum;
import lombok.Data;
import org.hibernate.validator.constraints.Range;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
* 空中下发航线
* @author guan
*/
@Data
public class CreateInFlightJobParam {
@NotBlank
private String name;
@NotBlank
private String fileId;
@NotBlank
private String dockSn;
@NotNull
private WaylineTypeEnum waylineType;
@NotNull
private TaskTypeEnum taskType;
@Range(min = 20, max = 500)
@NotNull
private Integer rthAltitude;
@NotNull
private OutOfControlActionEnum outOfControlAction;
private List<Long> taskDays;
private List<List<Long>> taskPeriods;
private String orgId;
}
......@@ -3,6 +3,7 @@ package com.dji.sample.wayline.service;
import com.dji.sample.common.model.CustomClaim;
import com.dji.sample.wayline.model.dto.ConditionalWaylineJobKey;
import com.dji.sample.wayline.model.dto.WaylineJobDTO;
import com.dji.sample.wayline.model.param.CreateInFlightJobParam;
import com.dji.sample.wayline.model.param.CreateJobParam;
import com.dji.sample.wayline.model.param.UpdateJobParam;
import com.dji.sdk.common.HttpResultResponse;
......@@ -75,4 +76,23 @@ public interface IFlightTaskService {
void updateJobStatus(String workspaceId, String jobId, UpdateJobParam param);
void retryPrepareJob(ConditionalWaylineJobKey jobKey, WaylineJobDTO waylineJob);
/**
* 空中下发航线
* @param param
* @param customClaim user info
* @return
*/
HttpResultResponse publishInFlightTask(CreateInFlightJobParam param, CustomClaim customClaim) throws SQLException;
/**
* 取消空中航线
* @param workspaceId
* @param dockSn
* @throws SQLException
*/
void cancelInFlightTask(String workspaceId, String dockSn);
void publishCancelInFlightTask(String workspaceId, String dockSn);
}
......@@ -5,6 +5,7 @@ import com.dji.sample.wayline.model.dto.TaskStatisticDTO;
import com.dji.sample.wayline.model.dto.WaylineJobDTO;
import com.dji.sample.wayline.model.entity.WaylineJobEntity;
import com.dji.sample.wayline.model.enums.WaylineJobStatusEnum;
import com.dji.sample.wayline.model.param.CreateInFlightJobParam;
import com.dji.sample.wayline.model.param.CreateJobParam;
import com.dji.sample.wayline.model.param.WaylineJobSearchParam;
import com.dji.sdk.common.PaginationData;
......@@ -32,6 +33,8 @@ public interface IWaylineJobService extends IService<WaylineJobEntity> {
*/
Optional<WaylineJobDTO> createWaylineJob(CreateJobParam param, String workspaceId, String username, Long beginTime, Long endTime);
Optional<WaylineJobDTO> createInFlightWaylineJob(CreateInFlightJobParam param, String workspaceId, String username, Long beginTime, Long endTime);
/**
* Create a sub-task based on the information of the parent task.
* @param workspaceId
......
......@@ -17,6 +17,7 @@ import com.dji.sample.wayline.model.dto.WaylineJobDTO;
import com.dji.sample.wayline.model.dto.WaylineTaskConditionDTO;
import com.dji.sample.wayline.model.enums.WaylineErrorCodeEnum;
import com.dji.sample.wayline.model.enums.WaylineJobStatusEnum;
import com.dji.sample.wayline.model.param.CreateInFlightJobParam;
import com.dji.sample.wayline.model.param.CreateJobParam;
import com.dji.sample.wayline.model.param.UpdateJobParam;
import com.dji.sample.wayline.service.IFlightTaskService;
......@@ -28,6 +29,7 @@ import com.dji.sdk.cloudapi.media.UploadFlighttaskMediaPrioritize;
import com.dji.sdk.cloudapi.media.api.AbstractMediaService;
import com.dji.sdk.cloudapi.wayline.*;
import com.dji.sdk.cloudapi.wayline.api.AbstractWaylineService;
import com.dji.sdk.common.BaseModel;
import com.dji.sdk.common.HttpResultResponse;
import com.dji.sdk.common.SDKManager;
import com.dji.sdk.mqtt.MqttReply;
......@@ -588,4 +590,180 @@ public class FlightTaskServiceImpl extends AbstractWaylineService implements IFl
return new TopicEventsResponse<>();
}
@Override
public HttpResultResponse publishInFlightTask(CreateInFlightJobParam param, CustomClaim customClaim) throws SQLException {
fillInflightImmediateTime(param);
// 直接默认 立即起飞
for (Long taskDay : param.getTaskDays()) {
LocalDate date = LocalDate.ofInstant(Instant.ofEpochSecond(taskDay), ZoneId.systemDefault());
for (List<Long> taskPeriod : param.getTaskPeriods()) {
long beginTime = LocalDateTime.of(date, LocalTime.ofInstant(Instant.ofEpochSecond(taskPeriod.get(0)), ZoneId.systemDefault()))
.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
long endTime = taskPeriod.size() > 1 ?
LocalDateTime.of(date, LocalTime.ofInstant(Instant.ofEpochSecond(taskPeriod.get(1)), ZoneId.systemDefault()))
.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() : beginTime;
if (TaskTypeEnum.IMMEDIATE != param.getTaskType() && endTime < System.currentTimeMillis()) {
continue;
}
Optional<WaylineJobDTO> waylineJobOpt = waylineJobService.createInFlightWaylineJob(param, customClaim.getWorkspaceId(), customClaim.getUsername(), beginTime, endTime);
if (waylineJobOpt.isEmpty()) {
throw new SQLException("Failed to create wayline job.");
}
WaylineJobDTO waylineJob = waylineJobOpt.get();
// If it is a conditional task type, add conditions to the job parameters.
// todo
addConditionsInFlight(waylineJob, param, beginTime, endTime);
HttpResultResponse response = this.publishOneInFlightFlightTask(waylineJob);
if (HttpResultResponse.CODE_SUCCESS != response.getCode()) {
return response;
}
}
}
return HttpResultResponse.success();
}
private void fillInflightImmediateTime(CreateInFlightJobParam param) {
if (TaskTypeEnum.IMMEDIATE != param.getTaskType()) {
return;
}
long now = System.currentTimeMillis() / 1000;
param.setTaskDays(List.of(now));
param.setTaskPeriods(List.of(List.of(now)));
}
private void addConditionsInFlight(WaylineJobDTO waylineJob, CreateInFlightJobParam param, Long beginTime, Long endTime) {
waylineJob.setConditions(
WaylineTaskConditionDTO.builder()
// .executableConditions(Objects.nonNull(param.getMinStorageCapacity()) ?
// new ExecutableConditions().setStorageCapacity(param.getMinStorageCapacity()) : null)
.executableConditions(null)
.readyConditions(new ReadyConditions()
// .setBatteryCapacity(param.getMinBatteryCapacity())
.setBeginTime(beginTime)
.setEndTime(endTime))
.build());
waylineRedisService.setConditionalWaylineJob(waylineJob);
// key: wayline_job_condition, value: {workspace_id}:{dock_sn}:{job_id}
boolean isAdd = waylineRedisService.addPrepareConditionalWaylineJob(waylineJob);
if (!isAdd) {
throw new RuntimeException("Failed to create conditional job.");
}
}
public HttpResultResponse publishOneInFlightFlightTask(WaylineJobDTO waylineJob) throws SQLException {
boolean isOnline = deviceRedisService.checkDeviceOnline(waylineJob.getDockSn());
if (!isOnline) {
throw new RuntimeException("Dock is offline.");
}
DockModeCodeEnum dockModeCodeEnum = deviceRedisService.getDeviceOsd(waylineJob.getDockSn(), OsdDock.class)
.map(OsdDock::getModeCode).orElse(null);
if (dockModeCodeEnum == null || dockModeCodeEnum == DockModeCodeEnum.REMOTE_DEBUGGING) {
throw new RuntimeException("Dock is remote_debugging state, does not support flight task.");
}
boolean isSuccess = this.prepareInFlightTask(waylineJob);
if (!isSuccess) {
return HttpResultResponse.error("Failed to prepare job.");
}
// Issue an immediate task execution command.
if (TaskTypeEnum.IMMEDIATE == waylineJob.getTaskType()) {
if (!executeFlightTask(waylineJob.getWorkspaceId(), waylineJob.getJobId())) {
return HttpResultResponse.error("Failed to execute job.");
}
}
// 发送 邮件
// this.sendCreatedTaskMail(waylineJob);
return HttpResultResponse.success();
}
private Boolean prepareInFlightTask(WaylineJobDTO waylineJob) throws SQLException {
// get wayline file
Optional<GetWaylineListResponse> waylineFile = waylineFileService.getWaylineByWaylineId(waylineJob.getWorkspaceId(), waylineJob.getFileId());
if (waylineFile.isEmpty()) {
throw new SQLException("Wayline file doesn't exist.");
}
// get file url
URL url = waylineFileService.getObjectUrl(waylineJob.getWorkspaceId(), waylineFile.get().getId());
InFlightWaylineTaskPrepareRequest flightTask = new InFlightWaylineTaskPrepareRequest()
.setInFlightWaylineId(waylineJob.getJobId())
.setRthAltitude(waylineJob.getRthAltitude())
.setOutOfControlAction(waylineJob.getOutOfControlAction())
.setExitWaylineWhenRcLost(ExitWaylineWhenRcLostEnum.EXECUTE_RC_LOST_ACTION)
.setWaylinePrecisionType(WaylinePrecisionTypeEnum.RTK)
.setFile(new FlighttaskFile()
.setUrl(url.toString())
.setFingerprint(waylineFile.get().getSign()));
if (waylineJob.getCustomProcess() != null) {
flightTask.setCustomProcess(waylineJob.getCustomProcess());
}
TopicServicesResponse<ServicesReplyData> serviceReply = abstractWaylineService.inFlightWaylineTaskPrepare(
SDKManager.getDeviceSDK(waylineJob.getDockSn()), flightTask);
if (!serviceReply.getData().getResult().isSuccess()) {
log.info("Prepare task ====> Error code: {}", serviceReply.getData().getResult());
waylineJobService.updateJob(WaylineJobDTO.builder()
.workspaceId(waylineJob.getWorkspaceId())
.jobId(waylineJob.getJobId())
.executeTime(LocalDateTime.now())
.status(WaylineJobStatusEnum.FAILED.getVal())
.completedTime(LocalDateTime.now())
.code(serviceReply.getData().getResult().getCode()).build());
return false;
}
return true;
}
/**
* 取消空中航线
* @param workspaceId
* @param dockSn
*/
@Override
public void cancelInFlightTask(String workspaceId, String dockSn) {
// 是否需要判断 无人机的状态 工作中 航线?
this.publishCancelInFlightTask(workspaceId, dockSn);
}
@Override
public void publishCancelInFlightTask(String workspaceId, String dockSn) {
boolean isOnline = deviceRedisService.checkDeviceOnline(dockSn);
if (!isOnline) {
throw new RuntimeException("Dock is offline.");
}
// 取消空中航线
TopicServicesResponse<ServicesReplyData> serviceReply = abstractWaylineService.inFlightWaylineCancel(SDKManager.getDeviceSDK(dockSn), new BaseModel());
if (!serviceReply.getData().getResult().isSuccess()) {
log.info("Cancel job ====> Error: {}", serviceReply.getData().getResult());
throw new RuntimeException("Failed to cancel the wayline job of " + dockSn);
}
// 还需要查询 对应的空中下发航线的in_flight_id;
// for (String jobId : jobIds) {
// waylineJobService.updateJob(WaylineJobDTO.builder()
// .workspaceId(workspaceId)
// .jobId(jobId)
// .status(WaylineJobStatusEnum.CANCEL.getVal())
// .completedTime(LocalDateTime.now())
// .build());
// RedisOpsUtils.zRemove(RedisConst.WAYLINE_JOB_TIMED_EXECUTE, workspaceId + RedisConst.DELIMITER + dockSn + RedisConst.DELIMITER + jobId);
// }
}
}
......@@ -21,6 +21,7 @@ import com.dji.sample.wayline.model.entity.WaylineFileEntity;
import com.dji.sample.wayline.model.entity.WaylineJobEntity;
import com.dji.sample.wayline.model.enums.TaskSceneEnum;
import com.dji.sample.wayline.model.enums.WaylineJobStatusEnum;
import com.dji.sample.wayline.model.param.CreateInFlightJobParam;
import com.dji.sample.wayline.model.param.CreateJobParam;
import com.dji.sample.wayline.model.param.WaylineJobSearchParam;
import com.dji.sample.wayline.service.IWaylineFileService;
......@@ -151,6 +152,16 @@ public class WaylineJobServiceImpl extends ServiceImpl<IWaylineJobMapper, Waylin
return this.insertWaylineJob(jobEntity);
}
public String spliceJobId(String jobName) {
LocalDateTime now = LocalDateTime.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd-HH-mm-ss");
String formattedDateTime = now.format(formatter);
return jobName.length() > 20 ? jobName.substring(0, 20) : jobName + "-" + formattedDateTime+ "-" + UUID.randomUUID().toString().substring(0, 4);
}
@Override
public List<WaylineJobDTO> getJobsByConditions(String workspaceId, Collection<String> jobIds, WaylineJobStatusEnum status) {
return mapper.selectList(
new LambdaQueryWrapper<WaylineJobEntity>()
......@@ -390,14 +401,15 @@ public class WaylineJobServiceImpl extends ServiceImpl<IWaylineJobMapper, Waylin
entity.getJobId().equals(waylineRedisService.getPausedWaylineJobId(entity.getDockSn())) ?
WaylineJobStatusEnum.PAUSED.getVal() : entity.getStatus())
.code(entity.getErrorCode())
.beginTime(LocalDateTime.ofInstant(Instant.ofEpochMilli(entity.getBeginTime()), ZoneId.systemDefault()))
.beginTime(Objects.nonNull(entity.getBeginTime()) ?
LocalDateTime.ofInstant(Instant.ofEpochMilli(entity.getBeginTime()), ZoneId.systemDefault()) : null)
.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(TaskTypeEnum.find(entity.getTaskType()))
.taskType(Objects.nonNull(entity.getTaskType()) ? TaskTypeEnum.find(entity.getTaskType()) : null)
.taskScene(Objects.nonNull(entity.getTaskScene()) ? TaskSceneEnum.find(entity.getTaskScene()) : null)
.waylineType(WaylineTypeEnum.find(entity.getWaylineType()))
.rthAltitude(entity.getRthAltitude())
......@@ -740,4 +752,114 @@ public class WaylineJobServiceImpl extends ServiceImpl<IWaylineJobMapper, Waylin
}
@Override
public Optional<WaylineJobDTO> createInFlightWaylineJob(CreateInFlightJobParam param, String workspaceId, String username, Long beginTime, Long endTime) {
if (Objects.isNull(param)) {
return Optional.empty();
}
// Immediate tasks, allocating time on the backend.
String jobId = spliceJobId(param.getName());
WaylineJobEntity jobEntity = WaylineJobEntity.builder()
.name(param.getName())
.dockSn(param.getDockSn())
.fileId(param.getFileId())
.waylineType(param.getWaylineType().getValue())
.username(username)
.workspaceId(workspaceId)
.orgId(StringUtils.hasText(param.getOrgId()) ? param.getOrgId() : getOrgId())
.jobId(jobId)
.beginTime(beginTime)
.endTime(endTime)
.status(WaylineJobStatusEnum.PENDING.getVal())
.taskType(param.getTaskType().getType())
.outOfControlAction(param.getOutOfControlAction().getAction())
.rthAltitude(param.getRthAltitude())
.mediaCount(0)
.build();
return insertInFlightWaylineJob(jobEntity);
}
private Optional<WaylineJobDTO> insertInFlightWaylineJob(WaylineJobEntity jobEntity) {
int id = mapper.insert(jobEntity);
if (id <= 0) {
return Optional.empty();
}
return Optional.ofNullable(this.inFlightentity2Dto(jobEntity));
}
private WaylineJobDTO inFlightentity2Dto(WaylineJobEntity entity) {
if (entity == null) {
return null;
}
WaylineJobDTO.WaylineJobDTOBuilder builder = WaylineJobDTO.builder()
.jobId(entity.getJobId())
.jobName(entity.getName())
.fileId(entity.getFileId())
.fileName(waylineFileService.getWaylineByWaylineId(entity.getWorkspaceId(), entity.getFileId())
.orElse(new GetWaylineListResponse()).getName())
.dockSn(entity.getDockSn())
.dockName(deviceService.getDeviceBySn(entity.getDockSn())
.orElse(DeviceDTO.builder().build()).getNickname())
.username(entity.getUsername())
.workspaceId(entity.getWorkspaceId())
.orgId(entity.getOrgId())
.status(WaylineJobStatusEnum.IN_PROGRESS.getVal() == entity.getStatus() &&
entity.getJobId().equals(waylineRedisService.getPausedWaylineJobId(entity.getDockSn())) ?
WaylineJobStatusEnum.PAUSED.getVal() : entity.getStatus())
.code(entity.getErrorCode())
.beginTime(Objects.nonNull(entity.getBeginTime()) ?
LocalDateTime.ofInstant(Instant.ofEpochMilli(entity.getBeginTime()), ZoneId.systemDefault()) : null)
.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(Objects.nonNull(entity.getTaskType()) ? TaskTypeEnum.find(entity.getTaskType()) : null)
.taskScene(Objects.nonNull(entity.getTaskScene()) ? TaskSceneEnum.find(entity.getTaskScene()) : null)
.waylineType(WaylineTypeEnum.find(entity.getWaylineType()))
.rthAltitude(entity.getRthAltitude())
.outOfControlAction(OutOfControlActionEnum.find(entity.getOutOfControlAction()))
.mediaCount(entity.getMediaCount());
if (Objects.nonNull(entity.getEndTime())) {
builder.endTime(LocalDateTime.ofInstant(Instant.ofEpochMilli(entity.getEndTime()), ZoneId.systemDefault()));
}
if (WaylineJobStatusEnum.IN_PROGRESS.getVal() == entity.getStatus()) {
builder.progress(waylineRedisService.getRunningWaylineJob(entity.getDockSn())
.map(EventsReceiver::getOutput)
.map(FlighttaskProgress::getProgress)
.map(FlighttaskProgressData::getPercent)
.orElse(null));
}
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.getWorkspaceId(), 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();
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment