New file |
| | |
| | | package com.zy.asrs.wcs.asrs.entity.param; |
| | | |
| | | import lombok.Data; |
| | | |
| | | import java.io.Serializable; |
| | | |
| | | @Data |
| | | public class CreateWcsTaskParam implements Serializable { |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | private String requestPK; //请求编号 |
| | | private String dvcNo; //初始设备编号 |
| | | private String contNo; //容器条码 |
| | | private String trkType; //任务类型 |
| | | private String trkSubType; //子任务类型 |
| | | private String trkPrty; //任务优先级 |
| | | private String frmPos; //起始位置 |
| | | private String toPos; //目标位置 |
| | | private String isFull; //容器空满状态 |
| | | private String contType; //容器类型 |
| | | private String operator; //上位系统名 |
| | | private String operationTime; //任务下发时间 |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | } |
| | |
| | | mainService.analyzeInBoundTask(); |
| | | // 解析小车移动工作档 |
| | | mainService.analyzeMoveTask(); |
| | | // 解析小车载货移动工作档 |
| | | mainService.analyzeLadenMoveTask(); |
| | | // 出库 ===>> 工作档信息写入led显示器 |
| | | mainService.ledExecute(); |
| | | // 其他 ===>> LED显示器复位,显示默认信息 |
| | |
| | | return R.ok(); |
| | | } |
| | | |
| | | //生成载货移动任务 |
| | | @PostMapping("/createLadenMoveTakeTask") |
| | | public R createLadenMoveTakeTask(@RequestBody CreateManualTakeTaskParam param) { |
| | | //获取手动任务类型 |
| | | TaskCtg taskCtg = taskCtgService.getOne(new LambdaQueryWrapper<TaskCtg>() |
| | | .eq(TaskCtg::getFlag, String.valueOf(TaskCtgType.MOVE)) |
| | | .eq(TaskCtg::getStatus, 1)); |
| | | if (taskCtg == null) { |
| | | return R.error("任务类型异常"); |
| | | } |
| | | |
| | | Task one = taskService.getOne(new LambdaQueryWrapper<Task>() |
| | | .eq(Task::getTaskCtg, taskCtg.getId()) |
| | | .eq(Task::getOriginLoc, param.getOriginLoc()) |
| | | .eq(Task::getDestLoc, param.getDestLoc())); |
| | | if (one != null) { |
| | | return R.error("任务已存在"); |
| | | } |
| | | |
| | | //优先级 |
| | | Integer priority = 10; |
| | | if (param.getPriority() != null) { |
| | | priority = param.getPriority(); |
| | | } |
| | | |
| | | Task task = new Task(); |
| | | task.setUuid(String.valueOf(snowflakeIdWorker.nextId())); |
| | | task.setTaskNo(String.valueOf(Utils.getTaskNo("OUT"))); |
| | | task.setWmsTaskNo(param.getTaskNo()); |
| | | task.setTaskSts(TaskStsType.NEW_LADEN_MOVE.sts); |
| | | task.setTaskCtg(taskCtg.getId()); |
| | | task.setPriority(priority); |
| | | task.setOriginSite(null); |
| | | task.setOriginLoc(param.getOriginLoc());//源库位 |
| | | task.setDestSite(null); |
| | | task.setDestLoc(param.getDestLoc());//目标库位 |
| | | task.setIoTime(new Date()); |
| | | task.setStartTime(new Date()); |
| | | task.setStatus(1); |
| | | task.setMemo(""); |
| | | task.setShuttleNo(null);//等待主线程分配小车 |
| | | task.setRecordLoc(param.getRecord() ? "Y" : "N");//记录库存信息 |
| | | task.setHostId(1L);//临时控制只允许host为1 |
| | | |
| | | boolean result = taskService.save(task); |
| | | if (!result) { |
| | | return R.error("生成手动取放货任务失败!"); |
| | | } |
| | | return R.ok(); |
| | | } |
| | | |
| | | //生成小车移动任务 |
| | | @PostMapping("/createMoveTask") |
| | | public R createMoveTask(@RequestBody CreateMoveTaskParam param) { |
| | |
| | | package com.zy.asrs.wcs.core.kernel; |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.zy.asrs.framework.common.Cools; |
| | | import com.zy.asrs.framework.common.R; |
| | | import com.zy.asrs.wcs.core.domain.dto.MotionDto; |
| | | import com.zy.asrs.wcs.core.entity.*; |
| | | import com.zy.asrs.wcs.core.model.enums.DeviceCtgType; |
| | |
| | | } |
| | | return motionList; |
| | | } |
| | | /** |
| | | * 生成小车载货迁移动作 |
| | | */ |
| | | public List<Motion> generateShuttleLadenMoveMotion(Task task) { |
| | | List<Motion> motionList = new ArrayList<>(); |
| | | if (task.getTaskSts() != TaskStsType.NEW_LADEN_MOVE.sts) { |
| | | return motionList; |
| | | } |
| | | //originLoc 源库位 |
| | | String originLoc = task.getOriginLoc(); |
| | | // locNo 目标库位 |
| | | String locNo = task.getDestLoc(); |
| | | |
| | | Device shuttleDevice = deviceService.getOne(new LambdaQueryWrapper<Device>() |
| | | .eq(Device::getDeviceNo, task.getShuttleNo()) |
| | | .eq(Device::getDeviceType, DeviceCtgType.SHUTTLE.val()) |
| | | .eq(Device::getHostId, task.getHostId()) |
| | | .eq(Device::getStatus, 1)); |
| | | if (shuttleDevice == null) { |
| | | return motionList; |
| | | } |
| | | |
| | | ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, shuttleDevice.getId().intValue()); |
| | | if (shuttleThread == null) { |
| | | return motionList; |
| | | } |
| | | |
| | | ShuttleProtocol shuttleProtocol = shuttleThread.getStatus(); |
| | | if (shuttleProtocol == null || shuttleProtocol.getShuttleNo() == null) { |
| | | return motionList; |
| | | } |
| | | |
| | | String shuttleLocNo = shuttleProtocol.getCurrentLocNo(); |
| | | |
| | | // 判断穿梭车是否在目标层 |
| | | if (Utils.getLev(shuttleLocNo) == Utils.getLev(locNo)) { |
| | | |
| | | if (!shuttleLocNo.equals(locNo)) {//小车不在目标库位 |
| | | // 穿梭车走行至源库位 |
| | | motionList.addAll(kernelService.shuttleMove( |
| | | MotionDto.build((dto -> { |
| | | dto.setShuttleNo(shuttleDevice.getId().intValue()); |
| | | dto.setLocNo(shuttleLocNo); |
| | | })), |
| | | MotionDto.build((dto -> { |
| | | dto.setShuttleNo(shuttleDevice.getId().intValue()); |
| | | dto.setLocNo(originLoc); |
| | | })), |
| | | MotionCtgType.SHUTTLE_MOVE |
| | | )); |
| | | |
| | | // 穿梭车顶升 |
| | | motionList.add(Motion.build(motion -> { |
| | | motion.setDeviceCtg(DeviceCtgType.SHUTTLE.val()); |
| | | motion.setDevice(String.valueOf(shuttleDevice.getId())); |
| | | motion.setMotionCtg(MotionCtgType.SHUTTLE_PALLET_LIFT.val()); |
| | | })); |
| | | |
| | | // 穿梭车走行至目标库位 |
| | | motionList.addAll(kernelService.shuttleMove( |
| | | MotionDto.build((dto -> { |
| | | dto.setShuttleNo(shuttleDevice.getId().intValue()); |
| | | dto.setLocNo(originLoc); |
| | | })), |
| | | MotionDto.build((dto -> { |
| | | dto.setShuttleNo(shuttleDevice.getId().intValue()); |
| | | dto.setLocNo(locNo); |
| | | })), |
| | | MotionCtgType.SHUTTLE_MOVE |
| | | )); |
| | | |
| | | //穿梭车托盘下降 |
| | | motionList.add(Motion.build(motion -> { |
| | | motion.setDeviceCtg(DeviceCtgType.SHUTTLE.val()); |
| | | motion.setDevice(String.valueOf(shuttleDevice.getId())); |
| | | motion.setMotionCtg(MotionCtgType.SHUTTLE_PALLET_DOWN.val()); |
| | | })); |
| | | |
| | | } |
| | | |
| | | } else { |
| | | //小车跨层 |
| | | } |
| | | return motionList; |
| | | } |
| | | |
| | | /** |
| | | * 生成小车手动动作 |
| | |
| | | |
| | | List<Task> selectWaitAnalyzeMoveTask(); |
| | | |
| | | List<Task> selectWaitAnalyzeLadenMoveTask(); |
| | | |
| | | List<Task> selectLadenMoveByAnalyzeSts(); |
| | | |
| | | List<Task> selectLadenMoveByExecuteSts(); |
| | | |
| | | List<Task> hasChargeInLoc(String locNo); |
| | | |
| | | Task selectMoveWorking(Integer shuttleNo); |
| | |
| | | package com.zy.asrs.wcs.core.model.enums; |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.zy.asrs.framework.common.SpringUtils; |
| | | import com.zy.asrs.framework.exception.CoolException; |
| | | import com.zy.asrs.wcs.core.entity.TaskSts; |
| | | import com.zy.asrs.wcs.core.service.TaskStsService; |
| | | |
| | | public enum TaskStsType { |
| | | |
| | |
| | | ANALYZE_MANUAL(402, "手动任务解析"), |
| | | EXECUTE_MANUAL(403, "执行手动任务"), |
| | | COMPLETE_MANUAL(410, "手动任务完成"), |
| | | |
| | | NEW_LADEN_MOVE(501,"生成移库任务"), |
| | | ANALYZE_LADEN_MOVE(502, "移库任务解析"), |
| | | EXECUTE_LADEN_MOVE(503, "执行移库任务"), |
| | | COMPLETE_LADEN_MOVE(504, "移库任务完成"), |
| | | ; |
| | | |
| | | |
| | |
| | | |
| | | List<Task> selectWaitAnalyzeMoveTask(); |
| | | |
| | | List<Task> selectWaitAnalyzeLadenMoveTask(); |
| | | |
| | | List<Task> selectLadenMoveByAnalyzeSts(); |
| | | |
| | | List<Task> selectLadenMoveByExecuteSts(); |
| | | |
| | | List<Task> hasChargeInLoc(String locNo); |
| | | |
| | | Task selectMoveWorking(Integer shuttleNo); |
| | |
| | | } |
| | | } |
| | | |
| | | // 解析小车载货移动工作档 |
| | | public synchronized void analyzeLadenMoveTask() { |
| | | for (Task task : taskService.selectWaitAnalyzeLadenMoveTask()) { |
| | | if (Cools.isEmpty(task.getShuttleNo())) { |
| | | //分配小车 |
| | | //搜索空闲车 |
| | | ShuttleThread shuttleThread = shuttleDispatcher.searchIdleShuttle(task); |
| | | if (shuttleThread == null) { |
| | | News.info("{}任务未找到空闲穿梭车", task.getTaskNo()); |
| | | continue; |
| | | } |
| | | |
| | | task.setShuttleNo(Integer.valueOf(shuttleThread.getDevice().getDeviceNo()));//保存穿梭车号 |
| | | task.setUpdateTime(new Date()); |
| | | if (!taskService.updateById(task)) { |
| | | News.info("{}任务更新穿梭车号失败", task.getTaskNo()); |
| | | } |
| | | continue; |
| | | } |
| | | |
| | | // generate motion list |
| | | List<Motion> motionList = analyzeService.generateShuttleLadenMoveMotion(task); |
| | | if (motionList.isEmpty()) { |
| | | continue; |
| | | } |
| | | motionService.batchInsert(motionList, task.getUuid(), Integer.valueOf(task.getTaskNo()), task.getHostId()); |
| | | |
| | | // 更新工作主档 |
| | | task.setTaskSts(TaskStsType.ANALYZE_LADEN_MOVE.sts); // 工作状态 |
| | | task.setUpdateTime(new Date()); |
| | | if (!taskService.updateById(task)) { |
| | | News.error("更新工作档失败!!! [工作号:{}]", task.getTaskNo()); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 四向穿梭车电量检测 ===>> 发起充电 |
| | | */ |
| | |
| | | } |
| | | |
| | | @Override |
| | | public List<Task> selectWaitAnalyzeLadenMoveTask() { |
| | | return this.baseMapper.selectWaitAnalyzeLadenMoveTask(); |
| | | } |
| | | |
| | | @Override |
| | | public List<Task> selectLadenMoveByAnalyzeSts() { |
| | | return this.baseMapper.selectLadenMoveByAnalyzeSts(); |
| | | } |
| | | |
| | | @Override |
| | | public List<Task> selectLadenMoveByExecuteSts() { |
| | | return this.baseMapper.selectLadenMoveByExecuteSts(); |
| | | } |
| | | |
| | | @Override |
| | | public List<Task> hasChargeInLoc(String locNo) { |
| | | return this.baseMapper.hasChargeInLoc(locNo); |
| | | } |
| | |
| | | } |
| | | |
| | | @Scheduled(cron = "0/1 * * * * ? ") |
| | | public synchronized void executeLadenMoveTask() { |
| | | Date now = new Date(); |
| | | // ANALYZE_CHARGE |
| | | for (Task taskCharge : taskService.selectLadenMoveByAnalyzeSts()) { |
| | | Motion executingMotion = motionService.selectOfTop1(taskCharge.getUuid(), MotionStsType.EXECUTING.val(), taskCharge.getHostId()); |
| | | if (executingMotion != null) {//存在正在执行的motion |
| | | if (executingMotion.getSync() == 1) {//当前执行中的动作是同步动作,等待执行完成后再执行下一个动作 |
| | | continue; |
| | | } |
| | | } |
| | | |
| | | Motion motion = motionService.selectOfTop1(taskCharge.getUuid(), MotionStsType.INIT.val(), taskCharge.getHostId()); |
| | | if (null != motion) { |
| | | boolean result = this.executeMotion(motion); |
| | | if (!result) { |
| | | continue; |
| | | } |
| | | // 更新Task |
| | | switch (TaskStsType.query(taskCharge.getTaskSts())) { |
| | | case ANALYZE_LADEN_MOVE: |
| | | taskCharge.setTaskSts(TaskStsType.EXECUTE_LADEN_MOVE.sts); |
| | | break; |
| | | } |
| | | taskCharge.setUpdateTime(now); |
| | | if (!taskService.updateById(taskCharge)) { |
| | | log.error("{}其他工作档更新状态失败!", taskCharge.getTaskNo()); |
| | | } |
| | | } |
| | | } |
| | | // EXECUTE_CHARGE |
| | | for (Task taskCharge : taskService.selectLadenMoveByExecuteSts()) { |
| | | if (!motionService.hasRunningMotion(taskCharge.getUuid(), taskCharge.getHostId())) { |
| | | Motion motion = motionService.selectOfTop1(taskCharge.getUuid(), MotionStsType.WAITING.val(), taskCharge.getHostId()); |
| | | if (null != motion) { |
| | | boolean result = this.executeMotion(motion); |
| | | if (!result) { |
| | | continue; |
| | | } |
| | | } else { |
| | | if (motionService.selectOfTop1(taskCharge.getUuid(), MotionStsType.EXECUTING.val(), taskCharge.getHostId()) != null) { |
| | | continue; |
| | | } |
| | | |
| | | // 更新Task |
| | | switch (TaskStsType.query(taskCharge.getTaskSts())) { |
| | | case EXECUTE_LADEN_MOVE: |
| | | taskCharge.setTaskSts(TaskStsType.COMPLETE_LADEN_MOVE.sts); |
| | | break; |
| | | } |
| | | taskCharge.setUpdateTime(now); |
| | | if (!taskService.updateById(taskCharge)) { |
| | | log.error("{}他工作档更新状态失败!", taskCharge.getTaskNo()); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | @Scheduled(cron = "0/1 * * * * ? ") |
| | | public synchronized void executeManualTask() { |
| | | Date now = new Date(); |
| | | // ANALYZE_MANUAL |
| | |
| | | taskSts.add(TaskStsType.COMPLETE_CHARGE.sts); |
| | | taskSts.add(TaskStsType.COMPLETE_MOVE.sts); |
| | | taskSts.add(TaskStsType.COMPLETE_MANUAL.sts); |
| | | taskSts.add(TaskStsType.COMPLETE_LADEN_MOVE.sts); |
| | | |
| | | List<Task> tasks = taskService.list(new LambdaQueryWrapper<Task>() |
| | | .eq(Task::getStatus, 1) |
| | |
| | | order by priority desc,start_time,task_no asc |
| | | </select> |
| | | |
| | | <select id="selectWaitAnalyzeLadenMoveTask" resultType="com.zy.asrs.wcs.core.entity.Task"> |
| | | select * from wcs_task where task_sts = 501 |
| | | order by priority desc,start_time,task_no asc |
| | | </select> |
| | | |
| | | <select id="selectLadenMoveByAnalyzeSts" resultType="com.zy.asrs.wcs.core.entity.Task"> |
| | | select * from wcs_task |
| | | where 1=1 |
| | | and task_sts in (502) |
| | | order by priority desc,start_time,task_no asc |
| | | </select> |
| | | |
| | | <select id="selectLadenMoveByExecuteSts" resultType="com.zy.asrs.wcs.core.entity.Task"> |
| | | select * from wcs_task |
| | | where 1=1 |
| | | and task_sts in (503) |
| | | order by priority desc,start_time,task_no asc |
| | | </select> |
| | | |
| | | <select id="hasChargeInLoc" resultType="com.zy.asrs.wcs.core.entity.Task"> |
| | | select * from wcs_task |
| | | where task_sts in (201,202,203,204) |