#
Junjie
2026-01-15 ef1cd5823fe7cf724e1de875a1a5737a44f160f1
#
7个文件已修改
976 ■■■■■ 已修改文件
src/main/java/com/zy/core/enums/RedisKeyType.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/model/command/StationCommand.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/network/fake/ZyStationFakeSegConnect.java 561 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/plugin/FakeProcess.java 172 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/plugin/NormalProcess.java 92 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/thread/impl/ZyStationV3Thread.java 25 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/utils/WmsOperateUtils.java 122 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/enums/RedisKeyType.java
@@ -49,6 +49,8 @@
    DUAL_CRN_OUT_TASK_STATION_INFO("dual_crn_out_task_station_info_"),
    CURRENT_CIRCLE_TASK_CRN_NO("current_circle_task_crn_no_"),
    ASYNC_WMS_IN_TASK_REQUEST("async_wms_in_task_request_"),
    ASYNC_WMS_IN_TASK_RESPONSE("async_wms_in_task_response_"),
    AI_CHAT_HISTORY("ai_chat_history_"),
    AI_CHAT_META("ai_chat_meta_"),
    MAIN_PROCESS_PSEUDOCODE("main_process_pseudocode"),
src/main/java/com/zy/core/model/command/StationCommand.java
@@ -19,6 +19,8 @@
    private List<Integer> navigatePath;
    private List<Integer> originalNavigatePath;
    private StationCommandType commandType;
}
src/main/java/com/zy/core/network/fake/ZyStationFakeSegConnect.java
@@ -3,8 +3,6 @@
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.zy.asrs.entity.DeviceConfig;
import com.zy.asrs.utils.Utils;
import com.zy.common.model.NavigateNode;
import com.zy.common.utils.RedisUtil;
import com.zy.core.News;
import com.zy.core.enums.RedisKeyType;
@@ -24,12 +22,14 @@
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
import java.util.Map;
import java.util.function.Supplier;
import java.util.Arrays;
public class ZyStationFakeSegConnect implements ZyStationConnectApi {
    private static int LOCK_STATION = 0;
    // 站点级锁:每个站点独立一把锁,提升并发性能
    private final Map<Integer, ReentrantLock> stationLocks = new ConcurrentHashMap<>();
    private HashMap<Integer, List<ZyStationStatusEntity>> deviceStatusMap = new HashMap<>();
    private HashMap<Integer, DeviceConfig> deviceConfigMap = new HashMap<>();
    private RedisUtil redisUtil;
@@ -60,8 +60,7 @@
                                    && statusEntity.isLoading()
                                    && statusEntity.getTaskNo() > 0
                                    && !statusEntity.isRunBlock()
                                    && !statusEntity.getStationId().equals(statusEntity.getTargetStaNo())
                            ) {
                                    && !statusEntity.getStationId().equals(statusEntity.getTargetStaNo())) {
                                BlockingQueue<StationCommand> commands = taskQueues.get(statusEntity.getTaskNo());
                                if (commands == null) {
                                    statusEntity.setRunBlock(true);
@@ -76,7 +75,7 @@
                }
            }
        });
        checkThread.start();
        // checkThread.start();
        return true;
    }
