#
Junjie
昨天 f5e49b2c04137fdc88c453cbe5d190cf7daab079
#
2个文件已添加
19个文件已修改
1195 ■■■■ 已修改文件
src/main/java/com/zy/asrs/controller/DualCrnController.java 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/BasCrnp.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/BasDualCrnp.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/WrkMast.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/WrkMastLog.java 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/utils/Utils.java 131 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/entity/FindCrnNoResult.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/service/CommonService.java 156 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/enums/RedisKeyType.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/network/fake/ZyDualCrnFakeConnect.java 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/plugin/FakeProcess.java 107 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/thread/impl/ZySiemensDualCrnThread.java 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/utils/DualCrnOperateProcessUtils.java 495 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/utils/StationOperateProcessUtils.java 27 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/utils/WmsOperateUtils.java 63 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/WrkMastLogMapper.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/WrkMastMapper.xml 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/static/js/basDualCrnp/basDualCrnp.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/static/js/wrkMastLog/wrkMastLog.js 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/views/basDualCrnp/basDualCrnp.html 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/views/wrkMast/wrkMast.html 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/controller/DualCrnController.java
@@ -103,7 +103,7 @@
            return R.error("线程不存在");
        }
        DualCrnCommand command = crnThread.getPickAndPutCommand(sourceLocNo, targetLocNo, 9999, crnNo, station);
        MessageQueue.offer(SlaveType.DualCrn, crnNo, new Task(2, command));
        MessageQueue.offer(SlaveType.DualCrn, crnNo, new Task(3, command));
        return R.ok();
    }
@@ -121,7 +121,7 @@
            return R.error("线程不存在");
        }
        DualCrnCommand command = crnThread.getPickCommand(targetLocNo, 9999, crnNo, station);
        MessageQueue.offer(SlaveType.DualCrn, crnNo, new Task(2, command));
        MessageQueue.offer(SlaveType.DualCrn, crnNo, new Task(3, command));
        return R.ok();
    }
@@ -139,7 +139,7 @@
            return R.error("线程不存在");
        }
        DualCrnCommand command = crnThread.getPutCommand(targetLocNo, 9999, crnNo, station);
        MessageQueue.offer(SlaveType.DualCrn, crnNo, new Task(2, command));
        MessageQueue.offer(SlaveType.DualCrn, crnNo, new Task(3, command));
        return R.ok();
    }
    
@@ -161,7 +161,7 @@
        if (station != null) {
            command.setStation(station.shortValue());
        }
        MessageQueue.offer(SlaveType.DualCrn, crnNo, new Task(2, command));
        MessageQueue.offer(SlaveType.DualCrn, crnNo, new Task(3, command));
        return R.ok();
    }
@@ -178,7 +178,7 @@
            return R.error("线程不存在");
        }
        DualCrnCommand command = crnThread.getResetCommand(crnNo, station);
        MessageQueue.offer(SlaveType.DualCrn, crnNo, new Task(2, command));
        MessageQueue.offer(SlaveType.DualCrn, crnNo, new Task(3, command));
        return R.ok();
    }
}
src/main/java/com/zy/asrs/entity/BasCrnp.java
@@ -6,7 +6,6 @@
import com.baomidou.mybatisplus.annotations.TableId;
import com.baomidou.mybatisplus.enums.IdType;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.annotations.TableField;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
src/main/java/com/zy/asrs/entity/BasDualCrnp.java
@@ -1,10 +1,17 @@
package com.zy.asrs.entity;
import com.core.common.Cools;import com.baomidou.mybatisplus.annotations.TableId;
import com.core.common.Cools;
import com.zy.core.model.StationObjModel;
import com.baomidou.mybatisplus.annotations.TableId;
import com.baomidou.mybatisplus.enums.IdType;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.annotations.TableField;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.springframework.format.annotation.DateTimeFormat;
import io.swagger.annotations.ApiModelProperty;
@@ -195,5 +202,43 @@
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.updateTime);
    }
    public List<StationObjModel> getInStationList$(){
        List<StationObjModel> list = new ArrayList<>();
        if (Cools.isEmpty(this.inStationList)){
            return list;
        }
        List<StationObjModel> jsonList = JSON.parseArray(this.inStationList,StationObjModel.class);
        for (StationObjModel json : jsonList){
            list.add(json);
        }
        return list;
    }
    public List<StationObjModel> getOutStationList$(){
        List<StationObjModel> list = new ArrayList<>();
        if (Cools.isEmpty(this.outStationList)){
            return list;
        }
        List<StationObjModel> jsonList = JSON.parseArray(this.outStationList,StationObjModel.class);
        for (StationObjModel json : jsonList){
            list.add(json);
        }
        return list;
    }
    public List<List<Integer>> getControlRows$(){
        List<List<Integer>> rowList = new ArrayList<>();
        if(Cools.isEmpty(this.controlRows)){
            return rowList;
        }
        JSONArray list = JSON.parseArray(this.controlRows);
        for (Object o : list) {
            List<Integer> rows = JSON.parseArray(JSON.toJSONString(o), Integer.class);
            rowList.add(rows);
        }
        return rowList;
    }
}
src/main/java/com/zy/asrs/entity/WrkMast.java
@@ -148,6 +148,13 @@
    private Integer crnNo;
    /**
     * 双工位堆垛机号
     */
    @ApiModelProperty(value= "双工位堆垛机号")
    @TableField(value = "dual_crn_no",strategy = FieldStrategy.IGNORED)
    private Integer dualCrnNo;
    /**
     * RGV号
     */
    @ApiModelProperty(value= "RGV号")
src/main/java/com/zy/asrs/entity/WrkMastLog.java
@@ -3,7 +3,6 @@
import com.baomidou.mybatisplus.annotations.TableField;
import com.baomidou.mybatisplus.annotations.TableId;
import com.baomidou.mybatisplus.annotations.TableName;
import com.baomidou.mybatisplus.enums.FieldStrategy;
import com.baomidou.mybatisplus.enums.IdType;
import com.core.common.Cools;
import com.core.common.SpringUtils;
@@ -153,6 +152,13 @@
    @TableField(value = "crn_no")
    private Integer crnNo;
     /**
     * 双工位堆垛机号
     */
    @ApiModelProperty(value= "双工位堆垛机号")
    @TableField(value = "dual_crn_no")
    private Integer dualCrnNo;
    /**
     * RGV号
     */
