Compare commits

..

2 Commits

Author SHA1 Message Date
zhangchuang 762fdf1d7b Merge branch '1.0.0-multi' into 1.0.0
# Conflicts:
#	admin/src/main/java/com/multictrl/modules/business/dto/flight/FlightTaskPrepare.java
#	admin/src/main/java/com/multictrl/modules/business/handler/OsdHandler.java
#	admin/src/main/java/com/multictrl/modules/business/service/impl/RouteFlightServiceImpl.java
#	prj-deploy/file/pgsql/init.sql
2026-06-05 10:24:13 +08:00
zhangchuang 5c0549e8d0 1、阿罗斯机库蛙跳 2026-06-03 17:53:20 +08:00
25 changed files with 718 additions and 103 deletions

View File

@ -47,6 +47,8 @@ public interface BusinessConstant {
String AIRPORT_ORGANIZATION_GET = "airport_organization_get"; String AIRPORT_ORGANIZATION_GET = "airport_organization_get";
String AIRPORT_ORGANIZATION_BIND = "airport_organization_bind"; String AIRPORT_ORGANIZATION_BIND = "airport_organization_bind";
String FLIGHT_TASK_RESOURCE_GET = "flighttask_resource_get"; String FLIGHT_TASK_RESOURCE_GET = "flighttask_resource_get";
//私有协议为了确认跳飞场景下妙算pskd设备是否开启成功
String PRIVATE_GET_MULTI_MIAOSUAN_PSDK_STATUS = "private_get_multi_miaosuan_psdk_status";
//********************************* dj events topic method *********************************// //********************************* dj events topic method *********************************//
String FLIGHTTASK_PROGRESS = "flighttask_progress"; String FLIGHTTASK_PROGRESS = "flighttask_progress";
String TAKEOFF_TO_POINT_PROGRESS = "takeoff_to_point_progress"; String TAKEOFF_TO_POINT_PROGRESS = "takeoff_to_point_progress";

View File

@ -25,13 +25,14 @@ import java.util.List;
@RestController @RestController
@RequestMapping("business/command") @RequestMapping("business/command")
@Tag(name = "航线飞行", description = """ @Tag(name = "航线飞行", description = """
航线管理是无人机自主作业的重要功能 航线管理是无人机自主作业的重要功能
可以实现行业领域的批量化智能化作业 可以实现行业领域的批量化智能化作业
上云 API 提供了相关的接口实现了航线任务在云端的共享查看下发执行取消以及进度上报等功能 上云 API 提供了相关的接口实现了航线任务在云端的共享查看下发执行取消以及进度上报等功能
用户需要遵照航线文件格式规范WPML编写航线文件定义航线任务一个航线任务中可以定义多条航线""") 用户需要遵照航线文件格式规范WPML编写航线文件定义航线任务一个航线任务中可以定义多条航线""")
@ApiOrder(5) @ApiOrder(5)
@RequiredArgsConstructor @RequiredArgsConstructor
public class RouteFlightController { public class RouteFlightController {
private final DJIBaseService djiBaseService; private final DJIBaseService djiBaseService;
private final RouteFlightService routeFlightService; private final RouteFlightService routeFlightService;
@ -76,7 +77,7 @@ public class RouteFlightController {
@Operation(summary = "取消任务") @Operation(summary = "取消任务")
@RequiresPermissions("bus:route:flight:flightTaskUndo") @RequiresPermissions("bus:route:flight:flightTaskUndo")
public Result<Object> flightTaskUndo(@PathVariable String dockSn, public Result<Object> flightTaskUndo(@PathVariable String dockSn,
@RequestBody List<String> taskIds) { @RequestBody List<String> taskIds) {
if (taskIds.isEmpty()) { if (taskIds.isEmpty()) {
return new Result<>().error(ErrorCode.PARAMS_ERROR); return new Result<>().error(ErrorCode.PARAMS_ERROR);
} }
@ -89,7 +90,7 @@ public class RouteFlightController {
@Operation(summary = "执行航线") @Operation(summary = "执行航线")
@RequiresPermissions("bus:route:flight:flightExecute") @RequiresPermissions("bus:route:flight:flightExecute")
public Result<Object> flightExecute(@PathVariable String dockSn, public Result<Object> flightExecute(@PathVariable String dockSn,
@RequestBody FlightExecute flightExecute) { @RequestBody FlightExecute flightExecute) {
return new Result<>().ok(routeFlightService.flightExecute(dockSn, flightExecute, true)); return new Result<>().ok(routeFlightService.flightExecute(dockSn, flightExecute, true));
} }
@ -99,8 +100,8 @@ public class RouteFlightController {
@Operation(summary = "空中下发航线") @Operation(summary = "空中下发航线")
@RequiresPermissions("bus:route:flight:inFlightWaylineDeliver") @RequiresPermissions("bus:route:flight:inFlightWaylineDeliver")
public Result<Object> inFlightWaylineDeliver(@PathVariable String dockSn, public Result<Object> inFlightWaylineDeliver(@PathVariable String dockSn,
@Parameter(name = "routeId", description = "航线标识") @Parameter(name = "routeId", description = "航线标识")
@RequestParam Long routeId) { @RequestParam Long routeId) {
return new Result<>().ok(routeFlightService.inFlightWaylineDeliver(dockSn, routeId)); return new Result<>().ok(routeFlightService.inFlightWaylineDeliver(dockSn, routeId));
} }

View File

@ -0,0 +1,16 @@
package com.multictrl.modules.business.dao;
import com.multictrl.common.dao.BaseDao;
import com.multictrl.modules.business.entity.MultiGroupEntity;
import org.apache.ibatis.annotations.Mapper;
/**
* 蛙跳组信息
*
* @author 张闯
* @since 2026-05-28
*/
@Mapper
public interface MultiGroupDao extends BaseDao<MultiGroupEntity> {
}

View File

@ -0,0 +1,16 @@
package com.multictrl.modules.business.dao;
import com.multictrl.common.dao.BaseDao;
import com.multictrl.modules.business.entity.MultiGroupDeviceEntity;
import org.apache.ibatis.annotations.Mapper;
/**
* 蛙跳组绑定的设备信息
*
* @author 张闯
* @since 2026-05-28
*/
@Mapper
public interface MultiGroupDeviceDao extends BaseDao<MultiGroupDeviceEntity> {
}

View File

@ -55,6 +55,10 @@ public class DockDTO implements Serializable {
@Schema(description = "机库型号") @Schema(description = "机库型号")
private String dockModel; private String dockModel;
@NotBlank(message = "{dock.model.require}", groups = {AddGroup.class, UpdateGroup.class})
@Schema(description = "使用场景")
private String scenario;
@NotNull(message = "{dept.id.require}", groups = {AddGroup.class, UpdateGroup.class}) @NotNull(message = "{dept.id.require}", groups = {AddGroup.class, UpdateGroup.class})
@JsonProperty(required = true) @JsonProperty(required = true)
@Schema(description = "所属部门") @Schema(description = "所属部门")

View File

@ -1,7 +1,9 @@
package com.multictrl.modules.business.dto.flight; package com.multictrl.modules.business.dto.flight;
import com.multictrl.modules.business.dto.multi.PrivateMultiFlightBindDockInfo;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
import java.util.List;
import lombok.Data; import lombok.Data;
/** /**
@ -20,4 +22,9 @@ public class FlightExecute {
@Schema(description = "模拟器执行") @Schema(description = "模拟器执行")
private FlightTaskPrepare.SimulateMission simulateMission; private FlightTaskPrepare.SimulateMission simulateMission;
@Schema(hidden = true)
List<PrivateMultiFlightBindDockInfo> privateMultiFlightBindDockInfos;
@Schema(hidden = true)
private String taskId;
} }

View File

@ -24,14 +24,14 @@ public class FlightTaskPrepare {
//开始执行时间 //开始执行时间
// 任务开始执行时间毫秒时间戳 // 任务开始执行时间毫秒时间戳
// 可选字段 task_type 0 1 时必填 2 时非必填 // 可选字段 task_type 0 1 时必填 2 时非必填
private Long execute_time; private long execute_time;
//任务类型 //任务类型
//{"0":"立即任务","1":"定时任务","2":"条件任务"} //{"0":"立即任务","1":"定时任务","2":"条件任务"}
//立即任务和定时任务均由execute_time指定执行时间 //立即任务和定时任务均由execute_time指定执行时间
// 条件任务支持ready_conditions字段指定任务就绪条件 // 条件任务支持ready_conditions字段指定任务就绪条件
// 备可在指定时间段内满足就绪条件后即可执行 // 备可在指定时间段内满足就绪条件后即可执行
// 立即任务媒体上传优先级最高定时任务和条件任务媒体上传优先级相同 // 立即任务媒体上传优先级最高定时任务和条件任务媒体上传优先级相同
private Integer task_type; private int task_type;
//航线文件对象 //航线文件对象
private FileInfo file; private FileInfo file;
//任务就绪条件 //任务就绪条件
@ -50,30 +50,30 @@ public class FlightTaskPrepare {
private BreakPoint break_point; private BreakPoint break_point;
//返航高度 //返航高度
//{"max":1500,"min":20,"step":"","unit_name":"米 / m"} //{"max":1500,"min":20,"step":"","unit_name":"米 / m"}
private Integer rth_altitude; private int rth_altitude;
//返航高度模式 //返航高度模式
//{"0":"智能高度","1":"设定高度"} //{"0":"智能高度","1":"设定高度"}
/// 智能返航模式下飞行器将自动规划最佳返航高度 /// 智能返航模式下飞行器将自动规划最佳返航高度
/// 大疆机场当前不支持设置返航高度模式只能选择'设定高度'模式 /// 大疆机场当前不支持设置返航高度模式只能选择'设定高度'模式
/// 当环境光线不满足视觉系统要求时譬如傍晚阳光直射夜间弱光无光 /// 当环境光线不满足视觉系统要求时譬如傍晚阳光直射夜间弱光无光
/// 飞行器将使用您设定的返航高度进行直线返航 /// 飞行器将使用您设定的返航高度进行直线返航
private Integer rth_mode; private int rth_mode;
//遥控器失控动作 //遥控器失控动作
//{"0":"返航","1":"悬停","2":"降落"} //{"0":"返航","1":"悬停","2":"降落"}
//失控动作当前固定传的值是 0即返航 //失控动作当前固定传的值是 0即返航
// 注意该枚举值定义跟飞控跟机场定义的不一致机场端会进行转换 // 注意该枚举值定义跟飞控跟机场定义的不一致机场端会进行转换
private Integer out_of_control_action; private int out_of_control_action;
//航线失控动作 //航线失控动作
//{"0":"继续执行航线任务","1":"退出航线任务,执行遥控器失控动作"} //{"0":"继续执行航线任务","1":"退出航线任务,执行遥控器失控动作"}
//保持跟 KMZ 文件一致 //保持跟 KMZ 文件一致
private Integer exit_wayline_when_rc_lost; private int exit_wayline_when_rc_lost;
//航线精度类型 //航线精度类型
//{"0":"GPS 任务","1":"高精度 RTK 任务"} //{"0":"GPS 任务","1":"高精度 RTK 任务"}
//高精度 RTK 任务飞行器起飞后会在空中等待 RTK 收敛后再执行任务等待 RTK 收敛的过程中无法暂停任务 //高精度 RTK 任务飞行器起飞后会在空中等待 RTK 收敛后再执行任务等待 RTK 收敛的过程中无法暂停任务
// 默认场景建议使用该模式 // 默认场景建议使用该模式
// GPS 任务飞行器无需等待 RTK 收敛便可以直接开始执行 // GPS 任务飞行器无需等待 RTK 收敛便可以直接开始执行
// 精度要求不高的任务或对起飞时效性要求较高的任务建议使用该模式 // 精度要求不高的任务或对起飞时效性要求较高的任务建议使用该模式
private Integer wayline_precision_type; private int wayline_precision_type;
//是否在模拟器中执行任务 //是否在模拟器中执行任务
//可选字段用于在室内进行模拟任务调试 //可选字段用于在室内进行模拟任务调试
//注意进行模拟飞行前请务必取下桨叶以防舱盖关闭时夹断桨叶 //注意进行模拟飞行前请务必取下桨叶以防舱盖关闭时夹断桨叶
@ -84,7 +84,7 @@ public class FlightTaskPrepare {
// 值为0表示关闭1表示开启 // 值为0表示关闭1表示开启
// 飞行安全预先检查表示: 飞行器执行任务前检查自身作业区文件是否与云端一致 // 飞行安全预先检查表示: 飞行器执行任务前检查自身作业区文件是否与云端一致
// 如果不一致则拉取文件更新如果一致则不处理 // 如果不一致则拉取文件更新如果一致则不处理
private Integer flight_safety_advance_check; private int flight_safety_advance_check;
@Data @Data
@NoArgsConstructor @NoArgsConstructor
@ -92,18 +92,18 @@ public class FlightTaskPrepare {
public static class BreakPoint { public static class BreakPoint {
//断点序号 //断点序号
@Schema(description = "断点序号") @Schema(description = "断点序号")
private Integer index; private int index;
//断点状态 //断点状态
//{"0":"在航段上","1":"在航点上"} //{"0":"在航段上","1":"在航点上"}
@Schema(description = "断点状态 {0:在航段上,1:在航点上}") @Schema(description = "断点状态 {\"0\":\"在航段上\",\"1\":\"在航点上\"}")
private Integer state; private int state;
//当前航段进度 //当前航段进度
//{"max":"1.0","min":"0"} //{"max":"1.0","min":"0"}
@Schema(description = "当前航段进度 {max:1.0,min:0}") @Schema(description = "当前航段进度 {\"max\":\"1.0\",\"min\":\"0\"}")
private Double progress; private double progress;
//航线 ID //航线 ID
@Schema(description = "wayline_id 航线 ID") @Schema(description = "航线 ID")
private Integer wayline_id; private int wayline_id;
} }
@Data @Data
@ -112,7 +112,7 @@ public class FlightTaskPrepare {
public static class ExecutableConditions { public static class ExecutableConditions {
//存储容量 //存储容量
//可执行任务的机场或飞行器最低存储容量机场或飞行器存储容量不满足 storage_capacity 任务执行失败 //可执行任务的机场或飞行器最低存储容量机场或飞行器存储容量不满足 storage_capacity 任务执行失败
private Integer storage_capacity; private int storage_capacity;
} }
@Data @Data
@ -132,13 +132,13 @@ public class FlightTaskPrepare {
public static class ReadyConditions { public static class ReadyConditions {
//电池容量 //电池容量
//可执行任务的飞行器电池电量百分比阈值任务开始执行时的飞行器电量必须大于 battery_capacity //可执行任务的飞行器电池电量百分比阈值任务开始执行时的飞行器电量必须大于 battery_capacity
private Integer battery_capacity; private int battery_capacity;
//任务可执行时段的开始时间 //任务可执行时段的开始时间
//任务可执行时段起始时间毫秒时间戳任务开始执行的时间必须大于 begin_time //任务可执行时段起始时间毫秒时间戳任务开始执行的时间必须大于 begin_time
private Long begin_time; private long begin_time;
//任务可执行时段的结束时间 //任务可执行时段的结束时间
//任务可执行时段截止时间毫秒时间戳任务开始执行的时间必须小于 end_time //任务可执行时段截止时间毫秒时间戳任务开始执行的时间必须小于 end_time
private Long end_time; private long end_time;
} }
@Data @Data
@ -148,19 +148,19 @@ public class FlightTaskPrepare {
//是否开启模拟器任务 //是否开启模拟器任务
//{"0":"不开启","1":"开启"} //{"0":"不开启","1":"开启"}
//当次任务打开或关闭模拟器 //当次任务打开或关闭模拟器
@Schema(description = "is_enable 是否开启模拟器任务 {0:不开启,1:开启}") @Schema(description = "是否开启模拟器任务 {\"0\":\"不开启\",\"1\":\"开启\"}")
private Integer is_enable; private int is_enable;
//纬度 //纬度
//{"max":"90.0","min":"-90.0"} //{"max":"90.0","min":"-90.0"}
@Schema(description = "机场纬度 {max:90.0,min:-90.0}") @Schema(description = "机场纬度 {\"max\":\"90.0\",\"min\":\"-90.0\"}")
private Double latitude; private double latitude;
//经度 //经度
//{"max":"180.0","min":"-180.0"} //{"max":"180.0","min":"-180.0"}
@Schema(description = "机场经度 {max:180.0,min:-180.0}") @Schema(description = "机场经度 {\"max\":\"180.0\",\"min\":\"-180.0\"}")
private Double longitude; private double longitude;
//高度 //高度
//{"max":"9999.9","min":"-9999.9"unit_name":" / m"} //{"max":"9999.9","min":"-9999.9"unit_name":" / m"}
@Schema(description = "机场海拔高度{max:9999.9,min:-9999.9unit_name:米/m}") @Schema(description = "机场海拔高度{\"max\":\"9999.9\",\"min\":\"-9999.9\"unit_name\":\" / m\"}")
private Double altitude; private double altitude;
} }
} }

View File

@ -0,0 +1,53 @@
package com.multictrl.modules.business.dto.multi;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* @author 张闯
* @since 2026-05-28
*/
@Schema(name = "蛙跳组绑定设备列表")
@Data
public class MultiDockDTO {
@Schema(description = "主键")
private Long id;
@JsonProperty(required = true)
@Schema(description = "机库名称")
private String dockName;
@JsonProperty(required = true)
@Schema(description = "SN码")
private String dockSn;
@JsonProperty(required = true)
@Schema(description = "机库类型")
private String dockType;
@JsonProperty(required = true)
@Schema(description = "机库型号")
private String dockModel;
@Schema(description = "使用场景")
private String scenario;
@JsonProperty(required = true)
@Schema(description = "所属部门")
private Long deptId;
@JsonProperty(required = true)
@Schema(description = "机场经度")
private double longitude;
@JsonProperty(required = true)
@Schema(description = "机场纬度")
private double latitude;
@JsonProperty(required = true)
@Schema(description = "机场椭球高度")
private double height;
}

View File

@ -0,0 +1,36 @@
package com.multictrl.modules.business.dto.multi;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.multictrl.common.validator.group.AddGroup;
import com.multictrl.common.validator.group.UpdateGroup;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Null;
import lombok.Data;
/**
* @author 张闯
* @since 2026-05-28
*/
@Data
@Schema(name = "蛙跳组信息")
public class MultiGroupDTO {
/**
* 蛙跳组名称
*/
@NotBlank(message = "{group.name.require}", groups = {AddGroup.class, UpdateGroup.class})
@JsonProperty(required = true)
@Schema(description = "蛙跳组名称")
private String groupName;
/**
* 蛙跳组备注说明
*/
@NotBlank(message = "{group.mark.require}", groups = {AddGroup.class, UpdateGroup.class})
@JsonProperty(required = true)
@Schema(description = "蛙跳组备注说明")
private String groupMark;
}

View File

@ -0,0 +1,34 @@
package com.multictrl.modules.business.dto.multi;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.multictrl.common.validator.group.AddGroup;
import com.multictrl.common.validator.group.UpdateGroup;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import java.util.List;
import lombok.Data;
/**
* @author 张闯
* @since 2026-05-28
*/
@Data
@Schema(name = "蛙跳组绑定设备列表")
public class MultiGroupDeviceDTO {
/**
* 蛙跳组id
*/
@NotBlank(message = "{group.id.require}", groups = {AddGroup.class, UpdateGroup.class})
@JsonProperty(required = true)
@Schema(description = "蛙跳组id")
private Long groudId;
/**
* 网关sn
*/
@NotBlank(message = "{gateway.sns.require}", groups = {AddGroup.class, UpdateGroup.class})
@JsonProperty(required = true)
@Schema(description = "设备网关sn列表")
private List<String> gatewaySns;
}

View File

@ -0,0 +1,25 @@
package com.multictrl.modules.business.dto.multi;
import io.swagger.v3.oas.annotations.media.Schema;
import java.util.List;
import lombok.Data;
/**
* @author 张闯
* @since 2026-05-31
*/
@Data
@Schema(name = "蛙跳任务类")
public class MultiTaskDTO {
List<MultiDockDTO> docks;
MultiDockDTO miaoSuan;
MultiDockDTO miaoSuanLocatedDock;
String taskId;
Long routeId;
}

View File

@ -0,0 +1,29 @@
package com.multictrl.modules.business.dto.multi;
import lombok.Data;
/**
* aros 机场蛙跳参数
* @author 张闯
* @since 2026-05-31
*/
@Data
public class PrivateMultiFlightBindDockInfo {
private String dock_sn;
private double longitude;
private double latitude;
private double height;
private double alternate_land_point_longitude;
private double alternate_land_point_latitude;
private double alternate_land_point_height;
private double alternate_land_point_safe_land_height;
}

View File

@ -31,8 +31,19 @@ public class DockEntity extends BaseEntity {
private String dockSn; private String dockSn;
/** /**
* 机库类型 * 机库类型
*
* dock
* pilot
* miao_suan
*/ */
private String dockType; private String dockType;
/**
* 使用场景
* null或者 inspection 巡检
* multi 蛙跳
*/
private String scenario;
/** /**
* 机库型号 * 机库型号
*/ */

View File

@ -0,0 +1,33 @@
package com.multictrl.modules.business.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import com.multictrl.common.entity.BaseEntity;
import java.util.Date;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* @author 张闯
* @since 2026-05-28
*/
@EqualsAndHashCode(callSuper = true)
@Data
@TableName("bus_multi_group_device")
public class MultiGroupDeviceEntity extends BaseEntity {
/**
* 蛙跳组id
*/
private Long groudId;
/**
* 网关sn
*/
private String gatewaySn;
/**
* 更新者
*/
private Long updater;
/**
* 更新时间
*/
private Date updateDate;
}

View File

@ -0,0 +1,33 @@
package com.multictrl.modules.business.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import com.multictrl.common.entity.BaseEntity;
import java.util.Date;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* @author 张闯
* @since 2026-05-28
*/
@EqualsAndHashCode(callSuper = true)
@Data
@TableName("bus_multi_group")
public class MultiGroupEntity extends BaseEntity {
/**
* 蛙跳组名称
*/
private String groupName;
/**
* 蛙跳组标识
*/
private String groupMark;
/**
* 组织编号
*/
private Long deptId;
private Long updater;
private Date updateDate;
}

View File

@ -58,13 +58,14 @@ public class OsdHandler implements MessageHandler {
CacheUtils.set(BusinessConstant.DOCK_IN_WORK + dockSn, true); CacheUtils.set(BusinessConstant.DOCK_IN_WORK + dockSn, true);
} }
//刚从任务中切到空闲说明架次结束入库了 //刚从任务中切到空闲说明架次结束入库了
if (modeCode == DockMode.IDLE.getCode() && CacheUtils.get(BusinessConstant.DOCK_IN_WORK + dockSn) != null) { if (modeCode == DockMode.IDLE.getCode()
&& CacheUtils.get(BusinessConstant.DOCK_IN_WORK + dockSn) != null) {
CacheUtils.delete(BusinessConstant.DOCK_IN_WORK + dockSn); CacheUtils.delete(BusinessConstant.DOCK_IN_WORK + dockSn);
log.debug("{}机库架次飞行完成取消DRC心跳", dockSn); log.debug("{}机库架次飞行完成取消DRC心跳", dockSn);
List<String> list = Optional.ofNullable(CacheUtils.get(BusinessConstant.DRC_HEART_BEAT_SN)) List<String> list = Optional.ofNullable(CacheUtils.get(BusinessConstant.DRC_HEART_BEAT_SN))
.filter(obj -> obj instanceof List) .filter(obj -> obj instanceof List)
.map(obj -> (List<String>) obj) .map(obj -> (List<String>) obj)
.orElse(Collections.emptyList()); .orElse(Collections.emptyList());
if (CollUtil.isNotEmpty(list)) { if (CollUtil.isNotEmpty(list)) {
list.remove(dockSn); list.remove(dockSn);
} }
@ -85,9 +86,10 @@ public class OsdHandler implements MessageHandler {
//保存osd到influxdb //保存osd到influxdb
String latitude = data.getStr("latitude"); String latitude = data.getStr("latitude");
String longitude = data.getStr("longitude"); String longitude = data.getStr("longitude");
if (latitude != null && longitude != null && !GPS_ZERO.equals(latitude) && !GPS_ZERO.equals(longitude)) { if (latitude != null && longitude != null && !GPS_ZERO.equals(latitude) && !GPS_ZERO.equals(
longitude)) {
String payload_index = data.getJSONArray("cameras") != null ? String payload_index = data.getJSONArray("cameras") != null ?
data.getJSONArray("cameras").getJSONObject(0).getStr("payload_index") : null; data.getJSONArray("cameras").getJSONObject(0).getStr("payload_index") : null;
//获取电池电量如果单电池则把 a赋值给b //获取电池电量如果单电池则把 a赋值给b
int capacity_percent_a; int capacity_percent_a;
int capacity_percent_b; int capacity_percent_b;
@ -100,44 +102,48 @@ public class OsdHandler implements MessageHandler {
} }
UavReport uavReport = UavReport.builder() UavReport uavReport = UavReport.builder()
.dockSn(dockSn) .dockSn(dockSn)
.obstacle_avoidance_horizon(data.getJSONObject("obstacle_avoidance").getInt("horizon")) .obstacle_avoidance_horizon(data.getJSONObject("obstacle_avoidance").getInt("horizon"))
.obstacle_avoidance_upside(data.getJSONObject("obstacle_avoidance").getInt("upside")) .obstacle_avoidance_upside(data.getJSONObject("obstacle_avoidance").getInt("upside"))
.obstacle_avoidance_downside(data.getJSONObject("obstacle_avoidance").getInt("downside")) .obstacle_avoidance_downside(data.getJSONObject("obstacle_avoidance").getInt("downside"))
.is_near_area_limit(data.getInt("is_near_area_limit")) .is_near_area_limit(data.getInt("is_near_area_limit"))
.is_near_height_limit(data.getInt("is_near_height_limit")) .is_near_height_limit(data.getInt("is_near_height_limit"))
.payload_index(payload_index) .payload_index(payload_index)
.gimbal_pitch(payload_index != null ? data.getJSONObject(payload_index).getDouble("gimbal_pitch") : null) .gimbal_pitch(
.gimbal_roll(payload_index != null ? data.getJSONObject(payload_index).getDouble("gimbal_roll") : null) payload_index != null ? data.getJSONObject(payload_index).getDouble("gimbal_pitch") : null)
.gimbal_yaw(payload_index != null ? data.getJSONObject(payload_index).getDouble("gimbal_yaw") : null) .gimbal_roll(
.zoom_factor(payload_index != null ? data.getJSONObject(payload_index).getDouble("zoom_factor") : null) payload_index != null ? data.getJSONObject(payload_index).getDouble("gimbal_roll") : null)
.track_id(data.getStr("track_id")) .gimbal_yaw(
.position_state_is_fixed(data.getJSONObject("position_state").getInt("is_fixed")) payload_index != null ? data.getJSONObject(payload_index).getDouble("gimbal_yaw") : null)
.position_state_is_quality(data.getJSONObject("position_state").getInt("quality")) .zoom_factor(
.position_state_is_gps_number(data.getJSONObject("position_state").getInt("gps_number")) payload_index != null ? data.getJSONObject(payload_index).getDouble("zoom_factor") : null)
.position_state_is_rtk_number(data.getJSONObject("position_state").getInt("rtk_number")) .track_id(data.getStr("track_id"))
.battery_capacity_percent(data.getJSONObject("battery").getInt("capacity_percent")) .position_state_is_fixed(data.getJSONObject("position_state").getInt("is_fixed"))
.battery_remain_flight_time(data.getJSONObject("battery").getInt("remain_flight_time")) .position_state_is_quality(data.getJSONObject("position_state").getInt("quality"))
.battery_return_home_power(data.getJSONObject("battery").getInt("return_home_power")) .position_state_is_gps_number(data.getJSONObject("position_state").getInt("gps_number"))
.battery_landing_power(data.getJSONObject("battery").getInt("landing_power")) .position_state_is_rtk_number(data.getJSONObject("position_state").getInt("rtk_number"))
.battery_capacity_percent_a(capacity_percent_a) .battery_capacity_percent(data.getJSONObject("battery").getInt("capacity_percent"))
.battery_capacity_percent_b(capacity_percent_b) .battery_remain_flight_time(data.getJSONObject("battery").getInt("remain_flight_time"))
.wind_direction(data.getInt("wind_direction")) .battery_return_home_power(data.getJSONObject("battery").getInt("return_home_power"))
.wind_speed(data.getDouble("wind_speed")) .battery_landing_power(data.getJSONObject("battery").getInt("landing_power"))
.home_distance(data.getDouble("home_distance")) .battery_capacity_percent_a(capacity_percent_a)
//state上报 .battery_capacity_percent_b(capacity_percent_b)
.wind_direction(data.getInt("wind_direction"))
.wind_speed(data.getDouble("wind_speed"))
.home_distance(data.getDouble("home_distance"))
//state上报
// .home_latitude(data.getDouble("home_latitude")) // .home_latitude(data.getDouble("home_latitude"))
// .home_longitude(data.getDouble("home_longitude")) // .home_longitude(data.getDouble("home_longitude"))
.attitude_head(data.getInt("attitude_head")) .attitude_head(data.getInt("attitude_head"))
.attitude_roll(data.getDouble("attitude_roll")) .attitude_roll(data.getDouble("attitude_roll"))
.attitude_pitch(data.getDouble("attitude_pitch")) .attitude_pitch(data.getDouble("attitude_pitch"))
.elevation(data.getDouble("elevation")) .elevation(data.getDouble("elevation"))
.height(data.getDouble("height")) .height(data.getDouble("height"))
.latitude(data.getDouble("latitude")) .latitude(data.getDouble("latitude"))
.longitude(data.getDouble("longitude")) .longitude(data.getDouble("longitude"))
.vertical_speed(data.getDouble("vertical_speed")) .vertical_speed(data.getDouble("vertical_speed"))
.horizontal_speed(data.getDouble("horizontal_speed")) .horizontal_speed(data.getDouble("horizontal_speed"))
.build(); .build();
influxService.addRecord(uavReport); influxService.addRecord(uavReport);
} }
} }

View File

@ -36,6 +36,7 @@ import java.util.List;
@Component @Component
@RequiredArgsConstructor @RequiredArgsConstructor
public class RequestsHandler implements MessageHandler { public class RequestsHandler implements MessageHandler {
private final DJIConfig djiConfig; private final DJIConfig djiConfig;
private final MqttPushService mqttPushService; private final MqttPushService mqttPushService;
private final DockDeviceDao dockDeviceDao; private final DockDeviceDao dockDeviceDao;
@ -74,7 +75,8 @@ public class RequestsHandler implements MessageHandler {
return; return;
} }
String sn = deviceJson.getStr("sn"); String sn = deviceJson.getStr("sn");
DockDeviceEntity dockDevice = dockDeviceDao.selectOne(new QueryWrapper<DockDeviceEntity>().eq("sn", sn)); DockDeviceEntity dockDevice = dockDeviceDao.selectOne(
new QueryWrapper<DockDeviceEntity>().eq("sn", sn));
if (dockDevice == null) { if (dockDevice == null) {
data.set("result", 1); data.set("result", 1);
mqttPushService.pushMessageByClient1(topic + BusinessConstant._REPLY, message.toString()); mqttPushService.pushMessageByClient1(topic + BusinessConstant._REPLY, message.toString());
@ -100,7 +102,8 @@ public class RequestsHandler implements MessageHandler {
} else if (BusinessConstant.AIRPORT_ORGANIZATION_GET.equals(method)) {//第三步 查询设备绑定对应的组织信息 } else if (BusinessConstant.AIRPORT_ORGANIZATION_GET.equals(method)) {//第三步 查询设备绑定对应的组织信息
String deviceBindingCode = data.getStr("device_binding_code"); String deviceBindingCode = data.getStr("device_binding_code");
String organizationId = data.getStr("organization_id"); String organizationId = data.getStr("organization_id");
if (!djiConfig.getDeviceBindCode().equals(deviceBindingCode) || !djiConfig.getOrganizationId().equals(organizationId)) { if (!djiConfig.getDeviceBindCode().equals(deviceBindingCode) || !djiConfig.getOrganizationId()
.equals(organizationId)) {
data.set("result", 2); data.set("result", 2);
mqttPushService.pushMessageByClient1(topic + BusinessConstant._REPLY, message.toString()); mqttPushService.pushMessageByClient1(topic + BusinessConstant._REPLY, message.toString());
log.debug("requests step3--> 查询设备绑定对应的组织信息失败设备绑定码或组织id不匹配"); log.debug("requests step3--> 查询设备绑定对应的组织信息失败设备绑定码或组织id不匹配");
@ -143,9 +146,9 @@ public class RequestsHandler implements MessageHandler {
device.setDeviceType(Integer.parseInt(split[1])); device.setDeviceType(Integer.parseInt(split[1]));
device.setSubType(Integer.parseInt(split[2])); device.setSubType(Integer.parseInt(split[2]));
DeviceDicEntity deviceDicEntity = deviceDicDao.selectOne(new QueryWrapper<DeviceDicEntity>() DeviceDicEntity deviceDicEntity = deviceDicDao.selectOne(new QueryWrapper<DeviceDicEntity>()
.eq("domain", device.getDomain()) .eq("domain", device.getDomain())
.eq("device_type", device.getDeviceType()) .eq("device_type", device.getDeviceType())
.eq("sub_type", device.getSubType())); .eq("sub_type", device.getSubType()));
device.setDeviceName(deviceDicEntity != null ? deviceDicEntity.getDeviceName() : "unknown"); device.setDeviceName(deviceDicEntity != null ? deviceDicEntity.getDeviceName() : "unknown");
bindDeviceList.add(device); bindDeviceList.add(device);
} }
@ -156,7 +159,7 @@ public class RequestsHandler implements MessageHandler {
return; return;
} }
dockDeviceDao.delete(new QueryWrapper<DockDeviceEntity>().eq("sn", gateway).or() dockDeviceDao.delete(new QueryWrapper<DockDeviceEntity>().eq("sn", gateway).or()
.eq("parent_sn", gateway)); .eq("parent_sn", gateway));
dockDeviceDao.insert(bindDeviceList); dockDeviceDao.insert(bindDeviceList);
data.set("result", 0); data.set("result", 0);
mqttPushService.pushMessageByClient1(topic + BusinessConstant._REPLY, message.toString()); mqttPushService.pushMessageByClient1(topic + BusinessConstant._REPLY, message.toString());
@ -208,6 +211,19 @@ public class RequestsHandler implements MessageHandler {
message.remove("gateway"); message.remove("gateway");
mqttPushService.pushMessageByClient1(topic + BusinessConstant._REPLY, message.toString()); mqttPushService.pushMessageByClient1(topic + BusinessConstant._REPLY, message.toString());
log.debug("requests storage_config_get--> 存储配置获取成功"); log.debug("requests storage_config_get--> 存储配置获取成功");
} else if (BusinessConstant.PRIVATE_GET_MULTI_MIAOSUAN_PSDK_STATUS.equals(method)) {
String psdkSn = message.getStr("psdk_sn");
int status = CacheUtils.get(BusinessConstant.DOCK_OSD + psdkSn) != null ? 1 : 0;
data.clear();
data.set("result", 0);
JSONObject output = new JSONObject();
output.set("status", status);
data.set("output", output);
message.set("timestamp", System.currentTimeMillis());
message.remove("need_reply");
mqttPushService.pushMessageByClient1(topic + BusinessConstant._REPLY, message.toString());
log.debug("requests private_get_multi_miaosuan_psdk_status--> 检查妙算设备是否上线:{}-> status: {}",
psdkSn, status);
} }
} else { } else {
log.debug("requests --> payload解析失败解析后为null"); log.debug("requests --> payload解析失败解析后为null");

View File

@ -15,6 +15,7 @@ import org.springframework.stereotype.Component;
@Slf4j @Slf4j
@Component @Component
public class MqttPushService { public class MqttPushService {
@Resource(name = "mqttOutboundChannel1") @Resource(name = "mqttOutboundChannel1")
private MessageChannel mqttOutboundHandler1; private MessageChannel mqttOutboundHandler1;
@ -22,7 +23,7 @@ public class MqttPushService {
private MessageChannel mqttOutboundHandler2; private MessageChannel mqttOutboundHandler2;
/** /**
* 客户端1推送消息 * 客户端1推送消息 该连接处理正常的协议交互
* *
* @param topic 主题 * @param topic 主题
* @param msg 消息 * @param msg 消息
@ -30,11 +31,11 @@ public class MqttPushService {
public void pushMessageByClient1(String topic, String msg) { public void pushMessageByClient1(String topic, String msg) {
log.debug("client1 down-> topic:{},msg:{}", topic, msg); log.debug("client1 down-> topic:{},msg:{}", topic, msg);
mqttOutboundHandler1.send(MessageBuilder.withPayload(msg). mqttOutboundHandler1.send(MessageBuilder.withPayload(msg).
setHeader("mqtt_topic", topic).build()); setHeader("mqtt_topic", topic).build());
} }
/** /**
* 客户端2推送消息 * 客户端2推送消息 该连接处理drc控制的协议交互
* *
* @param topic 主题 * @param topic 主题
* @param msg 消息 * @param msg 消息
@ -42,6 +43,6 @@ public class MqttPushService {
public void pushMessageByClient2(String topic, String msg) { public void pushMessageByClient2(String topic, String msg) {
log.debug("client2 down-> topic:{},msg:{}", topic, msg); log.debug("client2 down-> topic:{},msg:{}", topic, msg);
mqttOutboundHandler2.send(MessageBuilder.withPayload(msg). mqttOutboundHandler2.send(MessageBuilder.withPayload(msg).
setHeader("mqtt_topic", topic).build()); setHeader("mqtt_topic", topic).build());
} }
} }

View File

@ -0,0 +1,35 @@
package com.multictrl.modules.business.service;
import com.multictrl.common.utils.Result;
import com.multictrl.modules.business.dto.multi.MultiDockDTO;
import com.multictrl.modules.business.dto.multi.MultiGroupDTO;
import com.multictrl.modules.business.dto.multi.MultiGroupDeviceDTO;
import com.multictrl.modules.business.dto.multi.MultiTaskDTO;
import com.multictrl.modules.business.entity.DockEntity;
import java.util.List;
/**
* 阿罗斯机场 蛙跳 充电机库 Ars550 换电机库 Ars600
*
* @author 张闯
* @since 2026-05-28
*/
public interface MultiService {
List<MultiDockDTO> getDockList();
void saveMultiGroup(MultiGroupDTO multiGroupDTO);
void saveMultiGroupDevice(MultiGroupDeviceDTO multiGroupDeviceDTO);
void updateMultiGroup(MultiGroupDTO multiGroupDTO);
void updateMultiGroupDevice(MultiGroupDeviceDTO multiGroupDeviceDTO);
String privateMultiDockTaskFlightTaskCheck(MultiTaskDTO multiTaskDTO);
String privateMultiDockFlightTaskOutbound(MultiTaskDTO multiTaskDTO);
String privateMultiDockFlightTaskInbound(MultiTaskDTO multiTaskDTO);
}

View File

@ -2,6 +2,7 @@ package com.multictrl.modules.business.service;
import com.multictrl.modules.business.dto.flight.FlightExecute; import com.multictrl.modules.business.dto.flight.FlightExecute;
import com.multictrl.modules.business.dto.multi.PrivateMultiFlightBindDockInfo;
import java.util.List; import java.util.List;
/** /**

View File

@ -138,6 +138,7 @@ public class DJIBaseServiceImpl implements DJIBaseService {
return message; return message;
} }
@Override @Override
public String executeAndReturnResult(String dockSn, String method) { public String executeAndReturnResult(String dockSn, String method) {

View File

@ -0,0 +1,231 @@
package com.multictrl.modules.business.service.impl;
import cn.hutool.json.JSONObject;
import com.multictrl.common.constant.BusinessConstant;
import com.multictrl.common.exception.ErrorCode;
import com.multictrl.common.exception.RenException;
import com.multictrl.common.utils.CacheUtils;
import com.multictrl.common.utils.MessageUtils;
import com.multictrl.modules.business.dao.MultiGroupDao;
import com.multictrl.modules.business.dao.MultiGroupDeviceDao;
import com.multictrl.modules.business.dto.flight.FlightExecute;
import com.multictrl.modules.business.dto.multi.MultiDockDTO;
import com.multictrl.modules.business.dto.multi.MultiGroupDTO;
import com.multictrl.modules.business.dto.multi.MultiGroupDeviceDTO;
import com.multictrl.modules.business.dto.multi.MultiTaskDTO;
import com.multictrl.modules.business.dto.multi.PrivateMultiFlightBindDockInfo;
import com.multictrl.modules.business.service.DJIBaseService;
import com.multictrl.modules.business.service.MultiService;
import com.multictrl.modules.business.service.RouteFlightService;
import jakarta.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
/**
* 阿罗斯机场 蛙跳
*
* @author 张闯
* @since 2026-05-28
*/
@Slf4j
@Service
public class MultiServiceImpl implements MultiService {
@Resource
MultiGroupDao multiGroupDao;
@Resource
MultiGroupDeviceDao multiGroupDeviceDao;
@Resource
DJIBaseService djiBaseService;
@Resource
RouteFlightService routeFlightService;
private static final String MIAO_SUAN = "miao_suan";
@Override
public List<MultiDockDTO> getDockList() {
return List.of();
}
@Override
public void saveMultiGroup(MultiGroupDTO multiGroupDTO) {
}
@Override
public void saveMultiGroupDevice(MultiGroupDeviceDTO multiGroupDeviceDTO) {
}
@Override
public void updateMultiGroup(MultiGroupDTO multiGroupDTO) {
}
@Override
public void updateMultiGroupDevice(MultiGroupDeviceDTO multiGroupDeviceDTO) {
}
@Override
public String privateMultiDockTaskFlightTaskCheck(MultiTaskDTO multiTaskDTO) {
for (MultiDockDTO multiDockDTO : multiTaskDTO.getDocks()) {
if (multiDockDTO.getDockType().equals(MIAO_SUAN)) {
continue;
}
String result = privateMultiDockTaskFlightTaskCheck(multiDockDTO.getDockSn());
log.info("privateMultiDockTaskFlightTaskCheck-> dockSn:{},result:{}", multiDockDTO.getDockSn(), result);
}
return MessageUtils.getMessage(ErrorCode.DOCK_EXEC_SUCCESS);
}
@Override
public String privateMultiDockFlightTaskOutbound(MultiTaskDTO multiTaskDTO) {
//第一步调用所有机场出库
for (MultiDockDTO multiDockDTO : multiTaskDTO.getDocks()) {
if (multiDockDTO.getDockType().equals(MIAO_SUAN)) {
continue;
}
boolean need_drone_open = multiDockDTO.getDockSn()
.equals(multiTaskDTO.getMiaoSuanLocatedDock().getDockSn());
String result = privateMultiDockFlightTaskOutbound(multiDockDTO.getDockSn(),
need_drone_open, multiTaskDTO.getMiaoSuan().getDockSn(), multiTaskDTO.getTaskId());
log.info("privateMultiDockFlightTaskOutbound-> 调用所有机场出库 dockSn:{},result:{}",
multiDockDTO.getDockSn(),
result);
}
//第二步检查机库各传感器状态是否已经出库完成,180秒内
int tryCount = 180;
while (tryCount-- > 0) {
boolean allFinished = true;
for (MultiDockDTO multiDockDTO : multiTaskDTO.getDocks()) {
if (multiDockDTO.getDockType().equals(MIAO_SUAN)) {
continue;
}
Object o;
if ((o = CacheUtils.get(BusinessConstant.DOCK_OSD + multiDockDTO.getDockSn())) == null) {
continue;
}
JSONObject jsonObject = (JSONObject) o;
//cover_state 舱盖状态 {"0":"关闭","1":"打开","2":"半开","3":"舱盖状态异常"}
int cover_state = jsonObject.getInt("cover_state");
//putter_state 推杆状态 {"0":"关闭","1":"打开","2":"半开","3":"推杆状态异常"}
int putter_state = jsonObject.getInt("putter_state");
log.info(
"privateMultiDockFlightTaskOutbound-> 检查机库各传感器状态,是否已经出库完成 dockSn:{},cover_state:{},putter_state:{}"
, multiDockDTO.getDockSn(), cover_state, putter_state);
allFinished = allFinished && cover_state == 1 && putter_state == 1;
}
if (allFinished) {
break;
}
}
if (tryCount <= 0) {
return "出库超时";
}
//第三步下发航线给psdk
FlightExecute flightExecute = new FlightExecute();
flightExecute.setTaskId(multiTaskDTO.getTaskId());
flightExecute.setRouteId(multiTaskDTO.getRouteId());
//获取每个机库的 经纬度/高度/备降点经纬度/备降点高度
List<PrivateMultiFlightBindDockInfo> privateMultiFlightBindDockInfos = new ArrayList<>();
for (MultiDockDTO multiDockDTO : multiTaskDTO.getDocks()) {
if (multiDockDTO.getDockType().equals(MIAO_SUAN)) {
continue;
}
Object o;
if ((o = CacheUtils.get(BusinessConstant.DOCK_OSD + multiDockDTO.getDockSn())) == null) {
throw new RenException("机库: " + multiDockDTO.getDockSn() + "信息获取失败");
}
JSONObject jsonObject = (JSONObject) o;
PrivateMultiFlightBindDockInfo privateMultiFlightBindDockInfo = new PrivateMultiFlightBindDockInfo();
privateMultiFlightBindDockInfo.setDock_sn(multiDockDTO.getDockSn());
privateMultiFlightBindDockInfo.setLongitude(jsonObject.getDouble("longitude"));
privateMultiFlightBindDockInfo.setLatitude(jsonObject.getDouble("latitude"));
privateMultiFlightBindDockInfo.setHeight(jsonObject.getDouble("height"));
JSONObject alternate_land_point = jsonObject.getJSONObject("alternate_land_point");
privateMultiFlightBindDockInfo.setAlternate_land_point_longitude(
alternate_land_point.getDouble("longitude"));
privateMultiFlightBindDockInfo.setAlternate_land_point_latitude(alternate_land_point.getDouble("latitude"));
privateMultiFlightBindDockInfo.setAlternate_land_point_height(alternate_land_point.getDouble("height"));
privateMultiFlightBindDockInfo.setAlternate_land_point_safe_land_height(
alternate_land_point.getDouble("safe_land_height"));
privateMultiFlightBindDockInfos.add(privateMultiFlightBindDockInfo);
}
flightExecute.setPrivateMultiFlightBindDockInfos(privateMultiFlightBindDockInfos);
log.info("privateMultiDockFlightTaskOutbound-> 下发航线给妙算 flightExecute:{}", flightExecute);
return routeFlightService.flightExecute(multiTaskDTO.getMiaoSuan().getDockSn(), flightExecute);
}
@Override
public String privateMultiDockFlightTaskInbound(MultiTaskDTO multiTaskDTO) {
//第一步调用所有机场入库
for (MultiDockDTO multiDockDTO : multiTaskDTO.getDocks()) {
if (multiDockDTO.getDockType().equals(MIAO_SUAN)) {
continue;
}
boolean need_drone_close = multiDockDTO.getDockSn()
.equals(multiTaskDTO.getMiaoSuanLocatedDock().getDockSn());
String result = privateMultiDockFlightTaskInbound(multiDockDTO.getDockSn(),
need_drone_close, multiTaskDTO.getMiaoSuan().getDockSn(), multiTaskDTO.getTaskId());
log.info("privateMultiDockFlightTaskInbound-> dockSn:{},result:{}", multiDockDTO.getDockSn(),
result);
}
//第二步判断所有机场的门都关闭了
int tryCount = 180;
while (tryCount-- > 0) {
boolean allFinished = true;
for (MultiDockDTO multiDockDTO : multiTaskDTO.getDocks()) {
if (multiDockDTO.getDockType().equals(MIAO_SUAN)) {
continue;
}
Object o;
if ((o = CacheUtils.get(BusinessConstant.DOCK_OSD + multiDockDTO.getDockSn())) == null) {
continue;
}
JSONObject jsonObject = (JSONObject) o;
//cover_state 舱盖状态 {"0":"关闭","1":"打开","2":"半开","3":"舱盖状态异常"}
int cover_state = jsonObject.getInt("cover_state");
log.info(
"privateMultiDockFlightTaskInbound-> 检查机库各传感器状态,是否已经入库完成 dockSn:{},cover_state:{}"
, multiDockDTO.getDockSn(), cover_state);
allFinished = allFinished && cover_state == 0;
}
if (allFinished) {
break;
}
}
if (tryCount <= 0) {
return "入库超时";
}
return "流程结束";
}
private String privateMultiDockTaskFlightTaskCheck(String dockSn) {
return djiBaseService.executeAndReturnResult(dockSn, "private_multi_dock_task_flighttask_check");
}
private String privateMultiDockFlightTaskOutbound(String dockSn, boolean need_drone_open, String psdk_sn,
String task_id) {
JSONObject jsonObject = new JSONObject();
jsonObject.set("need_drone_open", need_drone_open);
jsonObject.set("psdk_sn", psdk_sn);
jsonObject.set("task_id", task_id);
return djiBaseService.executeAndReturnResult(dockSn, "private_multi_doc_dask_flighttask_outbound", jsonObject);
}
private String privateMultiDockFlightTaskInbound(String dockSn, boolean need_drone_close, String psdk_sn,
String task_id) {
JSONObject jsonObject = new JSONObject();
jsonObject.set("need_drone_close", need_drone_close);
jsonObject.set("psdk_sn", psdk_sn);
jsonObject.set("task_id", task_id);
return djiBaseService.executeAndReturnResult(dockSn, "private_multi_doc_dask_flighttask_inbound", jsonObject);
}
}

View File

@ -15,6 +15,7 @@ import com.multictrl.modules.business.dto.RouteDTO;
import com.multictrl.modules.business.dto.flight.FlightExecute; import com.multictrl.modules.business.dto.flight.FlightExecute;
import com.multictrl.modules.business.dto.flight.FlightTaskPrepare; import com.multictrl.modules.business.dto.flight.FlightTaskPrepare;
import com.multictrl.modules.business.dto.flight.InFlightWaylineDeliver; import com.multictrl.modules.business.dto.flight.InFlightWaylineDeliver;
import com.multictrl.modules.business.dto.multi.PrivateMultiFlightBindDockInfo;
import com.multictrl.modules.business.service.DJIBaseService; import com.multictrl.modules.business.service.DJIBaseService;
import com.multictrl.modules.business.service.FlightTaskService; import com.multictrl.modules.business.service.FlightTaskService;
import com.multictrl.modules.business.service.RouteFlightService; import com.multictrl.modules.business.service.RouteFlightService;
@ -40,6 +41,7 @@ import java.util.concurrent.locks.ReentrantLock;
@Service @Service
@RequiredArgsConstructor @RequiredArgsConstructor
public class RouteFlightServiceImpl implements RouteFlightService { public class RouteFlightServiceImpl implements RouteFlightService {
private final DJIBaseService djiBaseService; private final DJIBaseService djiBaseService;
private final RouteService routeService; private final RouteService routeService;
private final MinioConfig minioConfig; private final MinioConfig minioConfig;
@ -53,14 +55,17 @@ public class RouteFlightServiceImpl implements RouteFlightService {
return djiBaseService.executeAndReturnResult(dockSn, "flighttask_undo", data); return djiBaseService.executeAndReturnResult(dockSn, "flighttask_undo", data);
} }
/*
* multiFlightBindDockInfos aros机场蛙跳模式参数把N个参与到蛙跳的的机场信息给到妙算返航时自动计算离哪个机库位置近就降落到哪个机库
*/
@Override @Override
public String flightExecute(String dockSn, FlightExecute flightExecute, Boolean isRecord) { public String flightExecute(String dockSn, FlightExecute flightExecute) {
ReentrantLock lock = cacheLock.computeIfAbsent(dockSn, k -> new ReentrantLock()); ReentrantLock lock = cacheLock.computeIfAbsent(dockSn, k -> new ReentrantLock());
lock.lock(); lock.lock();
try { try {
Boolean dockOnline = djiBaseService.isDockOnline(dockSn); Boolean dockOnline = djiBaseService.isDockOnline(dockSn);
if (!dockOnline) { if (!dockOnline) {
throw new RenException(ErrorCode.DOCK_OSD_NOT_EXIST, "无法操作"); throw new RenException(ErrorCode.DOCK_OSD_NOT_EXIST, "机场不在线,无法操作");
} }
Integer dockModeCode = djiBaseService.getDockModeCode(dockSn); Integer dockModeCode = djiBaseService.getDockModeCode(dockSn);
if (!Objects.equals(DockMode.IDLE.getCode(), dockModeCode)) { if (!Objects.equals(DockMode.IDLE.getCode(), dockModeCode)) {
@ -73,6 +78,9 @@ public class RouteFlightServiceImpl implements RouteFlightService {
} }
//任务标识 //任务标识
String taskId = IdUtil.fastSimpleUUID(); String taskId = IdUtil.fastSimpleUUID();
if (StrUtil.isNotEmpty(flightExecute.getTaskId())) {
taskId = flightExecute.getTaskId();
}
CacheUtils.set(BusinessConstant.WORKING_TASK_ID + dockSn, taskId); CacheUtils.set(BusinessConstant.WORKING_TASK_ID + dockSn, taskId);
//设置默认相机模式需要定频推送前端 //设置默认相机模式需要定频推送前端
CacheUtils.set(BusinessConstant.UAV_VIDEO_TYPE + dockSn, "wide"); CacheUtils.set(BusinessConstant.UAV_VIDEO_TYPE + dockSn, "wide");
@ -104,27 +112,24 @@ public class RouteFlightServiceImpl implements RouteFlightService {
flightTaskPrepare.setFile(fileInfo); flightTaskPrepare.setFile(fileInfo);
//获取断点如果断点续飞请设置 //获取断点如果断点续飞请设置
// flightTaskPrepare.setBreak_point(null); // flightTaskPrepare.setBreak_point(null);
flightTaskPrepare.setRth_mode(1);
flightTaskPrepare.setRth_altitude((int) Math.round(globalRthHeight)); flightTaskPrepare.setRth_altitude((int) Math.round(globalRthHeight));
//{"0":"返航","1":"悬停","2":"降落"}
//失控动作当前固定传的值是 0即返航注意该枚举值定义跟飞控跟机场定义的不一致机场端会进行转换
flightTaskPrepare.setOut_of_control_action(0);
flightTaskPrepare.setExit_wayline_when_rc_lost(exitOnRcLost); flightTaskPrepare.setExit_wayline_when_rc_lost(exitOnRcLost);
//{"0":"GPS 任务","1":"高精度 RTK 任务"}
flightTaskPrepare.setWayline_precision_type(1);
//模拟器执行 //模拟器执行
if (flightExecute.getSimulateMission() != null) { if (flightExecute.getSimulateMission() != null) {
flightTaskPrepare.setSimulate_mission(flightExecute.getSimulateMission()); flightTaskPrepare.setSimulate_mission(flightExecute.getSimulateMission());
} }
if (flightExecute.getPrivateMultiFlightBindDockInfos() != null) {
flightTaskPrepare.setPrivate_multi_flight_bind_dock_info(
flightExecute.getPrivateMultiFlightBindDockInfos());
}
JSONObject data = JsonUtils.parseObject(JsonUtils.toJsonString(flightTaskPrepare), JSONObject.class); JSONObject data = JsonUtils.parseObject(JsonUtils.toJsonString(flightTaskPrepare), JSONObject.class);
String result = djiBaseService.executeAndReturnResult(dockSn, "flighttask_prepare", data); String result = djiBaseService.executeAndReturnResult(dockSn, "flighttask_prepare", data);
log.debug("flight_task_prepare --> result:{}", result); log.debug("flight_task_prepare --> result:{}", result);
//执行任务 //执行任务
Utils.sleep(1000); Utils.sleep(1000);
String resultMsg = djiBaseService.executeAndReturnResult(dockSn, "flighttask_execute", new JSONObject().set("flight_id", taskId)); String resultMsg = djiBaseService.executeAndReturnResult(dockSn, "flighttask_execute",
if (isRecord) { new JSONObject().set("flight_id", taskId));
flightTaskService.addRouteTask(taskId, dockSn, route.getId()); flightTaskService.addRouteTask(taskId, dockSn, route.getId());
}
return resultMsg; return resultMsg;
} finally { } finally {
Utils.sleep(2000); Utils.sleep(2000);
@ -184,7 +189,8 @@ public class RouteFlightServiceImpl implements RouteFlightService {
if (flightId == null) { if (flightId == null) {
throw new RenException(ErrorCode.ROUTE_TASK_NOT_EXIST); throw new RenException(ErrorCode.ROUTE_TASK_NOT_EXIST);
} }
return djiBaseService.executeAndReturnResult(dockSn, "in_flight_wayline_stop", new JSONObject().set("in_flight_wayline_id", flightId)); return djiBaseService.executeAndReturnResult(dockSn, "in_flight_wayline_stop",
new JSONObject().set("in_flight_wayline_id", flightId));
} }
@Override @Override
@ -193,6 +199,7 @@ public class RouteFlightServiceImpl implements RouteFlightService {
if (flightId == null) { if (flightId == null) {
throw new RenException(ErrorCode.ROUTE_TASK_NOT_EXIST); throw new RenException(ErrorCode.ROUTE_TASK_NOT_EXIST);
} }
return djiBaseService.executeAndReturnResult(dockSn, "in_flight_wayline_recover", new JSONObject().set("in_flight_wayline_id", flightId)); return djiBaseService.executeAndReturnResult(dockSn, "in_flight_wayline_recover",
new JSONObject().set("in_flight_wayline_id", flightId));
} }
} }

View File

@ -78,6 +78,6 @@ influx:
org: dj org: dj
host: host:
ip: 223.108.157.174 ip: 192.168.1.193
port: 61620 port: 61620
is-ssl: false is-ssl: false

19
pom.xml
View File

@ -8,8 +8,20 @@
<name>Dock-MultiCtrl</name> <name>Dock-MultiCtrl</name>
<description>大疆机场多版本控制</description> <description>大疆机场多版本控制</description>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>7</source>
<target>7</target>
</configuration>
</plugin>
</plugins>
</build>
<parent> <parent>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId> <artifactId>spring-boot-starter-parent</artifactId>
<version>4.0.5</version> <version>4.0.5</version>
@ -106,6 +118,11 @@
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId> <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>${springdoc.version}</version> <version>${springdoc.version}</version>
</dependency> </dependency>
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<version>2.0.62</version>
</dependency>
</dependencies> </dependencies>
<dependencyManagement> <dependencyManagement>