package com.zy.acs.manager.core.service;
|
|
import com.alibaba.fastjson.JSON;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.zy.acs.common.enums.AgvBackpackType;
|
import com.zy.acs.common.utils.GsonUtils;
|
import com.zy.acs.common.utils.Utils;
|
import com.zy.acs.framework.common.Cools;
|
import com.zy.acs.framework.common.SnowflakeIdWorker;
|
import com.zy.acs.framework.exception.CoolException;
|
import com.zy.acs.manager.common.domain.TaskDto;
|
import com.zy.acs.manager.common.domain.param.HandlerPublishParam;
|
import com.zy.acs.manager.common.exception.BusinessException;
|
import com.zy.acs.manager.core.domain.AgvBackpackDto;
|
import com.zy.acs.manager.core.domain.Lane;
|
import com.zy.acs.manager.core.domain.TaskPosDto;
|
import com.zy.acs.manager.core.service.astart.MapDataDispatcher;
|
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.manager.utils.ActionSorter;
|
import com.zy.acs.manager.system.service.ConfigService;
|
import lombok.extern.slf4j.Slf4j;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.stereotype.Service;
|
import org.springframework.transaction.annotation.Propagation;
|
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.interceptor.TransactionAspectSupport;
|
|
import java.util.*;
|
import java.util.stream.Collectors;
|
|
/**
|
* Created by vincent on 2023/6/14
|
*/
|
@Slf4j
|
@Service("mainService")
|
public class MainLxtService extends BaseMainService {
|
|
@Autowired
|
private BusService busService;
|
@Autowired
|
private TaskService taskService;
|
@Autowired
|
private ActionService actionService;
|
@Autowired
|
private StaService staService;
|
@Autowired
|
private LocService locService;
|
@Autowired
|
private AgvService agvService;
|
@Autowired
|
private AgvDetailService agvDetailService;
|
@Autowired
|
private ConfigService configService;
|
@Autowired
|
private ValidService validService;
|
@Autowired
|
private AllocateService allocateService;
|
@Autowired
|
private CodeService codeService;
|
@Autowired
|
private MapService mapService;
|
@Autowired
|
private SnowflakeIdWorker snowflakeIdWorker;
|
@Autowired
|
private CodeGapService codeGapService;
|
@Autowired
|
private AgvCmdService agvCmdService;
|
@Autowired
|
private FuncStaService funcStaService;
|
@Autowired
|
private MapDataDispatcher mapDataDispatcher;
|
@Autowired
|
private TravelService travelService;
|
@Autowired
|
private SegmentService segmentService;
|
// @Autowired
|
// private TrafficService trafficService;
|
@Autowired
|
private AgvModelService agvModelService;
|
@Autowired
|
private LaneService laneService;
|
@Autowired
|
private ActionSorter actionSorter;
|
|
@SuppressWarnings("all")
|
@Transactional
|
public Bus generateBusAndTask(OpenBusSubmitParam busSubmitParam, String memo) {
|
String errorMsg = busService.checkoutValid(busSubmitParam);
|
if (!Cools.isEmpty(errorMsg)) {
|
throw new BusinessException(errorMsg);
|
}
|
String batch = busSubmitParam.getBatch();
|
List<TaskDto> taskDtoList = busSubmitParam.getTaskList();
|
if (Cools.isEmpty(taskDtoList)) {
|
throw new BusinessException("taskList can't be empty!");
|
}
|
|
// 优先级排序
|
taskDtoList.sort((o1, o2) -> o2.getPriority() - o1.getPriority());
|
|
// 校验
|
List<Task> taskList = validService.validTaskDtoList(taskDtoList);
|
|
// 保存总线
|
Date now = new Date();
|
Bus bus = new Bus();
|
bus.setUuid(String.valueOf(snowflakeIdWorker.nextId()).substring(3));
|
bus.setBusNo(batch);
|
bus.setStartTime(now);
|
bus.setBusSts(BusStsType.RECEIVE.val());
|
bus.setMemo(memo);
|
|
if (!busService.save(bus)) {
|
throw new BusinessException("Internal Server Error!");
|
}
|
|
// 保存任务
|
for (Task task : taskList) {
|
task.setBusId(bus.getId());
|
task.setTaskSts(TaskStsType.INIT.val());
|
if (!taskService.save(task)) {
|
throw new BusinessException("seqNum:" + task.getSeqNum() + " failed to save!");
|
}
|
|
// 修改库位状态
|
Loc oriLoc = null;
|
Loc destLoc = null;
|
Sta oriSta = null;
|
Sta destSta = null;
|
switch (TaskTypeType.get(task.getTaskTypeEl())) {
|
case LOC_TO_LOC:
|
oriLoc = locService.getById(task.getOriLoc());
|
if (!oriLoc.getLocSts().equals(LocStsType.STOCK.val())) {
|
throw new BusinessException("oriLoc:" + task.getOriLoc$() + " is not in STOCK status");
|
}
|
oriLoc.setLocSts(LocStsType.PAKOUT.val());
|
oriLoc.setUpdateTime(now);
|
if (!locService.updateById(oriLoc)) {
|
throw new BusinessException("oriLoc:" + task.getOriLoc$() + " failed to update");
|
}
|
|
destLoc = locService.getById(task.getDestLoc());
|
if (!destLoc.getLocSts().equals(LocStsType.IDLE.val())) {
|
throw new BusinessException("destLoc:" + task.getDestLoc$() + " is not in IDLE status");
|
}
|
destLoc.setLocSts(LocStsType.PAKIN.val());
|
destLoc.setUpdateTime(now);
|
if (!locService.updateById(destLoc)) {
|
throw new BusinessException("destLoc:" + task.getDestLoc$() + " failed to update");
|
}
|
break;
|
case LOC_TO_STA:
|
oriLoc = locService.getById(task.getOriLoc());
|
if (!oriLoc.getLocSts().equals(LocStsType.STOCK.val())) {
|
throw new BusinessException("oriLoc:" + task.getOriLoc$() + " is not in STOCK status");
|
}
|
oriLoc.setLocSts(LocStsType.PAKOUT.val());
|
oriLoc.setUpdateTime(now);
|
if (!locService.updateById(oriLoc)) {
|
throw new BusinessException("oriLoc:" + task.getOriLoc$() + " failed to update");
|
}
|
|
destSta = staService.getById(task.getDestSta());
|
if (!destSta.getStaSts().equals(StaStsType.IDLE.val())) {
|
throw new BusinessException("destSta:" + task.getDestSta$() + " is not in IDLE status");
|
}
|
destSta.setStaSts(StaStsType.READY_RELEASE.val());
|
destSta.setUpdateTime(now);
|
if (!staService.updateById(destSta)) {
|
throw new BusinessException("destSta:" + task.getDestSta$() + " failed to update");
|
}
|
break;
|
case STA_TO_LOC:
|
oriSta = staService.getById(task.getOriSta());
|
if (!oriSta.getStaSts().equals(StaStsType.STOCK.val())) {
|
throw new BusinessException("oriSta:" + task.getOriSta$() + " is not in STOCK status");
|
}
|
oriSta.setStaSts(StaStsType.READY_TAKE.val());
|
oriSta.setUpdateTime(now);
|
if (!staService.updateById(oriSta)) {
|
throw new BusinessException("oriSta:" + task.getOriSta$() + " failed to update");
|
}
|
|
destLoc = locService.getById(task.getDestLoc());
|
if (!destLoc.getLocSts().equals(LocStsType.IDLE.val())) {
|
throw new BusinessException("destLoc:" + task.getDestLoc$() + " is not in IDLE status");
|
}
|
destLoc.setLocSts(LocStsType.PAKIN.val());
|
destLoc.setUpdateTime(now);
|
if (!locService.updateById(destLoc)) {
|
throw new BusinessException("destLoc:" + task.getDestLoc$() + " failed to update");
|
}
|
break;
|
case STA_TO_STA:
|
oriSta = staService.getById(task.getOriSta());
|
if (!oriSta.getStaSts().equals(StaStsType.STOCK.val())) {
|
throw new BusinessException("oriSta:" + task.getOriSta$() + " is not in STOCK status");
|
}
|
oriSta.setStaSts(StaStsType.READY_TAKE.val());
|
oriSta.setUpdateTime(now);
|
if (!staService.updateById(oriSta)) {
|
throw new BusinessException("oriSta:" + task.getOriSta$() + " failed to update");
|
}
|
|
destSta = staService.getById(task.getDestSta());
|
if (!destSta.getStaSts().equals(StaStsType.IDLE.val())) {
|
throw new BusinessException("destSta:" + task.getDestSta$() + " is not in IDLE status");
|
}
|
destSta.setStaSts(StaStsType.READY_RELEASE.val());
|
destSta.setUpdateTime(now);
|
if (!staService.updateById(destSta)) {
|
throw new BusinessException("destSta:" + task.getDestSta$() + " failed to update");
|
}
|
break;
|
default:
|
break;
|
}
|
|
}
|
return bus;
|
}
|
|
/**
|
* 任务分配给车辆 ( 车辆此时是空闲且静止的 )
|
*/
|
@Transactional
|
public synchronized void allocateTask(Bus bus) {
|
try {
|
Date now = new Date();
|
List<Task> taskList = taskService.list(new LambdaQueryWrapper<Task>()
|
.eq(Task::getBusId, bus.getId())
|
.eq(Task::getTaskSts, TaskStsType.INIT.val())
|
.orderByDesc(Task::getPriority)
|
);
|
|
if (Cools.isEmpty(taskList)) {
|
bus.setBusSts(BusStsType.PROGRESS.val());
|
bus.setUpdateTime(now);
|
if (!busService.updateById(bus)) {
|
log.error("Bus [{}] failed to Update !!!", bus.getUuid());
|
}
|
return;
|
}
|
|
List<Long> taskIds = taskList.stream().map(Task::getId).distinct().collect(Collectors.toList());
|
for (Task task : taskList) {
|
Agv agv = allocateService.execute(task);
|
if (null == agv) {
|
// log.warn("Task[{}] has an issue, because it failed to check out agv which is idle...", task.getSeqNum());
|
continue;
|
}
|
task.setAgvId(agv.getId());
|
task.setTaskSts(TaskStsType.WAITING.val());
|
task.setIoTime(now);
|
task.setUpdateTime(now);
|
if (!taskService.updateById(task)) {
|
throw new BusinessException("seqNum: " + task.getSeqNum() + " failed to update");
|
}
|
}
|
} catch (Exception e) {
|
log.error("mainService.infuseAgvForTask", e);
|
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
|
}
|
}
|
|
/**
|
* 解析取放货集合任务,进行最优的排列组合顺序 ( 车辆此时是空闲且静止的 )
|
* todo: {@link com.zy.acs.manager.core.HandlerController#controlAgv(String, HandlerPublishParam)}
|
*/
|
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
public void buildMajorTask(Long agvId, List<Task> taskList) {
|
if (Cools.isEmpty(agvId, taskList)) {
|
return;
|
}
|
try {
|
// valid -----------------------------------------------
|
Agv agv = agvService.getById(agvId);
|
if (!agvService.judgeEnable(agv.getId(), false)) {
|
return;
|
}
|
if (!Cools.isEmpty(taskService.selectInSts(agvId, TaskStsType.ASSIGN, TaskStsType.PROGRESS))) {
|
throw new CoolException("AGV[" + agv.getUuid() + "]分配任务失败,已存在执行任务...");
|
}
|
if (!Cools.isEmpty(segmentService.getByAgvAndState(agv.getId(), SegmentStateType.WAITING.toString()))
|
|| !Cools.isEmpty(segmentService.getByAgvAndState(agv.getId(), SegmentStateType.RUNNING.toString()))) {
|
throw new CoolException("AGV[" + agv.getUuid() + "] failed to assign,because already has the segment in running...");
|
}
|
|
// execute ----------------------------------------------------
|
Date now = new Date();
|
// sort and sub
|
taskList.sort(new Comparator<Task>() {
|
@Override
|
public int compare(Task o1, Task o2) {
|
return o2.getPriority() - o1.getPriority();
|
}
|
});
|
Integer backpack = agvService.getBackpack(agv);
|
if (taskList.size() > backpack) {
|
taskList = taskList.subList(0, backpack);
|
}
|
|
AgvDetail agvDetail = agvDetailService.selectByAgvId(agvId);
|
List<AgvBackpackDto> backpackDtoList = new ArrayList<>();
|
|
/**
|
* 同巷道归类
|
* same lane for every single agvId
|
*
|
* key: y(val) + TaskPosDto.PosType.ORI_LOC / ORI_STA / DEST_LOC / DEST_STA
|
* val: new TaskPosDto(taskId, new Double[]{code.getX(), code.getY()}, posType)
|
*/
|
Map<String, List<TaskPosDto>> groups = new HashMap<>();
|
final String sameGroupXy = configService.getVal("sameGroupXy", String.class);
|
|
int backpackLev = 0;
|
for (Task task : taskList) {
|
|
backpackLev++;
|
Code startCode = null;
|
Code endCode = null;
|
Loc oriLoc = null;
|
Loc destLoc = null;
|
Sta oriSta = null;
|
Sta destSta = null;
|
switch (Objects.requireNonNull(TaskTypeType.get(task.getTaskTypeEl()))) {
|
case LOC_TO_LOC:
|
oriLoc = locService.getById(task.getOriLoc());
|
destLoc = locService.getById(task.getDestLoc());
|
|
startCode = codeService.getCacheById(oriLoc.getCode());
|
endCode = codeService.getCacheById(destLoc.getCode());
|
|
TaskPosDto.packagePosGroup(groups, task, startCode, TaskPosDto.PosType.ORI_LOC, sameGroupXy);
|
TaskPosDto.packagePosGroup(groups, task, endCode, TaskPosDto.PosType.DEST_LOC, sameGroupXy);
|
break;
|
case LOC_TO_STA:
|
oriLoc = locService.getById(task.getOriLoc());
|
destSta = staService.getById(task.getDestSta());
|
|
startCode = codeService.getCacheById(oriLoc.getCode());
|
endCode = codeService.getCacheById(destSta.getCode());
|
|
TaskPosDto.packagePosGroup(groups, task, startCode, TaskPosDto.PosType.ORI_LOC, sameGroupXy);
|
TaskPosDto.packagePosGroup(groups, task, endCode, TaskPosDto.PosType.DEST_STA, sameGroupXy);
|
break;
|
case STA_TO_LOC:
|
oriSta = staService.getById(task.getOriSta());
|
destLoc = locService.getById(task.getDestLoc());
|
|
startCode = codeService.getCacheById(oriSta.getCode());
|
endCode = codeService.getCacheById(destLoc.getCode());
|
|
TaskPosDto.packagePosGroup(groups, task, startCode, TaskPosDto.PosType.ORI_STA, sameGroupXy);
|
TaskPosDto.packagePosGroup(groups, task, endCode, TaskPosDto.PosType.DEST_LOC, sameGroupXy);
|
break;
|
case STA_TO_STA:
|
oriSta = staService.getById(task.getOriSta());
|
destSta = staService.getById(task.getDestSta());
|
|
startCode = codeService.getCacheById(oriSta.getCode());
|
endCode = codeService.getCacheById(destSta.getCode());
|
|
TaskPosDto.packagePosGroup(groups, task, startCode, TaskPosDto.PosType.ORI_STA, sameGroupXy);
|
TaskPosDto.packagePosGroup(groups, task, endCode, TaskPosDto.PosType.DEST_STA, sameGroupXy);
|
break;
|
default:
|
throw new BusinessException(task.getSeqNum() + "任务类型错误");
|
|
}
|
|
if (backpackLev > backpack) {
|
throw new BusinessException("解析Task失败,AGV背篓已满......");
|
}
|
|
backpackDtoList.add(new AgvBackpackDto(backpackLev, task.getId()));
|
}
|
|
/**
|
* 1.Map<String, List<TaskPosDto>> groups
|
*
|
* key: 1000 + ORIGIN
|
* val: [TaskPosDto(taskId, new Double[]{code.getX(), code.getY()}, posType), TaskPosDto(taskId, new Double[]{code.getX(), code.getY()}, posType),...]
|
*
|
* key: 3000 + ORIGIN
|
* val: [TaskPosDto(taskId, new Double[]{code.getX(), code.getY()}, posType), TaskPosDto(taskId, new Double[]{code.getX(), code.getY()}, posType),...]
|
*
|
* key: 2000 + ORIGIN
|
* val: [TaskPosDto(taskId, new Double[]{code.getX(), code.getY()}, posType), TaskPosDto(taskId, new Double[]{code.getX(), code.getY()}, posType),...]
|
*
|
* key: 1000 + DESTINATION
|
* val: [TaskPosDto(taskId, new Double[]{code.getX(), code.getY()}, posType), TaskPosDto(taskId, new Double[]{code.getX(), code.getY()}, posType),...]
|
*
|
* key: 2000 + DESTINATION
|
* val: [TaskPosDto(taskId, new Double[]{code.getX(), code.getY()}, posType), TaskPosDto(taskId, new Double[]{code.getX(), code.getY()}, posType),...]
|
*
|
* ......
|
*
|
* 2.ArrayList<List<TaskPosDto>> list
|
* [
|
* [TaskPosDto(taskId, new Double[]{code.getX(), code.getY()}, posType), TaskPosDto(taskId, new Double[]{code.getX(), code.getY()}, posType),...],
|
* [TaskPosDto(taskId, new Double[]{code.getX(), code.getY()}, posType), TaskPosDto(taskId, new Double[]{code.getX(), code.getY()}, posType),...],
|
* [TaskPosDto(taskId, new Double[]{code.getX(), code.getY()}, posType), TaskPosDto(taskId, new Double[]{code.getX(), code.getY()}, posType),...],
|
* ......
|
* ]
|
*/
|
|
/**
|
* 对所有巷道进行有序排序,先是针对List为一个单位,对他们进行FirstWeight排序,相当于表1的key的数值进行有序排序
|
* List<TaskPosDto>: task list on the same lane
|
* ArrayList<List<TaskPosDto>>: all the task list by one agv
|
*
|
* tip: ORI 和 DEST 永远不会存在同一个 List
|
*/
|
ArrayList<List<TaskPosDto>> list = new ArrayList<>(groups.values());
|
list.sort((o1, o2) -> {
|
double o1CompVal = (o1.get(0).getFirstWeight(sameGroupXy) * 100) + o1.get(0).getPosType().compOffset;
|
double o2CompVal = (o2.get(0).getFirstWeight(sameGroupXy) * 100) + o2.get(0).getPosType().compOffset;
|
return (int) (o1CompVal - o2CompVal);
|
});
|
// 针对Dto,按照SecondWeight进行排序
|
for (List<TaskPosDto> taskPosDtoList : list) {
|
taskPosDtoList.sort((o1, o2) -> (int) (o1.getSecondWeight(sameGroupXy) * 100 - o2.getSecondWeight(sameGroupXy) * 100));
|
}
|
|
// re-order by agv current position
|
Code currCode = codeService.getCacheById(agvDetail.getRecentCode());
|
Double[] currPosition = new Double[]{currCode.getX(), currCode.getY()};
|
|
List<List<TaskPosDto>> pickGroups = new ArrayList<>();
|
List<List<TaskPosDto>> dropGroups = new ArrayList<>();
|
|
for (List<TaskPosDto> group : list) {
|
// Assume 一个任务组中所有TaskPosDto的PosType.brief相同
|
TaskPosDto.PosType posType = group.get(0).getPosType();
|
if (posType == TaskPosDto.PosType.ORI_LOC || posType == TaskPosDto.PosType.ORI_STA) {
|
pickGroups.add(group);
|
} else if (posType == TaskPosDto.PosType.DEST_LOC || posType == TaskPosDto.PosType.DEST_STA) {
|
dropGroups.add(group);
|
} else {
|
// import tip: the list must only contain ORIGIN and DESTINATION
|
log.error("the list must only contain ORIGIN and DESTINATION");
|
}
|
}
|
|
currPosition = allocateService.pac(currPosition, pickGroups);
|
currPosition = allocateService.pac(currPosition, dropGroups);
|
|
List<List<TaskPosDto>> reorderedList = new ArrayList<>();
|
reorderedList.addAll(pickGroups);
|
reorderedList.addAll(dropGroups);
|
|
list.clear();
|
list.addAll(reorderedList);
|
|
|
// generate travel
|
Travel travel = new Travel();
|
travel.setUuid(String.valueOf(snowflakeIdWorker.nextId()).substring(3));
|
travel.setTravelId(String.valueOf(snowflakeIdWorker.nextId()).substring(3));
|
travel.setAgvId(agvId);
|
travel.setTaskContent(JSON.toJSONString(list));
|
travel.setTaskIds(JSON.toJSONString(taskList.stream().map(Task::getId).collect(Collectors.toList())));
|
travel.setState(TravelStateType.RUNNING.toString());
|
if (!travelService.save(travel)) {
|
throw new BusinessException("任务组保存失败");
|
}
|
|
// generate segment
|
int segSerial = 0;
|
List<Segment> segmentList = new ArrayList<>();
|
for (List<TaskPosDto> dtoList : list) {
|
for (TaskPosDto taskPosDto : dtoList) {
|
segSerial++;
|
AgvBackpackType backpackType = AgvBackpackDto.find(backpackDtoList, taskPosDto.getTaskId());
|
assert null != backpackType;
|
|
Segment segment = new Segment();
|
segment.setUuid(String.valueOf(snowflakeIdWorker.nextId()).substring(3));
|
segment.setTravelId(travel.getId());
|
segment.setAgvId(agvId);
|
segment.setTaskId(taskPosDto.getTaskId());
|
segment.setSerial(segSerial);
|
segment.setEndNode(taskPosDto.getCodeId());
|
segment.setPosType(taskPosDto.getPosType().toString());
|
segment.setBackpack(backpackType.lev);
|
segment.setState(SegmentStateType.INIT.toString());
|
segmentList.add(segment);
|
}
|
}
|
for (int i = 0; i < segmentList.size(); i++) {
|
Segment segment = segmentList.get(i);
|
if (i == 0) {
|
segment.setState(SegmentStateType.WAITING.toString());
|
}
|
if (!segmentService.save(segment)) {
|
throw new BusinessException("任务组保存失败");
|
}
|
}
|
|
// task
|
for (Task task : taskList) {
|
task.setTaskSts(TaskStsType.ASSIGN.val());
|
task.setStartTime(now);
|
task.setUpdateTime(now);
|
if (!taskService.updateById(task)) {
|
throw new BusinessException(task.getUuid() + "任务更新失败");
|
}
|
}
|
|
} catch (Exception e) {
|
|
log.error("mainService.buildMajorTask[task]", e);
|
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
|
}
|
}
|
|
|
/**
|
* 充电 回待机位任务
|
*/
|
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
// although there is a Transactional here that the lock is isolated, but we can't join the caller's Transactional
|
public boolean buildMinorTask(Long agvId, TaskTypeType taskType, String destination, Jam jam) {
|
if (Cools.isEmpty(agvId, taskType)) {
|
return false;
|
}
|
try {
|
String agvNo = agvService.getAgvNo(agvId);
|
if (!agvService.judgeEnable(agvId)) {
|
return false;
|
}
|
if (!Cools.isEmpty(taskService.selectInSts(agvId, TaskStsType.ASSIGN, TaskStsType.PROGRESS))) {
|
throw new CoolException("AGV[" + agvNo + "] failed to assign,because already has the task in running...");
|
}
|
if (!Cools.isEmpty(segmentService.getByAgvAndState(agvId, SegmentStateType.WAITING.toString()))
|
|| !Cools.isEmpty(segmentService.getByAgvAndState(agvId, SegmentStateType.RUNNING.toString()))) {
|
throw new CoolException("AGV[" + agvNo + "] failed to assign,because already has the segment in running...");
|
}
|
|
Date now = new Date();
|
AgvDetail agvDetail = agvDetailService.selectMajorByAgvId(agvId);
|
Code endCode = null;
|
switch (taskType) {
|
case TO_CHARGE:
|
case TO_STANDBY:
|
List<FuncSta> idleFunStaList = funcStaService.findInIdleStatus(FuncStaType.query(taskType), agvId);
|
if (!Cools.isEmpty(idleFunStaList)) {
|
FuncSta funcSta = funcStaService.checkoutClosestFunSta(agvDetail.getRecentCode(), idleFunStaList);
|
endCode = codeService.getCacheById(funcSta.getCode());
|
}
|
if (null == endCode) {
|
log.warn("AGV[{}] failed to search destination,there hadn't any idle funSta,TaskTypeType:{}", agvNo, taskType.toString());
|
}
|
break;
|
case MOVE:
|
endCode = codeService.getCacheByData(destination);
|
break;
|
default:
|
return false;
|
}
|
|
if (null == endCode) {
|
return false;
|
}
|
if (!allocateService.validCapacityOfLane(agvNo, endCode)) {
|
throw new BusinessException("the lane with code:" + endCode.getData() + " is full of AGV[" + agvNo + "]!!!");
|
}
|
|
Task task = new Task();
|
task.setAgvId(agvId);
|
task.setUuid(String.valueOf(snowflakeIdWorker.nextId()).substring(3));
|
List<Task> lastTasks = taskService.list(new LambdaQueryWrapper<Task>().orderByDesc(Task::getId));
|
task.setSeqNum(Utils.generateSeqNum(Cools.isEmpty(lastTasks) ? null : lastTasks.get(0).getSeqNum()));
|
task.setOriCode(agvDetail.getCode());
|
task.setDestCode(endCode.getId());
|
// lane
|
Lane destLane = laneService.search(endCode.getData());
|
if (null != destLane) {
|
task.setDestLaneHash(destLane.getHashCode());
|
}
|
task.setPriority(taskType.equals(TaskTypeType.TO_CHARGE) ? 2 : 1);
|
task.setTaskSts(TaskStsType.ASSIGN.val());
|
task.setTaskType(taskType.val());
|
task.setIoTime(now);
|
task.setStartTime(now);
|
if (!taskService.save(task)) {
|
throw new BusinessException(task.getSeqNum() + " failed to save");
|
}
|
|
// generate travel
|
Travel travel = new Travel();
|
travel.setUuid(String.valueOf(snowflakeIdWorker.nextId()).substring(3));
|
travel.setTravelId(String.valueOf(snowflakeIdWorker.nextId()).substring(3));
|
travel.setAgvId(agvId);
|
// travel.setTaskContent(JSON.toJSONString(list));
|
travel.setTaskIds(GsonUtils.toJson(Utils.singletonList(task.getId())));
|
travel.setState(TravelStateType.RUNNING.toString());
|
if (!travelService.save(travel)) {
|
throw new BusinessException("travel failed to save");
|
}
|
|
// generate segment
|
int segSerial = 0;
|
segSerial++;
|
List<Segment> segmentList = new ArrayList<>();
|
|
String posType = "";
|
switch (taskType) {
|
case TO_CHARGE:
|
posType = TaskPosDto.PosType.TO_CHARGE.toString();
|
break;
|
case TO_STANDBY:
|
posType = TaskPosDto.PosType.TO_STANDBY.toString();
|
break;
|
case MOVE:
|
posType = TaskPosDto.PosType.MOVE.toString();
|
break;
|
default:
|
break;
|
}
|
|
Segment segment = new Segment();
|
segment.setUuid(String.valueOf(snowflakeIdWorker.nextId()).substring(3));
|
segment.setTravelId(travel.getId());
|
segment.setAgvId(agvId);
|
segment.setTaskId(task.getId());
|
segment.setSerial(segSerial);
|
segment.setEndNode(endCode.getId());
|
segment.setPosType(posType);
|
segment.setState(SegmentStateType.INIT.toString());
|
segmentList.add(segment);
|
|
for (int i = 0; i < segmentList.size(); i++) {
|
Segment next = segmentList.get(i);
|
if (i == 0) {
|
next.setState(SegmentStateType.WAITING.toString());
|
}
|
if (!segmentService.save(next)) {
|
throw new BusinessException("segment failed to save");
|
} else {
|
if (null != jam && i == 0) {
|
jam.setAvoSeg(next.getId());
|
jam.setAvoCode(endCode.getId());
|
}
|
}
|
}
|
|
switch (taskType) {
|
case TO_CHARGE:
|
case TO_STANDBY:
|
// funcSta
|
FuncSta destFuncSta = funcStaService.getByCodeAndType(task.getDestCode(), FuncStaType.query(taskType).toString());
|
destFuncSta.setState(FuncStaStateType.OCCUPIED.toString());
|
destFuncSta.setUpdateTime(now);
|
if (!funcStaService.updateById(destFuncSta)) {
|
log.error("FuncSta [{}] failed to update !!!", destFuncSta.getName());
|
}
|
break;
|
case MOVE:
|
break;
|
default:
|
break;
|
}
|
|
return true;
|
} catch (Exception e) {
|
log.error("mainService.buildMinorTask[task]", e);
|
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
|
|
return false;
|
}
|
}
|
|
|
}
|