package com.zy.acs.manager.core.service; import com.zy.acs.manager.core.domain.TaskPosDto; import com.zy.acs.manager.manager.entity.Code; import com.zy.acs.manager.manager.entity.Segment; import com.zy.acs.manager.manager.entity.Sta; import com.zy.acs.manager.manager.enums.StaTypeType; import com.zy.acs.manager.manager.service.*; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; import java.util.Objects; // man_segment: start_time, end_time, alter table man_segment // add roller_waiting int(1) default 0 null comment '滚筒线等待' after end_time; /** * alter table man_sta * add capacity int null comment '槽位数' after angle; * * alter table man_sta * add occ_cnt int null comment '占用数' after capacity; * * alter table man_sta * add rsv_in_cnt int null comment '预约放货量' after occ_cnt; * * alter table man_sta * add rsv_out_cnt int null comment '预约取货量' after rsv_in_cnt; */ @Slf4j @Service public class TransferStationHandler { private static final long LOAD_DELAY_MS = 15000L; // load ( inbound ) delay timeout private static final long PLACE_DELAY_MS = 15000L; // place ( outbound ) delay timeout @Autowired private SegmentService segmentService; @Autowired private AgvService agvService; @Autowired private AgvDetailService agvDetailService; @Autowired private CodeService codeService; @Autowired private StaService staService; /** * 取货(入库):在取完第一个货的时候,担心滚筒输送线会有下一个货物,所以建议AGV在原地等待一段时间 * 放货(出库):可能此时AGV上面其他背篓的料箱也是出库到这个滚筒输送线,所以等输送线把第一个料箱运走之后,再放第二个 * 要做 ready-for-next */ public boolean hasDelayAtSta(Segment currSeg) { if (currSeg == null) { throw new NullPointerException("segment is null in hasDelayAtSta."); } // 判断AGV是否在滚动输送线前 Code currentCode = agvDetailService.getCurrentCode(currSeg.getAgvId()); if (null == currentCode) { return false; } Sta rollerSta = staService.selectByCode(currentCode.getId(), StaTypeType.ROLLER); if (null == rollerSta) { return false; } // 如果为第一个segment(没有previous segment),则不需要等待 Segment preSeg = segmentService.getPreviousStepOfFinish(currSeg.getTravelId(), currSeg.getSerial()); if (preSeg == null || null == preSeg.getEndTime()) { return false; } TaskPosDto.PosType currPosType = TaskPosDto.PosType.of(currSeg.getPosType()); TaskPosDto.PosType prePosType = TaskPosDto.PosType.of(preSeg.getPosType()); if (prePosType == null || currPosType == null) { return false; } long preEndTime = preSeg.getEndTime().getTime(); long now = System.currentTimeMillis(); Long agvId = currSeg.getAgvId(); // inbound if (prePosType.equals(TaskPosDto.PosType.ORI_STA)) { // 背篓未满才等 Integer backpack = agvService.getBackpack(agvId); List usedBackpacks = segmentService.selectUsedBackpacks(currSeg.getTravelId(), agvId); if (usedBackpacks.size() >= backpack) { return false; } // sign waiting if (currSeg.getRollerWaiting() == 0) { currSeg.setRollerWaiting(1); segmentService.updateById(currSeg); } // timeout return (now - preEndTime) < LOAD_DELAY_MS; } // outbound if (prePosType == TaskPosDto.PosType.DEST_STA) { // 连续同口才等 if (currPosType != TaskPosDto.PosType.DEST_STA) { return false; } if (!Objects.equals(preSeg.getEndNode(), currSeg.getEndNode())) { return false; } // sign waiting if (currSeg.getRollerWaiting() == 0) { currSeg.setRollerWaiting(1); segmentService.updateById(currSeg); } // timeout return (now - preEndTime) < PLACE_DELAY_MS; } return false; } }