src/main/java/com/zy/asrs/service/impl/ForkMainServiceImpl.java
@@ -15,11 +15,13 @@ import com.zy.core.action.ForkLiftAction; import com.zy.core.action.ShuttleAction; import com.zy.core.cache.SlaveConnection; import com.zy.core.dispatcher.ForkLiftDispatchUtils; import com.zy.core.dispatcher.ShuttleDispatchUtils; import com.zy.core.enums.*; import com.zy.core.model.command.*; import com.zy.core.model.protocol.ForkLiftProtocol; import com.zy.core.model.protocol.ForkLiftStaProtocol; import com.zy.core.model.protocol.LiftStaProtocol; import com.zy.core.model.protocol.ShuttleProtocol; import com.zy.core.thread.ForkLiftThread; import com.zy.core.thread.ShuttleThread; @@ -35,7 +37,6 @@ /** * 立体仓库WCS系统主流程业务 * Created by vincent on 2020/8/6 */ @Slf4j @Service("forkMainService") @@ -62,8 +63,6 @@ @Autowired private ConfigService configService; @Autowired private NavigateMapUtils navigateMapUtils; @Autowired private NavigateMapData navigateMapData; @Autowired private NavigateUtils navigateUtils; @@ -79,6 +78,8 @@ private BasShuttleChargeService basShuttleChargeService; @Autowired private DeviceConfigService deviceConfigService; @Autowired private ForkLiftDispatchUtils forkLiftDispatchUtils; /** * 初始化实时地图 @@ -897,7 +898,7 @@ News.error("提升机已确认且任务完成状态,复位失败,但未找到工作档。提升机号={},工作号={}", forkLiftProtocol.getLiftNo(), forkLiftProtocol.getWrkNo()); } }else { boolean checkPreviewDispatchForkLift = commonService.checkWorkNoContainMk(forkLiftProtocol.getWrkNo(), WrkIoType.FORKLIFT_MOVE.id); boolean checkPreviewDispatchForkLift = commonService.checkWorkNoContainMk(forkLiftProtocol.getWrkNo(), WrkIoType.PREVIEW_LIFT_MOVE.id); if (checkPreviewDispatchForkLift) { //属于提升机预调度移动任务 //无工作档支撑,直接确认完成 @@ -1490,24 +1491,25 @@ return false; } //获取源输送站 ForkLiftStaProtocol liftSta = ForkLiftUtils.getLiftStaByStaNo(wrkMast.getSourceStaNo()); if (liftSta == null) { return false;//找不到站点 //搜索最近且无故障提升机 ForkLiftStaProtocol recentLiftStation = forkLiftDispatchUtils.getRecentLiftStation(shuttleProtocol.getShuttleNo(), Utils.getLev(wrkMast.getLocNo())); if(recentLiftStation == null) { News.info("{}号小车,{}目标库位,没有可用空闲输送站点", shuttleProtocol.getShuttleNo(), wrkMast.getLocNo()); return false; } if (liftSta.getHasTray()) { if (recentLiftStation.getHasTray()) { News.taskInfo(wrkMast.getWrkNo(), "{}任务,源站存在托盘", wrkMast.getWrkNo()); return false; } if (liftSta.getHasCar()) { if (recentLiftStation.getHasCar()) { News.taskInfo(wrkMast.getWrkNo(), "{}任务,源站存在小车", wrkMast.getWrkNo()); return false; } //获取目标输送站 ForkLiftStaProtocol liftStaTarget = ForkLiftUtils.getLiftStaByStaNo(wrkMast.getStaNo()); ForkLiftStaProtocol liftStaTarget = ForkLiftUtils.getLiftStaByLev(recentLiftStation.getLiftNo(), Utils.getLev(wrkMast.getLocNo())); if (liftStaTarget == null) { return false;//找不到站点 } @@ -1529,7 +1531,7 @@ assignCommand.setAuto(true);//自动模式 //计算近点位置 String endLocation = navigateUtils.calcEndLocation(shuttleProtocol.getCurrentLocNo(), liftSta.getLocNo(), NavigationMapType.getMapTypes(NavigationMapType.NORMAL), null, null, 1); String endLocation = navigateUtils.calcEndLocation(shuttleProtocol.getCurrentLocNo(), recentLiftStation.getLocNo(), NavigationMapType.getMapTypes(NavigationMapType.NORMAL), null, null, 1); if (endLocation == null) { News.taskInfo(wrkMast.getWrkNo(), "{}任务,小车近点位置计算失败", wrkMast.getWrkNo()); return false; @@ -1554,6 +1556,8 @@ assignCommand.setCommands(commands); wrkMast.setWrkSts(WrkStsType.MOVE_NEARBY.sts);//小车移动到提升机中 301.生成小车移库任务 ==> 302.小车移动至近点中 wrkMast.setSourceStaNo(recentLiftStation.getStaNo()); wrkMast.setStaNo(liftStaTarget.getStaNo()); wrkMast.setModiTime(now); wrkMast.setSystemMsg("");//清空消息 if (wrkMastService.updateById(wrkMast)) { @@ -2000,7 +2004,7 @@ } //移动 int workNo = commonService.getWorkNo(WrkIoType.FORKLIFT_MOVE.id);//获取任务号 int workNo = commonService.getWorkNo(WrkIoType.PREVIEW_LIFT_MOVE.id);//获取任务号 //获取提升机命令 ForkLiftCommand liftCommand = forkLiftThread.getMoveCommand(workNo, forkLiftProtocol.getLev(), Utils.getLev(wrkMast.getSourceLocNo())); src/main/java/com/zy/asrs/service/impl/MainServiceImpl.java
@@ -15,6 +15,7 @@ import com.zy.core.action.LiftAction; import com.zy.core.action.ShuttleAction; import com.zy.core.cache.SlaveConnection; import com.zy.core.dispatcher.LiftDispatchUtils; import com.zy.core.dispatcher.ShuttleDispatchUtils; import com.zy.core.enums.*; import com.zy.core.model.command.*; @@ -57,8 +58,6 @@ @Autowired private ConfigService configService; @Autowired private NavigateMapUtils navigateMapUtils; @Autowired private NavigateMapData navigateMapData; @Autowired private NavigateUtils navigateUtils; @@ -74,6 +73,8 @@ private BasShuttleChargeService basShuttleChargeService; @Autowired private DeviceConfigService deviceConfigService; @Autowired private LiftDispatchUtils liftDispatchUtils; /** * 初始化实时地图 @@ -568,9 +569,9 @@ } /** * 货叉提升机任务 * 提升机任务 */ public synchronized void forkLiftIoExecute() { public synchronized void liftIoExecute() { try { //搜索是否有待处理的任务 List<WrkMast> wrkMasts = wrkMastService.selectList(new EntityWrapper<WrkMast>() @@ -844,61 +845,63 @@ } /** * 货叉提升机任务完成 * 提升机任务完成 */ public synchronized void forkLiftFinished() { public synchronized void liftFinished() { try { List<DeviceConfig> forkliftList = deviceConfigService.selectList(new EntityWrapper<DeviceConfig>() .eq("device_type", String.valueOf(SlaveType.ForkLift))); for (DeviceConfig device : forkliftList) { List<DeviceConfig> liftList = deviceConfigService.selectList(new EntityWrapper<DeviceConfig>() .eq("device_type", String.valueOf(SlaveType.Lift))); for (DeviceConfig device : liftList) { //获取提升机信息 ForkLiftThread forkLiftThread = (ForkLiftThread) SlaveConnection.get(SlaveType.ForkLift, device.getDeviceNo()); if(forkLiftThread == null) { LiftThread liftThread = (LiftThread) SlaveConnection.get(SlaveType.Lift, device.getDeviceNo()); if(liftThread == null) { continue; } ForkLiftProtocol forkLiftProtocol = forkLiftThread.getStatus(); if (forkLiftProtocol == null) { LiftProtocol liftProtocol = liftThread.getStatus(); if (liftProtocol == null) { continue; } //提升机为等待确认且空闲 if (forkLiftProtocol.getProtocolStatus() == ForkLiftProtocolStatusType.WAITING.id && forkLiftProtocol.getWrkNo() != 0 if (liftProtocol.getProtocolStatus() == LiftProtocolStatusType.WAITING.id && liftProtocol.getTaskNo() != 0 ) { //将任务档标记为完成 WrkMast wrkMast = wrkMastService.selectByWorkNo(forkLiftProtocol.getWrkNo()); WrkMast wrkMast = wrkMastService.selectByWorkNo(liftProtocol.getTaskNo()); if (wrkMast != null) { if (wrkMast.getWrkSts() == WrkStsType.INBOUND_LIFT_RUN.sts) { //3.提升机搬运中 ==> 4.提升机搬运完成 wrkMast.setWrkSts(WrkStsType.INBOUND_LIFT_RUN_COMPLETE.sts); wrkMast.setLiftNo(null);//释放提升机 forkLiftThread.setSyncTaskNo(0); }else if (wrkMast.getWrkSts() == WrkStsType.MOVE_NEARBY_COMPLETE.sts) { //303.小车移动至近点完成 -- 调度提升机到小车层 } else if (wrkMast.getWrkSts() == WrkStsType.OUTBOUND_LIFT_RUN.sts) { //104.提升机搬运中 ==> 109.出库完成 //304.提升机搬运中 ==> 109.出库完成 wrkMast.setWrkSts(WrkStsType.COMPLETE_OUTBOUND.sts); wrkMast.setLiftNo(null);//释放提升机 forkLiftThread.setSyncTaskNo(0); redisUtil.set(RedisKeyType.FORK_LIFT_PUT_COMPLETE.key + forkLiftProtocol.getLiftNo(), wrkMast.getWmsWrkNo(), 60 * 3); } else if (wrkMast.getWrkSts() == WrkStsType.MOVE_LIFT_RUN.sts) { //306.提升机搬运中 ==> 307.提升机搬运完成 wrkMast.setWrkSts(WrkStsType.MOVE_LIFT_RUN_COMPLETE.sts); forkLiftThread.setSyncTaskNo(0); } else { News.error("提升机确认失败,提升机号={},工作号={}", liftProtocol.getLiftNo(), liftProtocol.getTaskNo()); return; } wrkMast.setModiTime(new Date()); if (wrkMastService.updateById(wrkMast)) { forkLiftThread.reset(); News.info("提升机已确认且任务完成状态。提升机号={}", forkLiftProtocol.getLiftNo()); liftThread.reset(); News.info("提升机已确认且任务完成状态。提升机号={}", liftProtocol.getLiftNo()); } else { News.error("提升机已确认且任务完成状态,复位失败,但未找到工作档。提升机号={},工作号={}", forkLiftProtocol.getLiftNo(), forkLiftProtocol.getWrkNo()); News.error("提升机已确认且任务完成状态,复位失败,但未找到工作档。提升机号={},工作号={}", liftProtocol.getLiftNo(), liftProtocol.getTaskNo()); } }else { boolean checkPreviewDispatchForkLift = commonService.checkWorkNoContainMk(forkLiftProtocol.getWrkNo(), WrkIoType.FORKLIFT_MOVE.id); boolean checkPreviewDispatchForkLift = commonService.checkWorkNoContainMk(liftProtocol.getTaskNo(), WrkIoType.PREVIEW_LIFT_MOVE.id); if (checkPreviewDispatchForkLift) { //属于提升机预调度移动任务 //无工作档支撑,直接确认完成 forkLiftThread.setSyncTaskNo(0); forkLiftThread.reset(); News.info("已确认提升机预调度移动任务。提升机号={}", forkLiftProtocol.getLiftNo()); liftThread.setSyncTaskNo(0); liftThread.reset(); News.info("已确认提升机预调度移动任务。提升机号={}", liftProtocol.getLiftNo()); } } } @@ -1485,25 +1488,15 @@ return false; } //获取源输送站 LiftStaProtocol liftSta = LiftUtils.getLiftStaByStaNo(wrkMast.getSourceStaNo()); if (liftSta == null) { return false;//找不到站点 } if (liftSta.getHasCar()) { News.taskInfo(wrkMast.getWrkNo(), "{}任务,源站存在小车", wrkMast.getWrkNo()); //搜索最近且无故障提升机 LiftStaProtocol recentLiftStation = liftDispatchUtils.getRecentLiftStation(shuttleProtocol.getShuttleNo(), Utils.getLev(wrkMast.getLocNo())); if(recentLiftStation == null) { News.info("{}号小车,{}目标库位,没有可用空闲输送站点", shuttleProtocol.getShuttleNo(), wrkMast.getLocNo()); return false; } //获取目标输送站 LiftStaProtocol liftStaTarget = LiftUtils.getLiftStaByStaNo(wrkMast.getStaNo()); if (liftStaTarget == null) { return false;//找不到站点 } if (liftStaTarget.getHasCar()) { News.taskInfo(wrkMast.getWrkNo(), "{}任务,目标站存在小车", wrkMast.getWrkNo()); LiftStaProtocol targetLiftSta = LiftUtils.getLiftStaByLev(recentLiftStation.getLiftNo(), Utils.getLev(wrkMast.getLocNo())); if(targetLiftSta == null) { return false; } @@ -1514,7 +1507,7 @@ assignCommand.setAuto(true);//自动模式 //计算近点位置 String endLocation = navigateUtils.calcEndLocation(shuttleProtocol.getCurrentLocNo(), liftSta.getLocNo(), NavigationMapType.getMapTypes(NavigationMapType.NORMAL), null, null, 1); String endLocation = navigateUtils.calcEndLocation(shuttleProtocol.getCurrentLocNo(), recentLiftStation.getLocNo(), NavigationMapType.getMapTypes(NavigationMapType.NORMAL), null, null, 1); if (endLocation == null) { News.taskInfo(wrkMast.getWrkNo(), "{}任务,小车近点位置计算失败", wrkMast.getWrkNo()); return false; @@ -1523,6 +1516,8 @@ //小车已在近点位置无需前往 if (shuttleProtocol.getCurrentLocNo().equals(endLocation)) { wrkMast.setWrkSts(WrkStsType.MOVE_NEARBY_COMPLETE.sts);//小车移动到提升机中 301.生成小车移库任务 ==> 303.小车移动至近点完成 wrkMast.setSourceStaNo(recentLiftStation.getStaNo()); wrkMast.setStaNo(targetLiftSta.getStaNo()); wrkMast.setModiTime(now); wrkMast.setSystemMsg("");//清空消息 wrkMastService.updateById(wrkMast); @@ -1539,6 +1534,8 @@ assignCommand.setCommands(commands); wrkMast.setWrkSts(WrkStsType.MOVE_NEARBY.sts);//小车移动到提升机中 301.生成小车移库任务 ==> 302.小车移动至近点中 wrkMast.setSourceStaNo(recentLiftStation.getStaNo()); wrkMast.setStaNo(targetLiftSta.getStaNo()); wrkMast.setModiTime(now); wrkMast.setSystemMsg("");//清空消息 if (wrkMastService.updateById(wrkMast)) { @@ -1627,7 +1624,7 @@ return false; } int targetLev = Utils.getLev(wrkMast.getLocNo()); int targetLev = Utils.getLev(shuttleProtocol.getCurrentLocNo()); if (liftProtocol.getLev() != targetLev) { //获取提升机命令 LiftCommand liftCommand = liftThread.getMoveCommand(wrkMast.getWrkNo(), liftProtocol.getLev(), targetLev); @@ -1639,7 +1636,7 @@ assignCommand.setCommands(commands); assignCommand.setLiftNo(wrkMast.getLiftNo()); assignCommand.setTaskNo(wrkMast.getWrkNo()); assignCommand.setTaskMode(ForkLiftTaskModeType.MOVE.id); assignCommand.setTaskMode(LiftTaskModeType.MOVE.id); //下发任务 liftAction.assignWork(wrkMast.getLiftNo(), assignCommand); News.taskInfo(wrkMast.getWrkNo(), "{}任务,{}号提升机在{}层,提升机不在小车层,调度移动中", wrkMast.getWrkNo(), liftProtocol.getLev(), wrkMast.getLiftNo()); @@ -1724,7 +1721,7 @@ assignCommand.setCommands(commands); assignCommand.setLiftNo(wrkMast.getLiftNo()); assignCommand.setTaskNo(wrkMast.getWrkNo()); assignCommand.setTaskMode(ForkLiftTaskModeType.SHUTTLE_SWITCH.id); assignCommand.setTaskMode(LiftTaskModeType.SHUTTLE_SWITCH.id); wrkMast.setWrkSts(WrkStsType.MOVE_LIFT_RUN.sts);//提升机搬运中 305.小车迁入提升机完成 ==> 306.提升机搬运中 wrkMast.setSystemMsg("");//清空消息 @@ -1855,77 +1852,6 @@ } } return true; } //自动切换出入库模式 public void autoSwitchForkLiftIOMode() { // List<DeviceConfig> forkliftList = deviceConfigService.selectList(new EntityWrapper<DeviceConfig>() // .eq("device_type", String.valueOf(SlaveType.ForkLift))); // for (DeviceConfig device : forkliftList) { // Integer liftNo = device.getDeviceNo(); // ForkLiftThread forkLiftThread = (ForkLiftThread) SlaveConnection.get(SlaveType.ForkLift, liftNo); // if (forkLiftThread == null) { // continue; // } // ForkLiftProtocol forkLiftProtocol = forkLiftThread.getStatus(); // if (forkLiftProtocol == null) { // continue; // } // // List<Integer> liftAllStaNo = ForkLiftUtils.getLiftAllStaNo(liftNo); // if (liftAllStaNo.isEmpty()) { // continue; // } // // List<Integer> conveyorBindLiftAllStaNo = ForkLiftUtils.getConveyorBindLiftAllStaNo(liftNo); // if (conveyorBindLiftAllStaNo.isEmpty()) { // continue; // } // // //获取入库任务 // List<WrkMast> inWrkMasts = wrkMastService.selectList(new EntityWrapper<WrkMast>() // .in("sta_no", liftAllStaNo) // .in("wrk_sts" // , WrkStsType.NEW_INBOUND.sts // , WrkStsType.INBOUND_DEVICE_RUN.sts // , WrkStsType.INBOUND_LIFT_RUN.sts // , WrkStsType.INBOUND_LIFT_RUN_COMPLETE.sts // , WrkStsType.INBOUND_SHUTTLE_RUN.sts // , WrkStsType.INBOUND_SHUTTLE_RUN_COMPLETE.sts // )); // // //获取出库任务 // List<WrkMast> outWrkMasts = wrkMastService.selectList(new EntityWrapper<WrkMast>() // .in("sta_no", conveyorBindLiftAllStaNo) // .in("wrk_sts" // , WrkStsType.NEW_OUTBOUND.sts // , WrkStsType.OUTBOUND_SHUTTLE_RUN.sts // , WrkStsType.OUTBOUND_SHUTTLE_RUN_COMPLETE.sts // , WrkStsType.OUTBOUND_LIFT_RUN.sts // , WrkStsType.OUTBOUND_LIFT_RUN_COMPLETE.sts // )); // // if (forkLiftProtocol.getIOModeType().equals(ForkLiftIoModeType.NONE)) { // //未知模式 // if (!inWrkMasts.isEmpty()) { // forkLiftThread.switchIOMode(ForkLiftIoModeType.IN); // } else if (!outWrkMasts.isEmpty()) { // forkLiftThread.switchIOMode(ForkLiftIoModeType.OUT); // }else { // forkLiftThread.switchIOMode(ForkLiftIoModeType.IN); // } // } else if (forkLiftProtocol.getIOModeType().equals(ForkLiftIoModeType.IN)) { // //入库模式 // if (inWrkMasts.isEmpty() && !outWrkMasts.isEmpty()) { // forkLiftThread.switchIOMode(ForkLiftIoModeType.OUT); // } // } else if (forkLiftProtocol.getIOModeType().equals(ForkLiftIoModeType.OUT)) { // //出库模式 // if (outWrkMasts.isEmpty() && !inWrkMasts.isEmpty()) { // forkLiftThread.switchIOMode(ForkLiftIoModeType.IN); // } // } // } } } src/main/java/com/zy/common/utils/NavigateSolution.java
@@ -205,7 +205,7 @@ } } if (map[x][y] == MapNodeType.NORMAL_PATH.id || map[x][y] == MapNodeType.MAIN_PATH.id || map[x][y] == MapNodeType.CONVEYOR_CAR_GO.id || map[x][y] == MapNodeType.CHARGE.id || map[x][y] == MapNodeType.LIFT.id) { if (map[x][y] == MapNodeType.NORMAL_PATH.id || map[x][y] == MapNodeType.MAIN_PATH.id || map[x][y] == MapNodeType.CONVEYOR_CAR_GO.id || map[x][y] == MapNodeType.CONVEYOR.id || map[x][y] == MapNodeType.CHARGE.id || map[x][y] == MapNodeType.LIFT.id) { //子轨和母轨、小车可走输送线、充电桩、提升机才能进行左右移动 if (is_valid(x, y + 1)) { NavigateNode node = new NavigateNode(x, y + 1); @@ -233,7 +233,7 @@ } } if (map[x][y] == MapNodeType.NORMAL_PATH.id || map[x][y] == MapNodeType.MAIN_PATH.id || map[x][y] == MapNodeType.CONVEYOR_CAR_GO.id || map[x][y] == MapNodeType.CHARGE.id || map[x][y] == MapNodeType.LIFT.id) { if (map[x][y] == MapNodeType.NORMAL_PATH.id || map[x][y] == MapNodeType.MAIN_PATH.id || map[x][y] == MapNodeType.CONVEYOR_CAR_GO.id || map[x][y] == MapNodeType.CONVEYOR.id || map[x][y] == MapNodeType.CHARGE.id || map[x][y] == MapNodeType.LIFT.id) { //子轨和母轨、小车可走输送线、充电桩、提升机才能进行上下移动 if (is_valid(x + 1, y)) { NavigateNode node = new NavigateNode(x + 1, y); src/main/java/com/zy/core/MainProcess.java
@@ -66,10 +66,10 @@ // mainService.shuttleFinished(); //执行移库任务 mainService.shuttleLocMoveExecute(); //货叉提升机任务 mainService.forkLiftIoExecute(); //货叉提升机任务完成 mainService.forkLiftFinished(); //提升机任务 mainService.liftIoExecute(); //提升机任务完成 mainService.liftFinished(); //执行小车移动任务 mainService.shuttleMoveExecute(); // 异常信息记录 @@ -77,9 +77,6 @@ // 穿梭车 ===>> 小车电量检测充电 mainService.loopShuttleCharge(); mainService.executeShuttleCharge(); //自动切换出入库模式 mainService.autoSwitchForkLiftIOMode(); // 间隔 Thread.sleep(200); src/main/java/com/zy/core/action/LiftAction.java
@@ -8,6 +8,7 @@ import com.zy.common.utils.RedisUtil; import com.zy.core.News; import com.zy.core.cache.SlaveConnection; import com.zy.core.enums.LiftProtocolStatusType; import com.zy.core.enums.LiftTaskModeType; import com.zy.core.enums.RedisKeyType; import com.zy.core.enums.SlaveType; @@ -121,6 +122,45 @@ redisCommand.setCommandStep(commandStep); // 更新redis数据 redisUtil.set(RedisKeyType.LIFT_WORK_FLAG.key + taskNo, JSON.toJSONString(redisCommand)); }else { if (!liftThread.isDeviceIdle()) { return false; } LiftCommand lastCommand = commands.get(commandStep - 1); if (lastCommand.getMode() == LiftTaskModeType.PICK_PUT.id) { if (liftProtocol.getLev() == lastCommand.getPut()) { lastCommand.setComplete(true); } } else if (lastCommand.getMode() == LiftTaskModeType.SHUTTLE_SWITCH.id) { if (liftProtocol.getLev() == lastCommand.getPut()) { lastCommand.setComplete(true); } } else if (lastCommand.getMode() == LiftTaskModeType.MOVE.id) { if (liftProtocol.getLev() == lastCommand.getPut()) { lastCommand.setComplete(true); } } //任务数据保存到redis redisUtil.set(RedisKeyType.LIFT_WORK_FLAG.key + redisCommand.getWrkNo(), JSON.toJSONString(redisCommand)); if (!lastCommand.getComplete()) { //上一条任务未完成,禁止下发命令 return false; } //判断是否为最后一条命令且命令执行完成,抛出等待确认状态 LiftCommand endCommand = commands.get(commands.size() - 1); if (endCommand.getComplete()) { //已执行完成 //删除redis redisUtil.del(RedisKeyType.LIFT_WORK_FLAG.key + redisCommand.getWrkNo()); //对主线程抛出等待确认状态waiting liftThread.setProtocolStatus(LiftProtocolStatusType.WAITING); News.info("提升机任务执行下发完成执行结束,提升机号={},任务数据={}", redisCommand.getLiftNo(), JSON.toJSON(redisCommand)); } } return true; src/main/java/com/zy/core/dispatcher/ForkLiftDispatchUtils.java
New file @@ -0,0 +1,127 @@ package com.zy.core.dispatcher; import com.baomidou.mybatisplus.mapper.EntityWrapper; import com.zy.asrs.entity.DeviceConfig; import com.zy.asrs.service.DeviceConfigService; import com.zy.asrs.utils.Utils; import com.zy.common.model.NavigateNode; import com.zy.common.model.enums.NavigationMapType; import com.zy.common.utils.ForkLiftUtils; import com.zy.common.utils.NavigateUtils; import com.zy.core.cache.SlaveConnection; import com.zy.core.enums.SlaveType; import com.zy.core.model.protocol.ForkLiftProtocol; import com.zy.core.model.protocol.ForkLiftStaProtocol; import com.zy.core.model.protocol.ShuttleProtocol; import com.zy.core.thread.ForkLiftThread; import com.zy.core.thread.ShuttleThread; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.List; /** * 提升机调度工具 */ @Component public class ForkLiftDispatchUtils { @Autowired private DeviceConfigService deviceConfigService; @Autowired private NavigateUtils navigateUtils; /** * 获取穿梭车最近且空闲的提升机输送站点 */ public ForkLiftStaProtocol getRecentLiftStation(Integer shuttleNo, Integer targetLev) { //获取四向穿梭车线程 ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, shuttleNo); if (shuttleThread == null) { return null; } ShuttleProtocol shuttleProtocol = shuttleThread.getStatus(); if (shuttleProtocol == null) { return null; } List<DeviceConfig> forkliftList = deviceConfigService.selectList(new EntityWrapper<DeviceConfig>() .eq("device_type", String.valueOf(SlaveType.ForkLift))); //获取小车同一楼层的站点 ArrayList<ForkLiftStaProtocol> list = new ArrayList<>(); int lev = Utils.getLev(shuttleProtocol.getCurrentLocNo());//小车楼层 for (DeviceConfig device : forkliftList) { ForkLiftThread forkLiftThread = (ForkLiftThread) SlaveConnection.get(SlaveType.ForkLift, device.getDeviceNo()); if (forkLiftThread == null) { continue; } ForkLiftProtocol forkLiftProtocol = forkLiftThread.getStatus(); if (forkLiftProtocol == null) { continue; } if (forkLiftProtocol.getErrorCode() > 0) { continue; } ForkLiftStaProtocol forkLiftStaProtocol = ForkLiftUtils.getLiftStaByLev(device.getDeviceNo(), lev); if (forkLiftStaProtocol == null) { continue; } //判断当前层是否无托盘 if (forkLiftStaProtocol.getHasTray()) { continue; } if (forkLiftStaProtocol.getHasCar()) { continue; } //判断目标楼层站点是否无托盘 ForkLiftStaProtocol targetLiftStaProtocol = ForkLiftUtils.getLiftStaByLev(device.getDeviceNo(), targetLev); if (targetLiftStaProtocol == null) { continue; } if (targetLiftStaProtocol.getHasTray()) { continue;//有托盘跳过 } if (targetLiftStaProtocol.getHasCar()) { continue; } list.add(forkLiftStaProtocol); } if (list.isEmpty()) { return null; } String currentLocNo = shuttleProtocol.getCurrentLocNo();//小车位置 Integer recentAllDistance = 9999999; ForkLiftStaProtocol recentSta = null;//最近站点 //搜索距离小车最近的站点 for (ForkLiftStaProtocol forkLiftStaProtocol : list) { Integer staNo = forkLiftStaProtocol.getStaNo();//站点号 String locNo = forkLiftStaProtocol.getLocNo();//站点库位号 //当前穿梭车线程到目标地点距离 List<NavigateNode> currentShuttlePath = navigateUtils.calc(currentLocNo, locNo, NavigationMapType.getMapTypes(NavigationMapType.NORMAL), Utils.getShuttlePoints(shuttleNo, Utils.getLev(currentLocNo)), null);//使用正常通道地图 if (currentShuttlePath == null) { continue; } Integer currentAllDistance = navigateUtils.getOriginPathAllDistance(currentShuttlePath);//计算当前路径行走总距离 if (currentAllDistance < recentAllDistance) { //如果当前楼层的车路径更小,则更新最近站点 recentSta = forkLiftStaProtocol; recentAllDistance = currentAllDistance; } } return recentSta; } } src/main/java/com/zy/core/dispatcher/LiftDispatchUtils.java
New file @@ -0,0 +1,110 @@ package com.zy.core.dispatcher; import com.baomidou.mybatisplus.mapper.EntityWrapper; import com.zy.asrs.entity.DeviceConfig; import com.zy.asrs.service.DeviceConfigService; import com.zy.asrs.utils.Utils; import com.zy.common.model.NavigateNode; import com.zy.common.model.enums.NavigationMapType; import com.zy.common.utils.LiftUtils; import com.zy.common.utils.NavigateUtils; import com.zy.core.cache.SlaveConnection; import com.zy.core.enums.SlaveType; import com.zy.core.model.protocol.LiftProtocol; import com.zy.core.model.protocol.LiftStaProtocol; import com.zy.core.model.protocol.ShuttleProtocol; import com.zy.core.thread.LiftThread; import com.zy.core.thread.ShuttleThread; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.List; /** * 提升机调度工具 */ @Component public class LiftDispatchUtils { @Autowired private DeviceConfigService deviceConfigService; @Autowired private NavigateUtils navigateUtils; /** * 获取穿梭车最近且无故障提升机输送站点 */ public LiftStaProtocol getRecentLiftStation(Integer shuttleNo, Integer targetLev) { //获取四向穿梭车线程 ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, shuttleNo); if (shuttleThread == null) { return null; } ShuttleProtocol shuttleProtocol = shuttleThread.getStatus(); if (shuttleProtocol == null) { return null; } List<DeviceConfig> liftList = deviceConfigService.selectList(new EntityWrapper<DeviceConfig>() .eq("device_type", String.valueOf(SlaveType.Lift))); //获取小车同一楼层的站点 ArrayList<LiftStaProtocol> list = new ArrayList<>(); int lev = Utils.getLev(shuttleProtocol.getCurrentLocNo());//小车楼层 for (DeviceConfig device : liftList) { LiftThread liftThread = (LiftThread) SlaveConnection.get(SlaveType.Lift, device.getDeviceNo()); if (liftThread == null) { continue; } LiftProtocol liftProtocol = liftThread.getStatus(); if (liftProtocol == null) { continue; } if (liftProtocol.getErrorCode() > 0) { continue; } //判断目标楼层站点是否无托盘 LiftStaProtocol targetLiftStaProtocol = LiftUtils.getLiftStaByLev(device.getDeviceNo(), targetLev); if (targetLiftStaProtocol == null) { continue; } //目标层有小车 if (targetLiftStaProtocol.getHasCar()) { continue; } list.add(targetLiftStaProtocol); } if (list.isEmpty()) { return null; } String currentLocNo = shuttleProtocol.getCurrentLocNo();//小车位置 Integer recentAllDistance = 9999999; LiftStaProtocol recentSta = null;//最近站点 //搜索距离小车最近的站点 for (LiftStaProtocol liftStaProtocol : list) { Integer staNo = liftStaProtocol.getStaNo();//站点号 String locNo = liftStaProtocol.getLocNo();//站点库位号 //当前穿梭车线程到目标地点距离 List<NavigateNode> currentShuttlePath = navigateUtils.calc(currentLocNo, locNo, NavigationMapType.getMapTypes(NavigationMapType.NORMAL), Utils.getShuttlePoints(shuttleNo, Utils.getLev(currentLocNo)), null);//使用正常通道地图 if (currentShuttlePath == null) { continue; } Integer currentAllDistance = navigateUtils.getOriginPathAllDistance(currentShuttlePath);//计算当前路径行走总距离 if (currentAllDistance < recentAllDistance) { //如果当前楼层的车路径更小,则更新最近站点 recentSta = liftStaProtocol; recentAllDistance = currentAllDistance; } } return recentSta; } } src/main/java/com/zy/core/dispatcher/ShuttleDispatchUtils.java
@@ -17,17 +17,13 @@ import com.zy.common.model.NavigateNode; import com.zy.common.model.enums.NavigationMapType; import com.zy.common.service.CommonService; import com.zy.common.utils.ForkLiftUtils; import com.zy.common.utils.NavigateUtils; import com.zy.core.News; import com.zy.core.cache.SlaveConnection; import com.zy.core.enums.SlaveType; import com.zy.core.enums.WrkIoType; import com.zy.core.enums.WrkStsType; import com.zy.core.model.ForkLiftSlave; import com.zy.core.model.ShuttleSlave; import com.zy.core.model.protocol.*; import com.zy.core.thread.ForkLiftThread; import com.zy.core.thread.ShuttleThread; import com.zy.system.entity.Config; import com.zy.system.service.ConfigService; @@ -251,27 +247,6 @@ } } Integer sourceStaNo = null;//小车换层源站点 Integer staNo = null;//小车换层目标站点 if (Utils.getLev(locNo) != Utils.getLev(shuttleProtocol.getCurrentLocNo())) { //目标库位和小车库位处于不同一楼层,需要通过提升机调度 //获取穿梭车最近且空闲的提升机输送站点 ForkLiftStaProtocol liftSta = this.getRecentLiftSta(shuttleNo, Utils.getLev(locNo)); if (liftSta == null) { News.info("{}号小车,{}目标库位,没有可用空闲输送站点", shuttleNo, locNo); return false;//没有可用且空闲的输送站点 } sourceStaNo = liftSta.getStaNo();//源站点 ForkLiftStaProtocol targetLiftSta = ForkLiftUtils.getLiftStaByLev(liftSta.getLiftNo(), Utils.getLev(locNo)); if (targetLiftSta == null) { News.info("{}号小车,{}目标库位,没有目标站点", shuttleNo, locNo); return false;//没有找到目标站点 } //目标站点 staNo = targetLiftSta.getStaNo();//目标站 } // 获取工作号 int workNo = commonService.getWorkNo(WrkIoType.SHUTTLE_MOVE.id); // 保存工作档 @@ -284,8 +259,6 @@ wrkMast.setShuttleNo(shuttleNo);//穿梭车号 wrkMast.setSourceLocNo(shuttleProtocol.getCurrentLocNo()); // 源库位 => 小车当前库位号 wrkMast.setLocNo(locNo); // 目标库位 wrkMast.setSourceStaNo(sourceStaNo);//源站 wrkMast.setStaNo(staNo);//目标站 wrkMast.setAppeTime(now); wrkMast.setModiTime(now); boolean res = wrkMastService.insert(wrkMast); @@ -419,98 +392,6 @@ return levCount < Integer.parseInt(config.getValue()); } /** * 获取穿梭车最近且空闲的提升机输送站点 */ public ForkLiftStaProtocol getRecentLiftSta(Integer shuttleNo, Integer targetLev) { //获取四向穿梭车线程 ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, shuttleNo); if (shuttleThread == null) { return null; } ShuttleProtocol shuttleProtocol = shuttleThread.getStatus(); if (shuttleProtocol == null) { return null; } List<DeviceConfig> forkliftList = deviceConfigService.selectList(new EntityWrapper<DeviceConfig>() .eq("device_type", String.valueOf(SlaveType.ForkLift))); //获取小车同一楼层的站点 ArrayList<ForkLiftStaProtocol> list = new ArrayList<>(); int lev = Utils.getLev(shuttleProtocol.getCurrentLocNo());//小车楼层 for (DeviceConfig device : forkliftList) { ForkLiftThread forkLiftThread = (ForkLiftThread) SlaveConnection.get(SlaveType.ForkLift, device.getDeviceNo()); if (forkLiftThread == null) { continue; } ForkLiftProtocol forkLiftProtocol = forkLiftThread.getStatus(); if (forkLiftProtocol == null) { continue; } if (!forkLiftThread.isIdle()) { continue; } ForkLiftStaProtocol forkLiftStaProtocol = ForkLiftUtils.getLiftStaByLev(device.getDeviceNo(), lev); if (forkLiftStaProtocol == null) { continue; } //判断当前层是否无托盘 if (forkLiftStaProtocol.getHasTray()) { continue; } if (forkLiftStaProtocol.getHasCar()) { continue; } //判断目标楼层站点是否无托盘 ForkLiftStaProtocol targetLiftStaProtocol = ForkLiftUtils.getLiftStaByLev(device.getDeviceNo(), targetLev); if (targetLiftStaProtocol == null) { continue; } if (targetLiftStaProtocol.getHasTray()) { continue;//有托盘跳过 } if (targetLiftStaProtocol.getHasCar()) { continue; } list.add(forkLiftStaProtocol); } if (list.isEmpty()) { return null; } String currentLocNo = shuttleProtocol.getCurrentLocNo();//小车位置 Integer recentAllDistance = 9999999; ForkLiftStaProtocol recentSta = null;//最近站点 //搜索距离小车最近的站点 for (ForkLiftStaProtocol forkLiftStaProtocol : list) { Integer staNo = forkLiftStaProtocol.getStaNo();//站点号 String locNo = forkLiftStaProtocol.getLocNo();//站点库位号 //当前穿梭车线程到目标地点距离 List<NavigateNode> currentShuttlePath = navigateUtils.calc(currentLocNo, locNo, NavigationMapType.getMapTypes(NavigationMapType.NORMAL), Utils.getShuttlePoints(shuttleNo, Utils.getLev(currentLocNo)), null);//使用正常通道地图 if (currentShuttlePath == null) { continue; } Integer currentAllDistance = navigateUtils.getOriginPathAllDistance(currentShuttlePath);//计算当前路径行走总距离 if (currentAllDistance < recentAllDistance) { //如果当前楼层的车路径更小,则更新最近站点 recentSta = forkLiftStaProtocol; recentAllDistance = currentAllDistance; } } return recentSta; } /** src/main/java/com/zy/core/enums/LiftDeviceStatusType.java
New file @@ -0,0 +1,42 @@ package com.zy.core.enums; public enum LiftDeviceStatusType { NONE(-1, "离线"), IDLE(0, "空闲"), BUSY(1, "忙碌"), WAITING(98, "等待确认"), ERROR(99, "故障"), ; public Integer id; public String desc; LiftDeviceStatusType(Integer id, String desc) { this.id = id; this.desc = desc; } public static LiftDeviceStatusType get(Integer id) { if (null == id) { return NONE; } for (LiftDeviceStatusType type : LiftDeviceStatusType.values()) { if (type.id.equals(id)) { return type; } } return NONE; } public static LiftDeviceStatusType get(LiftDeviceStatusType type) { if (null == type) { return NONE; } for (LiftDeviceStatusType type2 : LiftDeviceStatusType.values()) { if (type2 == type) { return type2; } } return NONE; } } src/main/java/com/zy/core/enums/WrkIoType.java
@@ -9,7 +9,7 @@ SHUTTLE_MOVE(200, "小车移动"), LOC_MOVE(201, "移库任务"), SHUTTLE_CHARGE(300, "小车充电"), FORKLIFT_MOVE(98, "提升机预调度移动任务"), PREVIEW_LIFT_MOVE(98, "提升机预调度移动任务"), MANUAL(99, "手动任务"), ; src/main/java/com/zy/core/model/protocol/LiftProtocol.java
@@ -39,12 +39,22 @@ /** * 任务状态 */ private Integer protocolStatus = LiftProtocolStatusType.NONE.id; private Integer protocolStatus = LiftProtocolStatusType.IDLE.id; /** * 任务状态枚举 */ private LiftProtocolStatusType protocolStatusType = LiftProtocolStatusType.NONE; private LiftProtocolStatusType protocolStatusType = LiftProtocolStatusType.IDLE; /** * 设备状态 */ private Integer deviceStatus = LiftDeviceStatusType.NONE.id; /** * 设备状态枚举 */ private LiftDeviceStatusType deviceStatusType = LiftDeviceStatusType.NONE; /** * 任务模式 @@ -222,6 +232,14 @@ return LiftProtocolStatusType.get(this.protocolStatus).desc; } public String getDeviceStatus$() { if (this.deviceStatus == null) { return ""; } return LiftDeviceStatusType.get(this.deviceStatus).desc; } public String getTaskMode$() { if (this.taskMode == null) { return ""; src/main/java/com/zy/core/thread/impl/NyLiftThread.java
@@ -160,7 +160,7 @@ if (null == liftProtocol) { liftProtocol = new LiftProtocol(); liftProtocol.setLiftNo(device.getDeviceNo()); liftProtocol.setProtocolStatus(LiftProtocolStatusType.NONE); liftProtocol.setProtocolStatus(LiftProtocolStatusType.IDLE); InnerLiftExtend innerLiftExtend = new InnerLiftExtend(); liftProtocol.setExtend(innerLiftExtend); @@ -171,8 +171,8 @@ liftProtocol.setModel(data.getInteger("model")); //PLC任务号 liftProtocol.setPlcTaskNo(data.getInteger("plcTaskNo")); //任务状态 liftProtocol.setProtocolStatus(data.getInteger("protocolStatus")); //设备状态 liftProtocol.setDeviceStatus(data.getInteger("deviceStatus")); //任务模式 liftProtocol.setTaskMode(data.getInteger("taskMode")); //取货数据 @@ -397,6 +397,8 @@ } this.liftProtocol.setSendTime(System.currentTimeMillis());//指令下发时间 this.setSyncTaskNo(0); this.setProtocolStatus(LiftProtocolStatusType.IDLE); response.setMessage(JSON.toJSONString(result)); response.setResult(true); return response; @@ -422,7 +424,7 @@ InnerLiftExtend extend = (InnerLiftExtend) this.liftProtocol.getExtend(); boolean res = this.liftProtocol.getProtocolStatus() == LiftProtocolStatusType.IDLE.id && this.liftProtocol.getPlcTaskNo() == 0 // && this.liftProtocol.getPlcTaskNo() == 0 && this.liftProtocol.getTaskNo() == 0 && this.liftProtocol.getModel() == 2 && this.liftProtocol.getErrorCode() == 0 src/main/webapp/views/lift.html
@@ -114,6 +114,7 @@ <th class="py-3 px-4">工作号</th> <th class="py-3 px-4">PLC工作号</th> <th class="py-3 px-4">设备模式</th> <th class="py-3 px-4">设备状态</th> <th class="py-3 px-4">任务状态</th> <th class="py-3 px-4">任务模式</th> <th class="py-3 px-4">取货数据</th> @@ -132,6 +133,7 @@ <td class="py-3 px-4">{{ item.taskNo }}</td> <td class="py-3 px-4">{{ item.plcTaskNo }}</td> <td class="py-3 px-4">{{ item.model$ }}</td> <td class="py-3 px-4">{{ item.deviceStatus$ }}</td> <td class="py-3 px-4">{{ item.protocolStatus$ }}</td> <td class="py-3 px-4">{{ item.taskMode$ }}</td> <td class="py-3 px-4">{{ item.pick }}</td>