Commit bd32adc0 LN

料架分配

1 个父辈 69bd99ca
......@@ -18,14 +18,22 @@ import java.util.Locale;
@Slf4j
@Data
public class ResultBean<T> {
public static ResultBean newErrorResult(int code, String msgKey, String msg ,Object data) {
ResultBean resultBean= newErrorResult(code, msgKey, msg, new String[]{},true);
resultBean.setData(data);
return resultBean;
}
public static ResultBean newErrorResult(int code, String msgKey, String msg,String[] params,Object data) {
ResultBean resultBean= newErrorResult(code, msgKey, msg, params,true);
resultBean.setData(data);
return resultBean;
}
public static ResultBean newErrorResult(int code, String msgKey, String msg ) {
return newErrorResult(code, msgKey, msg, new String[]{},true);
}
public static ResultBean newErrorResult(int code, String msgKey, String msg,String[] params) {
return newErrorResult(code, msgKey, msg, params,true);
}
public static ResultBean newErrorResult(int code, String msgKey, String msg,String[] params, boolean writeLog) {
ResultBean result = new ResultBean();
result.setCode(code);
......
......@@ -10,6 +10,7 @@ import com.neotel.smfcore.core.message.enums.MessageType;
import com.neotel.smfcore.core.message.service.manager.IMessageManager;
import com.neotel.smfcore.core.message.service.po.Message;
import com.neotel.smfcore.core.order.util.OrderFileWatch;
import com.neotel.smfcore.core.shelf.TaskShelfUtil;
import com.neotel.smfcore.security.service.manager.IMenuManager;
import com.neotel.smfcore.security.service.manager.IRoleManager;
import com.neotel.smfcore.security.service.manager.IUserManager;
......@@ -112,6 +113,10 @@ public class DataInitManager {
dataCache.getAllInventory(null,"");
TaskShelfUtil.dataCache=dataCache;
TaskShelfUtil.initShelfMap();
} catch (Exception exception) {
log.error("初始化环境出错..." + exception.toString(),exception);
}
......
......@@ -770,9 +770,9 @@ public class DataCache {
List<String> availableStorageIds = new ArrayList<>();
for (Storage storage : getAllStorage().values()) {
StatusBean bean = DevicesStatusUtil.getStatusBean(storage.getCid());
if (bean == null || bean.timeOut() || !bean.isAvailable()) {
continue;
}
// if (bean == null || bean.timeOut() || !bean.isAvailable()) {
// continue;
// }
availableStorageIds.add(storage.getId());
}
return availableStorageIds;
......
......@@ -21,6 +21,7 @@ import com.neotel.smfcore.core.order.service.manager.ILiteOrderItemManager;
import com.neotel.smfcore.core.order.service.manager.ILiteOrderManager;
import com.neotel.smfcore.core.order.service.po.LiteOrder;
import com.neotel.smfcore.core.order.service.po.LiteOrderItem;
import com.neotel.smfcore.core.shelf.TaskShelfUtil;
import com.neotel.smfcore.core.storage.enums.CHECKOUT_TYPE;
import com.neotel.smfcore.core.storage.service.manager.IStoragePosManager;
import com.neotel.smfcore.core.storage.service.po.Storage;
......@@ -259,7 +260,10 @@ public class LiteOrderCache {
order.setTotalTaskReelCount(order.getTotalTaskReelCount()-1);
log.info("工单[" + orderNo + "]的任务" + task.getPartNumber() + "[" + task.getBarcode() + "]已取消,任务数-1=" + order.getFinishedReelCount() + "/" + order.getTaskReelCount());
checkoutAgain(task,order);
//取消任务料架位置锁定
TaskShelfUtil.cancelReelTask(task);
// checkoutAgain(task,order);
}
else if (task.isFinished() || task.isEnd()) {
order.setFinishedReelCount(order.getFinishedReelCount() + 1);
......@@ -360,6 +364,7 @@ public class LiteOrderCache {
}
CHECKOUT_TYPE checkoutType = dataCache.getCheckOutType();
Collection<String> excludePosIds = excludeOutPosIds();
excludePosIds.add(task.getPosId());
StoragePos pos = storagePosManager.findPartNumberInStorages(availableStorageIds, item.getPn(), excludePosIds, checkoutType);
if (pos == null) {
log.error("工单[" + orderNo + "],PN[" + item.getPn() + "]出库任务被取消,补发失败:未找到可以出库的物料 ");
......@@ -376,9 +381,14 @@ public class LiteOrderCache {
newTasktask.setLightColor(task.getLightColor());
newTasktask.setStatus(OP_STATUS.WAIT.name());
newTasktask.setSingleOut(task.isSingleOut());
taskService.addTaskToExecute(task);
taskService.addTaskToExecute(newTasktask);
//增加一个料架位置
TaskShelfUtil.addLoc(newTasktask);
order.setTaskReelCount(order.getTaskReelCount() + 1);
order.setTotalTaskReelCount(order.getTotalTaskReelCount() + 1);
break;
}
}
}
......@@ -525,6 +535,9 @@ public class LiteOrderCache {
task.setSingleOut(singleOut);
// task = dataLogDao.save(task);
taskService.addTaskToExecute(task);
//增加一个料架位置
TaskShelfUtil.addLoc(task);
}
//如果是RI出库,只有一盘,出完就结束
if(!Strings.isNullOrEmpty(reelId)){
......
......@@ -32,13 +32,13 @@ public enum ORDER_COLOR {
BLUE("0000FF"),
//MAGENTA("FF00FF"),
CYAN("00FFFF"),
FIREBRICK("B22222"),
PURPLE("A020F0"),
SKYBLUE("6CA6CD"),
PINK("FF1493"),
FORESTGREEN("228B22"),
LIGHTBLUE("8470FF"),
INDIANRED("8B3A3A"),
// FIREBRICK("B22222"),
// PURPLE("A020F0"),
// SKYBLUE("6CA6CD"),
// PINK("FF1493"),
// FORESTGREEN("228B22"),
// LIGHTBLUE("8470FF"),
// INDIANRED("8B3A3A"),
DARKGREEN("556B2F"),
;
......
package com.neotel.smfcore.core.shelf;
import cn.hutool.core.util.ObjectUtil;
import com.google.common.collect.Lists;
import com.neotel.smfcore.core.device.util.DataCache;
import com.neotel.smfcore.core.shelf.bean.ShelfInfo;
import com.neotel.smfcore.core.shelf.bean.ShelfLoc;
import com.neotel.smfcore.core.shelf.enums.SHELF_TYPE;
import com.neotel.smfcore.core.system.service.po.DataLog;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
@Slf4j
public class TaskShelfUtil {
public static DataCache dataCache;
@Autowired
public void setDataCache(DataCache dataCache) {
TaskShelfUtil.dataCache = dataCache;
}
/**
* 料架管理Map, key为 hSerial, value的key为 tempRfid, value为料架
*/
public static Map<String, Map<String, ShelfInfo>> taskShelfMap =null;
private static String HSERIAL_SHELF_MAP_KEY = "HSERIAL_SHELF_MAP_KEY";
private static String DEFAULT_ORDERNO = "1";
public static void initShelfMap() {
if (taskShelfMap == null) {
taskShelfMap = dataCache.getCache(HSERIAL_SHELF_MAP_KEY);
if(taskShelfMap ==null){
taskShelfMap =new ConcurrentHashMap<>();
}
}
}
private static void saveShelfMap(Map<String, Map<String, ShelfInfo>> map) {
dataCache.updateCache(HSERIAL_SHELF_MAP_KEY, map);
}
/**
* 清理使用过的料架
*/
public static void clearShelf(String orderNo) {
if (orderNo != null) {
Map<String, ShelfInfo> shelfMap = taskShelfMap.get(orderNo);
if (shelfMap != null) {
log.info("清理[" + orderNo + "]使用过的料架");
taskShelfMap.remove(orderNo);
saveShelfMap(taskShelfMap);
}
}
}
public static boolean clearShelf(String orderNo, String rfid) {
boolean clearResult = false;
if (orderNo != null) {
log.info("清理[" + orderNo + "]使用的过料架[" + rfid + "]");
Map<String, ShelfInfo> shelfMap = taskShelfMap.get(orderNo);
if (shelfMap != null) {
ShelfInfo shelfInfo = findSameShelf(orderNo, rfid);
if (shelfInfo != null) {
String tempRfid = shelfInfo.tempRfid();
shelfMap.remove(tempRfid);
taskShelfMap.put(orderNo, shelfMap);
clearResult = true;
saveShelfMap(taskShelfMap);
}
}
}
return clearResult;
}
private static String getShelfType(DataLog task) {
return SHELF_TYPE.F;
}
/**
* 更新料架缓存信息
*/
private static void updateShelfInfo(ShelfInfo shelfInfo) {
String orderNo = shelfInfo.getOrderNo();
Map<String, ShelfInfo> shelfMap = taskShelfMap.getOrDefault(orderNo, new ConcurrentHashMap<>());
shelfMap.put(shelfInfo.tempRfid(), shelfInfo);
taskShelfMap.put(orderNo, shelfMap);
saveShelfMap(taskShelfMap);
}
/**
* 新增任务时增加位置
* @param task
* @return
*/
public static synchronized DataLog addLoc(DataLog task) {
try {
String orderNo = task.getSourceName();
if (ObjectUtil.isEmpty(orderNo)) {
orderNo = DEFAULT_ORDERNO;
}
ShelfInfo targetShelf = null;
int targetLoc = -1;
Map<String, ShelfInfo> shelfMap = taskShelfMap.get(orderNo);
int maxIndex = 0;
if (shelfMap != null) {
for (ShelfInfo shelfInfo : shelfMap.values()) {
if (shelfInfo.getRfidIndex() > maxIndex) {
maxIndex = shelfInfo.getRfidIndex();
}
targetLoc = shelfInfo.addUnLimitLoc(task);
if (targetLoc != -1) {
//添加成功
log.info("为[" + task.getBarcode() + "]添加架位[" + shelfInfo.tempRfid() + "][" + targetLoc + "]");
targetShelf = shelfInfo;
break;
}
}
}
if (targetShelf == null) {
targetShelf = ShelfInfo.newFShelf();
if (targetShelf != null) {
targetShelf.setRfidIndex(maxIndex + 1);
targetShelf.setOrderNo(orderNo);
targetShelf.setSourceWo(orderNo);
targetLoc = targetShelf.addUnLimitLoc(task);
log.info("为[" + task.getBarcode() + "]添加新料架[" + targetShelf.tempRfid() + "]架位[" + targetShelf.tempRfid() + "][" + targetLoc + "]");
}
}
task.setTempRfid(targetShelf.tempRfid());
task.setRfidLoc(targetLoc);
updateShelfInfo(targetShelf);
} catch (Exception ex) {
log.error("addLoc 出错:" + ex.getMessage());
}
return task;
}
// /**
// * 双层线上AGV拉走料架时调用清理料架,使料架可以重复使用
// */
// public static boolean agvRemoveRfid(String realRfid){
// ShelfInfo shelfToRemove = null;
// for (Map<String, ShelfInfo> shelfInfoMap : hSerialShelfMap.values()) {
// for (ShelfInfo shelfInfo : shelfInfoMap.values()) {
// String shelfRFID = shelfInfo.getRealRfid();
// if(shelfRFID.equals(realRfid)){
// //已经绑定过该Temp料架
// shelfToRemove = shelfInfo;
// }
// }
// }
//
// if(shelfToRemove != null){
// String hSerial = shelfToRemove.gethSerial();
// Map<String, ShelfInfo> shelfMap = hSerialShelfMap.get(hSerial);
// if(shelfMap != null){
// log.info("料架"+shelfToRemove.tempRfid()+"["+shelfToRemove.getRealRfid()+"]已放上AGV,从缓存中清理");
// shelfMap.remove(shelfToRemove.tempRfid());
// hSerialShelfMap.put(hSerial, shelfMap);
// saveShelfMap(hSerialShelfMap);
// return true;
// }
// }
// return false;
// }
public static ShelfInfo findSameShelf(String orderNo, String rfid) {
if (ObjectUtil.isEmpty(orderNo) || ObjectUtil.isEmpty(rfid)) {
return null;
}
Map<String, ShelfInfo> shelfMap = taskShelfMap.get(orderNo);
if (shelfMap != null) {
for (ShelfInfo shelf : shelfMap.values()) {
if (ObjectUtil.isEmpty(shelf.getRealRfid())) {
continue;
}
if (shelf.getRealRfid().equals(rfid)) {
log.debug(shelf.tempRfid() + "判断料架[" + shelf.getRealRfid() + "] = " + rfid);
//已经绑定过该Temp料架
return shelf;
}
}
}
return null;
}
/**
* 获取某个需求单已经绑定的RFID
*
* @param hSerial 需求单号
*/
public static List<String> getUsedRfidList(String hSerial) {
List<String> usedRfidList = new ArrayList<>();
Map<String, ShelfInfo> shelfMap = taskShelfMap.get(hSerial);
if (shelfMap != null) {
for (ShelfInfo shelfInfo : shelfMap.values()) {
String realRfid = shelfInfo.getRealRfid();
if (ObjectUtil.isNotEmpty(realRfid)) {
usedRfidList.add(realRfid);
}
}
}
return usedRfidList;
}
/**
* 锁定架位
*/
public static synchronized ShelfLoc lockShelfLoc(DataLog task, String rfidStr) {
String orderNo = task.getSourceName();
if(ObjectUtil.isEmpty(orderNo)){
orderNo=DEFAULT_ORDERNO;
//紧急料获取库位号时再锁定
addLoc(task);
}
ShelfInfo shelfInfo = null;
List<String> rfidList = Lists.newArrayList(rfidStr.split(";"));
ShelfLoc lockLoc = null;
if (orderNo != null) {
Map<String, ShelfInfo> shelfMap = taskShelfMap.get(orderNo);
if (shelfMap != null) {
List<ShelfInfo> shelfList = new ArrayList<>(shelfMap.values());
shelfList.sort(new Comparator<ShelfInfo>() {
@Override
public int compare(ShelfInfo o1, ShelfInfo o2) {
Integer index1 = o1.getRfidIndex();
Integer index2 = o2.getRfidIndex();
return index1.compareTo(index2);
}
});
ShelfInfo minIndexShelf = null;
for (ShelfInfo shelf : shelfList) {
if (shelf.isFull()) {
//已经放满,查找下一个
continue;
}
//已经放了此需求单的料架
if (rfidList.contains(shelf.getRealRfid())) {
lockLoc = shelf.lockOneEmptyLoc(task);
if (lockLoc != null) {
shelfInfo = shelf;
break;
}
} else {
if (minIndexShelf == null || shelf.getRfidIndex() < minIndexShelf.getRfidIndex()) {
minIndexShelf = shelf;
}
}
}
if (lockLoc == null) {
if (minIndexShelf == null) {
log.error("任务条码[" + task.getBarcode() + "]已无料架可放");
return null;
} else {
//这里判断是否有未绑定过的料架
boolean hasEmptyShelf = false;
for (String rfid : rfidList) {
ShelfInfo shelf = findShelfByRealRfid(rfid);
if (shelf == null) {
hasEmptyShelf = true;
break;
}
}
if (hasEmptyShelf) {
lockLoc = minIndexShelf.lockOneEmptyLoc(task);
if (lockLoc != null) {
shelfInfo = minIndexShelf;
}
}
}
}
}
}
if (lockLoc != null) {
log.info("为[" + task.getBarcode() + "]锁定架位:" + shelfInfo.tempRfid() + "[" + shelfInfo.getRealRfid() + "][" + lockLoc.getLoc() + "]原来分配架位:" + task.getAppendData("tempRfid") + "[" + task.getAppendData("rfidLoc") + "]");
if (shelfInfo.getRealRfid() == null || shelfInfo.getRealRfid().isEmpty()) {
//未绑定过的,使用TempRFID
lockLoc.setTempRfid(shelfInfo.tempRfid());
lockLoc.setRealRfid("");
} else {
//绑定过的使用RealRfid
lockLoc.setRealRfid(shelfInfo.getRealRfid());
lockLoc.setTempRfid(shelfInfo.tempRfid());
}
updateShelfInfo(shelfInfo);
return lockLoc;
}
return null;
}
/**
* 取消任务,解除料盘对料架的占用
*/
public static void cancelReelTask(DataLog task) {
String barcode = task.getBarcode();
String orderNo = task.getSourceName();
String tempRfid = task.getTempRfid();
Integer rfidLoc = task.getRfidLoc();
Map<String, ShelfInfo> shelfMap = taskShelfMap.get(orderNo);
if (shelfMap == null) {
log.warn("[" + task.getBarcode() + "]任务取消时未找到工单[" + orderNo + "]的料架缓存信息");
return;
}
//补料盘,解除最后一个料架上的位置
ShelfInfo minShelf = null;
for (ShelfInfo shelfInfo : shelfMap.values()) {
int limitLoc = shelfInfo.getBarcodeLoc(barcode);
if (limitLoc > 0) {
//已经锁定过
boolean result = shelfInfo.cancelLimitLoc(barcode);
if (result) {
log.info("料盘[" + task.getBarcode() + "]任务取消,解除料架" + shelfInfo.tempRfid() + "的锁定架位绑定");
updateShelfInfo(shelfInfo);
return;
}
} else if (!shelfInfo.isFull()) {
if (minShelf == null || shelfInfo.getRfidIndex() < minShelf.getRfidIndex()) {
minShelf = shelfInfo;
}
}
}
if (minShelf != null) {
boolean result = minShelf.cancelLoc(SHELF_TYPE.F, task);
if (result) {
log.info("补料盘[" + task.getBarcode() + "]任务取消,同类型最小料架" + minShelf.tempRfid() + "架位置空");
updateShelfInfo(minShelf);
}
}
}
/**
* 放料完成,更新位置信息
* @param task
* @param rfid
* @param loc
* @return
*/
public static synchronized boolean putInShelf(DataLog task, String rfid, int loc) {
String barcode = task.getBarcode();
String orderNo = task.getSourceName();
Map<String, ShelfInfo> shelfMap = taskShelfMap.get(orderNo);
if (shelfMap != null) {
//该料架是否已经绑定过
ShelfInfo bindedShelf = findSameShelf(orderNo, rfid);
//非首盘
if (bindedShelf != null) {
//已经绑定过
boolean putInResult = bindedShelf.putInLoc(rfid, loc, barcode);
if (putInResult) {
updateShelfInfo(bindedShelf);
log.info("物料[" + task.getBarcode() + "]使用料架" + rfid + "[" + loc + "]缓存更新成功");
return true;
}
} else {
for (ShelfInfo shelfInfo : shelfMap.values()) {
boolean putInResult = shelfInfo.putInLoc(rfid, loc, barcode);
if (putInResult) {
updateShelfInfo(shelfInfo);
log.info("物料[" + task.getBarcode() + "]使用新料架" + rfid + "[" + loc + "]缓存更新成功");
return true;
}
}
}
} else {
log.info("未找到[" + orderNo + "]相关料架");
}
log.error("物料[" + task.getBarcode() + "](" + task.getTempRfid() + "[" + task.getRfidLoc() + "])料架" + rfid + "[" + loc + "]缓存更新失败");
return false;
}
public static ShelfInfo findShelfByTempRfid(String tempRfid) {
for (Map<String, ShelfInfo> shelfInfoMap : taskShelfMap.values()) {
for (ShelfInfo shelf : shelfInfoMap.values()) {
if (shelf.tempRfid().equals(tempRfid)) {
return shelf;
}
}
}
return null;
}
public static ShelfInfo findShelfByRealRfid(String realRfid) {
for (Map<String, ShelfInfo> shelfInfoMap : taskShelfMap.values()) {
for (ShelfInfo shelf : shelfInfoMap.values()) {
String shelfRFID = shelf.getRealRfid();
if (ObjectUtil.isNotEmpty(shelfRFID)&& shelfRFID.equals(realRfid)) {
return shelf;
}
}
}
return null;
}
}
package com.neotel.smfcore.core.shelf.bean;
import cn.hutool.core.util.ObjectUtil;
import com.neotel.smfcore.core.shelf.enums.SHELF_TYPE;
import com.neotel.smfcore.core.system.service.po.DataLog;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Slf4j
public class ShelfInfo {
public ShelfInfo(String type,int maxNum){
shelfType=type ;
maxLocCount=maxNum;
}
/**
* F料架位置数量,1-26是小料,27=31是大料
*/
private static int F_POS_COUNT=31;
private static int MAX_F_SMALL_NUM=26;//F料架小料位置最大编号
/**
* 工单号
*/
private String orderNo;
/**
* 料架出库顺序编号
*/
private int rfidIndex;
/**
* 来源需求单号,用于分盘料,紧急料和工单的料区分
*/
private String sourceWo;
/**
* 实际编号
*/
private String realRfid;
/**
* 料架类型
*/
private String shelfType;
/**
* 料架的架位数
*/
private int maxLocCount = 0;
public static ShelfInfo newFShelf(){
return new ShelfInfo(SHELF_TYPE.F,31);
}
/**
* 架位放置情况, key小于0表示已经放过,key>0为空的库位
*/
private Map<Integer, ShelfLoc> locMap = new ConcurrentHashMap<>();
public String tempRfid(){
return getOrderNo() + "-" + rfidIndex + shelfType;
}
public boolean cancelLimitLoc(String barcode) {
for (ShelfLoc shelfLoc : locMap.values()) {
if (shelfLoc.isInThisLoc(barcode)) {
if (shelfLoc.isEmpty()) {
shelfLoc.putIn(barcode);
locMap.put(shelfLoc.getLoc(), shelfLoc);
return true;
} else {
log.error("料盘[" + barcode + "]解除绑定架位" + tempRfid() + "[" + shelfLoc.getLoc() + "]失败,此位置料盘已放入");
return false;
}
}
}
return false;
}
/**
* 根据条码获取库位信息
*/
public int getBarcodeLoc(String barcode) {
for (ShelfLoc shelfLoc : locMap.values()) {
if (shelfLoc.isLock() && shelfLoc.getBarcode().equals(barcode)) {
return shelfLoc.getLoc();
}
}
return -1;
}
/**
* 为不需要按顺序摆放的料盘锁定一个架位,如果已经锁定过,返回对应的架位
*/
public ShelfLoc lockOneEmptyLoc(DataLog task){
//先看看此条码是否已经锁定过
for (ShelfLoc shelfLoc : locMap.values()) {
if(shelfLoc.isLock() && shelfLoc.getBarcode().equals(task.getBarcode())){
log.info("找到条码["+task.getBarcode()+"]锁定的架位["+shelfLoc.getLoc()+"]");
return shelfLoc;
}
}
for(int i=1; i<= maxLocCount; i++){
ShelfLoc shelfLoc = lockLocation(i,task);
if(shelfLoc != null){
return shelfLoc;
}
}
return null;
}
/**
* 锁定库位,如果成功返回库位,如果失败返回null
*/
private ShelfLoc lockLocation(int loc, DataLog task){
ShelfLoc shelfLoc = locMap.get(loc);
if(shelfLoc != null && shelfLoc.isEmpty() && !shelfLoc.isLock() && getReelType(task) == shelfLoc.getReelType()){
log.info("为[" + task.getBarcode() + "]锁定架位"+tempRfid() + "["+loc+"]");
//未放过料,且未锁定
shelfLoc.setBarcode(task.getBarcode());
shelfLoc.setReelType(getReelType(task));
locMap.put(loc, shelfLoc);
return shelfLoc;
}
return null;
}
/**
* 添加一个库位
*/
public int addUnLimitLoc(DataLog task){
for(int i=1; i<= maxLocCount; i++){
ShelfLoc shelfLoc = locMap.get(i);
if(shelfLoc == null){
boolean addThis = false;
if(isSmallReel(task)){
if(i<= MAX_F_SMALL_NUM){
addThis = true;
}
}else{
if(i> MAX_F_SMALL_NUM){
addThis = true;
}
}
if(addThis){
shelfLoc = new ShelfLoc();
shelfLoc.setLoc(i);
shelfLoc.setBarcode("");
shelfLoc.setReelType(getReelType(task));
shelfLoc.setTempRfid(tempRfid());
if(ObjectUtil.isNotEmpty(realRfid)){
shelfLoc.setRealRfid(realRfid);
}
locMap.put(i, shelfLoc);
return i;
}
}
}
return -1;
}
/**
* 将料盘放入库位
* @param loc
* @param barcode
*/
public boolean putInLoc(String rfid, int loc, String barcode){
if(ObjectUtil.isNotEmpty(realRfid)){
//已绑定过真实料架,必须一致才能放入
if(!this.realRfid.equals(rfid)){
return false;
}
}
if(!rfid.contains(shelfType)){
//未绑定过料架的,需要判断类型是否一致
return false;
}
int lockLocation = -1;
for (ShelfLoc shelfLoc : locMap.values()) {
if(shelfLoc.isLock() && shelfLoc.getBarcode().equals(barcode)){
log.info("找到条码["+barcode+"]锁定的架位["+shelfLoc.getLoc()+"]");
lockLocation = shelfLoc.getLoc();
}
}
if(lockLocation == -1){
log.error("["+tempRfid()+"]未找到["+barcode+"]锁定的位置信息");
return false;
}
if(lockLocation != loc){
log.error(barcode + "放置位置["+loc+"]与锁定位置["+lockLocation+"]不一致");
return false;
}
this.setRealRfid(rfid);
ShelfLoc shelfLoc = locMap.get(loc);
if(shelfLoc == null){
log.error("未找到["+loc+"]的位置信息,当前料架位置信息:"+ locMap);
return false;
}
if(shelfLoc.isEmpty()){
boolean putInResult = shelfLoc.putIn(barcode);
locMap.put(loc, shelfLoc);
return putInResult;
}else{
log.error("料盘["+barcode+"]放入位置"+rfid+"["+loc+"]失败,此位置料盘已放入");
return false;
}
}
public boolean isFull(){
for (ShelfLoc loc : locMap.values()) {
if(loc.isEmpty()){
return false;
}
}
return true;
}
/**
* 为 取消一个库位
*/
public boolean cancelLoc(String rfidType, DataLog task){
if(rfidType.equals(this.getShelfType())){
for(int i=maxLocCount; i> 0; i--){
ShelfLoc shelfLoc = locMap.get(i);
if(shelfLoc != null && shelfLoc.isEmpty() && !shelfLoc.isLock() && shelfLoc.getReelType() == getReelType(task)){
//未放过料,且未锁定
shelfLoc.putIn(task.getBarcode());
return true;
}
}
}
return false;
}
public int getReelType(DataLog task){
return 0;
}
public boolean isSmallReel(DataLog task){
return true;
}
}
package com.neotel.smfcore.core.shelf.bean;
import com.neotel.smfcore.core.shelf.enums.REEL_TYPE;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Slf4j
public class ShelfLoc {
public ShelfLoc(String realRfid, int loc) {
this.loc = loc;
this.realRfid = realRfid;
}
/**
* 料架RFID编号
*/
private String realRfid;
/**
* 虚拟料架号
*/
private String tempRfid;
/**
* 架位号1-31
*/
private int loc;
/**
* 物料编码
*/
private String barcode;
/**
* 物料类型:1=小料,2=大料
*/
private int reelType;
/**
* 是否为空,放料后=false
*/
private boolean empty = true;
/**
* 是否已锁定
*/
private boolean isLock = false;
/**
* 判断该架位锁定的条码是否与给定的条码一样
*
* @param barcode
* @return
*/
public boolean isInThisLoc(String barcode) {
if (this.isLock()) {
return this.getBarcode().equals(barcode);
}
return false;
}
public boolean putIn(String barcode) {
boolean canPut = false;
//库位未锁定或条码与锁定barcode一样,可放入
if (!isLock()) {
canPut = true;
} else if (this.getBarcode().equals(barcode)) {
canPut = true;
}
if (canPut) {
this.setBarcode(barcode);
setEmpty(false);
}
return canPut;
}
public boolean isSmallLoc() {
return reelType == REEL_TYPE.SMALL;
}
public boolean isBigLoc() {
return reelType == REEL_TYPE.BIG;
}
}
package com.neotel.smfcore.core.shelf.enums;
public class REEL_TYPE {
public static int SMALL=1;
public static int BIG=2;
}
package com.neotel.smfcore.core.shelf.enums;
public class SHELF_TYPE {
public static String F="F";
}
package com.neotel.smfcore.core.shelf.rest;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import com.neotel.smfcore.common.bean.ResultBean;
import com.neotel.smfcore.core.barcode.service.po.Barcode;
import com.neotel.smfcore.core.barcode.utils.CodeResolve;
import com.neotel.smfcore.core.device.enums.OP_STATUS;
import com.neotel.smfcore.core.device.util.DataCache;
import com.neotel.smfcore.core.shelf.TaskShelfUtil;
import com.neotel.smfcore.core.shelf.bean.ShelfInfo;
import com.neotel.smfcore.core.shelf.bean.ShelfLoc;
import com.neotel.smfcore.core.system.service.manager.IDataLogManager;
import com.neotel.smfcore.core.system.service.po.DataLog;
import com.neotel.smfcore.core.system.util.TaskService;
import com.neotel.smfcore.security.annotation.AnonymousAccess;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Slf4j
@RestController
@Api(tags = "料架放料处理")
@RequestMapping("rest/api/shelf")
public class TaskShelfController {
@Autowired
private DataCache dataCache;
@Autowired
private CodeResolve codeResolve;
@Autowired
private TaskService taskService;
@Autowired
private IDataLogManager dataLogManager;
@ApiOperation("根据条码获取料架位置")
@PostMapping(value = "/getLocation")
@ResponseBody
@AnonymousAccess
public ResultBean getLocation(HttpServletRequest request) {
String rfid = request.getParameter("rfid");
String codeStr = request.getParameter("barcode");
//是否是在横移上判断
String onMoving = request.getParameter("onMoving");
//101=未找到有效条码
//301=任务不存在
//302=任务已完成
//304=获取任务位置失败
Barcode barcode = codeResolve.resolveOneValideBarcode(codeStr);
if (barcode == null) {
return ResultBean.newErrorResult(-1, "smfcore.error.barcode.invalid", "未找到有效条码");
}
Map<String, Object> resultMap = new HashMap<>();
resultMap.put("barcode", barcode.getBarcode());
resultMap.put("h", barcode.getHeight());
resultMap.put("w", barcode.getPlateSize());
DataLog opTask = getTask(barcode.getBarcode());
if (opTask == null) {
log.info(" getLocation barcode[" + barcode + "],rfid[" + rfid + "] 未找到出库任务,返回条码尺寸");
return ResultBean.newErrorResult(301, "smfcore.task.notExist", "任务不存在", resultMap);
}
if (opTask.isFinished()) {
log.info(" getLocation barcode[" + barcode + "],rfid[" + rfid + "] 任务已完成,返回条码尺寸");
return ResultBean.newErrorResult(302, "smfcore.task.hasEnd", "任务已完成", resultMap);
}
if (opTask.isCancel()) {
log.info(" getLocation barcode[" + barcode + "],rfid[" + rfid + "] 任务已完成,任务已被取消");
return ResultBean.newErrorResult(303, "smfcore.task.hasCancel", "更新状态时{0}的任务[{1}]已被取消", new String[]{opTask.getBarcode(), opTask.getId()}, resultMap);
}
try {
ShelfLoc loc = TaskShelfUtil.lockShelfLoc(opTask, rfid);
if (loc == null) {
return ResultBean.newErrorResult(304, "smfcore.taskLoc.lockLoc.fail", "{0}获取位置{1}失败", new String[]{opTask.getBarcode(), rfid}, resultMap);
}
String rfidSave = loc.getRealRfid();
if (ObjectUtil.isEmpty(rfidSave)) {
rfidSave = loc.getTempRfid();
}
opTask.setTempRfid( rfidSave);
opTask.setRfidLoc( loc.getLoc());
opTask = dataLogManager.save(opTask);
taskService.updateFinishedTask(opTask);
List<String> usedRfidList = TaskShelfUtil.getUsedRfidList(opTask.getSourceName());
resultMap.put("realRfid", loc.getRealRfid());
resultMap.put("rfid", loc.getTempRfid());
resultMap.put("usedRfidList", String.join(",", usedRfidList));
resultMap.put("rfidLoc", loc.getLoc());
log.info(" getLocation barcode[" + barcode + "],rfid[" + rfid + "] 返回:realRfid=" + loc.getRealRfid() + ",rfid=" + loc.getTempRfid() + ",loc=" + loc.getLoc() + ",usedRfidList=" + String.join(",", usedRfidList));
return ResultBean.newOkResult(resultMap);
} catch (Exception e) {
log.error("getLocation 出错 rfid=" + rfid + "; ;codeStr=" + codeStr, e);
}
//返回数据://Response:{"code":0,"msg":"ok","data":{"w":"7","realRfid":"","h":"8","rfid":"1-2F","usedRfidList":"F102","rfidLoc":"11","barcode":"985022*35030377*0822*3000*08220350"}}
return ResultBean.newErrorResult(-1, "", "");
}
private DataLog getTask(String barcode) {
DataLog opTask = null;
List<DataLog> allTasks = taskService.getAllTasks();
for (DataLog task : allTasks) {
if (task.isFinished() || task.isPutInTask()) {
continue;
}
if (ObjectUtil.isNotEmpty(barcode) && task.getBarcode().equals(barcode)) {
opTask = task;
break;
}
}
//如果任务为空,重新查找已完成的任务
if (opTask == null) {
for (DataLog task : allTasks) {
if (task.isPutInTask()) {
continue;
}
if (ObjectUtil.isNotEmpty(barcode) && task.getBarcode().equals(barcode)) {
opTask = task;
break;
}
}
}
return opTask;
}
@ApiOperation("放料到料架完成")
@PostMapping(value = "/putShelfFinished")
@ResponseBody
@AnonymousAccess
public ResultBean putShelfFinished(HttpServletRequest request) {
String rfid = request.getParameter("rfid");
Integer rfidLoc = Convert.toInt(request.getParameter("rfidLoc"));
String barcode = request.getParameter("barcode");
DataLog opTask = getTask(barcode);
if (opTask == null) {
log.info(" getLocation barcode[" + barcode + "],rfid[" + rfid + "] 未找到出库任务,返回条码尺寸");
return ResultBean.newErrorResult(301, "smfcore.task.notExist", "任务不存在");
}
if (opTask.isFinished()) {
log.info(" getLocation barcode[" + barcode + "],rfid[" + rfid + "] 任务已完成,返回条码尺寸");
return ResultBean.newErrorResult(302, "smfcore.task.hasEnd", "任务已完成");
}
if (opTask.isCancel()) {
log.info(" getLocation barcode[" + barcode + "],rfid[" + rfid + "] 任务已完成,任务已被取消");
return ResultBean.newErrorResult(303, "smfcore.task.hasCancel", "更新状态时{0}的任务[{1}]已被取消", new String[]{opTask.getBarcode(), opTask.getId()});
}
try {
//返回料架大料空位,小料空位,工单已使用料架号 bigEmpty,smallEmpty,usedRfidList
//当前料架还可放入的料盘数
int smallEmpty = 0;
int bigEmpty = 0;
boolean result = TaskShelfUtil.putInShelf(opTask, rfid, rfidLoc);
if(result){
//更改任务完成
opTask.setStatus(OP_STATUS.FINISHED.name());
taskService.removeQueueTask(opTask);
taskService.updateFinishedTask(opTask);
log.info(" getLocation barcode[" + barcode + "],rfid[" + rfid + "] 放料完成,更新任务状态为完成");
}
String orderNo = opTask.getSourceName();
List<String> usedRfidList = TaskShelfUtil.getUsedRfidList(orderNo);
ShelfInfo shelfInfo = TaskShelfUtil.findSameShelf(orderNo, rfid);
if (shelfInfo != null) {
Map<Integer, ShelfLoc> locMap = shelfInfo.getLocMap();
for (ShelfLoc shelfLoc : locMap.values()) {
if (shelfLoc.isEmpty()) {
if (shelfLoc.isSmallLoc()) {
smallEmpty = smallEmpty + 1;
} else if (shelfLoc.isBigLoc()) {
bigEmpty = bigEmpty + 1;
}
}
}
} else {
smallEmpty = 100;
bigEmpty = 100;
}
//剩余的任务数
Map<String, Object> resultMap = new HashMap<>();
resultMap.put("barcode", opTask.getBarcode());
resultMap.put("rfid", rfid);
//已经使用过的RFID列表
resultMap.put("usedRfidList", String.join(",", usedRfidList));
resultMap.put("smallEmpty", smallEmpty + "");
resultMap.put("bigEmpty", bigEmpty + "");
//总任务数,不需要
// resultMap.put("cutTask", cutTask + "");
// resultMap.put("smallTask", smallTask + "");
// resultMap.put("bigTask", bigTask + "");
return ResultBean.newOkResult(resultMap);
} catch (Exception e) {
log.error("putShelfFinished 出错 rfid=" + rfid + ";rfidLoc=" + rfidLoc + ";barcode=" + barcode, e);
}
return ResultBean.newErrorResult(-1, "", "");
}
@ApiOperation("获取料架空位置")
@PostMapping(value = "/getShelfEmptySlot")
@ResponseBody
@AnonymousAccess
public ResultBean getShelfEmptySlot(HttpServletRequest request) {
String rfids = request.getParameter("rfids");
try {
HashMap<String, Object> rfidMap = new HashMap<>();
if (!Strings.isBlank(rfids)) {
for (String rfid : rfids.split(",")) {
Integer emptyPos = 0;
ShelfInfo shelfInfo = TaskShelfUtil.findShelfByRealRfid(rfid);
if (shelfInfo != null) {
Map<Integer, ShelfLoc> locMap = shelfInfo.getLocMap();
for (ShelfLoc shelfLoc : locMap.values()) {
if (shelfLoc.isEmpty()) {
emptyPos++;
}
}
} else {
//空料架
emptyPos = 100;
}
rfidMap.put(rfid, emptyPos);
}
} else {
//返回所有料架的剩余库位
Map<String, Map<String, ShelfInfo>> shelfInfoMap = TaskShelfUtil.taskShelfMap;
for (Map<String, ShelfInfo> map :
shelfInfoMap.values()) {
for (ShelfInfo shelf :
map.values()) {
Map<Integer, ShelfLoc> locMap = shelf.getLocMap();
int emptyPos = 0;
for (ShelfLoc shelfLoc : locMap.values()) {
if (shelfLoc.isEmpty()) {
emptyPos++;
}
}
if (ObjectUtil.isNotEmpty(shelf.getRealRfid())) {
rfidMap.put(shelf.getRealRfid(), emptyPos);
} else {
rfidMap.put(shelf.getOrderNo() + "-" + shelf.getShelfType() + shelf.getRfidIndex(), emptyPos);
}
}
}
}
return ResultBean.newOkResult(rfidMap);
} catch (Exception e) {
log.error("getShelfEmptySlot 出错 rfids=" + rfids, e);
}
return ResultBean.newErrorResult(-1, "", "");
}
@ApiOperation("根据rfid清空料架信息")
@RequestMapping(value = "/clearRfid")
@AnonymousAccess
public ResultBean clearRfid(@RequestParam String orderNo,@RequestParam String rfid) {
if (ObjectUtil.isNotEmpty(orderNo)) {
if (ObjectUtil.isNotEmpty(rfid)) {
ShelfInfo shelfInfo = TaskShelfUtil.findSameShelf(orderNo, rfid);
if (shelfInfo == null) {
log.info("clearRfid 未找到工单[" + orderNo + "]的rfid[" + rfid + "]");
return ResultBean.newErrorResult(99, "smfcore.taskShelf.notExist", "未找到工单[" + orderNo + "]的rfid[" + rfid + "]");
}
TaskShelfUtil.clearShelf(orderNo, rfid);
} else {
TaskShelfUtil.clearShelf(orderNo);
}
}
return ResultBean.newOkResult("");
}
@GetMapping(value = "/viewTaskShelfMap")
@AnonymousAccess
public ResultBean viewTaskShelfMap() {
return ResultBean.newOkResult(TaskShelfUtil.taskShelfMap);
}
}
......@@ -15,7 +15,9 @@ import org.springframework.data.mongodb.core.mapping.Document;
import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Data
@Document
......@@ -257,6 +259,50 @@ public class DataLog extends BasePo implements Serializable ,Comparable<DataLog>
return posId;
}
/**
* 自定义的附加信息
*/
private Map<String,Object> appendData = new HashMap<>();
/**
* 添加或更新自定义附加信息
* @param appendKey
* @param appendValue
*/
public void updateAppendData(String appendKey, Object appendValue){
appendData.put(appendKey, appendValue);
}
/**
* 获取自定义附加信息 工单料架信息: tempRfid, rfidLoc
* @param appendKey
* @param <T>
* @return
*/
public <T> T getAppendData(String appendKey){
Object value = appendData.get(appendKey);
if(value != null){
return (T)value;
}
return null;
}
public void setTempRfid(String tempRfid) {
updateAppendData("tempRfid", tempRfid);
}
public void setRfidLoc(int rfidLoc) {
updateAppendData("rfidLoc", rfidLoc);
}
public String getTempRfid(){
return getAppendData("tempRfid");
}
public Integer getRfidLoc(){
return getAppendData("rfidLoc");
}
/**
* 是否被取消
*/
public boolean isCancel(){
......
支持 Markdown 格式
你添加了 0 到此讨论。请谨慎行事。
Finish editing this message first!