| | |
| | | task.getTaskId(), device.getId()); |
| | | return; |
| | | } |
| | | // 已完成/失败的步骤不再回退状态 |
| | | if (TaskStepDetail.Status.COMPLETED.name().equals(step.getStatus()) |
| | | || TaskStepDetail.Status.FAILED.name().equals(step.getStatus())) { |
| | | return; |
| | | } |
| | | // 进片大车设备:只有在真正开始处理时才设置为RUNNING |
| | | // 先检查卧转立设备是否已完成,如果还在执行中,不应该开始大车的工作 |
| | | boolean transferCompleted = isTransferDeviceCompleted(task.getTaskId(), context); |
| | | if (!transferCompleted) { |
| | | // 卧转立还在执行中,等待卧转立完成 |
| | | if (!TaskStepDetail.Status.PENDING.name().equals(step.getStatus())) { |
| | | step.setStatus(TaskStepDetail.Status.PENDING.name()); |
| | | step.setSuccessMessage("等待卧转立完成"); |
| | | if (step.getStartTime() == null) { |
| | | step.setStartTime(new Date()); |
| | | } |
| | | taskStepDetailMapper.updateById(step); |
| | | notificationService.notifyStepUpdate(task.getTaskId(), step); |
| | | } |
| | | log.debug("卧转立还在执行中,进片大车等待: taskId={}, deviceId={}", |
| | | task.getTaskId(), device.getId()); |
| | | return; |
| | | } |
| | | |
| | | // 检查是否有卧转立主体已输出、准备上大车的玻璃信息 |
| | | List<String> readyGlassIds = getTransferReadyGlassIds(context); |
| | | |
| | | // 如果当前没有新的玻璃,无论步骤是否已进入RUNNING,都应该轮询MES任务/确认状态 |
| | | // 如果当前没有新的玻璃,但卧转立已完成,可以轮询MES任务/确认状态 |
| | | if (CollectionUtils.isEmpty(readyGlassIds)) { |
| | | // 轮询MES任务/确认,避免错过MES侧后写入的任务 |
| | | pollMesForVehicle(task, step, device, context); |
| | | // 如果仍然没有卧转立输出的玻璃,保持/更新为PENDING提示 |
| | | if (!TaskStepDetail.Status.RUNNING.name().equals(step.getStatus()) |
| | | && !TaskStepDetail.Status.PENDING.name().equals(step.getStatus())) { |
| | | step.setStatus(TaskStepDetail.Status.PENDING.name()); |
| | | step.setSuccessMessage("等待卧转立输出玻璃"); |
| | | taskStepDetailMapper.updateById(step); |
| | | notificationService.notifyStepUpdate(task.getTaskId(), step); |
| | | // 检查是否所有初始玻璃都已装载 |
| | | @SuppressWarnings("unchecked") |
| | | List<String> initialGlassIds = (List<String>) context.getSharedData().get("initialGlassIds"); |
| | | List<String> loadedGlassIds = getLoadedGlassIds(context); |
| | | |
| | | if (initialGlassIds != null && !initialGlassIds.isEmpty()) { |
| | | // 如果所有初始玻璃都已装载,说明已经处理完,不应该再变回等待 |
| | | if (loadedGlassIds != null && !loadedGlassIds.isEmpty() |
| | | && loadedGlassIds.containsAll(initialGlassIds)) { |
| | | // 所有玻璃都已装载,保持RUNNING状态,继续轮询MES任务/确认 |
| | | if (!TaskStepDetail.Status.RUNNING.name().equals(step.getStatus())) { |
| | | step.setStatus(TaskStepDetail.Status.RUNNING.name()); |
| | | if (step.getStartTime() == null) { |
| | | step.setStartTime(new Date()); |
| | | } |
| | | taskStepDetailMapper.updateById(step); |
| | | notificationService.notifyStepUpdate(task.getTaskId(), step); |
| | | } |
| | | pollMesForVehicle(task, step, device, context); |
| | | return; |
| | | } |
| | | } |
| | | |
| | | // 如果大车已经装载过玻璃(RUNNING状态),轮询MES任务/确认状态 |
| | | if (TaskStepDetail.Status.RUNNING.name().equals(step.getStatus())) { |
| | | pollMesForVehicle(task, step, device, context); |
| | | } else { |
| | | // 如果还没有装载过玻璃,等待卧转立输出 |
| | | if (!TaskStepDetail.Status.PENDING.name().equals(step.getStatus())) { |
| | | step.setStatus(TaskStepDetail.Status.PENDING.name()); |
| | | step.setSuccessMessage("等待卧转立输出玻璃"); |
| | | if (step.getStartTime() == null) { |
| | | step.setStartTime(new Date()); |
| | | } |
| | | taskStepDetailMapper.updateById(step); |
| | | notificationService.notifyStepUpdate(task.getTaskId(), step); |
| | | } |
| | | } |
| | | return; |
| | | } |
| | |
| | | // 只有在任务已开始执行(有任务记录)时才检查MES确认 |
| | | DevicePlcVO.OperationResult mesResult = null; |
| | | try { |
| | | mesResult = handler.execute(device, "checkMesConfirm", Collections.emptyMap()); |
| | | Map<String, Object> confirmParams = new HashMap<>(); |
| | | confirmParams.put("_taskContext", context); |
| | | mesResult = handler.execute(device, "checkMesConfirm", confirmParams); |
| | | } catch (Exception e) { |
| | | log.warn("进片大车设备检查MES确认状态异常: taskId={}, deviceId={}, error={}", |
| | | task.getTaskId(), device.getId(), e.getMessage()); |
| | | } |
| | | |
| | | // 如果MES已确认完成(mesConfirm=1),检查卧转立设备状态和玻璃信息 |
| | | // 如果卧转立已完成且所有玻璃都已装载,可以标记为完成 |
| | | if (mesResult != null && mesResult.getData() != null) { |
| | | Object completedFlag = mesResult.getData().get("completed"); |
| | | boolean mesConfirmed = false; |
| | | if (completedFlag instanceof Boolean) { |
| | | mesConfirmed = (Boolean) completedFlag; |
| | | } else if (completedFlag != null) { |
| | | mesConfirmed = "true".equalsIgnoreCase(String.valueOf(completedFlag)); |
| | | } |
| | | |
| | | if (mesConfirmed) { |
| | | // MES已确认完成,检查卧转立设备是否已完成 |
| | | boolean transferCompletedForMes = isTransferDeviceCompleted(task.getTaskId(), context); |
| | | if (transferCompletedForMes) { |
| | | // 检查任务上下文中的初始玻璃ID和已装载的玻璃ID |
| | | @SuppressWarnings("unchecked") |
| | | List<String> initialGlassIds = (List<String>) context.getSharedData().get("initialGlassIds"); |
| | | List<String> loadedGlassIds = getLoadedGlassIds(context); |
| | | |
| | | if (initialGlassIds != null && !initialGlassIds.isEmpty() |
| | | && loadedGlassIds != null && !loadedGlassIds.isEmpty()) { |
| | | // 检查是否所有初始玻璃都已装载 |
| | | boolean allGlassesLoaded = loadedGlassIds.containsAll(initialGlassIds); |
| | | if (allGlassesLoaded) { |
| | | // 卧转立已完成且所有玻璃都已装载,标记为完成 |
| | | log.info("MES已确认且卧转立已完成且所有玻璃已装载,任务自动完成: taskId={}, deviceId={}, initialCount={}, loadedCount={}", |
| | | task.getTaskId(), device.getId(), initialGlassIds.size(), loadedGlassIds.size()); |
| | | // mesResult已经包含completed=true,不需要修改 |
| | | } |
| | | } |
| | | } else { |
| | | // 卧转立还未完成,不应该标记为完成 |
| | | log.debug("MES已确认但卧转立未完成,等待卧转立完成: taskId={}, deviceId={}", |
| | | task.getTaskId(), device.getId()); |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 更新步骤状态(大车设备保持RUNNING,直到MES确认完成或任务取消) |
| | | if (mesResult != null) { |
| | | updateStepStatusForVehicle(step, mesResult); |
| | | updateStepStatusForVehicle(task.getTaskId(), step, mesResult); |
| | | boolean opSuccess = Boolean.TRUE.equals(mesResult.getSuccess()); |
| | | updateTaskProgress(task, step.getStepOrder(), opSuccess); |
| | | if (!opSuccess) { |
| | |
| | | DeviceCoordinationService.DeviceStatus.FAILED, context); |
| | | } |
| | | } else { |
| | | updateStepStatusForVehicle(step, feedResult); |
| | | updateStepStatusForVehicle(task.getTaskId(), step, feedResult); |
| | | boolean opSuccess = Boolean.TRUE.equals(feedResult.getSuccess()); |
| | | updateTaskProgress(task, step.getStepOrder(), opSuccess); |
| | | if (!opSuccess) { |
| | |
| | | // 检查是否有已处理的玻璃信息(从大理片笼来的) |
| | | List<String> processedGlassIds = getProcessedGlassIds(context); |
| | | boolean isRunning = TaskStepDetail.Status.RUNNING.name().equals(step.getStatus()); |
| | | boolean isCompleted = TaskStepDetail.Status.COMPLETED.name().equals(step.getStatus()); |
| | | |
| | | // 如果设备已经在运行中,即使没有新玻璃,也要继续监控MES任务和确认状态 |
| | | // 获取已出片的玻璃ID列表(在方法开始处声明,避免重复定义) |
| | | List<String> outboundGlassIds = getOutboundGlassIds(context); |
| | | |
| | | // 如果步骤已完成,检查是否所有初始玻璃都已出片 |
| | | if (isCompleted) { |
| | | @SuppressWarnings("unchecked") |
| | | List<String> initialGlassIds = (List<String>) context.getSharedData().get("initialGlassIds"); |
| | | |
| | | // 如果还有未出片的玻璃,重置步骤状态为RUNNING,继续等待 |
| | | if (initialGlassIds != null && !initialGlassIds.isEmpty() |
| | | && (outboundGlassIds == null || !outboundGlassIds.containsAll(initialGlassIds))) { |
| | | log.info("出片大车步骤已完成,但还有未出片的玻璃,重置为RUNNING继续等待: taskId={}, deviceId={}, initialCount={}, outboundCount={}", |
| | | task.getTaskId(), device.getId(), |
| | | initialGlassIds.size(), |
| | | outboundGlassIds != null ? outboundGlassIds.size() : 0); |
| | | step.setStatus(TaskStepDetail.Status.RUNNING.name()); |
| | | step.setEndTime(null); // 清除结束时间 |
| | | step.setSuccessMessage("等待剩余玻璃出片"); |
| | | taskStepDetailMapper.updateById(step); |
| | | notificationService.notifyStepUpdate(task.getTaskId(), step); |
| | | // 继续执行后续逻辑,检查是否有新的已处理玻璃 |
| | | } else { |
| | | // 所有玻璃都已出片,保持完成状态 |
| | | log.debug("出片大车所有玻璃都已出片: taskId={}, deviceId={}, initialCount={}, outboundCount={}", |
| | | task.getTaskId(), device.getId(), |
| | | initialGlassIds != null ? initialGlassIds.size() : 0, |
| | | outboundGlassIds != null ? outboundGlassIds.size() : 0); |
| | | return; |
| | | } |
| | | } |
| | | |
| | | // 如果没有已处理玻璃,则不应主动把步骤拉到RUNNING,只保持已运行状态 |
| | | if (CollectionUtils.isEmpty(processedGlassIds)) { |
| | | if (isRunning) { |
| | | // 设备正在运行中,先检查MES任务,然后监控MES确认状态 |
| | | if (isRunning || isCompleted) { |
| | | // 已经在运行的情况下,继续轮询MES任务/确认,避免错过确认 |
| | | DeviceLogicHandler handler = handlerFactory.getHandler(device.getDeviceType()); |
| | | if (handler != null) { |
| | | Map<String, Object> logicParams = parseLogicParams(device); |
| | |
| | | DevicePlcVO.OperationResult mesTaskResult = null; |
| | | try { |
| | | mesTaskResult = handler.execute(device, "checkMesTask", Collections.emptyMap()); |
| | | if (mesTaskResult != null && Boolean.TRUE.equals(mesTaskResult.getSuccess())) { |
| | | log.info("出片大车设备已检查MES任务并开始执行: taskId={}, deviceId={}, message={}", |
| | | task.getTaskId(), device.getId(), mesTaskResult.getMessage()); |
| | | if (mesTaskResult != null) { |
| | | if (Boolean.TRUE.equals(mesTaskResult.getSuccess())) { |
| | | log.info("出片大车设备已检查MES任务并开始执行: taskId={}, deviceId={}, message={}", |
| | | task.getTaskId(), device.getId(), mesTaskResult.getMessage()); |
| | | } else { |
| | | log.debug("出片大车设备检查MES任务,等待中: taskId={}, deviceId={}, message={}", |
| | | task.getTaskId(), device.getId(), mesTaskResult.getMessage()); |
| | | } |
| | | } |
| | | } catch (Exception e) { |
| | | log.warn("出片大车设备检查MES任务异常: taskId={}, deviceId={}, error={}", |
| | |
| | | // 然后检查MES确认状态(只有在任务已开始执行时才检查) |
| | | DevicePlcVO.OperationResult mesResult = null; |
| | | try { |
| | | mesResult = handler.execute(device, "checkMesConfirm", Collections.emptyMap()); |
| | | Map<String, Object> checkParams = new HashMap<>(); |
| | | checkParams.put("_taskContext", context); |
| | | mesResult = handler.execute(device, "checkMesConfirm", checkParams); |
| | | } catch (Exception e) { |
| | | log.warn("出片大车设备检查MES确认状态异常: taskId={}, deviceId={}, error={}", |
| | | task.getTaskId(), device.getId(), e.getMessage()); |
| | |
| | | |
| | | // 更新步骤状态(大车设备保持RUNNING,直到MES确认完成或任务取消) |
| | | if (mesResult != null) { |
| | | updateStepStatusForVehicle(step, mesResult); |
| | | updateStepStatusForVehicle(task.getTaskId(), step, mesResult); |
| | | boolean opSuccess = Boolean.TRUE.equals(mesResult.getSuccess()); |
| | | updateTaskProgress(task, step.getStepOrder(), opSuccess); |
| | | if (!opSuccess) { |
| | |
| | | } |
| | | } |
| | | } |
| | | return; |
| | | } else { |
| | | // 没有数据,且设备未运行,保持PENDING状态 |
| | | if (!TaskStepDetail.Status.PENDING.name().equals(step.getStatus())) { |
| | | // 未运行且没有已处理玻璃,保持PENDING |
| | | if (!TaskStepDetail.Status.PENDING.name().equals(step.getStatus()) |
| | | && !TaskStepDetail.Status.COMPLETED.name().equals(step.getStatus())) { |
| | | step.setStatus(TaskStepDetail.Status.PENDING.name()); |
| | | step.setSuccessMessage("等待大理片笼处理完成"); |
| | | taskStepDetailMapper.updateById(step); |
| | |
| | | } |
| | | log.debug("出片大车设备定时器:暂无已处理的玻璃信息: taskId={}, deviceId={}", |
| | | task.getTaskId(), device.getId()); |
| | | return; |
| | | } |
| | | return; |
| | | } |
| | | |
| | | log.debug("出片大车设备定时器检测到已处理的玻璃信息: taskId={}, deviceId={}, glassCount={}", |
| | | task.getTaskId(), device.getId(), processedGlassIds.size()); |
| | | |
| | | // 过滤出还未出片的玻璃(支持分批出片) |
| | | // 重新获取已出片的玻璃ID列表(可能在上面的逻辑中已更新) |
| | | outboundGlassIds = getOutboundGlassIds(context); |
| | | List<String> glassIdsToOutbound = new ArrayList<>(); |
| | | for (String glassId : processedGlassIds) { |
| | | if (outboundGlassIds == null || !outboundGlassIds.contains(glassId)) { |
| | | glassIdsToOutbound.add(glassId); |
| | | } |
| | | } |
| | | |
| | | // 如果没有需要出片的玻璃(都已经出片过了),继续等待新的已处理玻璃 |
| | | if (glassIdsToOutbound.isEmpty()) { |
| | | log.debug("出片大车已处理的玻璃都已出片,等待新的已处理玻璃: taskId={}, deviceId={}", |
| | | task.getTaskId(), device.getId()); |
| | | return; |
| | | } |
| | | |
| | | log.debug("出片大车准备出片: taskId={}, deviceId={}, 待出片数量={}, 已出片数量={}", |
| | | task.getTaskId(), device.getId(), glassIdsToOutbound.size(), |
| | | outboundGlassIds != null ? outboundGlassIds.size() : 0); |
| | | |
| | | // 执行出片操作 |
| | | Map<String, Object> checkParams = new HashMap<>(); |
| | | checkParams.put("glassIds", new ArrayList<>(processedGlassIds)); |
| | | checkParams.put("glassIds", glassIdsToOutbound); |
| | | checkParams.put("_taskContext", context); |
| | | |
| | | DeviceLogicHandler handler = handlerFactory.getHandler(device.getDeviceType()); |
| | |
| | | notificationService.notifyStepUpdate(task.getTaskId(), step); |
| | | } |
| | | log.debug("出片大车设备定时器执行成功: taskId={}, deviceId={}, glassCount={}", |
| | | task.getTaskId(), device.getId(), processedGlassIds.size()); |
| | | // 清空已处理的玻璃ID列表(已处理) |
| | | clearProcessedGlassIds(context); |
| | | task.getTaskId(), device.getId(), glassIdsToOutbound.size()); |
| | | // 记录已出片的玻璃ID(只记录本次出片的玻璃) |
| | | addOutboundGlassIds(context, glassIdsToOutbound); |
| | | // 从processedGlassIds中移除已出片的玻璃,保留未出片的玻璃 |
| | | processedGlassIds.removeAll(glassIdsToOutbound); |
| | | // 如果还有未出片的玻璃,不清空processedGlassIds;如果全部出片了,清空 |
| | | if (processedGlassIds.isEmpty()) { |
| | | clearProcessedGlassIds(context); |
| | | } else { |
| | | setProcessedGlassIds(context, processedGlassIds); |
| | | } |
| | | |
| | | // feedGlass成功后,先检查MES任务(checkMesTask)来开始执行任务 |
| | | DevicePlcVO.OperationResult mesTaskResult = null; |
| | |
| | | // 只有在任务已开始执行(有任务记录)时才检查MES确认 |
| | | DevicePlcVO.OperationResult mesResult = null; |
| | | try { |
| | | mesResult = handler.execute(device, "checkMesConfirm", Collections.emptyMap()); |
| | | Map<String, Object> confirmParams = new HashMap<>(); |
| | | confirmParams.put("_taskContext", context); |
| | | mesResult = handler.execute(device, "checkMesConfirm", confirmParams); |
| | | } catch (Exception e) { |
| | | log.warn("出片大车设备检查MES确认状态异常: taskId={}, deviceId={}, error={}", |
| | | task.getTaskId(), device.getId(), e.getMessage()); |
| | | } |
| | | |
| | | // 对于出片大车,需要检查是否所有初始玻璃都已出片 |
| | | // 如果MES返回completed=true,但还有未出片的玻璃,则不应标记为完成 |
| | | if (mesResult != null && mesResult.getData() != null) { |
| | | Object completedFlag = mesResult.getData().get("completed"); |
| | | boolean mesCompleted = false; |
| | | if (completedFlag instanceof Boolean) { |
| | | mesCompleted = (Boolean) completedFlag; |
| | | } else if (completedFlag != null) { |
| | | mesCompleted = "true".equalsIgnoreCase(String.valueOf(completedFlag)); |
| | | } |
| | | |
| | | // 如果MES返回completed=true,检查是否所有初始玻璃都已出片 |
| | | if (mesCompleted) { |
| | | @SuppressWarnings("unchecked") |
| | | List<String> initialGlassIds = (List<String>) context.getSharedData().get("initialGlassIds"); |
| | | // 重新获取已出片的玻璃ID列表(可能在上面的逻辑中已更新) |
| | | outboundGlassIds = getOutboundGlassIds(context); |
| | | |
| | | // 如果还有未出片的玻璃,修改mesResult,将completed设为false |
| | | if (initialGlassIds != null && !initialGlassIds.isEmpty() |
| | | && (outboundGlassIds == null || !outboundGlassIds.containsAll(initialGlassIds))) { |
| | | log.debug("出片大车MES返回completed=true,但还有未出片的玻璃: taskId={}, deviceId={}, initialCount={}, outboundCount={}", |
| | | task.getTaskId(), device.getId(), |
| | | initialGlassIds.size(), |
| | | outboundGlassIds != null ? outboundGlassIds.size() : 0); |
| | | // 修改mesResult,将completed设为false,保持RUNNING状态 |
| | | Map<String, Object> modifiedData = new HashMap<>(mesResult.getData()); |
| | | modifiedData.put("completed", false); |
| | | DevicePlcVO.OperationResult modifiedResult = new DevicePlcVO.OperationResult(); |
| | | modifiedResult.setSuccess(mesResult.getSuccess()); |
| | | modifiedResult.setMessage(mesResult.getMessage()); |
| | | modifiedResult.setData(modifiedData); |
| | | mesResult = modifiedResult; |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 更新步骤状态(大车设备保持RUNNING,直到MES确认完成或任务取消) |
| | | if (mesResult != null) { |
| | | updateStepStatusForVehicle(step, mesResult); |
| | | updateStepStatusForVehicle(task.getTaskId(), step, mesResult); |
| | | boolean opSuccess = Boolean.TRUE.equals(mesResult.getSuccess()); |
| | | updateTaskProgress(task, step.getStepOrder(), opSuccess); |
| | | if (!opSuccess) { |
| | |
| | | DeviceCoordinationService.DeviceStatus.FAILED, context); |
| | | } |
| | | } else { |
| | | updateStepStatusForVehicle(step, feedResult); |
| | | updateStepStatusForVehicle(task.getTaskId(), step, feedResult); |
| | | boolean opSuccess = Boolean.TRUE.equals(feedResult.getSuccess()); |
| | | updateTaskProgress(task, step.getStepOrder(), opSuccess); |
| | | if (!opSuccess) { |
| | |
| | | task.getTaskId(), device.getId()); |
| | | return; |
| | | } |
| | | // 如果步骤已经完成,不再处理 |
| | | if (TaskStepDetail.Status.COMPLETED.name().equals(step.getStatus())) { |
| | | // 检查是否所有初始玻璃都已处理完 |
| | | @SuppressWarnings("unchecked") |
| | | List<String> initialGlassIds = (List<String>) context.getSharedData().get("initialGlassIds"); |
| | | List<String> processedGlassIds = getProcessedGlassIds(context); |
| | | |
| | | if (initialGlassIds != null && !initialGlassIds.isEmpty() |
| | | && processedGlassIds != null && !processedGlassIds.isEmpty() |
| | | && processedGlassIds.containsAll(initialGlassIds)) { |
| | | // 所有玻璃都已处理完,保持完成状态 |
| | | log.debug("大理片笼设备已完成且所有玻璃已处理: taskId={}, deviceId={}, initialCount={}, processedCount={}", |
| | | task.getTaskId(), device.getId(), initialGlassIds.size(), processedGlassIds.size()); |
| | | return; |
| | | } |
| | | } |
| | | |
| | | // 大理片笼设备:只有在真正开始处理时才设置为RUNNING |
| | | // 检查是否有已装载的玻璃信息(从进片大车来的) |
| | | List<String> loadedGlassIds = getLoadedGlassIds(context); |
| | | if (CollectionUtils.isEmpty(loadedGlassIds)) { |
| | | // 没有数据,保持WAITING状态和PENDING步骤状态 |
| | | // 没有数据,检查是否所有玻璃都已处理完 |
| | | @SuppressWarnings("unchecked") |
| | | List<String> initialGlassIds = (List<String>) context.getSharedData().get("initialGlassIds"); |
| | | List<String> processedGlassIds = getProcessedGlassIds(context); |
| | | |
| | | if (initialGlassIds != null && !initialGlassIds.isEmpty() |
| | | && processedGlassIds != null && !processedGlassIds.isEmpty() |
| | | && processedGlassIds.containsAll(initialGlassIds)) { |
| | | // 所有玻璃都已处理完,标记为完成 |
| | | if (!TaskStepDetail.Status.COMPLETED.name().equals(step.getStatus())) { |
| | | step.setStatus(TaskStepDetail.Status.COMPLETED.name()); |
| | | step.setSuccessMessage("所有玻璃已处理完成"); |
| | | if (step.getEndTime() == null) { |
| | | step.setEndTime(new Date()); |
| | | } |
| | | if (step.getStartTime() != null && step.getEndTime() != null) { |
| | | step.setDurationMs(step.getEndTime().getTime() - step.getStartTime().getTime()); |
| | | } |
| | | taskStepDetailMapper.updateById(step); |
| | | notificationService.notifyStepUpdate(task.getTaskId(), step); |
| | | checkAndCompleteTaskIfDone(step.getTaskId()); |
| | | } |
| | | return; |
| | | } |
| | | |
| | | // 没有数据且未完成,保持WAITING状态和PENDING步骤状态 |
| | | deviceCoordinationService.syncDeviceStatus(device, |
| | | DeviceCoordinationService.DeviceStatus.WAITING, context); |
| | | if (!TaskStepDetail.Status.PENDING.name().equals(step.getStatus())) { |
| | | if (!TaskStepDetail.Status.PENDING.name().equals(step.getStatus()) |
| | | && !TaskStepDetail.Status.COMPLETED.name().equals(step.getStatus())) { |
| | | step.setStatus(TaskStepDetail.Status.PENDING.name()); |
| | | step.setSuccessMessage("等待进片大车装载玻璃"); |
| | | taskStepDetailMapper.updateById(step); |
| | |
| | | Long processStartTime = getProcessStartTime(context); |
| | | if (processStartTime == null) { |
| | | // 第一次检测到玻璃,记录开始处理时间 |
| | | setProcessStartTime(context, System.currentTimeMillis()); |
| | | long now = System.currentTimeMillis(); |
| | | setProcessStartTime(context, now); |
| | | // 补齐步骤的开始时间与状态,确保前端耗时正常显示 |
| | | if (!TaskStepDetail.Status.RUNNING.name().equals(step.getStatus())) { |
| | | step.setStatus(TaskStepDetail.Status.RUNNING.name()); |
| | | } |
| | | if (step.getStartTime() == null) { |
| | | step.setStartTime(new Date(now)); |
| | | } |
| | | taskStepDetailMapper.updateById(step); |
| | | notificationService.notifyStepUpdate(task.getTaskId(), step); |
| | | log.debug("大理片笼设备开始处理: taskId={}, deviceId={}, glassCount={}, processTime={}s", |
| | | task.getTaskId(), device.getId(), loadedGlassIds.size(), processTimeSeconds); |
| | | return; |
| | |
| | | // 更新步骤状态 |
| | | step.setStatus(TaskStepDetail.Status.COMPLETED.name()); |
| | | step.setErrorMessage(null); |
| | | // 记录结束时间与耗时 |
| | | if (step.getEndTime() == null) { |
| | | step.setEndTime(new Date()); |
| | | } |
| | | if (step.getStartTime() == null) { |
| | | // 如果开始时间缺失,用处理开始时间或结束时间兜底 |
| | | step.setStartTime(new Date(processStartTime)); |
| | | } |
| | | if (step.getStartTime() != null && step.getEndTime() != null) { |
| | | step.setDurationMs(step.getEndTime().getTime() - step.getStartTime().getTime()); |
| | | } |
| | | step.setOutputData(toJson(Collections.singletonMap("glassIds", loadedGlassIds))); |
| | | taskStepDetailMapper.updateById(step); |
| | | // 大理片笼完成后尝试自动收尾整个任务 |
| | |
| | | */ |
| | | private void setLoadedGlassIds(TaskExecutionContext context, List<String> glassIds) { |
| | | if (context != null) { |
| | | context.getSharedData().put("loadedGlassIds", new ArrayList<>(glassIds)); |
| | | // 累加记录,避免后续 containsAll 判断因覆盖丢失历史玻璃而回退为等待 |
| | | List<String> merged = new ArrayList<>(getLoadedGlassIds(context)); // 确保可变 |
| | | if (glassIds != null) { |
| | | merged.addAll(glassIds); |
| | | } |
| | | // 去重 |
| | | List<String> distinct = merged.stream().distinct().collect(java.util.stream.Collectors.toList()); |
| | | context.getSharedData().put("loadedGlassIds", distinct); |
| | | } |
| | | } |
| | | |
| | |
| | | private void clearProcessedGlassIds(TaskExecutionContext context) { |
| | | if (context != null) { |
| | | context.getSharedData().put("processedGlassIds", new ArrayList<>()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 获取已出片的玻璃ID列表 |
| | | */ |
| | | @SuppressWarnings("unchecked") |
| | | private List<String> getOutboundGlassIds(TaskExecutionContext context) { |
| | | if (context == null) { |
| | | return Collections.emptyList(); |
| | | } |
| | | Object glassIds = context.getSharedData().get("outboundGlassIds"); |
| | | if (glassIds instanceof List) { |
| | | return new ArrayList<>((List<String>) glassIds); |
| | | } |
| | | return Collections.emptyList(); |
| | | } |
| | | |
| | | /** |
| | | * 添加已出片的玻璃ID列表 |
| | | */ |
| | | private void addOutboundGlassIds(TaskExecutionContext context, List<String> glassIds) { |
| | | if (context != null && glassIds != null && !glassIds.isEmpty()) { |
| | | List<String> existing = getOutboundGlassIds(context); |
| | | Set<String> allOutbound = new HashSet<>(existing); |
| | | allOutbound.addAll(glassIds); |
| | | context.getSharedData().put("outboundGlassIds", new ArrayList<>(allOutbound)); |
| | | } |
| | | } |
| | | |
| | |
| | | } |
| | | step.setOutputData(toJson(result)); |
| | | taskStepDetailMapper.updateById(step); |
| | | if (StringUtils.hasText(step.getTaskId())) { |
| | | notificationService.notifyStepUpdate(step.getTaskId(), step); |
| | | } |
| | | } |
| | | |
| | | /** |
| | |
| | | /** |
| | | * 更新大车设备步骤状态(保持RUNNING,直到手动停止或任务取消;失败时标记为FAILED) |
| | | */ |
| | | private void updateStepStatusForVehicle(TaskStepDetail step, DevicePlcVO.OperationResult result) { |
| | | private void updateStepStatusForVehicle(String taskId, TaskStepDetail step, DevicePlcVO.OperationResult result) { |
| | | if (step == null || result == null) { |
| | | return; |
| | | } |
| | | // 如果步骤已经处于完成或失败状态,则不再被重复更新(防止状态反复切换) |
| | | if (TaskStepDetail.Status.COMPLETED.name().equals(step.getStatus()) |
| | | || TaskStepDetail.Status.FAILED.name().equals(step.getStatus())) { |
| | | log.debug("步骤已完成或失败,不再更新状态: stepId={}, status={}", step.getId(), step.getStatus()); |
| | | return; |
| | | } |
| | | boolean success = Boolean.TRUE.equals(result.getSuccess()); |
| | |
| | | |
| | | if (success && !completed) { |
| | | // 成功但未完成:根据waiting状态决定显示为等待还是执行中 |
| | | if (waiting) { |
| | | // 注意:如果步骤已经是RUNNING状态(说明已经装载过玻璃),不应该改回PENDING |
| | | boolean isAlreadyRunning = TaskStepDetail.Status.RUNNING.name().equals(step.getStatus()); |
| | | if (waiting && !isAlreadyRunning) { |
| | | // 只有在还没有开始运行时,才设置为PENDING |
| | | step.setStatus(TaskStepDetail.Status.PENDING.name()); |
| | | } else { |
| | | // 如果已经运行过,或者不是等待状态,保持或设置为RUNNING |
| | | step.setStatus(TaskStepDetail.Status.RUNNING.name()); |
| | | } |
| | | String message = result.getMessage(); |
| | | if (!StringUtils.hasText(message) && waiting) { |
| | | message = "大车设备等待中" + (StringUtils.hasText(waitingReason) ? "(" + waitingReason + ")" : ""); |
| | | } |
| | | step.setSuccessMessage(StringUtils.hasText(message) ? message : (waiting ? "大车设备等待中" : "大车设备运行中")); |
| | | step.setSuccessMessage(StringUtils.hasText(message) ? message : (waiting && !isAlreadyRunning ? "大车设备等待中" : "大车设备运行中")); |
| | | step.setErrorMessage(null); |
| | | if (step.getStartTime() != null) { |
| | | step.setDurationMs(now.getTime() - step.getStartTime().getTime()); |
| | |
| | | |
| | | step.setOutputData(toJson(result)); |
| | | taskStepDetailMapper.updateById(step); |
| | | // 通知前端步骤状态已更新 |
| | | notificationService.notifyStepUpdate(taskId, step); |
| | | } |
| | | |
| | | /** |
| | |
| | | // 然后检查MES确认状态 |
| | | DevicePlcVO.OperationResult mesResult = null; |
| | | try { |
| | | mesResult = handler.execute(device, "checkMesConfirm", Collections.emptyMap()); |
| | | Map<String, Object> checkParams = new HashMap<>(); |
| | | checkParams.put("_taskContext", context); |
| | | mesResult = handler.execute(device, "checkMesConfirm", checkParams); |
| | | } catch (Exception e) { |
| | | log.warn("大车设备检查MES确认状态异常: taskId={}, deviceId={}, error={}", |
| | | task.getTaskId(), device.getId(), e.getMessage()); |
| | | } |
| | | |
| | | // 如果MES已确认完成(mesConfirm=1),检查卧转立设备状态和玻璃信息 |
| | | // 如果卧转立已完成且所有玻璃都已装载,可以标记为完成 |
| | | if (mesResult != null && mesResult.getData() != null) { |
| | | Object completedFlag = mesResult.getData().get("completed"); |
| | | boolean mesConfirmed = false; |
| | | if (completedFlag instanceof Boolean) { |
| | | mesConfirmed = (Boolean) completedFlag; |
| | | } else if (completedFlag != null) { |
| | | mesConfirmed = "true".equalsIgnoreCase(String.valueOf(completedFlag)); |
| | | } |
| | | |
| | | if (mesConfirmed) { |
| | | // MES已确认完成,检查卧转立设备是否已完成 |
| | | boolean transferCompleted = isTransferDeviceCompleted(task.getTaskId(), context); |
| | | if (transferCompleted) { |
| | | // 检查任务上下文中的初始玻璃ID和已装载的玻璃ID |
| | | @SuppressWarnings("unchecked") |
| | | List<String> initialGlassIds = (List<String>) context.getSharedData().get("initialGlassIds"); |
| | | List<String> loadedGlassIds = getLoadedGlassIds(context); |
| | | |
| | | if (initialGlassIds != null && !initialGlassIds.isEmpty() |
| | | && loadedGlassIds != null && !loadedGlassIds.isEmpty()) { |
| | | // 检查是否所有初始玻璃都已装载 |
| | | boolean allGlassesLoaded = loadedGlassIds.containsAll(initialGlassIds); |
| | | if (allGlassesLoaded) { |
| | | // 卧转立已完成且所有玻璃都已装载,标记为完成 |
| | | log.info("MES已确认且卧转立已完成且所有玻璃已装载,任务自动完成: taskId={}, deviceId={}, initialCount={}, loadedCount={}", |
| | | task.getTaskId(), device.getId(), initialGlassIds.size(), loadedGlassIds.size()); |
| | | // mesResult已经包含completed=true,不需要修改 |
| | | } |
| | | } |
| | | } else { |
| | | // 卧转立还未完成,不应该标记为完成 |
| | | log.debug("MES已确认但卧转立未完成,等待卧转立完成: taskId={}, deviceId={}", |
| | | task.getTaskId(), device.getId()); |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 更新步骤状态 |
| | | if (mesResult != null) { |
| | | updateStepStatusForVehicle(step, mesResult); |
| | | updateStepStatusForVehicle(task.getTaskId(), step, mesResult); |
| | | boolean opSuccess = Boolean.TRUE.equals(mesResult.getSuccess()); |
| | | updateTaskProgress(task, step.getStepOrder(), opSuccess); |
| | | if (!opSuccess) { |
| | |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 检查卧转立设备是否已完成 |
| | | * 返回true表示卧转立已完成(COMPLETED),可以判断大车是否完成 |
| | | * 返回false表示卧转立还在运行中(RUNNING)或等待中(PENDING),不应该标记大车为完成 |
| | | */ |
| | | private boolean isTransferDeviceCompleted(String taskId, TaskExecutionContext context) { |
| | | if (taskId == null || context == null) { |
| | | return false; |
| | | } |
| | | try { |
| | | // 从上下文中获取设备列表 |
| | | @SuppressWarnings("unchecked") |
| | | List<DeviceConfig> devices = (List<DeviceConfig>) context.getSharedData().get("devices"); |
| | | if (devices == null || devices.isEmpty()) { |
| | | return false; |
| | | } |
| | | |
| | | // 查找卧转立设备 |
| | | DeviceConfig transferDevice = null; |
| | | for (DeviceConfig device : devices) { |
| | | if (DeviceConfig.DeviceType.WORKSTATION_TRANSFER.equals(device.getDeviceType())) { |
| | | transferDevice = device; |
| | | break; |
| | | } |
| | | } |
| | | |
| | | if (transferDevice == null) { |
| | | // 没有卧转立设备,返回true(不影响判断) |
| | | return true; |
| | | } |
| | | |
| | | // 查找卧转立设备的步骤(应该只有一个步骤) |
| | | List<TaskStepDetail> transferSteps = taskStepDetailMapper.selectList( |
| | | Wrappers.<TaskStepDetail>lambdaQuery() |
| | | .eq(TaskStepDetail::getTaskId, taskId) |
| | | .eq(TaskStepDetail::getDeviceId, transferDevice.getId()) |
| | | .orderByDesc(TaskStepDetail::getStepOrder) |
| | | .last("LIMIT 1") |
| | | ); |
| | | |
| | | if (transferSteps == null || transferSteps.isEmpty()) { |
| | | // 没有找到步骤,返回false(卧转立可能还没开始) |
| | | return false; |
| | | } |
| | | |
| | | // 检查步骤状态:只有COMPLETED才算完成,RUNNING或PENDING都不算完成 |
| | | TaskStepDetail transferStep = transferSteps.get(0); |
| | | String status = transferStep.getStatus(); |
| | | boolean isCompleted = TaskStepDetail.Status.COMPLETED.name().equals(status); |
| | | |
| | | log.debug("检查卧转立设备状态: taskId={}, deviceId={}, status={}, isCompleted={}", |
| | | taskId, transferDevice.getId(), status, isCompleted); |
| | | |
| | | return isCompleted; |
| | | } catch (Exception e) { |
| | | log.warn("检查卧转立设备状态失败: taskId={}", taskId, e); |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | private String determineOperation(DeviceConfig device, Map<String, Object> params) { |
| | | if (params != null && params.containsKey("operation")) { |
| | | Object op = params.get("operation"); |