From b821735241678a21ddc033aba04ebaf7ce65a3d2 Mon Sep 17 00:00:00 2001
From: liusuyi <1951119284@qq.com>
Date: Thu, 31 Oct 2024 09:49:33 +0800
Subject: [PATCH] 优化结构

---
 ard-work/src/main/java/com/ard/tianyu/netty/handler/ClientHandler.java           |    2 
 ard-work/src/main/java/com/ard/tianyu/netty/handler/MessageProtocolDecoder.java  |  259 +++++++++++--------------------
 ard-work/src/main/java/com/ard/tianyu/service/impl/TyServiceImpl.java            |   81 ++++++---
 ard-work/src/main/java/com/ard/tianyu/netty/handler/MessageProtocolEncoder.java  |    9 
 ard-work/src/main/java/com/ard/tianyu/service/ITyService.java                    |    4 
 ard-work/src/main/java/com/ard/tianyu/netty/command/notice/UavReadyReplyCmd.java |    3 
 ard-work/src/main/java/com/ard/tianyu/controller/UavBaseController.java          |    1 
 ard-common/src/main/java/com/ard/common/utils/ByteUtils.java                     |   71 ++++++++
 8 files changed, 225 insertions(+), 205 deletions(-)

diff --git a/ard-common/src/main/java/com/ard/common/utils/ByteUtils.java b/ard-common/src/main/java/com/ard/common/utils/ByteUtils.java
new file mode 100644
index 0000000..a744ebc
--- /dev/null
+++ b/ard-common/src/main/java/com/ard/common/utils/ByteUtils.java
@@ -0,0 +1,71 @@
+package com.ard.common.utils;
+/**
+ * 字节工具类
+ *
+ * @author ruoyi
+ */
+public class ByteUtils {
+
+    /**
+     * 将字节数组转换为十六进制字符串,每个字节以0x格式显示
+     * @param bytes 字节数组
+     * @return 格式化后的字符串
+     */
+    public static String bytesToHexString(byte[] bytes) {
+        StringBuilder sb = new StringBuilder();
+        for (byte b : bytes) {
+            sb.append(String.format("0x%02X ", b));
+        }
+        return sb.toString().trim();
+    }
+
+    /**
+     * 将字节数组转换为常规字符串
+     * @param bytes 字节数组
+     * @return 字符串
+     */
+    public static String bytesToString(byte[] bytes) {
+        return new String(bytes);
+    }
+
+    /**
+     * 将单个字节转换为0x十六进制格式字符串
+     * @param b 字节
+     * @return 0x格式的字符串
+     */
+    public static String byteToHex(byte b) {
+        return String.format("0x%02X", b);
+    }
+
+    /**
+     * 将十六进制字符串转换为字节数组
+     * @param hexString 十六进制字符串,支持0x前缀
+     * @return 字节数组
+     */
+    public static byte[] hexStringToBytes(String hexString) {
+        hexString = hexString.replaceAll("0x", "").replaceAll("\\s+", "");
+        int length = hexString.length();
+        byte[] data = new byte[length / 2];
+        for (int i = 0; i < length; i += 2) {
+            data[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4)
+                                 + Character.digit(hexString.charAt(i+1), 16));
+        }
+        return data;
+    }
+
+    /**
+     * 将字节数组转换为十六进制字符串,每个字节用空格分隔显示
+     * @param bytes 字节数组
+     * @return 格式化后的十六进制字符串
+     */
+    public static String bytesToHexWithSpaces(byte[] bytes) {
+        StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < bytes.length; i++) {
+            sb.append(String.format("%02X", bytes[i]));
+            if (i < bytes.length - 1) {
+                sb.append(" ");
+            }
+        }
+        return sb.toString();
+    }
+}
diff --git a/ard-work/src/main/java/com/ard/tianyu/controller/UavBaseController.java b/ard-work/src/main/java/com/ard/tianyu/controller/UavBaseController.java
index e7a70bc..9a5f5a1 100644
--- a/ard-work/src/main/java/com/ard/tianyu/controller/UavBaseController.java
+++ b/ard-work/src/main/java/com/ard/tianyu/controller/UavBaseController.java
@@ -14,7 +14,6 @@
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import org.springframework.web.bind.annotation.*;
-
 import javax.annotation.Resource;
 import java.util.List;
 
