From 87689cefac709bdc2414c8d365b03ad0585e5bc5 Mon Sep 17 00:00:00 2001
From: liusuyi <1951119284@qq.com>
Date: Tue, 25 Nov 2025 14:02:55 +0800
Subject: [PATCH] 增加环绕飞行控制

---
 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-work/src/main/java/com/ard/work/domain/dto/manual/FlyRoundControlDTO.java                    |   51 ++++++++++
 ard-work/src/main/java/com/ard/work/service/impl/TyServiceImpl.java                              |   37 +++++++
 ard-work/src/main/java/com/ard/work/component/netty/command/manual/FlyRoundReplyCmd.java         |   35 +++++++
 ard-admin/src/main/java/com/ard/web/controller/work/UavManualFlyController.java                  |   19 +++
 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 ++
 ard-work/src/main/java/com/ard/work/domain/dto/manual/FlyRoundControlCancelDTO.java              |   22 ++++
 9 files changed, 260 insertions(+), 0 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-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/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/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