package com.zy.acs.manager.core.scheduler; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.zy.acs.framework.common.Cools; import com.zy.acs.framework.common.SnowflakeIdWorker; import com.zy.acs.manager.common.domain.TaskDto; import com.zy.acs.manager.core.domain.AgvTaskDto; import com.zy.acs.manager.core.service.MainLockWrapService; import com.zy.acs.manager.core.service.MainService; import com.zy.acs.manager.core.service.TrafficService; import com.zy.acs.manager.manager.controller.param.OpenBusSubmitParam; import com.zy.acs.manager.manager.entity.*; import com.zy.acs.manager.manager.enums.*; import com.zy.acs.manager.manager.service.*; import com.zy.acs.manager.system.service.ConfigService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.List; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.ReentrantLock; /** * to judgement agv idle status when generate action !!! * Created by vincent on 2023/6/18 */ @Slf4j @Component public class KernelScheduler { public static int CORE_SCAN_FREQUENCY_MILLISECOND = 15; private static final int LOCK_TIMEOUT = 5; private final ReentrantLock lock = new ReentrantLock(Boolean.TRUE); private Thread trafficCalcThread; private Thread actionPublicThread; @Autowired private AgvService agvService; @Autowired private BusService busService; @Autowired private TaskService taskService; @Autowired private MainService mainService; @Autowired private MainLockWrapService mainLockWrapService; @Autowired private ActionService actionService; @Autowired private SegmentService segmentService; @Autowired private TrafficService trafficService; @Autowired private ConfigService configService; @Autowired private LocService locService; @Autowired private AgvModelService agvModelService; @Autowired private SnowflakeIdWorker snowflakeIdWorker; @Scheduled(cron = "0/1 * * * * ? ") private void startupBus() throws InterruptedException { if (!configService.getVal("TaskAssignMode", Boolean.class)) { return; } if (!this.lock.tryLock(LOCK_TIMEOUT, TimeUnit.SECONDS)) { return; } List busList = busService.selectBySts(BusStsType.RECEIVE); for (Bus bus : busList) { mainService.allocateTask(bus); } this.lock.unlock(); } @Scheduled(cron = "0/1 * * * * ? ") private void calculateSeg() throws InterruptedException { if (!this.lock.tryLock(LOCK_TIMEOUT, TimeUnit.SECONDS)) { return; } List taskList = taskService.selectBySts(TaskStsType.WAITING); List taskDtoList = new ArrayList<>(); for (Task task : taskList) { AgvTaskDto taskDto = new AgvTaskDto(task.getAgvId(), task); if (AgvTaskDto.has(taskDtoList, taskDto)) { AgvTaskDto dto = AgvTaskDto.find(taskDtoList, taskDto); assert dto != null; dto.getTaskList().add(task); } else { taskDtoList.add(taskDto); } } for (AgvTaskDto dto : taskDtoList) { mainLockWrapService.buildMajorTask(dto.getAgvId(), dto.getTaskList()); } this.lock.unlock(); } @PostConstruct public void init() { try { Thread.sleep(1200); } catch (InterruptedException ignore) {} // traffic calculate this.trafficCalcThread = new Thread(() -> { while (!Thread.currentThread().isInterrupted()) { try { Thread.sleep(CORE_SCAN_FREQUENCY_MILLISECOND); List segments = segmentService.list(new LambdaQueryWrapper() .eq(Segment::getState, SegmentStateType.WAITING.toString()) ); for (Segment segment : segments) { long startTime = System.currentTimeMillis(); trafficService.trigger(segment); log.info("traffic calculation spend {} ms", System.currentTimeMillis() - startTime); } } catch (Exception e) { log.error("KernelScheduler.trafficCalcThread fail", e); } } }); this.trafficCalcThread.start(); // public action this.actionPublicThread = new Thread(() -> { while (!Thread.currentThread().isInterrupted()) { try { Thread.sleep(CORE_SCAN_FREQUENCY_MILLISECOND); List actionGroupIds = actionService.selectGroupNo(ActionStsType.PREPARE); for (String actionGroupId : actionGroupIds) { mainService.publishAction(actionGroupId); } } catch (Exception e) { log.error("KernelScheduler.actionPublicThread fail", e); } } }); this.actionPublicThread.start(); } // @Scheduled(fixedRate = 500) // 500毫秒执行一次,不同步 // @Scheduled(fixedDelay = 500) // 500毫秒执行一次,同步 // @Scheduled(cron = "0/1 * * * * ? ") // private void traffic() { // List segments = segmentService.list(new LambdaQueryWrapper() // .eq(Segment::getState, SegmentStateType.WAITING.toString()) // ); // for (Segment segment : segments) { // long startTime = System.currentTimeMillis(); // trafficService.trigger(segment); // log.info("traffic calculation spend {} ms", System.currentTimeMillis() - startTime); // } // } // // @Scheduled(cron = "0/1 * * * * ? ") // private void publishAction(){ // List actionGroupIds = actionService.selectPrepareGroup(); // for (String actionGroupId : actionGroupIds) { // long startTime = System.currentTimeMillis(); // mainService.publishAction(actionGroupId); // log.info("publish action calculation spend {} ms", System.currentTimeMillis() - startTime); // } // } // patch ---------------------------------------------------------------------------------------------- @Scheduled(cron = "0/3 * * * * ? ") private void busFinishPatch(){ List busList = busService.selectBySts(BusStsType.PROGRESS); for (Bus bus : busList) { boolean finish = true; List taskList = taskService.list(new LambdaQueryWrapper().eq(Task::getBusId, bus.getId())); for (Task task : taskList) { if (!task.getTaskSts().equals(TaskStsType.COMPLETE.val())) { finish = false; break; } } if (finish) { bus.setBusSts(BusStsType.FINISH.val()); bus.setEndTime(new Date()); bus.setUpdateTime(new Date()); if (!busService.updateById(bus)) { log.error("Bus [{}] 更新失败 !!!", bus.getUuid()); } } long cancelNum = taskList.stream().filter(task -> TaskStsType.CANCEL.val() == task.getTaskSts()).count(); if (cancelNum == taskList.size()) { bus.setBusSts(BusStsType.CANCEL.val()); bus.setUpdateTime(new Date()); if (!busService.updateById(bus)) { log.error("Bus [{}] 更新失败 !!!", bus.getUuid()); } } } } @PreDestroy public void shutDown(){ if (this.trafficCalcThread != null) { this.trafficCalcThread .interrupt(); } if (this.actionPublicThread != null) { this.actionPublicThread .interrupt(); } } // auto loc to loc ---------------------------------------------------------------------------------------------- @Scheduled(cron = "0/1 * * * * ? ") private void autoLocToLoc() { if (!configService.getVal("TaskAssignMode", Boolean.class)) { return; } // 最多两组bus运行 // if (1 < busService.count(new LambdaQueryWrapper().in(Bus::getBusSts, BusStsType.RECEIVE.val(), BusStsType.PROGRESS.val()))) { // return; // } int agvCount = agvService.count(new LambdaQueryWrapper().eq(Agv::getStatus, StatusType.ENABLE.val)); AgvModel agvModel = agvModelService.getOne(new LambdaQueryWrapper().eq(AgvModel::getType, AgvModelType.CTU_BOX_TRANSPORT_AGV.toString())); if (null == agvModel || 0 == agvCount) { return; } // int maxCapacity = agvModel.getBackpack() * agvCount; int maxCapacity = agvModel.getBackpack(); // STOCK List stockList = locService.list(new LambdaQueryWrapper().eq(Loc::getLocSts, LocStsType.STOCK.val())); if (Cools.isEmpty(stockList) || stockList.size() < agvModel.getBackpack()) { return; } Collections.shuffle(stockList); if (stockList.size() > maxCapacity) { stockList = stockList.subList(0, maxCapacity); } int numOfStockLocList = stockList.size(); // IDLE List idleList = locService.list(new LambdaQueryWrapper().eq(Loc::getLocSts, LocStsType.IDLE.val())); if (Cools.isEmpty(idleList)) { return; } Collections.shuffle(idleList); if (idleList.size() > numOfStockLocList) { idleList = idleList.subList(0, numOfStockLocList); } OpenBusSubmitParam param = new OpenBusSubmitParam(); param.setBatch(String.valueOf(snowflakeIdWorker.nextId()).substring(13, 19)); for (int i = 0; i < numOfStockLocList; i++) { Loc stockLoc = stockList.get(i); Loc idleLoc = idleList.get(i); TaskDto taskDto = new TaskDto(); taskDto.setOriLoc(stockLoc.getLocNo()); taskDto.setDestLoc(idleLoc.getLocNo()); taskDto.setSeqNum(String.valueOf(snowflakeIdWorker.nextId()).substring(15, 19)); param.getTaskList().add(taskDto); } mainService.generateBusAndTask(param, "autoLocToLoc"); } }