ard-work/src/main/java/com/ard/work/component/netty/TyTcpClientManager.java
@@ -53,7 +53,7 @@ @Override protected void initChannel(SocketChannel socketChannel) { ChannelPipeline pipeline = socketChannel.pipeline(); pipeline.addLast("heart", new IdleStateHandler(5, 5, 0, TimeUnit.SECONDS)); pipeline.addLast("heart", new IdleStateHandler(0, 5, 0, TimeUnit.SECONDS)); pipeline.addLast("encoder", new MessageProtocolEncoder()); pipeline.addLast("decoder", new MessageProtocolDecoder()); pipeline.addLast("handler", clientHandler); ard-work/src/main/java/com/ard/work/component/netty/handler/ClientHandler.java
@@ -58,21 +58,26 @@ public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { if (evt instanceof IdleStateEvent) { IdleStateEvent event = (IdleStateEvent) evt; long timestamp = System.currentTimeMillis(); switch (event.state()) { case READER_IDLE: log.debug("读空闲超时 - 可能服务器未响应"); ctx.close(); // <-- 必须加这句 //log.warn("读空闲超时 - 可能服务器未响应"); break; case WRITER_IDLE: // 写空闲时主动发心跳 HeartbeatCmd heartbeat = new HeartbeatCmd(timestamp); ctx.writeAndFlush(heartbeat); log.debug("写空闲 -> 发送心跳包 时间戳={}", timestamp); try { HeartbeatCmd heartbeat = new HeartbeatCmd(System.currentTimeMillis()); ctx.writeAndFlush(heartbeat).addListener(future -> { if (!future.isSuccess()) { log.error("写心跳失败,网络断开,关闭连接"); ctx.close(); } }); } catch (Exception e) { log.error("发送心跳异常", e); ctx.close(); } break; case ALL_IDLE: log.debug("读写都空闲 - 可考虑关闭连接或重连"); log.warn("读写都空闲 - 可考虑关闭连接或重连"); break; } } else { ard-work/src/main/java/com/ard/work/domain/entity/ArdDroneInfo.java
@@ -107,15 +107,4 @@ */ private String webrtcUrl; /** * 判断两个无人机对象的属性是否相同 */ public boolean isSameAs(BoxInfoReceiver other) { return Objects.equals(this.boxName, other.getBoxName()) && Objects.equals(this.boxVersion, other.getBoxVersion()) && Objects.equals(this.lastTaskId, other.getLastTaskId()) && Objects.equals(this.onLine, other.getOnLine()); // 对比其他属性 } } ard-work/src/main/java/com/ard/work/service/impl/ArdDroneInfoServiceImpl.java
@@ -299,41 +299,52 @@ updateArdDrone(ArdDroneInfo.builder().serverId(server.getId()).onLine(0).build()); continue; } boxList.forEach(remote -> { for (BoxInfoReceiver remote : boxList) { String boxSn = remote.getBoxSn(); // ✅ 维护在线状态缓存 // 只有在线的无人机才存 Redis String redisKey = CacheConstants.UAV_ONLINE_KEY + boxSn; // 只处理在线的 Redis if (remote.getOnLine() == 1) { redisCache.setCacheObject(redisKey, remote, 30, TimeUnit.SECONDS); } else { redisCache.deleteObject(CacheConstants.UAV_ONLINE_KEY + boxSn); redisCache.deleteObject(redisKey); } // 数据库同步 ArdDroneInfo local = localMap.get(boxSn); if (local != null && !local.isSameAs(remote)) { updateChangedAttributes(local, remote); updateArdDrone(local); if (local == null) continue; if (updateChangedAttributes(local, remote)) { updateArdDrone(local); // 只有真的有变化才更新数据库 } }); } } } /** * 更新 localBoxInfo 的字段,如果有变化返回 true,否则返回 false */ private boolean updateChangedAttributes(ArdDroneInfo localBoxInfo, BoxInfoReceiver remoteArdDrone) { boolean changed = false; // 更新变化的属性 private void updateChangedAttributes(ArdDroneInfo localBoxInfo, BoxInfoReceiver remoteArdDrone) { if (!Objects.equals(localBoxInfo.getBoxName(), remoteArdDrone.getBoxName())) { localBoxInfo.setBoxName(remoteArdDrone.getBoxName()); changed = true; } if (!Objects.equals(localBoxInfo.getBoxVersion(), remoteArdDrone.getBoxVersion())) { localBoxInfo.setBoxVersion(remoteArdDrone.getBoxVersion()); changed = true; } if (!Objects.equals(localBoxInfo.getLastTaskId(), remoteArdDrone.getLastTaskId())) { localBoxInfo.setLastTaskId(remoteArdDrone.getLastTaskId()); changed = true; } if (!Objects.equals(localBoxInfo.getOnLine(), remoteArdDrone.getOnLine())) { localBoxInfo.setOnLine(remoteArdDrone.getOnLine()); changed = true; } // 更新其他属性 // TODO: 更新其他属性时,如果变化也设置 changed = true return changed; } }