InquiryShelfBean.java 16.0 KB
package com.myproject.bean.qisda;

import com.myproject.bean.update.DataLog;
import com.myproject.bean.update.qisda.OutItem;
import com.myproject.util.StorageConstants;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 *
 * 出库需求单使用料架情况
 * Created by sunke on 2019/12/15.
 */
public class InquiryShelfBean {

    protected final static Logger log = LogManager.getLogger(InquiryShelfBean.class);

    /**
     * 料架管理Map, key为 hSerial, value的key为 tempRfid, value为料架
     */
    public static Map<String,Map<String,ShelfInfo>> hSerialShelfMap = new ConcurrentHashMap<>();

    /**
     * 添加限制库位(即库位中只能放入某个条码)
     * @param task
     * @param outItem
     * @return
     */
    public static DataLog addLimitLoc(DataLog task, OutItem outItem){
        return addLoc(task, outItem, task.getBarcode());
    }

    /**
     * 首盘料时,缺料站位空出一个架位
     */
    public static void addEmptyLoc(OutItem outItem, String shelfType){
        String hSerial = outItem.gethSerial();
        ShelfInfo emptyShelfInfo = getOrAddShelfInfo(hSerial,shelfType);
        if(emptyShelfInfo != null){
            int loc = emptyShelfInfo.addEmptyLoc();
            log.info("工单"+outItem.getSo()+"["+outItem.getSlotlocation()+"]"+outItem.getPn()+"预留架位"+emptyShelfInfo.tempRfid()+"["+ loc +"]");
            updateShelfInfo(emptyShelfInfo);
        }
    }

    /**
     * 添加不限制的库位,即库位对条码不作限制
     * @param task
     * @param outItem
     * @return
     */
    public static DataLog addUnlimitLoc(DataLog task, OutItem outItem){
        return addLoc(task, outItem, "");
    }

    public static String getShelfType(DataLog task){
        //空位预留
        if(task == null){
            //根据尺寸确定预留种架位
            return StorageConstants.SHEFL_TYPE.D;
        }
        String shelfType = "";
        //包装料架
        if(task.isPackageReel()){
            shelfType = StorageConstants.SHEFL_TYPE.A;
        }else {
            //需要分盘的料,且不是包装料,统一都放到料串上
            if(task.isCutReel() || task.isUrgentReel()){
                //B料串
                return StorageConstants.SHEFL_TYPE.B;
            }else{
                if(task.isSmallReel()){
                    //D料架
                    shelfType = StorageConstants.SHEFL_TYPE.D;
                }else{
                    shelfType = StorageConstants.SHEFL_TYPE.C;
                }
            }
        }
        return shelfType;
    }


    /**
     * 获取未达最大数量的料架,或者添加一个新的料架
     * @param shelfType
     * @return
     */
    private static ShelfInfo getOrAddShelfInfo(String hSerial, String shelfType){
        Map<String, ShelfInfo> shelfMap = hSerialShelfMap.get(hSerial);
        int rfidIndex = 0;
        if(shelfMap != null){

            for (ShelfInfo shelfInfo : shelfMap.values()) {
                if(StorageConstants.SHEFL_TYPE.judgeType(shelfInfo.getShelfType(), shelfType)){
                    if(shelfInfo != null && !shelfInfo.reachMaxLoc()){
                        return shelfInfo;
                    }
                }
            }
            rfidIndex = shelfMap.size();
        }

        ShelfInfo newShelf = null;
        if(StorageConstants.SHEFL_TYPE.isAShelf(shelfType)){
            newShelf = ShelfInfo.newAShelf();
        }else if(StorageConstants.SHEFL_TYPE.isBShelf(shelfType)){
            newShelf = ShelfInfo.newBShelf();
        }if(StorageConstants.SHEFL_TYPE.isCShelf(shelfType)){
            newShelf = ShelfInfo.newCShelf();
        }else if(StorageConstants.SHEFL_TYPE.isDShelf(shelfType)){
            newShelf = ShelfInfo.newDShelf();
        }
        if(newShelf != null){
            newShelf.setRfidIndex(rfidIndex);
            newShelf.sethSerial(hSerial);
            log.info("添加新料架["+newShelf.tempRfid() + "]");
            updateShelfInfo(newShelf);
        }
        return newShelf;
    }

    /**
     * 更新料架缓存信息
     */
    public static void updateShelfInfo(ShelfInfo shelfInfo){
        String hSerial = shelfInfo.gethSerial();
        Map<String, ShelfInfo> shelfMap = hSerialShelfMap.get(hSerial);
        if(shelfMap == null){
            shelfMap = new ConcurrentHashMap<>();
        }
        shelfMap.put(shelfInfo.tempRfid(), shelfInfo);
        hSerialShelfMap.put(hSerial, shelfMap);
    }

    private static synchronized DataLog addLoc(DataLog task, OutItem outItem, String barcode){
        String shelfType = getShelfType(task);
        String hSerial = outItem.gethSerial();
        ShelfInfo emptyShelfInfo = getOrAddShelfInfo(hSerial,shelfType);
        if(emptyShelfInfo != null){
            if(task != null){
                int loc = -1;
                AppendInfo appendInfo = task.getAppendInfo();
                if(task.isPackageReel()){
                    //包装料,固定库位
                    loc = emptyShelfInfo.addLimitLoc(task.getBarcode(),task.getReelType());
                    appendInfo.setRfidLoc(loc);
                }else{
                    loc = emptyShelfInfo.addLimitLoc(barcode,task.getReelType());
                }
                log.info("工单"+outItem.getSo()+"["+outItem.getSlotlocation()+"]"+outItem.getPn()+"为["+task.getBarcode()+"]添加架位["+emptyShelfInfo.tempRfid() + "]["+ loc +"]=" + barcode);

                appendInfo.setRfidIndex(emptyShelfInfo.getRfidIndex());
                appendInfo.setShelfType(shelfType);
                appendInfo.sethSerial(hSerial);
                if(barcode != null && !barcode.isEmpty()){
                    appendInfo.setRfidLoc(loc);
                }
                task.setAppendInfo(appendInfo);

                //包装料需要在C型料架上预留位置
                if(task.isPackageReel()){
                    String cShelf = StorageConstants.SHEFL_TYPE.C;
                    ShelfInfo packageCShelf = getOrAddShelfInfo(hSerial, cShelf);
                    int packageCLoc = packageCShelf.addLimitLoc(barcode, StorageConstants.REEL_TYPE.PACKAGE);
                    log.info("包装料预留C型料架:工单"+outItem.getSo()+"["+outItem.getSlotlocation()+"]"+outItem.getPn()+"添加架位["+emptyShelfInfo.tempRfid() + "]["+ packageCLoc +"]=["+packageCShelf.tempRfid() + "]["+ loc +"]=" + barcode);
                }
            }else{
                int loc = emptyShelfInfo.addEmptyLoc();
                log.info("工单"+outItem.getSo()+"["+outItem.getSlotlocation()+"]"+outItem.getPn()+"预留架位"+emptyShelfInfo.tempRfid()+"["+ loc +"]");
            }
            updateShelfInfo(emptyShelfInfo);
        }
        return task;
    }

    /**
     * 根据tempRfid编号获取料架信息
     */
    public ShelfInfo findSameShelf(String hSerial, String rfid){
        if(hSerial != null){
            Map<String, ShelfInfo> shelfMap = hSerialShelfMap.get(hSerial);
            if(shelfMap != null){
                for (ShelfInfo shelf : shelfMap.values()) {
                    String shelfRFID = shelf.getRealRfid();
                    log.info(shelf.tempRfid() + "判断料架["+shelfRFID+"] = " + rfid);
                    if(shelfRFID != null && rfid != null){
                        if(shelfRFID.equals(rfid)){
                            //已经绑定过该Temp料架
                            return shelf;
                        }
                    }
                }
            }else{
                log.error("未找到需求单["+hSerial+"]料架["+rfid+"], 当前Map:" + hSerialShelfMap);
            }
        }
        return null;
    }

    /**
     * 3号机器人放入时查找大料架,如果没有相同RFID,查找未绑定的相同类型料架
     * @param bigRfid
     * @return
     */
    public ShelfInfo findBigShelf(String bigRfid){
        if(bigRfid == null){
            return null;
        }
        ShelfInfo maxLocShelf = null;
        for (Map<String, ShelfInfo> shelfInfoMap : hSerialShelfMap.values()) {
            for (ShelfInfo shelf : shelfInfoMap.values()) {
                String shelfRFID = shelf.getRealRfid();
                if(StorageConstants.SHEFL_TYPE.judgeType(bigRfid, shelf.getShelfType())){
                    if(shelfRFID != null){
                        if(shelfRFID.equals(bigRfid)){
                            //已经绑定过该Temp料架
                            return shelf;
                        }
                    }else{
                        //未绑定过的
                        if(maxLocShelf == null){
                            maxLocShelf = shelf;
                        }else if(shelf.getUsedLocCount() > maxLocShelf.getUsedLocCount()){
                            maxLocShelf = shelf;
                        }
                    }
                }
            }
        }
        return maxLocShelf;
    }

