package com.zy.asrs.wcs.core.action; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.zy.asrs.wcs.core.entity.BasShuttle; import com.zy.asrs.wcs.core.entity.Loc; import com.zy.asrs.wcs.core.entity.Task; import com.zy.asrs.wcs.core.model.NavigateNode; import com.zy.asrs.wcs.core.model.command.ShuttleAssignCommand; import com.zy.asrs.wcs.core.model.command.ShuttleCommand; import com.zy.asrs.wcs.core.model.command.ShuttleRedisCommand; import com.zy.asrs.wcs.core.model.enums.ShuttleCommandModeType; import com.zy.asrs.wcs.core.service.BasShuttleService; import com.zy.asrs.wcs.core.service.LocService; import com.zy.asrs.wcs.core.utils.NavigateMapUtils; import com.zy.asrs.wcs.core.utils.RedisUtil; import com.zy.asrs.wcs.core.utils.ShuttleDispatcher; import com.zy.asrs.wcs.core.utils.Utils; import com.zy.asrs.wcs.rcs.News; import com.zy.asrs.wcs.rcs.cache.SlaveConnection; import com.zy.asrs.wcs.rcs.constant.DeviceRedisConstant; import com.zy.asrs.wcs.rcs.entity.Device; import com.zy.asrs.wcs.rcs.model.enums.ShuttleProtocolStatusType; import com.zy.asrs.wcs.rcs.model.enums.SlaveType; import com.zy.asrs.wcs.rcs.model.protocol.ShuttleProtocol; import com.zy.asrs.wcs.rcs.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 ShuttleAction { @Autowired private RedisUtil redisUtil; @Autowired private NavigateMapUtils navigateMapUtils; @Autowired private BasShuttleService basShuttleService; @Autowired private LocService locService; @Autowired private ShuttleDispatcher shuttleDispatcher; public synchronized boolean assignWork(Device device, ShuttleAssignCommand assignCommand) { ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, device.getId().intValue()); if (shuttleThread == null) { return false; } ShuttleProtocol shuttleProtocol = shuttleThread.getStatus(); if (shuttleProtocol == null) { return false; } ShuttleRedisCommand redisCommand = new ShuttleRedisCommand(); redisCommand.setShuttleNo(assignCommand.getShuttleNo());//四向穿梭车号 redisCommand.setWrkNo(assignCommand.getTaskNo());//工作号 redisCommand.setCommandStep(0);//命令执行步序 redisCommand.setAssignCommand(assignCommand);//命令 //任务数据保存到redis if (redisUtil.set(DeviceRedisConstant.SHUTTLE_WORK_FLAG + assignCommand.getTaskNo(), JSON.toJSONString(redisCommand))) { //下发行驶路径 boolean result = shuttleThread.movePath(assignCommand.getNodes(), assignCommand.getTaskNo().intValue()); if (!result) { return false; } shuttleProtocol.setTaskNo(assignCommand.getTaskNo().intValue()); return true; } return false; } public synchronized boolean executeWork(Device device, Integer taskNo) { Object obj = redisUtil.get(DeviceRedisConstant.SHUTTLE_WORK_FLAG + taskNo); if (obj == null) { return false; } ShuttleRedisCommand redisCommand = JSON.parseObject(obj.toString(), ShuttleRedisCommand.class); if (redisCommand == null) { return false; } ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, device.getId().intValue()); if (shuttleThread == null) { return false; } ShuttleProtocol shuttleProtocol = shuttleThread.getStatus(); if (shuttleProtocol == null) { return false; } //判断设备是否空闲 if (!shuttleThread.isIdle()) { return false; } List commands = redisCommand.getAssignCommand().getCommands(); if (commands.isEmpty()) { return false; } ShuttleAssignCommand assignCommand = redisCommand.getAssignCommand(); int commandStep = redisCommand.getCommandStep(); // 完结上一条命令 if (commandStep != 0) { ShuttleCommand command = commands.get(commandStep - 1); if (command.getMode() == ShuttleCommandModeType.MOVE.id) { // 正常移动 if (command.getTargetLocNo().equals(shuttleProtocol.getCurrentLocNo())) { command.setComplete(true); //解锁锁定路径,上一条路径 List nodes = JSON.parseArray(JSON.toJSONString(command.getNodes()), NavigateNode.class);//进行深度copy if (nodes != null) { NavigateNode targetNode = assignCommand.getNodes().get(assignCommand.getNodes().size() - 1);//最终节点 NavigateNode node = nodes.get(nodes.size() - 1); if (!(targetNode.getX() == node.getX() && targetNode.getY() == node.getY())) { nodes.remove(nodes.size() - 1);//剔除尾节点 } boolean result = navigateMapUtils.writeNavigateNodeToRedisMap(Utils.getLev(shuttleProtocol.getCurrentLocNo()), shuttleProtocol.getShuttleNo(), nodes, false);//解锁路径 if (!result) { return false;//解锁失败 } } } } else if (command.getMode() == ShuttleCommandModeType.PALLET_LIFT.id) { // 托盘顶升 //判断是否顶升到位 if (shuttleProtocol.getHasLift()) { //判断是否有物 if (shuttleProtocol.getHasPallet()) { command.setComplete(true); } } } else if (command.getMode() == ShuttleCommandModeType.PALLET_DOWN.id) { // 托盘下降命令 // 判断是否下降到位 if (!shuttleProtocol.getHasLift()) { command.setComplete(true); } } else if (command.getMode() == ShuttleCommandModeType.CHARGE_OPEN.id) { // 充电开 //判断小车充电状态 if (shuttleProtocol.getHasCharge()) { command.setComplete(true); } }else { command.setComplete(true);//其他命令默认认为完成 } // 更新redis数据 redisUtil.set(DeviceRedisConstant.SHUTTLE_WORK_FLAG + redisCommand.getWrkNo(), JSON.toJSONString(redisCommand)); if (!command.getComplete()) { return false; } //判断是否为最后一条命令且命令执行完成,抛出等待确认状态 ShuttleCommand endCommand = commands.get(commands.size() - 1); if (endCommand.getComplete()) { News.info("四向穿梭车任务执行下发完成等待执行结束,穿梭车号={},任务数据={}", shuttleProtocol.getShuttleNo(), JSON.toJSON(commands)); // 系统任务 if (assignCommand.getAuto()) { if (!assignCommand.getCharge()) { //对主线程抛出等待确认状态waiting shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.WAITING); }else { shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.CHARGING_WAITING); } News.info("四向穿梭车任务执行下发完成等待执行结束,穿梭车号={},任务数据={}", shuttleProtocol.getShuttleNo(), JSON.toJSON(command)); // 手动任务 } else { //手动模式不抛出等待状态,直接复位空闲状态 shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.IDLE); //任务号清零 shuttleProtocol.setTaskNo(0); //标记复位 shuttleProtocol.setPakMk(true); News.info("四向穿梭车手动任务执行完成,穿梭车号={},任务数据={}", shuttleProtocol.getShuttleNo(), JSON.toJSON(command)); } //删除redis redisUtil.del(DeviceRedisConstant.SHUTTLE_WORK_FLAG + redisCommand.getWrkNo()); return false;//禁止再下发命令 } } //取出命令 ShuttleCommand command = commands.get(commandStep); // 下发命令 if (!write(command, device)) { News.error("四向穿梭车命令下发失败,穿梭车号={},任务数据={}", shuttleProtocol.getShuttleNo(), JSON.toJSON(command)); return false; } return true; } //跑库程序 public synchronized void moveLoc(Device device) { ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, device.getId().intValue()); if (shuttleThread == null) { return; } ShuttleProtocol shuttleProtocol = shuttleThread.getStatus(); if (shuttleProtocol == null) { return; } //小车空闲且有跑库程序 if (!(shuttleThread.isIdle() && shuttleProtocol.getMoveLoc())) { return; } int lev = Utils.getLev(shuttleProtocol.getCurrentLocNo());//小车当前楼层 if (shuttleProtocol.getYCurrent() > shuttleProtocol.getYTarget()) { //跑库结束 shuttleProtocol.setMoveLoc(false); shuttleProtocol.setMoveType(0); shuttleProtocol.setXStart(0); shuttleProtocol.setXTarget(0); shuttleProtocol.setXCurrent(0); shuttleProtocol.setYStart(0); shuttleProtocol.setYTarget(0); shuttleProtocol.setYCurrent(0); return; } if (shuttleProtocol.getMoveType() == 0) {//跑轨道 ArrayList locs = new ArrayList<>(); for (int i = shuttleProtocol.getXCurrent(); i <= shuttleProtocol.getXTarget(); i++) { String locNo = Utils.getLocNo(i, shuttleProtocol.getYCurrent(), lev); locs.add(locNo); } List locList = locService.list(new LambdaQueryWrapper() .in(Loc::getLocNo, locs)); if (locList.isEmpty()) { //空库位 shuttleProtocol.setYCurrent(shuttleProtocol.getYCurrent() + 1); return; } Loc start = locList.get(0); Loc target = locList.get(locList.size() - 1); //判断小车是否在起点位置 if (!shuttleProtocol.getCurrentLocNo().equals(start.getLocNo())) {//不在起点位置,调度去起点位置 shuttleDispatcher.generateMoveTask(device, start.getLocNo()); }else { //在起点位置,调度去目标位置 if (shuttleProtocol.getCurrentLocNo().equals(target.getLocNo())) { shuttleProtocol.setYCurrent(shuttleProtocol.getYCurrent() + 1);//小车和目标位置一致,跳过 }else { shuttleDispatcher.generateMoveTask(device, start.getLocNo()); shuttleProtocol.setYCurrent(shuttleProtocol.getYCurrent() + 1); } } } else if (shuttleProtocol.getMoveType() == 1) {//跑库位 Integer xCurrent = shuttleProtocol.getXCurrent(); if (xCurrent > shuttleProtocol.getXTarget()) {//当X值大于X目标值,进行归零且Y方向+1 shuttleProtocol.setXCurrent(shuttleProtocol.getXStart()); shuttleProtocol.setYCurrent(shuttleProtocol.getYCurrent() + 1); return; } Integer yCurrent = shuttleProtocol.getYCurrent(); String locNo = Utils.getLocNo(xCurrent, yCurrent, lev); Loc target = locService.getOne(new LambdaQueryWrapper() .eq(Loc::getLocNo, locNo) .eq(Loc::getHostId, device.getHostId())); if (target == null) { shuttleProtocol.setXCurrent(shuttleProtocol.getXCurrent() + 1); return; } // if (!target.getLocSts().equals("O")) { // shuttleProtocol.setXCurrent(shuttleProtocol.getXCurrent() + 1); // return; // } //调度去目标位置 if (shuttleProtocol.getCurrentLocNo().equals(target.getLocNo())) { shuttleProtocol.setXCurrent(shuttleProtocol.getXCurrent() + 1);//小车和目标位置一致,跳过 } else { shuttleDispatcher.generateMoveTask(device, target.getLocNo()); shuttleProtocol.setXCurrent(shuttleProtocol.getXCurrent() + 1); } } else if (shuttleProtocol.getMoveType() == 2) {//母轨道循环跑 Integer xCurrent = shuttleProtocol.getXCurrent(); Integer yCurrent = shuttleProtocol.getYCurrent(); String locNo = Utils.getLocNo(xCurrent, yCurrent, lev); //调度去目标位置 if (shuttleProtocol.getCurrentLocNo().equals(locNo)) { if (yCurrent.equals(shuttleProtocol.getYStart())) { shuttleProtocol.setYCurrent(shuttleProtocol.getYTarget());//小车和目标位置一致,切换库位 } else { shuttleProtocol.setYCurrent(shuttleProtocol.getYStart());//小车和目标位置一致,切换库位 } } else { Task result = shuttleDispatcher.generateMoveTask(device, locNo); if (result != null) {//调度成功 if (yCurrent.equals(shuttleProtocol.getYStart())) { shuttleProtocol.setYCurrent(shuttleProtocol.getYTarget());//切换库位 } else { shuttleProtocol.setYCurrent(shuttleProtocol.getYStart());//切换库位 } } } } else if (shuttleProtocol.getMoveType() == 3) {//子轨道循环跑 Integer xCurrent = shuttleProtocol.getXCurrent(); Integer yCurrent = shuttleProtocol.getYCurrent(); String locNo = Utils.getLocNo(xCurrent, yCurrent, lev); //调度去目标位置 if (shuttleProtocol.getCurrentLocNo().equals(locNo)) { if (xCurrent.equals(shuttleProtocol.getXStart())) { shuttleProtocol.setXCurrent(shuttleProtocol.getXTarget());//小车和目标位置一致,切换库位 } else { shuttleProtocol.setXCurrent(shuttleProtocol.getXStart());//小车和目标位置一致,切换库位 } } else { Task result = shuttleDispatcher.generateMoveTask(device, locNo); if (result != null) {//调度成功 if (xCurrent.equals(shuttleProtocol.getXStart())) { shuttleProtocol.setXCurrent(shuttleProtocol.getXTarget());//切换库位 } else { shuttleProtocol.setXCurrent(shuttleProtocol.getXStart());//切换库位 } } } } } private synchronized boolean write(ShuttleCommand command, Device device) { if (null == command) { News.error("四向穿梭车写入命令为空"); return false; } ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, device.getId().intValue()); boolean result = false; if (command.getMode() == ShuttleCommandModeType.MOVE.id || command.getMode() == ShuttleCommandModeType.IN_LIFT.id || command.getMode() == ShuttleCommandModeType.OUT_LIFT.id) {//移动 result = shuttleThread.move(command); } else if (command.getMode() == ShuttleCommandModeType.PALLET_LIFT.id || command.getMode() == ShuttleCommandModeType.PALLET_DOWN.id) {//顶升 result = shuttleThread.lift(command); } else if (command.getMode() == ShuttleCommandModeType.CHARGE_OPEN.id || command.getMode() == ShuttleCommandModeType.CHARGE_CLOSE.id) {//充电 result = shuttleThread.charge(command); } else if (command.getMode() == ShuttleCommandModeType.RESET.id) {//复位 result = shuttleThread.reset(command); } return result; } }