diff --git a/ard-work/src/main/java/com/ard/tianyu/netty/command/notice/UavReadyReplyCmd.java b/ard-work/src/main/java/com/ard/tianyu/netty/command/notice/UavReadyReplyCmd.java
index 6ec47f5..2d9d149 100644
--- a/ard-work/src/main/java/com/ard/tianyu/netty/command/notice/UavReadyReplyCmd.java
+++ b/ard-work/src/main/java/com/ard/tianyu/netty/command/notice/UavReadyReplyCmd.java
@@ -18,7 +18,8 @@
     private final double longitude;         // 经度
     private final double latitude;          // 纬度
     private final int altitude;             // 海拔高度
-    public UavReadyReplyCmd(String boxSn,byte batteryPower,double longitude,double latitude,int altitude) {
+
+    public UavReadyReplyCmd(String boxSn, byte batteryPower, double longitude, double latitude, int altitude) {
         setDataHeader((short) 0x6A77);      // 设置帧头
         setCmdCode((byte) 0x3D);            // 设置指令编号
         setDataLength((short) 39);          // 数据长度
diff --git a/ard-work/src/main/java/com/ard/tianyu/netty/handler/ClientHandler.java b/ard-work/src/main/java/com/ard/tianyu/netty/handler/ClientHandler.java
index 1bef005..35e8ad7 100644
--- a/ard-work/src/main/java/com/ard/tianyu/netty/handler/ClientHandler.java
+++ b/ard-work/src/main/java/com/ard/tianyu/netty/handler/ClientHandler.java
@@ -31,7 +31,7 @@
         InetSocketAddress ipSocket = (InetSocketAddress) ctx.channel().remoteAddress();
         String host = ipSocket.getHostString();
         int port = ipSocket.getPort();
-        tyService.processMessage(host + ":" + port, command);
+        tyService.processReplyMessage(host + ":" + port, command);
     }
 
     @Override
diff --git a/ard-work/src/main/java/com/ard/tianyu/netty/handler/MessageProtocolDecoder.java b/ard-work/src/main/java/com/ard/tianyu/netty/handler/MessageProtocolDecoder.java
index 27fe205..2b811f9 100644
--- a/ard-work/src/main/java/com/ard/tianyu/netty/handler/MessageProtocolDecoder.java
+++ b/ard-work/src/main/java/com/ard/tianyu/netty/handler/MessageProtocolDecoder.java
@@ -1,6 +1,7 @@
 package com.ard.tianyu.netty.handler;// MessageProtocolDecoder.java
 
-import com.ard.tianyu.netty.command.*;
+import com.ard.common.utils.ByteUtils;
+import com.ard.tianyu.netty.command.BaseCmd;
 import com.ard.tianyu.netty.command.camera.CameraModeReplyCmd;
 import com.ard.tianyu.netty.command.camera.CapturePicReplyCmd;
 import com.ard.tianyu.netty.command.camera.RecordStartReplyCmd;
@@ -16,11 +17,11 @@
 import com.ard.tianyu.netty.command.register.RegisterReplyCmd;
 import com.ard.tianyu.netty.command.register.UavInitReplyCmd;
 import com.ard.tianyu.netty.protobuf.TelemetryDataPB;
+import com.google.protobuf.InvalidProtocolBufferException;
 import io.netty.buffer.ByteBuf;
 import io.netty.channel.ChannelHandlerContext;
 import io.netty.handler.codec.ByteToMessageDecoder;
 import lombok.extern.slf4j.Slf4j;
-
 import java.util.List;
 
 @Slf4j
@@ -45,6 +46,7 @@
         }
         byte cmdCode = in.readByte();
         BaseCmd baseCmd = null;
