| | |
| | | if (command != null) { |
| | | taskLastUpdateTime.put(taskNo, System.currentTimeMillis()); |
| | | |
| | | // 首次接收命令时初始化 |
| | | if (finalTargetStationId == null) { |
| | | finalTargetStationId = command.getTargetStaNo(); |
| | | if (checkTaskNoInArea(taskNo)) { |
| | | generateBarcode = true; |
| | | // 每次接收命令都刷新目标,避免沿用旧目标导致状态抖动 |
| | | Integer commandTargetStationId = command.getTargetStaNo(); |
| | | if (commandTargetStationId != null) { |
| | | if (!commandTargetStationId.equals(finalTargetStationId)) { |
| | | News.info("[WCS Debug] 任务{}切换目标: {} -> {}", taskNo, finalTargetStationId, |
| | | commandTargetStationId); |
| | | } |
| | | finalTargetStationId = commandTargetStationId; |
| | | // 当前站点先同步最新目标,避免上层在窗口期重复下发同一路径 |
| | | syncCurrentStationTarget(taskNo, currentStationId, finalTargetStationId); |
| | | } |
| | | |
| | | if (!generateBarcode && checkTaskNoInArea(taskNo)) { |
| | | generateBarcode = true; |
| | | } |
| | | |
| | | // 将新路径追加到待执行队列 |
| | |
| | | if (newPath != null && !newPath.isEmpty()) { |
| | | // 获取队列中最后一个站点(用于衔接点去重) |
| | | Integer lastInQueue = getLastInQueue(pendingPathQueue); |
| | | if (lastInQueue == null) { |
| | | lastInQueue = currentStationId; |
| | | } |
| | | |
| | | int startIndex = 0; |
| | | // 如果新路径的起点与当前位置或队列末尾重复,则跳过 |
| | | if (lastInQueue != null && !newPath.isEmpty() && newPath.get(0).equals(lastInQueue)) { |
| | | startIndex = 1; |
| | | } |
| | | int startIndex = getPathAppendStartIndex(newPath, currentStationId, lastInQueue); |
| | | |
| | | for (int i = startIndex; i < newPath.size(); i++) { |
| | | pendingPathQueue.offer(newPath.get(i)); |
| | |
| | | // 路径队列为空,等待新的分段命令 |
| | | if (currentStationId != null && finalTargetStationId != null |
| | | && currentStationId.equals(finalTargetStationId)) { |
| | | // 已到达最终目标,正常结束 |
| | | // 已到达目标:立即清空当前队列并结束本轮执行,后续新命令重新创建执行线程 |
| | | if (generateBarcode) { |
| | | Integer targetDeviceNo = getDeviceNoByStationId(finalTargetStationId); |
| | | if (targetDeviceNo != null) { |
| | |
| | | News.info("[WCS Debug] 任务{}到达目标{}并生成条码", taskNo, finalTargetStationId); |
| | | } |
| | | } |
| | | commandQueue.clear(); |
| | | pendingPathQueue.clear(); |
| | | News.info("[WCS Debug] 任务{}到达目标后清空队列并结束,等待后续新命令重启", taskNo); |
| | | break; |
| | | } |
| | | |
| | | // 未到达最终目标,等待新的分段命令 |
| | | // 继续等待新的分段命令 |
| | | Long lastTime = taskLastUpdateTime.get(taskNo); |
| | | if (lastTime != null && System.currentTimeMillis() - lastTime > 30000) { |
| | | // 超时:30秒内没有收到新分段命令 |
| | |
| | | last = item; |
| | | } |
| | | return last; |
| | | } |
| | | |
| | | /** |
| | | * 计算新路径在队列中的追加起点,避免重复下发导致路径来回跳 |
| | | */ |
| | | private int getPathAppendStartIndex(List<Integer> newPath, Integer currentStationId, Integer lastInQueue) { |
| | | if (newPath == null || newPath.isEmpty()) { |
| | | return 0; |
| | | } |
| | | |
| | | if (lastInQueue != null) { |
| | | int idx = newPath.lastIndexOf(lastInQueue); |
| | | if (idx >= 0) { |
| | | return idx + 1; |
| | | } |
| | | } |
| | | |
| | | if (currentStationId != null) { |
| | | int idx = newPath.lastIndexOf(currentStationId); |
| | | if (idx >= 0) { |
| | | return idx + 1; |
| | | } |
| | | } |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | /** |
| | | * 命令刚到达时同步当前站点目标,降低上层重复发同一路径的概率 |
| | | */ |
| | | private void syncCurrentStationTarget(Integer taskNo, Integer currentStationId, Integer targetStationId) { |
| | | if (currentStationId == null || targetStationId == null) { |
| | | return; |
| | | } |
| | | Integer currentDeviceNo = getDeviceNoByStationId(currentStationId); |
| | | if (currentDeviceNo == null) { |
| | | return; |
| | | } |
| | | |
| | | lockStations(currentStationId); |
| | | try { |
| | | List<ZyStationStatusEntity> statusList = deviceStatusMap.get(currentDeviceNo); |
| | | if (statusList == null) { |
| | | return; |
| | | } |
| | | |
| | | ZyStationStatusEntity currentStatus = statusList.stream() |
| | | .filter(item -> item.getStationId().equals(currentStationId)).findFirst().orElse(null); |
| | | if (currentStatus == null) { |
| | | return; |
| | | } |
| | | |
| | | if (currentStatus.getTaskNo() != null && currentStatus.getTaskNo() > 0 |
| | | && !currentStatus.getTaskNo().equals(taskNo) && currentStatus.isLoading()) { |
| | | return; |
| | | } |
| | | |
| | | updateStationDataInternal(currentStationId, currentDeviceNo, taskNo, targetStationId, null, null, null); |
| | | } finally { |
| | | unlockStations(currentStationId); |
| | | } |
| | | } |
| | | |
| | | /** |
| | |
| | | } |
| | | |
| | | if (command.getCommandType() == StationCommandType.WRITE_INFO) { |
| | | if (command.getBarcode() != null) { |
| | | updateStationBarcode(deviceNo, stationId, command.getBarcode()); |
| | | return; |
| | | } |
| | | if (taskNo == 9998 && targetStationId == 0) { |
| | | // 生成出库站点仿真数据 |
| | | generateFakeOutStationData(deviceNo, stationId); |
| | |
| | | } |
| | | } |
| | | |
| | | private void updateStationBarcode(Integer deviceNo, Integer stationId, String barcode) { |
| | | List<ZyStationStatusEntity> statusList = deviceStatusMap.get(deviceNo); |
| | | if (statusList == null) { |
| | | return; |
| | | } |
| | | |
| | | ZyStationStatusEntity status = statusList.stream() |
| | | .filter(item -> item.getStationId().equals(stationId)).findFirst().orElse(null); |
| | | if (status == null) { |
| | | return; |
| | | } |
| | | |
| | | synchronized (status) { |
| | | status.setBarcode(barcode); |
| | | } |
| | | } |
| | | |
| | | // segmentedPathCommand 方法已删除,功能已整合到 runTaskLoop |
| | | |
| | | private Integer getDeviceNoByStationId(Integer stationId) { |