package com.zy.acs.manager.core.service; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.zy.acs.common.utils.RedisSupport; import com.zy.acs.framework.common.R; import com.zy.acs.manager.manager.entity.Agv; import com.zy.acs.manager.manager.entity.AgvDetail; import com.zy.acs.manager.manager.entity.Code; import com.zy.acs.manager.manager.entity.Task; import com.zy.acs.manager.manager.enums.StatusType; import com.zy.acs.manager.manager.enums.TaskStsType; import com.zy.acs.manager.manager.enums.TaskTypeType; import com.zy.acs.manager.manager.service.AgvDetailService; import com.zy.acs.manager.manager.service.AgvService; import com.zy.acs.manager.manager.service.CodeService; import com.zy.acs.manager.manager.service.TaskService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.concurrent.*; /** * Created by vincent on 11/9/2024 */ @Slf4j @Service public class PatrolService { private static final int SCHEDULE_TIME_INTERVAL = 5; private static final Map> AGV_PATROL_MAP = new ConcurrentHashMap<>(); private final RedisSupport redis = RedisSupport.defaultRedisSupport; private ScheduledExecutorService scheduler = null; @Autowired private AgvService agvService; @Autowired private AgvDetailService agvDetailService; @Autowired private TaskService taskService; @Autowired private MainService mainService; @Autowired private CodeService codeService; @Autowired private MapService mapService; private void executePatrolLogic(String agvNo) { this.patrolOfMove(agvNo); } private void patrolOfMove(String agvNo) { Agv agv = agvService.selectByUuid(agvNo); AgvDetail agvDetail = agvDetailService.selectByAgvId(agv.getId()); if (taskService.count(new LambdaQueryWrapper() .eq(Task::getAgvId, agv.getId()) .and(i -> { i.eq(Task::getTaskSts, TaskStsType.WAITING.val()) .or().eq(Task::getTaskSts, TaskStsType.ASSIGN.val()) .or().eq(Task::getTaskSts, TaskStsType.PROGRESS.val()); })) > 0) { return; } if (!agvService.judgeEnable(agv.getId())) { return; } Code randomCode = this.getRandomCode(agvDetail); if (null == randomCode) { return; } if (mainService.buildMinorTask(agv, agvDetail, TaskTypeType.MOVE, randomCode.getData())) { log.info(agv.getUuid() + "开始走行演示..."); } } public Code getRandomCode(AgvDetail agvDetail) { Code startCode = codeService.getById(agvDetail.getRecentCode()); List notInCodeList = new ArrayList<>(); notInCodeList.add("00000061"); List list = codeService.list(new LambdaQueryWrapper().notIn(Code::getData, notInCodeList)); Collections.shuffle(list); for (Code endCode : list) { List pathList = mapService.validFeasibility(startCode, endCode); if (pathList.size() >= 5) { return endCode; } } return list.stream().findFirst().orElse(null); } // --------------------------------------------------------------------------- public boolean isPatrolling(String agvNo) { ScheduledFuture scheduledFuture = AGV_PATROL_MAP.get(agvNo); if (scheduledFuture == null) { return false; } return !scheduledFuture.isCancelled() && !scheduledFuture.isDone(); } public R startupPatrol(String agvNo) { if (AGV_PATROL_MAP.containsKey(agvNo)) { return R.error("AGV " + agvNo + " 的跑库任务已经在运行中。"); } Runnable patrolTask = () -> { try { executePatrolLogic(agvNo); } catch (Exception e) { log.error("执行AGV " + agvNo + " 跑库任务时发生异常: " + e.getMessage()); e.printStackTrace(); } }; ScheduledFuture scheduledFuture = scheduler.scheduleAtFixedRate(patrolTask, 0, SCHEDULE_TIME_INTERVAL, TimeUnit.SECONDS); AGV_PATROL_MAP.put(agvNo, scheduledFuture); log.info("已启动AGV " + agvNo + " 的跑库任务。"); return R.ok(); } public R shutdownPatrol(String agvNo) { ScheduledFuture scheduledFuture = AGV_PATROL_MAP.get(agvNo); if (scheduledFuture == null) { return R.error("AGV " + agvNo + " 没有正在运行的跑库任务。"); } boolean cancelled = scheduledFuture.cancel(true); if (cancelled) { AGV_PATROL_MAP.remove(agvNo); log.info("已停止AGV " + agvNo + " 的跑库任务。"); return R.ok("已停止AGV " + agvNo + " 的跑库任务。"); } else { log.error("未能成功停止AGV " + agvNo + " 的跑库任务。"); return R.error("未能成功停止AGV " + agvNo + " 的跑库任务。"); } } @PostConstruct public void init() { int count = agvService.count(new LambdaQueryWrapper().eq(Agv::getStatus, StatusType.ENABLE.val)); if (count > 0) { this.scheduler = Executors.newScheduledThreadPool(count); } } @PreDestroy public void destroy() throws InterruptedException { for (Map.Entry> entry : AGV_PATROL_MAP.entrySet()) { entry.getValue().cancel(true); } scheduler.shutdown(); if (!scheduler.awaitTermination(5, TimeUnit.SECONDS)) { scheduler.shutdownNow(); } } }