#
Junjie
4 天以前 efa3e3042d30506b8eb3ce662d39c4dd954ae945
src/main/java/com/zy/core/action/ShuttleAction.java
@@ -2,19 +2,24 @@
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.BasShuttleService;
import com.zy.asrs.service.LocMastService;
import com.zy.asrs.service.WrkMastService;
import com.zy.asrs.utils.Utils;
import com.zy.common.ExecuteSupport;
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.command.ShuttleAssignCommand;
@@ -22,13 +27,14 @@
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.Date;
import java.util.List;
import java.util.*;
@Component
public class ShuttleAction {
@@ -38,8 +44,6 @@
    @Autowired
    private NavigateMapUtils navigateMapUtils;
    @Autowired
    private BasShuttleService basShuttleService;
    @Autowired
    private LocMastService locMastService;
    @Autowired
    private ObjectMapper objectMapper;
@@ -47,11 +51,28 @@
    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;
        }
        //清空下发索引
        Set<String> keys = redisUtil.searchKeys(RedisKeyType.SHUTTLE_SEND_COMMAND_INDEX.key + shuttleNo);
        for (String key : keys) {
            redisUtil.del(key);
        }
        ShuttleRedisCommand redisCommand = new ShuttleRedisCommand();
@@ -61,7 +82,7 @@
        redisCommand.setCommandStep(0);//命令执行步序
        redisCommand.setAssignCommand(assignCommand);//命令
        //任务数据保存到redis
        if (redisUtil.set(RedisKeyType.SHUTTLE.key + assignCommand.getTaskNo(), JSON.toJSONString(redisCommand, SerializerFeature.DisableCircularReferenceDetect))) {
        if (redisUtil.set(RedisKeyType.SHUTTLE_WORK_FLAG.key + assignCommand.getTaskNo(), JSON.toJSONString(redisCommand, SerializerFeature.DisableCircularReferenceDetect))) {
            shuttleThread.setSyncTaskNo(assignCommand.getTaskNo());
            return true;
        }
@@ -69,7 +90,7 @@
    }
    public synchronized boolean executeWork(Integer shuttleNo, Integer taskNo) {
        Object obj = redisUtil.get(RedisKeyType.SHUTTLE.key + taskNo);
        Object obj = redisUtil.get(RedisKeyType.SHUTTLE_WORK_FLAG.key + taskNo);
        if (obj == null) {
            return false;
        }
@@ -100,139 +121,69 @@
            return false;
        }
        List<ShuttleCommand> commands = redisCommand.getAssignCommand().getCommands();
        if (commands.isEmpty()) {
        //检测命令
        int checked = checkCommand(redisCommand, shuttleNo);
        if (checked == 0) {
            return false;
        }
        ShuttleAssignCommand assignCommand = redisCommand.getAssignCommand();
        int commandStep = redisCommand.getCommandStep();
        Integer mode = -1;
        if(commandStep < commands.size()) {
            //取出命令
            ShuttleCommand currentCommand = commands.get(commandStep);
            mode = currentCommand.getMode();
        }
        //判断设备是否空闲
        Integer finalMode = mode;
        if (!shuttleThread.isDeviceIdle(new ExecuteSupport() {
            @Override
            public Boolean judgement() {
                if (ShuttleCommandModeType.CHARGE_CLOSE.id.equals(finalMode)) {//关闭充电
                    return false;//不需要判断状态
                }
                return true;//需要判断状态
            }
        })) {
        List<ShuttleCommand> commands = assignCommand.getCommands();
        if (commands.isEmpty()) {
            return false;
        }
        // 完结上一条命令
        boolean updateCommand = false;
        if (commandStep != 0) {
            ShuttleCommand command = commands.get(commandStep - 1);
            if (command.getMode() == ShuttleCommandModeType.MOVE.id) {
                // 正常移动
                if (command.getTargetLocNo().equals(shuttleProtocol.getCurrentLocNo())) {
                    command.setComplete(true);
                    updateCommand = true;
                    //解锁锁定路径,上一条路径
                    List<NavigateNode> nodes = null;
                    try {
                        String nodesStr = objectMapper.writeValueAsString(command.getNodes());
                        nodes = objectMapper.readValue(nodesStr, new TypeReference<List<NavigateNode>>() {
                        });
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                    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()) {
                    command.setComplete(true);
                    updateCommand = true;
//                    //判断是否有物
//                    if (shuttleProtocol.getHasPallet()) {
//                        command.setComplete(true);
//                    }
                }
            } else if (command.getMode() == ShuttleCommandModeType.PALLET_DOWN.id) {
                // 托盘下降命令
                // 判断是否下降到位
                if (!shuttleProtocol.getHasLift()) {
                    command.setComplete(true);
                    updateCommand = true;
                }
            } else if (command.getMode() == ShuttleCommandModeType.CHARGE_OPEN.id) {
                // 充电开
                //判断小车充电状态
                if (shuttleProtocol.getHasCharge()) {
                    command.setComplete(true);
                    updateCommand = true;
                }
            }else {
                command.setComplete(true);//其他命令默认认为完成
                updateCommand = true;
            }
            if(updateCommand) {
                // 更新redis数据
                redisUtil.set(RedisKeyType.SHUTTLE.key + redisCommand.getWrkNo(), JSON.toJSONString(redisCommand, SerializerFeature.DisableCircularReferenceDetect));
            }
            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
                        shuttleThread.setProtocolStatus(ShuttleProtocolStatusType.WAITING);
                    }else {
                        shuttleThread.setProtocolStatus(ShuttleProtocolStatusType.CHARGING_WAITING);
                    }
                    News.info("四向穿梭车任务执行下发完成等待执行结束,穿梭车号={},任务数据={}", shuttleProtocol.getShuttleNo(), JSON.toJSON(command));
                    // 手动任务
                } else {
                    //手动模式不抛出等待状态,直接复位空闲状态
                    shuttleThread.setProtocolStatus(ShuttleProtocolStatusType.IDLE);
                    //任务号清零
                    shuttleThread.setSyncTaskNo(0);
                    //标记复位
                    shuttleThread.setPakMk(true);
                    News.info("四向穿梭车手动任务执行完成,穿梭车号={},任务数据={}", shuttleProtocol.getShuttleNo(), JSON.toJSON(command));
                }
                //删除redis
                redisUtil.del(RedisKeyType.SHUTTLE.key + redisCommand.getWrkNo());
                return false;//禁止再下发命令
            }
        int commandStep = redisCommand.getCommandStep();
        if(commandStep >= commands.size()){
            return false;
        }
        //取出命令
        ShuttleCommand command = commands.get(commandStep);
        ShuttleCommand command = null;
        if (checked == 1) {
            //非连续指令,需要检测上一条指令是否完成
            if (commandStep > 0) {
                ShuttleCommand lastCommand = commands.get(commandStep - 1);
                if (!lastCommand.getComplete()) {
                    return false;//指令未完成
                }
            }
            command = commands.get(commandStep);
        } else if (checked == 2) {
            //连续指令直接取数据
            command = commands.get(commandStep);
        }
        if(command == null){
            return false;
        }
        //移动命令,锁定路径
        if (command.getMode() == ShuttleCommandModeType.MOVE.id) {
            List<NavigateNode> nodes = JSON.parseArray(JSON.toJSONString(command.getNodes()), NavigateNode.class);
            //申请管制
            boolean apply = applyTrafficControl(commands, nodes, shuttleNo, taskNo);
            if(!apply){
                return false;//申请失败
            }
//            //检测路径是否冲突
//            int conflict = searchShuttlePathConflict(nodes, shuttleNo);
//            if(conflict == 2){
//                return false;//检测后有冲突
//            }
            if (checked == 2) {
                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);
                return false;//路径锁定失败
            }
        }
        // 下发命令
        CommandResponse response = write(command, shuttleNo);
