From 2b43275bd260eda468f305ebca4b4f4291b0605d Mon Sep 17 00:00:00 2001
From: liusuyi <1951119284@qq.com>
Date: Wed, 23 Oct 2024 14:50:33 +0800
Subject: [PATCH] 优化netty连接

---
 ard-work/src/main/java/com/ard/tianyu/netty/handler/ClientHandler.java          |    8 +-
 /dev/null                                                                       |   39 ---------
 ard-work/src/main/java/com/ard/tianyu/netty/TyNettyTcpClient.java               |   50 ++++++------
 ard-work/src/main/java/com/ard/tianyu/netty/handler/MessageProtocolDecoder.java |    7 +
 ard-work/src/main/java/com/ard/tianyu/netty/command/SubscribeCommand.java       |   26 ++++++
 ard-work/src/main/java/com/ard/tianyu/service/impl/TyServiceImpl.java           |   23 +++++
 ard-work/src/main/java/com/ard/tianyu/controller/UavController.java             |    7 +
 ard-work/src/main/java/com/ard/tianyu/service/ITyService.java                   |    6 +
 ard-work/src/main/java/com/ard/tianyu/netty/command/SubscribeReplyCommand.java  |   26 ++++++
 ard-work/src/main/java/com/ard/tianyu/netty/TyBoxSession.java                   |    2 
 10 files changed, 123 insertions(+), 71 deletions(-)

diff --git a/ard-work/src/main/java/com/ard/tianyu/controller/UavController.java b/ard-work/src/main/java/com/ard/tianyu/controller/UavController.java
index 23488fe..aa35cba 100644
--- a/ard-work/src/main/java/com/ard/tianyu/controller/UavController.java
+++ b/ard-work/src/main/java/com/ard/tianyu/controller/UavController.java
@@ -69,7 +69,12 @@
         Boolean state = tyService.updateBoxSettings(boxSettingsDTO);
         return AjaxResult.success(state);
     }
