diff --git a/wms-webapi/pom.xml b/wms-webapi/pom.xml
index 68ce21f..bac2344 100644
--- a/wms-webapi/pom.xml
+++ b/wms-webapi/pom.xml
@@ -67,6 +67,13 @@
aws-java-sdk-s3
1.12.780
+
+
+ com.fazecast
+ jSerialComm
+ 2.9.2
+
+
diff --git a/wms-webapi/src/main/java/top/wms/admin/controller/weighManage/ah/AHDZCConnect.java b/wms-webapi/src/main/java/top/wms/admin/controller/weighManage/ah/AHDZCConnect.java
new file mode 100644
index 0000000..01856dc
--- /dev/null
+++ b/wms-webapi/src/main/java/top/wms/admin/controller/weighManage/ah/AHDZCConnect.java
@@ -0,0 +1,307 @@
+package top.wms.admin.controller.weighManage.ah;
+
+import com.fazecast.jSerialComm.SerialPort;
+import com.fazecast.jSerialComm.SerialPortDataListener;
+import com.fazecast.jSerialComm.SerialPortEvent;
+import jakarta.annotation.PostConstruct;
+import jakarta.annotation.PreDestroy;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import java.nio.charset.Charset;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * 安衡电子秤连接类
+ */
+@Component
+@Slf4j
+public class AHDZCConnect {
+
+ private static final String PORT_NAME = "COM5";
+ private static final int BAUD_RATE = 9600;
+ private static final int DATA_BITS = 8;
+ private static final int STOP_BITS = 1;
+ private static final int TIMEOUT = 2000;
+ private static final Charset SCALE_CHARSET = Charset.forName("GBK");
+
+ private static final long HEALTH_CHECK_INTERVAL = 5000;
+ private static final long DATA_TIMEOUT = 10000;
+ private static final int MAX_RECONNECT_DELAY = 30000;
+ private static final int INITIAL_RECONNECT_DELAY = 1000;
+ private static final int BUFFER_SIZE = 256;
+
+ private volatile SerialPort serialPort;
+ private final AtomicBoolean isConnecting = new AtomicBoolean(false);
+ private final AtomicBoolean isRunning = new AtomicBoolean(true);
+ private final AtomicLong lastDataTime = new AtomicLong(System.currentTimeMillis());
+ private final AtomicInteger reconnectAttempts = new AtomicInteger(0);
+ private final AtomicInteger currentReconnectDelay = new AtomicInteger(INITIAL_RECONNECT_DELAY);
+
+ private final byte[] readBuffer = new byte[BUFFER_SIZE];
+
+ private ScheduledExecutorService executorService;
+
+
+
+ @PostConstruct
+ public void init() {
+ // 项目启动时初始化并启动服务
+ ScaleService();
+ start();
+ }
+
+ @PreDestroy
+ public void destroy() {
+ // 项目关闭时停止服务
+ stop();
+ }
+
+
+ public void ScaleService() {
+ executorService = Executors.newScheduledThreadPool(2, r -> {
+ Thread t = new Thread(r, "ScaleService-Worker");
+ t.setDaemon(true);
+ return t;
+ });
+
+ Runtime.getRuntime().addShutdownHook(new Thread(this::stop, "Shutdown-Hook"));
+ }
+
+ public void start() {
+ log.info("========================================");
+ log.info("启动电子秤连接线程,串口: " + PORT_NAME + " | 波特率: " + BAUD_RATE);
+ log.info("========================================");
+
+ startHealthCheck();
+ startConnectionMonitor();
+ if (connect()) {
+ log.info("电子秤连接成功!");
+ } else {
+ log.info("电子秤连接失败,将自动尝试重连...");
+ }
+ }
+
+ private boolean connect() {
+ if (!isRunning.get()) {
+ return false;
+ }
+
+ if (!isConnecting.compareAndSet(false, true)) {
+ log.error("[连接] 已有连接任务正在执行,跳过");
+ return false;
+ }
+
+ try {
+ closeSerialPort();
+
+ SerialPort newPort = SerialPort.getCommPort(PORT_NAME);
+ newPort.setBaudRate(BAUD_RATE);
+ newPort.setNumDataBits(DATA_BITS);
+ newPort.setNumStopBits(STOP_BITS);
+ newPort.setParity(SerialPort.NO_PARITY);
+ newPort.setComPortTimeouts(TIMEOUT, TIMEOUT, TIMEOUT);
+
+ if (!newPort.openPort()) {
+ int attempts = reconnectAttempts.incrementAndGet();
+ int delay = calculateReconnectDelay();
+ log.info("[连接失败] 无法打开串口 {} (第{}次尝试,下次重试间隔: {}ms)", PORT_NAME, attempts, delay);
+ return false;
+ }
+
+ serialPort = newPort;
+ reconnectAttempts.set(0);
+ currentReconnectDelay.set(INITIAL_RECONNECT_DELAY);
+ lastDataTime.set(System.currentTimeMillis());
+
+ log.info("[连接成功] 串口 {} 已打开", PORT_NAME);
+
+ startDataListener();
+
+ return true;
+ } catch (Exception e) {
+ log.error("[连接异常] {}", e.getMessage());
+ return false;
+ } finally {
+ isConnecting.set(false);
+ }
+ }
+
+ private int calculateReconnectDelay() {
+ int delay = currentReconnectDelay.get();
+ int newDelay = Math.min(delay * 2, MAX_RECONNECT_DELAY);
+ currentReconnectDelay.set(newDelay);
+ return newDelay;
+ }
+
+ private void closeSerialPort() {
+ SerialPort oldPort = serialPort;
+ serialPort = null;
+
+ if (oldPort != null) {
+ try {
+ if (oldPort.isOpen()) {
+ oldPort.closePort();
+ }
+ } catch (Exception e) {
+ log.error("[关闭串口] 异常: {}", e.getMessage());
+ }
+ }
+ }
+
+ private void startDataListener() {
+ SerialPort port = serialPort;
+ if (port == null || !port.isOpen()) {
+ return;
+ }
+
+ port.addDataListener(new SerialPortDataListener() {
+ @Override
+ public int getListeningEvents() {
+ return SerialPort.LISTENING_EVENT_DATA_AVAILABLE;
+ }
+
+ @Override
+ public void serialEvent(SerialPortEvent event) {
+ if (event.getEventType() != SerialPort.LISTENING_EVENT_DATA_AVAILABLE) {
+ return;
+ }
+
+ try {
+ SerialPort currentPort = serialPort;
+ if (currentPort == null) {
+ return;
+ }
+
+ int bytesAvailable = currentPort.bytesAvailable();
+ if (bytesAvailable <= 0) {
+ return;
+ }
+
+ int bytesToRead = Math.min(bytesAvailable, BUFFER_SIZE);
+ int numRead = currentPort.readBytes(readBuffer, bytesToRead);
+
+ if (numRead > 0) {
+ lastDataTime.set(System.currentTimeMillis());
+ String data = new String(readBuffer, 0, numRead, SCALE_CHARSET);
+ log.info("[数据] {}", data.trim());
+ }
+ } catch (Exception e) {
+ log.error("[读取异常] {}", e.getMessage());
+ triggerReconnect();
+ }
+ }
+ });
+ }
+
+ private void startHealthCheck() {
+ log.info("[健康检查] 启动,间隔 {} 秒", HEALTH_CHECK_INTERVAL / 1000);
+
+ executorService.scheduleAtFixedRate(() -> {
+ if (!isRunning.get()) {
+ return;
+ }
+
+ try {
+ SerialPort port = serialPort;
+
+ if (port == null) {
+ log.error("[健康检查] 串口对象为空");
+ if (reconnectAttempts.get() < 10) {
+ connect();
+ }
+ return;
+ }
+
+ boolean isOpen = port.isOpen();
+ log.error("[健康检查] 串口状态: {}", isOpen ? "已打开" : "已关闭");
+
+ if (!isOpen) {
+ log.info("[健康检查] 检测到串口关闭,尝试重连...");
+ connect();
+ }
+ } catch (Exception e) {
+ log.error("[健康检查异常] {}", e.getMessage());
+ }
+ }, HEALTH_CHECK_INTERVAL, HEALTH_CHECK_INTERVAL, TimeUnit.MILLISECONDS);
+ }
+
+ private void startConnectionMonitor() {
+ log.info("[连接监控] 启动,间隔 3 秒");
+
+ executorService.scheduleAtFixedRate(() -> {
+ if (!isRunning.get()) {
+ return;
+ }
+
+ try {
+ long currentTime = System.currentTimeMillis();
+ long timeSinceLastData = currentTime - lastDataTime.get();
+
+ if (timeSinceLastData > DATA_TIMEOUT) {
+ SerialPort port = serialPort;
+
+ if (port != null && port.isOpen()) {
+ try {
+ int bytesAvailable = port.bytesAvailable();
+
+ if (bytesAvailable < 0) {
+ log.info("[连接监控] 检测到连接已断开,尝试重连...");
+ triggerReconnect();
+ } else {
+ log.error("[连接监控] 超时无数据,但连接正常,等待数据...");
+ }
+ } catch (Exception e) {
+ log.error("[连接监控] 检测到连接异常: {}", e.getMessage());
+ triggerReconnect();
+ }
+ }
+ }
+ } catch (Exception e) {
+ log.error("[连接监控异常] {}", e.getMessage());
+ }
+ }, 3000, 3000, TimeUnit.MILLISECONDS);
+ }
+
+ private void triggerReconnect() {
+ if (isConnecting.compareAndSet(false, true)) {
+ isConnecting.set(false);
+ connect();
+ }
+ }
+
+ public void stop() {
+ if (!isRunning.compareAndSet(true, false)) {
+ return;
+ }
+
+ log.info("========================================");
+ log.info("停止电子秤线程...");
+ log.info("========================================");
+
+ try {
+ if (executorService != null && !executorService.isShutdown()) {
+ executorService.shutdown();
+ if (!executorService.awaitTermination(3, TimeUnit.SECONDS)) {
+ executorService.shutdownNow();
+ }
+ }
+ } catch (InterruptedException e) {
+ if (executorService != null) {
+ executorService.shutdownNow();
+ }
+ Thread.currentThread().interrupt();
+ }
+
+ closeSerialPort();
+
+ log.info("线程已完全停止");
+ }
+
+
+}