Compare commits

1 Commits

Author SHA1 Message Date
cd1ba55b26 优化 2026-03-13 10:30:55 +08:00
6 changed files with 155 additions and 34 deletions

View File

@@ -119,5 +119,10 @@
<groupId>org.springframework</groupId> <groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId> <artifactId>spring-test</artifactId>
</dependency> </dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.100.Final</version>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@@ -21,5 +21,11 @@
<groupId>top.wms</groupId> <groupId>top.wms</groupId>
<artifactId>wms-common</artifactId> <artifactId>wms-common</artifactId>
</dependency> </dependency>
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
<scope>provided</scope>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@@ -33,7 +33,6 @@ public class NettyTcpServer {
private EventLoopGroup workerGroup; private EventLoopGroup workerGroup;
private Channel serverChannel; private Channel serverChannel;
@PostConstruct @PostConstruct
public void start() throws InterruptedException { public void start() throws InterruptedException {
log.info("正在启动TCP服务端端口: {}", port); log.info("正在启动TCP服务端端口: {}", port);
@@ -43,27 +42,27 @@ public class NettyTcpServer {
ServerBootstrap bootstrap = new ServerBootstrap(); ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(bossGroup, workerGroup) bootstrap.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class) .channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG, 128) .option(ChannelOption.SO_BACKLOG, 128)
.childOption(ChannelOption.SO_KEEPALIVE, true) .childOption(ChannelOption.SO_KEEPALIVE, true)
.childHandler(new ChannelInitializer<SocketChannel>() { .childHandler(new ChannelInitializer<SocketChannel>() {
@Override @Override
protected void initChannel(SocketChannel ch) { protected void initChannel(SocketChannel ch) {
ChannelPipeline pipeline = ch.pipeline(); ChannelPipeline pipeline = ch.pipeline();
// 解决TCP粘包问题 // 解决TCP粘包问题
pipeline.addLast(new LineBasedFrameDecoder(1024)); pipeline.addLast(new LineBasedFrameDecoder(1024));
// 字符串编解码 // 字符串编解码
pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8)); pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8));
pipeline.addLast(new StringEncoder(CharsetUtil.UTF_8)); pipeline.addLast(new StringEncoder(CharsetUtil.UTF_8));
// 关键修复直接new不要从Spring容器获取 // 关键修复直接new不要从Spring容器获取
pipeline.addLast(new TcpServerHandler()); pipeline.addLast(new TcpServerHandler());
log.debug("新连接接入,处理器已添加"); log.debug("新连接接入,处理器已添加");
} }
}); });
ChannelFuture future = bootstrap.bind(port).sync(); ChannelFuture future = bootstrap.bind(port).sync();
if (future.isSuccess()) { if (future.isSuccess()) {

View File

@@ -3,8 +3,6 @@ package top.wms.admin.controller.tcp.service;
import io.netty.channel.Channel; import io.netty.channel.Channel;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled; import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.bind.annotation.RequestParam;
import top.continew.starter.core.validation.CheckUtils;
import top.wms.admin.controller.tcp.manager.ChannelManager; import top.wms.admin.controller.tcp.manager.ChannelManager;
import top.wms.admin.controller.tcp.model.VMResult; import top.wms.admin.controller.tcp.model.VMResult;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -51,10 +49,8 @@ public class CommandService {
// 获取统计信息 // 获取统计信息
public String getStatistics() { public String getStatistics() {
return String.format("成功: %d, 失败: %d, 总数: %d", return String.format("成功: %d, 失败: %d, 总数: %d", successCount.get(), failCount.get(), successCount
successCount.get(), .get() + failCount.get());
failCount.get(),
successCount.get() + failCount.get());
} }
// 获取最新结果 // 获取最新结果
@@ -62,11 +58,10 @@ public class CommandService {
return resultQueue.peek(); return resultQueue.peek();
} }
@Autowired @Autowired
private ChannelManager channelManager; private ChannelManager channelManager;
// @Scheduled(cron = "*/3 * * * * ?") @Scheduled(cron = "*/1 * * * * ?")
public void sendAndWait() { public void sendAndWait() {
// 1. 检查连接 // 1. 检查连接
log.info("查询时间========"); log.info("查询时间========");

View File

@@ -1,13 +1,30 @@
package top.wms.admin.controller.vm; package top.wms.admin.controller.vm;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import io.netty.channel.Channel; import io.netty.channel.Channel;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.dromara.x.file.storage.core.FileInfo;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import top.continew.starter.core.validation.CheckUtils; import top.continew.starter.core.validation.CheckUtils;
import top.wms.admin.controller.tcp.config.SimpleRequestMatcher; import top.wms.admin.controller.tcp.config.SimpleRequestMatcher;
import top.wms.admin.controller.tcp.manager.ChannelManager; 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 @Slf4j
@RestController @RestController
@@ -20,6 +37,9 @@ public class VmCommandController {
@Autowired @Autowired
private SimpleRequestMatcher requestMatcher; private SimpleRequestMatcher requestMatcher;
@Autowired
private FileService fileService;
@GetMapping("/send") @GetMapping("/send")
public String sendAndWait(@RequestParam String msg) { public String sendAndWait(@RequestParam String msg) {
// 1. 检查连接 // 1. 检查连接
@@ -32,17 +52,114 @@ public class VmCommandController {
log.info("发送指令: {}", sendMsg); log.info("发送指令: {}", sendMsg);
// 3. 等待响应 // 3. 等待响应
String response = requestMatcher.waitForResponse(20); String response = requestMatcher.waitForResponse(20);
CheckUtils.throwIf("TIMEOUT".equals(response),"响应超时,请重试"); CheckUtils.throwIf("TIMEOUT".equals(response), "响应超时,请重试");
if (StrUtil.equals(response, "success") || StrUtil.equals(response, "failed")) { if (StrUtil.equals(response, "success") || StrUtil.equals(response, "failed")) {
return response; return response;
} }
if (StrUtil.equals(response, msg)) { if (StrUtil.equals(response, msg)) {
response = "success"; response = "success";
}else{ } else {
response = "failed"; response = "failed";
} }
// 4. 返回结果 // 4. 返回结果
return response; // 直接返回VM的响应 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<byte[]> 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());
}
}
} }

View File

@@ -25,7 +25,7 @@ import java.util.regex.Pattern;
@Slf4j @Slf4j
public class AHDZCConnect { public class AHDZCConnect {
private static final String PORT_NAME = "COM5"; private static final String PORT_NAME = "COM12";
private static final int BAUD_RATE = 9600; private static final int BAUD_RATE = 9600;
private static final int DATA_BITS = 8; private static final int DATA_BITS = 8;
private static final int STOP_BITS = 1; private static final int STOP_BITS = 1;
@@ -52,10 +52,9 @@ public class AHDZCConnect {
@PostConstruct @PostConstruct
public void init() { public void init() {
// 项目启动时初始化并启动服务 // 项目启动时初始化并启动服务
if (false) { ScaleService();
ScaleService(); start();
start();
}
} }
@PreDestroy @PreDestroy