#
Junjie
2024-06-12 848b1bc9331722a43b062b6bfb013b7e1804b7f4
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/action/ShuttleAction.java
@@ -1,17 +1,25 @@
package com.zy.asrs.wcs.core.action;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.zy.asrs.wcs.core.entity.BasShuttle;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zy.asrs.wcs.common.ExecuteSupport;
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.LocStsType;
import com.zy.asrs.wcs.core.model.enums.MotionCtgType;
import com.zy.asrs.wcs.core.model.enums.ShuttleCommandModeType;
import com.zy.asrs.wcs.core.model.enums.ShuttleTaskModeType;
import com.zy.asrs.wcs.core.service.BasShuttleService;
import com.zy.asrs.wcs.core.utils.NavigateMapUtils;
import com.zy.asrs.wcs.core.utils.RedisUtil;
import com.zy.asrs.wcs.core.utils.Utils;
import com.zy.asrs.wcs.core.service.LocService;
import com.zy.asrs.wcs.core.utils.*;
import com.zy.asrs.wcs.rcs.News;
import com.zy.asrs.wcs.rcs.cache.SlaveConnection;
import com.zy.asrs.wcs.rcs.constant.DeviceRedisConstant;
@@ -20,10 +28,14 @@
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 com.zy.asrs.wcs.system.entity.Dict;
import com.zy.asrs.wcs.system.service.DictService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
@Component
public class ShuttleAction {
@@ -34,6 +46,16 @@
    private NavigateMapUtils navigateMapUtils;
    @Autowired
    private BasShuttleService basShuttleService;
    @Autowired
    private LocService locService;
    @Autowired
    private ShuttleDispatcher shuttleDispatcher;
    @Autowired
    private ObjectMapper objectMapper;
    @Autowired
    private DictService dictService;
    @Autowired
    private ConveyorDispatcher conveyorDispatcher;
    public synchronized boolean assignWork(Device device, ShuttleAssignCommand assignCommand) {
        ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, device.getId().intValue());
@@ -49,17 +71,22 @@
        ShuttleRedisCommand redisCommand = new ShuttleRedisCommand();
        redisCommand.setShuttleNo(assignCommand.getShuttleNo());//四向穿梭车号
        redisCommand.setWrkNo(assignCommand.getTaskNo());//工作号
        redisCommand.setTaskNo(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;
        if (redisUtil.set(DeviceRedisConstant.SHUTTLE_WORK_FLAG + assignCommand.getTaskNo(), JSON.toJSONString(redisCommand, SerializerFeature.DisableCircularReferenceDetect))) {
            if (assignCommand.getTaskMode() == ShuttleTaskModeType.PAK_IN.id
                    || assignCommand.getTaskMode() == ShuttleTaskModeType.PAK_OUT.id
                    || assignCommand.getTaskMode() == ShuttleTaskModeType.MOVE_LOC_NO.id
                    || assignCommand.getTaskMode() == ShuttleTaskModeType.SHUTTLE_MOVE_LOC_NO.id) {
                //下发行驶路径
                boolean result = shuttleThread.movePath(assignCommand.getNodes(), assignCommand.getDeviceTaskNo());
                if (!result) {
                    return false;
                }
            }
            shuttleProtocol.setTaskNo(assignCommand.getTaskNo().intValue());
            shuttleProtocol.setSyncTaskNo(assignCommand.getTaskNo());
            return true;
        }
        return false;
@@ -70,7 +97,14 @@
        if (obj == null) {
            return false;
        }
        ShuttleRedisCommand redisCommand = JSON.parseObject(obj.toString(), ShuttleRedisCommand.class);
        ShuttleRedisCommand redisCommand = null;
        try {
            redisCommand = objectMapper.readValue(String.valueOf(obj), ShuttleRedisCommand.class);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
        if (redisCommand == null) {
            return false;
        }
@@ -85,10 +119,8 @@
            return false;
        }
        //四向穿梭车空闲、有任务、标记为true、存在任务指令,需要执行任务的下一条指令
        if (!shuttleProtocol.getIdle()
                || shuttleProtocol.getTaskNo() == 0
                || !shuttleProtocol.getPakMk()) {
        //判断工作号是否相同
        if (!shuttleProtocol.getTaskNo().equals(taskNo)) {
            return false;
        }
@@ -108,7 +140,15 @@
                if (command.getTargetLocNo().equals(shuttleProtocol.getCurrentLocNo())) {
                    command.setComplete(true);
                    //解锁锁定路径,上一条路径
                    List<NavigateNode> nodes = JSON.parseArray(JSON.toJSONString(command.getNodes()), NavigateNode.class);//进行深度copy
                    List<NavigateNode> nodes = null;
                    try {
                        String nodesStr = objectMapper.writeValueAsString(command.getNodes());
                        nodes = objectMapper.readValue(nodesStr, new TypeReference<List<NavigateNode>>() {
                        });
                    } catch (JsonProcessingException e) {
                        throw new RuntimeException(e);
                    }
                    if (nodes != null) {
                        NavigateNode targetNode = assignCommand.getNodes().get(assignCommand.getNodes().size() - 1);//最终节点
                        NavigateNode node = nodes.get(nodes.size() - 1);
@@ -125,10 +165,11 @@
                // 托盘顶升
                //判断是否顶升到位
                if (shuttleProtocol.getHasLift()) {
                    //判断是否有物
                    if (shuttleProtocol.getHasPallet()) {
                        command.setComplete(true);
                    }
                    command.setComplete(true);
//                    //判断是否有物
//                    if (shuttleProtocol.getHasPallet()) {
//                        command.setComplete(true);
//                    }
                }
            } else if (command.getMode() == ShuttleCommandModeType.PALLET_DOWN.id) {
                // 托盘下降命令
@@ -136,8 +177,8 @@
                if (!shuttleProtocol.getHasLift()) {
                    command.setComplete(true);
                }
            } else if (command.getMode() == ShuttleCommandModeType.CHARGE.id) {
                // 充电开关
            } else if (command.getMode() == ShuttleCommandModeType.CHARGE_OPEN.id) {
                // 充电开
                //判断小车充电状态
                if (shuttleProtocol.getHasCharge()) {
                    command.setComplete(true);
@@ -147,7 +188,7 @@
            }
            // 更新redis数据
            redisUtil.set(DeviceRedisConstant.SHUTTLE_WORK_FLAG + redisCommand.getWrkNo(), JSON.toJSONString(redisCommand));
            redisUtil.set(DeviceRedisConstant.SHUTTLE_WORK_FLAG + redisCommand.getTaskNo(), JSON.toJSONString(redisCommand, SerializerFeature.DisableCircularReferenceDetect));
            if (!command.getComplete()) {
                return false;
@@ -162,25 +203,25 @@
                if (assignCommand.getAuto()) {
                    if (!assignCommand.getCharge()) {
                        //对主线程抛出等待确认状态waiting
                        shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.WAITING);
                        shuttleThread.setProtocolStatus(ShuttleProtocolStatusType.WAITING);
                    }else {
                        shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.CHARGING_WAITING);
                        shuttleThread.setProtocolStatus(ShuttleProtocolStatusType.CHARGING_WAITING);
                    }
                    News.info("四向穿梭车任务执行下发完成等待执行结束,穿梭车号={},任务数据={}", shuttleProtocol.getShuttleNo(), JSON.toJSON(command));
                    // 手动任务
                } else {
                    //手动模式不抛出等待状态,直接复位空闲状态
                    shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.IDLE);
                    shuttleThread.setProtocolStatus(ShuttleProtocolStatusType.IDLE);
                    //任务号清零
                    shuttleProtocol.setTaskNo(0);
                    shuttleThread.setSyncTaskNo(0);
                    //标记复位
                    shuttleProtocol.setPakMk(true);
                    shuttleThread.setPakMk(true);
                    News.info("四向穿梭车手动任务执行完成,穿梭车号={},任务数据={}", shuttleProtocol.getShuttleNo(), JSON.toJSON(command));
                }
                //删除redis
                redisUtil.del(DeviceRedisConstant.SHUTTLE_WORK_FLAG + redisCommand.getWrkNo());
                redisUtil.del(DeviceRedisConstant.SHUTTLE_WORK_FLAG + redisCommand.getTaskNo());
                return false;//禁止再下发命令
            }
        }
@@ -188,13 +229,397 @@
        //取出命令
        ShuttleCommand command = commands.get(commandStep);
        Integer mode = command.getMode();
        //判断设备是否空闲
        if (!shuttleThread.isDeviceIdle(new ExecuteSupport() {
            @Override
            public Boolean judgement() {
                if (ShuttleCommandModeType.CHARGE_CLOSE.id.equals(mode)) {//关闭充电motion
                    return false;//不需要判断状态
                }
                return true;//需要判断状态
            }
        })) {
            return false;
        }
        // 下发命令
        if (!write(command, device)) {
            News.error("四向穿梭车命令下发失败,穿梭车号={},任务数据={}", shuttleProtocol.getShuttleNo(), JSON.toJSON(command));
            return false;
        }
        shuttleThread.setProtocolStatus(ShuttleProtocolStatusType.WORKING);
        commandStep++;
        //更新redis数据
        redisCommand.setCommandStep(commandStep);
        //任务数据保存到redis
        redisUtil.set(DeviceRedisConstant.SHUTTLE_WORK_FLAG + redisCommand.getTaskNo(), JSON.toJSONString(redisCommand));
        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(false);
        if (shuttleProtocol == null) {
            return;
        }
        //小车开启跑库模式
        if (!shuttleProtocol.getMoveLoc()) {
            return;
        }
        //小车空闲
        if (!shuttleThread.isIdle()) {
            return;
        }
        int lev = Utils.getLev(shuttleProtocol.getCurrentLocNo());//小车当前楼层
        if (shuttleProtocol.getMoveType() == 0) {//跑轨道
            //根据地图方向决定跑x或y
            Dict dict = dictService.getOne(new LambdaQueryWrapper<Dict>()
                    .eq(Dict::getFlag, "direction_map")
                    .eq(Dict::getStatus, 1));
            if (dict == null) {
                //跑库结束
                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;
            }
            String direction = dict.getValue();
            if (direction.equals("y")) {//跑x轴方向,跑完x轴再切换y轴
                ArrayList<String> locs = new ArrayList<>();
                for (int i = shuttleProtocol.getXCurrent(); i <= shuttleProtocol.getXTarget(); i++) {
                    String locNo = Utils.getLocNo(i, shuttleProtocol.getYCurrent(), lev);
                    locs.add(locNo);
                }
                List<Loc> locList = locService.list(new LambdaQueryWrapper<Loc>()
                        .eq(Loc::getLocSts, LocStsType.O.val())
                        .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 {
                    //在起点位置,调度去目标位置
                    shuttleDispatcher.generateMoveTask(device, target.getLocNo());
                    shuttleProtocol.setYCurrent(shuttleProtocol.getYCurrent() + 1);//切换y轴
                    if(shuttleProtocol.getYCurrent() > shuttleProtocol.getYTarget()) {
                        //y轴也跑完了,结束跑库
                        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;
                    }
                }
            }else {//跑y轴方向,跑完y轴再切换x轴
                ArrayList<String> locs = new ArrayList<>();
                for (int i = shuttleProtocol.getYCurrent(); i <= shuttleProtocol.getYTarget(); i++) {
                    String locNo = Utils.getLocNo(shuttleProtocol.getXCurrent(), i, lev);
                    locs.add(locNo);
                }
                List<Loc> locList = locService.list(new LambdaQueryWrapper<Loc>()
                        .eq(Loc::getLocSts, LocStsType.O.val())
                        .in(Loc::getLocNo, locs));
                if (locList.isEmpty()) {
                    //空库位
                    shuttleProtocol.setXCurrent(shuttleProtocol.getXCurrent() + 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 {
                    //在起点位置,调度去目标位置
                    shuttleDispatcher.generateMoveTask(device, target.getLocNo());
                    shuttleProtocol.setXCurrent(shuttleProtocol.getXCurrent() + 1);//切换x轴
                    if(shuttleProtocol.getXCurrent() > shuttleProtocol.getXTarget()) {
                        //y轴也跑完了,结束跑库
                        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;
                    }
                }
            }
        } else if (shuttleProtocol.getMoveType() == 1) {//跑库位
            //根据地图方向决定跑x或y
            Dict dict = dictService.getOne(new LambdaQueryWrapper<Dict>()
                    .eq(Dict::getFlag, "direction_map")
                    .eq(Dict::getStatus, 1));
            if (dict == null) {
                //跑库结束
                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;
            }
            String direction = dict.getValue();
            if (direction.equals("y")) {//跑x轴方向,跑完x轴再切换y轴
                Integer xCurrent = shuttleProtocol.getXCurrent();
                //获取待跑库位号
                String locNo = Utils.getLocNo(xCurrent, shuttleProtocol.getYCurrent(), lev);
                Loc target = locService.getOne(new LambdaQueryWrapper<Loc>()
                        .eq(Loc::getLocNo, locNo)
                        .eq(Loc::getLocSts, LocStsType.O.val())
                        .eq(Loc::getHostId, device.getHostId()));
                if (target == null || shuttleProtocol.getCurrentLocNo().equals(locNo)) {//库位不存在或小车已在当前位置
                    shuttleProtocol.setXCurrent(xCurrent + 1);
                    if (shuttleProtocol.getXCurrent() > shuttleProtocol.getXTarget()) {
                        //x轴跑完,切换y轴
                        shuttleProtocol.setXCurrent(shuttleProtocol.getXStart());
                        shuttleProtocol.setYCurrent(shuttleProtocol.getYCurrent() + 1);
                        if(shuttleProtocol.getYCurrent() > shuttleProtocol.getYTarget()) {
                            //y轴也跑完了,结束跑库
                            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;
                        }
                    }
                    return;
                }
                //调度去库位
                Task task = shuttleDispatcher.generateMoveTask(device, locNo);
                if (task == null) {
                    return;//调度失败
                }
                shuttleProtocol.setXCurrent(xCurrent + 1);
                if (shuttleProtocol.getXCurrent() > shuttleProtocol.getXTarget()) {
                    //x轴跑完,切换y轴
                    shuttleProtocol.setXCurrent(shuttleProtocol.getXStart());
                    shuttleProtocol.setYCurrent(shuttleProtocol.getYCurrent() + 1);
                    if(shuttleProtocol.getYCurrent() > shuttleProtocol.getYTarget()) {
                        //y轴也跑完了,结束跑库
                        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;
                    }
                }
            }else {//跑y轴方向,跑完y轴再切换x轴
                Integer yCurrent = shuttleProtocol.getYCurrent();
                //获取待跑库位号
                String locNo = Utils.getLocNo(shuttleProtocol.getXCurrent(), yCurrent, lev);
                Loc target = locService.getOne(new LambdaQueryWrapper<Loc>()
                        .eq(Loc::getLocNo, locNo)
                        .eq(Loc::getLocSts, LocStsType.O.val())
                        .eq(Loc::getHostId, device.getHostId()));
                if (target == null || shuttleProtocol.getCurrentLocNo().equals(locNo)) {//库位不存在或小车已在当前位置
                    shuttleProtocol.setYCurrent(yCurrent + 1);
                    if (shuttleProtocol.getYCurrent() > shuttleProtocol.getYTarget()) {
                        //y轴跑完,切换x轴
                        shuttleProtocol.setYCurrent(shuttleProtocol.getYStart());
                        shuttleProtocol.setXCurrent(shuttleProtocol.getXCurrent() + 1);
                        if(shuttleProtocol.getXCurrent() > shuttleProtocol.getXTarget()) {
                            //x轴也跑完了,结束跑库
                            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;
                        }
                    }
                }
                //调度去库位
                Task task = shuttleDispatcher.generateMoveTask(device, locNo);
                if (task == null) {
                    return;//调度失败
                }
                shuttleProtocol.setYCurrent(yCurrent + 1);
                if (shuttleProtocol.getYCurrent() > shuttleProtocol.getYTarget()) {
                    //y轴跑完,切换x轴
                    shuttleProtocol.setYCurrent(shuttleProtocol.getYStart());
                    shuttleProtocol.setXCurrent(shuttleProtocol.getXCurrent() + 1);
                    if(shuttleProtocol.getXCurrent() > shuttleProtocol.getXTarget()) {
                        //x轴也跑完了,结束跑库
                        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;
                    }
                }
            }
        } 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());//切换库位
                    }
                }
            }
        } else if (shuttleProtocol.getMoveType() == 4) {//取放货
            Integer xCurrent = shuttleProtocol.getXCurrent();
            if (xCurrent > shuttleProtocol.getXTarget()) {//当X值大于X目标值
                shuttleProtocol.setXCurrent(shuttleProtocol.getXStart());
                shuttleProtocol.setYCurrent(shuttleProtocol.getYStart());
                return;
            }
            //判断x轴货位是否放满
            boolean flag = true;
            for (Loc loc : locService.list(new LambdaQueryWrapper<Loc>()
                    .eq(Loc::getHostId, device.getHostId())
                    .eq(Loc::getRow, xCurrent)
                    .ge(Loc::getBay, shuttleProtocol.getYStart())
                    .le(Loc::getBay, shuttleProtocol.getYTarget()))) {
                if (loc.getLocSts() != LocStsType.F.val()) {
                    flag = false;//未满
                    break;
                }
            }
            if (flag) {
                shuttleProtocol.setXCurrent(shuttleProtocol.getXCurrent() + 1);
                return;
            }
            //搜索有货库位
            List<Loc> list = locService.list(new LambdaQueryWrapper<Loc>()
                    .eq(Loc::getLocSts, LocStsType.F.val())
                    .eq(Loc::getHostId, device.getHostId())
                    .notIn(Loc::getRow, xCurrent)
                    .eq(Loc::getStatus, 1));
            if (list.isEmpty()) {
                return;
            }
            Loc start = list.get(0);
            List<Loc> locList = locService.list(new LambdaQueryWrapper<Loc>()
                    .eq(Loc::getHostId, device.getHostId())
                    .eq(Loc::getStatus, 1)
                    .eq(Loc::getLocSts, LocStsType.O.val())
                    .eq(Loc::getRow, xCurrent)
                    .orderByDesc(Loc::getBay)
                    .orderByAsc(Loc::getRow));
            if (locList.isEmpty()) {
                return;
            }
            Loc target = locList.get(0);
            if (target == null) {
                return;
            }
            //调度去目标位置
            if (!shuttleProtocol.getCurrentLocNo().equals(target.getLocNo())) {
                Task task = shuttleDispatcher.generateManuaTakeMoveTask(device, start.getLocNo(), target.getLocNo());
//                if(task != null) {//调度成功
//                    shuttleProtocol.setXCurrent(shuttleProtocol.getXCurrent() + 1);
//                }
            }
        }
    }
    private synchronized boolean write(ShuttleCommand command, Device device) {
@@ -211,7 +636,8 @@
        } else if (command.getMode() == ShuttleCommandModeType.PALLET_LIFT.id
                || command.getMode() == ShuttleCommandModeType.PALLET_DOWN.id) {//顶升
            result = shuttleThread.lift(command);
        } else if (command.getMode() == ShuttleCommandModeType.CHARGE.id) {//充电
        } 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);