#
Administrator
2026-04-25 439450cb2b161110b28c660e532b4955f4ba37e9
src/main/java/com/zy/core/network/real/ZyStationV3RealConnect.java
@@ -35,6 +35,8 @@
 */
@Slf4j
public class ZyStationV3RealConnect implements ZyStationConnectApi {
    private static final long COMMAND_IDX_SLOW_THRESHOLD_MS = 500L;
    private static final long COMMAND_SEND_SLOW_THRESHOLD_MS = 1000L;
    private List<ZyStationStatusEntity> statusList;
    private List<StationObjModel> barcodeOriginList;
@@ -43,6 +45,8 @@
    private RedisUtil redisUtil;
    private final static int taskAddressLength = 48;
    private final static int taskAddressLimit = 50;
    private final static int taskStatusOffset = 46;
    private final static int commandAreaTotalLength = taskAddressLength * taskAddressLimit;
    public ZyStationV3RealConnect(DeviceConfig deviceConfig, RedisUtil redisUtil) {
        this.deviceConfig = deviceConfig;
@@ -228,9 +232,18 @@
        int tryCount = 0;
        if (command.getCommandType().equals(StationCommandType.MOVE)) {
            int enableCommandIdx = -1;
            long sendStartMs = System.currentTimeMillis();
            EnableCommandIdxResult idxResult = null;
            while (true) {
                enableCommandIdx = getEnableCommandIdx(command.getTaskNo());
                idxResult = getEnableCommandIdx(command.getTaskNo());
                enableCommandIdx = idxResult.enableCommandIdx;
                if(enableCommandIdx == -1) {
                    if (idxResult != null && idxResult.duplicateTaskNo) {
                        commandResponse.setMessage("命令区已存在相同任务号,等待已有命令执行完成");
                        log.warn("[WCS Trace][输送线命令] 命令区已存在相同任务号,取消本次重复下发。deviceNo={}, taskNo={}, occupiedSlotCount={}, scanCostMs={}",
                                deviceNo, command.getTaskNo(), idxResult.occupiedSlotCount, idxResult.scanCostMs);
                        return commandResponse;
                    }
                    try {
                        Thread.sleep(300);
                    }catch (Exception e) {}
@@ -238,10 +251,22 @@
                    break;
                }
                tryCount++;
                if (tryCount == 1 || tryCount % 10 == 0) {
                    log.warn("[WCS Trace][输送线命令] 暂未找到可用下发区域。deviceNo={}, taskNo={}, tryCount={}, occupiedSlotCount={}, scanCostMs={}",
                            deviceNo, command.getTaskNo(), tryCount,
                            idxResult == null ? -1 : idxResult.occupiedSlotCount,
                            idxResult == null ? -1 : idxResult.scanCostMs);
                }
                if (tryCount > maxTryCount) {
                    commandResponse.setMessage("命令下发超时,无法找到可用下发区域");
                    log.error("[WCS Trace][输送线命令] 命令下发超时。deviceNo={}, taskNo={}, totalWaitMs={}, tryCount={}",
                            deviceNo, command.getTaskNo(), System.currentTimeMillis() - sendStartMs, tryCount);
                    return commandResponse;
                }
            }
            if (idxResult != null && idxResult.scanCostMs > COMMAND_IDX_SLOW_THRESHOLD_MS) {
                log.warn("[WCS Trace][输送线命令] 获取可用下发区域较慢。deviceNo={}, taskNo={}, enableIdx={}, occupiedSlotCount={}, scanCostMs={}, tryCount={}",
                        deviceNo, command.getTaskNo(), enableCommandIdx, idxResult.occupiedSlotCount, idxResult.scanCostMs, tryCount);
            }
            List<Integer> pathList = command.getNavigatePath();
@@ -267,6 +292,12 @@
            if(writeTask.IsSuccess &&  writeData.IsSuccess &&  writeConfirm.IsSuccess) {
                log.info("写入输送线命令成功。任务号={},站点数据={}", command.getTaskNo(), JSON.toJSON(command));
                long totalCostMs = System.currentTimeMillis() - sendStartMs;
                if (totalCostMs > COMMAND_SEND_SLOW_THRESHOLD_MS) {
                    log.warn("[WCS Trace][输送线命令] 命令写入总耗时较长。deviceNo={}, taskNo={}, enableIdx={}, tryCount={}, occupiedSlotCount={}, totalCostMs={}",
                            deviceNo, command.getTaskNo(), enableCommandIdx, tryCount,
                            idxResult == null ? -1 : idxResult.occupiedSlotCount, totalCostMs);
                }
                commandResponse.setResult(true);
            }else {
                log.error("写入输送线命令失败。站点编号={},站点数据={}", command.getTaskNo(), JSON.toJSON(command));
@@ -274,9 +305,18 @@
            }
        } else if (command.getCommandType().equals(StationCommandType.WRITE_INFO)) {
            int enableCommandIdx = -1;
            long sendStartMs = System.currentTimeMillis();
            EnableCommandIdxResult idxResult = null;
            while (true) {
                enableCommandIdx = getEnableCommandIdx(command.getTaskNo());
                idxResult = getEnableCommandIdx(command.getTaskNo());
                enableCommandIdx = idxResult.enableCommandIdx;
                if(enableCommandIdx == -1) {
                    if (idxResult != null && idxResult.duplicateTaskNo) {
                        commandResponse.setMessage("命令区已存在相同任务号,等待已有命令执行完成");
                        log.warn("[WCS Trace][输送线命令] WRITE_INFO 命令区已存在相同任务号,取消本次重复下发。deviceNo={}, taskNo={}, occupiedSlotCount={}, scanCostMs={}",
                                deviceNo, command.getTaskNo(), idxResult.occupiedSlotCount, idxResult.scanCostMs);
                        return commandResponse;
                    }
                    try {
                        Thread.sleep(300);
                    }catch (Exception e) {}
@@ -284,10 +324,22 @@
                    break;
                }
                tryCount++;
                if (tryCount == 1 || tryCount % 10 == 0) {
                    log.warn("[WCS Trace][输送线命令] WRITE_INFO 暂未找到可用下发区域。deviceNo={}, taskNo={}, tryCount={}, occupiedSlotCount={}, scanCostMs={}",
                            deviceNo, command.getTaskNo(), tryCount,
                            idxResult == null ? -1 : idxResult.occupiedSlotCount,
                            idxResult == null ? -1 : idxResult.scanCostMs);
                }
                if (tryCount > maxTryCount) {
                    commandResponse.setMessage("命令下发超时,无法找到可用下发区域");
                    log.error("[WCS Trace][输送线命令] WRITE_INFO 命令下发超时。deviceNo={}, taskNo={}, totalWaitMs={}, tryCount={}",
                            deviceNo, command.getTaskNo(), System.currentTimeMillis() - sendStartMs, tryCount);
                    return commandResponse;
                }
            }
            if (idxResult != null && idxResult.scanCostMs > COMMAND_IDX_SLOW_THRESHOLD_MS) {
                log.warn("[WCS Trace][输送线命令] WRITE_INFO 获取可用下发区域较慢。deviceNo={}, taskNo={}, enableIdx={}, occupiedSlotCount={}, scanCostMs={}, tryCount={}",
                        deviceNo, command.getTaskNo(), enableCommandIdx, idxResult.occupiedSlotCount, idxResult.scanCostMs, tryCount);
            }
            short[] data = new short[21];
@@ -307,6 +359,12 @@
            if(writeTask.IsSuccess &&  writeData.IsSuccess &&  writeConfirm.IsSuccess) {
                log.error("写入输送线命令成功。任务号={},站点数据={}", command.getTaskNo(), JSON.toJSON(command));
                long totalCostMs = System.currentTimeMillis() - sendStartMs;
                if (totalCostMs > COMMAND_SEND_SLOW_THRESHOLD_MS) {
                    log.warn("[WCS Trace][输送线命令] WRITE_INFO 命令写入总耗时较长。deviceNo={}, taskNo={}, enableIdx={}, tryCount={}, occupiedSlotCount={}, totalCostMs={}",
                            deviceNo, command.getTaskNo(), enableCommandIdx, tryCount,
                            idxResult == null ? -1 : idxResult.occupiedSlotCount, totalCostMs);
                }
                commandResponse.setResult(true);
            }else {
                log.error("写入输送线命令失败。站点编号={},站点数据={}", command.getTaskNo(), JSON.toJSON(command));
@@ -361,29 +419,49 @@
        return null;
    }
    private int getEnableCommandIdx(int taskNo) {
    private EnableCommandIdxResult getEnableCommandIdx(int taskNo) {
        long startMs = System.currentTimeMillis();
        OperateResultExOne<byte[]> result = siemensNet.Read("DB23.0", (short) commandAreaTotalLength);
        EnableCommandIdxResult idxResult = new EnableCommandIdxResult();
        idxResult.scanCostMs = System.currentTimeMillis() - startMs;
        if (!result.IsSuccess || result.Content == null || result.Content.length < commandAreaTotalLength) {
            idxResult.enableCommandIdx = -1;
            idxResult.readSuccess = false;
            log.warn("[WCS Trace][输送线命令] 批量读取命令区失败。deviceNo={}, taskNo={}, contentLength={}, scanCostMs={}",
                    deviceConfig == null ? null : deviceConfig.getDeviceNo(), taskNo,
                    result.Content == null ? -1 : result.Content.length, idxResult.scanCostMs);
            return idxResult;
        }
        idxResult.readSuccess = true;
        int useIdx = -1;
        for (int i = 0; i < taskAddressLimit; i++) {
            OperateResultExOne<byte[]> resultTask = siemensNet.Read("DB23." + (i * taskAddressLength + 0), (short) 4);
            OperateResultExOne<byte[]> resultStatus = siemensNet.Read("DB23." + (i * taskAddressLength + 46), (short) 2);
            if(!resultTask.IsSuccess || !resultStatus.IsSuccess) {
                continue;
            }
            int taskOffset = i * taskAddressLength;
            int commandAreaTaskNo = siemensNet.getByteTransform().TransInt32(result.Content, taskOffset);
            int taskStatus = siemensNet.getByteTransform().TransInt16(result.Content, taskOffset + taskStatusOffset);
            int commandAreaTaskNo = siemensNet.getByteTransform().TransInt32(resultTask.Content, 0);
            if(commandAreaTaskNo == taskNo) {
                return -1;
            }
            int taskStatus = siemensNet.getByteTransform().TransInt16(resultStatus.Content, 0);
            if (taskStatus == 1) {
                continue;
                idxResult.occupiedSlotCount++;
            }
            useIdx = i;
            break;
            if (commandAreaTaskNo == taskNo) {
                idxResult.enableCommandIdx = -1;
                idxResult.duplicateTaskNo = true;
                return idxResult;
            }
            if (useIdx == -1 && taskStatus != 1) {
                useIdx = i;
            }
        }
        return  useIdx;
        idxResult.enableCommandIdx = useIdx;
        return idxResult;
    }
    private static class EnableCommandIdxResult {
        private int enableCommandIdx = -1;
        private int occupiedSlotCount = 0;
        private boolean duplicateTaskNo = false;
        private boolean readSuccess = false;
        private long scanCostMs = 0L;
    }
}