+        byte actionCode;
         switch (cmdCode) {
             case 0x01:
                 byte success = in.readByte(); // 读取是否成功
@@ -56,13 +58,10 @@
                 baseCmd = new HeartbeatReplyCmd(timestamp);
                 log.debug("心跳回复: 时间戳 {}", timestamp);
                 break;
-            case 0x03:
-            case 0x04:
-                break;
             case 0x0A:
                 byte status = in.readByte();
                 baseCmd = new BoxPowerStatusReplyCmd(status);
-                log.debug("云盒开机/关机通知回复: 状态 {}", String.format("0x%02X", status & 0xFF));
+                log.debug("云盒开机/关机通知回复: 状态 {}", ByteUtils.byteToHex(status));
                 break;
             case (byte) 0xA8:
                 byte[] uavStatus = new byte[dataLength - 1];
@@ -72,181 +71,109 @@
                 log.debug("无人机状态数据: {}", uavState.getBoxSn());
                 break;
             case (byte) 0xA9:
-                byte[] uavData = new byte[dataLength - 1];
-                in.readBytes(uavData);
-                TelemetryDataPB.TelemetryData telemetryData = TelemetryDataPB.TelemetryData.parseFrom(uavData);
+                byte[] telemetryDataBytes = new byte[dataLength - 1];
+                in.readBytes(telemetryDataBytes);
+                TelemetryDataPB.TelemetryData telemetryData = TelemetryDataPB.TelemetryData.parseFrom(telemetryDataBytes);
                 baseCmd = new UavTelemetryDataCmd(telemetryData);
                 log.debug("遥测数据: {}", telemetryData.getBoxSn());
                 break;
             case (byte) 0x0C:
                 int delayTime = in.readInt();
-                uavData = new byte[15];
-                in.readBytes(uavData);
-                //  String boxSn12 = new String(uavData);
-                uavData = new byte[dataLength - 20];
-                in.readBytes(uavData);
-                TelemetryDataPB.SignalInfo signalInfo = TelemetryDataPB.SignalInfo.parseFrom(uavData);
+                byte[] signalInfoBytes = new byte[15];
+                in.readBytes(signalInfoBytes);
+                signalInfoBytes = new byte[dataLength - 20];
+                in.readBytes(signalInfoBytes);
+                TelemetryDataPB.SignalInfo signalInfo = TelemetryDataPB.SignalInfo.parseFrom(signalInfoBytes);
                 baseCmd = new SignalInfoCmd(signalInfo);
                 log.debug("信道质量数据: {}", delayTime);
                 break;
             case (byte) 0xD1:
-                byte encryptionFlag = in.readByte();
-                byte actionCode = in.readByte();
-                switch (actionCode) {
-                    case 0x11:
-                        byte result = in.readByte();
-                        int errorCode = in.readInt();
-                        uavData = new byte[15];
-                        in.readBytes(uavData);
-                        String boxSn = new String(uavData);
-                        baseCmd = new TakeOffReplyCmd(boxSn, result, errorCode);
-                        log.debug("起飞回复: {}", boxSn);
-                        break;
-                    case 0x12:
-                        result = in.readByte();
-                        errorCode = in.readInt();
-                        uavData = new byte[15];
-                        in.readBytes(uavData);
-                        boxSn = new String(uavData);
-                        baseCmd = new ReturnHomeReplyCmd(boxSn, result, errorCode);
-                        log.debug("返航回复: {}", boxSn);
-                        break;
-                    case 0x13:
-                        result = in.readByte();
-                        errorCode = in.readInt();
-                        uavData = new byte[15];
-                        in.readBytes(uavData);
-                        boxSn = new String(uavData);
-                        baseCmd = new ReturnHomeCancelReplyCmd(boxSn, result, errorCode);
-                        log.debug("取消返航回复: {}", boxSn);
-                        break;
-                    case 0x14:
-                        result = in.readByte();
-                        errorCode = in.readInt();
-                        uavData = new byte[15];
-                        in.readBytes(uavData);
-                        boxSn = new String(uavData);
-                        baseCmd = new LandReplyCmd(boxSn, result, errorCode);
-                        log.debug("降落回复: {}", boxSn);
-                        break;
-                    case 0x15:
-                        result = in.readByte();
-                        errorCode = in.readInt();
-                        uavData = new byte[15];
-                        in.readBytes(uavData);
-                        boxSn = new String(uavData);
-                        baseCmd = new LandCancelReplyCmd(boxSn, result, errorCode);
-                        log.debug("取消降落回复: {}", boxSn);
-                        break;
-                    case 0x29:
-                        result = in.readByte();
-                        errorCode = in.readInt();
-                        uavData = new byte[15];
-                        in.readBytes(uavData);
-                        boxSn = new String(uavData);
-                        baseCmd = new LandForcedReplyCmd(boxSn, result, errorCode);
-                        log.debug("强制降落回复: {}", boxSn);
-                        break;
-                    case 0x32:
-                        result = in.readByte();
-                        errorCode = in.readInt();
-                        uavData = new byte[15];
-                        in.readBytes(uavData);
-                        boxSn = new String(uavData);
-                        baseCmd = new EmergencyBrakeReplyCmd(boxSn, result, errorCode);
-                        log.debug("紧急制动回复: {}", boxSn);
-                        break;
-                    case 0x39:
-                        result = in.readByte();
-                        errorCode = in.readInt();
-                        uavData = new byte[15];
-                        in.readBytes(uavData);
-                        boxSn = new String(uavData);
-                        baseCmd = new PointControlReachedReplyCmd(boxSn, result, errorCode);
-                        log.debug("到达指点飞行位置回复: {}", boxSn);
-                        break;
-                    case 0x22:
-                        result = in.readByte();
-                        errorCode = in.readInt();
-                        uavData = new byte[15];
-                        in.readBytes(uavData);
-                        boxSn = new String(uavData);
-                        baseCmd = new CameraModeReplyCmd(boxSn, result, errorCode);
-                        log.debug("设置相机模式回复: {}", boxSn);
-                        break;
-                    case 0x23:
-                        result = in.readByte();
-                        errorCode = in.readInt();
-                        uavData = new byte[15];
-                        in.readBytes(uavData);
-                        boxSn = new String(uavData);
-                        baseCmd = new CapturePicReplyCmd(boxSn, result, errorCode);
-                        log.debug("拍照回复: {}", boxSn);
-                        break;
-                    case 0x24:
-                        result = in.readByte();
-                        errorCode = in.readInt();
-                        uavData = new byte[15];
-                        in.readBytes(uavData);
-                        boxSn = new String(uavData);
-                        baseCmd = new RecordStartReplyCmd(boxSn, result, errorCode);
-                        log.debug("开始录像回复: {}", boxSn);
-                        break;
-                    case 0x25:
-                        result = in.readByte();
-                        errorCode = in.readInt();
-                        uavData = new byte[15];
-                        in.readBytes(uavData);
-                        boxSn = new String(uavData);
-                        baseCmd = new RecordStopReplyCmd(boxSn, result, errorCode);
-                        log.debug("停止录像回复: {}", boxSn);
-                        break;
-                    case 0x2E:
-                        result = in.readByte();
-                        errorCode = in.readInt();
-                        uavData = new byte[15];
-                        in.readBytes(uavData);
-                        boxSn = new String(uavData);
-                        baseCmd = new FlyWayEndReplyCmd(boxSn, result, errorCode);
-                        log.debug("航线结束通知回复: {}", boxSn);
-                        break;
-                    case 0x3D:
-                        byte batteryPower = in.readByte();
-                        double longitude = in.readDouble();
-                        double latitude = in.readDouble();
-                        int altitude = in.readInt();
-                        uavData = new byte[dataLength - 24];
-                        in.readBytes(uavData);
-                        boxSn = new String(uavData);
-                        baseCmd = new UavReadyReplyCmd(boxSn, batteryPower, longitude, latitude, altitude);
-                        log.debug("无人机准备完成通知回复: 电池电量 {}", String.format("0x%02X", batteryPower & 0xFF));
-                        break;
-                    case 0x42:
-                        byte[] uavData1 = new byte[dataLength - 18];
-                        in.readBytes(uavData1);
-                        byte[] uavData2 = new byte[15];
-                        in.readBytes(uavData2);
-                        boxSn = new String(uavData2);
-                        TelemetryDataPB.UavInitInfo uavInitInfo = TelemetryDataPB.UavInitInfo.parseFrom(uavData1);
-                        baseCmd = new UavInitReplyCmd(boxSn, uavInitInfo);
-                        log.debug("无人机初始化数据: {}", boxSn);
-                        break;
-                    default:
-                        log.warn("无法识别的命令码动作编号:{}", String.format("0x%02X", actionCode & 0xFF));
-                        break;
-                }
+                in.readByte();//加密标志
+                actionCode = in.readByte();//动作编号
+                baseCmd = processD1ReplyCmd(in, actionCode);
                 break;
             default:
-                encryptionFlag = in.readByte();
+                in.readByte();//加密标志
                 actionCode = in.readByte();
-                log.warn("无法识别的命令码: {},加密标志:{},动作编号:{}",
-                        String.format("0x%02X", cmdCode & 0xFF),
-                        String.format("0x%02X", encryptionFlag & 0xFF),
-                        String.format("0x%02X", actionCode & 0xFF));//String.format("0x%02X", cmdCode & 0xFF)
-
+                log.warn("无法识别的命令码: {},动作编号:{}",
+                        ByteUtils.byteToHex(cmdCode),
+                        ByteUtils.byteToHex(actionCode)
+                );
         }
         if (baseCmd != null) {
             out.add(baseCmd);
         }
     }
