package com.zy.core.action; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.serializer.SerializerFeature; import com.baomidou.mybatisplus.mapper.EntityWrapper; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import com.zy.asrs.domain.param.CreateLocMoveTaskParam; import com.zy.asrs.entity.BasShuttleOpt; import com.zy.asrs.entity.LocMast; import com.zy.asrs.entity.WrkMast; import com.zy.asrs.service.BasShuttleOptService; import com.zy.asrs.service.LocMastService; import com.zy.asrs.service.WrkMastService; import com.zy.asrs.utils.Utils; import com.zy.common.model.NavigateNode; import com.zy.common.service.CommonService; import com.zy.common.utils.NavigateMapUtils; import com.zy.common.utils.RedisUtil; import com.zy.core.News; import com.zy.core.cache.SlaveConnection; import com.zy.core.dispatcher.ShuttleDispatchUtils; import com.zy.core.enums.*; import com.zy.core.model.CommandResponse; import com.zy.core.model.TrafficControlDataModel; import com.zy.core.model.command.ShuttleAssignCommand; import com.zy.core.model.command.ShuttleCommand; import com.zy.core.model.command.ShuttleRedisCommand; import com.zy.core.model.protocol.ShuttleProtocol; import com.zy.core.thread.ShuttleThread; import com.zy.core.thread.TrafficControlThread; import com.zy.system.entity.Config; import com.zy.system.service.ConfigService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.io.IOException; import java.util.*; @Component public class ShuttleAction { @Autowired private RedisUtil redisUtil; @Autowired private NavigateMapUtils navigateMapUtils; @Autowired private LocMastService locMastService; @Autowired private ObjectMapper objectMapper; @Autowired private ConfigService configService; @Autowired private BasShuttleOptService basShuttleOptService; @Autowired private WrkMastService wrkMastService; @Autowired private ShuttleDispatchUtils shuttleDispatchUtils; @Autowired private CommonService commonService; public synchronized boolean assignWork(Integer shuttleNo, ShuttleAssignCommand assignCommand) { ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, shuttleNo); if (shuttleThread == null) { return false; } TrafficControlThread trafficControlThread = (TrafficControlThread) SlaveConnection.get(SlaveType.TrafficControl, 1); if(trafficControlThread == null){ return false; } //Clear Traffic Control trafficControlThread.forceCancelTrafficControl(shuttleNo); ShuttleRedisCommand redisCommand = new ShuttleRedisCommand(); redisCommand.setShuttleNo(assignCommand.getShuttleNo());//四向穿梭车号 redisCommand.setWrkNo(assignCommand.getTaskNo());//工作号 redisCommand.setCommandStep(0);//命令执行步序 redisCommand.setAssignCommand(assignCommand);//命令 //任务数据保存到redis if (redisUtil.set(RedisKeyType.SHUTTLE_WORK_FLAG.key + assignCommand.getTaskNo(), JSON.toJSONString(redisCommand, SerializerFeature.DisableCircularReferenceDetect))) { shuttleThread.setSyncTaskNo(assignCommand.getTaskNo()); return true; } return false; } public boolean executeWork(Integer shuttleNo, Integer taskNo) { Object obj = redisUtil.get(RedisKeyType.SHUTTLE_WORK_FLAG.key + taskNo); if (obj == null) { return false; } ShuttleRedisCommand redisCommand = null; try { redisCommand = objectMapper.readValue(String.valueOf(obj), ShuttleRedisCommand.class); } catch (IOException e) { throw new RuntimeException(e); } if (redisCommand == null) { return false; } ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, shuttleNo); if (shuttleThread == null) { return false; } ShuttleProtocol shuttleProtocol = shuttleThread.getStatus(); if (shuttleProtocol == null) { return false; } //判断工作号是否相同 if (!shuttleProtocol.getTaskNo().equals(taskNo)) { return false; } News.info("[RCS Debug] Execute check command {},{}", shuttleNo, taskNo); //检测命令 ShuttleCheckCommandResultType checked = checkCommand(redisCommand, shuttleNo); News.info("[RCS Debug] Execute check command complete {},{}", shuttleNo, taskNo); if (checked.equals(ShuttleCheckCommandResultType.FAIL)) { return false; } ShuttleAssignCommand assignCommand = redisCommand.getAssignCommand(); List commands = assignCommand.getCommands(); if (commands.isEmpty()) { return false; } int commandStep = redisCommand.getCommandStep(); if(commandStep >= commands.size()){ return false; } //取出命令 ShuttleCommand command = null; if (checked.equals(ShuttleCheckCommandResultType.SUCCESS)) { //非连续指令,需要检测上一条指令是否完成 if (commandStep > 0) { ShuttleCommand lastCommand = commands.get(commandStep - 1); if (!lastCommand.getComplete()) { return false;//指令未完成 } } command = commands.get(commandStep); } else if (checked.equals(ShuttleCheckCommandResultType.SUCCESS_GO)) { //连续指令直接取数据 command = commands.get(commandStep); } if(command == null){ return false; } //移动命令,锁定路径 if (command.getMode() == ShuttleCommandModeType.MOVE.id) { TrafficControlThread trafficControlThread = (TrafficControlThread) SlaveConnection.get(SlaveType.TrafficControl, 1); if (trafficControlThread == null) { return false; } List nodes = JSON.parseArray(JSON.toJSONString(command.getNodes()), NavigateNode.class); Object object = redisUtil.get(RedisKeyType.TRAFFIC_CONTROL_LOCK_APPLY.key + shuttleNo); if (object == null) { //申请管制 News.info("[RCS Debug] Execute apply control {},{}", shuttleNo, taskNo); redisUtil.set(RedisKeyType.TRAFFIC_CONTROL_LOCK_APPLY.key + shuttleNo, "lock", 10); applyTrafficControl(commands, nodes, shuttleNo, taskNo); News.info("[RCS Debug] Execute apply control complete {},{}", shuttleNo, taskNo); } News.info("[RCS Debug] Execute query control {},{}", shuttleNo, taskNo); //查询管制 boolean apply = queryTrafficControl(shuttleNo, taskNo); News.info("[RCS Debug] Execute query control complete {},{}", shuttleNo, taskNo); if(!apply){ return false;//申请失败 } if (checked.equals(ShuttleCheckCommandResultType.SUCCESS_GO)) { nodes.remove(0); } boolean result = navigateMapUtils.writeNavigateNodeToRedisMap(Utils.getLev(command.getTargetLocNo()), shuttleNo, nodes, true);//锁定路径 if (!result) { News.error("{} device can't lock path!", shuttleNo); shuttleThread.offerSystemMsg("{} device can't lock path!", shuttleNo); trafficControlThread.trafficReportError(shuttleNo, taskNo); return false;//路径锁定失败 } } News.info("[RCS Debug] Execute send command {},{}", shuttleNo, taskNo); // 下发命令 CommandResponse response = write(command, shuttleNo); News.info("[RCS Debug] Execute send command complete {},{}", shuttleNo, taskNo); //保存命令日志 BasShuttleOpt basShuttleOpt = new BasShuttleOpt(); basShuttleOpt.setWrkNo(redisCommand.getWrkNo()); basShuttleOpt.setShuttleNo(shuttleNo); basShuttleOpt.setMode(ShuttleTaskModeType.get(assignCommand.getTaskMode()).desc); basShuttleOpt.setSourceLocNo(assignCommand.getSourceLocNo()); basShuttleOpt.setDistLocNo(assignCommand.getLocNo()); basShuttleOpt.setCommand(JSON.toJSONString(command)); basShuttleOpt.setSystemStatus(JSON.toJSONString(shuttleProtocol)); basShuttleOpt.setDeviceWrk(String.valueOf(command.getTaskNo())); basShuttleOpt.setResponse(response.getMessage());//获取响应 basShuttleOpt.setSendTime(new Date());//指令下发时间 basShuttleOpt.setSend(response.getResult() ? 1 : 0); //保存命令流水 basShuttleOptService.insert(basShuttleOpt); if (!response.getResult()) { News.error("四向穿梭车命令下发失败,穿梭车号={},任务数据={}", shuttleProtocol.getShuttleNo(), JSON.toJSON(command)); return false; } shuttleThread.setProtocolStatus(ShuttleProtocolStatusType.WORKING); commandStep += 1; //更新redis数据 redisCommand.setCommandStep(commandStep); //任务数据保存到redis redisUtil.set(RedisKeyType.SHUTTLE_WORK_FLAG.key + redisCommand.getWrkNo(), JSON.toJSONString(redisCommand)); return true; } /** * 检测命令 * 0:未通过 1:通过 2:通过且可提前下发指令 */ private ShuttleCheckCommandResultType checkCommand(ShuttleRedisCommand redisCommand, Integer shuttleNo) { TrafficControlThread trafficControlThread = (TrafficControlThread) SlaveConnection.get(SlaveType.TrafficControl, 1); if(trafficControlThread == null){ return ShuttleCheckCommandResultType.FAIL; } ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, shuttleNo); if (shuttleThread == null) { return ShuttleCheckCommandResultType.FAIL; } ShuttleProtocol shuttleProtocol = shuttleThread.getStatus(); if (shuttleProtocol == null) { return ShuttleCheckCommandResultType.FAIL; } int commandStep = redisCommand.getCommandStep(); if (commandStep == 0) { return ShuttleCheckCommandResultType.SUCCESS;//第一条命令无需检测 } ShuttleAssignCommand assignCommand = redisCommand.getAssignCommand(); List commands = assignCommand.getCommands(); if (commands.isEmpty()) { return ShuttleCheckCommandResultType.FAIL; } boolean supportContinuously = false; int checkIdx = commandStep - 2; if (checkIdx < 0) { supportContinuously = true; checkIdx = commandStep - 1; } ShuttleCommand last2Command = commands.get(checkIdx); if(last2Command.getComplete()){ supportContinuously = true; checkIdx = commandStep - 1; } ShuttleCommand lastCommand = commands.get(checkIdx); if (!lastCommand.getComplete()) { //检测更新命令完成 boolean checked = updateCommandComplete(checkIdx, commands, shuttleNo); if (checked) { // 更新redis数据 redisUtil.set(RedisKeyType.SHUTTLE_WORK_FLAG.key + redisCommand.getWrkNo(), JSON.toJSONString(redisCommand, SerializerFeature.DisableCircularReferenceDetect)); }else { //小车移动连续下发指令 if (assignCommand.getShuttleMoveCommandsContinuously()) { if (!supportContinuously) { return ShuttleCheckCommandResultType.FAIL; } //移动指令 if(lastCommand.getMode() != ShuttleCommandModeType.MOVE.id) { return ShuttleCheckCommandResultType.FAIL; } List nodes = lastCommand.getNodes(); NavigateNode startNode = nodes.get(0); if (!startNode.getLinePartAllowGo()) {//直线段部分,允许直接行走 return ShuttleCheckCommandResultType.FAIL; } //直线段数据标识 Long linePartFlag = startNode.getLinePartFlag(); if(commandStep < commands.size()){ //取指令 ShuttleCommand currentCommand = commands.get(commandStep); if(currentCommand.getMode() != ShuttleCommandModeType.MOVE.id) { return ShuttleCheckCommandResultType.FAIL; } List currentNodes = currentCommand.getNodes(); NavigateNode currentStartNode = currentNodes.get(0); if(!currentStartNode.getLinePartAllowGo()) {//直线段部分,允许直接行走 return ShuttleCheckCommandResultType.FAIL; } if(currentStartNode.getLinePartFlag().equals(linePartFlag)) { //数据标识一致 return ShuttleCheckCommandResultType.SUCCESS_GO;//允许小车移动连续下发指令 } } } return ShuttleCheckCommandResultType.FAIL; } } //判断是否为最后一条命令且命令执行完成,抛出等待确认状态 ShuttleCommand endCommand = commands.get(commands.size() - 1); if (endCommand.getComplete()) { News.info("四向穿梭车任务执行下发完成等待执行结束,穿梭车号={},任务数据={}", shuttleProtocol.getShuttleNo(), JSON.toJSON(commands)); // 系统任务 if (assignCommand.getAuto()) { if (assignCommand.getTaskMode() == ShuttleTaskModeType.UPDATE_LOCATION.id) {//更新坐标无需等待确认 //直接复位空闲状态 shuttleThread.setProtocolStatus(ShuttleProtocolStatusType.IDLE); //任务号清零 shuttleThread.setSyncTaskNo(0); //标记复位 shuttleThread.setPakMk(true); News.info("四向穿梭车更新坐标任务执行完成,穿梭车号={},任务数据={}", shuttleProtocol.getShuttleNo(), JSON.toJSON(endCommand)); }else { if (!assignCommand.getCharge()) { //对主线程抛出等待确认状态waiting shuttleThread.setProtocolStatus(ShuttleProtocolStatusType.WAITING); } else { shuttleThread.setProtocolStatus(ShuttleProtocolStatusType.CHARGING_WAITING); } News.info("四向穿梭车任务执行下发完成等待执行结束,穿梭车号={},任务数据={}", shuttleProtocol.getShuttleNo(), JSON.toJSON(endCommand)); } } else {// 手动任务 //手动模式不抛出等待状态,直接复位空闲状态 shuttleThread.setProtocolStatus(ShuttleProtocolStatusType.IDLE); //任务号清零 shuttleThread.setSyncTaskNo(0); //标记复位 shuttleThread.setPakMk(true); News.info("四向穿梭车手动任务执行完成,穿梭车号={},任务数据={}", shuttleProtocol.getShuttleNo(), JSON.toJSON(endCommand)); } //申请取消管制 cancelTrafficControl(shuttleNo, shuttleProtocol.getTaskNo()); //删除redis redisUtil.del(RedisKeyType.SHUTTLE_WORK_FLAG.key + redisCommand.getWrkNo()); return ShuttleCheckCommandResultType.FAIL;//禁止再下发命令 } return ShuttleCheckCommandResultType.SUCCESS; } //检测更新命令完成 private boolean updateCommandComplete(Integer commandIdx, List commands, Integer shuttleNo) { ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, shuttleNo); if (shuttleThread == null) { return false; } ShuttleProtocol shuttleProtocol = shuttleThread.getStatus(); if (shuttleProtocol == null) { return false; } //判断设备是否空闲 boolean deviceIdle = shuttleThread.isDeviceIdle(); ShuttleCommand command = commands.get(commandIdx); if (command.getMode() == ShuttleCommandModeType.MOVE.id) { // 正常移动 List targetPoints = new ArrayList<>(); //解锁锁定路径,上一条路径 List nodes = null; try { String nodesStr = objectMapper.writeValueAsString(command.getNodes()); nodes = objectMapper.readValue(nodesStr, new TypeReference>() { }); } catch (IOException e) { throw new RuntimeException(e); } NavigateNode startNode = nodes.get(0); Long linePartFlag = startNode.getLinePartFlag(); NavigateNode targetNode = nodes.get(nodes.size() - 1); targetPoints.add(targetNode.getX() + "-" + targetNode.getY()); for (int i = commandIdx + 1; i < commands.size(); i++) { ShuttleCommand nextCommand = commands.get(i); if (nextCommand.getMode() == ShuttleCommandModeType.MOVE.id) { List nextCommandNodes = nextCommand.getNodes(); NavigateNode nextStartNode = nextCommandNodes.get(0); Long nextLinePartFlag = nextStartNode.getLinePartFlag(); if(nextLinePartFlag.equals(linePartFlag)) { for (NavigateNode node : nextCommandNodes) { String key = node.getX() + "-" + node.getY(); if(!targetPoints.contains(key)) { targetPoints.add(key); } } } } } TrafficControlThread trafficControlThread = (TrafficControlThread) SlaveConnection.get(SlaveType.TrafficControl, 1); if (trafficControlThread == null) { return false; } //上报交管 News.info("[RCS Debug] Execute check command report traffic {},{}", shuttleNo, shuttleProtocol.getTaskNo()); trafficControlThread.trafficReport(command.getNodesDeepCopy(), shuttleNo, shuttleProtocol.getTaskNo()); News.info("[RCS Debug] Execute check command report traffic complete {},{}", shuttleNo, shuttleProtocol.getTaskNo()); String currentLocNo = shuttleProtocol.getCurrentLocNo(); if (currentLocNo == null) { return false; } if (targetPoints.contains(Utils.getRow(currentLocNo) + "-" + Utils.getBay(currentLocNo))) { boolean result = navigateMapUtils.writeNavigateNodeToRedisMap(Utils.getLev(shuttleProtocol.getCurrentLocNo()), shuttleProtocol.getShuttleNo(), nodes, false);//解锁路径 if (!result) { return false;//解锁失败 } command.setComplete(true); }else { return false; } } else if (command.getMode() == ShuttleCommandModeType.PALLET_LIFT.id) { // 托盘顶升 if (!deviceIdle) { return false;//设备不空闲 } //判断是否顶升到位 if (shuttleProtocol.getHasLift()) { command.setComplete(true); // //判断是否有物 // if (shuttleProtocol.getHasPallet()) { // command.setComplete(true); // } }else { return false; } } else if (command.getMode() == ShuttleCommandModeType.PALLET_DOWN.id) { // 托盘下降命令 if (!deviceIdle) { return false;//设备不空闲 } // 判断是否下降到位 if (!shuttleProtocol.getHasLift()) { command.setComplete(true); }else { return false; } } else if (command.getMode() == ShuttleCommandModeType.CHARGE_OPEN.id) { // 充电开 //判断小车充电状态 if (shuttleProtocol.getHasCharge()) { command.setComplete(true); }else { return false; } } else if (command.getMode() == ShuttleCommandModeType.CHARGE_CLOSE.id) { //关闭充电 command.setComplete(true); } else { command.setComplete(true);//其他命令默认认为完成 } return true; } //申请管制 public boolean applyTrafficControl(List commands, List nodeList, Integer shuttleNo, Integer taskNo) { TrafficControlThread trafficControlThread = (TrafficControlThread) SlaveConnection.get(SlaveType.TrafficControl, 1); if (trafficControlThread == null) { return false; } List totalNodeList = new ArrayList<>(); for (ShuttleCommand command : commands) { if (command.getMode() == ShuttleCommandModeType.MOVE.id) { List deepCopy = command.getNodesDeepCopy(); if (deepCopy != null) { totalNodeList.addAll(deepCopy); } } } return trafficControlThread.applyTrafficControl(totalNodeList, nodeList, shuttleNo, taskNo); } //查询是否申请管制成功 public boolean queryTrafficControl(Integer shuttleNo, Integer taskNo) { Object object = redisUtil.get(RedisKeyType.TRAFFIC_CONTROL_SUCCESS_APPLY.key + shuttleNo + "_" + taskNo); if (object == null) { return false; } return true; } public boolean cancelTrafficControl(Integer shuttleNo, Integer taskNo) { TrafficControlDataModel model = new TrafficControlDataModel(); model.setShuttleNo(shuttleNo); model.setTaskNo(taskNo); redisUtil.set(RedisKeyType.TRAFFIC_CONTROL_CANCEL_LIST.key + shuttleNo + "_" + taskNo, model); return true; } //演示模式 public synchronized void demo(Integer shuttleNo) { ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, shuttleNo); if (shuttleThread == null) { return; } ShuttleProtocol shuttleProtocol = shuttleThread.getStatus(); if (shuttleProtocol == null) { return; } if (!shuttleProtocol.getDemo()) { return; } WrkMast moveWorking = wrkMastService.selectShuttleHasMoveWorking(shuttleNo); if (moveWorking != null) { return; } WrkMast shuttleWorking = wrkMastService.selectShuttleWorking(shuttleNo); if(shuttleWorking != null) { return; } WrkMast chargeWorking = wrkMastService.selectChargeWorking(shuttleNo); if (chargeWorking != null) { return; } if (!shuttleThread.isRequireCharge().equals(ShuttleRequireChargeType.NONE)) { return; } if (!shuttleThread.isIdle()) { return; } boolean demoSwitchLev = false; Config demoSwitchLevConfig = configService.selectOne(new EntityWrapper().eq("code", "demoSwitchLev")); if (demoSwitchLevConfig != null) { if (demoSwitchLevConfig.getValue().equals("Y")) { demoSwitchLev = true; } } Config demoRunLevConfig = configService.selectOne(new EntityWrapper().eq("code", "demoRunLev")); if (demoRunLevConfig == null) { return; } List levList = JSON.parseArray(demoRunLevConfig.getValue(), Integer.class); if (!demoSwitchLev) { String currentLocNo = shuttleProtocol.getCurrentLocNo(); levList = new ArrayList<>(); levList.add(Utils.getLev(currentLocNo)); } LocMast targetLoc = null; EntityWrapper wrapper = new EntityWrapper<>(); wrapper.in("lev1", levList); wrapper.eq("loc_sts", "O"); wrapper.last("ORDER BY RAND() LIMIT 1"); for (int i = 0; i < 3; i++) { LocMast locMast = locMastService.selectOne(wrapper); if(locMast == null) { continue; } ArrayList locs = new ArrayList<>(); locs.add(locMast.getLocNo()); Integer shuttle = Utils.checkGroupLocHasShuttle(locs); if(shuttle != null) { continue; } targetLoc = locMast; break; } if(targetLoc == null) { return; } shuttleDispatchUtils.dispatchShuttle(null, targetLoc.getLocNo(), shuttleProtocol.getShuttleNo()); } public synchronized void demoModeCargoMove() { Config demoCargoMoveConfig = configService.selectOne(new EntityWrapper().eq("code", "demoCargoMove")); if (demoCargoMoveConfig == null) { return; } if (!demoCargoMoveConfig.getValue().equals("Y")) { return; } Config demoRunLevConfig = configService.selectOne(new EntityWrapper().eq("code", "demoRunLev")); if (demoRunLevConfig == null) { return; } List levList = JSON.parseArray(demoRunLevConfig.getValue(), Integer.class); Random random = new Random(); int index = random.nextInt(levList.size()); Integer lev = levList.get(index); //获取楼层小车数量 int shuttleCountByLev = shuttleDispatchUtils.getShuttleCountByLev(lev); //获取楼层货物搬运任务 int currentLevTask = 0; for (WrkMast wrkMast : wrkMastService.selectList(new EntityWrapper().eq("io_type", WrkIoType.LOC_MOVE.id))) { if (Utils.getLev(wrkMast.getLocNo()) == lev) { currentLevTask += 1; } } //搬运任务数量超过小车数量,暂时不生成新任务 if (currentLevTask > shuttleCountByLev) { return; } LocMast sourceLoc = null; EntityWrapper wrapper = new EntityWrapper<>(); wrapper.eq("lev1", lev); wrapper.eq("loc_sts", "F"); wrapper.last("ORDER BY RAND() LIMIT 1"); for (int i = 0; i < 3; i++) { LocMast locMast = locMastService.selectOne(wrapper); if(locMast == null) { continue; } sourceLoc = locMast; break; } if(sourceLoc == null) { return; } LocMast targetLoc = null; EntityWrapper targetWrapper = new EntityWrapper<>(); targetWrapper.eq("lev1", lev); targetWrapper.eq("loc_sts", "O"); targetWrapper.last("ORDER BY RAND() LIMIT 1"); for (int i = 0; i < 3; i++) { LocMast locMast = locMastService.selectOne(targetWrapper); if(locMast == null) { continue; } targetLoc = locMast; break; } if(targetLoc == null) { return; } try { CreateLocMoveTaskParam param = new CreateLocMoveTaskParam(); param.setSourceLocNo(sourceLoc.getLocNo()); param.setLocNo(targetLoc.getLocNo()); param.setTaskPri(13); boolean result = commonService.createLocMoveTask(param); } catch (Exception e) { e.printStackTrace(); } } public synchronized void demoModeRunLoc(Integer shuttleNo) { Config demoModeRunLocConfig = configService.selectOne(new EntityWrapper().eq("code", "demoModeRunLoc")); if (demoModeRunLocConfig == null) { return; } if (!demoModeRunLocConfig.getValue().equals("Y")) { return; } ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, shuttleNo); if (shuttleThread == null) { return; } ShuttleProtocol shuttleProtocol = shuttleThread.getStatus(); if (shuttleProtocol == null) { return; } if (!shuttleThread.isIdle()) { return; } LocMast targetLoc = null; EntityWrapper wrapper = new EntityWrapper<>(); wrapper.eq("lev1", Utils.getLev(shuttleProtocol.getCurrentLocNo())); wrapper.notIn("loc_sts", "X"); wrapper.isNull("loc_type"); wrapper.last("ORDER BY RAND() LIMIT 1"); for (int i = 0; i < 3; i++) { LocMast locMast = locMastService.selectOne(wrapper); if(locMast == null) { continue; } targetLoc = locMast; break; } if(targetLoc == null) { return; } boolean result = shuttleDispatchUtils.dispatchShuttle(null, targetLoc.getLocNo(), shuttleProtocol.getShuttleNo()); if (result) { targetLoc.setLocType("Y"); locMastService.updateById(targetLoc); } } public synchronized boolean clearPath(Integer shuttleNo) { return navigateMapUtils.clearPath(shuttleNo); } private CommandResponse write(ShuttleCommand command, Integer shuttleNo) { CommandResponse response = new CommandResponse(false); if (null == command) { News.error("四向穿梭车写入命令为空"); response.setMessage("四向穿梭车写入命令为空"); return response; } ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, shuttleNo); if (command.getMode() == ShuttleCommandModeType.MOVE.id || command.getMode() == ShuttleCommandModeType.IN_LIFT.id || command.getMode() == ShuttleCommandModeType.OUT_LIFT.id) {//移动 response = shuttleThread.move(command); } else if (command.getMode() == ShuttleCommandModeType.PALLET_LIFT.id || command.getMode() == ShuttleCommandModeType.PALLET_DOWN.id) {//顶升 response = shuttleThread.lift(command); } else if (command.getMode() == ShuttleCommandModeType.CHARGE_OPEN.id || command.getMode() == ShuttleCommandModeType.CHARGE_CLOSE.id) {//充电 response = shuttleThread.charge(command); } else if (command.getMode() == ShuttleCommandModeType.RESET.id) {//复位 response = shuttleThread.reset(command); } else if (command.getMode() == ShuttleCommandModeType.UPDATE_LOCATION.id) {//更新坐标 response = shuttleThread.updateLocation(command); } News.info("四向穿梭车命令下发,穿梭车号={},任务数据={}", shuttleNo, JSON.toJSON(command)); return response; } }