@@ -260,14 +211,549 @@
        }
        shuttleThread.setProtocolStatus(ShuttleProtocolStatusType.WORKING);
        commandStep++;
        //存储下发指令索引
        redisUtil.set(RedisKeyType.SHUTTLE_SEND_COMMAND_INDEX.key + shuttleNo + "_" + taskNo + "_" + commandStep, commandStep);
        commandStep += 1;
        //更新redis数据
        redisCommand.setCommandStep(commandStep);
        //任务数据保存到redis
        redisUtil.set(RedisKeyType.SHUTTLE.key + redisCommand.getWrkNo(), JSON.toJSONString(redisCommand));
        redisUtil.set(RedisKeyType.SHUTTLE_WORK_FLAG.key + redisCommand.getWrkNo(), JSON.toJSONString(redisCommand));
        return true;
    }
    /**
     * 检测命令
     * 0:未通过 1:通过 2:通过且可提前下发指令
     */
    private int checkCommand(ShuttleRedisCommand redisCommand, Integer shuttleNo) {
        TrafficControlThread trafficControlThread = (TrafficControlThread) SlaveConnection.get(SlaveType.TrafficControl, 1);
        if(trafficControlThread == null){
            return 0;
        }
        ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, shuttleNo);
        if (shuttleThread == null) {
            return 0;
        }
        ShuttleProtocol shuttleProtocol = shuttleThread.getStatus();
        if (shuttleProtocol == null) {
            return 0;
        }
        int commandStep = redisCommand.getCommandStep();
        if (commandStep == 0) {
            return 1;//第一条命令无需检测
        }
        ShuttleAssignCommand assignCommand = redisCommand.getAssignCommand();
        List<ShuttleCommand> commands = assignCommand.getCommands();
        if (commands.isEmpty()) {
            return 0;
        }
        //上一条指令
        String searchKey = RedisKeyType.SHUTTLE_SEND_COMMAND_INDEX.key + shuttleNo + "_" + redisCommand.getWrkNo() + "_";
        Set<String> keys = redisUtil.searchKeys(searchKey);
        TreeSet<Integer> treeSet = new TreeSet<>();
        for (String key : keys) {
            String[] split = key.split(searchKey);
            treeSet.add(Integer.parseInt(split[1]));
        }
        if (treeSet.isEmpty()) {
            return 1;
        }
        String firstKey = searchKey + treeSet.first();
        Integer lastCommandIdx = (Integer) redisUtil.get(firstKey);
        ShuttleCommand lastCommand = commands.get(lastCommandIdx);
        if (!lastCommand.getComplete()) {
            //检测更新命令完成
            boolean checked = updateCommandComplete(lastCommandIdx, commands, shuttleNo);
            if (checked) {
                //删除索引
                redisUtil.del(firstKey);
                // 更新redis数据
                redisUtil.set(RedisKeyType.SHUTTLE_WORK_FLAG.key + redisCommand.getWrkNo(), JSON.toJSONString(redisCommand, SerializerFeature.DisableCircularReferenceDetect));
            }else {
                //小车移动连续下发指令
                if (assignCommand.getShuttleMoveCommandsContinuously()) {
                    if (treeSet.size() <= 1) {
                        if(commandStep >= commands.size()) {
                            return 0;
                        }
                        //移动指令
                        if(lastCommand.getMode() != ShuttleCommandModeType.MOVE.id) {
                            return 0;
                        }
                        List<NavigateNode> nodes = lastCommand.getNodes();
                        NavigateNode startNode = nodes.get(0);
                        if (!startNode.getLinePartAllowGo()) {//直线段部分,允许直接行走
                            return 0;
                        }
                        //直线段数据标识
                        Long linePartFlag = startNode.getLinePartFlag();
                        //取指令
                        ShuttleCommand currentCommand = commands.get(commandStep);
                        if(currentCommand.getMode() != ShuttleCommandModeType.MOVE.id) {
                            return 0;
                        }
                        List<NavigateNode> currentNodes = currentCommand.getNodes();
                        NavigateNode currentStartNode = currentNodes.get(0);
                        if(!currentStartNode.getLinePartAllowGo()) {//直线段部分,允许直接行走
                            return 0;
                        }
                        if(currentStartNode.getLinePartFlag().equals(linePartFlag)) {
                            //数据标识一致
                            return 2;//允许小车移动连续下发指令
                        }
                    }
                }
                return 0;
            }
        }
        //判断是否为最后一条命令且命令执行完成,抛出等待确认状态
        ShuttleCommand endCommand = commands.get(commands.size() - 1);
        if (endCommand.getComplete()) {
            News.info("四向穿梭车任务执行下发完成等待执行结束,穿梭车号={},任务数据={}", shuttleProtocol.getShuttleNo(), JSON.toJSON(commands));
            // 系统任务
            if (assignCommand.getAuto()) {
                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));
            }
            //申请取消管制
            trafficControlThread.cancelTrafficControl(shuttleNo, shuttleProtocol.getTaskNo());
            //删除redis
            redisUtil.del(RedisKeyType.SHUTTLE_WORK_FLAG.key + redisCommand.getWrkNo());
            return 0;//禁止再下发命令
        }
        return 1;
    }
    //检测更新命令完成
    private boolean updateCommandComplete(Integer commandIdx, List<ShuttleCommand> 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<String> targetPoints = new ArrayList<>();
            //解锁锁定路径,上一条路径
            List<NavigateNode> nodes = null;
            try {
                String nodesStr = objectMapper.writeValueAsString(command.getNodes());
                nodes = objectMapper.readValue(nodesStr, new TypeReference<List<NavigateNode>>() {
                });
            } 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<NavigateNode> 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;
            }
            //上报交管
            trafficControlThread.trafficReport(command.getNodesDeepCopy(), shuttleNo, shuttleProtocol.getTaskNo());
            String currentLocNo = shuttleProtocol.getCurrentLocNo();
            if (targetPoints.contains(Utils.getRow(currentLocNo) + "-" + Utils.getBay(currentLocNo))) {
                command.setComplete(true);
                boolean result = navigateMapUtils.writeNavigateNodeToRedisMap(Utils.getLev(shuttleProtocol.getCurrentLocNo()), shuttleProtocol.getShuttleNo(), nodes, false);//解锁路径
                if (!result) {
                    return false;//解锁失败
                }
            }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<ShuttleCommand> commands, List<NavigateNode> nodeList, Integer shuttleNo, Integer taskNo) {
        TrafficControlThread trafficControlThread = (TrafficControlThread) SlaveConnection.get(SlaveType.TrafficControl, 1);
        if (trafficControlThread == null) {
            return false;
        }
        List<NavigateNode> totalNodeList = new ArrayList<>();
        for (ShuttleCommand command : commands) {
            if (command.getMode() == ShuttleCommandModeType.MOVE.id) {
                List<NavigateNode> deepCopy = command.getNodesDeepCopy();
                if (deepCopy != null) {
                    totalNodeList.addAll(deepCopy);
                }
            }
        }
        return trafficControlThread.applyTrafficControl(totalNodeList, nodeList, shuttleNo, taskNo);
    }