    /**
     * 3号机器人放入时查找包装料架上的物料信息(肯定会存在)
     * @param packageRfid
     * @return
     */
    public ShelfInfo findPackageShelf(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;
                    }
                }
            }
        }
        return null;
    }


    /**
     * 首套料,获取分配好的库位
     */
    public ShelfLoc getLimitLoc(DataLog task){
        AppendInfo appendInfo = task.getAppendInfo();
        String barcode = task.getBarcode();
        String hSerial = appendInfo.gethSerial();
        Map<String, ShelfInfo> shelfMap = hSerialShelfMap.get(hSerial);
        if(shelfMap != null){
            for (ShelfInfo shelfInfo : shelfMap.values()) {
                int loc = shelfInfo.getBarcodeLoc(barcode, appendInfo.getShelfType());
                if(loc != -1){
                    ShelfLoc shelfLoc = new ShelfLoc();
                    shelfLoc.setLoc(loc);
                    shelfLoc.setTempRfid(shelfInfo.tempRfid());
                    shelfLoc.setRealRfid(shelfInfo.getRealRfid());
                    log.info("查找到["+barcode+"]分配的库位" + shelfInfo.tempRfid()+"["+loc+"] Task库位"+appendInfo.getRfid()+"["+appendInfo.getRfidLoc()+"]");
                    return shelfLoc;
                }
            }
        }
        return null;
    }

    /**
     * 锁定架位
     */
    public synchronized ShelfLoc lockShelfLoc(DataLog task, String rfid, String robotIndex){
        AppendInfo appendInfo = task.getAppendInfo();
        String hSerial = appendInfo.gethSerial();
        ShelfInfo shelfInfo = null;
        if(hSerial != null){
            Map<String, ShelfInfo> shelfMap = hSerialShelfMap.get(hSerial);
            if(shelfMap != null){
                //先判断任务料架是否与双层线上的实际料架类型是否一致,如果不一致,直接使用新的料架
                if(rfid != null && !rfid.isEmpty()){
                    if(StorageConstants.SHEFL_TYPE.judgeType(rfid, task.getAppendInfo().getShelfType())){
                        //任务与当前料架一致,使用已经绑定过的料架
                        shelfInfo = findSameShelf(hSerial, rfid);
                    }
                }

                if(shelfInfo != null){
                    //找到与实际料架相同的料架,但料架上已经满了,查找其他同类型料架
                    if(shelfInfo.isFull()){
                        log.info("料架["+shelfInfo.getRealRfid()+"]="+shelfInfo.tempRfid()+"已满,查找新的料架");
                        shelfInfo = null;
                    }
                }

                //未找到已经有实际RFID的料架,查找库位最多的料架
                if(shelfInfo == null){
                    log.info(task.getBarcode() + "未找到实际绑定的["+rfid+"]料架,开始查找库位最多的同种料架["+task.getAppendInfo().getShelfType()+"]");
                    ShelfInfo maxLocShelf = null;
                    for (ShelfInfo shelf : shelfMap.values()) {
                        if(StorageConstants.SHEFL_TYPE.judgeType(task.getAppendInfo().getShelfType(), shelf.getShelfType())){
                            //同一种料架
                            if(maxLocShelf == null){
                                maxLocShelf = shelf;
                            }
                            if(shelf.getUsedLocCount() > maxLocShelf.getUsedLocCount()){
                                maxLocShelf = shelf;
                            }
                        }
                    }
                    shelfInfo = maxLocShelf;
                    if(shelfInfo != null){
                        log.info(task.getBarcode() + "["+ appendInfo.getTempRfid()+"]未找到rfid=["+rfid+"]的空料架,使用库位最多的同种料架["+shelfInfo.tempRfid()+"]");
                    }else{
                        log.info("已没有与["+rfid+"]类型相同的料架");;
                    }
                }
            }
        }

        if(shelfInfo == null){
            log.error("任务条码["+task.getBarcode()+"]未找到对应的料架" + rfid);
            return null;
        }


        ShelfLoc lockLoc = shelfInfo.lockOneEmptyLoc(task.getBarcode(), task.getReelType(), robotIndex);
        if(lockLoc != null){
            log.info("为["+task.getBarcode()+"]锁定架位:" + shelfInfo.tempRfid() + "[" +shelfInfo.getRealRfid()+"]["+lockLoc.getLoc()+"]原来分配架位:" + appendInfo.getTempRfid() + "[" + appendInfo.getRfidLoc() + "]");
//            ShelfLoc shelfLoc = new ShelfLoc();
//            shelfLoc.setLoc(lockLoc);
//            shelfLoc.setRfid(rfid);

            if(shelfInfo.getRealRfid() == null || shelfInfo.getRealRfid().isEmpty()){
                //未绑定过的,使用TempRFID
                lockLoc.setTempRfid(shelfInfo.tempRfid());
                lockLoc.setRealRfid("");
            }else{
                //绑定过的使用RealRfid
                lockLoc.setRealRfid(shelfInfo.getRealRfid());
                lockLoc.setTempRfid("");
            }
            updateShelfInfo(shelfInfo);
            return lockLoc;
        }
        return null;
    }


    public synchronized boolean putInShelf(DataLog task, String rfid, int loc){
        AppendInfo appendInfo = task.getAppendInfo();
        String barcode = task.getBarcode();
        String hSerial = appendInfo.gethSerial();
        Map<String, ShelfInfo> shelfMap = hSerialShelfMap.get(hSerial);
        if(shelfMap != null){
            if(appendInfo.isFirstReelAction()){
                //首盘料,要按位置放
                for (ShelfInfo shelfInfo : shelfMap.values()) {
                    boolean putInResult = shelfInfo.putInLimitLoc(rfid,loc, barcode);
                    if(putInResult){
                        updateShelfInfo(shelfInfo);
                        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("未找到["+hSerial+"]相关料架");
        }
        log.error("物料["+task.getBarcode()+"]("+task.getAppendInfo().getTempRfid()+"["+task.getAppendInfo().getRfidLoc()+"])更新料架" + rfid +"["+loc+"]缓存失败");
        return false;
    }

}