package com.vincent.rsf.server.api.utils; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.vincent.rsf.framework.common.Arith; import com.vincent.rsf.framework.common.Cools; import com.vincent.rsf.framework.common.SpringUtils; import com.vincent.rsf.framework.exception.CoolException; import com.vincent.rsf.server.api.controller.params.TaskInParam; import com.vincent.rsf.server.api.entity.dto.InTaskMsgDto; import com.vincent.rsf.server.api.entity.dto.LocTypeDto; import com.vincent.rsf.server.manager.entity.*; import com.vincent.rsf.server.manager.enums.LocStsType; import com.vincent.rsf.server.manager.enums.TaskStsType; import com.vincent.rsf.server.manager.enums.TaskType; import com.vincent.rsf.server.manager.service.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; import javax.annotation.RegEx; import javax.annotation.Resource; import java.util.List; @Component public class LocUtils { public static final Logger logger = LoggerFactory.getLogger(LocUtils.class); private static List doubleLocs; private static Boolean isDoubleDeep; @Autowired private SlaveProperties slavePropertie; @PostConstruct public void init() { doubleLocs = slavePropertie.getDoubleLocs(); isDoubleDeep = slavePropertie.isDoubleDeep(); } /** * 获取 浅库位对应的深库位号 */ public static String getDeepLoc(String shallowLoc) { LocService locService = SpringUtils.getBean(LocService.class); Loc shaLoc = locService.getOne(new LambdaQueryWrapper().eq(Loc::getCode, shallowLoc)); int row = shaLoc.getRow()-1; boolean contains = doubleLocs.contains(row); Loc deepLoc = null; if (contains) { deepLoc = locService.getOne(new LambdaQueryWrapper() .eq(Loc::getAreaId, shaLoc.getAreaId()) .eq(Loc::getRow, row) .eq(Loc::getCol, shaLoc.getCol()) .eq(Loc::getLev, shaLoc.getLev()) ); }else { deepLoc = locService.getOne(new LambdaQueryWrapper() .eq(Loc::getAreaId, shaLoc.getAreaId()) .eq(Loc::getRow, shaLoc.getRow()+1) .eq(Loc::getCol, shaLoc.getCol()) .eq(Loc::getLev, shaLoc.getLev()) ); } return deepLoc.getCode(); } /** * 获取 深库位对应的浅库位号 */ public static String getShallowLoc(String deepLoc) { LocService locService = SpringUtils.getBean(LocService.class); Loc depLoc = locService.getOne(new LambdaQueryWrapper().eq(Loc::getCode, deepLoc)); int row; if (depLoc.getRow() != 1) { row = depLoc.getRow()-1; } else { row = depLoc.getRow(); } boolean contains = doubleLocs.contains(row); Loc shallowLoc = null; if (!contains) { shallowLoc = locService.getOne(new LambdaQueryWrapper() .eq(Loc::getAreaId, depLoc.getAreaId()) .eq(Loc::getRow, row) .eq(Loc::getCol, depLoc.getCol()) .eq(Loc::getLev, depLoc.getLev()) ); }else { shallowLoc = locService.getOne(new LambdaQueryWrapper() .eq(Loc::getAreaId, depLoc.getAreaId()) .eq(Loc::getRow, depLoc.getRow()+1) .eq(Loc::getCol, depLoc.getCol()) .eq(Loc::getLev, depLoc.getLev()) ); } return shallowLoc.getCode(); } /** * 判断是否为浅库位 */ public static boolean isShallowLoc(String locNo) { if (isDoubleDeep) { int row = getRow(locNo); return !doubleLocs.contains(row); } else { return false; } } //获取站点对应的库类型 public static Long getAreaType(Integer sourceStaNo) { DeviceBindService rowLastnoService = SpringUtils.getBean(DeviceBindService.class); List deviceBinds = rowLastnoService.list(new LambdaQueryWrapper()); for (DeviceBind deviceBind : deviceBinds) { String[] staNoList = deviceBind.getStaList().split(";"); for (String staNo : staNoList) { if (staNo.equals(sourceStaNo.toString())) { return deviceBind.getId(); } } } return 0L; } //库位排号分配 public static int[] LocNecessaryParameters(DeviceBind deviceBind, Integer curRow, Integer crnNumber) { return LocNecessaryParametersDoubleExtension(curRow, crnNumber); //已完善 } //经典双伸库位, 获取双深排 public static int[] LocNecessaryParametersDoubleExtension( Integer curRow, Integer crnNumber) { int[] necessaryParameters = new int[]{0, 0, 0, 0}; necessaryParameters[0] = crnNumber; // 轮询次数 //满板正常入库 if (curRow.equals(crnNumber * 4)) { necessaryParameters[1] = 1; //curRow 最深库位排 necessaryParameters[2] = 1; //crnNo 堆垛机号 necessaryParameters[3] = 2; //nearRow 最浅库位排 } else if (curRow.equals(crnNumber * 4 - 3)) { necessaryParameters[1] = 4; //curRow 最深库位排 necessaryParameters[2] = 1; //crnNo 堆垛机号 necessaryParameters[3] = 3; //nearRow 最浅库位排 } else { curRow = curRow + 4; if (curRow < 1 || curRow > (crnNumber * 4)) { throw new CoolException("库位排号异常:排号:" + curRow); } if ((curRow - 1) % 4 == 0) { necessaryParameters[1] = curRow; //curRow 最深库位排 necessaryParameters[2] = (curRow + 3) / 4; //crnNo 堆垛机号 necessaryParameters[3] = curRow + 1; //nearRow 最浅库位排 } else if (curRow % 4 == 0) { necessaryParameters[1] = curRow; //curRow 最深库位排 necessaryParameters[2] = curRow / 4; //crnNo 堆垛机号 necessaryParameters[3] = curRow - 1; //nearRow 最浅库位排 } else { throw new CoolException("库位排号异常:排号:" + curRow); } } return necessaryParameters; } /** * 通过库位号获取 排 */ public static int getRow(String locNo) { if (!Cools.isEmpty(locNo)) { LocService locService = SpringUtils.getBean(LocService.class); Loc loc = locService.getOne(new LambdaQueryWrapper().eq(Loc::getCode, locNo)); if (null == loc) { throw new RuntimeException("库位解析异常"); } return loc.getRow(); } throw new RuntimeException("库位解析异常"); } /** * 通过库位号获取 列 */ public static int getBay(String locNo) { if (!Cools.isEmpty(locNo)) { return Integer.parseInt(locNo.substring(2, 5)); } throw new RuntimeException("库位解析异常"); } /** * 通过库位号获取 层 */ public static int getLev(String locNo) { if (!Cools.isEmpty(locNo)) { return Integer.parseInt(locNo.substring(5, 7)); } throw new RuntimeException("库位解析异常"); } /** * 类型检测 * 完全检测 **/ public static boolean locMoveCheckLocTypeComplete(Loc loc, LocTypeDto dto) { // 如果源库位是高库位,目标库位是低库位 return dto.getLocType1().equals(Integer.parseInt(loc.getType())); } public static String getCrnLoc() { // SlaveProperties bean = SpringUtils.getBean(SlaveProperties.class); System.out.println(doubleLocs); return null; } public static String zerofill(String msg, Integer count) { if (msg.length() == count) { return msg; } else if (msg.length() > count) { return msg.substring(0, 16); } else { StringBuilder msgBuilder = new StringBuilder(msg); for (int i = 0; i < count - msg.length(); i++) { msgBuilder.insert(0, "0"); } return msgBuilder.toString(); } } /** * 获取堆垛机库位信息 * @param deviceBind * @param area * @param sourceStaNo * @param matnr * @param batch * @param locTypeDto * @param times * @param ioType 作业类型(*必传参数) * @return */ public static InTaskMsgDto getLocNoCrn(DeviceBind deviceBind, Long area, Integer sourceStaNo, String matnr, String batch, LocTypeDto locTypeDto, int times, Integer ioType) { DeviceBindService deviceBindService = SpringUtils.getBean(DeviceBindService.class); DeviceSiteService deviceSiteService = SpringUtils.getBean(DeviceSiteService.class); LocService locService = SpringUtils.getBean(LocService.class); LocItemService locItemService = SpringUtils.getBean(LocItemService.class); if (Cools.isEmpty(matnr)) { //物料号 matnr = ""; } if (Cools.isEmpty(batch)) { //批次 batch = ""; } // 初始化参数 int channel = 0; //堆垛机号 int nearRow = 0; //最浅库位排 int curRow = 0; //最深库位排 int rowCount = 0; //轮询轮次 Loc loc = null; // 目标库位 InTaskMsgDto inTaskMsgDto = new InTaskMsgDto(); int sRow = deviceBind.getStartRow(); int eRow = deviceBind.getEndRow(); int deviceQty = deviceBind.getDeviceQty(); // ===============>>>> 开始执行 curRow = deviceBind.getCurrentRow(); //此程序用于优化堆垛机异常时的运行时间 for (int i = times; i <= deviceQty * 2; i++) { int[] locNecessaryParameters = LocUtils.LocNecessaryParameters(deviceBind, curRow, deviceQty); curRow = locNecessaryParameters[1]; channel = locNecessaryParameters[2]; rowCount = locNecessaryParameters[0]; nearRow = locNecessaryParameters[3]; break; } if (nearRow == 0) { throw new CoolException("无可用堆垛机"); } //入库靠近摆放 if (ioType == 1 && deviceBind.getBeSimilar().equals("1") && !Cools.isEmpty(matnr)) { if (nearRow != curRow) { List locItems = locItemService.list(new LambdaQueryWrapper().eq(LocItem::getMatnrCode, matnr)); for (LocItem locItem : locItems) { Loc loc1 = locService.getById(locItem.getLocId()); if (LocUtils.isShallowLoc(loc1.getCode())) { continue; } String shallowLocNo = LocUtils.getShallowLoc(loc1.getCode()); // 检测目标库位是否为空库位 Loc shallowLoc = locService.getOne(new LambdaQueryWrapper().eq(Loc::getCode, shallowLocNo)); if (shallowLoc != null && shallowLoc.getUseStatus().equals(LocStsType.LOC_STS_TYPE_O.type)) { if (LocUtils.locMoveCheckLocTypeComplete(shallowLoc, locTypeDto)) { loc = shallowLoc; channel = shallowLoc.getChannel(); break; } } } } } // // 靠近摆放规则 --- 空托 //互通版 // if (ioType == 10 && deviceBind.getEmptySimilar().equals("1")) { // List locMasts = locMastService.selectList(new EntityWrapper() // .eq("loc_sts", "D").ge("row1", sRow).le("row1", eRow).eq("whs_type", rowLastnoType.getType().longValue())); // if (!locMasts.isEmpty()) { // for (LocMast loc : locMasts) { // if (Utils.isShallowLoc(slaveProperties, loc.getLocNo())) { // continue; // } // String shallowLocNo = Utils.getShallowLoc(slaveProperties, loc.getLocNo()); // // 检测目标库位是否为空库位 // LocMast shallowLoc = locMastService.selectById(shallowLocNo); // if (shallowLoc != null && shallowLoc.getLocSts().equals("O")) { // if (VersionUtils.locMoveCheckLocTypeComplete(shallowLoc, locTypeDto)) { // if (basCrnpService.checkSiteError(shallowLoc.getCrnNo(), true)) { // locMast = shallowLoc; // crnNo = locMast.getCrnNo(); // break; // } // } // } // } // } // } //查找路径 DeviceSite deviceSite = deviceSiteService.getOne(new LambdaQueryWrapper() .eq(DeviceSite::getType, ioType) .eq(DeviceSite::getSite, sourceStaNo) .eq(DeviceSite::getChannel, channel) ); if (Cools.isEmpty(deviceSite)) { channel = 0; } else { inTaskMsgDto.setStaNo(Integer.parseInt(deviceSite.getDeviceSite())); } //更新当前排 deviceBind.setCurrentRow(curRow); deviceBindService.updateById(deviceBind); // 开始查找库位 ==============================>> // 1.按规则查找库位 if (Cools.isEmpty(loc) && channel != 0) { List locMasts = null; locMasts = locService.list(new LambdaQueryWrapper() .eq(Loc::getRow, nearRow) .eq(Loc::getUseStatus, LocStsType.LOC_STS_TYPE_O.type) .eq(Loc::getType, locTypeDto.getLocType1()) .eq(Loc::getAreaId, area) .orderByAsc(Loc::getLev) .orderByAsc(Loc::getCol) ); for (Loc locMast1 : locMasts) { if (!LocUtils.locMoveCheckLocTypeComplete(locMast1, locTypeDto)) { continue; } String shallowLoc = LocUtils.getDeepLoc(locMast1.getCode()); if ((ioType == TaskStsType.GENERATE_IN.id && deviceBind.getBeSimilar().equals("1"))) { //相似物料打开,判断深库位有没有货,没货就放深库位,有货就不操作 Loc locMast2 = locService.getOne(new LambdaQueryWrapper() .eq(Loc::getCode, shallowLoc) .eq(Loc::getUseStatus, LocStsType.LOC_STS_TYPE_O.type) .eq(Loc::getAreaId, area) ); if (!Cools.isEmpty(locMast2)) { loc = locMast2; break; } } else { //相似物料关闭,判断深库位有没有货,有货就放浅库位,无货就不操作 Loc locMast2 = locService.getOne(new LambdaQueryWrapper() .eq(Loc::getCode, shallowLoc) .in(Loc::getUseStatus, LocStsType.LOC_STS_TYPE_D.type, LocStsType.LOC_STS_TYPE_F.type) .eq(Loc::getAreaId, area) ); if (!Cools.isEmpty(locMast2)) { loc = locMast1; break; } else { locMast2 = locService.getOne(new LambdaQueryWrapper() .eq(Loc::getCode, shallowLoc) .eq(Loc::getUseStatus, LocStsType.LOC_STS_TYPE_O.type) .eq(Loc::getAreaId, area) ); if (!Cools.isEmpty(locMast2)) { loc = locMast2; break; } } } } if (Cools.isEmpty(loc) && deviceBind.getBeSimilar().equals("1")) { for (Loc locMast1 : locMasts) { if (!LocUtils.locMoveCheckLocTypeComplete(locMast1, locTypeDto)) { continue; } if (deviceBind.getBeSimilar().equals("1")) { String shallowLoc = LocUtils.getDeepLoc(locMast1.getCode()); Loc locMast2 = locService.getOne(new LambdaQueryWrapper() .eq(Loc::getCode, shallowLoc) .eq(Loc::getUseStatus, LocStsType.LOC_STS_TYPE_O.type) .eq(Loc::getAreaId, area) ); if (!Cools.isEmpty(locMast2)) { loc = locMast2; break; } else { locMast2 = locService.getOne(new LambdaQueryWrapper() .eq(Loc::getCode, shallowLoc) .in(Loc::getUseStatus, LocStsType.LOC_STS_TYPE_D.type, LocStsType.LOC_STS_TYPE_D.type) .eq(Loc::getAreaId, area) ); if (!Cools.isEmpty(locMast2)) { loc = locMast1; break; } } } else { if (!Cools.isEmpty(locMast1)) { loc = locMast1; break; } } } } } //查询当前库位类型空库位 小于5个则locmast = null List locTypeLocMasts = locService.list(new LambdaQueryWrapper() .eq(Loc::getUseStatus, LocStsType.LOC_STS_TYPE_O.type) .eq(Loc::getChannel, channel) .eq(Loc::getType, locTypeDto.getLocType1()) .eq(Loc::getAreaId, area) ); if (null != locTypeLocMasts && locTypeLocMasts.size() <= 5) { loc = null; } // 递归查询 if (Cools.isEmpty(loc) || !loc.getUseStatus().equals(LocStsType.LOC_STS_TYPE_O.type)) { // 当前巷道无空库位时,递归调整至下一巷道,检索全部巷道无果后,跳出递归 if (times < rowCount * 2) { times = times + 1; return getLocNoCrn(deviceBind, area, sourceStaNo, matnr, batch, locTypeDto, times, ioType); } // 2.库位当前所属尺寸无空库位时,调整尺寸参数,向上兼容检索库位 if (locTypeDto.getLocType1() < 3) { int i = locTypeDto.getLocType1() + 1; locTypeDto.setLocType1(i); return getLocNoCrn(deviceBind, area, sourceStaNo, matnr, batch, locTypeDto, 0, ioType); } throw new CoolException("没有空库位"); } String locNo = loc.getCode(); // 返回dto inTaskMsgDto.setDeviceNo(channel); inTaskMsgDto.setSourceStaNo(sourceStaNo); // inTaskMsgDto.setStaNo(); inTaskMsgDto.setLocNo(locNo); return inTaskMsgDto; } }