| | |
| | | alter table man_code |
| | | add dir_rule varchar(255) null comment '方向规则' after corner; |
| | | alter table man_travel |
| | | add roller_waiting int(1) default 0 null comment '滚筒线等待' after task_ids; |
| | | |
| | | alter table man_travel |
| | | add roller_waiting_code bigint null comment '滚筒线等待地码' after roller_waiting; |
| | | |
| | | alter table man_travel_log |
| | | add roller_waiting int(1) default 0 null comment '滚筒线等待' after task_ids; |
| | | |
| | | alter table man_travel_log |
| | | add roller_waiting_code bigint null comment '滚筒线等待地码' after roller_waiting; |
| | | |
| | | CREATE INDEX idx_agv_state_wait |
| | | ON man_travel (agv_id, state, roller_waiting, deleted); |
| | |
| | | # todo idx ==> deleted |
| | | # man_action |
| | | CREATE INDEX idx_agv_action ON man_action(agv_id, action_sts); |
| | | CREATE INDEX idx_group_io_time ON man_action(group_id, io_time); |
| | |
| | | # man_action_type |
| | | CREATE INDEX idx_action_type_uuid ON man_action_type(uuid); |
| | | # man_travel |
| | | CREATE INDEX idx_agv_id_state on man_travel(agv_id, state); |
| | | CREATE INDEX idx_agv_id_state ON man_travel(agv_id, state); |
| | | CREATE INDEX idx_agv_state_wait ON man_travel (agv_id, state, roller_waiting, deleted); |
| | | # man_agv_model |
| | | CREATE INDEX idx_agv_model_type ON man_agv_model(type); |
| | | # man_bus_sts |
| New file |
| | |
| | | package com.zy.acs.common.utils; |
| | | |
| | | public class Base62 { |
| | | |
| | | private static final char[] CHARS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray(); |
| | | |
| | | public static String encode(long value) { |
| | | if (value == 0) return "0"; |
| | | StringBuilder sb = new StringBuilder(); |
| | | while (value > 0) { |
| | | sb.append(CHARS[(int) (value % 62)]); |
| | | value /= 62; |
| | | } |
| | | return sb.reverse().toString(); |
| | | } |
| | | |
| | | } |
| | |
| | | package com.zy.acs.common.utils; |
| | | |
| | | import com.zy.acs.framework.common.Cools; |
| | | import com.zy.acs.framework.common.SnowflakeIdWorker; |
| | | |
| | | import java.util.*; |
| | | import java.util.concurrent.ThreadLocalRandom; |
| | |
| | | return str; |
| | | } |
| | | |
| | | public static void main(String[] args) { |
| | | System.out.println(Base62.encode(new SnowflakeIdWorker().nextId())); |
| | | } |
| | | |
| | | public static String generateSeqNum(String lastSeqNum) { |
| | | if (Cools.isEmpty(lastSeqNum)) { |
| | | return zeroFill("1", 4); |
| | |
| | | import com.alibaba.fastjson.JSON; |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.zy.acs.common.constant.RedisConstant; |
| | | import com.zy.acs.common.utils.Base62; |
| | | import com.zy.acs.common.utils.RedisSupport; |
| | | import com.zy.acs.common.utils.Utils; |
| | | import com.zy.acs.framework.common.Cools; |
| | | import com.zy.acs.framework.common.R; |
| | | import com.zy.acs.framework.common.SnowflakeIdWorker; |
| | |
| | | task.setAgvId(agv.getId()); |
| | | 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())); // todo |
| | | // task.setSeqNum(Utils.generateSeqNum(Cools.isEmpty(lastTasks)?null:lastTasks.get(0).getSeqNum())); |
| | | task.setSeqNum(Base62.encode(snowflakeIdWorker.nextId())); |
| | | |
| | | task.setTaskType(param.getTaskMode().val()); |
| | | task.setTaskSts(TaskStsType.WAITING.val()); |
| | |
| | | @Autowired |
| | | private LocService locService; |
| | | @Autowired |
| | | private AgvModelService agvModelService; |
| | | private TravelService travelService; |
| | | @Autowired |
| | | private TransferStationHandler transferStationHandler; |
| | | |
| | |
| | | for (Segment segment : segments) { |
| | | if (transferStationHandler.hasDelayAtSta(segment)) { |
| | | continue; |
| | | } else { |
| | | travelService.clearRollerWaiting(segment.getTravelId()); |
| | | } |
| | | try { |
| | | txTemplate.executeWithoutResult(status -> { |
| | |
| | | // if (taskCnt == 0) { |
| | | // continue; |
| | | // } |
| | | // in TransferStationHandler.hasDelayAtSta todo |
| | | Travel runningTravel = travelService.findRunningTravel(agvId); |
| | | if (null == runningTravel) { |
| | | // in TransferStationHandler.hasDelayAtSta |
| | | Travel currTravelInRollerWaiting = travelService.findRollerWaitingTravel(agvId, currentCode.getId()); |
| | | if (null == currTravelInRollerWaiting) { |
| | | continue; |
| | | } |
| | | segmentService.hasRollerWaitingNow(runningTravel.getId(), agvId, sta.getCode(), TaskPosDto.PosType.ORI_STA) |
| | | Segment currSeg = segmentService.getRollerWaiting(agvId, sta.getCode(), TaskPosDto.PosType.ORI_STA); |
| | | if (null == currSeg) { |
| | | continue; |
| | | } |
| | | // Segment currSeg = segmentService.getRollerWaiting(agvId, sta.getCode(), TaskPosDto.PosType.ORI_STA); |
| | | // if (null == currSeg) { |
| | | // continue; |
| | | // } |
| | | |
| | | // has enough backpack space to load |
| | | Integer backpack = agvService.getBackpack(agvId); |
| | | List<Integer> usedBackpacks = segmentService.selectUsedBackpacks(null, agvId); |
| | | List<Integer> usedBackpacks = segmentService.selectUsedBackpacks(currTravelInRollerWaiting.getId(), agvId); |
| | | if (usedBackpacks.size() >= backpack) { |
| | | continue; |
| | | } |
| | |
| | | import com.zy.acs.common.domain.protocol.*; |
| | | import com.zy.acs.common.domain.protocol.action.*; |
| | | import com.zy.acs.common.enums.*; |
| | | import com.zy.acs.common.utils.Base62; |
| | | import com.zy.acs.common.utils.GsonUtils; |
| | | import com.zy.acs.common.utils.RedisSupport; |
| | | import com.zy.acs.common.utils.Utils; |
| | |
| | | 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.setSeqNum(Utils.generateSeqNum(Cools.isEmpty(lastTasks)?null:lastTasks.get(0).getSeqNum())); |
| | | task.setSeqNum(Base62.encode(snowflakeIdWorker.nextId())); |
| | | task.setOriCode(agvDetail.getCode()); |
| | | task.setDestCode(endCode.getId()); |
| | | // lane |
| | |
| | | staReserveService.rollbackWaitingToReserved(sta, currTask, StaReserveType.OUT); |
| | | break; |
| | | } |
| | | log.info("Agv [{}] 取放货成功", protocol.getAgvNo()); // todo |
| | | log.info("AGV[{}] load permitted at conveyor station [{}]", protocol.getAgvNo(), sta.getStaNo()); |
| | | success = true; |
| | | break; |
| | | case DEST_STA: |
| | |
| | | staReserveService.rollbackWaitingToReserved(sta, currTask, StaReserveType.IN); |
| | | break; |
| | | } |
| | | log.info("Agv [{}] 取放货成功", protocol.getAgvNo()); // todo |
| | | log.info("AGV[{}] unload permitted at conveyor station [{}]", protocol.getAgvNo(), sta.getStaNo()); |
| | | success = true; |
| | | break; |
| | | default: |
| | |
| | | continue; |
| | | } |
| | | // 当前vehicle正在进行滚筒输送线等待 |
| | | if (segmentService.isRollerWaiting(agvId)) { |
| | | if (travelService.hasRollerWaiting(agvId)) { |
| | | continue; |
| | | } |
| | | // if (segmentService.isRollerWaiting(agvId)) { |
| | | // continue; |
| | | // } |
| | | return blockVehicleDto.getVehicle(); |
| | | } |
| | | return null; |
| | |
| | | private CodeService codeService; |
| | | @Autowired |
| | | private StaService staService; |
| | | @Autowired |
| | | private TravelService travelService; |
| | | |
| | | /** |
| | | * 取货(入库):在取完第一个货的时候,担心滚筒输送线会有下一个货物,所以建议AGV在原地等待一段时间 |
| | |
| | | return false; |
| | | } |
| | | |
| | | // sign waiting |
| | | if (currSeg.getRollerWaiting() == 0) { |
| | | currSeg.setRollerWaiting(1); |
| | | segmentService.updateById(currSeg); |
| | | } |
| | | // mark roller waiting |
| | | travelService.markRollerWaiting(currSeg.getTravelId(), currentCode.getId()); |
| | | // if (currSeg.getRollerWaiting() == 0) { |
| | | // currSeg.setRollerWaiting(1); |
| | | // segmentService.updateById(currSeg); |
| | | // } |
| | | |
| | | // timeout |
| | | return (now - preEndTime) < LOAD_DELAY_MS; |
| | |
| | | return false; |
| | | } |
| | | |
| | | // sign waiting |
| | | if (currSeg.getRollerWaiting() == 0) { |
| | | currSeg.setRollerWaiting(1); |
| | | segmentService.updateById(currSeg); |
| | | } |
| | | // mark roller waiting |
| | | travelService.markRollerWaiting(currSeg.getTravelId(), currentCode.getId()); |
| | | // if (currSeg.getRollerWaiting() == 0) { |
| | | // currSeg.setRollerWaiting(1); |
| | | // segmentService.updateById(currSeg); |
| | | // } |
| | | |
| | | // timeout |
| | | return (now - preEndTime) < PLACE_DELAY_MS; |
| | |
| | | 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 com.zy.acs.manager.manager.service.TravelService; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | |
| | |
| | | private String memo; |
| | | |
| | | public Segment() {} |
| | | |
| | | public String getTravelId$(){ |
| | | TravelService service = SpringUtils.getBean(TravelService.class); |
| | | Travel travel = service.getById(this.travelId); |
| | | if (!Cools.isEmpty(travel)){ |
| | | return String.valueOf(travel.getUuid()); |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | public String getTaskId$(){ |
| | | TaskService service = SpringUtils.getBean(TaskService.class); |
| | |
| | | import com.baomidou.mybatisplus.annotation.IdType; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import com.zy.acs.framework.common.Cools; |
| | | import com.zy.acs.framework.common.SpringUtils; |
| | | import com.zy.acs.manager.manager.service.AgvService; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | |
| | |
| | | private String taskIds; |
| | | |
| | | /** |
| | | * 滚筒线等待 1: 是 0: 否 |
| | | */ |
| | | @ApiModelProperty(value= "滚筒线等待 1: 是 0: 否 ") |
| | | private Integer rollerWaiting; |
| | | |
| | | /** |
| | | * 滚筒线等待地码 |
| | | */ |
| | | @ApiModelProperty(value= "滚筒线等待地码") |
| | | private Long rollerWaitingCode; |
| | | |
| | | /** |
| | | * 进度 |
| | | */ |
| | | @ApiModelProperty(value= "进度") |
| | |
| | | @ApiModelProperty(value= "备注") |
| | | private String memo; |
| | | |
| | | public Travel() {} |
| | | |
| | | public Travel(String uuid,String travelId,Long agvId,Long currSeg,String taskContent,String taskIds,String state,Integer status,Integer deleted,Long tenantId,Long createBy,Date createTime,Long updateBy,Date updateTime,String memo) { |
| | | this.uuid = uuid; |
| | | this.travelId = travelId; |
| | | this.agvId = agvId; |
| | | this.currSeg = currSeg; |
| | | this.taskContent = taskContent; |
| | | this.taskIds = taskIds; |
| | | this.state = state; |
| | | this.status = status; |
| | | this.deleted = deleted; |
| | | this.tenantId = tenantId; |
| | | this.createBy = createBy; |
| | | this.createTime = createTime; |
| | | this.updateBy = updateBy; |
| | | this.updateTime = updateTime; |
| | | this.memo = memo; |
| | | } |
| | | |
| | | // Travel travel = new Travel( |
| | | // null, // 编号 |
| | | // null, // 组编号 |
| | | // null, // AGV |
| | | // null, // 当前节点 |
| | | // null, // 内容 |
| | | // null, // 任务列表 |
| | | // null, // 进度 |
| | | // null, // 状态[非空] |
| | | // null, // 是否删除[非空] |
| | | // null, // 租户 |
| | | // null, // 添加人员 |
| | | // null, // 添加时间[非空] |
| | | // null, // 修改人员 |
| | | // null, // 修改时间 |
| | | // null // 备注 |
| | | // ); |
| | | |
| | | public String getAgvId$(){ |
| | | AgvService service = SpringUtils.getBean(AgvService.class); |
| | | Agv agv = service.getById(this.agvId); |
| | | if (!Cools.isEmpty(agv)){ |
| | | return String.valueOf(agv.getUuid()); |
| | | } |
| | | public Boolean rollerWaitingBool(){ |
| | | if (null == this.rollerWaiting){ return null; } |
| | | switch (this.rollerWaiting){ |
| | | case 1: |
| | | return true; |
| | | case 0: |
| | | return false; |
| | | default: |
| | | return null; |
| | | } |
| | | |
| | | public String getStatus$(){ |
| | | if (null == this.status){ return null; } |
| | | switch (this.status){ |
| | | case 1: |
| | | return "正常"; |
| | | case 0: |
| | | return "冻结"; |
| | | default: |
| | | return String.valueOf(this.status); |
| | | } |
| | | } |
| | | |
| | | |
| | | public Boolean getStatusBool(){ |
| | | if (null == this.status){ return null; } |
| | |
| | | |
| | | List<Integer> selectUsedBackpacks(Long travelId, Long agvId); |
| | | |
| | | Segment hasRollerWaitingNow(Long travelId, Long agvId, Long codeId, TaskPosDto.PosType posType); |
| | | |
| | | Segment getRollerWaiting(Long agvId, Long codeId, TaskPosDto.PosType posType); |
| | | |
| | | Boolean isRollerWaiting(Long agvId); |
| | |
| | | |
| | | Travel findRunningTravel(Long agvId); |
| | | |
| | | Travel findRollerWaitingTravel(Long agvId, Long code); |
| | | |
| | | Boolean hasRollerWaiting(Long agvId); |
| | | |
| | | Boolean markRollerWaiting(Long travelId, Long codeId); |
| | | |
| | | Boolean clearRollerWaiting(Long travelId); |
| | | |
| | | } |
| | |
| | | } |
| | | |
| | | @Override // todo |
| | | public Segment hasRollerWaitingNow(Long travelId, Long agvId, Long codeId, TaskPosDto.PosType posType) { |
| | | List<Segment> segments = this.list(new LambdaQueryWrapper<Segment>() |
| | | .eq(Segment::getTravelId, travelId) |
| | | .eq(Segment::getAgvId, agvId) |
| | | .eq(Segment::getState, SegmentStateType.WAITING.toString()) |
| | | .eq(Segment::getEndNode, codeId) |
| | | .eq(Segment::getPosType, posType.toString()) |
| | | .eq(Segment::getRollerWaiting, 1) |
| | | .orderByDesc(Segment::getId) |
| | | ); |
| | | |
| | | return null; |
| | | } |
| | | |
| | | @Override //todo |
| | | public Segment getRollerWaiting(Long agvId, Long codeId, TaskPosDto.PosType posType) { |
| | | List<Segment> segments = this.list(new LambdaQueryWrapper<Segment>() |
| | | .eq(Segment::getAgvId, agvId) |
| | |
| | | return segments.get(0); |
| | | } |
| | | |
| | | @Override // todo |
| | | @Override |
| | | public Boolean isRollerWaiting(Long agvId) { |
| | | return 0 < this.count(new LambdaQueryWrapper<Segment>() |
| | | .eq(Segment::getAgvId, agvId) |
| | |
| | | package com.zy.acs.manager.manager.service.impl; |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.zy.acs.framework.common.Cools; |
| | | import com.zy.acs.framework.exception.CoolException; |
| | | import com.zy.acs.manager.manager.entity.Segment; |
| | | import com.zy.acs.manager.manager.entity.Travel; |
| | | import com.zy.acs.manager.manager.enums.SegmentStateType; |
| | |
| | | import com.zy.acs.manager.manager.mapper.TravelMapper; |
| | | import com.zy.acs.manager.manager.service.SegmentService; |
| | | import com.zy.acs.manager.manager.service.TravelService; |
| | | import com.zy.acs.framework.exception.CoolException; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import java.util.Date; |
| | | import java.util.List; |
| | | import java.util.Objects; |
| | | |
| | | @Slf4j |
| | | @Service("travelService") |
| | |
| | | ); |
| | | } |
| | | |
| | | @Override |
| | | public Travel findRollerWaitingTravel(Long agvId, Long code) { |
| | | return this.getOne(new LambdaQueryWrapper<Travel>() |
| | | .eq(Travel::getAgvId, agvId) |
| | | .eq(Travel::getState, TravelStateType.RUNNING.toString()) |
| | | .eq(Travel::getRollerWaiting, 1) |
| | | .eq(Travel::getRollerWaitingCode, code) |
| | | .orderByDesc(Travel::getCreateTime) |
| | | .last("limit 1") |
| | | ); |
| | | } |
| | | |
| | | @Override |
| | | public Boolean hasRollerWaiting(Long agvId) { |
| | | if (null == agvId) { |
| | | return false; |
| | | } |
| | | return 0 < this.count(new LambdaQueryWrapper<Travel>() |
| | | .eq(Travel::getAgvId, agvId) |
| | | .eq(Travel::getState, TravelStateType.RUNNING.toString()) |
| | | .eq(Travel::getRollerWaiting, 1) |
| | | ); |
| | | } |
| | | |
| | | @Override |
| | | public Boolean markRollerWaiting(Long travelId, Long codeId) { |
| | | if (Cools.isEmpty(travelId, codeId)) { |
| | | return false; |
| | | } |
| | | Travel travel = this.getById(travelId); |
| | | if (travel == null) { |
| | | return false; |
| | | } |
| | | if (!TravelStateType.RUNNING.toString().equals(travel.getState())) { |
| | | return false; |
| | | } |
| | | if (travel.getRollerWaiting() == 1 |
| | | && Objects.equals(travel.getRollerWaitingCode(), codeId)) { |
| | | return true; |
| | | } |
| | | travel.setRollerWaiting(1); |
| | | travel.setRollerWaitingCode(codeId); |
| | | if (!this.updateById(travel)) { |
| | | log.error("travel [{}] failed to mark roller waiting (code={})", travelId, codeId); |
| | | return false; |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | @Override |
| | | public Boolean clearRollerWaiting(Long travelId) { |
| | | if (null == travelId) { |
| | | return false; |
| | | } |
| | | Travel travel = this.getById(travelId); |
| | | if (travel == null) { |
| | | return false; |
| | | } |
| | | // if (!TravelStateType.RUNNING.toString().equals(travel.getState())) { |
| | | // return false; |
| | | // } |
| | | if (travel.getRollerWaiting() == 0 && Cools.isEmpty(travel.getRollerWaitingCode())) { |
| | | return true; |
| | | } |
| | | if (!this.update( |
| | | new LambdaUpdateWrapper<Travel>() |
| | | .eq(Travel::getId, travelId) |
| | | .set(Travel::getRollerWaiting, 0) |
| | | .set(Travel::getRollerWaitingCode, null) |
| | | )) { |
| | | log.error("travel [{}] failed to clear roller waiting", travelId); |
| | | return false; |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | } |