| | |
| | | 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; |
| | |
| | | */ |
| | | @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; |
| | |
| | | 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; |
| | |
| | | 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); |
| | | } |
| | |
| | | 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) {} |
| | |
| | | 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(); |
| | |
| | | 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)); |
| | |
| | | } |
| | | } 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) {} |
| | |
| | | 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]; |
| | |
| | | |
| | | 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)); |
| | |
| | | } |
| | | |
| | | @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("数据为空"); |
| | |
| | | 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; |
| | | } |
| | | |
| | | } |