From aae8b5dc994fffdc211b1f0fc860840cb0d4687a Mon Sep 17 00:00:00 2001
From: zhaowenyu <35589726@qq.com>
Date: Tue, 25 Nov 2025 14:34:02 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/dev' into dev
---
ard-work/src/main/java/com/ard/work/component/netty/handler/MessageProtocolDecoder.java | 2
ard-work/src/main/java/com/ard/work/component/netty/command/manual/FlyRoundControlCancelCmd.java | 33 +++
ard-route/src/main/java/com/ard/route/domain/route/ArdRouteInfo.java | 3
ard-route/src/main/java/com/ard/route/util/ToolUtils.java | 4
ard-work/src/main/java/com/ard/work/service/impl/TyServiceImpl.java | 37 ++++
ard-route/src/main/resources/mapper/ArdRouteInfoMapper.xml | 9
ard-work/src/main/java/com/ard/work/component/netty/command/manual/FlyRoundReplyCmd.java | 35 +++
ard-route/src/main/java/com/ard/route/service/impl/ArdRouteInfoServiceImpl.java | 22 +
ard-admin/src/main/java/com/ard/web/controller/work/UavManualFlyController.java | 19 ++
ard-work/src/main/java/com/ard/work/domain/dto/manual/FlyRoundControlCancelDTO.java | 22 ++
ard-work/src/main/java/com/ard/work/service/impl/ArdFlightTaskServiceServiceImpl.java | 122 ++++++-------
ard-work/src/main/java/com/ard/work/component/websocket/handler/TyMessageHandler.java | 13
ard-route/src/main/java/com/ard/route/service/impl/UavRouteServiceImpl.java | 63 ++----
ard-work/src/main/java/com/ard/work/domain/dto/manual/FlyRoundControlDTO.java | 51 +++++
ard-work/src/main/java/com/ard/work/component/netty/command/manual/FlyRoundControlCmd.java | 50 +++++
ard-work/src/main/java/com/ard/work/service/ITyService.java | 11 +
16 files changed, 370 insertions(+), 126 deletions(-)
diff --git a/ard-admin/src/main/java/com/ard/web/controller/work/UavManualFlyController.java b/ard-admin/src/main/java/com/ard/web/controller/work/UavManualFlyController.java
index ab6aad4..e3b17f6 100644
--- a/ard-admin/src/main/java/com/ard/web/controller/work/UavManualFlyController.java
+++ b/ard-admin/src/main/java/com/ard/web/controller/work/UavManualFlyController.java
@@ -108,6 +108,25 @@
return AjaxResult.success();
}
+ @ApiOperation(value = "开始环绕飞行", notes = "速度speed:0~20 单位m/s " +
+ "环绕半径radius:单位m,"+
+ "飞行模式flyMode:0-节能模式【飞机直线飞到目标点,需飞机在空中】," +
+ "1-安全模式【飞机飞行至目标点高度再平飞到目标点,飞机可以在地面或空中】 默认为节能模式")
+ @ApiOperationSupport(order = 9)
+ @PostMapping("/flyRoundControl")
+ public AjaxResult flyRoundControl(@RequestBody FlyRoundControlDTO flyRoundControlDTO) {
+ tyService.FlyRoundControl(flyRoundControlDTO);
+ return AjaxResult.success();
+ }
+
+ @ApiOperation("停止环绕飞行")
+ @ApiOperationSupport(order = 10)
+ @PostMapping("/flyRoundControlCancel")
+ public AjaxResult flyRoundControlCancel(@RequestBody FlyRoundControlCancelDTO flyRoundControlCancelDTO) {
+ tyService.FlyRoundControlCancel(flyRoundControlCancelDTO);
+ return AjaxResult.success();
+ }
+
@ApiOperation(value = "紧急制动", notes = "动作参数actionParam: 0-解除紧急制动 1-紧急制动")
@ApiOperationSupport(order = 11)
@PostMapping("/emeragencyBrake")
diff --git a/ard-route/src/main/java/com/ard/route/domain/route/ArdRouteInfo.java b/ard-route/src/main/java/com/ard/route/domain/route/ArdRouteInfo.java
index d12c4d4..509e3f5 100644
--- a/ard-route/src/main/java/com/ard/route/domain/route/ArdRouteInfo.java
+++ b/ard-route/src/main/java/com/ard/route/domain/route/ArdRouteInfo.java
@@ -64,4 +64,7 @@
/** 航线数据 */
private byte[] routeData;
+ /** 行点总数 */
+ private Integer pointCount;
+
}
diff --git a/ard-route/src/main/java/com/ard/route/service/impl/ArdRouteInfoServiceImpl.java b/ard-route/src/main/java/com/ard/route/service/impl/ArdRouteInfoServiceImpl.java
index 1190edc..57f6522 100644
--- a/ard-route/src/main/java/com/ard/route/service/impl/ArdRouteInfoServiceImpl.java
+++ b/ard-route/src/main/java/com/ard/route/service/impl/ArdRouteInfoServiceImpl.java
@@ -21,6 +21,7 @@
import com.ard.route.domain.dto.ArdNoflyDto;
import com.ard.route.domain.route.ArdRouteInfo;
import com.ard.route.domain.sixhe.ArdRouteChange;
+import com.ard.route.domain.vo.KmzInfoVo;
import com.ard.route.domain.vo.KmzResultVo;
import com.ard.route.mapper.ArdRouteInfoMapper;
import com.ard.route.service.IArdRouteInfoService;
@@ -121,6 +122,7 @@
KmzResultVo kmzResult = routeService.buildKmz(ardRouteInfo.getUavRouteReq(), ardRouteInfo.getName());
ardRouteInfo.setPath(kmzResult.getPath());
ardRouteInfo.setReadOnly("0");
+ ardRouteInfo.setPointCount(getPointCount(ardRouteInfo));
ardRouteInfoMapper.insertArdRouteInfo(ardRouteInfo);
return kmzResult.getPath();
}
@@ -149,7 +151,15 @@
}
ardRouteInfo.setPath(kmzResult.getPath());
}
+ ardRouteInfo.setPointCount(getPointCount(ardRouteInfo));
return ardRouteInfoMapper.updateArdRouteInfo(ardRouteInfo);
+ }
+
+ private Integer getPointCount(ArdRouteInfo ardRouteInfo) {
+ if (ardRouteInfo.getUavRouteReq().getRoutePointList() != null) {
+ return ardRouteInfo.getUavRouteReq().getRoutePointList().size();
+ }
+ return 0;
}
/**
@@ -194,6 +204,7 @@
information.setPath(url);
information.setGroupId("0"); // 默认分组
information.setReadOnly("1"); // 默认只读
+ // 增加航线实体类信息
insertRouteInfomation(information);
return MinioUploadResult.builder()
.url(url)
@@ -331,9 +342,10 @@
if (autoFlightSpeed != null){
planLineData.setAutoSpeed(8);
}
- if (globalTransitionalSpeed != null){
- planLineData.setMaxSpeed(15);
- }
+ planLineData.setMaxSpeed(15);
+// if (globalTransitionalSpeed != null){
+// planLineData.setMaxSpeed(15);
+// }
if (exitOnRcLostAction != null){
planLineData.setFinishedAction(1);
}
@@ -359,11 +371,11 @@
if (height != null){
pointData.setHeight(height.floatValue());
}
- Double longitude = routePointReq.getLatitude();
+ Double longitude = routePointReq.getLongitude();
if (longitude != null){
pointData.setLng(longitude.floatValue());
}
- Double latitude = routePointReq.getLongitude();
+ Double latitude = routePointReq.getLatitude();
if (latitude != null){
pointData.setLat(latitude.floatValue());
}
diff --git a/ard-route/src/main/java/com/ard/route/service/impl/UavRouteServiceImpl.java b/ard-route/src/main/java/com/ard/route/service/impl/UavRouteServiceImpl.java
index cd006dd..1a8b76e 100644
--- a/ard-route/src/main/java/com/ard/route/service/impl/UavRouteServiceImpl.java
+++ b/ard-route/src/main/java/com/ard/route/service/impl/UavRouteServiceImpl.java
@@ -178,54 +178,31 @@
String kml = XML_HEADER + xStream.toXML(kmlInfo);
String wpml = XML_HEADER + xStream.toXML(wpmlInfo);
-
KmzResultVo result = new KmzResultVo();
+ try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ZipOutputStream zipOutputStream = new ZipOutputStream(baos)) {
+ zipOutputStream.setLevel(0);
- // 判断本地生成kmz文件
- if (isLocal) {
- try (FileOutputStream fileOutputStream = new FileOutputStream(localFilePath + fileName + ".kmz");
- ZipOutputStream zipOutputStream = new ZipOutputStream(fileOutputStream)) {
- zipOutputStream.setLevel(0); // 0 表示不压缩,存储方式
+ // 创建 wpmz 目录中的 template.kml 文件条目
+ buildZipFile("wpmz/template.kml", zipOutputStream, kml);
+ // 创建 wpmz 目录中的 waylines.wpml 文件条目
+ buildZipFile("wpmz/waylines.wpml", zipOutputStream, wpml);
- // 创建KMZ文件内容
- buildZipFile("wpmz/template.kml", zipOutputStream, kml);
- buildZipFile("wpmz/waylines.wpml", zipOutputStream, wpml);
+ zipOutputStream.finish();
+ zipOutputStream.flush();
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- result.setPath(localFilePath + fileName + ".kmz");
+ // 创建MultipartFile对象
+ MultipartFile multipartFile = new MockMultipartFile(
+ fileName + ".kmz",
+ fileName + ".kmz",
+ "application/vnd.google-earth.kmz",
+ new ByteArrayInputStream(baos.toByteArray())
+ );
+ String kmzFilePath = ossService.upload(kmzPath,multipartFile);
+ result.setPath(kmzFilePath);
return result;
- }else {
- try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
- ZipOutputStream zipOutputStream = new ZipOutputStream(baos)) {
- zipOutputStream.setLevel(0);
-
- // 创建 wpmz 目录中的 template.kml 文件条目
- buildZipFile("wpmz/template.kml", zipOutputStream, kml);
-
- // 创建 wpmz 目录中的 waylines.wpml 文件条目
- buildZipFile("wpmz/waylines.wpml", zipOutputStream, wpml);
-
- zipOutputStream.finish();
- zipOutputStream.flush();
-
- // 获取文件大小
- Double fileSize = (double) baos.size(); // 字节数
-
- // 创建MultipartFile对象
- MultipartFile multipartFile = new MockMultipartFile(
- fileName + ".kmz",
- fileName + ".kmz",
- "application/vnd.google-earth.kmz",
- new ByteArrayInputStream(baos.toByteArray())
- );
- String kmzFilePath = ossService.upload(kmzPath,multipartFile);
- result.setPath(kmzFilePath);
- return result;
- } catch (Exception e) {
- throw new RuntimeException("KMZ文件生成或上传失败", e);
- }
+ } catch (Exception e) {
+ throw new RuntimeException("KMZ文件生成或上传失败", e);
}
}
diff --git a/ard-route/src/main/java/com/ard/route/util/ToolUtils.java b/ard-route/src/main/java/com/ard/route/util/ToolUtils.java
index 2d34f6c..d392f34 100644
--- a/ard-route/src/main/java/com/ard/route/util/ToolUtils.java
+++ b/ard-route/src/main/java/com/ard/route/util/ToolUtils.java
@@ -9,10 +9,6 @@
*/
public class ToolUtils {
- public static Boolean isLocal = false;
-
- public static String localFilePath = "KmzFile/kmz/";
-
public static String kmzPath = "kmz";
/**
diff --git a/ard-route/src/main/resources/mapper/ArdRouteInfoMapper.xml b/ard-route/src/main/resources/mapper/ArdRouteInfoMapper.xml
index 5c23ab9..f1c5619 100644
--- a/ard-route/src/main/resources/mapper/ArdRouteInfoMapper.xml
+++ b/ard-route/src/main/resources/mapper/ArdRouteInfoMapper.xml
@@ -18,6 +18,7 @@
<result property="createTime" column="create_time" />
<result property="updateBy" column="update_by" />
<result property="updateTime" column="update_time" />
+ <result property="pointCount" column="point_count" />
</resultMap>
<sql id="selectArdRouteInfoVo">
@@ -33,7 +34,8 @@
create_by,
create_time,
update_by,
- update_time
+ update_time,
+ point_count
from ard_route_info
</sql>
@@ -74,6 +76,7 @@
<if test="createTime != null">create_time,</if>
<if test="updateBy != null">update_by,</if>
<if test="updateTime != null">update_time,</if>
+ <if test="pointCount != null">point_count,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="id != null">#{id},</if>
@@ -89,6 +92,7 @@
<if test="createTime != null">#{createTime},</if>
<if test="updateBy != null">#{updateBy},</if>
<if test="updateTime != null">#{updateTime},</if>
+ <if test="pointCount != null">#{pointCount},</if>
</trim>
</insert>
@@ -107,6 +111,7 @@
<if test="createTime != null">create_time = #{createTime},</if>
<if test="updateBy != null">update_by = #{updateBy},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
+ <if test="pointCount != null">point_count = #{pointCount},</if>
</trim>
where id = #{id}
</update>
@@ -135,7 +140,7 @@
</delete>
<select id="selectArdRouteInfoByGroupId" parameterType="String" resultMap="ArdRouteInfoResult">
- select id,name,path,group_id,type,aircraft,payload,read_only,create_by,create_time,update_by,update_time from ard_route_info
+ select id,name,path,group_id,type,aircraft,payload,read_only,create_by,create_time,update_by,update_time,point_count from ard_route_info
<where>
<if test="groupId != null "> and group_id = #{groupId}</if>
</where>
diff --git a/ard-work/src/main/java/com/ard/work/component/netty/command/manual/FlyRoundControlCancelCmd.java b/ard-work/src/main/java/com/ard/work/component/netty/command/manual/FlyRoundControlCancelCmd.java
new file mode 100644
index 0000000..d6d137e
--- /dev/null
+++ b/ard-work/src/main/java/com/ard/work/component/netty/command/manual/FlyRoundControlCancelCmd.java
@@ -0,0 +1,33 @@
+package com.ard.work.component.netty.command.manual;
+
+import com.ard.work.component.netty.command.BaseCmd;
+import com.ard.work.domain.dto.manual.FlyRoundControlCancelDTO;
+import com.ard.work.domain.dto.manual.FlyRoundControlDTO;
+import io.netty.buffer.ByteBuf;
+
+/**
+ * 环绕飞行控制指令
+ *
+ * @author liusuyi
+ * @date 2024年10月26日15:43
+ **/
+public class FlyRoundControlCancelCmd extends BaseCmd {
+
+
+ public FlyRoundControlCancelCmd(FlyRoundControlCancelDTO flyRoundControlCancelDTO) {
+ setDataHeader((short) 0x7479);
+ setDataLength((short) 18);
+ setBoxSn(flyRoundControlCancelDTO.getBoxSn().getBytes());
+ setCmdCode((byte) 0xD1);
+ }
+
+
+ public void encode(ByteBuf out) {
+ out.writeShort(getDataHeader()); // 写入数据头
+ out.writeShort(getDataLength()); // 写入数据长度
+ out.writeBytes(getBoxSn()); // 写入盒子SN
+ out.writeByte(getCmdCode()); // 写入命令码
+ out.writeByte(0x00); // 写入加密标志
+ out.writeByte(0x3C); // 写入动作编号
+ }
+}
diff --git a/ard-work/src/main/java/com/ard/work/component/netty/command/manual/FlyRoundControlCmd.java b/ard-work/src/main/java/com/ard/work/component/netty/command/manual/FlyRoundControlCmd.java
new file mode 100644
index 0000000..3684c57
--- /dev/null
+++ b/ard-work/src/main/java/com/ard/work/component/netty/command/manual/FlyRoundControlCmd.java
@@ -0,0 +1,50 @@
+package com.ard.work.component.netty.command.manual;
+
+import com.ard.work.component.netty.command.BaseCmd;
+import com.ard.work.domain.dto.manual.FlyPointControlDTO;
+import com.ard.work.domain.dto.manual.FlyRoundControlDTO;
+import io.netty.buffer.ByteBuf;
+
+/**
+ * 环绕飞行控制指令
+ *
+ * @author liusuyi
+ * @date 2024年10月26日15:43
+ **/
+public class FlyRoundControlCmd extends BaseCmd {
+ private final double longitude; // 兴趣点经度
+ private final double latitude; // 兴趣点纬度
+ private final float altitude; // 兴趣点高度
+ private final float speed; // 环绕速度
+ private final float radius; // 环绕半径
+ private final byte flyMode; // 飞行模式
+
+ public FlyRoundControlCmd(FlyRoundControlDTO flyRoundControlDTO) {
+ setDataHeader((short) 0x7479);
+ setDataLength((short) 47);
+ setBoxSn(flyRoundControlDTO.getBoxSn().getBytes());
+ setCmdCode((byte) 0xD1);
+ this.longitude = flyRoundControlDTO.getLongitude();
+ this.latitude = flyRoundControlDTO.getLatitude();
+ this.altitude = flyRoundControlDTO.getAltitude();
+ this.speed = flyRoundControlDTO.getSpeed();
+ this.radius= flyRoundControlDTO.getRadius();
+ this.flyMode = flyRoundControlDTO.getFlyMode();
+ }
+
+
+ public void encode(ByteBuf out) {
+ out.writeShort(getDataHeader()); // 写入数据头
+ out.writeShort(getDataLength()); // 写入数据长度
+ out.writeBytes(getBoxSn()); // 写入盒子SN
+ out.writeByte(getCmdCode()); // 写入命令码
+ out.writeByte(0x00); // 写入加密标志
+ out.writeByte(0x3B); // 写入动作编号
+ out.writeDouble(longitude); // 写入兴趣点经度
+ out.writeDouble(latitude); // 写入兴趣点纬度
+ out.writeFloat(altitude); // 写入兴趣点高度
+ out.writeFloat(speed); // 写入环绕速度
+ out.writeFloat(radius); // 写入环绕半径
+ out.writeByte(flyMode); // 写入飞行模式
+ }
+}
diff --git a/ard-work/src/main/java/com/ard/work/component/netty/command/manual/FlyRoundReplyCmd.java b/ard-work/src/main/java/com/ard/work/component/netty/command/manual/FlyRoundReplyCmd.java
new file mode 100644
index 0000000..abfa708
--- /dev/null
+++ b/ard-work/src/main/java/com/ard/work/component/netty/command/manual/FlyRoundReplyCmd.java
@@ -0,0 +1,35 @@
+package com.ard.work.component.netty.command.manual;
+
+import com.ard.work.component.netty.command.BaseCmd;
+import io.netty.buffer.ByteBuf;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 到达环绕位置回复指令
+ *
+ * @author liusuyi
+ * @date 2024年10月26日15:43
+ **/
+@Data
+@EqualsAndHashCode(callSuper = false)
+public class FlyRoundReplyCmd extends BaseCmd {
+
+ private final byte encryptFlag = 0x00; // 加密标志
+ private final byte actionCode = 0x3B; // 动作编号
+ private final byte result; // 执行结果
+ private final Integer errorCode; // 错误码
+
+ public FlyRoundReplyCmd(String boxSn, Byte result, Integer errorCode) {
+ setDataHeader((short) 0x6A77);
+ setDataLength((short) 19);
+ setBoxSn(boxSn.getBytes());
+ setCmdCode((byte) 0xD1);
+ this.result = result;
+ this.errorCode = errorCode;
+ }
+
+ public void encode(ByteBuf out) {
+
+ }
+}
diff --git a/ard-work/src/main/java/com/ard/work/component/netty/handler/MessageProtocolDecoder.java b/ard-work/src/main/java/com/ard/work/component/netty/handler/MessageProtocolDecoder.java
index a36e068..337ed0c 100644
--- a/ard-work/src/main/java/com/ard/work/component/netty/handler/MessageProtocolDecoder.java
+++ b/ard-work/src/main/java/com/ard/work/component/netty/handler/MessageProtocolDecoder.java
@@ -174,6 +174,8 @@
return new EmergencyBrakeReplyCmd(boxSn, result, errorCode);
case 0x39:
return new PointControlReachedReplyCmd(boxSn, result, errorCode);
+ case 0x3B:
+ return new FlyRoundReplyCmd(boxSn, result, errorCode);
case 0x22:
return new CameraModeReplyCmd(boxSn, result, errorCode);
case 0x23:
diff --git a/ard-work/src/main/java/com/ard/work/component/websocket/handler/TyMessageHandler.java b/ard-work/src/main/java/com/ard/work/component/websocket/handler/TyMessageHandler.java
index a46cfb6..6d9f21e 100644
--- a/ard-work/src/main/java/com/ard/work/component/websocket/handler/TyMessageHandler.java
+++ b/ard-work/src/main/java/com/ard/work/component/websocket/handler/TyMessageHandler.java
@@ -290,14 +290,7 @@
Long userId = Long.parseLong(userIdStr);
WebSocketSessionManager.removeSession(userId);
log.info("【cmd】size: {}", WebSocketSessionManager.getOnlineUserCount());
-
// 释放该用户所有 UAV 控制权
- uavControlService.releaseAllControls(userId);
- uavStreamManager.stopAllPullStreamByUser(userId);
- uavStateManager.removeSubscribe(userId);
- uavTelemetryManager.removeSubscribe(userId);
- uavSignalManager.removeSubscribe(userId);
- uavControlManager.removeSubscribe(userId);
// 延迟10秒删除token(若期间没重连)
CompletableFuture.runAsync(() -> {
@@ -309,6 +302,12 @@
if (!WebSocketSessionManager.containsUser(userId)) {
LoginUser loginUser = tokenService.getLoginUserByUserId(userId);
if (loginUser != null) {
+ uavControlService.releaseAllControls(userId);
+ uavStreamManager.stopAllPullStreamByUser(userId);
+ uavStateManager.removeSubscribe(userId);
+ uavTelemetryManager.removeSubscribe(userId);
+ uavSignalManager.removeSubscribe(userId);
+ uavControlManager.removeSubscribe(userId);
tokenService.delLoginUser(loginUser.getToken(), userId);
log.info("【cmd】用户 [{}] 超时未重连,已删除 token", userId);
}
diff --git a/ard-work/src/main/java/com/ard/work/domain/dto/manual/FlyRoundControlCancelDTO.java b/ard-work/src/main/java/com/ard/work/domain/dto/manual/FlyRoundControlCancelDTO.java
new file mode 100644
index 0000000..5132935
--- /dev/null
+++ b/ard-work/src/main/java/com/ard/work/domain/dto/manual/FlyRoundControlCancelDTO.java
@@ -0,0 +1,22 @@
+package com.ard.work.domain.dto.manual;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 环绕飞行控制实体对象
+ *
+ * @author liusuyi
+ * @date 2024年10月26日9:02
+ **/
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class FlyRoundControlCancelDTO {
+
+ private String boxSn;
+
+}
diff --git a/ard-work/src/main/java/com/ard/work/domain/dto/manual/FlyRoundControlDTO.java b/ard-work/src/main/java/com/ard/work/domain/dto/manual/FlyRoundControlDTO.java
new file mode 100644
index 0000000..7a10ec4
--- /dev/null
+++ b/ard-work/src/main/java/com/ard/work/domain/dto/manual/FlyRoundControlDTO.java
@@ -0,0 +1,51 @@
+package com.ard.work.domain.dto.manual;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 环绕飞行控制实体对象
+ *
+ * @author liusuyi
+ * @date 2024年10月26日9:02
+ **/
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class FlyRoundControlDTO {
+
+ private String boxSn;
+
+ /**
+ * 兴趣点经度
+ */
+ private Double longitude;
+ /**
+ * 兴趣点纬度
+ */
+ private Double latitude;
+ /**
+ * 兴趣点高度
+ */
+ private Float altitude;
+
+ /**
+ * 环绕速度
+ */
+ private Float speed;
+
+ /**
+ * 环绕半径
+ */
+ private Float radius;
+
+ /**
+ * 飞行模式
+ */
+ @Builder.Default
+ private byte flyMode = 0;
+
+}
diff --git a/ard-work/src/main/java/com/ard/work/service/ITyService.java b/ard-work/src/main/java/com/ard/work/service/ITyService.java
index b5b1350..fb43af9 100644
--- a/ard-work/src/main/java/com/ard/work/service/ITyService.java
+++ b/ard-work/src/main/java/com/ard/work/service/ITyService.java
@@ -206,6 +206,17 @@
*/
Boolean flyPointControlCancel(FlyPointControlCancelDTO flyPointControlCancelDTO);
+
+ /**
+ * 环绕飞行控制
+ */
+ Boolean FlyRoundControl(FlyRoundControlDTO flyRoundControlDTO);
+
+ /**
+ * 停止环绕飞行
+ */
+ Boolean FlyRoundControlCancel(FlyRoundControlCancelDTO flyRoundControlCancelDTO);
+
/**
* 紧急制动
*/
diff --git a/ard-work/src/main/java/com/ard/work/service/impl/ArdFlightTaskServiceServiceImpl.java b/ard-work/src/main/java/com/ard/work/service/impl/ArdFlightTaskServiceServiceImpl.java
index cb0a57b..1627d98 100644
--- a/ard-work/src/main/java/com/ard/work/service/impl/ArdFlightTaskServiceServiceImpl.java
+++ b/ard-work/src/main/java/com/ard/work/service/impl/ArdFlightTaskServiceServiceImpl.java
@@ -1,5 +1,8 @@
package com.ard.work.service.impl;
+import com.ard.common.constant.CacheConstants;
+import com.ard.common.core.domain.entity.SysUser;
+import com.ard.common.core.redis.RedisCache;
import com.ard.common.utils.DateUtils;
import com.ard.common.utils.file.MimeTypeUtils;
import com.ard.common.utils.uuid.IdUtils;
@@ -16,8 +19,10 @@
import com.ard.work.mapper.ArdMediaMapper;
import com.ard.work.service.IArdFlightTaskService;
import com.ard.work.service.IArdServerInfoService;
+import com.ard.work.service.control.UavControlService;
import com.ard.work.util.osSelect;
import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
@@ -57,7 +62,10 @@
private OssServiceContext ossServiceContext;
@Resource
private ThreadPoolTaskExecutor threadPoolTaskExecutor; // 使用线程池执行异步任务
-
+ @Resource
+ private UavControlService uavControlService;
+ @Autowired
+ private RedisCache redisCache;
/**
* 查询飞行架次列表
*
@@ -128,6 +136,14 @@
.startTime(DateUtils.dateTime(DateUtils.YYYY_MM_DD_HH_MM_SS, boxHistoryReceiver.getStartTime()))
.endTime(DateUtils.dateTime(DateUtils.YYYY_MM_DD_HH_MM_SS, boxHistoryReceiver.getEndTime()))
.build();
+
+ Long flyUserId = uavControlService.getCurrentController(flightTask.getBoxSn(), "fly");
+ if (flyUserId != null) {
+ SysUser flyUser = redisCache.getCacheObject(CacheConstants.SYS_USER_KEY + flyUserId);
+ if (flyUser != null && flyUser.getNickName() != null) {
+ flightTask.setCreateBy(flyUser.getNickName());
+ }
+ }
flightTask.setCreateTime(DateUtils.getNowDate());
// 插入新记录
int rows = ardFlightTaskMapper.insertArdFlightTask(flightTask);
@@ -144,12 +160,46 @@
} else {
// 如果存在,则更新记录
log.debug("Updating task {}", boxHistoryReceiver.getTaskId());
+ updateFlightTask(ardFlightTask, boxHistoryReceiver);
// 增量更新
updateVideoToDatabase(ardFlightTask, boxHistoryReceiver.getVideoPathList());
// 增量更新图片
updatePhotoToDatabase(ardFlightTask, serverId, boxHistoryReceiver.getBoxSn());
}
+ }
+ private void updateFlightTask(ArdFlightTask local, BoxHistoryReceiver remote) {
+
+ boolean needUpdate = false;
+
+ // endTime 更新(重要!!!)
+ Date newEnd = DateUtils.dateTime(DateUtils.YYYY_MM_DD_HH_MM_SS, remote.getEndTime());
+ if (newEnd != null && (local.getEndTime() == null || !local.getEndTime().equals(newEnd))) {
+ local.setEndTime(newEnd);
+ needUpdate = true;
+ }
+
+ // photoCount 更新
+ int remotePhotoCount = Integer.parseInt(remote.getPhotoCount());
+ if (local.getPhotoCount() != remotePhotoCount) {
+ local.setPhotoCount(remotePhotoCount);
+ needUpdate = true;
+ }
+
+ // videoCount 更新
+ int remoteVideoCount = remote.getVideoPathList() != null ? remote.getVideoPathList().size() : 0;
+ if (local.getVideoCount() != remoteVideoCount) {
+ local.setVideoCount(remoteVideoCount);
+ needUpdate = true;
+ }
+
+ if (needUpdate) {
+ ardFlightTaskMapper.updateArdFlightTask(local);
+ }
+
+ // 其它媒体增量更新
+ updateVideoToDatabase(local, remote.getVideoPathList());
+ updatePhotoToDatabase(local, local.getServerId(), remote.getBoxSn());
}
@@ -415,70 +465,6 @@
}
// 生成视频缩略图
- public ByteArrayInputStream generateThumbnail1(String videoFile, int skipFrames, int targetWidth) {
-// long start = System.currentTimeMillis();
-// FFmpegFrameGrabber grabber = null;
-//
-// try {
-// grabber = new FFmpegFrameGrabber(videoFile);
-// grabber.start();
-//
-// int totalFrames = grabber.getLengthInFrames();
-// System.out.println("视频总帧数: " + totalFrames);
-// System.out.println("视频时长: " + grabber.getLengthInTime() / 1000000 + "秒");
-//
-// Frame frame = null;
-// int currentFrame = 0;
-//
-// // 读取指定帧数后的第一帧有效图像
-// while (currentFrame < totalFrames) {
-// frame = grabber.grabImage();
-// if (frame == null) {
-// break;
-// }
-//
-// if (currentFrame > skipFrames && frame.image != null) {
-// break;
-// }
-// currentFrame++;
-// }
-//
-// if (frame == null || frame.image == null) {
-// throw new Exception("无法获取有效视频帧");
-// }
-//
-// // 转换 Frame 为 BufferedImage
-// Java2DFrameConverter converter = new Java2DFrameConverter();
-// BufferedImage image = converter.getBufferedImage(frame);
-//
-// // 按目标宽度等比缩放
-// int targetHeight = (int) ((double) targetWidth / image.getWidth() * image.getHeight());
-// BufferedImage scaledImage = new BufferedImage(targetWidth, targetHeight, BufferedImage.TYPE_3BYTE_BGR);
-// scaledImage.getGraphics().drawImage(image, 0, 0, targetWidth, targetHeight, null);
-//
-// // 转成 ByteArrayInputStream
-// ByteArrayOutputStream baos = new ByteArrayOutputStream();
-// ImageIO.write(scaledImage, "jpg", baos);
-// long cost = System.currentTimeMillis() - start;
-// System.out.println("处理耗时: " + cost + "ms");
-//
-// return new ByteArrayInputStream(baos.toByteArray());
-//
-// } catch (Exception e) {
-// throw new RuntimeException(e);
-// } finally {
-// if (grabber != null) {
-// try {
-// grabber.stop();
-// grabber.close();
-// } catch (Exception e) {
-// e.printStackTrace();
-// }
-// }
-// }
- return null;
- }
-
public ByteArrayInputStream generateThumbnail(
String videoFile,
int skipSeconds,
@@ -492,6 +478,12 @@
try {
List<String> command = new ArrayList<>();
command.add(ffmpegPath);
+
+ command.add("-timeout");
+ command.add("3000000");
+ command.add("-rw_timeout");
+ command.add("3000000");
+
command.add("-ss");
command.add(String.format("00:00:%02d", skipSeconds));
command.add("-i");
diff --git a/ard-work/src/main/java/com/ard/work/service/impl/TyServiceImpl.java b/ard-work/src/main/java/com/ard/work/service/impl/TyServiceImpl.java
index 8db4ecb..432a475 100644
--- a/ard-work/src/main/java/com/ard/work/service/impl/TyServiceImpl.java
+++ b/ard-work/src/main/java/com/ard/work/service/impl/TyServiceImpl.java
@@ -603,6 +603,37 @@
return true;
}
+
+ /**
+ * 环绕飞行控制
+ */
+ @Override
+ public Boolean FlyRoundControl(FlyRoundControlDTO flyRoundControlDTO) {
+ String boxSn = flyRoundControlDTO.getBoxSn();
+ ArdDroneInfo ardDroneInfo = ardDroneService.selectArdDroneByboxSn(boxSn);
+ if (ardDroneInfo == null) {
+ throw new ControlException("未找到对应的飞行器信息,boxSn:{}" + boxSn);
+ }
+ FlyRoundControlCmd flyPointControlCmd = new FlyRoundControlCmd(flyRoundControlDTO);
+ this.sendMessage(ardDroneInfo.getServerId(), flyPointControlCmd);
+ return true;
+ }
+
+ /**
+ * 停止环绕飞行控制
+ */
+ @Override
+ public Boolean FlyRoundControlCancel(FlyRoundControlCancelDTO flyRoundControlCancelDTO) {
+ String boxSn = flyRoundControlCancelDTO.getBoxSn();
+ ArdDroneInfo ardDroneInfo = ardDroneService.selectArdDroneByboxSn(boxSn);
+ if (ardDroneInfo == null) {
+ throw new ControlException("未找到对应的飞行器信息,boxSn:{}" + boxSn);
+ }
+ FlyRoundControlCancelCmd flyRoundControlCancelCmd = new FlyRoundControlCancelCmd(flyRoundControlCancelDTO);
+ this.sendMessage(ardDroneInfo.getServerId(), flyRoundControlCancelCmd);
+ return true;
+ }
+
/**
* 紧急制动
*/
@@ -1042,6 +1073,12 @@
logPrint("设置返航点", returnPointSettingReplyCmd.getResult(),
returnPointSettingReplyCmd.getErrorCode());
}
+ //到达环绕位置回复
+ if (tyCommand instanceof FlyRoundReplyCmd) {
+ FlyRoundReplyCmd flyRoundReplyCmd = (FlyRoundReplyCmd) tyCommand;
+ logPrint("到达环绕位置", flyRoundReplyCmd.getResult(),
+ flyRoundReplyCmd.getErrorCode());
+ }
break;
case (byte) 0xD2:
//设置视频码流回复
--
Gitblit v1.9.3