+
+    //处理D1指令回复
+    private BaseCmd processD1ReplyCmd(ByteBuf in, byte actionCode) {
+        byte result = in.readByte();
+        int errorCode = in.readInt();
+        byte[] uavData = new byte[15];
+        in.readBytes(uavData);
+        String boxSn = new String(uavData);
+        switch (actionCode) {
+            case 0x11:
+                return new TakeOffReplyCmd(boxSn, result, errorCode);
+            case 0x12:
+                return new ReturnHomeReplyCmd(boxSn, result, errorCode);
+            case 0x13:
+                return new ReturnHomeCancelReplyCmd(boxSn, result, errorCode);
+            case 0x14:
+                return new LandReplyCmd(boxSn, result, errorCode);
+            case 0x15:
+                return new LandCancelReplyCmd(boxSn, result, errorCode);
+            case 0x29:
+                return new LandForcedReplyCmd(boxSn, result, errorCode);
+            case 0x32:
+                return new EmergencyBrakeReplyCmd(boxSn, result, errorCode);
+            case 0x39:
+                return new PointControlReachedReplyCmd(boxSn, result, errorCode);
+            case 0x22:
+                return new CameraModeReplyCmd(boxSn, result, errorCode);
+            case 0x23:
+                return new CapturePicReplyCmd(boxSn, result, errorCode);
+            case 0x24:
+                return new RecordStartReplyCmd(boxSn, result, errorCode);
+            case 0x25:
+                return new RecordStopReplyCmd(boxSn, result, errorCode);
+            case 0x2E:
+                return new FlyWayEndReplyCmd(boxSn, result, errorCode);
+            // Special cases
+            case 0x3D:
+            case 0x42:
+                return processSpecialD1ReplyCmd(in, actionCode, boxSn);
+            // Add other cases...
+            default:
+                log.warn("无法识别的动作编号:{}", ByteUtils.byteToHex(actionCode));
+        }
+        return null;
+    }
+
+    //处理特殊D1指令回复
+    private BaseCmd processSpecialD1ReplyCmd(ByteBuf in, byte actionCode, String boxSn) {
+        switch (actionCode) {
+            //无人机准备完成通知回复
+            case 0x3D:
+                byte batteryPower = in.readByte();
+                double longitude = in.readDouble();
+                double latitude = in.readDouble();
+                int altitude = in.readInt();
+                return new UavReadyReplyCmd(boxSn, batteryPower, longitude, latitude, altitude);
+            //无人机初始化信息回复
+            case 0x42:
+                byte[] uavData1 = new byte[in.readableBytes() - 15];
+                in.readBytes(uavData1);
+                TelemetryDataPB.UavInitInfo uavInitInfo;
+                try {
+                    uavInitInfo = TelemetryDataPB.UavInitInfo.parseFrom(uavData1);
+                } catch (InvalidProtocolBufferException e) {
+                    throw new RuntimeException(e);
+                }
+                return new UavInitReplyCmd(boxSn, uavInitInfo);
+            default:
+                return null;
+        }
+    }
+
 }
