#
Administrator
1 天以前 1c8455e647bfb059d52788afaa845c52e7d6213f
src/main/java/com/zy/core/network/real/ZyStationV3RealConnect.java
@@ -15,6 +15,7 @@
import com.zy.common.utils.RedisUtil;
import com.zy.core.News;
import com.zy.core.cache.OutputQueue;
import com.zy.core.enums.RedisKeyType;
import com.zy.core.enums.StationCommandType;
import com.zy.core.model.CommandResponse;
import com.zy.core.model.StationObjModel;
@@ -34,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;
@@ -42,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;
@@ -145,7 +150,8 @@
                if (barcodeEntity == null) {
                    continue;
                }
                String barcode = siemensNet.getByteTransform().TransString(result2.Content, i * 16 + 2, 14, "UTF-8");
                byte length = 10;//result2.Content[1];
                String barcode = siemensNet.getByteTransform().TransString(result2.Content, i * 16 + 2, length, "UTF-8");
                barcode = barcode.trim();
                barcodeEntity.setBarcode(barcode);
            }
@@ -226,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) {}
@@ -236,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();
@@ -264,7 +291,13 @@
            OperateResult writeConfirm = siemensNet.Write("DB23." + (enableCommandIdx * taskAddressLength + 46), (short) 1);
            if(writeTask.IsSuccess &&  writeData.IsSuccess &&  writeConfirm.IsSuccess) {
                log.error("写入输送线命令成功。任务号={},站点数据={}", command.getTaskNo(), JSON.toJSON(command));
                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));
@@ -272,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) {}
@@ -282,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];
@@ -305,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));
@@ -315,7 +375,7 @@
    }
    @Override
    public CommandResponse sendOriginCommand(String address, short[] data) {
    public synchronized CommandResponse sendOriginCommand(String address, short[] data) {
        CommandResponse commandResponse = new CommandResponse(false);
        if (null == data || data.length == 0) {
            commandResponse.setMessage("数据为空");
@@ -359,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;
    }
}