package com.zy.asrs.task; import com.baomidou.mybatisplus.mapper.EntityWrapper; import com.baomidou.mybatisplus.mapper.Wrapper; import com.core.common.Cools; import com.zy.asrs.entity.Task; import com.zy.asrs.entity.WrkMast; import com.zy.asrs.mapper.WrkMastMapper; import com.zy.asrs.entity.WrkMastLog; import com.zy.asrs.service.TaskService; import com.zy.asrs.service.WrkMastLogService; import com.zy.asrs.service.WrkMastService; import com.zy.asrs.task.handler.AgvHandler; import com.zy.common.properties.SchedulerProperties; import com.zy.system.entity.Config; import com.zy.system.service.ConfigService; import lombok.extern.slf4j.Slf4j; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import javax.annotation.Resource; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.List; /** * @author pang.jiabao * @description AGV交互相关定时任务 * @createDate 2025/11/18 14:18 */ @Slf4j @Component public class AgvScheduler { @Resource private ConfigService configService; @Resource private AgvHandler agvHandler; @Resource private TaskService taskService; @Resource private WrkMastMapper wrkMastMapper; @Resource private WrkMastService wrkMastService; @Resource private WrkMastLogService wrkMastLogService; @Resource private SchedulerProperties schedulerProperties; /** * 呼叫agv搬运 */ @Scheduled(cron = "0/5 * * * * ? ") private void callAgv() { if (!schedulerProperties.isEnabled()) { return; } // 查询待呼叫agv任务,按id升序排序(id最小的优先呼叫) List taskList = taskService.selectList( new EntityWrapper() .eq("wrk_sts", 7) .orderBy("id", true) // 按id升序,id最小的优先 ); if(taskList.isEmpty()) { return; } agvHandler.callAgv(taskList); } /** * 货物到达出库口,生成agv任务 */ @Scheduled(cron = "0/3 * * * * ? ") private void createAgvOutTasks() { if (!schedulerProperties.isEnabled()) { return; } // 获取呼叫agv配置 List configs = configService.selectList(new EntityWrapper().in("code", "eastCallAgvControl", "westCallAgvControl").eq("status", 1)); if(configs.isEmpty()) { return; } // 获取agv出库可用站点 List sites = new ArrayList<>(); for(Config config: configs) { String value = config.getValue(); if(Cools.isEmpty(value)) { continue; } String[] split = value.split(";"); sites.addAll(Arrays.asList(split)); } if(sites.isEmpty()) { return; } agvHandler.createAgvOutTasks(sites); } /** * 任务完成转历史 */ @Scheduled(cron = "0/10 * * * * ? ") private void moveTaskToHistory() { if (!schedulerProperties.isEnabled()) { return; } List taskList = taskService.selectList(new EntityWrapper().eq("wrk_sts", 9)); if(taskList.isEmpty()) { return; } agvHandler.moveTaskToHistory(taskList); } /** * 检查入库成功的任务,完结对应的AGV呼叫单 * 如果入库任务呼叫AGV后没有收到回调,但工作档已经入库成功,则完结AGV呼叫单 */ @Scheduled(cron = "0/10 * * * * ? ") private void checkInboundCompletedTasks() { if (!schedulerProperties.isEnabled()) { return; } try { // 查询入库成功的工作档(状态4:入库完成,入库类型:1,10,53,57) List completedWrkMasts = wrkMastService.selectList( new EntityWrapper() .eq("wrk_sts", 4L) // 入库完成 .in("io_type", 1, 10, 53, 57) // 入库类型 .isNotNull("wrk_no") ); if (completedWrkMasts.isEmpty()) { return; } Date now = new Date(); int completedCount = 0; for (WrkMast wrkMast : completedWrkMasts) { // 查找对应的AGV任务(优先通过wrk_no查询) Wrapper taskWrapper1 = new EntityWrapper() .eq("task_type", "agv") .eq("wrk_sts", 8L) // 已呼叫AGV状态 .eq("wrk_no", wrkMast.getWrkNo()); List agvTasks = taskService.selectList(taskWrapper1); // 如果通过wrk_no没找到,且有条码,则通过条码查询 if (agvTasks.isEmpty() && !Cools.isEmpty(wrkMast.getBarcode())) { Wrapper taskWrapper2 = new EntityWrapper() .eq("task_type", "agv") .eq("wrk_sts", 8L) .eq("barcode", wrkMast.getBarcode()); agvTasks = taskService.selectList(taskWrapper2); } for (Task agvTask : agvTasks) { // 确保是入库任务 if (agvTask.getIoType() != null && (agvTask.getIoType() == 1 || agvTask.getIoType() == 10 || agvTask.getIoType() == 53 || agvTask.getIoType() == 57)) { // 更新AGV任务状态为完成 agvTask.setWrkSts(9L); agvTask.setModiTime(now); if (taskService.updateById(agvTask)) { completedCount++; log.info("入库任务工作档已入库成功,完结AGV呼叫单,taskId:{},wrkNo:{},barcode:{}", agvTask.getId(), wrkMast.getWrkNo(), wrkMast.getBarcode()); } } } } if (completedCount > 0) { log.info("本次检查完结了{}个入库AGV呼叫单", completedCount); } } catch (Exception e) { log.error("检查入库成功任务并完结AGV呼叫单异常", e); } } /** * 检查AGV任务对应的工作档是否已完成或已转历史档并完结 * 处理被跳过的AGV任务:如果工作档已完成(wrk_sts=4,5,14,15)或已转历史档并完结,则完结AGV任务 */ @Scheduled(cron = "0/10 * * * * ? ") private void checkCompletedTasksInHistory() { if (!schedulerProperties.isEnabled()) { return; } try { // 查询状态为8(已呼叫AGV)的AGV任务 List agvTasks = taskService.selectList( new EntityWrapper() .eq("task_type", "agv") .eq("wrk_sts", 8L) // 已呼叫AGV状态 .isNotNull("wrk_no") ); if (agvTasks.isEmpty()) { return; } Date now = new Date(); int completedCount = 0; for (Task agvTask : agvTasks) { boolean isCompleted = false; String reason = ""; // 检查工作档是否存在 WrkMast wrkMast = null; if (agvTask.getWrkNo() != null) { wrkMast = wrkMastService.selectOne( new EntityWrapper().eq("wrk_no", agvTask.getWrkNo()) ); } // 如果工作档存在,检查是否已完成 if (wrkMast != null) { Long wrkSts = wrkMast.getWrkSts(); Integer ioType = agvTask.getIoType(); if (wrkSts != null && ioType != null) { // 入库任务:状态4(入库完成)或5(库存更新完成) if ((ioType == 1 || ioType == 10 || ioType == 53 || ioType == 57) && (wrkSts == 4L || wrkSts == 5L)) { isCompleted = true; reason = String.format("工作档已完成,状态:%d", wrkSts); } // 出库任务:状态14(已出库未确认)或15(出库更新完成) else if ((ioType == 101 || ioType == 110 || ioType == 103 || ioType == 107) && (wrkSts == 14L || wrkSts == 15L)) { isCompleted = true; reason = String.format("工作档已完成,状态:%d", wrkSts); } } } else { // 如果工作档不存在,检查历史档 WrkMastLog wrkMastLog = null; // 优先通过wrk_no查询历史档 if (agvTask.getWrkNo() != null) { wrkMastLog = wrkMastLogService.selectOne( new EntityWrapper().eq("wrk_no", agvTask.getWrkNo()) ); } // 如果通过wrk_no没找到,且有条码,则通过条码查询 if (wrkMastLog == null && !Cools.isEmpty(agvTask.getBarcode())) { List logList = wrkMastLogService.selectList( new EntityWrapper().eq("barcode", agvTask.getBarcode()) ); if (!logList.isEmpty()) { wrkMastLog = logList.get(0); // 取第一个 } } // 如果历史档存在且已完结,则完结AGV任务 if (wrkMastLog != null) { Integer ioType = agvTask.getIoType(); long logWrkSts = wrkMastLog.getWrkSts(); if (ioType != null) { // 入库任务:状态5(库存更新完成) if ((ioType == 1 || ioType == 10 || ioType == 53 || ioType == 57) && logWrkSts == 5L) { isCompleted = true; reason = String.format("工作档已转历史档并完结,历史档状态:%d", logWrkSts); } // 出库任务:状态15(出库更新完成) else if ((ioType == 101 || ioType == 110 || ioType == 103 || ioType == 107) && logWrkSts == 15L) { isCompleted = true; reason = String.format("工作档已转历史档并完结,历史档状态:%d", logWrkSts); } } } } // 如果已完成,更新AGV任务状态 if (isCompleted) { agvTask.setWrkSts(9L); agvTask.setModiTime(now); if (taskService.updateById(agvTask)) { completedCount++; log.info("{},完结AGV呼叫单,taskId:{},wrkNo:{},barcode:{},站点:{}", reason, agvTask.getId(), agvTask.getWrkNo(), agvTask.getBarcode(), agvTask.getStaNo()); } } } if (completedCount > 0) { log.info("本次检查完结了{}个AGV呼叫单(工作档已完成或已转历史档)", completedCount); } } catch (Exception e) { log.error("检查工作档已完成或历史档完结任务并完结AGV呼叫单异常", e); } } }