@@ -94,7 +93,8 @@
        }
        DeviceConfig deviceConfig = deviceConfigMap.get(deviceNo);
        if (statusList.isEmpty()) {
            List<ZyStationStatusEntity> init = JSON.parseArray(deviceConfig.getFakeInitStatus(), ZyStationStatusEntity.class);
            List<ZyStationStatusEntity> init = JSON.parseArray(deviceConfig.getFakeInitStatus(),
                    ZyStationStatusEntity.class);
            if (init != null) {
                statusList.addAll(init);
                for (ZyStationStatusEntity status : statusList) {
@@ -126,12 +126,15 @@
        if (command.getCommandType() != StationCommandType.MOVE) {
            handleCommand(deviceNo, command);
        }else {
            // 将移动命令追加到任务队列(支持分段下发)
            taskQueues.computeIfAbsent(taskNo, k -> new LinkedBlockingQueue<>()).offer(command);
            taskLastUpdateTime.put(taskNo, System.currentTimeMillis());
            // 只有任务未启动时才启动执行器,后续分段命令仅追加到队列
            if (taskRunning.putIfAbsent(taskNo, true) == null) {
                executor.submit(() -> runTaskLoop(deviceNo, taskNo));
            }
            // 后续分段命令不再返回错误,正常追加到队列
        }
        return new CommandResponse(true, "命令已受理(异步执行)");
@@ -139,138 +142,171 @@
    private void runTaskLoop(Integer deviceNo, Integer taskNo) {
        try {
            // 用于存储当前任务待执行的完整路径队列
            BlockingQueue<Integer> pathQueue = new LinkedBlockingQueue<>();
            // 当前是否正在执行移动
            boolean isMoving = false;
            // 当前移动到的路径索引
            int currentPathIndex = 0;
            // 完整路径记录
            List<Integer> fullPath = new ArrayList<>();
            StationCommand initialCommand = null;
            // 待执行的路径队列(存储站点ID序列)
            LinkedBlockingQueue<Integer> pendingPathQueue = new LinkedBlockingQueue<>();
            // 当前所在站点ID
            Integer currentStationId = null;
            // 最终目标站点ID
            Integer finalTargetStationId = null;
            // 是否需要生成条码
            boolean generateBarcode = false;
            // 是否已初始化起点
            boolean initialized = false;
            // 上一步执行时间(用于堵塞检测)
            long stepExecuteTime = System.currentTimeMillis();
            while (true) {
                if (Thread.currentThread().isInterrupted()) {
                    break;
                }
                BlockingQueue<StationCommand> commandQueue = taskQueues.get(taskNo);
                if (commandQueue == null) {
                    break;
                }
                // 尝试获取新命令,如果没有新命令则继续执行现有路径
                // 尝试获取新的分段命令
                StationCommand command = commandQueue.poll(100, TimeUnit.MILLISECONDS);
                if (command != null) {
                    stepExecuteTime = System.currentTimeMillis();
                    taskLastUpdateTime.put(taskNo, System.currentTimeMillis());
                    
                    if (initialCommand == null) {
                        initialCommand = command;
                    // 首次接收命令时初始化
                    if (finalTargetStationId == null) {
                        finalTargetStationId = command.getTargetStaNo();
                        if (checkTaskNoInArea(taskNo)) {
                            generateBarcode = true;
                        }
                    }
                    // 将新路径追加到待执行队列
                    List<Integer> newPath = command.getNavigatePath();
                    if (newPath != null && !newPath.isEmpty()) {
                        // 如果是第一段路径
                        if (fullPath.isEmpty()) {
                            fullPath.addAll(newPath);
                            for (Integer stationId : newPath) {
                                pathQueue.offer(stationId);
                        // 获取队列中最后一个站点(用于衔接点去重)
                        Integer lastInQueue = getLastInQueue(pendingPathQueue);
                        if (lastInQueue == null) {
                            lastInQueue = currentStationId;
                            }
                        } else {
                            // 追加路径,需要去重衔接点
                            Integer lastStationId = fullPath.get(fullPath.size() - 1);
                            int startIndex = 0;
                            if (!newPath.isEmpty() && newPath.get(0).equals(lastStationId)) {
                        // 如果新路径的起点与当前位置或队列末尾重复,则跳过
                        if (lastInQueue != null && !newPath.isEmpty() && newPath.get(0).equals(lastInQueue)) {
                                startIndex = 1;
                            }
                            for (int i = startIndex; i < newPath.size(); i++) {
                                Integer stationId = newPath.get(i);
                                fullPath.add(stationId);
                                pathQueue.offer(stationId);
                            pendingPathQueue.offer(newPath.get(i));
                            }
                        }
                        News.info("[WCS Debug] 任务{}追加路径段: {} -> 队列大小: {}", taskNo, newPath, pendingPathQueue.size());
                    }
                }
                // 执行移动逻辑
                if (!pathQueue.isEmpty()) {
                    // 如果刚开始,先初始化当前位置
                    if (currentPathIndex == 0 && !fullPath.isEmpty()) {
                         Integer startStationId = fullPath.get(0);
                         Integer deviceId = getDeviceNoByStationId(startStationId);
                if (!pendingPathQueue.isEmpty()) {
                    Integer nextStationId = pendingPathQueue.peek();
                    // 如果尚未初始化起点
                    if (!initialized && currentStationId == null) {
                        // 优先查找托盘当前实际位置(支持堵塞后重路由场景)
                        Integer actualCurrentStationId = findCurrentStationIdByTask(taskNo);
                        if (actualCurrentStationId != null) {
                            // 找到了当前托盘位置,使用实际位置作为起点
                            currentStationId = actualCurrentStationId;
                            initialized = true;
                            // 清除该站点的 runBlock 标记(堵塞恢复)
                            Integer deviceId = getDeviceNoByStationId(currentStationId);
                         if (deviceId != null) {
                             initStationMove(taskNo, startStationId, deviceId, taskNo, finalTargetStationId, true, null);
                         }
                                clearRunBlock(currentStationId, deviceId);
                    }
                    // 取出下一个目标点
                    Integer nextStationId = pathQueue.peek(); // 这里的逻辑需要改为逐个行走
                    // 实际行走逻辑应该是在这里消费 pathQueue
                    // 为了简化,我们将 pathQueue 转为 stationMoveByPathIds 的逻辑,但这里需要改造成步进式
                            // 如果路径起点与当前位置相同,移除起点避免重复
                            if (nextStationId.equals(currentStationId)) {
                                pendingPathQueue.poll();
                            }
                    
                    // 重新设计:runTaskLoop 负责不断消费 pathQueue 并执行单步移动
                    if (nextStationId != null) {
                        Integer currentStationId = fullPath.get(currentPathIndex);
                        if (currentStationId.equals(nextStationId)) {
                            pathQueue.poll(); // 移除已到达的点
                            stepExecuteTime = System.currentTimeMillis();
                            News.info("[WCS Debug] 任务{}恢复执行,当前位置: {}", taskNo, currentStationId);
                            continue;
                        }
                        
                        // 执行从 currentStationId 到 nextStationId 的移动
                        // 未找到当前位置(首次执行),首个站点就是起点
                        currentStationId = nextStationId;
                        Integer deviceId = getDeviceNoByStationId(currentStationId);
                        if (deviceId != null) {
                            boolean result = initStationMove(taskNo, currentStationId, deviceId, taskNo,
                                    finalTargetStationId, true, null);
                            if (result) {
                                initialized = true;
                                pendingPathQueue.poll(); // 移除起点
                                stepExecuteTime = System.currentTimeMillis();
                                News.info("[WCS Debug] 任务{}初始化起点: {}", taskNo, currentStationId);
                            }
                        }
                        sleep(500);
                        continue;
                    }
                    // 执行从当前站点到下一站点的移动
                        Integer currentDeviceNo = getDeviceNoByStationId(currentStationId);
                        Integer nextDeviceNo = getDeviceNoByStationId(nextStationId);
                        
                        if (currentDeviceNo != null && nextDeviceNo != null) {
                            boolean moveSuccess = stationMoveToNext(taskNo, currentStationId, currentDeviceNo, nextStationId, nextDeviceNo, taskNo, finalTargetStationId);
                        boolean moveSuccess = stationMoveToNext(taskNo, currentStationId, currentDeviceNo,
                                nextStationId, nextDeviceNo, taskNo, finalTargetStationId);
                            if (moveSuccess) {
                                currentPathIndex++;
                                pathQueue.poll();
                            currentStationId = nextStationId;
                            pendingPathQueue.poll();
                                stepExecuteTime = System.currentTimeMillis();
                                sleep(1000); // 模拟耗时
                            News.info("[WCS Debug] 任务{}移动到站点: {}, 剩余队列: {}", taskNo, currentStationId,
                                    pendingPathQueue.size());
                            sleep(1000); // 模拟移动耗时
                            } else {
                            // 移动失败,检查是否堵塞
                                if (!checkTaskNoInArea(taskNo)) {
                                    boolean fakeAllowCheckBlock = true;
                                    Object systemConfigMapObj = redisUtil.get(RedisKeyType.SYSTEM_CONFIG_MAP.key);
                                    if (systemConfigMapObj != null) {
                                        HashMap<String, String> systemConfigMap = (HashMap<String, String>) systemConfigMapObj;
                                        if (systemConfigMap.get("fakeAllowCheckBlock") != null && !systemConfigMap.get("fakeAllowCheckBlock").equals("Y")) {
                                            fakeAllowCheckBlock = false;
                                boolean fakeAllowCheckBlock = getFakeAllowCheckBlock();
                                if (fakeAllowCheckBlock && System.currentTimeMillis() - stepExecuteTime > 10000) {
                                    // 认定堵塞
                                    boolean result = runBlockStation(taskNo, currentStationId, currentDeviceNo, taskNo,
                                            currentStationId);
                                    if (result) {
                                        News.info("[WCS Debug] 任务{}在站点{}被标记为堵塞", taskNo, currentStationId);
                                        pendingPathQueue.clear();
                                        break;
                                        }
                                }
                            }
                            sleep(500); // 失败重试等待
                        }
                    } else {
                        // 无法获取设备号,跳过该站点
                        pendingPathQueue.poll();
                    }
                } else {
                    // 路径队列为空,等待新的分段命令
                    if (currentStationId != null && finalTargetStationId != null
                            && currentStationId.equals(finalTargetStationId)) {
                        // 已到达最终目标,正常结束
                        if (generateBarcode) {
                            Integer targetDeviceNo = getDeviceNoByStationId(finalTargetStationId);
                            if (targetDeviceNo != null) {
                                generateStationBarcode(taskNo, finalTargetStationId, targetDeviceNo);
                                News.info("[WCS Debug] 任务{}到达目标{}并生成条码", taskNo, finalTargetStationId);
                            }
                        }
                        break;
                                    }
                                    if (fakeAllowCheckBlock && System.currentTimeMillis() - stepExecuteTime > 1000 * 10) {
                                        //认定堵塞
                                        boolean result = runBlockStation(taskNo, currentStationId, currentDeviceNo, taskNo, currentStationId);
                                        if(result) {
                                            break;
                                        }
                                    }
                                }
                                sleep(1000); // 失败重试等待
                            }
                        } else {
                            pathQueue.poll(); // 无法执行,跳过
                        }
                    }
                } else {
                    // 队列为空,检查是否超时
                    // 未到达最终目标,等待新的分段命令
                    Long lastTime = taskLastUpdateTime.get(taskNo);
                    if (lastTime != null && System.currentTimeMillis() - lastTime > 30000) {
                        // 完成任务后清理
                        if (fullPath.size() > 0 && generateBarcode) {
                             Integer lastStation = fullPath.get(fullPath.size()-1);
                             Integer lastDevice = getDeviceNoByStationId(lastStation);
                             if (lastDevice != null) {
                                 generateStationBarcode(taskNo, finalTargetStationId, lastDevice);
                             }
                        }
                        // 超时:30秒内没有收到新分段命令
                        News.info("[WCS Debug] 任务{}等待分段超时,当前位置: {}, 目标: {}", taskNo, currentStationId,
                                finalTargetStationId);
                        break;
                    }
                    // 继续等待新分段命令(不做任何事情,下一轮循环会尝试获取新命令)
                }
            }
        } catch (InterruptedException e) {
@@ -279,7 +315,35 @@
            taskQueues.remove(taskNo);
            taskLastUpdateTime.remove(taskNo);
            taskRunning.remove(taskNo);
            News.info("[WCS Debug] 任务{}执行结束并清理资源", taskNo);
        }
    }
    /**
     * 获取队列中最后一个元素(不移除)
     */
    private Integer getLastInQueue(LinkedBlockingQueue<Integer> queue) {
        Integer last = null;
        for (Integer item : queue) {
            last = item;
        }
        return last;
    }
    /**
     * 获取是否允许检查堵塞的配置
     */
    private boolean getFakeAllowCheckBlock() {
        boolean fakeAllowCheckBlock = true;
        Object systemConfigMapObj = redisUtil.get(RedisKeyType.SYSTEM_CONFIG_MAP.key);
        if (systemConfigMapObj != null) {
            HashMap<String, String> systemConfigMap = (HashMap<String, String>) systemConfigMapObj;
            String value = systemConfigMap.get("fakeAllowCheckBlock");
            if (value != null && !value.equals("Y")) {
                fakeAllowCheckBlock = false;
            }
        }
        return fakeAllowCheckBlock;
    }
    @Override
@@ -319,12 +383,7 @@
        if (taskNo > 0 && taskNo != 9999 && taskNo != 9998 && stationId == targetStationId) {
            generateStationData(deviceNo, taskNo, stationId, targetStationId);
        }
        List<Integer> navigatePath = command.getNavigatePath();
        if (navigatePath != null && !navigatePath.isEmpty()) {
            segmentedPathCommand(command, generateBarcode);
            return;
        }
        // 注意:MOVE 类型的命令现已在 sendCommand 中处理,handleCommand 仅处理非 MOVE 命令
    }
    private void generateFakeOutStationData(Integer deviceNo, Integer stationId) {
@@ -369,32 +428,7 @@
        }
    }
    private void segmentedPathCommand(StationCommand command, boolean generateBarcode) {
        Integer taskNo = command.getTaskNo();
        Integer finalTargetStationId = command.getTargetStaNo();
        List<Integer> path = command.getNavigatePath();
        if (path == null || path.isEmpty()) {
            return;
        }
        Integer currentStationId = findCurrentStationIdByTask(taskNo);
        int startIdx = 0;
        if (currentStationId != null) {
            int idx = path.indexOf(currentStationId);
            if (idx >= 0) {
                startIdx = idx;
            }
        }
        Integer segmentTargetStationId = path.get(path.size() - 1);
        int endIdx = path.size() - 1;
        boolean isFinalSegment = segmentTargetStationId.equals(finalTargetStationId);
        boolean appendMode = currentStationId != null && path.indexOf(currentStationId) >= 0;
        boolean generateBarcodeFinal = generateBarcode && isFinalSegment;
        stationMoveByPathIds(path, taskNo, finalTargetStationId, false, generateBarcodeFinal, startIdx, endIdx, appendMode);
    }
    // segmentedPathCommand 方法已删除,功能已整合到 runTaskLoop
    private Integer getDeviceNoByStationId(Integer stationId) {
        for (Integer devNo : deviceStatusMap.keySet()) {
@@ -426,116 +460,7 @@
        return null;
    }
    private boolean stationMoveByPathIds(List<Integer> stationPath, Integer taskNo, Integer targetStationId, boolean clearData, boolean generateBarcode, int startIdx, int endIdx, boolean appendMode) {
        Integer lastStationId = null;
        Integer targetStationDeviceNo = getDeviceNoByStationId(targetStationId);
        long executeTime = System.currentTimeMillis();
        int i = Math.max(0, startIdx);
        while (i < stationPath.size() && i <= endIdx) {
            if (Thread.currentThread().isInterrupted()) {
                return false;
            }
            Integer currentStationId = stationPath.get(i);
            Integer currentStationDeviceNo = getDeviceNoByStationId(currentStationId);
            if (currentStationDeviceNo == null) {
                return false;
            }
            Integer nextStationId = null;
            Integer nextStationDeviceNo = null;
            try {
                nextStationId = stationPath.get(i + 1);
                nextStationDeviceNo = getDeviceNoByStationId(nextStationId);
            } catch (Exception ignore) {}
            if (!checkTaskNoInArea(taskNo)) {
                boolean fakeAllowCheckBlock = true;
                Object systemConfigMapObj = redisUtil.get(RedisKeyType.SYSTEM_CONFIG_MAP.key);
                if (systemConfigMapObj != null) {
                    HashMap<String, String> systemConfigMap = (HashMap<String, String>) systemConfigMapObj;
                    if (!systemConfigMap.get("fakeAllowCheckBlock").equals("Y")) {
                        fakeAllowCheckBlock = false;
                    }
                }
                if (fakeAllowCheckBlock && System.currentTimeMillis() - executeTime > 1000 * 10) {
                    boolean result = runBlockStation(taskNo, currentStationId, currentStationDeviceNo, taskNo, currentStationId);
                    if(!result) {
                        continue;
                    }
                    return false;
                }
            }
            if (i == startIdx && !appendMode) {
                boolean result = initStationMove(taskNo, currentStationId, currentStationDeviceNo, taskNo, targetStationId, true, null);
                if (!result) {
                    continue;
                }
                sleep(1000);
                if (Thread.currentThread().isInterrupted()) {
                    return false;
                }
            }
            if (nextStationId != null && nextStationDeviceNo != null) {
                boolean result = stationMoveToNext(taskNo, currentStationId, currentStationDeviceNo, nextStationId, nextStationDeviceNo, taskNo, targetStationId);
                if (!result) {
                    continue;
                }
                lastStationId = currentStationId;
            }
            if (currentStationId.equals(targetStationId)) {
                break;
            }
            i++;
            executeTime = System.currentTimeMillis();
            sleep(1000);
            if (Thread.currentThread().isInterrupted()) {
                return false;
            }
        }
        if (generateBarcode) {
            if (lastStationId != null && targetStationDeviceNo != null) {
                while (true) {
                    if (Thread.currentThread().isInterrupted()) {
                        break;
                    }
                    boolean result = generateStationBarcode(taskNo, targetStationId, targetStationDeviceNo);
                    sleep(1000);
                    if (!result) {
                        continue;
                    }
                    break;
                }
            }
        }
        if (clearData) {
            sleep(10000);
            if (Thread.currentThread().isInterrupted()) {
                return true;
            }
            if (lastStationId != null && targetStationDeviceNo != null) {
                while (true) {
                    if (Thread.currentThread().isInterrupted()) {
                        break;
                    }
                    boolean result = clearStation(targetStationDeviceNo, taskNo, targetStationId);
                    sleep(1000);
                    if (!result) {
                        continue;
                    }
                    break;
                }
            }
        }
        return true;
    }
    // stationMoveByPathIds 方法已删除,功能已整合到 runTaskLoop
    private void sleep(long ms) {
        try {
@@ -545,32 +470,40 @@
        }
    }
    public synchronized boolean setLockStation(Integer uuid) {
        if (LOCK_STATION == 0) {
            LOCK_STATION = uuid;
            return true;
        }else {
            if(LOCK_STATION == uuid) {
                return true;
            }
        }
        return false;
    /**
     * 获取站点锁,如果不存在则创建
     */
    private ReentrantLock getStationLock(Integer stationId) {
        return stationLocks.computeIfAbsent(stationId, k -> new ReentrantLock());
    }
    public synchronized boolean releaseLockStation(Integer uuid) {
        if (LOCK_STATION != uuid) {
            return false;
    /**
     * 按顺序锁定多个站点(避免死锁)
     */
    private void lockStations(Integer... stationIds) {
        Integer[] sorted = Arrays.copyOf(stationIds, stationIds.length);
        Arrays.sort(sorted);
        for (Integer stationId : sorted) {
            getStationLock(stationId).lock();
        }
        }
        LOCK_STATION = 0;
        return true;
    /**
     * 按逆序解锁多个站点
     */
    private void unlockStations(Integer... stationIds) {
        Integer[] sorted = Arrays.copyOf(stationIds, stationIds.length);
        Arrays.sort(sorted);
        for (int i = sorted.length - 1; i >= 0; i--) {
            getStationLock(sorted[i]).unlock();
        }
    }
    public synchronized boolean updateStationData(Integer lockTaskNo, Integer stationId, Integer deviceNo, Integer taskNo, Integer targetStaNo, Boolean isLoading, String barcode, Boolean runBlock) {
        if (LOCK_STATION != lockTaskNo) {
            return false;
        }
    /**
     * 更新站点数据(调用前必须已持有该站点的锁)
     */
    private boolean updateStationDataInternal(Integer stationId, Integer deviceNo, Integer taskNo, Integer targetStaNo,
            Boolean isLoading, String barcode, Boolean runBlock) {
        List<ZyStationStatusEntity> statusList = deviceStatusMap.get(deviceNo);
        if (statusList == null) {
            return false;
@@ -605,8 +538,13 @@
        return true;
    }
    public synchronized boolean initStationMove(Integer lockTaskNo, Integer currentStationId, Integer currentStationDeviceNo, Integer taskNo, Integer targetStationId, Boolean isLoading, String barcode) {
        boolean executeResult = lockExecute(lockTaskNo, () -> {
    /**
     * 初始化站点移动(使用站点级锁)
     */
    public boolean initStationMove(Integer lockTaskNo, Integer currentStationId, Integer currentStationDeviceNo,
            Integer taskNo, Integer targetStationId, Boolean isLoading, String barcode) {
        lockStations(currentStationId);
        try {
            List<ZyStationStatusEntity> statusList = deviceStatusMap.get(currentStationDeviceNo);
            if (statusList == null) {
                return false;
@@ -625,25 +563,28 @@
                }
            }
            boolean result = updateStationData(lockTaskNo, currentStationId, currentStationDeviceNo, taskNo, targetStationId, isLoading, barcode, false);
            if (!result) {
                return false;
            return updateStationDataInternal(currentStationId, currentStationDeviceNo, taskNo, targetStationId,
                    isLoading, barcode, false);
        } finally {
            unlockStations(currentStationId);
            }
            return true;
        });
        return executeResult;
    }
    public synchronized boolean stationMoveToNext(Integer lockTaskNo, Integer currentStationId, Integer currentStationDeviceNo, Integer nextStationId, Integer nextStationDeviceNo, Integer taskNo, Integer targetStaNo) {
        boolean executeResult = lockExecute(lockTaskNo, () -> {
    /**
     * 站点移动到下一个位置(使用站点级锁,按ID顺序获取锁避免死锁)
     */
    public boolean stationMoveToNext(Integer lockTaskNo, Integer currentStationId, Integer currentStationDeviceNo,
            Integer nextStationId, Integer nextStationDeviceNo, Integer taskNo, Integer targetStaNo) {
        // 同时锁定当前站点和下一个站点(按ID顺序,避免死锁)
        lockStations(currentStationId, nextStationId);
        try {
            List<ZyStationStatusEntity> statusList = deviceStatusMap.get(currentStationDeviceNo);
            if (statusList == null) {
                return false;
            }
            List<ZyStationStatusEntity> nextStatusList = deviceStatusMap.get(nextStationDeviceNo);
            if (statusList == null) {
            if (nextStatusList == null) {
                return false;
            }
@@ -661,23 +602,31 @@
                return false;
            }
            boolean result = updateStationData(lockTaskNo, nextStationId, nextStationDeviceNo, taskNo, targetStaNo, true, null, false);
            boolean result = updateStationDataInternal(nextStationId, nextStationDeviceNo, taskNo, targetStaNo, true,
                    null, false);
            if (!result) {
                return false;
            }
            boolean result2 = updateStationData(lockTaskNo, currentStationId, currentStationDeviceNo, 0, 0, false, "", false);
            boolean result2 = updateStationDataInternal(currentStationId, currentStationDeviceNo, 0, 0, false, "",
                    false);
            if (!result2) {
                return false;
            }
            return true;
        });
        return executeResult;
        } finally {
            unlockStations(currentStationId, nextStationId);
        }
    }
    public synchronized boolean generateStationBarcode(Integer lockTaskNo, Integer currentStationId, Integer currentStationDeviceNo) {
        boolean executeResult = lockExecute(lockTaskNo, () -> {
    /**
     * 生成站点条码(使用站点级锁)
     */
    public boolean generateStationBarcode(Integer lockTaskNo, Integer currentStationId,
            Integer currentStationDeviceNo) {
        lockStations(currentStationId);
        try {
            List<ZyStationStatusEntity> statusList = deviceStatusMap.get(currentStationDeviceNo);
            if (statusList == null) {
                return false;
@@ -693,20 +642,21 @@
            Random random = new Random();
            String barcodeTime = String.valueOf(System.currentTimeMillis());
            String barcode = String.valueOf(random.nextInt(10)) + String.valueOf(random.nextInt(10)) + barcodeTime.substring(7);
            String barcode = String.valueOf(random.nextInt(10)) + String.valueOf(random.nextInt(10))
                    + barcodeTime.substring(7);
            boolean result = updateStationData(lockTaskNo, currentStationId, currentStationDeviceNo, null, null, null, barcode, null);
            if (!result) {
                return false;
            return updateStationDataInternal(currentStationId, currentStationDeviceNo, null, null, null, barcode, null);
        } finally {
            unlockStations(currentStationId);
            }
            return true;
        });
        return executeResult;
    }
    public synchronized boolean clearStation(Integer deviceNo, Integer lockTaskNo, Integer currentStationId) {
        boolean executeResult = lockExecute(lockTaskNo, () -> {
    /**
     * 清除站点数据(使用站点级锁)
     */
    public boolean clearStation(Integer deviceNo, Integer lockTaskNo, Integer currentStationId) {
        lockStations(currentStationId);
        try {
            List<ZyStationStatusEntity> statusList = deviceStatusMap.get(deviceNo);
            if (statusList == null) {
                return false;
@@ -719,18 +669,19 @@
                return false;
            }
            boolean result = updateStationData(deviceNo, lockTaskNo, currentStationId, 0, 0, false, "", false);
            if (!result) {
                return false;
            return updateStationDataInternal(currentStationId, deviceNo, 0, 0, false, "", false);
        } finally {
            unlockStations(currentStationId);
            }
            return true;
        });
        return executeResult;
    }
    public synchronized boolean runBlockStation(Integer lockTaskNo, Integer currentStationId, Integer currentStationDeviceNo, Integer taskNo, Integer blockStationId) {
        boolean executeResult = lockExecute(lockTaskNo, () -> {
    /**
     * 标记站点堵塞(使用站点级锁)
     */
    public boolean runBlockStation(Integer lockTaskNo, Integer currentStationId, Integer currentStationDeviceNo,
            Integer taskNo, Integer blockStationId) {
        lockStations(currentStationId);
        try {
            List<ZyStationStatusEntity> statusList = deviceStatusMap.get(currentStationDeviceNo);
            if (statusList == null) {
                return false;
@@ -743,24 +694,38 @@
                return false;
            }
            boolean result = updateStationData(lockTaskNo, currentStationId, currentStationDeviceNo, taskNo, blockStationId, true, "", true);
            if (!result) {
                return false;
            return updateStationDataInternal(currentStationId, currentStationDeviceNo, taskNo, blockStationId, true, "",
                    true);
        } finally {
            unlockStations(currentStationId);
            }
            return true;
        });
        return executeResult;
    }
    public boolean lockExecute(Integer taskNo, Supplier<Boolean> function) {
        if (!setLockStation(taskNo)) {
            return false;
    /**
     * 清除站点堵塞标记(堵塞恢复时使用)
     */
    public void clearRunBlock(Integer stationId, Integer deviceNo) {
        lockStations(stationId);
        try {
            List<ZyStationStatusEntity> statusList = deviceStatusMap.get(deviceNo);
            if (statusList == null) {
                return;
        }
        boolean result = function.get();
        releaseLockStation(taskNo);
        return result;
            ZyStationStatusEntity currentStatus = statusList.stream()
                    .filter(item -> item.getStationId().equals(stationId)).findFirst().orElse(null);
            if (currentStatus == null) {
                return;
            }
            if (currentStatus.isRunBlock()) {
                currentStatus.setRunBlock(false);
                News.info("[WCS Debug] 站点{}堵塞标记已清除", stationId);
            }
        } finally {
            unlockStations(stationId);
        }
    }
    private boolean checkTaskNoInArea(Integer taskNo) {
src/main/java/com/zy/core/plugin/FakeProcess.java
@@ -88,6 +88,7 @@
    /**
     * 带超时保护执行方法
     *
     * @param taskName 任务名称(用于日志)
     * @param task 要执行的任务
     */
@@ -140,22 +141,26 @@
        asyncFakeRunThread = new Thread(() -> {
            while (!Thread.currentThread().isInterrupted()) {
                try {
                    Config enableFakeConfig = configService.selectOne(new EntityWrapper<Config>().eq("code", "enableFake"));
                    Config enableFakeConfig = configService
                            .selectOne(new EntityWrapper<Config>().eq("code", "enableFake"));
                    if (enableFakeConfig != null) {
                        enableFake = enableFakeConfig.getValue();
                    }
                    Config fakeRealTaskRequestWmsConfig = configService.selectOne(new EntityWrapper<Config>().eq("code", "fakeRealTaskRequestWms"));
                    Config fakeRealTaskRequestWmsConfig = configService
                            .selectOne(new EntityWrapper<Config>().eq("code", "fakeRealTaskRequestWms"));
                    if (fakeRealTaskRequestWmsConfig != null) {
                        fakeRealTaskRequestWms = fakeRealTaskRequestWmsConfig.getValue();
                    }
                    Config fakeGenerateInTaskConfig = configService.selectOne(new EntityWrapper<Config>().eq("code", "fakeGenerateInTask"));
                    Config fakeGenerateInTaskConfig = configService
                            .selectOne(new EntityWrapper<Config>().eq("code", "fakeGenerateInTask"));
                    if (fakeGenerateInTaskConfig != null) {
                        fakeGenerateInTask = fakeGenerateInTaskConfig.getValue();
                    }
                    Config fakeGenerateOutTaskConfig = configService.selectOne(new EntityWrapper<Config>().eq("code", "fakeGenerateOutTask"));
                    Config fakeGenerateOutTaskConfig = configService
                            .selectOne(new EntityWrapper<Config>().eq("code", "fakeGenerateOutTask"));
                    if (fakeGenerateOutTaskConfig != null) {
                        fakeGenerateOutTask = fakeGenerateOutTaskConfig.getValue();
                    }
@@ -197,7 +202,7 @@
    }
    //检测入库站是否有任务生成,并仿真生成模拟入库站点数据
    private void checkInStationHasTask() {
    private synchronized void checkInStationHasTask() {
        if (!enableFake.equals("Y")) {
            return;
        }
@@ -235,9 +240,10 @@
                //满足自动、无物、工作号0,生成入库数据
                if (stationProtocol.isAutoing()
                        && !stationProtocol.isLoading()
                        && stationProtocol.getTaskNo() == 0
                ) {
                    StationCommand command = stationThread.getCommand(StationCommandType.MOVE, commonService.getWorkNo(WrkIoType.FAKE_TASK_NO.id), stationId, entity.getBarcodeStation().getStationId(), 0);
                        && stationProtocol.getTaskNo() == 0) {
                    StationCommand command = stationThread.getCommand(StationCommandType.MOVE,
                            commonService.getWorkNo(WrkIoType.FAKE_TASK_NO.id), stationId,
                            entity.getBarcodeStation().getStationId(), 0);
                    MessageQueue.offer(SlaveType.Devp, basDevp.getDevpNo(), new Task(2, command));
                    redisUtil.set(RedisKeyType.GENERATE_FAKE_IN_STATION_DATA_LIMIT.key + stationId, "lock", 5);
                }
@@ -246,7 +252,7 @@
    }
    //生成仿真模拟入库任务
    private void generateFakeInTask() {
    private synchronized void generateFakeInTask() {
        if (!enableFake.equals("Y")) {
            return;
        }
@@ -288,19 +294,20 @@
                //满足自动、有物、有工作号,生成入库数据
                if (stationProtocol.isAutoing()
                        && stationProtocol.isLoading()
                        && stationProtocol.getTaskNo() > 0
                ) {
                        && stationProtocol.getTaskNo() > 0) {
                    if (Cools.isEmpty(stationProtocol.getBarcode())) {
                        continue;
                    }
                    //检测任务是否生成
                    List<WrkMast> wrkMasts = wrkMastService.selectList(new EntityWrapper<WrkMast>().eq("barcode", stationProtocol.getBarcode()));
                    List<WrkMast> wrkMasts = wrkMastService
                            .selectList(new EntityWrapper<WrkMast>().eq("barcode", stationProtocol.getBarcode()));
                    if (!wrkMasts.isEmpty()) {
                        continue;
                    }
                    List<LocMast> locMastList = locMastService.selectList(new EntityWrapper<LocMast>().eq("loc_sts", String.valueOf(LocStsType.O)));
                    List<LocMast> locMastList = locMastService
                            .selectList(new EntityWrapper<LocMast>().eq("loc_sts", String.valueOf(LocStsType.O)));
                    if (locMastList.isEmpty()) {
                        continue;
                    }
@@ -326,7 +333,8 @@
                    taskParam.setBarcode(stationProtocol.getBarcode());
                    WrkMast wrkMast = commonService.createInTask(taskParam);
                    StationCommand command = stationThread.getCommand(StationCommandType.MOVE, wrkMast.getWrkNo(), stationId, stationId, 0);
                    StationCommand command = stationThread.getCommand(StationCommandType.MOVE, wrkMast.getWrkNo(),
                            stationId, stationId, 0);
                    if(command == null){
                        News.taskInfo(wrkMast.getWrkNo(), "获取输送线命令失败");
                        continue;
@@ -339,7 +347,7 @@
    }
    //生成仿真模拟出库任务
    private void generateFakeOutTask() {
    private synchronized void generateFakeOutTask() {
        if (!enableFake.equals("Y")) {
            return;
        }
@@ -381,9 +389,9 @@
                //满足自动、无物、工作号0,生成出库数据
                if (stationProtocol.isAutoing()
                        && !stationProtocol.isLoading()
                        && stationProtocol.getTaskNo() == 0
                ) {
                    List<LocMast> locMastList = locMastService.selectList(new EntityWrapper<LocMast>().eq("loc_sts", String.valueOf(LocStsType.F)));
                        && stationProtocol.getTaskNo() == 0) {
                    List<LocMast> locMastList = locMastService
                            .selectList(new EntityWrapper<LocMast>().eq("loc_sts", String.valueOf(LocStsType.F)));
                    if (locMastList.isEmpty()) {
                        continue;
                    }
@@ -452,14 +460,14 @@
                    //满足自动、有物、有工作号,生成入库数据
                    if (stationProtocol.isAutoing()
                            && stationProtocol.isLoading()
                            && stationProtocol.getTaskNo() > 0
                    ) {
                            && stationProtocol.getTaskNo() > 0) {
                        if (Cools.isEmpty(stationProtocol.getBarcode())) {
                            continue;
                        }
                        //检测任务是否生成
                        List<WrkMast> wrkMasts = wrkMastService.selectList(new EntityWrapper<WrkMast>().eq("barcode", stationProtocol.getBarcode()));
                        List<WrkMast> wrkMasts = wrkMastService
                                .selectList(new EntityWrapper<WrkMast>().eq("barcode", stationProtocol.getBarcode()));
                        if (!wrkMasts.isEmpty()) {
                            continue;
                        }
@@ -468,13 +476,26 @@
                        if (lock != null) {
                            continue;
                        }
                        redisUtil.set(RedisKeyType.GENERATE_IN_TASK_LIMIT.key + stationId, "lock", 2);
                        String response = wmsOperateUtils.applyInTask(stationProtocol.getBarcode(), stationProtocol.getStationId(), stationProtocol.getPalletHeight());
                        if (response == null) {
                            News.error("请求WMS入库接口失败,接口未响应!!!response:{}", response);
                        String barcode = stationProtocol.getBarcode();
                        Integer stationIdVal = stationProtocol.getStationId();
                        // 1. 首先查询是否有已完成的异步响应
                        String response = wmsOperateUtils.queryAsyncInTaskResponse(barcode, stationIdVal);
                        if (response != null) {
                            // 2. 有响应结果,处理响应
                            if (response.equals("FAILED") || response.startsWith("ERROR:")) {
                                // 请求失败,重新发起异步请求
                                News.error("WMS入库请求失败,重新发起请求,barcode={},stationId={},response={}", barcode,
                                        stationIdVal, response);
                                wmsOperateUtils.applyInTaskAsync(barcode, stationIdVal,
                                        stationProtocol.getPalletHeight());
                                redisUtil.set(RedisKeyType.GENERATE_IN_TASK_LIMIT.key + stationId, "lock", 2);
                            continue;
                        }
                            // 解析响应
                        JSONObject jsonObject = JSON.parseObject(response);
                        if (jsonObject.getInteger("code").equals(200)) {
                            StartupDto dto = jsonObject.getObject("data", StartupDto.class);
@@ -483,15 +504,34 @@
                            taskParam.setTaskNo(dto.getTaskNo());
                            taskParam.setLocNo(dto.getLocNo());
                            taskParam.setTaskPri(dto.getTaskPri());
                            taskParam.setBarcode(stationProtocol.getBarcode());
                                taskParam.setBarcode(barcode);
                            WrkMast wrkMast = commonService.createInTask(taskParam);
                            StationCommand command = stationThread.getCommand(StationCommandType.WRITE_INFO, wrkMast.getWrkNo(), stationId, stationId, 0);
                                StationCommand command = stationThread.getCommand(StationCommandType.WRITE_INFO,
                                        wrkMast.getWrkNo(), stationId, stationId, 0);
                            if (command == null) {
                                News.taskInfo(wrkMast.getWrkNo(), "获取输送线命令失败");
                                continue;
                            }
                            MessageQueue.offer(SlaveType.Devp, basDevp.getDevpNo(), new Task(2, command));
                            } else {
                                // 接口返回非200,重新发起请求
                                News.error("WMS入库接口返回非200,重新发起请求,barcode={},stationId={},response={}", barcode,
                                        stationIdVal, response);
                                wmsOperateUtils.applyInTaskAsync(barcode, stationIdVal,
                                        stationProtocol.getPalletHeight());
                                redisUtil.set(RedisKeyType.GENERATE_IN_TASK_LIMIT.key + stationId, "lock", 2);
                            }
                        } else {
                            // 3. 没有响应结果,检查是否有请求正在进行中
                            if (!wmsOperateUtils.isAsyncRequestInProgress(barcode, stationIdVal)) {
                                // 没有请求进行中,发起新的异步请求
                                News.info("发起异步WMS入库请求,barcode={},stationId={}", barcode, stationIdVal);
                                wmsOperateUtils.applyInTaskAsync(barcode, stationIdVal,
                                        stationProtocol.getPalletHeight());
                                redisUtil.set(RedisKeyType.GENERATE_IN_TASK_LIMIT.key + stationId, "lock", 2);
                            }
                            // 如果有请求进行中,等待下次循环再检查
                        }
                    }
                }
@@ -502,7 +542,7 @@
    }
    //计算所有站点停留时间
    public void calcAllStationStayTime() {
    public synchronized void calcAllStationStayTime() {
        List<BasDevp> basDevps = basDevpService.selectList(new EntityWrapper<>());
        for (BasDevp basDevp : basDevps) {
            StationThread stationThread = (StationThread) SlaveConnection.get(SlaveType.Devp, basDevp.getDevpNo());
@@ -512,11 +552,13 @@
            List<StationProtocol> list = stationThread.getStatus();
            for (StationProtocol stationProtocol : list) {
                if (stationProtocol.getTaskNo() > 0 && !stationStayTimeMap.containsKey(stationProtocol.getStationId())) {
                if (stationProtocol.getTaskNo() > 0
                        && !stationStayTimeMap.containsKey(stationProtocol.getStationId())) {
                    stationStayTimeMap.put(stationProtocol.getStationId(), System.currentTimeMillis());
                }
                if(stationProtocol.getTaskNo() <= 0 && stationStayTimeMap.containsKey(stationProtocol.getStationId())) {
                if (stationProtocol.getTaskNo() <= 0
                        && stationStayTimeMap.containsKey(stationProtocol.getStationId())) {
                    stationStayTimeMap.remove(stationProtocol.getStationId());
                }
            }
@@ -524,7 +566,7 @@
    }
    //检测出库站点停留是否超时
    public void checkOutStationStayTimeOut() {
    public synchronized void checkOutStationStayTimeOut() {
        List<BasDevp> basDevps = basDevpService.selectList(new EntityWrapper<>());
        for (BasDevp basDevp : basDevps) {
            List<StationObjModel> outStationList = basDevp.getOutStationList$();
@@ -534,7 +576,8 @@
            }
            for (StationObjModel stationObjModel : outStationList) {
                Object lock = redisUtil.get(RedisKeyType.CHECK_OUT_STATION_STAY_TIME_OUT_LIMIT.key + stationObjModel.getStationId());
                Object lock = redisUtil
                        .get(RedisKeyType.CHECK_OUT_STATION_STAY_TIME_OUT_LIMIT.key + stationObjModel.getStationId());
                if(lock != null){
                    continue;
                }
@@ -545,26 +588,31 @@
                }
                if(System.currentTimeMillis() - stayTime > 1000 * 15) {
                    StationThread stationThread = (StationThread) SlaveConnection.get(SlaveType.Devp, stationObjModel.getDeviceNo());
                    StationThread stationThread = (StationThread) SlaveConnection.get(SlaveType.Devp,
                            stationObjModel.getDeviceNo());
                    if(stationThread == null){
                        continue;
                    }
                    StationCommand command = stationThread.getCommand(StationCommandType.RESET, 0, stationObjModel.getStationId(), 0, 0);
                    StationCommand command = stationThread.getCommand(StationCommandType.RESET, 0,
                            stationObjModel.getStationId(), 0, 0);
                    if(command == null){
                        continue;
                    }
                    MessageQueue.offer(SlaveType.Devp, stationObjModel.getDeviceNo(), new Task(2, command));
                    redisUtil.set(RedisKeyType.CHECK_OUT_STATION_STAY_TIME_OUT_LIMIT.key + stationObjModel.getStationId(), "lock",10);
                    News.info("输送站点出库重置命令下发成功,站点号={},命令数据={}", stationObjModel.getStationId(), JSON.toJSONString(command));
                    redisUtil.set(
                            RedisKeyType.CHECK_OUT_STATION_STAY_TIME_OUT_LIMIT.key + stationObjModel.getStationId(),
                            "lock", 10);
                    News.info("输送站点出库重置命令下发成功,站点号={},命令数据={}", stationObjModel.getStationId(),
                            JSON.toJSONString(command));
                }
            }
        }
    }
    //检测入库站点堆垛机是否取走货物
    public void checkInStationCrnTake() {
    public synchronized void checkInStationCrnTake() {
        List<BasCrnp> basCrnps = basCrnpService.selectList(new EntityWrapper<>());
        for (BasCrnp basCrnp : basCrnps) {
            List<StationObjModel> inStationList = basCrnp.getInStationList$();
@@ -586,14 +634,16 @@
        }
    }
    private void checkInStationListCrnTake(List<StationObjModel> inStationList) {
    private synchronized void checkInStationListCrnTake(List<StationObjModel> inStationList) {
        for (StationObjModel stationObjModel : inStationList) {
            Object lock = redisUtil.get(RedisKeyType.CHECK_IN_STATION_STAY_TIME_OUT_LIMIT.key + stationObjModel.getStationId());
            Object lock = redisUtil
                    .get(RedisKeyType.CHECK_IN_STATION_STAY_TIME_OUT_LIMIT.key + stationObjModel.getStationId());
            if(lock != null){
                continue;
            }
            StationThread stationThread = (StationThread) SlaveConnection.get(SlaveType.Devp, stationObjModel.getDeviceNo());
            StationThread stationThread = (StationThread) SlaveConnection.get(SlaveType.Devp,
                    stationObjModel.getDeviceNo());
            if(stationThread == null){
                continue;
            }
@@ -605,7 +655,8 @@
            }
            if(stationProtocol.getTaskNo() > 0) {
                StationCommand command = stationThread.getCommand(StationCommandType.RESET, 0, stationObjModel.getStationId(), 0, 0);
                StationCommand command = stationThread.getCommand(StationCommandType.RESET, 0,
                        stationObjModel.getStationId(), 0, 0);
                if(command == null){
                    continue;
                }
@@ -613,10 +664,14 @@
                WrkMast wrkMast = wrkMastService.selectByWorkNo(stationProtocol.getTaskNo());
                if (wrkMast == null) {
                    MessageQueue.offer(SlaveType.Devp, stationObjModel.getDeviceNo(), new Task(2, command));
                    redisUtil.set(RedisKeyType.CHECK_IN_STATION_STAY_TIME_OUT_LIMIT.key + stationObjModel.getStationId(), "lock",10);
                    News.info("输送站点重置命令下发成功(task_over),站点号={},命令数据={}", stationObjModel.getStationId(), JSON.toJSONString(command));
                    redisUtil.set(
                            RedisKeyType.CHECK_IN_STATION_STAY_TIME_OUT_LIMIT.key + stationObjModel.getStationId(),
                            "lock", 10);
                    News.info("输送站点重置命令下发成功(task_over),站点号={},命令数据={}", stationObjModel.getStationId(),
                            JSON.toJSONString(command));
                }else {
                    if (wrkMast.getWrkSts() != WrkStsType.NEW_INBOUND.sts && wrkMast.getWrkSts() != WrkStsType.INBOUND_DEVICE_RUN.sts) {
                    if (wrkMast.getWrkSts() != WrkStsType.NEW_INBOUND.sts
                            && wrkMast.getWrkSts() != WrkStsType.INBOUND_DEVICE_RUN.sts) {
                        Integer crnNo = wrkMast.getCrnNo();
                        if (crnNo != null) {
                            CrnThread crnThread = (CrnThread) SlaveConnection.get(SlaveType.Crn, crnNo);
@@ -624,16 +679,20 @@
                                continue;
                            }
                            CrnProtocol crnProtocol = crnThread.getStatus();
                            if (!crnProtocol.getStatusType().equals(CrnStatusType.PUT_MOVING) && !crnProtocol.getStatusType().equals(CrnStatusType.PUTTING)) {
                            if (!crnProtocol.getStatusType().equals(CrnStatusType.PUT_MOVING)
                                    && !crnProtocol.getStatusType().equals(CrnStatusType.PUTTING)) {
                                continue;
                            }
                            MessageQueue.offer(SlaveType.Devp, stationObjModel.getDeviceNo(), new Task(2, command));
                            redisUtil.set(RedisKeyType.CHECK_IN_STATION_STAY_TIME_OUT_LIMIT.key + stationObjModel.getStationId(), "lock",10);
                            News.info("输送站点重置命令下发成功(crn_fetch),站点号={},命令数据={}", stationObjModel.getStationId(), JSON.toJSONString(command));
                            redisUtil.set(RedisKeyType.CHECK_IN_STATION_STAY_TIME_OUT_LIMIT.key
                                    + stationObjModel.getStationId(), "lock", 10);
                            News.info("输送站点重置命令下发成功(crn_fetch),站点号={},命令数据={}", stationObjModel.getStationId(),
                                    JSON.toJSONString(command));
                        }else {
                            Integer dualCrnNo = wrkMast.getDualCrnNo();
                            DualCrnThread dualCrnThread = (DualCrnThread) SlaveConnection.get(SlaveType.DualCrn, dualCrnNo);
                            DualCrnThread dualCrnThread = (DualCrnThread) SlaveConnection.get(SlaveType.DualCrn,
                                    dualCrnNo);
                            if (dualCrnThread == null) {
                                continue;
                            }
@@ -653,8 +712,10 @@
                            }
                            MessageQueue.offer(SlaveType.Devp, stationObjModel.getDeviceNo(), new Task(2, command));
                            redisUtil.set(RedisKeyType.CHECK_IN_STATION_STAY_TIME_OUT_LIMIT.key + stationObjModel.getStationId(), "lock",10);
                            News.info("输送站点重置命令下发成功(crn_fetch),站点号={},命令数据={}", stationObjModel.getStationId(), JSON.toJSONString(command));
                            redisUtil.set(RedisKeyType.CHECK_IN_STATION_STAY_TIME_OUT_LIMIT.key
                                    + stationObjModel.getStationId(), "lock", 10);
                            News.info("输送站点重置命令下发成功(crn_fetch),站点号={},命令数据={}", stationObjModel.getStationId(),
                                    JSON.toJSONString(command));
                        }
                    }
                }
@@ -663,7 +724,7 @@
    }
    //堆垛机任务执行完成
    public void crnIoExecuteFinish() {
    public synchronized void crnIoExecuteFinish() {
        List<BasCrnp> basCrnps = basCrnpService.selectList(new EntityWrapper<>());
        for (BasCrnp basCrnp : basCrnps) {
            CrnThread crnThread = (CrnThread) SlaveConnection.get(SlaveType.Crn, basCrnp.getCrnNo());
@@ -678,8 +739,7 @@
            if (crnProtocol.getMode() == CrnModeType.AUTO.id
                    && crnProtocol.getTaskNo() > 0
                    && crnProtocol.getStatus() == CrnStatusType.WAITING.id
            ) {
                    && crnProtocol.getStatus() == CrnStatusType.WAITING.id) {
                Object lock = redisUtil.get(RedisKeyType.CRN_IO_EXECUTE_FINISH_LIMIT.key + basCrnp.getCrnNo());
                if(lock != null){
                    continue;
@@ -710,12 +770,14 @@
                            continue;
                        }
                        StationThread stationThread = (StationThread) SlaveConnection.get(SlaveType.Devp, stationObjModel.getDeviceNo());
                        StationThread stationThread = (StationThread) SlaveConnection.get(SlaveType.Devp,
                                stationObjModel.getDeviceNo());
                        if (stationThread == null) {
                            continue;
                        }
                        //生成仿真站点数据
                        StationCommand command = stationThread.getCommand(StationCommandType.WRITE_INFO, 9998, wrkMast.getSourceStaNo(), 0, 0);
                        StationCommand command = stationThread.getCommand(StationCommandType.WRITE_INFO, 9998,
                                wrkMast.getSourceStaNo(), 0, 0);
                        MessageQueue.offer(SlaveType.Devp, stationObjModel.getDeviceNo(), new Task(2, command));
                    }
                }else if(wrkMast.getWrkSts() == WrkStsType.LOC_MOVE_RUN.sts){
src/main/java/com/zy/core/plugin/NormalProcess.java
@@ -32,6 +32,7 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -81,6 +82,24 @@
     * 入库站,根据条码扫描生成入库工作档
     */
    public synchronized void generateStoreWrkFile() {
        try {
            Object systemConfigMapObj = redisUtil.get(RedisKeyType.SYSTEM_CONFIG_MAP.key);
            if (systemConfigMapObj == null) {
                return;
            }
            HashMap<String, String> systemConfigMap = (HashMap<String, String>) systemConfigMapObj;
            int conveyorStationTaskLimit = 30;
            String conveyorStationTaskLimitStr = systemConfigMap.get("conveyorStationTaskLimit");
            if (conveyorStationTaskLimitStr != null) {
                conveyorStationTaskLimit = Integer.parseInt(conveyorStationTaskLimitStr);
            }
            int currentStationTaskCount = stationOperateProcessUtils.getCurrentStationTaskCount();
            if (currentStationTaskCount > conveyorStationTaskLimit) {
                News.error("输送站点任务已达到上限,上限值:{},站点任务数:{}", conveyorStationTaskLimit, currentStationTaskCount);
                return;
            }
        List<BasDevp> basDevps = basDevpService.selectList(new EntityWrapper<>());
        for (BasDevp basDevp : basDevps) {
            StationThread stationThread = (StationThread) SlaveConnection.get(SlaveType.Devp, basDevp.getDevpNo());
@@ -105,29 +124,14 @@
                //满足自动、有物、有工作号,生成入库数据
                if (stationProtocol.isAutoing()
                        && stationProtocol.isLoading()
                        && stationProtocol.isInEnable()
                        && stationProtocol.getTaskNo() > 0
                ) {
                    if (stationProtocol.getError() > 0) {
                        Object backLock = redisUtil.get(RedisKeyType.GENERATE_STATION_BACK_LIMIT.key + stationId);
                        if (backLock != null) {
                            continue;
                        }
                        //报警回退
                        StationCommand command = stationThread.getCommand(StationCommandType.MOVE, commonService.getWorkNo(WrkIoType.STATION_BACK.id), stationId, entity.getBackStation().getStationId(), 0);
                        MessageQueue.offer(SlaveType.Devp, basDevp.getDevpNo(), new Task(2, command));
                        redisUtil.set(RedisKeyType.GENERATE_STATION_BACK_LIMIT.key + stationId, "lock", 15);
                        News.info("{}站点报警回退成功,数据包:{}", stationId, JSON.toJSONString(command));
                        continue;
                    }
                            && stationProtocol.getTaskNo() > 0) {
                    if (Cools.isEmpty(stationProtocol.getBarcode())) {
                        continue;
                    }
                    //检测任务是否生成
                    List<WrkMast> wrkMasts = wrkMastService.selectList(new EntityWrapper<WrkMast>().eq("barcode", stationProtocol.getBarcode()));
                        List<WrkMast> wrkMasts = wrkMastService
                                .selectList(new EntityWrapper<WrkMast>().eq("barcode", stationProtocol.getBarcode()));
                    if (!wrkMasts.isEmpty()) {
                        continue;
                    }
@@ -136,13 +140,26 @@
                    if (lock != null) {
                        continue;
                    }
                    redisUtil.set(RedisKeyType.GENERATE_IN_TASK_LIMIT.key + stationId, "lock", 2);
                    String response = wmsOperateUtils.applyInTask(stationProtocol.getBarcode(), stationProtocol.getStationId(), stationProtocol.getPalletHeight());
                    if (response == null) {
                        News.error("请求WMS入库接口失败,接口未响应!!!response:{}", response);
                        String barcode = stationProtocol.getBarcode();
                        Integer stationIdVal = stationProtocol.getStationId();
                        // 1. 首先查询是否有已完成的异步响应
                        String response = wmsOperateUtils.queryAsyncInTaskResponse(barcode, stationIdVal);
                        if (response != null) {
                            // 2. 有响应结果,处理响应
                            if (response.equals("FAILED") || response.startsWith("ERROR:")) {
                                // 请求失败,重新发起异步请求
                                News.error("WMS入库请求失败,重新发起请求,barcode={},stationId={},response={}", barcode,
                                        stationIdVal, response);
                                wmsOperateUtils.applyInTaskAsync(barcode, stationIdVal,
                                        stationProtocol.getPalletHeight());
                                redisUtil.set(RedisKeyType.GENERATE_IN_TASK_LIMIT.key + stationId, "lock", 2);
                        continue;
                    }
                            // 解析响应
                    JSONObject jsonObject = JSON.parseObject(response);
                    if (jsonObject.getInteger("code").equals(200)) {
                        StartupDto dto = jsonObject.getObject("data", StartupDto.class);
@@ -151,12 +168,41 @@
                        taskParam.setTaskNo(dto.getTaskNo());
                        taskParam.setLocNo(dto.getLocNo());
                        taskParam.setTaskPri(dto.getTaskPri());
                        taskParam.setBarcode(stationProtocol.getBarcode());
                                taskParam.setBarcode(barcode);
                        WrkMast wrkMast = commonService.createInTask(taskParam);
                                StationCommand command = stationThread.getCommand(StationCommandType.WRITE_INFO,
                                        wrkMast.getWrkNo(), stationId, stationId, 0);
                                if (command == null) {
                                    News.taskInfo(wrkMast.getWrkNo(), "获取输送线命令失败");
                                    continue;
                                }
                                MessageQueue.offer(SlaveType.Devp, basDevp.getDevpNo(), new Task(2, command));
                            } else {
                                // 接口返回非200,重新发起请求
                                News.error("WMS入库接口返回非200,重新发起请求,barcode={},stationId={},response={}", barcode,
                                        stationIdVal, response);
                                wmsOperateUtils.applyInTaskAsync(barcode, stationIdVal,
                                        stationProtocol.getPalletHeight());
                                redisUtil.set(RedisKeyType.GENERATE_IN_TASK_LIMIT.key + stationId, "lock", 2);
                            }
                        } else {
                            // 3. 没有响应结果,检查是否有请求正在进行中
                            if (!wmsOperateUtils.isAsyncRequestInProgress(barcode, stationIdVal)) {
                                // 没有请求进行中,发起新的异步请求
                                News.info("发起异步WMS入库请求,barcode={},stationId={}", barcode, stationIdVal);
                                wmsOperateUtils.applyInTaskAsync(barcode, stationIdVal,
                                        stationProtocol.getPalletHeight());
                                redisUtil.set(RedisKeyType.GENERATE_IN_TASK_LIMIT.key + stationId, "lock", 2);
                            }
                            // 如果有请求进行中,等待下次循环再检查
                    }
                }
            }
        }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //检测入库站是否有任务生成,并启动入库
src/main/java/com/zy/core/thread/impl/ZyStationV3Thread.java
@@ -2,6 +2,7 @@
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.core.common.DateUtils;
import com.core.common.SpringUtils;
@@ -295,10 +296,7 @@
        }
        if(original.getCommandType() == StationCommandType.MOVE){
            List<Integer> path = original.getNavigatePath();
            if (path == null || path.isEmpty()) {
                path = calcPathStationIds(original.getStationId(), original.getTargetStaNo());
            }
            List<Integer> path = JSON.parseArray(JSON.toJSONString(original.getNavigatePath(), SerializerFeature.DisableCircularReferenceDetect), Integer.class);
            if (path == null || path.isEmpty()) {
                return;
            }
@@ -329,6 +327,7 @@
            sendCommand(segCmd);
            long runTime = System.currentTimeMillis();
            boolean firstRun = true;
            while (true) {
                try {
                    StationProtocol currentStation = findCurrentStationByTask(original.getTaskNo());
@@ -341,7 +340,7 @@
                    }
                    runTime = System.currentTimeMillis();
                    if (currentStation.isRunBlock()) {
                    if (!firstRun && currentStation.isRunBlock()) {
                        break;
                    }
                    int currentIndex = path.indexOf(currentStation.getStationId());
@@ -370,12 +369,26 @@
                        nextCmd.setCommandType(original.getCommandType());
                        nextCmd.setPalletSize(original.getPalletSize());
                        nextCmd.setNavigatePath(new ArrayList<>(path.subList(currentStartIdx, currentEndIdx + 1)));
                        sendCommand(nextCmd);
                        nextCmd.setOriginalNavigatePath(path);
                        while (true) {
                            CommandResponse commandResponse = sendCommand(nextCmd);
                            if (commandResponse == null) {
                                Thread.sleep(200);
                                continue;
                            }
                            if (commandResponse.getResult()) {
                                break;
                            }
                            Thread.sleep(200);
                        }
                    }
                    Thread.sleep(500);
                } catch (Exception e) {
                    break;
                }
                firstRun = false;
            }
        }else {
            sendCommand(original);
src/main/java/com/zy/core/utils/WmsOperateUtils.java
@@ -79,7 +79,8 @@
        String response = null;
        int result = 0;
        try {
            BasStation basStation = basStationService.selectOne(new EntityWrapper<BasStation>().eq("station_id", sourceStaNo));
            BasStation basStation = basStationService
                    .selectOne(new EntityWrapper<BasStation>().eq("station_id", sourceStaNo));
            if(basStation == null){
                News.error("站点{}不存在", sourceStaNo);
                return null;
@@ -106,15 +107,19 @@
                JSONObject jsonObject = JSON.parseObject(response);
                if (jsonObject.getInteger("code") == 200) {
                    result = 1;
                    News.info("请求WMS入库接口成功!!!url:{};request:{};response:{}", wmsUrl + wmsSystemInUrl, JSON.toJSONString(requestParam), response);
                    News.info("请求WMS入库接口成功!!!url:{};request:{};response:{}", wmsUrl + wmsSystemInUrl,
                            JSON.toJSONString(requestParam), response);
                }else {
                    News.info("请求WMS入库接口失败,接口返回Code异常!!!url:{};request:{};response:{}", wmsUrl + wmsSystemInUrl, JSON.toJSONString(requestParam), response);
                    News.info("请求WMS入库接口失败,接口返回Code异常!!!url:{};request:{};response:{}", wmsUrl + wmsSystemInUrl,
                            JSON.toJSONString(requestParam), response);
                }
            }else {
                News.info("请求WMS入库接口失败,接口未响应!!!url:{};request:{};response:{}", wmsUrl + wmsSystemInUrl, JSON.toJSONString(requestParam), response);
                News.info("请求WMS入库接口失败,接口未响应!!!url:{};request:{};response:{}", wmsUrl + wmsSystemInUrl,
                        JSON.toJSONString(requestParam), response);
            }
        } catch (Exception e) {
            News.error("请求WMS入库接口异常!!!url:{};request:{};response:{}", wmsUrl + wmsSystemInUrl, JSON.toJSONString(requestParam), response, e);
            News.error("请求WMS入库接口异常!!!url:{};request:{};response:{}", wmsUrl + wmsSystemInUrl,
                    JSON.toJSONString(requestParam), response, e);
        } finally {
            HttpRequestLog httpRequestLog = new HttpRequestLog();
            httpRequestLog.setName(wmsUrl + wmsSystemInUrl);
@@ -125,6 +130,80 @@
            httpRequestLogService.insert(httpRequestLog);
        }
        return response;
    }
    /**
     * 异步申请入库任务 - 非阻塞版本
     * 将请求提交到线程池异步执行,结果存储到Redis中
     *
     * @param barcode     托盘码
     * @param sourceStaNo 站点编号
     * @param locType1    托盘高度
     */
    public void applyInTaskAsync(String barcode, Integer sourceStaNo, Integer locType1) {
        String requestKey = RedisKeyType.ASYNC_WMS_IN_TASK_REQUEST.key + barcode + "_" + sourceStaNo;
        String responseKey = RedisKeyType.ASYNC_WMS_IN_TASK_RESPONSE.key + barcode + "_" + sourceStaNo;
        // 检查是否已有请求在进行中
        Object existingRequest = redisUtil.get(requestKey);
        if (existingRequest != null) {
            return; // 已有请求在进行中,跳过
        }
        // 标记请求进行中,设置60秒超时
        redisUtil.set(requestKey, "processing", 60);
        // 提交异步任务
        new Thread(() -> {
            try {
                String response = applyInTask(barcode, sourceStaNo, locType1);
                if (response != null) {
                    // 存储响应结果,设置60秒超时
                    redisUtil.set(responseKey, response, 60);
                    News.info("异步WMS入库请求完成,barcode={},stationId={},response={}", barcode, sourceStaNo, response);
                } else {
                    // 请求失败,存储失败标记
                    redisUtil.set(responseKey, "FAILED", 10);
                    News.error("异步WMS入库请求失败,barcode={},stationId={}", barcode, sourceStaNo);
                }
            } catch (Exception e) {
                News.error("异步WMS入库请求异常,barcode={},stationId={},error={}", barcode, sourceStaNo, e.getMessage());
                redisUtil.set(responseKey, "ERROR:" + e.getMessage(), 10);
            } finally {
                // 清除请求进行中标记
                redisUtil.del(requestKey);
            }
        }).start();
    }
    /**
     * 查询异步入库任务请求结果
     *
     * @param barcode   托盘码
     * @param stationId 站点编号
     * @return 响应结果,null表示还未完成或未找到
     */
    public String queryAsyncInTaskResponse(String barcode, Integer stationId) {
        String responseKey = RedisKeyType.ASYNC_WMS_IN_TASK_RESPONSE.key + barcode + "_" + stationId;
        Object response = redisUtil.get(responseKey);
        if (response != null) {
            // 获取后删除,避免重复处理
            redisUtil.del(responseKey);
            return response.toString();
        }
        return null;
    }
    /**
     * 检查是否有异步请求正在进行中
     *
     * @param barcode   托盘码
     * @param stationId 站点编号
     * @return true表示正在请求中
     */
    public boolean isAsyncRequestInProgress(String barcode, Integer stationId) {
        String requestKey = RedisKeyType.ASYNC_WMS_IN_TASK_REQUEST.key + barcode + "_" + stationId;
        return redisUtil.get(requestKey) != null;
    }
    //申请任务重新分配库位
@@ -141,7 +220,8 @@
        }
        String wmsSystemReassignInTaskUrl = null;
        Config wmsSystemReassignInTaskUrlConfig = configService.selectOne(new EntityWrapper<Config>().eq("code", "wmsSystemReassignInTaskUrl"));
        Config wmsSystemReassignInTaskUrlConfig = configService
                .selectOne(new EntityWrapper<Config>().eq("code", "wmsSystemReassignInTaskUrl"));
        if (wmsSystemReassignInTaskUrlConfig != null) {
            wmsSystemReassignInTaskUrl = wmsSystemReassignInTaskUrlConfig.getValue();
        }
@@ -184,15 +264,19 @@
                JSONObject jsonObject = JSON.parseObject(response);
                if (jsonObject.getInteger("code") == 200) {
                    result = 1;
                    News.info("请求申请任务重新分配入库接口成功!!!url:{};request:{};response:{}", wmsUrl + wmsSystemReassignInTaskUrl, JSON.toJSONString(requestParam), response);
                    News.info("请求申请任务重新分配入库接口成功!!!url:{};request:{};response:{}", wmsUrl + wmsSystemReassignInTaskUrl,
                            JSON.toJSONString(requestParam), response);
                } else {
                    News.info("请求申请任务重新分配入库接口失败,接口返回Code异常!!!url:{};request:{};response:{}", wmsUrl + wmsSystemReassignInTaskUrl, JSON.toJSONString(requestParam), response);
                    News.info("请求申请任务重新分配入库接口失败,接口返回Code异常!!!url:{};request:{};response:{}",
                            wmsUrl + wmsSystemReassignInTaskUrl, JSON.toJSONString(requestParam), response);
                }
            } else {
                News.info("请求申请任务重新分配入库接口失败,接口未响应!!!url:{};request:{};response:{}", wmsUrl + wmsSystemReassignInTaskUrl, JSON.toJSONString(requestParam), response);
                News.info("请求申请任务重新分配入库接口失败,接口未响应!!!url:{};request:{};response:{}", wmsUrl + wmsSystemReassignInTaskUrl,
                        JSON.toJSONString(requestParam), response);
            }
        } catch (Exception e) {
            News.error("请求申请任务重新分配入库接口异常!!!url:{};request:{}; response:{}", wmsUrl + wmsSystemReassignInTaskUrl, JSON.toJSONString(requestParam), response, e);
            News.error("请求申请任务重新分配入库接口异常!!!url:{};request:{}; response:{}", wmsUrl + wmsSystemReassignInTaskUrl,
                    JSON.toJSONString(requestParam), response, e);
        } finally {
            HttpRequestLog httpRequestLog = new HttpRequestLog();
            httpRequestLog.setName(wmsUrl + wmsSystemReassignInTaskUrl);
@@ -219,7 +303,8 @@
        }
        String wmsSystemChangeLocNoUrl = null;
        Config wmsSystemChangeLocNoUrlConfig = configService.selectOne(new EntityWrapper<Config>().eq("code", "wmsSystemChangeLocNoUrl"));
        Config wmsSystemChangeLocNoUrlConfig = configService
                .selectOne(new EntityWrapper<Config>().eq("code", "wmsSystemChangeLocNoUrl"));
        if (wmsSystemChangeLocNoUrlConfig != null) {
            wmsSystemChangeLocNoUrl = wmsSystemChangeLocNoUrlConfig.getValue();
        }
@@ -246,7 +331,8 @@
                crnRows.addAll(list);
            }
        } else if (findCrnNoResult.getCrnType().equals(SlaveType.DualCrn)) {
            BasDualCrnp basDualCrnp = basDualCrnpService.selectOne(new EntityWrapper<BasDualCrnp>().eq("crn_no", crnNo));
            BasDualCrnp basDualCrnp = basDualCrnpService
                    .selectOne(new EntityWrapper<BasDualCrnp>().eq("crn_no", crnNo));
            if (basDualCrnp == null) {
                return null;
            }
@@ -277,15 +363,19 @@
                JSONObject jsonObject = JSON.parseObject(response);
                if (jsonObject.getInteger("code") == 200) {
                    result = 1;
                    News.info("请求WMS申请更换库位接口成功!!!url:{};request:{};response:{}", wmsUrl + wmsSystemChangeLocNoUrl, JSON.toJSONString(requestParam), response);
                    News.info("请求WMS申请更换库位接口成功!!!url:{};request:{};response:{}", wmsUrl + wmsSystemChangeLocNoUrl,
                            JSON.toJSONString(requestParam), response);
                }else {
                    News.info("请求WMS申请更换库位接口失败,接口返回Code异常!!!url:{};request:{};response:{}", wmsUrl + wmsSystemChangeLocNoUrl, JSON.toJSONString(requestParam), response);
                    News.info("请求WMS申请更换库位接口失败,接口返回Code异常!!!url:{};request:{};response:{}",
                            wmsUrl + wmsSystemChangeLocNoUrl, JSON.toJSONString(requestParam), response);
                }
            }else {
                News.info("请求WMS申请更换库位接口失败,接口未响应!!!url:{};request:{};response:{}", wmsUrl + wmsSystemChangeLocNoUrl, JSON.toJSONString(requestParam), response);
                News.info("请求WMS申请更换库位接口失败,接口未响应!!!url:{};request:{};response:{}", wmsUrl + wmsSystemChangeLocNoUrl,
                        JSON.toJSONString(requestParam), response);
            }
        } catch (Exception e) {
            News.error("请求WMS申请更换库位接口异常!!!url:{};request:{};response:{}", wmsUrl + wmsSystemChangeLocNoUrl, JSON.toJSONString(requestParam), response, e);
            News.error("请求WMS申请更换库位接口异常!!!url:{};request:{};response:{}", wmsUrl + wmsSystemChangeLocNoUrl,
                    JSON.toJSONString(requestParam), response, e);
        } finally {
            HttpRequestLog httpRequestLog = new HttpRequestLog();
            httpRequestLog.setName(wmsUrl + wmsSystemChangeLocNoUrl);