\ No newline at end of file
diff --git a/ard-work/src/main/java/com/ard/tianyu/netty/handler/MessageProtocolEncoder.java b/ard-work/src/main/java/com/ard/tianyu/netty/handler/MessageProtocolEncoder.java
index c4dca37..3ff7b6c 100644
--- a/ard-work/src/main/java/com/ard/tianyu/netty/handler/MessageProtocolEncoder.java
+++ b/ard-work/src/main/java/com/ard/tianyu/netty/handler/MessageProtocolEncoder.java
@@ -1,5 +1,6 @@
 package com.ard.tianyu.netty.handler;// MessageProtocolEncoder.java
 
+import com.ard.common.utils.ByteUtils;
 import com.ard.tianyu.netty.command.BaseCmd;
 import io.netty.buffer.ByteBuf;
 import io.netty.channel.ChannelHandlerContext;
@@ -25,11 +26,7 @@
         out.getBytes(out.readerIndex(), encodedBytes); // 读取ByteBuf中的字节到字节数组中
         // log.warn("Encoded message bytes: {}", Arrays.toString(encodedBytes));
         // 将字节数组转换为十六进制格式
-        StringBuilder hexString = new StringBuilder();
-        for (byte b : encodedBytes) {
-            hexString.append(String.format("%02X ", b)); // 将每个字节转换为两位十六进制并加上空格
-        }
-
-        log.warn("Encoded message in hex: {}", hexString.toString().trim());
+        String hexString = ByteUtils.bytesToHexWithSpaces(encodedBytes);
+        log.warn("Encoded message in hex: {}", hexString);
     }
 }