//    /**
//     * 搜索小车路径是否存在冲突
//     * 0:未检测 1:检测无冲突 2:检测有冲突
//     */
//    public int searchShuttlePathConflict(List<NavigateNode> nodeList, Integer shuttleNo) {
//        ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, shuttleNo);
//        if (shuttleThread == null) {
//            return 0;
//        }
//
//        ShuttleProtocol shuttleProtocol = shuttleThread.getStatus();
//        if (shuttleProtocol == null) {
//            return 0;
//        }
//
//        int lev = Utils.getLev(shuttleProtocol.getCurrentLocNo());
//
//        TrafficControlThread trafficControlThread = (TrafficControlThread) SlaveConnection.get(SlaveType.TrafficControl, 1);
//        if (trafficControlThread == null) {
//            return 2;
//        }
//        HashMap<String, List<Integer>> nodeMap = trafficControlThread.getNodesMapByLev(lev);
//        if (nodeMap == null || nodeMap.isEmpty()) {
//            return 2;
//        }
//
//        List<String> conflictLocList = new ArrayList<>();
//        for (NavigateNode node : nodeList) {
//            String locNo = Utils.getLocNo(node.getX(), node.getY(), lev);
//            if(!nodeMap.containsKey(locNo)) {
//                return 2;
//            }
//
//            List<Integer> shuttleNos = nodeMap.get(locNo);
//            if (shuttleNos.size() > 1) {
//                //路径存在多车,冲突
//                conflictLocList.add(locNo);
//            }
//        }
//
//        if (conflictLocList.isEmpty()) {
//            //无冲突,解除交通管制
//            shuttleThread.setTrafficControl(false, null);
//            return 1;//检测后无冲突
//        }
//
//        //路径存在冲突,检测可执行车辆是否为当前小车
//        //上报小车状态-交通管制中
//        shuttleThread.setTrafficControl(true, nodeList);
//
//        HashMap<String, Integer> deviceMap = trafficControlThread.getDeviceMap();
//        if(deviceMap == null) {
//            return 2;
//        }
//
//        boolean detected = false;
////            for (Map.Entry<String, Integer> entry : deviceMap.entrySet()) {
////                List<String> mainList = JSON.parseArray(entry.getKey(), String.class);
////                Integer device = entry.getValue();
////                if(result) {
////                    //判断管制车辆是否匹配
////                    if(shuttleNo.equals(device)) {
////                        detected = true;
////                        break;
////                    }
////                }
////            }
//
//        for (Map.Entry<String, Integer> entry : deviceMap.entrySet()) {
//            String key = entry.getKey();
//            Integer value = entry.getValue();
//            if(shuttleNo.equals(value)) {
//                //判断管制车辆是否匹配
//                detected = true;
//                break;
//            }
//        }
//
//        if (detected) {
//            return 1;//检测后无冲突,交通管制已允许此小车运行
//        }
//
//        return 2;//检测后有冲突
//    }
    //演示模式
    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()) {
            return;
        }
        if (!shuttleThread.isIdle()) {
            return;
        }
        boolean demoSwitchLev = false;
        Config demoSwitchLevConfig = configService.selectOne(new EntityWrapper<Config>().eq("code", "demoSwitchLev"));
        if (demoSwitchLevConfig != null) {
            if (demoSwitchLevConfig.getValue().equals("Y")) {
                demoSwitchLev = true;
            }
        }
        Config demoRunLevConfig = configService.selectOne(new EntityWrapper<Config>().eq("code", "demoRunLev"));
        if (demoRunLevConfig == null) {
            return;
        }
        List<Integer> 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<LocMast> 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<String> 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<Config>().eq("code", "demoCargoMove"));
        if (demoCargoMoveConfig == null) {
            return;
        }
        if (!demoCargoMoveConfig.getValue().equals("Y")) {
            return;
        }
        Config demoRunLevConfig = configService.selectOne(new EntityWrapper<Config>().eq("code", "demoRunLev"));
        if (demoRunLevConfig == null) {
            return;
        }
        List<Integer> 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<WrkMast>().eq("io_type", WrkIoType.LOC_MOVE.id))) {
            if (Utils.getLev(wrkMast.getLocNo()) == lev) {
                currentLevTask += 1;
            }
        }
        //搬运任务数量超过小车数量,暂时不生成新任务
        if (currentLevTask > shuttleCountByLev) {
            return;
        }
        LocMast sourceLoc = null;
        EntityWrapper<LocMast> 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<LocMast> 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 moveLoc(Integer shuttleNo) {
//        ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, shuttleNo);