Exemple #1
0
        //*******************
        //A20.05.28.0 取得目前空BOX數量 並同時回復是否執行成功
        private (List <CassetteData> emptyBox, bool isSuccess) GetTotalEmptyBoxNumber()
        {
            List <CassetteData> emptyBox_ = new List <CassetteData>();
            bool isSuccess_ = false;

            try
            {
                emptyBox_ = cassette_dataBLL.loadCassetteData().
                            Where(data => data.CSTID == "" &&
                                  scApp.TransferService.isUnitType(data.Carrier_LOC, UnitType.SHELF)
                                  ).ToList();
                if (emptyBox_ != null)
                {
                    isSuccess_ = true;
                }
            }
            catch (Exception ex)
            {
                logger.Error(ex, "Exception:");
                emptyBoxLogger.Error(ex, DateTime.Now.ToString("HH:mm:ss.fff ") + "[GetTotalEmptyBoxNumber]");
            }
            return(emptyBox_, isSuccess_);
        }
        public void CheckTheEmptyBoxStockLevel()
        {
            emptyBoxLogger.Info("[CheckTheEmptyBoxStockLevel]");

            zoneDatas  = zoneBLL.loadZoneData();
            boxDatas   = cassette_dataBLL.loadCassetteData();
            shelfDatas = shelfDefBLL.LoadShelf();
            var emptyBox = GetTotalEmptyBoxNumber();

            if (!initializedFlag)
            {
                zoneCacheDatas = new List <ZoneDef>(zoneDatas);
                foreach (var zoneCache in zoneCacheDatas)
                {
                    zoneCache.EmptyBoxList          = new List <string>();
                    zoneCache.SolidBoxList          = new List <string>();
                    zoneCache.WaitForRecycleBoxList = new List <string>();
                }
                initializedFlag = true;
                emptyBoxLogger.Info("===== EmptyBoxHandlerService initialized =====");
            }

            //更新zone內的空箱實箱列表
            UpdateZoneData();

            //2020/06/22 Hsinyu Chang
            //A. 高水位檢查: 30秒一次
            //A1: zone內有沒有已經標記成待退的空box,有則跳過這次檢查
            //A2: 檢查是否達緊急水位,有則強制送往STK
            // A2-1: 如果沒有STK可以送,就送往其他OHB
            // A2-2: 連其他OHB也送不過去,呼叫MCS幫忙(to A3)
            //A3: 檢查是否達高水位,是則請求MCS幫退空box
            //B. 低水位檢查: 2分鐘一次
            //B1: 先確認目前的line 上shelf的空box 是否夠用(目前標準為AGV station 數量)
            //B2: 檢查各個zone是否需要補空box

            //高水位檢查
            foreach (ZoneDef zoneData in zoneCacheDatas)
            {
                //A1: zone內有沒有已經標記成待退的空box,有則跳過這次檢查
                if (zoneData.WaitForRecycleBoxList.Count() != 0)
                {
                    continue;
                }
                //A2: 檢查是否達緊急水位,有則強制送往STK,沒有STK就送往OHCV
                if (zoneData.BoxCount > zoneData.ZoneSize * emergencyWaterLevel)
                {
                    //已達緊急水位,產生往Loop or STK的manual command退box
                    emptyBoxLogger.Info($"{zoneData.ZoneID} reaches emergency water level: {zoneData.ZoneSize * emergencyWaterLevel}, force to send empty box to STK or OHCV...");
                    //找out mode下的STK port,沒有就找out mode下的OHCV port
                    string dest = scApp.TransferService.GetSTKorOHCV_OutModePortName();
                    if (string.IsNullOrWhiteSpace(dest) == false)
                    {
                        string recycleBoxID  = FindBestRecycleBoxID(zoneData, emptyBox.emptyBox);
                        string recycleBoxLoc = cassette_dataBLL.GetCassetteLocByBoxID(recycleBoxID);
                        scApp.TransferService.Manual_InsertCmd(recycleBoxLoc, dest, 5, "CheckTheEmptyBoxStockLevel", ACMD_MCS.CmdType.OHBC);
                    }
                    else
                    {
                        //沒有找到STK、OHCV為OutMode => 請求MCS幫退
                        emptyBoxLogger.Info($"No port is avaliable for recycling box directly, notice MCS and wait transfer command to recycling...");
                        RecycleBoxByMCS(zoneData, zoneData.BoxCount);
                    }
                }
                //A3: 檢查是否達高水位,是則請求MCS幫退空box
                else if (zoneData.BoxCount > zoneData.HighWaterMark)
                {
                    //還沒到緊急水位走這邊
                    //過多box,呼叫MCS退掉(優先退空的)
                    emptyBoxLogger.Info($"{zoneData.ZoneID} do not reach emergency water level, just notice MCS and wait transfer command to recycling...");
                    RecycleBoxByMCS(zoneData, zoneData.BoxCount);
                }
            }

            //低水位檢查
            if (lowLevelCheckCount < lowLevelCheckTime)
            {
                lowLevelCheckCount++;
            }
            else
            {
                lowLevelCheckCount = 0;
                //B1: 先確認目前的line 上shelf的空box 是否夠用(目前標準為AGV station 數量)
                if (emptyBox.isSuccess == true)
                {
                    int requriedBoxAGV;
                    List <CassetteData> emptyBoxList = new List <CassetteData>(emptyBox.emptyBox);
                    var isEnoughEmptyBox             = CheckIsEnoughEmptyBox(emptyBoxList.Count, out requriedBoxAGV);
                    if (isEnoughEmptyBox.isEnough == false)
                    {
                        emptyBoxLogger.Info($"Not enough empty box for AGV ST use, request for empty box...");
                        DoSendRequireEmptyBoxToMCS(zoneCacheDatas.FirstOrDefault().ZoneID, requriedBoxAGV);
                    }
                    else
                    {
                        //B2: 檢查各個zone是否需要補空box
                        foreach (ZoneDef zoneData in zoneCacheDatas)
                        {
                            if (zoneData.EmptyBoxList.Count() < zoneData.LowWaterMark)
                            {
                                emptyBoxLogger.Info($"{zoneData.ZoneID} has {zoneData.EmptyBoxList.Count()} empty box(es), reaches low water level: {zoneData.LowWaterMark}, request for empty box...");
                                //空box不足,呼叫MCS補充
                                DoSendRequireEmptyBoxToMCS(zoneData.ZoneID, (int)(zoneData.LowWaterMark - zoneData.EmptyBoxList.Count()));
                            }
                        }
                    }
                }
            }
        }