diff --git a/ard-work/src/main/java/com/ard/tianyu/service/ITyService.java b/ard-work/src/main/java/com/ard/tianyu/service/ITyService.java
index 612fcb2..c4f9e4c 100644
--- a/ard-work/src/main/java/com/ard/tianyu/service/ITyService.java
+++ b/ard-work/src/main/java/com/ard/tianyu/service/ITyService.java
@@ -193,7 +193,7 @@
     SignalInfo getSignalInfo(String boxSn);
 
     /**
-     * 解析天宇服务端发来的消息
+     * 处理回复消息
      */
-    void processMessage(String key, BaseCmd tyMessage);
+    void processReplyMessage(String key, BaseCmd tyMessage);
 }
diff --git a/ard-work/src/main/java/com/ard/tianyu/service/impl/TyServiceImpl.java b/ard-work/src/main/java/com/ard/tianyu/service/impl/TyServiceImpl.java
index 88d749c..c5cd5b7 100644
--- a/ard-work/src/main/java/com/ard/tianyu/service/impl/TyServiceImpl.java
+++ b/ard-work/src/main/java/com/ard/tianyu/service/impl/TyServiceImpl.java
@@ -1,5 +1,6 @@
 package com.ard.tianyu.service.impl;
 
+import com.ard.common.utils.ByteUtils;
 import com.ard.tianyu.config.TyConfiguration;
 import com.ard.tianyu.http.TyClient;
 import com.ard.tianyu.model.cache.UavSignalInfoCache;
@@ -47,6 +48,8 @@
 import java.net.InetSocketAddress;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
 
 /**
  * TyServiceImpl
@@ -63,6 +66,9 @@
 
     @Resource
     private TyConfiguration tyConfiguration;
+
+    // 存储每个无人机的最后遥测处理时间
+    private Map<String, Long> lastTelemetryTimes = new ConcurrentHashMap<>();
 
     /**
      * 获取天宇token信息
@@ -139,29 +145,12 @@
      */
     @Override
     public void registerMessage() {
-        AccessTokenReceiver tyToken = tyConfiguration.getAccessToken();
-        RegisterCmd registerMessage = new RegisterCmd(tyToken.getCompanyId(), tyToken.getAccessToken().getBytes());
-        this.sendMessage(tyConfiguration.getIpPort(), registerMessage);
-    }
-
-    /**
-     * 发送消息
-     */
-    public void sendMessage(String key, BaseCmd msg) {
         try {
-            ChannelFuture future = TyNettyTcpClient.channels.get(key).getChannelFuture();
-            Channel channel = future.channel();
-            if (channel.isActive()) {
-                InetSocketAddress ipSocket = (InetSocketAddress) channel.remoteAddress();
-                String host = ipSocket.getHostString();
-                int port = ipSocket.getPort();
-                channel.writeAndFlush(msg); // 发送编码后的数据
-                log.debug("向天宇服务器【{}:{}】发送数据,命令码:{}", host, port, String.format("0x%02X", msg.getCmdCode() & 0xFF));
-            } else {
-                log.error("与天宇服务器链接断开,无法发送数据!");
-            }
+            AccessTokenReceiver tyToken = tyConfiguration.getAccessToken();
+            RegisterCmd registerMessage = new RegisterCmd(tyToken.getCompanyId(), tyToken.getAccessToken().getBytes());
+            this.sendMessage(tyConfiguration.getIpPort(), registerMessage);
         } catch (Exception e) {
-            log.error("发送消息异常:{}", e.getMessage());
+            log.error("注册天宇平台失败:{}", e.getMessage());
         }
     }
 
