huang
2025-12-02 628aa6a42e587e9f337e213f87f922fc2ab2af02
mes-processes/mes-plcSend/src/main/java/com/mes/task/service/TaskExecutionEngine.java
@@ -165,6 +165,12 @@
                    log.info("检测到扫码设备,准备启动定时器: deviceId={}, deviceType={}, deviceName={}", 
                            device.getId(), device.getDeviceType(), device.getDeviceName());
                    TaskStepDetail step = createStepRecord(task, device, currentOrder);
                    // 设置步骤为运行状态,并设置开始时间
                    step.setStatus(TaskStepDetail.Status.RUNNING.name());
                    step.setStartTime(new Date());
                    taskStepDetailMapper.updateById(step);
                    notificationService.notifyStepUpdate(task.getTaskId(), step);
                    ScheduledFuture<?> scannerTask = startScannerTimer(task, step, device, context);
                    if (scannerTask != null) {
                        registerScheduledTask(task.getTaskId(), scannerTask);
@@ -187,6 +193,12 @@
                    log.info("检测到卧转立设备,准备启动定时器: deviceId={}, deviceType={}, deviceName={}", 
                            device.getId(), device.getDeviceType(), device.getDeviceName());
                    TaskStepDetail step = createStepRecord(task, device, currentOrder);
                    // 设置步骤为运行状态,并设置开始时间
                    step.setStatus(TaskStepDetail.Status.RUNNING.name());
                    step.setStartTime(new Date());
                    taskStepDetailMapper.updateById(step);
                    notificationService.notifyStepUpdate(task.getTaskId(), step);
                    ScheduledFuture<?> transferTask = startTransferTimer(task, step, device, context);
                    if (transferTask != null) {
                        registerScheduledTask(task.getTaskId(), transferTask);
@@ -209,6 +221,12 @@
                    boolean isInboundVehicle = currentLoadVehicleIndex == 1; // 第一个大车是进片大车
                    
                    TaskStepDetail step = createStepRecord(task, device, currentOrder);
                    // 设置步骤为运行状态,并设置开始时间
                    step.setStatus(TaskStepDetail.Status.RUNNING.name());
                    step.setStartTime(new Date());
                    taskStepDetailMapper.updateById(step);
                    notificationService.notifyStepUpdate(task.getTaskId(), step);
                    ScheduledFuture<?> vehicleTask;
                    if (isInboundVehicle) {
                        // 进片大车:监控容量,动态判断
@@ -242,6 +260,12 @@
                // 4. 大理片笼设备:启动定时器逻辑处理(不涉及PLC交互,只负责逻辑处理)
                if (isLargeGlass) {
                    TaskStepDetail step = createStepRecord(task, device, currentOrder);
                    // 设置步骤为运行状态,并设置开始时间
                    step.setStatus(TaskStepDetail.Status.RUNNING.name());
                    step.setStartTime(new Date());
                    taskStepDetailMapper.updateById(step);
                    notificationService.notifyStepUpdate(task.getTaskId(), step);
                    ScheduledFuture<?> largeGlassTask = startLargeGlassTimer(task, step, device, context);
                    if (largeGlassTask != null) {
                        registerScheduledTask(task.getTaskId(), largeGlassTask);
@@ -392,6 +416,17 @@
                        log.info("卧转立扫码定时器完成: taskId={}, deviceId={}, processed={}/{}, success={}, fail={}",
                                task.getTaskId(), device.getId(), processedCount.get(), glassIds.size(),
                                successCount.get(), failCount.get());
                        // 若之前未出现失败,再将状态置为完成
                        boolean alreadyFailed = TaskStepDetail.Status.FAILED.name().equals(step.getStatus());
                        if (!alreadyFailed) {
                            step.setStatus(TaskStepDetail.Status.COMPLETED.name());
                            step.setSuccessMessage(String.format("已完成扫描: 成功=%d, 失败=%d", successCount.get(), failCount.get()));
                            if (step.getEndTime() == null) {
                                step.setEndTime(new Date());
                            }
                            taskStepDetailMapper.updateById(step);
                            notificationService.notifyStepUpdate(task.getTaskId(), step);
                        }
                        deviceCoordinationService.syncDeviceStatus(device,
                                DeviceCoordinationService.DeviceStatus.COMPLETED, context);
                        return;
@@ -492,15 +527,21 @@
                    if (handler != null) {
                        DevicePlcVO.OperationResult result = handler.execute(device, "checkAndProcess", params);
                        
                        // 更新步骤状态
                        updateStepStatus(step, result);
                        // 更新步骤状态(区分等待中和真正完成)
                        updateStepStatusForTransfer(step, result);
                        // 通知步骤更新(让前端实时看到步骤状态)
                        notificationService.notifyStepUpdate(task.getTaskId(), step);
                        boolean opSuccess = Boolean.TRUE.equals(result.getSuccess());
                        updateTaskProgress(task, step.getStepOrder(), opSuccess);
                        if (opSuccess) {
                            log.debug("卧转立设备定时器执行成功: taskId={}, deviceId={}, message={}",
                                    task.getTaskId(), device.getId(), result.getMessage());
                            String message = result.getMessage();
                            if (message != null && message.contains("批次已写入PLC")) {
                                log.info("卧转立设备定时器执行成功(已写入PLC): taskId={}, deviceId={}, message={}",
                                        task.getTaskId(), device.getId(), message);
                            } else {
                                log.debug("卧转立设备定时器等待中: taskId={}, deviceId={}, message={}",
                                        task.getTaskId(), device.getId(), message);
                            }
                        } else {
                            log.warn("卧转立设备定时器执行失败: taskId={}, deviceId={}, message={}",
                                    task.getTaskId(), device.getId(), result.getMessage());
@@ -544,28 +585,27 @@
                                task.getTaskId(), device.getId());
                        return;
                    }
                    // 检查是否有已扫描的玻璃信息
                    List<String> scannedGlassIds = getScannedGlassIds(context);
                    if (CollectionUtils.isEmpty(scannedGlassIds)) {
                        // 没有已扫描的玻璃,确保卧转立扫码继续运行
                        setScannerPause(context, false);
                    // 检查是否有卧转立主体已输出、准备上大车的玻璃信息
                    List<String> readyGlassIds = getTransferReadyGlassIds(context);
                    if (CollectionUtils.isEmpty(readyGlassIds)) {
                        // 没有卧转立输出的玻璃,继续等待
                        return;
                    }
                    
                    // 如果玻璃ID数量没有变化,说明没有新的玻璃,继续等待
                    int currentCount = scannedGlassIds.size();
                    int currentCount = readyGlassIds.size();
                    if (currentCount == lastProcessedCount.get()) {
                        log.debug("大车设备定时器:玻璃ID数量未变化,继续等待: taskId={}, deviceId={}, count={}",
                                task.getTaskId(), device.getId(), currentCount);
                        return;
                    }
                    
                    log.info("进片大车设备定时器检测到新的玻璃信息: taskId={}, deviceId={}, glassCount={}",
                    log.info("进片大车设备定时器检测到卧转立输出的玻璃信息: taskId={}, deviceId={}, glassCount={}",
                            task.getTaskId(), device.getId(), currentCount);
                    
                    // 检查容量
                    Map<String, Object> checkParams = new HashMap<>();
                    checkParams.put("glassIds", new ArrayList<>(scannedGlassIds));
                    checkParams.put("glassIds", new ArrayList<>(readyGlassIds));
                    checkParams.put("_taskContext", context);
                    
                    DeviceLogicHandler handler = handlerFactory.getHandler(device.getDeviceType());
@@ -579,19 +619,18 @@
                        
                        if (Boolean.TRUE.equals(result.getSuccess())) {
                            log.info("进片大车设备定时器执行成功: taskId={}, deviceId={}, glassCount={}",
                                    task.getTaskId(), device.getId(), scannedGlassIds.size());
                                    task.getTaskId(), device.getId(), readyGlassIds.size());
                            // 将已装载的玻璃ID保存到共享数据中(供大理片笼使用)
                            setLoadedGlassIds(context, new ArrayList<>(scannedGlassIds));
                            // 清空已扫描的玻璃ID列表(已处理)
                            clearScannedGlassIds(context);
                            setLoadedGlassIds(context, new ArrayList<>(readyGlassIds));
                            // 清空卧转立输出的玻璃ID列表(已处理)
                            clearTransferReadyGlassIds(context);
                            lastProcessedCount.set(0);
                            // 确保卧转立扫码继续运行
                            setScannerPause(context, false);
                        } else {
                            // 装不下,通知卧转立扫码暂停
                            log.warn("进片大车设备定时器容量不足: taskId={}, deviceId={}, message={}, 已通知卧转立扫码暂停",
                            // 装不下,记录容量不足(是否需要影响扫码由工艺再决定)
                            log.warn("进片大车设备定时器容量不足: taskId={}, deviceId={}, message={}",
                                    task.getTaskId(), device.getId(), result.getMessage());
                            setScannerPause(context, true);
                            lastProcessedCount.set(currentCount); // 记录当前数量,避免重复检查
                        }
                        
@@ -944,6 +983,30 @@
    }
    
    /**
     * 获取卧转立主体已输出、准备上大车的玻璃ID列表
     */
    @SuppressWarnings("unchecked")
    private List<String> getTransferReadyGlassIds(TaskExecutionContext context) {
        if (context == null) {
            return Collections.emptyList();
        }
        Object glassIds = context.getSharedData().get("transferReadyGlassIds");
        if (glassIds instanceof List) {
            return new ArrayList<>((List<String>) glassIds);
        }
        return Collections.emptyList();
    }
    /**
     * 清空卧转立主体已输出的玻璃ID列表
     */
    private void clearTransferReadyGlassIds(TaskExecutionContext context) {
        if (context != null) {
            context.getSharedData().put("transferReadyGlassIds", new ArrayList<>());
        }
    }
    /**
     * 注册定时器任务
     */
    private void registerScheduledTask(String taskId, ScheduledFuture<?> future) {
@@ -1025,10 +1088,61 @@
        if (success) {
            // 成功时,如果有消息则保存(用于提示信息),否则清空
            step.setSuccessMessage(StringUtils.hasText(message) ? message : null);
            // 如果状态变为完成,设置结束时间
            if (TaskStepDetail.Status.COMPLETED.name().equals(step.getStatus()) && step.getEndTime() == null) {
                step.setEndTime(new Date());
            }
        } else {
            // 失败时保存错误消息
            step.setErrorMessage(message);
            // 如果状态变为失败,设置结束时间
            if (TaskStepDetail.Status.FAILED.name().equals(step.getStatus()) && step.getEndTime() == null) {
                step.setEndTime(new Date());
        }
        }
        step.setOutputData(toJson(result));
        taskStepDetailMapper.updateById(step);
    }
    /**
     * 更新卧转立设备步骤状态(区分等待中和真正完成)
     */
    private void updateStepStatusForTransfer(TaskStepDetail step, DevicePlcVO.OperationResult result) {
        if (step == null || result == null) {
            return;
        }
        boolean success = Boolean.TRUE.equals(result.getSuccess());
        String message = result.getMessage();
        // 判断是否真正完成(只有写入PLC才算完成)
        boolean isRealCompleted = success && message != null && message.contains("批次已写入PLC");
        if (isRealCompleted) {
            // 真正完成:设置为完成状态,并设置结束时间
            step.setStatus(TaskStepDetail.Status.COMPLETED.name());
            step.setSuccessMessage(message);
            if (step.getEndTime() == null) {
                step.setEndTime(new Date());
            }
        } else if (success) {
            // 等待中:保持运行状态,只更新消息
            if (!TaskStepDetail.Status.RUNNING.name().equals(step.getStatus())) {
                step.setStatus(TaskStepDetail.Status.RUNNING.name());
            }
            step.setSuccessMessage(message);
            // 确保开始时间已设置
            if (step.getStartTime() == null) {
                step.setStartTime(new Date());
            }
        } else {
            // 失败:设置为失败状态,并设置结束时间
            step.setStatus(TaskStepDetail.Status.FAILED.name());
            step.setErrorMessage(message);
            if (step.getEndTime() == null) {
                step.setEndTime(new Date());
            }
        }
        step.setOutputData(toJson(result));
        taskStepDetailMapper.updateById(step);
    }