Commit be279abb sunke

包装料机器人逻辑

1 个父辈 57191c57
......@@ -26,6 +26,16 @@ public class InquiryShelfBean {
public static Map<String,Map<String,ShelfInfo>> hSerialShelfMap = new ConcurrentHashMap<>();
/**
* 清理使用过的料架
*/
public static void clearShelf(String hSerial){
if(hSerial != null){
log.info("清理["+hSerial+"]使用的过料架");
hSerialShelfMap.remove(hSerial);
}
}
/**
* 添加限制库位(即库位中只能放入某个条码)
* @param task
* @param outItem
......@@ -241,18 +251,20 @@ public class InquiryShelfBean {
* @param packageRfid
* @return
*/
public ShelfInfo findPackageShelf(String packageRfid){
public ShelfInfo findPackageShelf(String hSerial, String packageRfid){
if(packageRfid == null){
return null;
}
for (Map<String, ShelfInfo> shelfInfoMap : hSerialShelfMap.values()) {
for (ShelfInfo shelf : shelfInfoMap.values()) {
String shelfRFID = shelf.getRealRfid();
if(shelfRFID != null){
if(shelfRFID.equals(packageRfid)){
//已经绑定过该Temp料架
return shelf;
}
Map<String, ShelfInfo> shSerialShelfInfoMap = hSerialShelfMap.get(hSerial);
if(shSerialShelfInfoMap == null ){
return null;
}
for (ShelfInfo shelf : shSerialShelfInfoMap.values()) {
String shelfRFID = shelf.getRealRfid();
if(shelfRFID != null){
if(shelfRFID.equals(packageRfid)){
//已经绑定过该Temp料架
return shelf;
}
}
}
......@@ -284,6 +296,28 @@ public class InquiryShelfBean {
return null;
}
public ShelfInfo findMaxUsedShelf(String hSerial, String shelfType){
Map<String, ShelfInfo> shelfMap = hSerialShelfMap.get(hSerial);
ShelfInfo maxLocShelf = null;
for (ShelfInfo shelf : shelfMap.values()) {
if(StorageConstants.SHEFL_TYPE.judgeType(shelfType, shelf.getShelfType())){
//同一种料架
if(maxLocShelf == null){
maxLocShelf = shelf;
}
if(shelf.getUsedLocCount() > maxLocShelf.getUsedLocCount()){
maxLocShelf = shelf;
}
}
}
if(maxLocShelf != null){
log.info("找到类型为["+shelfType+"]库位最多的同种料架["+maxLocShelf.tempRfid()+"]");
}else{
log.info("已没有与["+shelfType+"]类型相同的料架");;
}
return maxLocShelf;
}
/**
* 锁定架位
*/
......
......@@ -177,6 +177,14 @@ public class OutInfo extends BaseMongoBean {
return getAction().contains("首盘");
}
/**
* 补料需求单
*/
public boolean isTailAction(){
return getAction().contains("补料");
}
public int getTaskFinishNum() {
return taskFinishNum;
}
......
......@@ -26,6 +26,22 @@ public class OutInfoCache {
//定时查询未完成的需求单
private static Map<String,OutInfo> outInfoMap = new ConcurrentHashMap<>();
/**
* 当前正在执行的工单需求单(首盘,补料),未完成时,其他工单需求单不可执行
*/
private static String currentOrderHSerial = "";
public static void setCurrentOrderHSerial(String currentOrderHSerial) {
if(currentOrderHSerial == null){
currentOrderHSerial = "";
}
OutInfoCache.currentOrderHSerial = currentOrderHSerial;
}
public String getCurrentOrderHSerial() {
return currentOrderHSerial;
}
@Autowired
private IOutInfoDao outInfoDao;
......
......@@ -429,17 +429,17 @@ public class QisdaApiController extends BaseController {
private void realBindReel(OutItem outItem){
if(!outItem.isCutMaterial()){
//先从预绑定料盘中进行绑定,如果还有缺料的,从未使用的物料中查找,如果还缺料,从预绑定的物料中查找
log.info("绑定非分盘料:So=["+outItem.getSo()+"]hSerial=["+outItem.gethSerial()+"]+refno=["+outItem.getRefno()+"]的slotLoction"+outItem.getSlotlocation()+"]pn=["+outItem.getPn()+"]当前绑定数量["+outItem.getRealLockQty()+"/"+outItem.getQty()+"]");
log.info("绑定非分盘料:So=["+outItem.getSo()+"]hSerial=["+outItem.gethSerial()+"]+refno=["+outItem.getRefno()+"]的slotLoction"+outItem.getSlotlocation()+"]pn=["+outItem.getPn()+"]当前绑定数量["+outItem.getRealLockQty()+"/"+outItem.getQty()+"]当前出库/发料数量["+outItem.getOutQty()+"/"+outItem.getSendQty()+"]");
List<StoragePos> preBindPosList = storagePosDao.findPreBindList(outItem.getSo(), outItem.getSlotlocation());
for (StoragePos pos : preBindPosList) {
outItem = tryRealBind(pos, outItem);
}
log.info("将预绑定转为真实绑定结束,当前数量:"+ outItem.getRealLockQty() +"/" + outItem.getQty());
int needNum = outItem.getQty() - outItem.getRealLockQty();
//所需数量=需求单数量-已发料数量-真实绑定数量
int needNum = outItem.getQty() - outItem.getSendQty() - outItem.getRealLockQty();
log.info("将预绑定转为真实绑定结束,所需数量("+needNum+")=需求单数量("+outItem.getQty()+")-已发料数量("+ outItem.getSendQty()+")-真实绑定数量"+ outItem.getRealLockQty() +")");
if(needNum >= 0){
log.info("预绑定数量不足,查找未绑定料盘进行真实绑定结束,当前数量:"+ outItem.getRealLockQty() +"/" + outItem.getQty());
log.info("预绑定数量不足,查找未绑定料盘进行真实绑定结束,当前数量:"+outItem.getSendQty()+"+"+ outItem.getRealLockQty() +"/" + outItem.getQty());
while(needNum >= 0){
StoragePos pos = storagePosDao.findNoBindMinQty(outItem.getPn(), outItem.getFacility());
OutItem resultOutItem = tryRealBind(pos, outItem);
......@@ -455,9 +455,9 @@ public class QisdaApiController extends BaseController {
}
needNum = outItem.getQty() - outItem.getRealLockQty();
needNum = outItem.getQty() - outItem.getSendQty() - outItem.getRealLockQty();
if(needNum >= 0 ){
log.info("未绑定料盘数量不足,开始抢其他工单的预绑定物料进行真实绑定,当前数量:"+ outItem.getRealLockQty() +"/" + outItem.getQty());
log.info("未绑定料盘数量不足,开始抢其他工单的预绑定物料进行真实绑定,当前数量:"+outItem.getSendQty()+"+"+ outItem.getRealLockQty() +"/" + outItem.getQty());
//抢其他工单的预绑定
while(needNum >= 0){
StoragePos pos = storagePosDao.findOtherPreBindMinQty(outItem.getPn(), outItem.getFacility());
......@@ -466,13 +466,13 @@ public class QisdaApiController extends BaseController {
break;
}
outItem = resultOutItem;
if(outItem.getRealLockQty() > outItem.getQty()){
if(outItem.getRealLockQty() + outItem.getSendQty() > outItem.getQty()){
//已经满足需求了,直接跳出
break;
}
}
}
log.info("So=["+outItem.getSo()+"]hSerial=["+outItem.gethSerial()+"]+refno=["+outItem.getRefno()+"]的slot"+outItem.getSlotlocation()+"]pn=["+outItem.getPn()+"]真实绑定结束,当前数量:"+ outItem.getRealLockQty() +"/" + outItem.getQty());
log.info("So=["+outItem.getSo()+"]hSerial=["+outItem.gethSerial()+"]+refno=["+outItem.getRefno()+"]的slot"+outItem.getSlotlocation()+"]pn=["+outItem.getPn()+"]真实绑定结束,当前数量:"+outItem.getSendQty()+"+"+ outItem.getRealLockQty() +"/" + outItem.getQty());
}
}
......@@ -993,9 +993,10 @@ public class QisdaApiController extends BaseController {
tasks.add(task);
}
}else{
int needNum = outItem.getQty() - outItem.getRealLockQty();
//紧急料,未绑定数量=需求单数量-已出库数量-已绑数量
int needNum = outItem.getQty() - outItem.getOutQty() - outItem.getRealLockQty();
if(needNum >= 0){
log.info("紧急料,查找未绑定料盘进行出库,当前数量:"+ outItem.getRealLockQty() +"/" + outItem.getQty());
log.info("紧急料,查找未绑定料盘进行出库,未绑数量为"+needNum+"=(需求单"+ outItem.getQty() + ") - (已出" + outItem.getOutQty() + ")-已绑(" + outItem.getRealLockQty()+")");
while(needNum >= 0){
StoragePos pos = storagePosDao.findNoBindMinQty(outItem.getPn(), outItem.getFacility());
if(pos != null){
......@@ -1139,25 +1140,15 @@ public class QisdaApiController extends BaseController {
}
}
//清理掉已经完成的需求单的料架
// Set<String> hserialSet = InquiryShelfBean.hSerialShelfMap.keySet();
// for (String hserial : hserialSet) {
// OutInfo out = outInfoDao.findByHSerial(hSerial);
// if(!outInfo.isReelCutAction() && !outInfo.isUrgentAction()){
// log.info("清理需求单["+out.gethSerial()+"]占用的料架");
// InquiryShelfBean.hSerialShelfMap.remove(hserial);
// }
// }
//TODO:可以出的时候把之前的料架信息清空
outInfo.setTaskNum(0);
outInfo.setTaskFinishNum(0);
outInfo.setOutReelNum(0);
outInfo = outInfoDao.save(outInfo);
//如果是工单需求单,设置当前正在执行的工单需求单
if(outInfo.isFirstReelAction() || outInfo.isTailAction()){
String oldHSerial = outInfoCache.getCurrentOrderHSerial();
log.info("设置当前正在执行的工单料需求为:" + outInfo.gethSerial()+"清理之前["+oldHSerial+"]出库使用的料架");
InquiryShelfBean.clearShelf(oldHSerial);
outInfoCache.setCurrentOrderHSerial(outInfo.gethSerial());
}
List<DataLog> tasks = new ArrayList<>();
......@@ -1186,8 +1177,12 @@ public class QisdaApiController extends BaseController {
int outReelNum = tasks.size();
if(outReelNum > 0){
log.info("需求单"+outInfo.gethSerial()+"已出("+outInfo.getOutReelNum()+")/已发("+outInfo.getTaskFinishNum()+") 本次出库料盘数量:" + outReelNum);
outInfo.setOutReelNum(0);
outInfo.setTaskFinishNum(0);
outInfo.setTaskNum(outReelNum);
outInfo = outInfoDao.save(outInfo);
//先出小料盘,再出大料盘
for (DataLog task : tasks) {
if(task.isSmallReel()){
......@@ -1201,7 +1196,6 @@ public class QisdaApiController extends BaseController {
}
}
log.info("需求单"+outInfo.gethSerial()+" 出库料盘数量:" + outReelNum);
if(outInfo.isReelCutAction() || outInfo.isFirstReelAction()){
if(outReelNum == 0){
......
......@@ -584,9 +584,9 @@ public class StorageDataController extends BaseController {
}else {
StoragePos pos = null;
try {
log.info("条码["+barcode.getBarcode()+"]入库,清空Facility入库信息");
barcode.setAppendInfo(null);
barcode = barcodeManager.save(barcode);
// log.info("条码["+barcode.getBarcode()+"]入库,清空Facility入库信息");
// barcode.setAppendInfo(null);
// barcode = barcodeManager.save(barcode);
pos = taskService.findEmptyPosForPutIn(storageList,barcode, rfid);
if(pos != null){
......
......@@ -559,30 +559,28 @@ public class TaskService implements ITaskService {
}
}
//按任务数量从小到大排序
// List<Map.Entry<String, Integer>> list = new ArrayList<>(countMap.entrySet());
// Collections.sort(list, new Comparator<Map.Entry<String, Integer>>()
// {
// @Override
// public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2)
// {
// //按照value值,用compareTo()方法默认是从小到大排序
// return o1.getValue().compareTo(o2.getValue());
// }
// });
//可用的料仓(在线,且可以放入)
List<Storage> availbleStorageList = new ArrayList<>();
for(Storage storage : storageList){
StatusBean status = getStatus(storage.getCid());
if(status.timeOut()){
continue;
}
if(storage.canPutIn(barcode.getPlateSize(),barcode.getHeight())){
availbleStorageList.add(storage);
}
}
//
for (Storage storage : storageList) {
for (Storage storage : availbleStorageList) {
String storageId = storage.getId();
Integer taskCount = countMap.get(storageId);
if(taskCount >= 2){
continue;
}
StatusBean status = getStatus(storage.getCid());
if(status.timeOut()){
continue;
}
try{
log.info("尝试从"+storage.getName()+"["+storage.getCid()+"]查找空位,当前料仓任务数:" + taskCount);
return findLineEmptyPosForPutIn(storage,barcode);
......@@ -591,6 +589,17 @@ public class TaskService implements ITaskService {
}
}
//只有一个料仓可以入时,只能继续往里面放
log.info("可用料仓太少,不按任务数分配,重新查找...");
for (Storage storage : availbleStorageList) {
try{
log.info("尝试从"+storage.getName()+"["+storage.getCid()+"]查找空位,当前料仓任务数");
return findLineEmptyPosForPutIn(storage,barcode);
}catch(Exception e){
log.info("从"+storage.getName()+"["+storage.getCid()+"]查找空位失败:" + e.getMessage());
}
}
return null;
}
......@@ -1027,6 +1036,11 @@ public class TaskService implements ITaskService {
}
}
if(!shelfNameList.contains(storageTask.getAppendInfo().getTempRfid())){
if(storageTask.getAppendInfo().isCShelfTask()){
//大料(C料架)只能同时出一个架子,不然到包装料工位时无法切换
log.info("未完成的工单料架为:["+String.join(",",shelfNameList)+ "]大料架任务["+storageTask.getBarcode()+"]暂停出库,以免包装工位无法切换");
return null;
}
//未完成的工单任务料架数量>2,且未包含此任务,任务先不出,等到只有一个料架时再说
if(shelfNameList.size() >= 2){
log.info("未完成的工单任务料架为:["+String.join(",",shelfNameList)+ "]任务"+storageTask.getBarcode()+"暂停出库");
......
支持 Markdown 格式
你添加了 0 到此讨论。请谨慎行事。
Finish editing this message first!