src/main/java/com/zy/asrs/utils/Utils.java
@@ -10,18 +10,22 @@
import com.core.common.SpringUtils;
import com.core.exception.CoolException;
import com.zy.asrs.entity.BasCrnp;
import com.zy.asrs.entity.BasDualCrnp;
import com.zy.asrs.entity.WrkMast;
import com.zy.asrs.service.BasCrnpService;
import com.zy.asrs.service.BasDualCrnpService;
import com.zy.asrs.service.WrkMastService;
import com.zy.common.model.NavigateNode;
import com.zy.common.utils.NavigateUtils;
import com.zy.common.utils.RedisUtil;
import com.zy.core.News;
import com.zy.core.cache.SlaveConnection;
import com.zy.core.enums.CrnModeType;
import com.zy.core.enums.RedisKeyType;
import com.zy.core.enums.SlaveType;
import com.zy.core.enums.WrkIoType;
import com.zy.core.enums.*;
import com.zy.core.model.StationObjModel;
import com.zy.core.model.protocol.CrnProtocol;
import com.zy.core.model.protocol.DualCrnProtocol;
import com.zy.core.thread.CrnThread;
import com.zy.core.thread.DualCrnThread;
import java.lang.reflect.Field;
import java.text.DecimalFormat;
@@ -140,15 +144,28 @@
    }
    //获取入库任务可用排
    public static List<Integer> getInTaskEnableRow() {
        return getInTaskEnableRow(new ArrayList<>(), true);
    public static List<Integer> getInTaskEnableRow(Integer stationId) {
        return getInTaskEnableRow(stationId, new ArrayList<>(), new ArrayList<>(), true);
    }
    //获取入库任务可用排
    public static List<Integer> getInTaskEnableRow(List<Integer> excludeCrnList, boolean maxInTaskControl) {
    public static List<Integer> getInTaskEnableRow(Integer stationId, List<Integer> excludeCrnList, List<Integer> excludeDualCrnList, boolean maxInTaskControl) {
        //获取堆垛机入库任务可用排
        List<Integer> rowList = getCrnInTaskEnableRow(stationId, excludeCrnList, maxInTaskControl);
        //获取双工位堆垛机入库任务可用排
        List<Integer> dualRowList = getDualCrnInTaskEnableRow(stationId, excludeDualCrnList, maxInTaskControl);
        if (!dualRowList.isEmpty()) {
            rowList.addAll(dualRowList);
        }
        return rowList;
    }
    //获取堆垛机入库任务可用排
    public static List<Integer> getCrnInTaskEnableRow(Integer stationId, List<Integer> excludeCrnList, boolean maxInTaskControl) {
        List<Integer> list = new ArrayList<>();
        try {
            RedisUtil redisUtil = SpringUtils.getBean(RedisUtil.class);
            NavigateUtils navigateUtils = SpringUtils.getBean(NavigateUtils.class);
            WrkMastService wrkMastService = SpringUtils.getBean(WrkMastService.class);
            BasCrnpService basCrnpService = SpringUtils.getBean(BasCrnpService.class);
@@ -209,7 +226,25 @@
                if (excludeCrnList.contains(basCrnp.getCrnNo())) {
                    continue;
                }
                enabledCrnps.add(basCrnp);
                //计算站点是否可达该堆垛机
                List<StationObjModel> inStationList = basCrnp.getInStationList$();
                boolean enableGo = false;
                for (StationObjModel stationObjModel : inStationList) {
                    try {
                        List<NavigateNode> navigateNodes = navigateUtils.calcByStationId(stationId, stationObjModel.getStationId());
                        if(navigateNodes != null && !navigateNodes.isEmpty()) {
                            enableGo = true;
                            break;
                        }
                    } catch (Exception e) {
                    }
                }
                if (enableGo) {
                    enabledCrnps.add(basCrnp);
                }
            }
            enabledCrnps.sort(Comparator.comparingInt(o -> map.getOrDefault(o.getCrnNo(), 0)));
@@ -226,6 +261,86 @@
        return list;
    }
    //获取双工位堆垛机入库任务可用排
    public static List<Integer> getDualCrnInTaskEnableRow(Integer stationId, List<Integer> excludeCrnList, boolean maxInTaskControl) {
        List<Integer> list = new ArrayList<>();
        try {
            RedisUtil redisUtil = SpringUtils.getBean(RedisUtil.class);
            NavigateUtils navigateUtils = SpringUtils.getBean(NavigateUtils.class);
            WrkMastService wrkMastService = SpringUtils.getBean(WrkMastService.class);
            BasDualCrnpService basDualCrnpService = SpringUtils.getBean(BasDualCrnpService.class);
            Wrapper<BasDualCrnp> wrapper = new EntityWrapper<BasDualCrnp>()
                    .eq("in_enable", "Y")
                    .eq("status", 1);
            HashMap<Integer, Integer> map = new HashMap<>();
            List<WrkMast> wrkMasts = wrkMastService.selectList(new EntityWrapper<>());
            List<BasDualCrnp> basDualCrnps = basDualCrnpService.selectList(wrapper);
            for (WrkMast wrkMast : wrkMasts) {
                Integer dualCrnNo = wrkMast.getDualCrnNo();
                map.put(dualCrnNo, map.getOrDefault(dualCrnNo, 0) + 1);
            }
            List<BasDualCrnp> enabledCrnps = new ArrayList<>();
            for (BasDualCrnp basDualCrnp : basDualCrnps) {
                DualCrnThread dualCrnThread = (DualCrnThread) SlaveConnection.get(SlaveType.DualCrn, basDualCrnp.getCrnNo());
                if (dualCrnThread == null) {
                    continue;
                }
                DualCrnProtocol dualCrnProtocol = dualCrnThread.getStatus();
                if (dualCrnProtocol.getMode() != DualCrnModeType.AUTO.id) {
                    continue;
                }
                List<WrkMast> inWrkMasts = wrkMastService.selectList(new EntityWrapper<WrkMast>()
                        .eq("dual_crn_no", basDualCrnp.getCrnNo())
                        .eq("io_type", WrkIoType.IN.id)
                );
                // 检查是否超过最大入库任务数
                if (maxInTaskControl && inWrkMasts.size() >= basDualCrnp.getMaxInTask()) {
                    News.info("堆垛机:{} 已达最大入库任务数,当前任务数:{}", basDualCrnp.getCrnNo(), inWrkMasts.size());
                    continue;
                }
                if (excludeCrnList.contains(basDualCrnp.getCrnNo())) {
                    continue;
                }
                //计算站点是否可达该堆垛机
                List<StationObjModel> inStationList = basDualCrnp.getInStationList$();
                boolean enableGo = false;
                for (StationObjModel stationObjModel : inStationList) {
                    try {
                        List<NavigateNode> navigateNodes = navigateUtils.calcByStationId(stationId, stationObjModel.getStationId());
                        if(navigateNodes != null && !navigateNodes.isEmpty()) {
                            enableGo = true;
                            break;
                        }
                    } catch (Exception e) {
                    }
                }
                if (enableGo) {
                    enabledCrnps.add(basDualCrnp);
                }
            }
            enabledCrnps.sort(Comparator.comparingInt(o -> map.getOrDefault(o.getCrnNo(), 0)));
            for (BasDualCrnp basDualCrnp : enabledCrnps) {
                List<List<Integer>> rowList = basDualCrnp.getControlRows$();
                for (List<Integer> rows : rowList) {
                    list.addAll(rows);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return list;
    }
    public static Map<String, Object> convertObjectToMap(Object obj) {
        Map<String, Object> map = new HashMap<>();
        Class<?> clazz = obj.getClass();
src/main/java/com/zy/common/entity/FindCrnNoResult.java
New file
@@ -0,0 +1,13 @@
package com.zy.common.entity;
import com.zy.core.enums.SlaveType;
import lombok.Data;
@Data
public class FindCrnNoResult {
    private Integer crnNo;
    private SlaveType crnType;
}
src/main/java/com/zy/common/service/CommonService.java
@@ -9,11 +9,13 @@
import com.zy.asrs.entity.*;
import com.zy.asrs.service.*;
import com.zy.asrs.utils.Utils;
import com.zy.common.entity.FindCrnNoResult;
import com.zy.common.model.NavigateNode;
import com.zy.common.utils.NavigateUtils;
import com.zy.common.utils.RedisUtil;
import com.zy.core.News;
import com.zy.core.enums.RedisKeyType;
import com.zy.core.enums.SlaveType;
import com.zy.core.enums.WrkIoType;
import com.zy.core.enums.WrkStsType;
import com.zy.core.model.StationObjModel;
@@ -21,6 +23,7 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@@ -36,6 +39,8 @@
    private LocMastService locMastService;
    @Autowired
    private BasCrnpService basCrnpService;
    @Autowired
    private BasDualCrnpService basDualCrnpService;
    @Autowired
    private NavigateUtils navigateUtils;
    @Autowired
@@ -138,19 +143,20 @@
            ioPri = param.getTaskPri().doubleValue();
        }
        Integer sourceCrnNo = this.findCrnNoByLocNo(sourceLocMast.getLocNo());
        if (sourceCrnNo == null) {
        FindCrnNoResult sourceCrnResult = this.findCrnNoByLocNo(sourceLocMast.getLocNo());
        if (sourceCrnResult == null) {
            throw new CoolException("未找到对应堆垛机");
        }
        Integer crnNo = this.findCrnNoByLocNo(locMast.getLocNo());
        if (crnNo == null) {
        FindCrnNoResult targetCrnResult = this.findCrnNoByLocNo(locMast.getLocNo());
        if (targetCrnResult == null) {
            throw new CoolException("未找到对应堆垛机");
        }
        if (!sourceCrnNo.equals(crnNo)) {
        if (!sourceCrnResult.getCrnNo().equals(targetCrnResult.getCrnNo())) {
            throw new CoolException("源库位和目标库位不在同一巷道");
        }
        Integer crnNo = targetCrnResult.getCrnNo();
        // 获取工作号
        int workNo = getWorkNo(WrkIoType.LOC_MOVE.id);
@@ -202,10 +208,11 @@
            ioPri = param.getTaskPri().doubleValue();
        }
        Integer crnNo = this.findCrnNoByLocNo(locMast.getLocNo());
        if (crnNo == null) {
        FindCrnNoResult findCrnResult = this.findCrnNoByLocNo(locMast.getLocNo());
        if (findCrnResult == null) {
            throw new CoolException("未找到对应堆垛机");
        }
        Integer crnNo = findCrnResult.getCrnNo();
        // 获取工作号
        int workNo = getWorkNo(WrkIoType.IN.id);
@@ -221,9 +228,20 @@
        wrkMast.setStaNo(param.getStaNo());//目标站
        wrkMast.setWmsWrkNo(param.getTaskNo());
        wrkMast.setBarcode(param.getBarcode());
        wrkMast.setCrnNo(crnNo);
        wrkMast.setAppeTime(now);
        wrkMast.setModiTime(now);
        if (findCrnResult.getCrnType().equals(SlaveType.Crn)) {
            wrkMast.setCrnNo(findCrnResult.getCrnNo());
            //缓存记录当前命令堆垛机编号
            redisUtil.set(RedisKeyType.CURRENT_CIRCLE_TASK_CRN_NO.key, crnNo, 60 * 60 * 24);
        } else if (findCrnResult.getCrnType().equals(SlaveType.DualCrn)) {
            wrkMast.setDualCrnNo(findCrnResult.getCrnNo());
        }else {
            throw new CoolException("未知设备类型");
        }
        boolean res = wrkMastService.insert(wrkMast);
        if (!res) {
            News.error("入库任务 --- 保存工作档失败!");
@@ -233,9 +251,6 @@
        locMast.setLocSts("S");
        locMast.setModiTime(new Date());
        locMastService.updateById(locMast);
        //缓存记录当前命令堆垛机编号
        redisUtil.set(RedisKeyType.CURRENT_CIRCLE_TASK_CRN_NO.key, crnNo, 60 * 60 * 24);
        return wrkMast;
    }
@@ -256,28 +271,15 @@
            ioPri = param.getTaskPri().doubleValue();
        }
        Integer crnNo = this.findCrnNoByLocNo(locMast.getLocNo());
        if (crnNo == null) {
        FindCrnNoResult findCrnResult = this.findCrnNoByLocNo(locMast.getLocNo());
        if (findCrnResult == null) {
            throw new CoolException("未找到对应堆垛机");
        }
        Integer crnNo = findCrnResult.getCrnNo();
        Integer sourceStationId = this.findOutStationId(crnNo, param.getStaNo());
        Integer sourceStationId = this.findOutStationId(findCrnResult, param.getStaNo());
        if (sourceStationId == null) {
            throw new CoolException("未找到输送目标站点可走行路径");
        }
        BasCrnp basCrnp = basCrnpService.selectOne(new EntityWrapper<BasCrnp>().eq("crn_no", crnNo));
        if(basCrnp == null) {
            throw new CoolException("未找到对应堆垛机数据");
        }
        List<WrkMast> outWrkMasts = wrkMastService.selectList(new EntityWrapper<WrkMast>()
                .eq("crn_no", crnNo)
                .eq("io_type", WrkIoType.OUT.id)
        );
        // 检查是否超过最大出库任务数
        if(outWrkMasts.size() >= basCrnp.getMaxOutTask()){
            News.info("堆垛机:{} 已达最大出库任务数,当前任务数:{}", basCrnp.getCrnNo(), outWrkMasts.size());
            throw new CoolException("堆垛机:" + basCrnp.getCrnNo() + "已达最大出库任务数,当前任务数:" + outWrkMasts.size());
        }
        // 获取工作号
@@ -294,9 +296,45 @@
        wrkMast.setStaNo(param.getStaNo());//目标站
        wrkMast.setWmsWrkNo(param.getTaskNo());
        wrkMast.setBarcode(locMast.getBarcode());
        wrkMast.setCrnNo(crnNo);
        wrkMast.setAppeTime(now);
        wrkMast.setModiTime(now);
        if (findCrnResult.getCrnType().equals(SlaveType.Crn)) {
            BasCrnp basCrnp = basCrnpService.selectOne(new EntityWrapper<BasCrnp>().eq("crn_no", crnNo));
            if(basCrnp == null) {
                throw new CoolException("未找到对应堆垛机数据");
            }
            List<WrkMast> outWrkMasts = wrkMastService.selectList(new EntityWrapper<WrkMast>()
                    .eq("crn_no", crnNo)
                    .eq("io_type", WrkIoType.OUT.id)
            );
            // 检查是否超过最大出库任务数
            if(outWrkMasts.size() >= basCrnp.getMaxOutTask()){
                News.info("堆垛机:{} 已达最大出库任务数,当前任务数:{}", basCrnp.getCrnNo(), outWrkMasts.size());
                throw new CoolException("堆垛机:" + basCrnp.getCrnNo() + "已达最大出库任务数,当前任务数:" + outWrkMasts.size());
            }
            wrkMast.setCrnNo(findCrnResult.getCrnNo());
        } else if (findCrnResult.getCrnType().equals(SlaveType.DualCrn)) {
            BasDualCrnp basDualCrnp = basDualCrnpService.selectOne(new EntityWrapper<BasDualCrnp>().eq("crn_no", crnNo));
            if(basDualCrnp == null) {
                throw new CoolException("未找到对应双工位堆垛机数据");
            }
            List<WrkMast> outWrkMasts = wrkMastService.selectList(new EntityWrapper<WrkMast>()
                    .eq("dual_crn_no", crnNo)
                    .eq("io_type", WrkIoType.OUT.id)
            );
            // 检查是否超过最大出库任务数
            if(outWrkMasts.size() >= basDualCrnp.getMaxOutTask()){
                News.info("双工位堆垛机:{} 已达最大出库任务数,当前任务数:{}", basDualCrnp.getCrnNo(), outWrkMasts.size());
                throw new CoolException("双工位堆垛机:" + basDualCrnp.getCrnNo() + "已达最大出库任务数,当前任务数:" + outWrkMasts.size());
            }
            wrkMast.setDualCrnNo(findCrnResult.getCrnNo());
        }else {
            throw new CoolException("未知设备类型");
        }
        boolean res = wrkMastService.insert(wrkMast);
        if (!res) {
            News.error("出库任务 --- 保存工作档失败!");
@@ -309,27 +347,53 @@
        return true;
    }
    public Integer findCrnNoByLocNo(String locNo) {
    public FindCrnNoResult findCrnNoByLocNo(String locNo) {
        List<BasCrnp> basCrnps = basCrnpService.selectList(new EntityWrapper<>());
        for (BasCrnp basCrnp : basCrnps) {
            List<List<Integer>> rowList = basCrnp.getControlRows$();
            for (List<Integer> rows : rowList) {
                if(rows.contains(Utils.getRow(locNo))) {
                    return basCrnp.getCrnNo();
                    FindCrnNoResult result = new FindCrnNoResult();
                    result.setCrnNo(basCrnp.getCrnNo());
                    result.setCrnType(SlaveType.Crn);
                    return result;
                }
            }
        }
        List<BasDualCrnp> basDualCrnps = basDualCrnpService.selectList(new EntityWrapper<>());
        for (BasDualCrnp basDualCrnp : basDualCrnps) {
            List<List<Integer>> rowList = basDualCrnp.getControlRows$();
            for (List<Integer> rows : rowList) {
                if(rows.contains(Utils.getRow(locNo))) {
                    FindCrnNoResult result = new FindCrnNoResult();
                    result.setCrnNo(basDualCrnp.getCrnNo());
                    result.setCrnType(SlaveType.DualCrn);
                    return result;
                }
            }
        }
        return null;
    }
    public Integer findInStationId(Integer crnNo, Integer sourceStationId) {
        BasCrnp basCrnp = basCrnpService.selectOne(new EntityWrapper<BasCrnp>().eq("crn_no", crnNo));
        if(basCrnp == null) {
            return null;
    public Integer findInStationId(FindCrnNoResult findCrnNoResult, Integer sourceStationId) {
        List<StationObjModel> stationList = new ArrayList<>();
        Integer crnNo = findCrnNoResult.getCrnNo();
        if (findCrnNoResult.getCrnType().equals(SlaveType.Crn)) {
            BasCrnp basCrnp = basCrnpService.selectOne(new EntityWrapper<BasCrnp>().eq("crn_no", crnNo));
            if(basCrnp == null) {
                return null;
            }
            stationList = basCrnp.getInStationList$();
        } else if (findCrnNoResult.getCrnType().equals(SlaveType.DualCrn)) {
            BasDualCrnp basDualCrnp = basDualCrnpService.selectOne(new EntityWrapper<BasDualCrnp>().eq("crn_no", crnNo));
            if(basDualCrnp == null) {
                return null;
            }
            stationList = basDualCrnp.getInStationList$();
        }
        Integer targetStationId = null;
        List<StationObjModel> stationList = basCrnp.getInStationList$();
        for (StationObjModel stationObjModel : stationList) {
            try {
                List<NavigateNode> navigateNodes = navigateUtils.calcByStationId(sourceStationId, stationObjModel.getStationId());
@@ -344,14 +408,24 @@
        return targetStationId;
    }
    public Integer findOutStationId(Integer crnNo, Integer targetStationId) {
        BasCrnp basCrnp = basCrnpService.selectOne(new EntityWrapper<BasCrnp>().eq("crn_no", crnNo));
        if(basCrnp == null) {
            return null;
    public Integer findOutStationId(FindCrnNoResult findCrnNoResult, Integer targetStationId) {
        List<StationObjModel> stationList = new ArrayList<>();
        Integer crnNo = findCrnNoResult.getCrnNo();
        if (findCrnNoResult.getCrnType().equals(SlaveType.Crn)) {
            BasCrnp basCrnp = basCrnpService.selectOne(new EntityWrapper<BasCrnp>().eq("crn_no", crnNo));
            if(basCrnp == null) {
                return null;
            }
            stationList = basCrnp.getOutStationList$();
        } else if (findCrnNoResult.getCrnType().equals(SlaveType.DualCrn)) {
            BasDualCrnp basDualCrnp = basDualCrnpService.selectOne(new EntityWrapper<BasDualCrnp>().eq("crn_no", crnNo));
            if(basDualCrnp == null) {
                return null;
            }
            stationList = basDualCrnp.getOutStationList$();
        }
        Integer finalSourceStationId = null;
        List<StationObjModel> stationList = basCrnp.getOutStationList$();
        for (StationObjModel stationObjModel : stationList) {
            try {
                List<NavigateNode> navigateNodes = navigateUtils.calcByStationId(stationObjModel.getStationId(), targetStationId);
src/main/java/com/zy/core/enums/RedisKeyType.java
@@ -9,6 +9,8 @@
    LIFT_WORK_FLAG("lift_wrk_no_"),
    LIFT_FLAG("lift_"),
    DUAL_CRN_COMMAND_("dual_crn_command_"),
    QUEUE_CRN("queue_crn_"),
    QUEUE_DEVP("queue_devp_"),
    QUEUE_RGV("queue_rgv_"),
@@ -31,11 +33,14 @@
    CHECK_OUT_STATION_STAY_TIME_OUT_LIMIT("check_out_station_stay_time_out_limit_"),
    CHECK_IN_STATION_STAY_TIME_OUT_LIMIT("check_in_station_stay_time_out_limit_"),
    CRN_IO_EXECUTE_FINISH_LIMIT("crn_io_execute_finish_limit_"),
    DUAL_CRN_IO_EXECUTE_FINISH_LIMIT("dual_crn_io_execute_finish_limit_"),
    STATION_IN_EXECUTE_LIMIT("station_in_execute_limit_"),
    STATION_OUT_EXECUTE_LIMIT("station_out_execute_limit_"),
    CHECK_STATION_RUN_BLOCK_LIMIT_("check_station_run_block_limit_"),
    CHECK_SHALLOW_LOC_STATUS_LIMIT("check_shallow_loc_status_limit_"),
    DUAL_CRN_PICK_WAIT_NEXT_TASK("dual_crn_pick_wait_next_task_"),
    CURRENT_CIRCLE_TASK_CRN_NO("current_circle_task_crn_no_"),
    AI_CHAT_HISTORY("ai_chat_history_"),
    AI_CHAT_META("ai_chat_meta_"),
src/main/java/com/zy/core/network/fake/ZyDualCrnFakeConnect.java
@@ -64,11 +64,15 @@
    private void commandTaskComplete(DualCrnCommand command) {
        if(command.getStation() == 1) {
            this.crnStatus.setTaskNo(0);
            if (crnStatus.getLoaded() == 0) {
                this.crnStatus.setTaskNo(0);
            }
            this.crnStatus.setTaskReceive(0);
            this.crnStatus.setStatus(CrnStatusType.IDLE.id);
        }else {
            this.crnStatus.setTaskNoTwo(0);
            if (crnStatus.getLoadedTwo() == 0) {
                this.crnStatus.setTaskNoTwo(0);
            }
            this.crnStatus.setTaskReceiveTwo(0);
            this.crnStatus.setStatusTwo(CrnStatusType.IDLE.id);
        }
src/main/java/com/zy/core/plugin/FakeProcess.java
@@ -8,6 +8,7 @@
import com.zy.asrs.domain.param.CreateOutTaskParam;
import com.zy.asrs.entity.*;
import com.zy.asrs.service.*;
import com.zy.common.entity.FindCrnNoResult;
import com.zy.common.model.StartupDto;
import com.zy.common.service.CommonService;
import com.zy.common.utils.RedisUtil;
@@ -20,11 +21,14 @@
import com.zy.core.model.command.CrnCommand;
import com.zy.core.model.command.StationCommand;
import com.zy.core.model.protocol.CrnProtocol;
import com.zy.core.model.protocol.DualCrnProtocol;
import com.zy.core.model.protocol.StationProtocol;
import com.zy.core.properties.SystemProperties;
import com.zy.core.thread.CrnThread;
import com.zy.core.thread.DualCrnThread;
import com.zy.core.thread.StationThread;
import com.zy.core.utils.CrnOperateProcessUtils;
import com.zy.core.utils.DualCrnOperateProcessUtils;
import com.zy.core.utils.StationOperateProcessUtils;
import com.zy.core.utils.WmsOperateUtils;
import com.zy.system.entity.Config;
@@ -61,6 +65,8 @@
    @Autowired
    private BasCrnpService basCrnpService;
    @Autowired
    private BasDualCrnpService basDualCrnpService;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private CrnOperateProcessUtils crnOperateUtils;
@@ -68,6 +74,8 @@
    private StationOperateProcessUtils stationOperateProcessUtils;
    @Autowired
    private WmsOperateUtils wmsOperateUtils;
    @Autowired
    private DualCrnOperateProcessUtils dualCrnOperateProcessUtils;
    @Override
    public void run() {
@@ -84,6 +92,11 @@
        stationOperateProcessUtils.stationOutExecute();
        //检测输送站点出库任务执行完成
        stationOperateProcessUtils.stationOutExecuteFinish();
        //执行双工位堆垛机任务
        dualCrnOperateProcessUtils.dualRrnIoExecute();
        //双工位堆垛机任务执行完成
        dualCrnOperateProcessUtils.dualCrnIoExecuteFinish();
    }
    public void asyncRun() {
@@ -293,12 +306,12 @@
                    int nextInt = new Random().nextInt(locMastList.size());
                    LocMast locMast = locMastList.get(nextInt);
                    Integer crnNo = commonService.findCrnNoByLocNo(locMast.getLocNo());
                    if (crnNo == null) {
                    FindCrnNoResult findCrnNoResult = commonService.findCrnNoByLocNo(locMast.getLocNo());
                    if (findCrnNoResult == null) {
                        continue;
                    }
                    Integer targetStationId = commonService.findInStationId(crnNo, stationId);
                    Integer targetStationId = commonService.findInStationId(findCrnNoResult, stationId);
                    if (targetStationId == null) {
                        continue;
                    }
@@ -374,11 +387,6 @@
                    }
                    LocMast locMast = locMastList.get(0);
                    Integer crnNo = commonService.findCrnNoByLocNo(locMast.getLocNo());
                    if (crnNo == null) {
                        continue;
                    }
                    CreateOutTaskParam taskParam = new CreateOutTaskParam();
                    taskParam.setTaskNo(String.valueOf(commonService.getWorkNo(WrkIoType.OUT.id)));
@@ -541,38 +549,53 @@
                News.info("堆垛机:{} 入库站点未设置", basCrnp.getCrnNo());
                continue;
            }
            checkInStationListCrnTake(inStationList);
        }
            for (StationObjModel stationObjModel : inStationList) {
                Object lock = redisUtil.get(RedisKeyType.CHECK_IN_STATION_STAY_TIME_OUT_LIMIT.key + stationObjModel.getStationId());
                if(lock != null){
                    continue;
                }
        List<BasDualCrnp> basDualCrnps = basDualCrnpService.selectList(new EntityWrapper<>());
        for (BasDualCrnp basDualCrnp : basDualCrnps) {
            List<StationObjModel> inStationList = basDualCrnp.getInStationList$();
            if(inStationList.isEmpty()){
                News.info("双工位堆垛机:{} 入库站点未设置", basDualCrnp.getCrnNo());
                continue;
            }
            checkInStationListCrnTake(inStationList);
        }
    }
                StationThread stationThread = (StationThread) SlaveConnection.get(SlaveType.Devp, stationObjModel.getDeviceNo());
                if(stationThread == null){
                    continue;
                }
    private void checkInStationListCrnTake(List<StationObjModel> inStationList) {
        for (StationObjModel stationObjModel : inStationList) {
            Object lock = redisUtil.get(RedisKeyType.CHECK_IN_STATION_STAY_TIME_OUT_LIMIT.key + stationObjModel.getStationId());
            if(lock != null){
                continue;
            }
                StationCommand command = stationThread.getMoveCommand(0, stationObjModel.getStationId(), 0, 0);
                if(command == null){
                    continue;
                }
            StationThread stationThread = (StationThread) SlaveConnection.get(SlaveType.Devp, stationObjModel.getDeviceNo());
            if(stationThread == null){
                continue;
            }
                Map<Integer, StationProtocol> statusMap = stationThread.getStatusMap();
                StationProtocol stationProtocol = statusMap.get(stationObjModel.getStationId());
                if (stationProtocol == null) {
                    continue;
                }
            StationCommand command = stationThread.getMoveCommand(0, stationObjModel.getStationId(), 0, 0);
            if(command == null){
                continue;
            }
                if(stationProtocol.getTaskNo() > 0) {
                    WrkMast wrkMast = wrkMastService.selectByWorkNo(stationProtocol.getTaskNo());
                    if (wrkMast == null) {
                        MessageQueue.offer(SlaveType.Devp, stationObjModel.getDeviceNo(), new Task(2, command));
                        redisUtil.set(RedisKeyType.CHECK_IN_STATION_STAY_TIME_OUT_LIMIT.key + stationObjModel.getStationId(), "lock",10);
                        News.info("输送站点重置命令下发成功(task_over),站点号={},命令数据={}", stationObjModel.getStationId(), JSON.toJSONString(command));
                    }else {
                        if (wrkMast.getWrkSts() != WrkStsType.NEW_INBOUND.sts && wrkMast.getWrkSts() != WrkStsType.INBOUND_DEVICE_RUN.sts) {
                            Integer crnNo = wrkMast.getCrnNo();
            Map<Integer, StationProtocol> statusMap = stationThread.getStatusMap();
            StationProtocol stationProtocol = statusMap.get(stationObjModel.getStationId());
            if (stationProtocol == null) {
                continue;
            }
            if(stationProtocol.getTaskNo() > 0) {
                WrkMast wrkMast = wrkMastService.selectByWorkNo(stationProtocol.getTaskNo());
                if (wrkMast == null) {
                    MessageQueue.offer(SlaveType.Devp, stationObjModel.getDeviceNo(), new Task(2, command));
                    redisUtil.set(RedisKeyType.CHECK_IN_STATION_STAY_TIME_OUT_LIMIT.key + stationObjModel.getStationId(), "lock",10);
                    News.info("输送站点重置命令下发成功(task_over),站点号={},命令数据={}", stationObjModel.getStationId(), JSON.toJSONString(command));
                }else {
                    if (wrkMast.getWrkSts() != WrkStsType.NEW_INBOUND.sts && wrkMast.getWrkSts() != WrkStsType.INBOUND_DEVICE_RUN.sts) {
                        Integer crnNo = wrkMast.getCrnNo();
                        if (crnNo != null) {
                            CrnThread crnThread = (CrnThread) SlaveConnection.get(SlaveType.Crn, crnNo);
                            if (crnThread == null) {
                                continue;
@@ -585,6 +608,20 @@
                            MessageQueue.offer(SlaveType.Devp, stationObjModel.getDeviceNo(), new Task(2, command));
                            redisUtil.set(RedisKeyType.CHECK_IN_STATION_STAY_TIME_OUT_LIMIT.key + stationObjModel.getStationId(), "lock",10);
                            News.info("输送站点重置命令下发成功(crn_fetch),站点号={},命令数据={}", stationObjModel.getStationId(), JSON.toJSONString(command));
                        }else {
                            Integer dualCrnNo = wrkMast.getDualCrnNo();
                            DualCrnThread dualCrnThread = (DualCrnThread) SlaveConnection.get(SlaveType.DualCrn, dualCrnNo);
                            if (dualCrnThread == null) {
                                continue;
                            }
                            DualCrnProtocol dualCrnProtocol = dualCrnThread.getStatus();
                            if (!dualCrnProtocol.getStatusType().equals(DualCrnStatusType.PUT_MOVING) && !dualCrnProtocol.getStatusType().equals(DualCrnStatusType.PUTTING)) {
                                continue;
                            }
                            MessageQueue.offer(SlaveType.Devp, stationObjModel.getDeviceNo(), new Task(2, command));
                            redisUtil.set(RedisKeyType.CHECK_IN_STATION_STAY_TIME_OUT_LIMIT.key + stationObjModel.getStationId(), "lock",10);
                            News.info("输送站点重置命令下发成功(crn_fetch),站点号={},命令数据={}", stationObjModel.getStationId(), JSON.toJSONString(command));
                        }
                    }
                }
src/main/java/com/zy/core/thread/impl/ZySiemensDualCrnThread.java
@@ -1,6 +1,8 @@
package com.zy.core.thread.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.core.common.DateUtils;
import com.core.common.SpringUtils;
@@ -12,11 +14,10 @@
import com.zy.asrs.service.BasDualCrnpService;
import com.zy.asrs.utils.Utils;
import com.zy.common.utils.RedisUtil;
import com.zy.core.News;
import com.zy.core.cache.MessageQueue;
import com.zy.core.cache.OutputQueue;
import com.zy.core.enums.DualCrnTaskModeType;
import com.zy.core.enums.RedisKeyType;
import com.zy.core.enums.SlaveType;
import com.zy.core.enums.*;
import com.zy.core.model.CommandResponse;
import com.zy.core.model.Task;
import com.zy.core.model.command.DualCrnCommand;
@@ -30,6 +31,8 @@
import java.text.MessageFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
@@ -51,6 +54,7 @@
    private volatile boolean closed = false;
    private ScheduledExecutorService readExecutor;
    private ScheduledExecutorService processExecutor;
    private ScheduledExecutorService commandExecutor;
    public ZySiemensDualCrnThread(DeviceConfig deviceConfig, RedisUtil redisUtil) {
        this.deviceConfig = deviceConfig;
@@ -102,13 +106,93 @@
                if (task != null) {
                    step = task.getStep();
                }
                if (step == 2 && task != null) {
                if (step == 2) {
                    List<DualCrnCommand> commandList = (List<DualCrnCommand>) task.getData();
                    DualCrnCommand command = commandList.get(0);
                    HashMap<String, Object> map = new HashMap<>();
                    map.put("commands", commandList);
                    map.put("idx", 1);
                    redisUtil.set(RedisKeyType.DUAL_CRN_COMMAND_.key + command.getTaskNo(), JSON.toJSONString(map, SerializerFeature.DisableCircularReferenceDetect), 60 * 60 * 24);
                    sendCommand(command);
                } else if (step == 3) {
                    sendCommand((DualCrnCommand) task.getData());
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }, 0, 200, TimeUnit.MILLISECONDS);
        commandExecutor = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                Thread t = new Thread(r);
                t.setName("DualCrnCommand-" + deviceConfig.getDeviceNo());
                t.setDaemon(true);
                return t;
            }
        });
        commandExecutor.scheduleAtFixedRate(() -> {
            if (closed || Thread.currentThread().isInterrupted()) {
                return;
            }
            try {
                if(crnProtocol.getMode() != DualCrnModeType.AUTO.id) {
                    return;
                }
                if(crnProtocol.getAlarm() != 0) {
                    return;
                }
                //等待下一个任务
                Object wait = redisUtil.get(RedisKeyType.DUAL_CRN_PICK_WAIT_NEXT_TASK.key + crnProtocol.getCrnNo());
                if (wait != null) {
                    return;
                }
                if(crnProtocol.getTaskNo() > 0 && crnProtocol.getStatus() == DualCrnStatusType.IDLE.id) {
                    Integer taskNo = crnProtocol.getTaskNo();
                    Object commandObj = redisUtil.get(RedisKeyType.DUAL_CRN_COMMAND_.key + taskNo);
                    if (commandObj == null) {
                        News.error("双工位堆垛机,工位1空闲等待下发命令,但未找到命令。堆垛机号={},工作号={}", crnProtocol.getCrnNo(), taskNo);
                        return;
                    }
                    JSONObject commandMap = JSON.parseObject(commandObj.toString());
                    Integer idx = commandMap.getInteger("idx");
                    List<DualCrnCommand> commandList = commandMap.getJSONArray("commands").toJavaList(DualCrnCommand.class);
                    DualCrnCommand dualCommand = commandList.get(idx);
                    idx++;
                    commandMap.put("idx", idx);
                    sendCommand(dualCommand);
                    redisUtil.set(RedisKeyType.DUAL_CRN_COMMAND_.key + taskNo, commandMap.toJSONString(), 60 * 60 * 24);
                }
                if(crnProtocol.getTaskNoTwo() > 0 && crnProtocol.getStatusTwo() == DualCrnStatusType.IDLE.id) {
                    Integer taskNo = crnProtocol.getTaskNoTwo();
                    Object commandObj = redisUtil.get(RedisKeyType.DUAL_CRN_COMMAND_.key + taskNo);
                    if (commandObj == null) {
                        News.error("双工位堆垛机,工位2空闲等待下发命令,但未找到命令。堆垛机号={},工作号={}", crnProtocol.getCrnNo(), taskNo);
                        return;
                    }
                    JSONObject commandMap = JSON.parseObject(commandObj.toString());
                    Integer idx = commandMap.getInteger("idx");
                    List<DualCrnCommand> commandList = commandMap.getJSONArray("commands").toJavaList(DualCrnCommand.class);
                    DualCrnCommand dualCommand = commandList.get(idx);
                    idx++;
                    commandMap.put("idx", idx);
                    sendCommand(dualCommand);
                    redisUtil.set(RedisKeyType.DUAL_CRN_COMMAND_.key + taskNo, commandMap.toJSONString(), 60 * 60 * 24);
                }
            } catch (Exception e) {
                e.printStackTrace();
                log.error("DualCrnCommandThread Fail", e);
            }
        }, 0, 200, TimeUnit.MILLISECONDS);
    }
    /**
src/main/java/com/zy/core/utils/DualCrnOperateProcessUtils.java
New file
@@ -0,0 +1,495 @@
package com.zy.core.utils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.core.exception.CoolException;
import com.zy.asrs.domain.param.CreateLocMoveTaskParam;
import com.zy.asrs.entity.BasCrnp;
import com.zy.asrs.entity.BasDualCrnp;
import com.zy.asrs.entity.LocMast;
import com.zy.asrs.entity.WrkMast;
import com.zy.asrs.service.BasDualCrnpService;
import com.zy.asrs.service.LocMastService;
import com.zy.asrs.service.WrkMastService;
import com.zy.asrs.utils.Utils;
import com.zy.common.model.StartupDto;
import com.zy.common.service.CommonService;
import com.zy.common.utils.RedisUtil;
import com.zy.core.News;
import com.zy.core.cache.MessageQueue;
import com.zy.core.cache.SlaveConnection;
import com.zy.core.enums.*;
import com.zy.core.model.StationObjModel;
import com.zy.core.model.Task;
import com.zy.core.model.command.CrnCommand;
import com.zy.core.model.command.DualCrnCommand;
import com.zy.core.model.protocol.CrnProtocol;
import com.zy.core.model.protocol.DualCrnProtocol;
import com.zy.core.model.protocol.StationProtocol;
import com.zy.core.thread.CrnThread;
import com.zy.core.thread.DualCrnThread;
import com.zy.core.thread.StationThread;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Component
public class DualCrnOperateProcessUtils {
    @Autowired
    private WrkMastService wrkMastService;
    @Autowired
    private BasDualCrnpService basDualCrnpService;
    @Autowired
    private LocMastService locMastService;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private WmsOperateUtils wmsOperateUtils;
    @Autowired
    private CommonService commonService;
    //入出库  ===>>  双工位堆垛机入出库作业下发
    public synchronized void dualRrnIoExecute() {
        List<BasDualCrnp> basDualCrnps = basDualCrnpService.selectList(new EntityWrapper<>());
        for (BasDualCrnp basDualCrnp : basDualCrnps) {
            DualCrnThread dualCrnThread = (DualCrnThread) SlaveConnection.get(SlaveType.DualCrn, basDualCrnp.getCrnNo());
            if(dualCrnThread == null){
                continue;
            }
            DualCrnProtocol dualCrnProtocol = dualCrnThread.getStatus();
            if(dualCrnProtocol == null){
                continue;
            }
            List<WrkMast> wrkMasts = wrkMastService.selectList(new EntityWrapper<WrkMast>()
                    .eq("dual_crn_no", basDualCrnp.getCrnNo())
                    .in("wrk_sts", WrkStsType.INBOUND_RUN.sts, WrkStsType.OUTBOUND_RUN.sts)
            );
            if(wrkMasts.size() >= 2){
                continue;
            }
            if(dualCrnProtocol.getMode() != DualCrnModeType.AUTO.id) {
                continue;
            }
            if(dualCrnProtocol.getAlarm() != 0) {
                continue;
            }
            int executeTaskNo = 0;
            if (dualCrnProtocol.getTaskNo() > 0) {
                executeTaskNo = dualCrnProtocol.getTaskNo();
            }
            if (dualCrnProtocol.getTaskNoTwo() > 0) {
                executeTaskNo = dualCrnProtocol.getTaskNoTwo();
            }
            if (executeTaskNo > 0) {
                WrkMast wrkMast = wrkMastService.selectByWorkNo(executeTaskNo);
                if (wrkMast != null) {
                    if (wrkMast.getIoType().equals(WrkIoType.IN.id)) {
                        this.crnExecuteIn(basDualCrnp, dualCrnThread); //  入库
                    } else if (wrkMast.getIoType().equals(WrkIoType.OUT.id)) {
                        this.crnExecuteOut(basDualCrnp, dualCrnThread); //  出库
                    }else {
                        continue;
                    }
                }
            }
            // 如果最近一次是入库模式
            if (dualCrnProtocol.getLastIo().equals("I")) {
                if (basDualCrnp.getInEnable().equals("Y")) {
                    this.crnExecuteIn(basDualCrnp, dualCrnThread); //  入库
                    dualCrnProtocol.setLastIo("O");
                } else if (basDualCrnp.getOutEnable().equals("Y")) {
                    this.crnExecuteOut(basDualCrnp, dualCrnThread); //  出库
                    dualCrnProtocol.setLastIo("I");
                }
            }
            // 如果最近一次是出库模式
            else if (dualCrnProtocol.getLastIo().equals("O")) {
                if (basDualCrnp.getOutEnable().equals("Y")) {
                    this.crnExecuteOut(basDualCrnp, dualCrnThread); //  出库
                    dualCrnProtocol.setLastIo("I");
                } else if (basDualCrnp.getInEnable().equals("Y")) {
                    this.crnExecuteIn(basDualCrnp, dualCrnThread); //  入库
                    dualCrnProtocol.setLastIo("O");
                }
            }
        }
    }
    private synchronized void crnExecuteIn(BasDualCrnp basDualCrnp, DualCrnThread dualCrnThread) {
        DualCrnProtocol dualCrnProtocol = dualCrnThread.getStatus();
        if(dualCrnProtocol == null){
            return;
        }
        if(!basDualCrnp.getInEnable().equals("Y")){
            News.info("双工位堆垛机:{} 可入信号不满足", basDualCrnp.getCrnNo());
            return;
        }
        List<StationObjModel> inStationList = basDualCrnp.getInStationList$();
        if(inStationList.isEmpty()){
            News.info("双工位堆垛机:{} 入库站点未设置", basDualCrnp.getCrnNo());
            return;
        }
        Integer crnNo = basDualCrnp.getCrnNo();
        int station = calcStation(dualCrnProtocol);
        if(station == 0){
            News.info("双工位堆垛机:{} 无可用工位", basDualCrnp.getCrnNo());
            return;
        }
        for (StationObjModel stationObjModel : inStationList) {
            StationThread stationThread = (StationThread) SlaveConnection.get(SlaveType.Devp, stationObjModel.getDeviceNo());
            if (stationThread == null) {
                continue;
            }
            Map<Integer, StationProtocol> stationProtocolMap = stationThread.getStatusMap();
            StationProtocol stationProtocol = stationProtocolMap.get(stationObjModel.getStationId());
            if (stationProtocol == null) {
                continue;
            }
            if (!stationProtocol.isAutoing()) {
                continue;
            }
            if (!stationProtocol.isLoading()) {
                continue;
            }
            if (stationProtocol.getTaskNo() <= 0) {
                continue;
            }
            if (!stationProtocol.isInEnable()) {
                News.taskInfo(stationProtocol.getTaskNo(), "取货站点:{} 没有可入信号", stationObjModel.getStationId());
                continue;
            }
            // 获取任务
            WrkMast wrkMast = wrkMastService.selectByWorkNo(stationProtocol.getTaskNo());
            if (null == wrkMast) {
                News.taskInfo(stationProtocol.getTaskNo(), "工作号:{} 任务信息不存在", stationProtocol.getTaskNo());
                continue;
            }
            if(wrkMast.getWrkSts() != WrkStsType.INBOUND_DEVICE_RUN.sts){
                News.taskInfo(stationProtocol.getTaskNo(), "工作号:{} 任务状态异常", stationProtocol.getTaskNo());
                continue;
            }
            // 获取库位信息
            LocMast locMast = locMastService.selectById(wrkMast.getLocNo());
            if (locMast == null) {
                News.taskInfo(wrkMast.getWrkNo(), "目标库位:{} 信息不存在", wrkMast.getLocNo());
                continue;
            }
            if (!locMast.getLocSts().equals("S")) {
                News.taskInfo(wrkMast.getWrkNo(), "目标库位:{} 状态异常", wrkMast.getLocNo());
                continue;
            }
            //检测浅库位状态
            boolean checkStatus = checkShallowLocStatus(locMast.getLocNo(), wrkMast.getWrkNo());
            if (!checkStatus) {
                News.taskInfo(wrkMast.getWrkNo(), "因浅库位堵塞无法执行");
                continue;
            }
            String sourceLocNo = Utils.getLocNo(stationObjModel.getDeviceRow(), stationObjModel.getDeviceBay(), stationObjModel.getDeviceLev());
            List<DualCrnCommand> commandList = new ArrayList<>();
            DualCrnCommand pickCommand = dualCrnThread.getPickCommand(sourceLocNo, wrkMast.getWrkNo(), crnNo, station);
            DualCrnCommand putCommand = dualCrnThread.getPutCommand(wrkMast.getLocNo(), wrkMast.getWrkNo(), crnNo, station);
            commandList.add(pickCommand);
            commandList.add(putCommand);
            wrkMast.setWrkSts(WrkStsType.INBOUND_RUN.sts);
            wrkMast.setDualCrnNo(crnNo);
            wrkMast.setSystemMsg("");
            wrkMast.setIoTime(new Date());
            if (wrkMastService.updateById(wrkMast)) {
                MessageQueue.offer(SlaveType.DualCrn, crnNo, new Task(2, commandList));
                News.info("双工位堆垛机命令下发成功,堆垛机号={},任务数据={}", crnNo, JSON.toJSON(commandList));
            }
        }
    }
    private synchronized void crnExecuteOut(BasDualCrnp basDualCrnp, DualCrnThread dualCrnThread) {
        DualCrnProtocol dualCrnProtocol = dualCrnThread.getStatus();
        if(dualCrnProtocol == null){
            return;
        }
        if(!basDualCrnp.getOutEnable().equals("Y")){
            News.info("双工位堆垛机:{} 可出信号不满足", basDualCrnp.getCrnNo());
            return;
        }
        List<StationObjModel> outStationList = basDualCrnp.getOutStationList$();
        if(outStationList.isEmpty()){
            News.info("双工位堆垛机:{} 出库站点未设置", basDualCrnp.getCrnNo());
            return;
        }
        Integer crnNo = basDualCrnp.getCrnNo();
        int station = calcStation(dualCrnProtocol);
        if(station == 0){
            News.info("双工位堆垛机:{} 无可用工位", basDualCrnp.getCrnNo());
            return;
        }
        List<WrkMast> wrkMasts = wrkMastService.selectList(new EntityWrapper<WrkMast>()
                .eq("crn_no", crnNo)
                .eq("wrk_sts", WrkStsType.NEW_OUTBOUND.sts)
        );
        for (WrkMast wrkMast : wrkMasts) {
            for (StationObjModel stationObjModel : outStationList) {
                StationThread stationThread = (StationThread) SlaveConnection.get(SlaveType.Devp, stationObjModel.getDeviceNo());
                if (stationThread == null) {
                    continue;
                }
                Map<Integer, StationProtocol> stationProtocolMap = stationThread.getStatusMap();
                StationProtocol stationProtocol = stationProtocolMap.get(stationObjModel.getStationId());
                if (stationProtocol == null) {
                    continue;
                }
                if (!stationProtocol.isAutoing()) {
                    continue;
                }
                if (stationProtocol.isLoading()) {
                    continue;
                }
                if (stationProtocol.getTaskNo() != 0) {
                    continue;
                }
                if (!stationProtocol.isOutEnable()) {
                    News.info("放货站点:{} 没有可出信号", stationObjModel.getStationId());
                    continue;
                }
                // 获取库位信息
                LocMast locMast = locMastService.selectById(wrkMast.getSourceLocNo());
                if (locMast == null) {
                    News.taskInfo(wrkMast.getWrkNo(), "源库位:{} 信息不存在", wrkMast.getSourceLocNo());
                    continue;
                }
                if (!locMast.getLocSts().equals("R")) {
                    News.taskInfo(wrkMast.getWrkNo(), "源库位:{} 状态异常", wrkMast.getSourceLocNo());
                    continue;
                }
                //检测浅库位状态
                boolean checkStatus = checkShallowLocStatus(locMast.getLocNo(), wrkMast.getWrkNo());
                if (!checkStatus) {
                    News.taskInfo(wrkMast.getWrkNo(), "因浅库位堵塞无法执行");
                    continue;
                }
                String targetLocNo = Utils.getLocNo(stationObjModel.getDeviceRow(), stationObjModel.getDeviceBay(), stationObjModel.getDeviceLev());
                List<DualCrnCommand> commandList = new ArrayList<>();
                DualCrnCommand pickCommand = dualCrnThread.getPickCommand(wrkMast.getSourceLocNo(), wrkMast.getWrkNo(), crnNo, station);
                DualCrnCommand putCommand = dualCrnThread.getPutCommand(targetLocNo, wrkMast.getWrkNo(), crnNo, station);
                commandList.add(pickCommand);
                commandList.add(putCommand);
                wrkMast.setWrkSts(WrkStsType.OUTBOUND_RUN.sts);
                wrkMast.setDualCrnNo(crnNo);
                wrkMast.setSystemMsg("");
                wrkMast.setIoTime(new Date());
                if (wrkMastService.updateById(wrkMast)) {
                    MessageQueue.offer(SlaveType.DualCrn, crnNo, new Task(2, commandList));
                    //取货后等待下一个任务时长
                    redisUtil.set(RedisKeyType.DUAL_CRN_PICK_WAIT_NEXT_TASK.key + crnNo, "wait", 5);
                    News.info("双工位堆垛机命令下发成功,堆垛机号={},任务数据={}", crnNo, JSON.toJSON(commandList));
                    return;
                }
            }
        }
    }
    //双工位堆垛机任务执行完成
    public synchronized void dualCrnIoExecuteFinish() {
        List<BasDualCrnp> basDualCrnps = basDualCrnpService.selectList(new EntityWrapper<>());
        for (BasDualCrnp basDualCrnp : basDualCrnps) {
            DualCrnThread dualCrnThread = (DualCrnThread) SlaveConnection.get(SlaveType.DualCrn, basDualCrnp.getCrnNo());
            if(dualCrnThread == null){
                continue;
            }
            DualCrnProtocol dualCrnProtocol = dualCrnThread.getStatus();
            if(dualCrnProtocol == null){
                continue;
            }
            if(dualCrnProtocol.getMode() != DualCrnModeType.AUTO.id) {
                continue;
            }
            if(dualCrnProtocol.getAlarm() != 0) {
                continue;
            }
            if(dualCrnProtocol.getTaskNo() > 0 && dualCrnProtocol.getStatus() == DualCrnStatusType.WAITING.id) {
                executeFinish(basDualCrnp, dualCrnThread, dualCrnProtocol, dualCrnProtocol.getTaskNo(), 1);
                continue;
            }
            if(dualCrnProtocol.getTaskNoTwo() > 0 && dualCrnProtocol.getStatusTwo() == DualCrnStatusType.WAITING.id) {
                executeFinish(basDualCrnp, dualCrnThread, dualCrnProtocol, dualCrnProtocol.getTaskNoTwo(), 2);
                continue;
            }
        }
    }
    private void executeFinish(BasDualCrnp basDualCrnp, DualCrnThread dualCrnThread, DualCrnProtocol dualCrnProtocol, int taskNo, int station) {
        Object lock = redisUtil.get(RedisKeyType.DUAL_CRN_IO_EXECUTE_FINISH_LIMIT.key + basDualCrnp.getCrnNo() + "_" + taskNo);
        if (lock != null) {
            return;
        }
        // 获取待确认工作档
        WrkMast wrkMast = wrkMastService.selectByWorkNo(taskNo);
        if (wrkMast == null) {
            News.error("双工位堆垛机处于等待确认且任务完成状态,但未找到工作档。堆垛机号={},工作号={}", basDualCrnp.getCrnNo(), taskNo);
            return;
        }
        Object commandObj = redisUtil.get(RedisKeyType.DUAL_CRN_COMMAND_.key + wrkMast.getWrkNo());
        if (commandObj == null) {
            News.error("双工位堆垛机处于等待确认且任务完成状态,但未找到命令。堆垛机号={},工作号={}", basDualCrnp.getCrnNo(), taskNo);
            return;
        }
        JSONObject commandMap = JSON.parseObject(commandObj.toString());
        Integer idx = commandMap.getInteger("idx");
        List<DualCrnCommand> commandList = commandMap.getJSONArray("commands").toJavaList(DualCrnCommand.class);
        if (idx >= commandList.size()) {
            Long updateWrkSts = null;
            if (wrkMast.getWrkSts() == WrkStsType.INBOUND_RUN.sts) {
                updateWrkSts = WrkStsType.COMPLETE_INBOUND.sts;
            } else if (wrkMast.getWrkSts() == WrkStsType.OUTBOUND_RUN.sts) {
                updateWrkSts = WrkStsType.OUTBOUND_RUN_COMPLETE.sts;
            } else if (wrkMast.getWrkSts() == WrkStsType.LOC_MOVE_RUN.sts) {
                updateWrkSts = WrkStsType.COMPLETE_LOC_MOVE.sts;
            } else {
                News.error("双工位堆垛机处于等待确认且任务完成状态,但工作状态异常。堆垛机号={},工作号={}", basDualCrnp.getCrnNo(), taskNo);
                return;
            }
            wrkMast.setWrkSts(updateWrkSts);
            wrkMast.setSystemMsg("");
            wrkMast.setIoTime(new Date());
            if (wrkMastService.updateById(wrkMast)) {
                DualCrnCommand resetCommand = dualCrnThread.getResetCommand(dualCrnProtocol.getCrnNo(), station);
                MessageQueue.offer(SlaveType.DualCrn, dualCrnProtocol.getCrnNo(), new Task(3, resetCommand));
                News.info("双工位堆垛机任务状态更新成功,堆垛机号={},工作号={}", basDualCrnp.getCrnNo(), taskNo);
            }
            redisUtil.set(RedisKeyType.DUAL_CRN_IO_EXECUTE_FINISH_LIMIT.key + basDualCrnp.getCrnNo() + "_" + taskNo, "lock", 10);
        }else {
            DualCrnCommand resetCommand = dualCrnThread.getResetCommand(dualCrnProtocol.getCrnNo(), station);
            MessageQueue.offer(SlaveType.DualCrn, dualCrnProtocol.getCrnNo(), new Task(3, resetCommand));
            News.info("双工位堆垛机命令完成确认成功,堆垛机号={},工作号={}", basDualCrnp.getCrnNo(), taskNo);
        }
    }
    //检测浅库位状态
    public synchronized boolean checkShallowLocStatus(String locNo, Integer taskNo) {
        String checkDeepLocOutTaskBlockReport = "Y";
        Object systemConfigMapObj = redisUtil.get(RedisKeyType.SYSTEM_CONFIG_MAP.key);
        if (systemConfigMapObj != null) {
            HashMap<String, String> systemConfigMap = (HashMap<String, String>) systemConfigMapObj;
            checkDeepLocOutTaskBlockReport = systemConfigMap.get("checkDeepLocOutTaskBlockReport");
        }
        if (!checkDeepLocOutTaskBlockReport.equals("Y")) {
            return true;
        }
        Object lock = redisUtil.get(RedisKeyType.CHECK_SHALLOW_LOC_STATUS_LIMIT.key + taskNo);
        if (lock != null) {
            return false;
        }
        redisUtil.set(RedisKeyType.CHECK_SHALLOW_LOC_STATUS_LIMIT.key + taskNo, "lock", 5);
        Integer shallowRow = Utils.getShallowRowByDeepRow(Utils.getRow(locNo));
        if (shallowRow == null) {
            return true;
        }
        String shallowLocNo = Utils.getLocNo(shallowRow, Utils.getBay(locNo), Utils.getLev(locNo));
        LocMast shallowLocMast = locMastService.queryByLoc(shallowLocNo);
        if (shallowLocMast == null) {
            News.taskInfo(taskNo, "浅库位:{} 数据不存在", shallowLocNo);
            return false;
        }
        if (shallowLocMast.getLocSts().equals("O")) {
            return true;
        }
        if (shallowLocMast.getLocSts().equals("F")) {
            //浅库位状态有货,申请更换库位
            String response = wmsOperateUtils.applyChangeLocNo(shallowLocNo);
            if (response == null) {
                News.taskError(taskNo, "WCS申请在库库位更换库位失败,WMS接口未响应!!!response:{}", response);
                return false;
            }
            JSONObject jsonObject = JSON.parseObject(response);
            if (jsonObject.getInteger("code").equals(200)) {
                StartupDto dto = jsonObject.getObject("data", StartupDto.class);
                String moveLocNo = dto.getLocNo();
                CreateLocMoveTaskParam moveTaskParam = new CreateLocMoveTaskParam();
                moveTaskParam.setTaskNo(dto.getTaskNo());
                moveTaskParam.setSourceLocNo(shallowLocNo);
                moveTaskParam.setLocNo(moveLocNo);
                try {
                    boolean result = commonService.createLocMoveTask(moveTaskParam);
                } catch (CoolException e) {
                    News.taskInfo(taskNo, e.getMessage());
                }
            } else {
                News.error("请求WMS申请更换库位接口失败!!!response:{}", response);
            }
        }
        return false;
    }
    private int calcStation(DualCrnProtocol dualCrnProtocol) {
        int station = 0;
        if(dualCrnProtocol.getTaskNo() == 0){
            station = 1;
        }else if (dualCrnProtocol.getTaskNoTwo() == 0){
            station = 2;
        }
        return station;
    }
}
src/main/java/com/zy/core/utils/StationOperateProcessUtils.java
@@ -3,8 +3,10 @@
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.core.exception.CoolException;
import com.zy.asrs.entity.*;
import com.zy.asrs.service.*;
import com.zy.common.entity.FindCrnNoResult;
import com.zy.common.model.StartupDto;
import com.zy.common.service.CommonService;
import com.zy.common.utils.RedisUtil;
@@ -91,13 +93,13 @@
                    }
                    String locNo = wrkMast.getLocNo();
                    Integer crnNo = commonService.findCrnNoByLocNo(locNo);
                    if (crnNo == null) {
                    FindCrnNoResult findCrnNoResult = commonService.findCrnNoByLocNo(locNo);
                    if (findCrnNoResult == null) {
                        News.taskInfo(wrkMast.getWrkNo(), "未匹配到堆垛机");
                        continue;
                    }
                    Integer targetStationId = commonService.findInStationId(crnNo, stationId);
                    Integer targetStationId = commonService.findInStationId(findCrnNoResult, stationId);
                    if (targetStationId == null) {
                        News.taskInfo(wrkMast.getWrkNo(), "搜索入库站点失败");
                        continue;
@@ -246,7 +248,7 @@
                    if (runBlockReassignLocStationList.contains(stationProtocol.getStationId())) {
                        //站点处于重新分配库位区域
                        //运行堵塞,重新申请任务
                        String response = wmsOperateUtils.applyReassignTaskLocNo(wrkMast.getWrkNo());
                        String response = wmsOperateUtils.applyReassignTaskLocNo(wrkMast.getWrkNo(), stationProtocol.getStationId());
                        if (response == null) {
                            News.taskError(wrkMast.getWrkNo(), "请求WMS重新分配库位接口失败,接口未响应!!!response:{}", response);
                            continue;
@@ -280,13 +282,14 @@
                                continue;
                            }
                            Integer crnNo = commonService.findCrnNoByLocNo(locNo);
                            if (crnNo == null) {
                            FindCrnNoResult findCrnNoResult = commonService.findCrnNoByLocNo(locNo);
                            if (findCrnNoResult == null) {
                                News.taskInfo(wrkMast.getWrkNo(), "未匹配到堆垛机");
                                continue;
                            }
                            Integer crnNo = findCrnNoResult.getCrnNo();
                            Integer targetStationId = commonService.findInStationId(crnNo, stationProtocol.getStationId());
                            Integer targetStationId = commonService.findInStationId(findCrnNoResult, stationProtocol.getStationId());
                            if (targetStationId == null) {
                                News.taskInfo(wrkMast.getWrkNo(), "搜索入库站点失败");
                                continue;
@@ -310,8 +313,16 @@
                            //更新工作档数据
                            wrkMast.setLocNo(locNo);
                            wrkMast.setCrnNo(crnNo);
                            wrkMast.setStaNo(targetStationId);
                            if (findCrnNoResult.getCrnType().equals(SlaveType.Crn)) {
                                wrkMast.setCrnNo(crnNo);
                            } else if (findCrnNoResult.getCrnType().equals(SlaveType.DualCrn)) {
                                wrkMast.setDualCrnNo(crnNo);
                            }else {
                                throw new CoolException("未知设备类型");
                            }
                            if (wrkMastService.updateById(wrkMast)) {
                                MessageQueue.offer(SlaveType.Devp, basDevp.getDevpNo(), new Task(2, command));
                            }
src/main/java/com/zy/core/utils/WmsOperateUtils.java
@@ -3,16 +3,22 @@
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.core.common.Cools;
import com.core.exception.CoolException;
import com.zy.asrs.entity.BasCrnp;
import com.zy.asrs.entity.BasDualCrnp;
import com.zy.asrs.entity.HttpRequestLog;
import com.zy.asrs.entity.WrkMast;
import com.zy.asrs.service.BasCrnpService;
import com.zy.asrs.service.BasDualCrnpService;
import com.zy.asrs.service.HttpRequestLogService;
import com.zy.asrs.service.WrkMastService;
import com.zy.asrs.utils.Utils;
import com.zy.common.entity.FindCrnNoResult;
import com.zy.common.service.CommonService;
import com.zy.common.utils.HttpHandler;
import com.zy.core.News;
import com.zy.core.enums.SlaveType;
import com.zy.system.entity.Config;
import com.zy.system.service.ConfigService;
import org.springframework.beans.factory.annotation.Autowired;
@@ -37,6 +43,8 @@
    private CommonService commonService;
    @Autowired
    private BasCrnpService basCrnpService;
    @Autowired
    private BasDualCrnpService basDualCrnpService;
    //申请入库任务
    public synchronized String applyInTask(String barcode, Integer sourceStaNo, Integer locType1) {
@@ -69,7 +77,7 @@
            requestParam.put("barcode", barcode);
            requestParam.put("sourceStaNo", sourceStaNo);
            requestParam.put("locType1", locType1);
            requestParam.put("row", Utils.getInTaskEnableRow());
            requestParam.put("row", Utils.getInTaskEnableRow(sourceStaNo));
            response = new HttpHandler.Builder()
                    .setUri(wmsUrl)
@@ -104,7 +112,7 @@
    }
    //申请任务重新分配库位
    public synchronized String applyReassignTaskLocNo(Integer taskNo) {
    public synchronized String applyReassignTaskLocNo(Integer taskNo, Integer stationId) {
        String wmsUrl = null;
        Config wmsSystemUriConfig = configService.selectOne(new EntityWrapper<Config>().eq("code", "wmsSystemUri"));
        if (wmsSystemUriConfig != null) {
@@ -122,7 +130,7 @@
            wmsSystemReassignInTaskUrl = wmsSystemReassignInTaskUrlConfig.getValue();
        }
        if(wmsSystemReassignInTaskUrl == null){
        if (wmsSystemReassignInTaskUrl == null) {
            News.error("未配置WMS任务重新分配入库库位接口地址,配置文件Code编码:wmsSystemReassignInTaskUrl");
            return null;
        }
@@ -137,8 +145,17 @@
        String response = null;
        int result = 0;
        try {
            List<Integer> excludeCrnList = new ArrayList<>();
            List<Integer> excludeDualCrnList = new ArrayList<>();
            if (!Cools.isEmpty(wrkMast.getCrnNo())) {
                excludeCrnList.add(wrkMast.getCrnNo());
            }
            if (!Cools.isEmpty(wrkMast.getDualCrnNo())) {
                excludeDualCrnList.add(wrkMast.getDualCrnNo());
            }
            requestParam.put("taskNo", wrkMast.getWmsWrkNo());
            requestParam.put("row", Utils.getInTaskEnableRow(new ArrayList<>(wrkMast.getCrnNo()), false));
            requestParam.put("row", Utils.getInTaskEnableRow(stationId, excludeCrnList, excludeDualCrnList, false));
            response = new HttpHandler.Builder()
                    .setUri(wmsUrl)
@@ -152,10 +169,10 @@
                if (jsonObject.getInteger("code") == 200) {
                    result = 1;
                    News.info("请求申请任务重新分配入库接口成功!!!url:{};request:{};response:{}", wmsUrl + wmsSystemReassignInTaskUrl, JSON.toJSONString(requestParam), response);
                }else {
                } else {
                    News.info("请求申请任务重新分配入库接口失败,接口返回Code异常!!!url:{};request:{};response:{}", wmsUrl + wmsSystemReassignInTaskUrl, JSON.toJSONString(requestParam), response);
                }
            }else {
            } else {
                News.info("请求申请任务重新分配入库接口失败,接口未响应!!!url:{};request:{};response:{}", wmsUrl + wmsSystemReassignInTaskUrl, JSON.toJSONString(requestParam), response);
            }
        } catch (Exception e) {
@@ -196,19 +213,33 @@
            return null;
        }
        Integer crnNo = commonService.findCrnNoByLocNo(locNo);
        if (crnNo == null) {
        FindCrnNoResult findCrnNoResult = commonService.findCrnNoByLocNo(locNo);
        if (findCrnNoResult == null) {
            return null;
        }
        BasCrnp basCrnp = basCrnpService.selectOne(new EntityWrapper<BasCrnp>().eq("crn_no", crnNo));
        if (basCrnp == null) {
            return null;
        }
        Integer crnNo = findCrnNoResult.getCrnNo();
        List<Integer> crnRows = new ArrayList<>();
        List<List<Integer>> rowList = basCrnp.getControlRows$();
        for (List<Integer> list : rowList) {
            crnRows.addAll(list);
        if (findCrnNoResult.getCrnType().equals(SlaveType.Crn)) {
            BasCrnp basCrnp = basCrnpService.selectOne(new EntityWrapper<BasCrnp>().eq("crn_no", crnNo));
            if (basCrnp == null) {
                return null;
            }
            List<List<Integer>> rowList = basCrnp.getControlRows$();
            for (List<Integer> list : rowList) {
                crnRows.addAll(list);
            }
        } else if (findCrnNoResult.getCrnType().equals(SlaveType.DualCrn)) {
            BasDualCrnp basDualCrnp = basDualCrnpService.selectOne(new EntityWrapper<BasDualCrnp>().eq("crn_no", crnNo));
            if (basDualCrnp == null) {
                return null;
            }
            List<List<Integer>> rowList = basDualCrnp.getControlRows$();
            for (List<Integer> list : rowList) {
                crnRows.addAll(list);
            }
        }else {
            throw new CoolException("未知设备类型");
        }
        HashMap<String, Object> requestParam = new HashMap<>();
src/main/resources/mapper/WrkMastLogMapper.xml
@@ -23,8 +23,9 @@
        <result column="error_memo" property="errorMemo" />
        <result column="memo" property="memo" />
        <result column="barcode" property="barcode" />
        <result column="lift_no" property="liftNo" />
        <result column="shuttle_no" property="shuttleNo" />
        <result column="crn_no" property="crnNo" />
        <result column="dual_crn_no" property="dualCrnNo" />
        <result column="rgv_no" property="rgvNo" />
        <result column="wms_wrk_no" property="wmsWrkNo" />
        <result column="system_msg" property="systemMsg" />
    </resultMap>
src/main/resources/mapper/WrkMastMapper.xml
@@ -23,6 +23,7 @@
        <result column="memo" property="memo" />
        <result column="barcode" property="barcode" />
        <result column="crn_no" property="crnNo" />
        <result column="dual_crn_no" property="dualCrnNo" />
        <result column="rgv_no" property="rgvNo" />
        <result column="wms_wrk_no" property="wmsWrkNo" />
        <result column="system_msg" property="systemMsg" />
src/main/webapp/static/js/basDualCrnp/basDualCrnp.js
@@ -24,7 +24,7 @@
            {type: 'checkbox'}
            ,{field: 'crnNo', align: 'center',title: '编号'}
            ,{field: 'status$', align: 'center',title: '状态'}
            ,{field: 'wrkNo', align: 'center',title: '工作号'}
            // ,{field: 'wrkNo', align: 'center',title: '工作号'}
            ,{field: 'inEnable', align: 'center',title: '可入(checkBox)'}
            ,{field: 'outEnable', align: 'center',title: '可出(checkBox)'}
            // ,{field: 'createBy', align: 'center',title: '创建人员'}
src/main/webapp/static/js/wrkMastLog/wrkMastLog.js
@@ -31,6 +31,7 @@
            ,{field: 'sourceLocNo', align: 'center',title: '源库位'}
            ,{field: 'locNo', align: 'center',title: '目标库位'}
            ,{field: 'crnNo', align: 'center',title: '堆垛机'}
            ,{field: 'dualCrnNo', align: 'center',title: '双工位堆垛机'}
            ,{field: 'modiUser$', align: 'center',title: '修改人员', hide:true}
            ,{field: 'modiTime$', align: 'center',title: '修改时间', hide:true}
            // ,{field: 'appeUser$', align: 'center',title: '创建者',event: 'appeUser', style: 'cursor:pointer'}
src/main/webapp/views/basDualCrnp/basDualCrnp.html
@@ -69,7 +69,7 @@
<!-- 表单弹窗 -->
<script type="text/html" id="editDialog">
    <form id="detail" lay-filter="detail" class="layui-form admin-form model-form">
        <input name="id" type="hidden">
        <input name="crnNo" type="hidden">
        <div class="layui-row">
            <div class="layui-col-md12">
                <div class="layui-form-item">
@@ -82,12 +82,12 @@
                        </select>
                    </div>
                </div>
                <div class="layui-form-item">
                    <label class="layui-form-label">工作号: </label>
                    <div class="layui-input-block">
                        <input class="layui-input" name="wrkNo" placeholder="请输入工作号">
                    </div>
                </div>
<!--                <div class="layui-form-item">-->
<!--                    <label class="layui-form-label">工作号: </label>-->
<!--                    <div class="layui-input-block">-->
<!--                        <input class="layui-input" name="wrkNo" placeholder="请输入工作号">-->
<!--                    </div>-->
<!--                </div>-->
                <div class="layui-form-item">
                    <label class="layui-form-label">可入(checkBox): </label>
                    <div class="layui-input-block">
src/main/webapp/views/wrkMast/wrkMast.html
@@ -58,6 +58,8 @@
                        </el-table-column>
                        <el-table-column property="crnNo" label="堆垛机">
                        </el-table-column>
                        <el-table-column property="dualCrnNo" label="双工位堆垛机">
                        </el-table-column>
                        <el-table-column property="systemMsg" label="系统消息">
                        </el-table-column>
                        <el-table-column label="操作" width="100">