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; @@ -154,6 +153,13 @@ private Integer crnNo; /** * 双工位堆垛机号 */ @ApiModelProperty(value= "双工位堆垛机号") @TableField(value = "dual_crn_no") private Integer dualCrnNo; /** * RGV号 */ @ApiModelProperty(value= "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; } //计算站点是否可达该堆垛机 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) { 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) { 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) { if (crnStatus.getLoaded() == 0) { this.crnStatus.setTaskNo(0); } this.crnStatus.setTaskReceive(0); this.crnStatus.setStatus(CrnStatusType.IDLE.id); }else { 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,7 +549,21 @@ News.info("堆垛机:{} 入库站点未设置", basCrnp.getCrnNo()); continue; } checkInStationListCrnTake(inStationList); } 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); } } 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){ @@ -573,6 +595,7 @@ }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) { @@ -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) @@ -196,20 +213,34 @@ return null; } Integer crnNo = commonService.findCrnNoByLocNo(locNo); if (crnNo == null) { FindCrnNoResult findCrnNoResult = commonService.findCrnNoByLocNo(locNo); if (findCrnNoResult == null) { return null; } Integer crnNo = findCrnNoResult.getCrnNo(); List<Integer> crnRows = new ArrayList<>(); if (findCrnNoResult.getCrnType().equals(SlaveType.Crn)) { BasCrnp basCrnp = basCrnpService.selectOne(new EntityWrapper<BasCrnp>().eq("crn_no", crnNo)); if (basCrnp == null) { return null; } List<Integer> crnRows = new ArrayList<>(); 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<>(); String response = null; 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">