diff --git a/wms-webapi/src/main/java/top/wms/admin/controller/tcp/config/SimpleRequestMatcher.java b/wms-webapi/src/main/java/top/wms/admin/controller/tcp/config/SimpleRequestMatcher.java index fc39cf1..12dd8a8 100644 --- a/wms-webapi/src/main/java/top/wms/admin/controller/tcp/config/SimpleRequestMatcher.java +++ b/wms-webapi/src/main/java/top/wms/admin/controller/tcp/config/SimpleRequestMatcher.java @@ -23,11 +23,10 @@ public class SimpleRequestMatcher { public String waitForResponse(int timeoutSeconds) { isWaiting = true; try { - log.info("等待响应, 超时={}秒", timeoutSeconds); // 从队列取响应,最多等待timeoutSeconds秒 String response = responseQueue.poll(timeoutSeconds, TimeUnit.SECONDS); + log.info("waitForResponse-收到响应: {}", response); if (response != null) { - log.info("收到响应: {}", response); return response; } else { log.error("等待响应超时"); @@ -46,10 +45,15 @@ public class SimpleRequestMatcher { */ public void handleResponse(String response) { try { + log.info("开始处理响应: {}", response); // 如果有请求在等待,把响应放入队列 if (isWaiting) { - responseQueue.offer(response); - log.info("响应接收成功: {}", response); + boolean offer = responseQueue.offer(response); + if (offer) { + log.info("响应接收成功: {}", response); + } else { + log.error("响应队列已满, 响应被丢弃: {}", response); + } } else { log.warn("没有正在等待的请求, 响应被丢弃: {}", response); } @@ -66,4 +70,4 @@ public class SimpleRequestMatcher { isWaiting = false; log.info("请求匹配器已清空"); } -} +} \ No newline at end of file diff --git a/wms-webapi/src/main/java/top/wms/admin/controller/tcp/handler/TcpServerHandler.java b/wms-webapi/src/main/java/top/wms/admin/controller/tcp/handler/TcpServerHandler.java index 0c7f948..4700521 100644 --- a/wms-webapi/src/main/java/top/wms/admin/controller/tcp/handler/TcpServerHandler.java +++ b/wms-webapi/src/main/java/top/wms/admin/controller/tcp/handler/TcpServerHandler.java @@ -15,14 +15,30 @@ public class TcpServerHandler extends SimpleChannelInboundHandler { private ChannelManager getChannelManager() { if (channelManager == null) { - channelManager = SpringContextUtil.getBean(ChannelManager.class); + try { + channelManager = SpringContextUtil.getBean(ChannelManager.class); + log.info("ChannelManager获取成功: {}", channelManager); + } catch (Exception e) { + log.error("ChannelManager获取失败: ", e); + throw e; + } + } else { + log.info("ChannelManager已存在: {}", channelManager); } return channelManager; } private SimpleRequestMatcher getRequestMatcher() { if (requestMatcher == null) { - requestMatcher = SpringContextUtil.getBean(SimpleRequestMatcher.class); + try { + requestMatcher = SpringContextUtil.getBean(SimpleRequestMatcher.class); + log.info("SimpleRequestMatcher获取成功: {}", requestMatcher); + } catch (Exception e) { + log.error("SimpleRequestMatcher获取失败:", e); + throw e; + } + } else { + log.info("SimpleRequestMatcher已存在: {}", requestMatcher); } return requestMatcher; } @@ -34,21 +50,33 @@ public class TcpServerHandler extends SimpleChannelInboundHandler { @Override public void channelActive(ChannelHandlerContext ctx) { String clientId = getClientId(ctx); - getChannelManager().addChannel(clientId, ctx.channel()); - log.info("✅ VM客户端连接成功: {}", clientId); + try { + // 清空缓冲区,避免之前的消息残留 + ctx.channel().read(); + + getChannelManager().addChannel(clientId, ctx.channel()); + log.info("VM客户端连接成功: {}", clientId); + } catch (Exception e) { + log.error("处理客户端连接失败: ", e); + } } @Override public void channelInactive(ChannelHandlerContext ctx) { String clientId = getClientId(ctx); - getChannelManager().removeChannel(clientId); - log.info("❌ VM客户端断开连接: {}", clientId); + try { + ChannelManager manager = getChannelManager(); + manager.removeChannel(clientId); + log.info("VM客户端断开连接: {}", clientId); + } catch (Exception e) { + log.error("处理客户端断开连接失败:", e); + } } @Override protected void channelRead0(ChannelHandlerContext ctx, String msg) { String clientId = getClientId(ctx); - log.info("📥 收到VM数据 [{}]: {}", clientId, msg); + log.info("收到VM数据 [{}]: {}", clientId, msg); try { // 直接把收到的消息交给匹配器(不解析,不匹配) @@ -64,4 +92,4 @@ public class TcpServerHandler extends SimpleChannelInboundHandler { log.error("连接异常: {}", cause.getMessage()); ctx.close(); } -} +} \ No newline at end of file diff --git a/wms-webapi/src/main/java/top/wms/admin/controller/tcp/service/CommandService.java b/wms-webapi/src/main/java/top/wms/admin/controller/tcp/service/CommandService.java index 642d24d..bd1bc40 100644 --- a/wms-webapi/src/main/java/top/wms/admin/controller/tcp/service/CommandService.java +++ b/wms-webapi/src/main/java/top/wms/admin/controller/tcp/service/CommandService.java @@ -60,10 +60,11 @@ public class CommandService { @Autowired private ChannelManager channelManager; + /** + * 001流程是执行保存图片到本地 + */ // @Scheduled(cron = "*/1 * * * * ?") public void sendAndWait() { - // 1. 检查连接 - log.info("查询时间========"); Channel channel = channelManager.getFirstChannel(); channel.writeAndFlush("001"); } diff --git a/wms-webapi/src/main/java/top/wms/admin/controller/vm/VmCommandController.java b/wms-webapi/src/main/java/top/wms/admin/controller/vm/VmCommandController.java index aaaa9a4..ea42941 100644 --- a/wms-webapi/src/main/java/top/wms/admin/controller/vm/VmCommandController.java +++ b/wms-webapi/src/main/java/top/wms/admin/controller/vm/VmCommandController.java @@ -1,27 +1,14 @@ package top.wms.admin.controller.vm; -import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson2.JSONObject; import io.netty.channel.Channel; import lombok.extern.slf4j.Slf4j; -import org.dromara.x.file.storage.core.FileInfo; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.mock.web.MockMultipartFile; import org.springframework.web.bind.annotation.*; -import org.springframework.web.multipart.MultipartFile; import top.continew.starter.core.validation.CheckUtils; import top.wms.admin.controller.tcp.config.SimpleRequestMatcher; import top.wms.admin.controller.tcp.manager.ChannelManager; -import top.wms.admin.system.service.FileService; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.time.LocalDate; -import java.time.format.DateTimeFormatter; @Slf4j @RestController @@ -34,128 +21,25 @@ public class VmCommandController { @Autowired private SimpleRequestMatcher requestMatcher; - @Autowired - private FileService fileService; + @PostMapping("/send") + public String sendAndWait(@RequestBody JSONObject js) { + String msg = js.getString("msg"); + log.info("开始比对: {}", msg); - @GetMapping("/send") - public String sendAndWait(@RequestParam String msg) { // 1. 检查连接 Channel channel = channelManager.getFirstChannel(); if (channel == null) { return "ERROR: VM未连接"; } - String sendMsg = msg; - channel.writeAndFlush(sendMsg); - log.info("发送指令: {}", sendMsg); + // 2. 清空之前的响应队列,避免影响当前请求 + requestMatcher.clear(); + channel.writeAndFlush(msg); // 3. 等待响应 String response = requestMatcher.waitForResponse(20); + log.info("sendAndWait-收到响应: {}", response); CheckUtils.throwIf("TIMEOUT".equals(response), "响应超时,请重试"); - if (StrUtil.equals(response, "success") || StrUtil.equals(response, "failed")) { - return response; - } - if (StrUtil.equals(response, msg)) { - response = "success"; - } else { - response = "failed"; - } - // 4. 返回结果 - return response; // 直接返回VM的响应 - } - - // 基础路径 - private static final String BASE_PATH = "C:/Users/14725/Desktop/material"; - - // 固定照片名称 - private static final String PHOTO_NAME = "001.bmp"; - - /** - * 获取最新的001.bmp照片 - * - * @return 图片文件 - */ - /*@GetMapping("/latest-photo") - public ResponseEntity getLatestPhoto() { - try { - // 获取当前日期 - LocalDate now = LocalDate.now(); - String yearMonth = now.format(DateTimeFormatter.ofPattern("yyyyMM")); - String day = now.format(DateTimeFormatter.ofPattern("dd")); - - // 构建完整的文件路径 - // 格式: C:/Users/14725/Desktop/material/202603/20260312/001.bmp - String filePath = String.format("%s/%s/%s%s/%s", BASE_PATH, yearMonth, yearMonth, day, PHOTO_NAME); - - // 读取图片文件 - Path imagePath = Paths.get(filePath); - - // 检查文件是否存在 - if (!Files.exists(imagePath)) { - return ResponseEntity.notFound().build(); - } - - // 读取文件字节 - byte[] imageBytes = Files.readAllBytes(imagePath); - - // 设置响应头 - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.valueOf("image/bmp")); - headers.setContentLength(imageBytes.length); - - // 返回图片 - return new ResponseEntity<>(imageBytes, headers, HttpStatus.OK); - - } catch (IOException e) { - e.printStackTrace(); - return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build(); - } - }*/ - - @GetMapping("/latest-photo") - public String getLatestPhoto() { - try { - // 获取当前日期 - LocalDate now = LocalDate.now(); - String yearMonth = now.format(DateTimeFormatter.ofPattern("yyyyMM")); - String day = now.format(DateTimeFormatter.ofPattern("dd")); - - // 构建完整的本地文件路径 - // 格式: C:/Users/14725/Desktop/material/202603/20260312/001.bmp - String filePath = String.format("%s/%s/%s%s/%s", BASE_PATH, yearMonth, yearMonth, day, PHOTO_NAME); - - // 读取图片文件 - Path imagePath = Paths.get(filePath); - - // 检查文件是否存在 - if (!Files.exists(imagePath)) { - return null; // 或者抛出异常,根据业务需求决定 - } - - // 将文件转换为MultipartFile - File file = imagePath.toFile(); - FileInputStream input = new FileInputStream(file); - MultipartFile multipartFile = new MockMultipartFile(file.getName(), // 文件名 - file.getName(), // 原始文件名 - "image/bmp", // 内容类型 - input // 文件输入流 - ); - - // 构建MinIO存储路径 - String photoStoragePath = "catch" + DateUtil.today() + "/"; - - // 使用现有的fileService上传到MinIO - FileInfo fileInfo = fileService.upload(multipartFile, photoStoragePath, null, true, true); - - // 检查上传结果 - CheckUtils.throwIfNull(fileInfo, "照片上传失败"); - - // 关闭输入流 - input.close(); - return fileInfo.getUrl(); - - } catch (IOException e) { - e.printStackTrace(); - throw new RuntimeException("处理图片失败: " + e.getMessage()); - } + CheckUtils.throwIf("ERROR".equals(response), "设备连接异常!"); + return response; } }