-
+    @ApiOperation("无人机控制订阅")
+    @GetMapping("/uavControlSubscribe")
+    public AjaxResult uavControlSubscribe(String boxSn) {
+        tyService.uavControlSubscribe(boxSn);
+        return AjaxResult.success();
+    }
     @ApiOperation("云台转动(基于角度)")
     @GetMapping("/controlAngle")
     public AjaxResult controlAngle(String boxSn) {
diff --git a/ard-work/src/main/java/com/ard/tianyu/netty/NettyConfig.java b/ard-work/src/main/java/com/ard/tianyu/netty/NettyConfig.java
deleted file mode 100644
index 304caa2..0000000
--- a/ard-work/src/main/java/com/ard/tianyu/netty/NettyConfig.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package com.ard.tianyu.netty;
-
-import com.ard.tianyu.config.TyConfiguration;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.stereotype.Component;
-import javax.annotation.PostConstruct;
-import javax.annotation.Resource;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-@Component
-@Slf4j
-public class NettyConfig {
-
-    @Resource
-    private TyConfiguration tianyuConfiguration;
-
-    @Resource
-    private TyNettyTcpClient tyNettyTcpClient;
-
-    @PostConstruct
-    public void createTyConnect() {
-        try {
-            // 将Tcp访问的IP和地址加入到字典
-            Map<String,Object> mapParam =new HashMap<String, Object>();
-            mapParam.put("IP",tianyuConfiguration.getTcpserver());
-            mapParam.put("PORT",tianyuConfiguration.getTcpport());
-
-            //要么从数据库查询信息,要么从配置文件读取信息
-            List<Map<String, Object>> list = new ArrayList<>();
-            list.add(mapParam);
-            tyNettyTcpClient.initAllChannel(list);
-        }catch (Exception e) {
-            e.printStackTrace();
-        }
-    }
-}
diff --git a/ard-work/src/main/java/com/ard/tianyu/netty/TyBoxSession.java b/ard-work/src/main/java/com/ard/tianyu/netty/TyBoxSession.java
index 9173c53..eb82f17 100644
--- a/ard-work/src/main/java/com/ard/tianyu/netty/TyBoxSession.java
+++ b/ard-work/src/main/java/com/ard/tianyu/netty/TyBoxSession.java
@@ -14,7 +14,7 @@
 
     public String subBoxSn;
 
-    public ChannelFuture future;
+    public ChannelFuture channelFuture;
 
     public Boolean isReConnect;
 
diff --git a/ard-work/src/main/java/com/ard/tianyu/netty/TyNettyTcpClient.java b/ard-work/src/main/java/com/ard/tianyu/netty/TyNettyTcpClient.java
index 02f2fa7..08065a6 100644
--- a/ard-work/src/main/java/com/ard/tianyu/netty/TyNettyTcpClient.java
+++ b/ard-work/src/main/java/com/ard/tianyu/netty/TyNettyTcpClient.java
@@ -1,5 +1,6 @@
 package com.ard.tianyu.netty;
 
+import com.ard.tianyu.config.TyConfiguration;
 import com.ard.tianyu.netty.handler.ClientHandler;
 import com.ard.tianyu.netty.handler.MessageProtocolDecoder;
 import com.ard.tianyu.netty.handler.MessageProtocolEncoder;
@@ -12,10 +13,9 @@
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Component;
 
+import javax.annotation.PostConstruct;
 import javax.annotation.Resource;
-import java.net.InetSocketAddress;
 import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
 import java.util.concurrent.TimeUnit;
 
@@ -28,17 +28,16 @@
     EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
 
     @Resource
+    private TyConfiguration tyConfiguration;
+    @Resource
     ClientHandler clientHandler;
 
     /**
      * 初始化Bootstrap
      */
-    public Bootstrap getBootstrap(EventLoopGroup group) {
-        if (null == group) {
-            group = eventLoopGroup;
-        }
+    private Bootstrap getBootstrap() {
         Bootstrap bootstrap = new Bootstrap();
-        bootstrap.group(group)
+        bootstrap.group(eventLoopGroup)
                 .channel(NioSocketChannel.class)
                 .option(ChannelOption.TCP_NODELAY, true)
                 .option(ChannelOption.SO_KEEPALIVE, true)
@@ -55,28 +54,21 @@
         return bootstrap;
     }
 
-    //   获取所有连接
-    public void initAllChannel(List<Map<String, Object>> portHosts) {
-        for (Map<String, Object> map : portHosts) {
-            String host = (String) map.get("IP");
-            Integer port = (Integer) map.get("PORT");
-            initOneConnection(host, port);
-        }
-    }
-
-    public void initOneConnection(String host, Integer port) {
+    /**
+     * 初始化连接
+     */
+    public void initConnection(String host, Integer port) {
 
         log.info("初始化连接天宇tcp服务器【{}:{}】", host, port);
-        //判断该账号下,是否有盒子被控制
-        //当前正在被控制的盒子
         String currentBoxSn = "";
+        //判断是否已经存在连接,如果存在则关闭之前的连接
         if (channels.containsKey(host + ":" + port)) {
             currentBoxSn = channels.get(host + ":" + port).getSubBoxSn();
-            channels.get(host + ":" + port).getFuture().channel().close();
+            channels.get(host + ":" + port).getChannelFuture().channel().close();
         }
 
         //异步连接tcp服务端
-        Bootstrap bootstrap = getBootstrap(null);
+        Bootstrap bootstrap = getBootstrap();
         ChannelFuture future = bootstrap.connect(host, port).addListener((ChannelFuture futureListener) -> {
             if (futureListener.isSuccess()) {
                 log.info("连接天宇TCP服务器成功【{}:{}】", host, port);
@@ -85,16 +77,24 @@
                 eventLoop.schedule(() -> {
                     log.info("连接天宇TCP服务器失败【{}:{}】,正尝试重连...", host, port);
                     try {
-                        initOneConnection(host, port);
+                        initConnection(host, port);
                     } catch (Exception e) {
                         e.printStackTrace();
                     }
                 }, 5, TimeUnit.SECONDS);
             }
         });
+        //将连接存入集合
+        channels.put(host + ":" + port, TyBoxSession.builder().subBoxSn(currentBoxSn).channelFuture(future).isReConnect(!currentBoxSn.equals("")).build());
+    }
 
-        //判断是否有盒子被订阅
-        channels.put(host + ":" + port, TyBoxSession.builder().subBoxSn(currentBoxSn).future(future)
-                .isReConnect(!currentBoxSn.equals("")).build());
+    //创建天宇连接
+    @PostConstruct
+    public void createTyConnect() {
+        try {
+            initConnection(tyConfiguration.getTcpserver(), tyConfiguration.getTcpport());
+        } catch (Exception e) {
+            log.error("创建TCP连接异常:{}", e.getMessage());
+        }
     }
 }
\ No newline at end of file
diff --git a/ard-work/src/main/java/com/ard/tianyu/netty/command/SubscribeCommand.java b/ard-work/src/main/java/com/ard/tianyu/netty/command/SubscribeCommand.java
new file mode 100644
index 0000000..962e88a
--- /dev/null
+++ b/ard-work/src/main/java/com/ard/tianyu/netty/command/SubscribeCommand.java
@@ -0,0 +1,26 @@
+package com.ard.tianyu.netty.command;
+
+import io.netty.buffer.ByteBuf;
+import lombok.Data;
+
+@Data
+public class SubscribeCommand extends BaseCommand {
+
+    //云盒SN号
+    private String BoxSn;
+
+    public SubscribeCommand(String BoxSn) {
+        setDataHeader((short) 0x7479);                        // 设置帧头
+        setDataLength((short) (6 + BoxSn.getBytes().length)); // 数据长度
+        setCmdCode((byte) 0x03);                              // 设置命令编号
+        this.BoxSn = BoxSn;
+    }
+
+    @Override
+    public void encode(ByteBuf out) {
+        out.writeShort(getDataHeader());    // 写入帧头
+        out.writeShort(getDataLength());    // 写入数据长度
+        out.writeByte(getCmdCode());        // 写入指令编号
+        out.writeBytes(BoxSn.getBytes());   // 写入云盒SN号
+    }
+}
\ No newline at end of file
diff --git a/ard-work/src/main/java/com/ard/tianyu/netty/command/SubscribeReplyCommand.java b/ard-work/src/main/java/com/ard/tianyu/netty/command/SubscribeReplyCommand.java
new file mode 100644
index 0000000..62cb5c7
--- /dev/null
+++ b/ard-work/src/main/java/com/ard/tianyu/netty/command/SubscribeReplyCommand.java
@@ -0,0 +1,26 @@
+package com.ard.tianyu.netty.command;
+
+import io.netty.buffer.ByteBuf;
+import lombok.Data;
+
+@Data
+public class SubscribeReplyCommand extends BaseCommand {
+
+    //云盒SN号
+    private String BoxSn;
+
+    public SubscribeReplyCommand(String BoxSn) {
+        setDataHeader((short) 0x6A77); // 设置帧头
+        setDataLength((short) (6 + BoxSn.getBytes().length)); // 数据长度
+        setCmdCode((byte) 0x03); // 设置命令编号
+        this.BoxSn = BoxSn;
+    }
+
+    @Override
+    public void encode(ByteBuf out) {
+        out.writeShort(getDataHeader());    // 写入帧头
+        out.writeShort(getDataLength());    // 写入数据长度
+        out.writeByte(getCmdCode());        // 写入指令编号
+        out.writeBytes(BoxSn.getBytes());   // 写入云盒SN号
+    }
+}
\ No newline at end of file
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 3fc7b5f..a84e551 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
@@ -56,9 +56,9 @@
             if (event.state() == IdleState.READER_IDLE) {
                 log.info("客户端读超时");
             } else if (event.state() == IdleState.WRITER_IDLE) {
-                log.info("写空闲发送⼼跳!");
-                HeartbeatCommand msg = new HeartbeatCommand(System.currentTimeMillis());
-                ctx.writeAndFlush(msg);
+              //  log.info("写空闲发送⼼跳!");
+               // HeartbeatCommand msg = new HeartbeatCommand(System.currentTimeMillis());
+                //ctx.writeAndFlush(msg);
             } else if (event.state() == IdleState.ALL_IDLE) {
                 log.info("客户端所有操作超时");
             }
@@ -75,7 +75,7 @@
         ctx.channel().eventLoop().schedule(() -> {
             log.error("天宇服务端链接不上,开始重连操作...");
             try {
-                tyNettyTcpClient.initOneConnection(host, port);
+                tyNettyTcpClient.initConnection(host, port);
             } catch (Exception e) {
                 log.error("天宇服务端连接异常: {}", e.getMessage());
             }
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 4dcb9e0..2867a9b 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
@@ -42,6 +42,13 @@
                 baseCommand = new HeartbeatReplyCommand(timestamp);
                 log.debug("心跳回复: 时间戳 {}", timestamp);
                 break;
+            case 0x03:
+            case 0x04:
+                byte[] boxSn = new byte[dataLength - 1];
+                in.readBytes(boxSn);
+                SubscribeCommand payload = new SubscribeCommand(new String(boxSn));
+                log.debug("订阅回复: {}", payload.getBoxSn());
+                break;
             case (byte) 0xA8:
                 byte[] uavStatus = new byte[dataLength - 1];
                 in.readBytes(uavStatus);  // 读取 ProtoBuf 数据
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 85f64d5..55d919d 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
@@ -58,6 +58,12 @@
      * 注册
      */
     void registerMessage();
+
+    /**
+     * 无人机控制订阅
+     */
+    void uavControlSubscribe(String boxSn);
+
     /**
      * 云台转动(基于角度)
      */
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 b18e6d8..9ec76ae 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
@@ -119,11 +119,19 @@
     }
 
     /**
+     * 无人机控制订阅
+     */
+    public void uavControlSubscribe(String boxSn) {
+        SubscribeCommand subscribeCommand = new SubscribeCommand(boxSn);
+        this.sendMessage(tyConfiguration.getIpPort(), subscribeCommand);
+    }
+
+    /**
      * 发送消息
      */
     public void sendMessage(String key, BaseCommand msg) {
         try {
-            ChannelFuture future = TyNettyTcpClient.channels.get(key).getFuture();
+            ChannelFuture future = TyNettyTcpClient.channels.get(key).getChannelFuture();
             Channel channel = future.channel();
             if (channel.isActive()) {
                 InetSocketAddress ipSocket = (InetSocketAddress) channel.remoteAddress();
@@ -142,6 +150,9 @@
         }
     }
 
+    /**
+     * 云台控制基于角度
+     */
     @Override
     public void controlAngle(String boxSn) {
         ControlAngleCommand controlAngleCommand = new ControlAngleCommand(boxSn.getBytes(), (byte) 0x00, (byte) 0x00, (byte) 0x05);
@@ -167,6 +178,16 @@
                 HeartbeatReplyCommand heartbeatReplyCommand = (HeartbeatReplyCommand) tyCommand;
                 log.info("收到心跳消息-->处理心跳消息{}", heartbeatReplyCommand.getTimestamp());
                 break;
+            case 0x03:
+                // 处理订阅消息
+                SubscribeCommand subscribeCommand = (SubscribeCommand) tyCommand;
+                log.info("收到订阅消息-->处理订阅消息{}", subscribeCommand.getBoxSn());
+                break;
+            case 0x04:
+                // 处理取消订阅消息
+                subscribeCommand = (SubscribeCommand) tyCommand;
+                log.info("收到取消订阅消息-->处理取消订阅消息{}", subscribeCommand.getBoxSn());
+                break;
             case (byte) 0xA8:
                 // 处理无人机状态消息
                 log.info("收到无人机状态消息-->无人机状态消息");

--
Gitblit v1.9.3