自动化立体仓库 - WMS系统
chen.llin
3 天以前 cea1758e1f540e3f5f807951f128b7385b32afe6
src/main/java/com/zy/asrs/task/AgvScheduler.java
@@ -1,5 +1,7 @@
package com.zy.asrs.task;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.core.common.Cools;
@@ -11,7 +13,9 @@
import com.zy.asrs.service.WrkMastLogService;
import com.zy.asrs.service.WrkMastService;
import com.zy.asrs.task.handler.AgvHandler;
import com.zy.common.constant.ApiInterfaceConstant;
import com.zy.common.properties.SchedulerProperties;
import com.zy.common.utils.HttpHandler;
import com.zy.system.entity.Config;
import com.zy.system.service.ConfigService;
import lombok.extern.slf4j.Slf4j;
@@ -19,11 +23,14 @@
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
/**
@@ -144,6 +151,7 @@
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    log.warn("定时任务allocateSite:延迟被中断", e);
                    isAllocateSite.set(false);
                    break; // 如果被中断,退出循环
                }
            }
@@ -202,7 +210,6 @@
                        displayTaskId, task.getWrkNo(), task.getIoType(), task.getStaNo());
                boolean processed = agvHandler.callAgv(Collections.singletonList(task));
                // 只有当任务成功处理(成功呼叫AGV,状态从7变为8)时,才更新lastProcessedTaskId
                // 如果任务被跳过(站点被占用等),不更新lastProcessedTaskId,下次会重新尝试
                if (processed) {
                    lastProcessedTaskId = task.getId();
@@ -218,6 +225,7 @@
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    log.warn("呼叫AGV定时任务:延迟被中断", e);
                    isAllocateSite.set(false);
                    break; // 如果被中断,退出循环
                }
            }
@@ -325,14 +333,16 @@
                    if (agvTask.getIoType() != null &&
                            (agvTask.getIoType() == 1 || agvTask.getIoType() == 10 ||
                                    agvTask.getIoType() == 53 || agvTask.getIoType() == 57)) {
                        // taskId使用工作号(wrk_no),如果工作号为空则使用任务ID
                        String displayTaskId = (agvTask.getWrkNo() != null) ? String.valueOf(agvTask.getWrkNo()) : String.valueOf(agvTask.getId());
                        // 更新AGV任务状态为完成
                        agvTask.setWrkSts(9L);
                        agvTask.setModiTime(now);
                        if (taskService.updateById(agvTask)) {
                            completedTasks.add(agvTask);
                            completedCount++;
                            // taskId使用工作号(wrk_no),如果工作号为空则使用任务ID
                            String displayTaskId = (agvTask.getWrkNo() != null) ? String.valueOf(agvTask.getWrkNo()) : String.valueOf(agvTask.getId());
                            log.info("入库任务工作档已入库成功,完结AGV呼叫单,taskId:{},wrkNo:{},barcode:{}",
                                    displayTaskId, wrkMast.getWrkNo(), wrkMast.getBarcode());
                        }
@@ -577,6 +587,36 @@
                                reason, displayTaskId, agvTask.getWrkNo(), agvTask.getBarcode(), agvTask.getStaNo());
                    }
                }
                // 检查订单创建时间,超过五分钟后才查询AGV订单状态
                Date appeTime = agvTask.getAppeTime();
                boolean shouldCheckAgvStatus = false;
                if (appeTime != null) {
                    long timeDiff = now.getTime() - appeTime.getTime();
                    long fiveMinutesInMillis = 5 * 60 * 1000; // 5分钟
                    if (timeDiff >= fiveMinutesInMillis) {
                        shouldCheckAgvStatus = true;
                    }
                } else {
                    // 如果没有创建时间,默认检查
                    shouldCheckAgvStatus = true;
                }
                // taskId使用工作号(wrk_no),如果工作号为空则使用任务ID
                String displayTaskId = (agvTask.getWrkNo() != null) ? String.valueOf(agvTask.getWrkNo()) : String.valueOf(agvTask.getId());
                // 如果订单创建超过五分钟,查询AGV订单状态
                if (shouldCheckAgvStatus) {
                    String agvOrderStatus = queryAgvOrderStatus(agvTask, displayTaskId);
                    if (agvOrderStatus != null) {
                        // 根据订单状态处理
                        boolean shouldComplete = processAgvOrderStatus(agvTask, agvOrderStatus, displayTaskId, now);
                        if (shouldComplete) {
                            completedTasks.add(agvTask);
                        }
                    }
                }
            }
            // 立即将完成的AGV任务转移到历史表,不保留在Task表中
@@ -597,5 +637,177 @@
        }
    }
    /**
     * 查询AGV订单状态
     * @param agvTask AGV任务
     * @param displayTaskId 显示的任务ID
     * @return 订单状态(Building/Created/Assigned/Failed/Done/Cancelled),如果查询失败返回null
     */
    private String queryAgvOrderStatus(Task agvTask, String displayTaskId) {
        try {
            // 构建订单ID,格式为 "T" + wrkNo
            String orderId = null;
            if (agvTask.getWrkNo() != null) {
                orderId = "T" + agvTask.getWrkNo();
            } else {
                String errorMsg = String.format("查询AGV订单状态失败:任务ID:%s,wrkNo为空", displayTaskId);
                log.warn("查询AGV订单状态失败 - 任务ID:{},{}", displayTaskId, errorMsg);
                agvTask.setErrorMemo(errorMsg);
                agvTask.setErrorTime(new Date());
                taskService.updateById(agvTask);
                return null;
            }
            // 构建请求JSON
            JSONObject requestJson = new JSONObject();
            requestJson.put("entityName", "ContainerTransportOrder");
            requestJson.put("id", orderId);
            String requestBody = requestJson.toJSONString();
            // 构建请求头
            Map<String, Object> headers = new HashMap<>();
            headers.put("xyy-app-id", "seer");
            headers.put("xyy-app-key", "123456");
            // 发送请求
            String response = null;
            try {
                response = new HttpHandler.Builder()
                        .setUri(ApiInterfaceConstant.AGV_IP)
                        .setPath(ApiInterfaceConstant.AGV_FIND_ONE_PATH)
                        .setJson(requestBody)
                        .setHeaders(headers)
                        .build()
                        .doPost();
            } catch (IOException e) {
                String errorMsg = String.format("查询AGV订单状态API调用失败:%s,请求:%s", e.getMessage(), requestBody);
                log.error("查询AGV订单状态失败 - 任务ID:{},订单ID:{},{}", displayTaskId, orderId, errorMsg, e);
                agvTask.setErrorMemo2(errorMsg);
                agvTask.setErrorTime2(new Date());
                taskService.updateById(agvTask);
                return null;
            }
            // 解析响应
            if (response == null || response.trim().isEmpty()) {
                String errorMsg = String.format("查询AGV订单状态API返回为空,请求:%s", requestBody);
                log.warn("查询AGV订单状态失败 - 任务ID:{},订单ID:{},{}", displayTaskId, orderId, errorMsg);
                agvTask.setErrorMemo2(errorMsg);
                agvTask.setErrorTime2(new Date());
                taskService.updateById(agvTask);
                return null;
            }
            try {
                JSONObject responseJson = JSON.parseObject(response);
                // 检查是否有错误码
                String code = responseJson.getString("code");
                if (code != null && "errNoSuchEntity".equals(code)) {
                    // 找不到业务对象,记录到errorMemo但忽略(不阻止后续处理)
                    String errorMsg = String.format("查询AGV订单状态:找不到订单(errNoSuchEntity),请求:%s,响应:%s", requestBody, response);
                    log.debug("查询AGV订单状态:找不到订单 - 任务ID:{},订单ID:{}", displayTaskId, orderId);
                    agvTask.setErrorMemo2(errorMsg);
                    agvTask.setErrorTime2(new Date());
                    taskService.updateById(agvTask);
                    return null;
                }
                // 获取订单信息
                JSONObject entityValue = responseJson.getJSONObject("entityValue");
                if (entityValue != null) {
                    String status = entityValue.getString("status");
                    if (status != null) {
                        log.info("查询AGV订单状态成功 - 任务ID:{},订单ID:{},状态:{}", displayTaskId, orderId, status);
                        return status;
                    } else {
                        String errorMsg = String.format("查询AGV订单状态响应中缺少status字段,请求:%s,响应:%s", requestBody, response);
                        log.warn("查询AGV订单状态失败 - 任务ID:{},订单ID:{},{}", displayTaskId, orderId, errorMsg);
                        agvTask.setErrorMemo2(errorMsg);
                        agvTask.setErrorTime2(new Date());
                        taskService.updateById(agvTask);
                        return null;
                    }
                } else {
                    String errorMsg = String.format("查询AGV订单状态响应中缺少entityValue字段,请求:%s,响应:%s", requestBody, response);
                    log.warn("查询AGV订单状态失败 - 任务ID:{},订单ID:{},{}", displayTaskId, orderId, errorMsg);
                    agvTask.setErrorMemo2(errorMsg);
                    agvTask.setErrorTime2(new Date());
                    taskService.updateById(agvTask);
                    return null;
                }
            } catch (com.alibaba.fastjson.JSONException e) {
                String errorMsg = String.format("解析AGV订单状态响应JSON失败:%s,请求:%s,响应:%s", e.getMessage(), requestBody, response);
                log.error("查询AGV订单状态失败 - 任务ID:{},订单ID:{},{}", displayTaskId, orderId, errorMsg, e);
                agvTask.setErrorMemo2(errorMsg);
                agvTask.setErrorTime2(new Date());
                taskService.updateById(agvTask);
                return null;
            }
        } catch (Exception e) {
            String errorMsg = String.format("查询AGV订单状态异常:%s", e.getMessage());
            log.error("查询AGV订单状态异常 - 任务ID:{},{}", displayTaskId, errorMsg, e);
            agvTask.setErrorMemo2(errorMsg);
            agvTask.setErrorTime2(new Date());
            taskService.updateById(agvTask);
            return null;
        }
    }
    /**
     * 处理AGV订单状态
     * @param agvTask AGV任务
     * @param status 订单状态
     * @param displayTaskId 显示的任务ID
     * @param now 当前时间
     * @return true表示应该完结订单,false表示不应该完结(跳过)
     */
    private boolean processAgvOrderStatus(Task agvTask, String status, String displayTaskId, Date now) {
        if (status == null) {
            return false; // 状态为空,跳过
        }
        switch (status) {
            case "Building":
                // Building=未提交,正常没有此状态,忽略
                log.debug("AGV订单状态为Building(未提交),忽略 - 任务ID:{}", displayTaskId);
                return true; // 继续处理
            case "Created":
                // Created=已提交,等待期间,不处理
                log.debug("AGV订单状态为Created(已提交),等待期间,不处理 - 任务ID:{}", displayTaskId);
                return false; // 不处理,跳过
            case "Assigned":
            case "Assined":
                // Assigned=已派车,正常状态,不处理
                log.debug("AGV订单状态为{}(已派车),正常状态,不处理 - 任务ID:{}", status, displayTaskId);
                return false; // 不处理,跳过
            case "Failed":
            case "Failde":
                // Failed=失败,标记为失败订单
                log.warn("AGV订单状态为{}(失败),标记为失败订单 - 任务ID:{}", status, displayTaskId);
                agvTask.setWrkSts(10L);
                agvTask.setErrorTime(now);
                agvTask.setErrorMemo(String.format("AGV订单状态为%s(失败)", status));
                taskService.updateById(agvTask);
                return false; // 不处理,跳过
            case "Done":
                // Done=已完成,完结订单
                log.info("AGV订单状态为Done(已完成),完结订单 - 任务ID:{}", displayTaskId);
                return true; // 继续处理,完结订单
            case "Cancelled":
                // Cancelled=取消,取消订单
                log.warn("AGV订单状态为Cancelled(取消),取消订单 - 任务ID:{}", displayTaskId);
                agvTask.setWrkSts(10L);
                agvTask.setErrorTime(now);
                agvTask.setErrorMemo("AGV订单状态为Cancelled(取消)");
                taskService.updateById(agvTask);
                return false; // 不处理,跳过
            default:
                // 未知状态,记录日志但继续处理
                log.warn("AGV订单状态未知:{},继续处理 - 任务ID:{}", status, displayTaskId);
                return true; // 继续处理
        }
    }
}