#
Junjie
2026-01-15 ef1cd5823fe7cf724e1de875a1a5737a44f160f1
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) {