diff --git a/Machines/ILSOS_CCW_H52A/Datas/CellInfoScheduler.cs b/Machines/ILSOS_CCW_H52A/Datas/CellInfoScheduler.cs index 9256830..ac58d3b 100644 --- a/Machines/ILSOS_CCW_H52A/Datas/CellInfoScheduler.cs +++ b/Machines/ILSOS_CCW_H52A/Datas/CellInfoScheduler.cs @@ -57,6 +57,8 @@ namespace ILSOS_CCW_H52A.Data private readonly JigInfo _pendingFromReportSlot = new JigInfo(); // 정지 직전 Complete: 용접은 완료됐으나 ReportSlot 진입 전 정지 (LBAD 수신 여부 불확실) private readonly JigInfo _pendingFromComplete = new JigInfo(); + // 정지 직전 큐 잔류: Dequeue 전 큐에만 있던 셀 (파이프라인 미진입) + private readonly JigInfo _pendingFromQueue = new JigInfo(); // ── 재시작 미완료 보고 접근 ────────────────────────────────────────────────── // 우선순위: _pendingFromReportSlot > _pendingFromComplete @@ -88,7 +90,8 @@ namespace ILSOS_CCW_H52A.Data // 정지 전 미용접 슬롯이 보존돼 있는지 (재시작 후 복원 가능 여부) public bool HasPendingPrefetch => !string.IsNullOrEmpty(_pendingPrefetch1.CellId) - || !string.IsNullOrEmpty(_pendingPrefetch2.CellId); + || !string.IsNullOrEmpty(_pendingPrefetch2.CellId) + || !string.IsNullOrEmpty(_pendingFromQueue.CellId); // 보고가 필요한 상태인지 (정상 + 재시작 모두 포함) >> 용접 완, 보고 미완 // ReportSlot은 Shift()마다 갱신되므로 IsCanExist·WeldComplete 조건을 함께 확인한다. @@ -149,6 +152,7 @@ namespace ILSOS_CCW_H52A.Data /// 재시작 시 해당 JigNo의 보존된 셀 정보 복원 시도. /// 성공 시 해당 슬롯을 즉시 클리어하여 한 번만 사용되도록 보장. /// canExist=false 지그가 들어오면 슬롯을 소비(폐기)하여 이후 오염 방지. + /// 우선순위: _pendingPrefetch1 → _pendingPrefetch2 → _pendingFromQueue /// /// 복원 성공 시 true (ReceivedCellInfoQueue TryDequeue 불필요) public bool TryRestoreCell(int jigNo, out string lotId, out string cellId) @@ -165,11 +169,31 @@ namespace ILSOS_CCW_H52A.Data _pendingPrefetch2.Clear(); return true; } + if (_pendingFromQueue.JigNo == jigNo && !string.IsNullOrEmpty(_pendingFromQueue.CellId)) { + lotId = _pendingFromQueue.LotId; + cellId = _pendingFromQueue.CellId; + _pendingFromQueue.Clear(); + return true; + } lotId = null; cellId = null; return false; } + /// + /// 정지 시점에 큐에 잔류한 셀을 JigNo와 함께 보존. + /// Prefetch2.JigNo 기준으로 다음 지그 번호를 계산하여 호출자가 전달. + /// DrainCellInfoQueue() 호출 전에 먼저 호출해야 한다. + /// + public void SaveQueueEntry(string lotId, string cellId, int jigNo) + { + _pendingFromQueue.Clear(); + _pendingFromQueue.LotId = lotId; + _pendingFromQueue.CellId = cellId; + _pendingFromQueue.JigNo = jigNo; + // IsCanExist는 재시작 후 ReadyScannerList에서 PLC 실측값으로 채워지므로 여기서 설정하지 않음 + } + /// /// LBAD MES Report 수신 시 CellId로 파이프라인 슬롯을 찾아 LbadAvg를 저장. /// 정상 경로: Complete 단계에서 수신 (~100ms 후). diff --git a/Machines/ILSOS_CCW_H52A/Sequences/SeqAutoRunCCWH52A.cs b/Machines/ILSOS_CCW_H52A/Sequences/SeqAutoRunCCWH52A.cs index 05d1445..152577e 100644 --- a/Machines/ILSOS_CCW_H52A/Sequences/SeqAutoRunCCWH52A.cs +++ b/Machines/ILSOS_CCW_H52A/Sequences/SeqAutoRunCCWH52A.cs @@ -448,6 +448,17 @@ namespace ILSOS_CCW_H52A.Sequences // SavePendingComplete()로 _pendingSlot에 복사한 뒤 Reset()을 호출한다. _CellScheduler.SavePendingComplete(); + + // 큐 잔류 셀 보존 — DrainCellInfoQueue 전에 선행 (Prefetch2 다음 지그 기준) + // Prefetch2.JigNo가 확정값이므로 다음 지그 = (JigNo % 16) + 1 로 신뢰성 있게 계산 + if (_CellScheduler.Prefetch2 != null && _CellScheduler.Prefetch2.JigNo > 0) { + int nextJigNo = (_CellScheduler.Prefetch2.JigNo % ProcessManager.RotaryJigCount) + 1; + if (ProcessManager.Instance.ReceivedCellInfoQueue.TryDequeue(out var qCell)) { + _CellScheduler.SaveQueueEntry(qCell.LotId, qCell.CellId, nextJigNo); + Log.I($"[QueueSave] Jig{nextJigNo} 큐 잔류 셀 보존 >> CellId({qCell.CellId})"); + } + } + if (_CellScheduler.HasPendingPrefetch) Log.I("[PendingRestore] 미용접 셀 보존됨 >> 재시작 후 JigNo 매칭 시 복원 예정"); _CellScheduler.Reset();