@@ -366,7 +355,7 @@
      */
     @Override
     public void emeragencyBrake(EmeragencyBrakeDTO emeragencyBrakeDTO) {
-        EmergencyBrakeCmd emergencyBrakeCmd=new EmergencyBrakeCmd(emeragencyBrakeDTO);
+        EmergencyBrakeCmd emergencyBrakeCmd = new EmergencyBrakeCmd(emeragencyBrakeDTO);
         this.sendMessage(tyConfiguration.getIpPort(), emergencyBrakeCmd);
     }
 
@@ -398,7 +387,7 @@
      * 处理天宇服务器返回的消息
      */
     @Override
-    public void processMessage(String key, BaseCmd tyCommand) {
+    public void processReplyMessage(String key, BaseCmd tyCommand) {
         byte cmdCode = tyCommand.getCmdCode();
         switch (cmdCode) {
             case 0x01:
@@ -438,10 +427,25 @@
             case (byte) 0xA9:
                 // 处理无人机遥测消息
                 UavTelemetryDataCmd uavTelemetryDataCmd = (UavTelemetryDataCmd) tyCommand;
-                TelemetryData telemetryData = UavTelemetryDataConverter.convertProtoToEntity(uavTelemetryDataCmd.getTelemetryData());
-                UavTelemetryDataCache.putUavTelemetryData(telemetryData);
-                logPrint("无人机遥测", telemetryData.getBoxSn());
+                String boxSn = ByteUtils.bytesToString(uavTelemetryDataCmd.getBoxSn()); // 假设有获取无人机ID的方法
+                long currentTime = System.currentTimeMillis();
+
+                // 获取无人机的最后处理时间,如果没有则设置为0
+                long lastTelemetryTime = lastTelemetryTimes.getOrDefault(boxSn, 0L);
+
+                // 检查与上次处理时间的间隔
+                if (currentTime - lastTelemetryTime >= 1000) { // 1秒
+                    TelemetryData telemetryData = UavTelemetryDataConverter.convertProtoToEntity(uavTelemetryDataCmd.getTelemetryData());
+                    UavTelemetryDataCache.putUavTelemetryData(telemetryData);
+                    logPrint("无人机遥测", telemetryData.getBoxSn());
+
+                    // 更新最后处理时间
+                    lastTelemetryTimes.put(boxSn, currentTime);
+                } else {
+                    log.debug("无人机 " + boxSn + " 遥测数据接收过于频繁,已跳过处理");
+                }
                 break;
+
             case (byte) 0x0C:
                 // 处理无人机信道质量数据
                 SignalInfoCmd signalInfoCmd = (SignalInfoCmd) tyCommand;
@@ -524,7 +528,7 @@
                 break;
             default:
                 // 处理其他消息
-                log.debug("收到其他消息-->其他消息");
+                log.warn("收到其他消息-->{}", tyCommand.getCmdCode());
         }
     }
 
@@ -537,7 +541,7 @@
     private void logPrint(String message, byte result, Integer errorCode) {
         log.info("收到{}回复:{} 错误码:{}【{}】",
                 message,
-                String.format("0x%02X", result & 0xFF),
+                ByteUtils.byteToHex(result),
                 errorCode,
                 ErrorCodeEnum.getDescByCode(errorCode));
     }
@@ -552,4 +556,25 @@
         HeartbeatCmd heartbeatMessage = new HeartbeatCmd(timestamp);
         this.sendMessage(tyConfiguration.getIpPort(), heartbeatMessage);
     }
+
+    /**
+     * 发送消息
+     */
+    private void sendMessage(String key, BaseCmd msg) {
+        try {
+            ChannelFuture future = TyNettyTcpClient.channels.get(key).getChannelFuture();
+            Channel channel = future.channel();
+            if (channel.isActive()) {
+                InetSocketAddress ipSocket = (InetSocketAddress) channel.remoteAddress();
+                String host = ipSocket.getHostString();
+                int port = ipSocket.getPort();
+                channel.writeAndFlush(msg); // 发送编码后的数据
+                log.debug("向天宇服务器【{}:{}】发送数据,命令码:{}", host, port, String.format("0x%02X", msg.getCmdCode() & 0xFF));
+            } else {
+                log.error("与天宇服务器链接断开,无法发送数据!");
+            }
+        } catch (Exception e) {
+            log.error("发送消息异常:{}", e.getMessage());
+        }
+    }
 }
\ No newline at end of file

--
Gitblit v1.9.3