diff --git a/.vs/marking_gui.slnx/v18/.suo b/.vs/marking_gui.slnx/v18/.suo index 67c01aa..fb1a699 100644 Binary files a/.vs/marking_gui.slnx/v18/.suo and b/.vs/marking_gui.slnx/v18/.suo differ diff --git a/.vs/marking_gui.slnx/v18/DocumentLayout.backup.json b/.vs/marking_gui.slnx/v18/DocumentLayout.backup.json index f151ae1..22dca5d 100644 --- a/.vs/marking_gui.slnx/v18/DocumentLayout.backup.json +++ b/.vs/marking_gui.slnx/v18/DocumentLayout.backup.json @@ -22,12 +22,16 @@ "DocumentGroups": [ { "DockedWidth": 200, - "SelectedChildIndex": 3, + "SelectedChildIndex": 4, "Children": [ { "$type": "Bookmark", "Name": "ST:0:0:{aa2115a1-9712-457b-9047-dbb71ca2cdd2}" }, + { + "$type": "Bookmark", + "Name": "ST:0:0:{cce594b6-0c39-4442-ba28-10c64ac7e89f}" + }, { "$type": "Document", "DocumentIndex": 1, @@ -37,8 +41,7 @@ "ToolTip": "C:\\Users\\COMPUTER1\\Desktop\\mobi\\marking_gui\\marking_gui\\QrVerificationWindow.xaml", "RelativeToolTip": "marking_gui\\QrVerificationWindow.xaml", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.003549|", - "WhenOpened": "2026-07-29T04:12:09.69Z", - "EditorCaption": "" + "WhenOpened": "2026-07-29T04:12:09.69Z" }, { "$type": "Document", @@ -49,8 +52,7 @@ "ToolTip": "C:\\Users\\COMPUTER1\\Desktop\\mobi\\marking_gui\\marking_gui\\SettingsWindow.xaml", "RelativeToolTip": "marking_gui\\SettingsWindow.xaml", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.003549|", - "WhenOpened": "2026-07-29T04:12:06.926Z", - "EditorCaption": "" + "WhenOpened": "2026-07-29T04:12:06.926Z" }, { "$type": "Document", diff --git a/.vs/marking_gui.slnx/v18/DocumentLayout.json b/.vs/marking_gui.slnx/v18/DocumentLayout.json index f151ae1..22dca5d 100644 --- a/.vs/marking_gui.slnx/v18/DocumentLayout.json +++ b/.vs/marking_gui.slnx/v18/DocumentLayout.json @@ -22,12 +22,16 @@ "DocumentGroups": [ { "DockedWidth": 200, - "SelectedChildIndex": 3, + "SelectedChildIndex": 4, "Children": [ { "$type": "Bookmark", "Name": "ST:0:0:{aa2115a1-9712-457b-9047-dbb71ca2cdd2}" }, + { + "$type": "Bookmark", + "Name": "ST:0:0:{cce594b6-0c39-4442-ba28-10c64ac7e89f}" + }, { "$type": "Document", "DocumentIndex": 1, @@ -37,8 +41,7 @@ "ToolTip": "C:\\Users\\COMPUTER1\\Desktop\\mobi\\marking_gui\\marking_gui\\QrVerificationWindow.xaml", "RelativeToolTip": "marking_gui\\QrVerificationWindow.xaml", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.003549|", - "WhenOpened": "2026-07-29T04:12:09.69Z", - "EditorCaption": "" + "WhenOpened": "2026-07-29T04:12:09.69Z" }, { "$type": "Document", @@ -49,8 +52,7 @@ "ToolTip": "C:\\Users\\COMPUTER1\\Desktop\\mobi\\marking_gui\\marking_gui\\SettingsWindow.xaml", "RelativeToolTip": "marking_gui\\SettingsWindow.xaml", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.003549|", - "WhenOpened": "2026-07-29T04:12:06.926Z", - "EditorCaption": "" + "WhenOpened": "2026-07-29T04:12:06.926Z" }, { "$type": "Document", diff --git a/marking_gui/MainWindow.xaml b/marking_gui/MainWindow.xaml index d4eb44c..a445187 100644 --- a/marking_gui/MainWindow.xaml +++ b/marking_gui/MainWindow.xaml @@ -449,7 +449,7 @@ - + diff --git a/marking_gui/MainWindow.xaml.cs b/marking_gui/MainWindow.xaml.cs index 0d98f95..eb9bd08 100644 --- a/marking_gui/MainWindow.xaml.cs +++ b/marking_gui/MainWindow.xaml.cs @@ -355,7 +355,7 @@ namespace marking_gui private void UpdateRangeGuides() { - txtVoltageRangeGuide.Text = string.Format("기준범위: {0:F1}V ~ {1:F1}V", _limits.MinVoltage, _limits.MaxVoltage); + txtVoltageRangeGuide.Text = string.Format("기준범위: {0:F2}V ~ {1:F2}V", _limits.MinVoltage, _limits.MaxVoltage); txtCurrentRangeGuide.Text = string.Format("기준범위: {0:F2}mA ~ {1:F2}mA", _limits.MinCurrent, _limits.MaxCurrent); txtResistanceRangeGuide.Text = string.Format("기준범위: {0:F3}kΩ ~ {1:F3}kΩ", _limits.MinResistance, _limits.MaxResistance); } @@ -1363,9 +1363,6 @@ namespace marking_gui string lotNo = string.IsNullOrWhiteSpace(_loginInfo.LotNo) ? "00" : _loginInfo.LotNo.Trim(); string markedSerial = string.Format("{0}{1:D4}", lotNo, seq); - string drawingNo = _markingConfig.DrawingNo; - string hkmcNo = _markingConfig.HkmcNo; - string qrString = string.Format("{0};{1};{2};{3};", serial, drawingNo, hkmcNo, markedSerial); // 마킹 스캔 요청 데이터 빌드 var req = new MarkingRequest @@ -1374,12 +1371,12 @@ namespace marking_gui IcSerial = serial, LotNo = lotNo, ProductNo = _loginInfo.Model, - DrawingNo = drawingNo, - HkmcNo = hkmcNo, + DrawingNo = string.Empty, + HkmcNo = string.Empty, EzdFileName = _currentEzdFile, LineCode = _loginInfo.LineNo, ShiftCode = "A", // 기본 1조 - QrString = qrString + QrString = string.Empty }; MarkingResult markingRes; @@ -1387,12 +1384,19 @@ namespace marking_gui { // 오프라인 모드 시뮬레이션 await System.Threading.Tasks.Task.Delay(500); + string offDrawingNo = _markingConfig.GetDrawingNoForEzd(_currentEzdFile); + string offHkmcNo = _markingConfig.GetHkmcNoForEzd(_currentEzdFile); + string offQr = string.Format("{0};{1};{2};{3};", serial, offDrawingNo, offHkmcNo, markedSerial); + markingRes = new MarkingResult { Success = true, ErrorCode = 0, ErrorMessage = "오프라인 모드 각인 완료 모사", - MarkedAt = DateTime.Now + MarkedAt = DateTime.Now, + DrawingNo = offDrawingNo, + HkmcNo = offHkmcNo, + QrString = offQr }; } else @@ -1403,13 +1407,17 @@ namespace marking_gui // UI 스레드로 안전하게 컴백 await Dispatcher.InvokeAsync(async () => { + string ezdDrawingNo = markingRes.DrawingNo; + string ezdHkmcNo = markingRes.HkmcNo; + string ezdQrString = markingRes.QrString; + if (txtMarkedSerial != null) { txtMarkedSerial.Text = markedSerial; } if (txtMarkingQr != null) { - txtMarkingQr.Text = qrString; + txtMarkingQr.Text = string.IsNullOrWhiteSpace(ezdQrString) ? "---" : ezdQrString; } bool finalMarkingPass = markingRes.Success; @@ -1418,10 +1426,10 @@ namespace marking_gui { if (txtMarkingStatus != null) txtMarkingStatus.Text = "마킹 완료 (QR 검증 대기)"; if (borderMarkingStatus != null) borderMarkingStatus.Background = new SolidColorBrush(Color.FromRgb(245, 158, 11)); // Amber - LoggerService.Info($"[마킹 성공] S/N: {serial}, 각인번호: {markedSerial} -> QR 검증 팝업 오픈"); + LoggerService.Info($"[마킹 성공] S/N: {serial}, 각인번호: {markedSerial}, 도면품번: {ezdDrawingNo}, HKMC품번: {ezdHkmcNo} -> QR 검증 팝업 오픈"); // DB 저장 전 레이저 각인 QR 코드 스캔 검증 팝업 오픈 (시리얼 스캐너 서비스 인계) - var qrVerifyWin = new QrVerificationWindow(qrString, _barcodeScanner) + var qrVerifyWin = new QrVerificationWindow(ezdQrString, _barcodeScanner) { Owner = this }; @@ -1439,8 +1447,8 @@ namespace marking_gui if (borderMarkingStatus != null) borderMarkingStatus.Background = new SolidColorBrush(Color.FromRgb(16, 185, 129)); // Green LoggerService.Info($"[QR 검증 성공] S/N: {serial}, 각인번호: {markedSerial} -> DB 저장 진행"); - // QR 검증 통과 시 최종 DB 저장 및 완료 처리 - await SaveAndFinalizeAsync(serial, finalVoltage, finalCurrent, finalResistance, true, "OK", markedSerial, bypassPrevSteps); + // QR 검증 통과 시 최종 DB 저장 및 완료 처리 (EZD 추출 실시간 품번 포함) + await SaveAndFinalizeAsync(serial, finalVoltage, finalCurrent, finalResistance, true, "OK", markedSerial, ezdDrawingNo, ezdHkmcNo, bypassPrevSteps); } else { @@ -1448,8 +1456,8 @@ namespace marking_gui if (borderMarkingStatus != null) borderMarkingStatus.Background = new SolidColorBrush(Color.FromRgb(239, 68, 68)); // Red LoggerService.Warn($"[QR 검증 실패] S/N: {serial}, 각인번호: {markedSerial} -> DB NG 저장 진행"); - // 마킹 성공 후 QR 검증 불일치/취소 시 NG로 DB 저장 - await SaveAndFinalizeAsync(serial, finalVoltage, finalCurrent, finalResistance, false, "NG", markedSerial, bypassPrevSteps); + // 마킹 성공 후 QR 검증 불일치/취소 시 NG로 DB 저장 (EZD 추출 실시간 품번 포함) + await SaveAndFinalizeAsync(serial, finalVoltage, finalCurrent, finalResistance, false, "NG", markedSerial, ezdDrawingNo, ezdHkmcNo, bypassPrevSteps); } } else @@ -1526,8 +1534,12 @@ namespace marking_gui } else { - // 불합격인 경우 즉시 DB 저장 및 복구 - await SaveAndFinalizeAsync(serial, finalVoltage, finalCurrent, finalResistance, isFinalPass, "NG", "", bypassPrevSteps); + // 불합격인 경우에도 Lot No 및 예정 각인번호/품번 정보를 포함하여 DB 저장 및 복구 + string markedSerial = GetCurrentMarkedSerial(); + string drawingNo = _markingConfig.GetDrawingNoForEzd(_currentEzdFile); + string hkmcNo = _markingConfig.GetHkmcNoForEzd(_currentEzdFile); + + await SaveAndFinalizeAsync(serial, finalVoltage, finalCurrent, finalResistance, isFinalPass, "NG", markedSerial, drawingNo, hkmcNo, bypassPrevSteps: bypassPrevSteps); } } } @@ -1586,7 +1598,38 @@ namespace marking_gui } } - private async Task SaveAndFinalizeAsync(string serial, double voltage, double current, double resistance, bool isFinalPass, string result, string markedSerial, bool bypassPrevSteps = false) + private string GetCurrentMarkedSerial() + { + int seq = 1; + if (txtNextSequence != null) + { + if (Dispatcher.CheckAccess()) + { + string rawText = txtNextSequence.Text; + string digitsOnly = System.Text.RegularExpressions.Regex.Replace(rawText ?? "", @"[^\d]", ""); + if (int.TryParse(digitsOnly, out int parsedSeq) && parsedSeq > 0) + { + seq = parsedSeq; + } + } + else + { + Dispatcher.Invoke(() => + { + string rawText = txtNextSequence.Text; + string digitsOnly = System.Text.RegularExpressions.Regex.Replace(rawText ?? "", @"[^\d]", ""); + if (int.TryParse(digitsOnly, out int parsedSeq) && parsedSeq > 0) + { + seq = parsedSeq; + } + }); + } + } + string lotNo = string.IsNullOrWhiteSpace(_loginInfo.LotNo) ? "00" : _loginInfo.LotNo.Trim(); + return string.Format("{0}{1:D4}", lotNo, seq); + } + + private async Task SaveAndFinalizeAsync(string serial, double voltage, double current, double resistance, bool isFinalPass, string result, string markedSerial, string drawingNo = "", string hkmcNo = "", bool bypassPrevSteps = false) { // 종료 시간 기록 및 UI 갱신 _testEndTime = DateTime.Now; @@ -1608,6 +1651,9 @@ namespace marking_gui _currentProduct.PcbBarcode = serial; } + string finalDrawingNo = string.IsNullOrWhiteSpace(drawingNo) ? _markingConfig.DrawingNo : drawingNo; + string finalHkmcNo = string.IsNullOrWhiteSpace(hkmcNo) ? _markingConfig.HkmcNo : hkmcNo; + try { // 데이터베이스 저장 (비동기 스레드 격리로 UI 프리징 방지) @@ -1631,8 +1677,8 @@ namespace marking_gui _testEndTime, markedSerial, pcbBarcodeToSave, // 강제검사 시 시리얼 번호 사용 - _markingConfig.DrawingNo, - _markingConfig.HkmcNo); + finalDrawingNo, + finalHkmcNo); }); if (dbResult) @@ -1745,11 +1791,18 @@ namespace marking_gui { borderNormalStatus.Visibility = System.Windows.Visibility.Collapsed; } - } - // 컨트롤 원상 복구 (재검사를 위해) - txtSerial.IsEnabled = true; - SetStartButtonReady(); + _dbWasOffline = true; + SetStartButtonConnecting("⚠️ DB 연결 필요"); + } + finally + { + txtSerial.IsEnabled = true; + if (!_dbWasOffline) + { + SetStartButtonReady(); + } + } } // 화면 렌더링 완료 시 최초 로그인 팝업 구동 @@ -1835,6 +1888,11 @@ namespace marking_gui { // DB 재연결 감시 루프 중단 _dbWatcherCts?.Cancel(); + _dbWatcherCts?.Dispose(); + + // 윈도우 타이머 정지 (WPF DispatcherTimer GC 메모리 누수 방지) + _clockTimer?.Stop(); + _clockTimer = null; // LMC 마킹 기계 무선/시리얼 연결 핸들 안전 해제 (재시작 시 LMC 장치 락 방지) _markingService?.Shutdown(); @@ -1882,7 +1940,7 @@ namespace marking_gui if (!_isInspectionRunning) { - Dispatcher.Invoke(() => + await Dispatcher.InvokeAsync(() => { SetStartButtonConnecting("⚠️ DB 연결 필요"); @@ -1906,7 +1964,7 @@ namespace marking_gui if (!_isInspectionRunning) { - Dispatcher.Invoke(() => + await Dispatcher.InvokeAsync(() => { if (txtSystemStatus != null) { @@ -1921,11 +1979,6 @@ namespace marking_gui await Dispatcher.InvokeAsync(() => RefreshNextSequence()); } } - else if (isNowConnected && !_dbWasOffline && !_isInspectionRunning) - { - // DB 연결 유지 상태에서도 DB 레코드 직접 변경/삭제 시 각인 순번 실시간 반영 (조용히 UI 갱신) - await Dispatcher.InvokeAsync(() => RefreshNextSequenceSilently()); - } } catch (Exception ex) { @@ -2101,7 +2154,18 @@ namespace marking_gui { _markingConfig.SaveLastSelectedEzdFile(fullPath); } - LoggerService.Info($"EZD 도안 파일 선택 완료: {fileName} (절대경로: {fullPath})"); + + string drawingNo = string.Empty; + string hkmcNo = string.Empty; + if (_markingService is EzdMarkingService ezdService) + { + drawingNo = ezdService.GetTextFromEzd(_markingConfig.DrawingNoTag, fullPath); + hkmcNo = ezdService.GetTextFromEzd(_markingConfig.HkmcNoTag, fullPath); + } + if (string.IsNullOrWhiteSpace(drawingNo)) drawingNo = _markingConfig.GetDrawingNoForEzd(fullPath); + if (string.IsNullOrWhiteSpace(hkmcNo)) hkmcNo = _markingConfig.GetHkmcNoForEzd(fullPath); + + LoggerService.Info($"EZD 도안 파일 선택 완료: {fileName} (절대경로: {fullPath}, 도면품번: {drawingNo}, HKMC품번: {hkmcNo})"); } private void InitializeBarcodeScanner() diff --git a/marking_gui/Manual/.obsidian/workspace.json b/marking_gui/Manual/.obsidian/workspace.json index 3f3bab1..e323cef 100644 --- a/marking_gui/Manual/.obsidian/workspace.json +++ b/marking_gui/Manual/.obsidian/workspace.json @@ -41,7 +41,9 @@ "type": "file-explorer", "state": { "sortOrder": "alphabetical", - "autoReveal": false + "autoReveal": false, + "showSearch": false, + "searchQuery": "" }, "icon": "lucide-folder-closed", "title": "파일 탐색기" diff --git a/marking_gui/Manual/07_시험_프로세스.md b/marking_gui/Manual/07_시험_프로세스.md index 335910b..fa876ef 100644 --- a/marking_gui/Manual/07_시험_프로세스.md +++ b/marking_gui/Manual/07_시험_프로세스.md @@ -67,8 +67,8 @@ graph TD * 이 경우 레이저 마킹 장비 구동은 자동으로 제외(Skip)되며, `NG` 내역으로 DB에 기록됩니다. 2. **모든 항목이 합격인 경우 (OK)**: * 모든 수치가 기준치 내에 들어오면 최종 합격(**`OK`**) 판정이 내려집니다. - * 합격 판정과 동시에 레이저 마킹기에 각인 데이터가 전달되어 QR 코드 및 제품 일련번호 각인이 자동으로 실행됩니다. - * 마킹 완료 후 QR 스캔 검증 팝업이 활성화되어 각인 상태를 교차 검증합니다. + * 합격 판정과 동시에 선택된 EZD 도안 파일(.ezd)에서 도면품번 및 HKMC품번을 실시간으로 추출하여 각인 및 QR 코드가 자동으로 조합되어 레이저 마킹이 실행됩니다. + * 마킹 완료 후 EZD 파싱 품번 기반의 QR 스캔 검증 팝업이 활성화되어 각인 상태를 교차 검증하고, 검증 완료 시 해당 품번 데이터로 DB 저장을 완료합니다. --- @@ -76,12 +76,14 @@ graph TD 레이저 마킹이 완료되면 검증을 위해 **QR 검증 팝업 창**이 화면에 활성화되며 바코드 스캐너 또는 가상 키보드로 각인된 QR 코드를 읽어 들입니다. -1. **QR 스캔 검증 성공 (즉시 자동 닫힘)** +1. **QR 스캔 검증 성공 (즉시 자동 닫힘 및 DB OK 적재)** - 스캔된 QR 코드가 예상 QR 코드와 정확히 일치하면 팝업 창이 지연 없이 **즉시 자동으로 닫히며** DB에 `OK` 상태로 최종 저장을 완료하고 대기 상태로 복구됩니다. -2. **QR 스캔 검증 실패 (NG 판정 및 설명 표출)** - - 스캔된 QR 코드가 불일치하거나 검증을 취소하는 경우, 작업자가 [확인] 버튼을 누르면 팝업 창이 닫힙니다. - - 팝업이 닫힘과 동시에 메인 화면의 대형 판정 카드가 **`OK`**에서 **`NG`** (빨간색 테두리 및 배경)로 즉시 전환됩니다. +2. **QR 스캔 검증 실패 (팝업 유지 및 연속 재스캔 지원)** + - 스캔된 QR 코드가 불일치(대조 실패)할 경우, 팝업 창이 **자동으로 닫히지 않고 열린 상태를 유지**하며 "QR 바코드 불일치" 경고 상태를 표출합니다. + - 팝업이 열려 있는 동안 바코드/QR 스캐너 또는 키보드 입력을 통해 올바른 QR 코드로 **연속 재스캔**할 수 있으며, 재스캔에서 대조 성공 시 자동으로 통과(닫힘) 및 DB `OK` 저장 처리됩니다. + - 대조 불일치 상태에서 작업자가 **[확인]** 또는 **[취소]** (ESC 키) 버튼을 누르면 팝업 창이 닫히며, 판정 결과 **`NG`**로 데이터베이스 저장을 완료합니다. + - 팝업이 닫힘과 동시에 메인 화면의 대형 판정 카드가 **`OK`**에서 **`NG`** (빨간색 테두리 및 배경)로 전환됩니다. - 공정 진행 상태 및 시스템 상태 바에 `"마킹 완료 / 각인 QR 검증 NG"`, `"상태: 검사 불합격 (각인 QR 검증 실패)"`, `"각인 QR 검증 실패 (DB NG 저장 완료)"` 등 구체적인 원인 설명이 표시되며, DB에 최종 `NG` 결과로 기록됩니다. diff --git a/marking_gui/Manual/Manual_Merged.md b/marking_gui/Manual/Manual_Merged.md index b776e98..dbf36f9 100644 --- a/marking_gui/Manual/Manual_Merged.md +++ b/marking_gui/Manual/Manual_Merged.md @@ -658,7 +658,7 @@ Channel=1 ; 통신 채널 번호 (1 또는 2) * **세부 정보 그리드**: - **검사 시간 정보**: 전체 시퀀스 기동 시작 시간 및 종료 시간 표출 - **일련번호 정보**: `IC S/N`, **`Marking QR :`** (마킹 생성 QR 값), **`Scan QR :`** (스캐너 실측 QR 값), `각인 번호` 4개 항목을 수직 배열로 표출 - - **최종 판정결과**: 최종 **PASS/OK** (초록색) / **FAIL/NG** (빨간색) 대형 배지 표출 (성능 합격 후 마킹 QR 검증 실패 시에도 **NG**로 자동 반영됨) + - **최종 판정결과**: 최종 **`OK`** (초록색) / **`NG`** (빨간색) 대형 배지 표출 (성능 합격 후 마킹 QR 검증 실패 시에도 **`NG`**로 자동 반영됨) - **시스템 상태**: 통신 및 디바이스 가동 상태 또는 에러/검증 실패 사유 메시지 배너 표출 Pasted image 20260728100413.png --- @@ -840,8 +840,8 @@ graph TD H --> I[12~14단계: 전압 / 저항 / 전류 실측] I --> J[15단계: 테스트 주전원 안전 차단] J --> K{최종 규격 비교 판정} - K -- 1개 이상 이탈 FAIL --> L[대형 FAIL 표시 & 마킹 제외 & DB 불합격 적재] - K -- 모두 통과 PASS --> M[대형 PASS 표시 & DB 합격 적재 & LMC1 레이저 QR 각인] + K -- 1개 이상 이탈 NG --> L[대형 NG 표시 & 마킹 제외 & DB NG 적재] + K -- 모두 통과 OK --> M[대형 OK 표시 & DB OK 적재 & LMC1 레이저 QR 각인] L --> Z M --> Z ``` @@ -880,13 +880,13 @@ graph TD 계측이 완료되면 측정된 전압(V), 저항(kΩ), 전류(mA) 값을 설정한 기준 규격값(SPEC)과 비교하여 최종 판정을 내립니다. -1. **기준 규격을 벗어난 경우 (FAIL)**: - * 전압, 전류, 저항 중 하나라도 기준을 벗어나면 최종 불합격(FAIL) 판정이 내려집니다. - * 이 경우 레이저 마킹 장비 구동은 자동으로 제외(Skip)되며, 불합격 내역으로 DB에 기록됩니다. -2. **모든 항목이 합격인 경우 (PASS)**: - * 모든 수치가 기준치 내에 들어오면 최종 합격(PASS) 판정이 내려집니다. - * 합격 판정과 동시에 레이저 마킹기에 각인 데이터가 전달되어 QR 코드 및 제품 일련번호 각인이 자동으로 실행됩니다. - * 마킹 완료 후 QR 스캔 검증 팝업이 활성화되어 각인 상태를 교차 검증합니다. +1. **기준 규격을 벗어난 경우 (NG)**: + * 전압, 전류, 저항 중 하나라도 기준을 벗어나면 최종 불합격(**`NG`**) 판정이 내려집니다. + * 이 경우 레이저 마킹 장비 구동은 자동으로 제외(Skip)되며, `NG` 내역으로 DB에 기록됩니다. +2. **모든 항목이 합격인 경우 (OK)**: + * 모든 수치가 기준치 내에 들어오면 최종 합격(**`OK`**) 판정이 내려집니다. + * 합격 판정과 동시에 선택된 EZD 도안 파일(.ezd)에서 도면품번 및 HKMC품번을 실시간으로 추출하여 각인 및 QR 코드가 자동으로 조합되어 레이저 마킹이 실행됩니다. + * 마킹 완료 후 EZD 파싱 품번 기반의 QR 스캔 검증 팝업이 활성화되어 각인 상태를 교차 검증하고, 검증 완료 시 해당 품번 데이터로 DB 저장을 완료합니다. --- @@ -894,12 +894,14 @@ graph TD 레이저 마킹이 완료되면 검증을 위해 **QR 검증 팝업 창**이 화면에 활성화되며 바코드 스캐너 또는 가상 키보드로 각인된 QR 코드를 읽어 들입니다. -1. **QR 스캔 검증 성공 (즉시 자동 닫힘)** +1. **QR 스캔 검증 성공 (즉시 자동 닫힘 및 DB OK 적재)** - 스캔된 QR 코드가 예상 QR 코드와 정확히 일치하면 팝업 창이 지연 없이 **즉시 자동으로 닫히며** DB에 `OK` 상태로 최종 저장을 완료하고 대기 상태로 복구됩니다. -2. **QR 스캔 검증 실패 (NG 판정 및 설명 표출)** - - 스캔된 QR 코드가 불일치하거나 검증을 취소하는 경우, 작업자가 [확인] 버튼을 누르면 팝업 창이 닫힙니다. - - 팝업이 닫힘과 동시에 메인 화면의 대형 판정 카드가 **`OK`**에서 **`NG`** (빨간색 테두리 및 배경)로 즉시 전환됩니다. +2. **QR 스캔 검증 실패 (팝업 유지 및 연속 재스캔 지원)** + - 스캔된 QR 코드가 불일치(대조 실패)할 경우, 팝업 창이 **자동으로 닫히지 않고 열린 상태를 유지**하며 "QR 바코드 불일치" 경고 상태를 표출합니다. + - 팝업이 열려 있는 동안 바코드/QR 스캐너 또는 키보드 입력을 통해 올바른 QR 코드로 **연속 재스캔**할 수 있으며, 재스캔에서 대조 성공 시 자동으로 통과(닫힘) 및 DB `OK` 저장 처리됩니다. + - 대조 불일치 상태에서 작업자가 **[확인]** 또는 **[취소]** (ESC 키) 버튼을 누르면 팝업 창이 닫히며, 판정 결과 **`NG`**로 데이터베이스 저장을 완료합니다. + - 팝업이 닫힘과 동시에 메인 화면의 대형 판정 카드가 **`OK`**에서 **`NG`** (빨간색 테두리 및 배경)로 전환됩니다. - 공정 진행 상태 및 시스템 상태 바에 `"마킹 완료 / 각인 QR 검증 NG"`, `"상태: 검사 불합격 (각인 QR 검증 실패)"`, `"각인 QR 검증 실패 (DB NG 저장 완료)"` 등 구체적인 원인 설명이 표시되며, DB에 최종 `NG` 결과로 기록됩니다. diff --git a/marking_gui/Manual/Manual_for_pdf.html b/marking_gui/Manual/Manual_for_pdf.html index e40fbdf..5a9e004 100644 --- a/marking_gui/Manual/Manual_for_pdf.html +++ b/marking_gui/Manual/Manual_for_pdf.html @@ -405,9 +405,9 @@ a:hover {
  • 프로그램 실행 및 로그인
  • 바탕화면의 Marking System (marking_gui) 프로그램을 실행한 뒤, 작업자 계정 정보를 입력하여 로그인합니다. (데이터베이스 점검 중인 경우 설정 파일을 통해 오프라인 모드로의 진입이 가능합니다.)
  • 통신 상태 확인 및 채널 설정
  • -
  • 우측 상단의 통신 설정 메뉴에서 센서가 올바른 포트와 채널에 연결되었는지 확인합니다.
  • +
  • 화면 하단 바의 포트 설정 버튼을 클릭하여 센서가 올바른 포트와 채널에 연결되었는지 확인합니다.
  • 검사 규격값 검증
  • -
  • 우측 상단의 시험 설정 메뉴를 열고, 전압/전류/저항 검사 기준치와 각인 템플릿 도면 파일의 경로가 올바른지 점검합니다.
  • +
  • 화면 하단 바의 파라미터 설정 버튼을 클릭하여 전압/전류/저항 검사 기준치와 각인 템플릿 도면 파일의 경로가 올바른지 점검합니다.
  • 성능 검사 및 마킹 시작
  • 안착 지그에 제품을 바르게 장착한 뒤 메인 화면 하단의 검사 시작 (START) 버튼을 눌러 계측 및 마킹을 수행합니다.
  • @@ -640,7 +640,7 @@ a:hover {

    1) Setting.ini (주요 변경 가능 설정)

    현장 네트워크 IP, 도안 파일 경로 및 검사 규격(임계치) 변경 시 수정하는 주요 설정 항목입니다.

    [Settings]
    -EzdFolderPath=c:\EzCad\EasyCfg    ; EZD 도안 파일 기본 탐색/저장 폴더 경로
    +EzdFolderPath=c:\EzCad                   ; EZD 도안 파일 기본 탐색/저장 폴더 경로
     test=false                       ; 테스트 마킹 버튼 및 개발 모드 노출 여부 (true/false)
     
     [Equipment]
    @@ -738,9 +738,9 @@ Channel=1                        ; 통신 채널 번호 (1 또는 2)
     Pasted image 20260728100354.png

    3.2.3 [카드 3] 측정 데이터 수치 카드 (우측 상단)

    실제 계측기를 통해 수집된 3대 전기 파라미터 수치와 설정된 규격 범위를 표시하는 3열 구조의 카드입니다. -* 측정 전압 (Voltage): DMM 계측 장비가 측정한 실측 전압 수치 (V 단위, 기본 기준범위: 0.0V ~ 0.5V) -* 측정 전류 (Current): Power Supply 전원공급 장치가 측정한 소모 전류 수치 (mA 단위, 기본 기준범위: 8.00mA ~ 10.00mA) -* 측정 저항 (Resistance): DMM 측정 장비가 측정한 전기적 저항 수치 (kΩ 단위, 기본 기준범위: 0.400kΩ ~ 0.800kΩ) +* 측정 전압 (Voltage): DMM 계측 장비가 측정한 실측 전압 수치 (V 단위, 기본 기준범위: 1.00V ~ 6.00V) +* 측정 전류 (Current): Power Supply 전원공급 장치가 측정한 소모 전류 수치 (mA 단위, 기본 기준범위: 5.00mA ~ 10.00mA) +* 측정 저항 (Resistance): DMM 측정 장비가 측정한 전기적 저항 수치 (kΩ 단위, 기본 기준범위: 8.000kΩ ~ 13.000kΩ) * 알림: 각 수치 카드 하단에는 설정 파일(Setting.ini)에서 지정한 임계 규격 범위가 표시되며, 실측값이 범위 내에 들어오면 카드 테두리가 초록색(PASS)으로, 범위를 벗어나면 빨간색(FAIL)으로 자동 전환됩니다. Pasted image 20260728100404.png

    3.2.4 [카드 4] 최종 판정 및 종합 상태 영역 (우측 하단)

    @@ -749,7 +749,7 @@ Channel=1 ; 통신 채널 번호 (1 또는 2) * 세부 정보 그리드: - 검사 시간 정보: 전체 시퀀스 기동 시작 시간 및 종료 시간 표출 - 일련번호 정보: IC S/N, Marking QR : (마킹 생성 QR 값), Scan QR : (스캐너 실측 QR 값), 각인 번호 4개 항목을 수직 배열로 표출 - - 최종 판정결과: 최종 PASS/OK (초록색) / FAIL/NG (빨간색) 대형 배지 표출 (성능 합격 후 마킹 QR 검증 실패 시에도 NG로 자동 반영됨) + - 최종 판정결과: 최종 OK (초록색) / NG (빨간색) 대형 배지 표출 (성능 합격 후 마킹 QR 검증 실패 시에도 NG로 자동 반영됨) - 시스템 상태: 통신 및 디바이스 가동 상태 또는 에러/검증 실패 사유 메시지 배너 표출 Pasted image 20260728100413.png


    @@ -761,7 +761,7 @@ Channel=1 ; 통신 채널 번호 (1 또는 2)
  • 포트 설정: 센서 통신 보드의 시리얼 COM 포트 및 채널 설정 창을 호출합니다.
  • 강제 검사 (스킵): 이전 공정 이력이 없어도 검증을 건너뛰고 계측 및 마킹을 수행합니다.
  • 테스트 마킹: 계측 과정 없이 레이저 각인 장비 동작을 테스트합니다.
  • -
  • 참고: 강제 검사 (스킵) 및 테스트 마킹 버튼은 설정 파일(Setting.ini)에서 TestMode=true로 활성화된 경우에만 화면에 노출됩니다. +
  • 참고: 강제 검사 (스킵) 버튼은 설정 파일(Setting.ini)에서 test=true로 활성화된 경우에만 화면에 노출됩니다. Pasted image 20260728100445.png
  • @@ -924,8 +924,8 @@ Channel=1 ; 통신 채널 번호 (1 또는 2) H --> I[12~14단계: 전압 / 저항 / 전류 실측] I --> J[15단계: 테스트 주전원 안전 차단] J --> K{최종 규격 비교 판정} - K -- 1개 이상 이탈 FAIL --> L[대형 FAIL 표시 & 마킹 제외 & DB 불합격 적재] - K -- 모두 통과 PASS --> M[대형 PASS 표시 & DB 합격 적재 & LMC1 레이저 QR 각인] + K -- 1개 이상 이탈 NG --> L[대형 NG 표시 & 마킹 제외 & DB NG 적재] + K -- 모두 통과 OK --> M[대형 OK 표시 & DB OK 적재 & LMC1 레이저 QR 각인] L --> Z M --> Z
    @@ -961,15 +961,15 @@ Channel=1 ; 통신 채널 번호 (1 또는 2)

    7.3 최종 판정 및 마킹 실행 조건

    계측이 완료되면 측정된 전압(V), 저항(kΩ), 전류(mA) 값을 설정한 기준 규격값(SPEC)과 비교하여 최종 판정을 내립니다.

      -
    1. 기준 규격을 벗어난 경우 (FAIL):
    @@ -977,15 +977,17 @@ Channel=1 ; 통신 채널 번호 (1 또는 2)

    7.4 레이저 각인 QR 검증 팝업 및 결과 연동

    레이저 마킹이 완료되면 검증을 위해 QR 검증 팝업 창이 화면에 활성화되며 바코드 스캐너 또는 가상 키보드로 각인된 QR 코드를 읽어 들입니다.

      -
    1. QR 스캔 검증 성공 (즉시 자동 닫힘)
    2. +
    3. QR 스캔 검증 성공 (즉시 자동 닫힘 및 DB OK 적재)
    4. 스캔된 QR 코드가 예상 QR 코드와 정확히 일치하면 팝업 창이 지연 없이 즉시 자동으로 닫히며 DB에 OK 상태로 최종 저장을 완료하고 대기 상태로 복구됩니다.

    5. -

      QR 스캔 검증 실패 (NG 판정 및 설명 표출)

      +

      QR 스캔 검증 실패 (팝업 유지 및 연속 재스캔 지원)

    6. -
    7. 스캔된 QR 코드가 불일치하거나 검증을 취소하는 경우, 작업자가 [확인] 버튼을 누르면 팝업 창이 닫힙니다.
    8. -
    9. 팝업이 닫힘과 동시에 메인 화면의 대형 판정 카드가 OK에서 NG (빨간색 테두리 및 배경)로 즉시 전환됩니다.
    10. +
    11. 스캔된 QR 코드가 불일치(대조 실패)할 경우, 팝업 창이 자동으로 닫히지 않고 열린 상태를 유지하며 "QR 바코드 불일치" 경고 상태를 표출합니다.
    12. +
    13. 팝업이 열려 있는 동안 바코드/QR 스캐너 또는 키보드 입력을 통해 올바른 QR 코드로 연속 재스캔할 수 있으며, 재스캔에서 대조 성공 시 자동으로 통과(닫힘) 및 DB OK 저장 처리됩니다.
    14. +
    15. 대조 불일치 상태에서 작업자가 [확인] 또는 [취소] (ESC 키) 버튼을 누르면 팝업 창이 닫히며, 판정 결과 NG로 데이터베이스 저장을 완료합니다.
    16. +
    17. 팝업이 닫힘과 동시에 메인 화면의 대형 판정 카드가 OK에서 NG (빨간색 테두리 및 배경)로 전환됩니다.
    18. 공정 진행 상태 및 시스템 상태 바에 "마킹 완료 / 각인 QR 검증 NG", "상태: 검사 불합격 (각인 QR 검증 실패)", "각인 QR 검증 실패 (DB NG 저장 완료)" 등 구체적인 원인 설명이 표시되며, DB에 최종 NG 결과로 기록됩니다.
    @@ -996,7 +998,7 @@ Channel=1 ; 통신 채널 번호 (1 또는 2)

    본 제어 프로그램은 설비 가동 중에 발생하는 계측기와의 통신 상태, 측정값 정보 및 각종 예외 오류 상황을 로그 파일로 기록합니다.

    8.1.1 로그 파일 보관 방법