to3796zw 159eda2d4d fix: RecipeNo 재폴링 널가드 + PC_PAGE_NO 보존 + 새 Page 정상 처리
- CheckRecipeNoComp: 동일레시피 시 PLC_RECIPE_NO 재폴링(늦은 갱신 대응),
  recipe==null(0/미등록) 널 가드 추가, 에코는 활성 레시피 기준으로 null-safe 처리
- OnSeqActionStop: PC_ERROR_CODE 0 쓰기 삭제(WriteDWord가 인접 PC_PAGE_NO까지
  0으로 덮던 버그 해소) → 정지 시 에코워드 보존
- CheckInitCondition: ResumeMode 핸드셰이크 스킵 제거(옵션A) → bit15 후 PLC가
  주는 새 Recipe/Page를 정상 핸드셰이크로 처리. Resume 주석/로그도 정정
- 빌드 0오류

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 23:17:41 +09:00

130 lines
14 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 작업일지 — 2026-06-21
## 1. 가접 레시피(20~23) 추가 — 시퀀스 무수정 방식 확정
- 가접을 시퀀스로 추가하지 않고 **레시피 번호만 추가**해서 처리. (레시피 활성화+페이지별 용접 행위가 동일하므로)
- 코드 검증: 레시피 조회 `.Id` 1:1(하드코딩 없음), 페이지 검증 `Layers.Count()` 가변 → **노드 수정 불필요, 레시피 데이터만 추가.**
- Recipe Number 시트 구조 (`…_260621_가접용접추가.xlsx`):
- 11: 양극/음극 탭 비드(기존, 2P) · 31: 상면(기존, 2P) · 32: 하면(기존, 2P)
- **20: Pre 가변 전면(가접) / 21: 전면 본접 / 22: Pre 가변 후면(가접) / 23: 후면 본접** (각 1~5P)
- PRE(가접)→본접을 레시피 쌍으로 분리(전면 20→21, 후면 22→23).
## 2. Recipe/Page 핸드셰이크 — 이미 구현·커밋 확인 (`25edd79`)
- 현장 결정: PLC가 전환마다 RECIPE_REQ는 안 주고 **양극에서 PAGE_REQ만** 줌.
- 동작 = Page 신호만 체크 → Recipe/Page WORD 읽기 → RecipeNum 변화 시 활성화 → PageNum 받고 → ACK 송신. (이미 `SeqAutoRunPTOP.cs`에 반영됨)
- `CheckPageNo`: `PLC_PAGE_CHANGE_REQ`만 대기
- `CheckRecipeNoComp`: `PLC_RECIPE_NO` 읽기 → 0/미등록/현재활성 동일이면 스킵, 다를 때만 `ActivateRecipe` + `Dispatcher.Invoke(OnActiveReloaded)` 동기 Layers 재로드(stale 방지) + `PC_RECIPE_NO` 에코
- `CheckPageNoComp`: `PLC_PAGE_NO` 3회 검증 → `Layers.Count()` 범위검증 → `PC_PAGE_NO` 에코 + `PC_PAGE_CHANGE_COMPLETE`(ACK)
- 인터페이스와 1:1 일치: PAGE 핸드셰이크 `M70508/M70608`(REQ)·`M70008/M70108`(COMPLETE), 워드 `D70502/D70501`(PLC) ↔ `D70002/D70001`(PC 에코). 레시피 COMP 비트(`M70509/M70009`)는 미사용(워드 에코만).
## 3. 기동 시 디바이스 연결 vs 알람체크 타이밍 (분석단계, 소스 미수정)
- 증상: 기동 직후 연결 확립 전에 알람이 뜸.
- 결론: 순서는 이미 "활성화 → 알람모니터"로 맞음(`OnStartUp` `await ActivateDevices()` 후 `SeqAlarmMonitor.Start()`). **진짜 갭은 `Activate()≠Connected`** — 첫 알람 루프가 연결 전 `GetConnected()=false`를 읽어 오알람.
- 비대칭: PLC는 `PLC_LIVE_STATUS` 2000ms grace 있음 / **Laser·OCT·Chiller·LBAD는 즉시 알람(grace 없음)** → 오알람 주범.
- 권고 레버: **`SeqAlarmMonitor.StartNode`에 연결확립 대기 게이트 추가**(권장) > no-op `WaitTime` 노드 활용 > `OnStartUp`에서 연결 await.
## 4. bit15(MODECHANGE) 기능 구현 — 팝업 + Auto→Manual + Resume (빌드 0오류, 커밋 `ff4fc03`)
보완항목 확정: 1=작업지시서, 2=(나)작업자 수동 RunWelding, 3=작업지시서, 4=작업지시서, 5=현행유지.
- **bit 정의** (※ 현장 확정맵 반영해 명칭 정정 — 아래 6장 참고): bit15(0x0F) = **Weld_01 Ready** (`PLC_WELD_READY_REQ`/`PC_WELD_READY_ACK`, M70515/M70015). 가변용접 시 PLC가 ON → 확인 팝업 + Resume 트리거 겸용. (임시명 `MODE_CHANGE`였음)
- **정지 보존(#1)**: `OnSeqActionStop`에서 `ResumeMode`면 `PC_PAGE_NO/RECIPE_NO=0` 쓰기 스킵(에코 보존).
- **확인 핸들러(#2-나)**: `ResumeMode=true`→Stop(보존)→팝업(`MessageDialog.Show` OK-only)→Manual 전환. 레시피 이미 활성이라 재활성/롤백 안 함. 가변 용접은 작업자가 Manual에서 직접.
- **핸드셰이크 스킵(#3)**: `CheckInitCondition`에서 `ResumeMode`면 `SEQ_SET_PARAMS_UPLOAD_WELDING_LIST_SEQ`로 분기(+Flow 엣지).
- **출력 bit15 수명(#4)**: `OnAutoRunResume`에서 ON+Auto 재개, `CheckCycleStop`에서 한 사이클 후 OFF+`ResumeMode=false`.
- **감지(#5)**: `UCMainAutoRunViewModel.OnMonitoring`(화면 타이머) 현행 유지.
- 버튼 **[AutoRun Resume]** = Equipment Status 그룹 좌측, `IsModeChangeActive`(bit15 ON) 때만 표시. 확인창 없이 즉시 재개.
- 재용접 중복은 **PLC가 레이저 차단**으로 합의(option2).
## 6. 현장 확정 PLC DeviceMap 반영 — bit15 명칭/용접비트 정정 (빌드 0오류)
현장 확정 CSV(`Doc/ILSOSConfig/.../External/PLC/PLC_DeviceMap_*_M/D_Device.csv`) 확인 결과, 임시명 `MODE_CHANGE`로 잡았던 bit15가 **Weld_01 Ready로 확정**됨. 또 원래 Ready(0x10)는 **Trigger**로 밀림. 전 파일 일괄 정정.
- 0x0F (M70515/M70015): `MODE_CHANGE` → **`WELD_READY_REQ`/`WELD_READY_ACK`** (Weld_01 Ready, Resume 트리거 겸용)
- 0x10 (M70516/M70016): 기존 `WELD_READY_REQ`/`ACK` → **`WELD_TRIGGER_REQ`/`ACK`** (원래 Ready, 용접 발진 신호)
- **주소(0x0F/0x10) 불변 = 런타임 동작 동일**, 심볼 이름만 정정. 단 양극 `_P`(0x73) 미러는 제거(현장 단일블록).
- 수정 범위: 공통 enum(`WeldingCommon/.../PLCController.Address.cs`) + PTOP enum + 시퀀스 5종(SeqAutoRunPTOP/ComponentWeld/Prismatic/TestRun/WaitWeldOrChangePage) + `UCMainAutoRunViewModel`. 타 머신 영향 없음(심볼 미참조 확인).
- 레시피 번호도 변경됨: **21 전면Pre / 22 후면Pre / 23 전면 / 24 후면** (20 폐지). 코드는 데이터구동이라 영향 없음.
## 7. 미확정 / 확인 필요 (다음 액션)
- **현장 실증 전** — 빌드만 통과. bit15(Weld Ready) 흐름·레시피 전환·실제 Laser 발진은 현장 테스트 필요.
- **PLC 협의**:
- 출력 `PC_WELD_READY_ACK`(bit15) false 처리 위치 — 현재 `CheckCycleStop`. 대안: 다음 `PAGE_CHANGE_REQ` 수신 블록에서 false (CSV 노트 "15bit page change 때 init 0"과 정합 — 위치 확정 필요).
- bit15 발생 정책: CSV 노트상 **레시피 21·22(가변) 시 PLC가 ON** → 가변 페이지마다인지 레시피당 1회인지 세부 확인.
- 용접 핸드셰이크 Ready(0x0F)→Trigger(0x10) 2단계 프로토콜 — 기존 용접시작 로직 현장 동작 확인.
- 레시피 시트 "Pre **가변**" 표기가 PRE **가접** 오타인지 확인.
- 21~24 페이지 수 미확정(코드는 `Layers.Count()` 가변 대응).
- 알람 타이밍: `device.Activate()`가 연결완료까지 동기인지/개시만인지 디바이스별 확인.
- 제품 1개 = Recipe×Page 사이클 예상 시나리오: `docs/분석/2026/06/21/121750_제품1개_recipe_page_사이클_예상시나리오.md`.
## 8. 현장 피드백 반영 SW 수정 (5건, 빌드 0오류·미커밋)
> 모두 MSBuild Debug|x64 EXITCODE=0 확인. 현장 런타임 검증 대기.
1. **D70002(PC_RECIPE_NO) 에코 누락 수정** — `SeqAutoRunPTOP.cs` `CheckRecipeNoComp`
- 증상: Page CHG Request 수신·레시피는 그대로인데 `PC_RECIPE_NO`(D70002)가 안 바뀜.
- 원인: "이미 활성 레시피" 분기가 에코 없이 조기 return → 정지 시 0으로 지워진 값이 그대로 남음(PageNo는 매번 에코라 비대칭).
- 조치: 동일 레시피여도 `WriteWord(PC_RECIPE_NO, plcRecipeNo)` 에코 유지(재활성/reload는 계속 생략).
2. **bit15 Manual 전환 시 레시피 활성화+로드 추가** — `UCMainAutoRunViewModel.cs` `ShowRecipePageConfirmAndSwitchManual`
- 증상: bit15 팝업 후 Manual로 가도 레시피 비활성화되어 해당 Recipe/Page로 이동·수동용접 불가.
- 원인: "레시피 이미 활성" 가정으로 ActivateRecipe/OnActiveReloaded 생략 → 티칭/캔버스(SelectedRecipe)가 PLC 레시피로 로드 안 됨.
- 조치: `ActivateRecipe(recipe.Id)` + `RecipeHelper.OnActiveReloaded()` 추가(미등록/0이면 현재 활성 레시피 폴백).
3. **bit15 ON 중 AUTO_REQ 자동시작 무시** — `UCMainAutoRunViewModel.cs` `OnAutoRunStartRequest`
- 증상: bit15 살아있을 때 Recipe/Page 팝업과 "자동운전 시작?" 팝업이 동시에 뜨고, Manual이 아닌 Auto로 복귀.
- 원인: AutoRun 팝업은 `PLC_AUTO_REQ`(0x02) rising edge로 트리거(bit15와 별개·무가드), TimerMessageBox default=true(5초 자동확인)가 Manual을 덮어씀.
- 조치: `OnAutoRunStartRequest` 진입부에 `PLC_WELD_READY_REQ`(0x0F=bit15) ON이면 즉시 return. (Resume 버튼 경로는 별개라 무관)
4. **정지 시 에코 워드 0 초기화 제거** — `SeqAutoRunPTOP.cs` `OnSeqActionStop`
- `if(!ResumeMode){ PC_PAGE_NO=0; PC_RECIPE_NO=0; }` 블록 제거 → 모든 정지에서 D70001·D70002 보존(다음 사이클 재에코). `PC_ERROR_CODE=0`은 유지.
5. **[AutoRun Resume] PC bit15 1초 펄스 OFF** — `UCMainAutoRunViewModel.cs` `OnAutoRunResume`
- `PC_WELD_READY_ACK`(PC쪽 bit15) ON 직후 one-shot DispatcherTimer로 1초 뒤 자동 false.
- 참고: 시퀀스 `CheckCycleStop`의 동일 OFF는 이제 중복(무해) — 정리는 별도 검토.
### 검증 메모 (bit15 흐름)
- bit15 감지는 `OnMonitoring`이 **실 PLC(비-Simul)** 에서만 동작(Simul 가드) → 벤치 검증 불가, 실 PLC 필요.
- 코드는 입력 **0x0F(`PLC_WELD_READY_REQ`)** 를 봄 → PLC의 "15번 bit" 실주소가 0x0F(M70515)인지 디바이스맵 대조 필요(안 먹히면 1순위 원인).
- 확인 로그: `[Bit15] ModeChange…` / `[Bit15] Recipe 활성화+로드…` / `[Bit15] bit15 ON 중 → AUTO_REQ 자동시작 무시` / `[Bit15] PC_WELD_READY_ACK OFF (1초 펄스)`.
## 9. 양극(P) 미사용 정리 + eCommon READY 제거 + 로그 개편 (빌드 0오류·미커밋)
### 9-1. 공유 enum eCommon READY(0x0F) 제거 — `WeldingCommon/Devices/PLC/PLCController.Address.cs`
- `eCommonBitInput.PLC_WELD_READY_REQ` / `eCommonBitOutput.PC_WELD_READY_ACK` (0x0F) **제거**(`// 0x0A~0x0F` 예약범위로). 공유 enum의 READY는 미사용 항목(실제 bit15는 PTOP enum 0x0F 사용)이라 제거 안전. `PC_WELD_TRIGGER_ACK`(0x10)는 유지.
- **PTOP enum의 READY(0x0F)는 유지** → bit15/Resume 코드 영향 없음.
### 9-2. 양극(P) PC→PLC 출력 전체 제거 (현장: 현재 장비 P 미사용)
- 증상: `Out of Range: 0x0065 (WriteBit)` — 0x65=`PC_AUTO_STATUS_P`(양극 Auto, M70601)가 출력맵에 없는데 코드가 씀.
- **PC_AUTO_STATUS_P(0x65) 쓰기 8곳 제거** — `SeqAutoRunPTOP`(Sequence_Enter/InitAutoRunBit/OnSeqActionStop) + `UCMainAutoRunViewModel`(bit15핸들러/OnAutoRunResume/OnAutoRunStartRequest×2/OnStopSequenceAutoRun).
- **양극 용접 핸드셰이크(PC_WELD_P_* 0x74~76) 제거** — `WaitWeldingStart`·`ExecuteWelding`의 `plcPageNo==2` 양극 분기 삭제 → **모든 페이지 음극 비트(0x10~12)로 통일**(용접 트리거가 음극 `PLC_WELD_TRIGGER_REQ`라 정합). `RestoreDeviceStatus`·`InitAutoRunBit` 양극 리셋도 제거.
- 검증: 두 파일에 `PC_AUTO_STATUS_P`/`PC_WELD_P_` 0건.
- ⚠️ PLC 확인: 이제 page2 용접 완료도 음극 COMPLETE(0x12)로 송신 → PLC가 전 페이지를 음극 완료로 받는지 정합 확인 필요. (보조 `SeqAutoRunPrismatic`의 양극 비트는 미변경.)
### 9-3. SeqAutoRunPTOP 로그 개편 (로그만 수정, 로직 무변경)
- 제네릭 `[X] 노드 Start/End` 전부 제거 → 각 노드 동작을 설명하는 로그로 교체(InitSequenceVariable/LaserReadyResponse/SaveScannerRecordFileForamt/RestoreDeviceStatus/InitDev/CheckDeviceReady/CheckCondition/CheckCondition_Interlock/InitializeDeviceStatus/InitAutoRunBit/OnForceError/OnStopped). 잘못된 프리픽스(`SaveScannerRecordFileForamt` 내 `[SaveResultData]`) 정정.
- 핵심 동작 노드는 기존 촘촘한 로그 유지 → 로그만으로 시퀀스 어느 구간인지 추적 가능.
## 10. 현장 진행 상황 / 이어서 할 일
- **확인 완료(현장)**: 앞서 수정분으로 해당 구간 **정상 통과** 확인, **Auto↔Manual 모드 전환** 동작 확인.
- **보류**: Recipe No / Page No 관련 **이번 세션 수정 코드는 아직 현장 미적용** → 추후 현장에 적용 후 검증 예정.
- **이어서 할 일(다음)**: 수정 코드(D70002 에코, 정지 시 에코워드 보존, 양극 제거/음극 통일, bit15 흐름, 로그 개편) 현장 반영 → Recipe/Page 핸드셰이크 + 용접 완료신호(음극) PLC 정합 재확인부터 이어감.
- 상태: 이번 세션 변경 4개 파일 + 작업일지 커밋·푸시 완료(`e61e99f`).
### 10-1. 현장 후속 이슈 수정 (빌드 0오류)
- **증상①**: bit15 들어올 때 `PC_PAGE_NO`(D70001)가 0으로 바뀜.
- **진짜 원인(현재 코드 버그)**: `OnSeqActionStop`의 `_PLC.WriteDWord(PC_ERROR_CODE, 0)`가 **32비트(2워드)** 쓰기라 인접 `PC_PAGE_NO`(idx1)까지 0으로 덮음. `PC_RECIPE_NO`(idx2)는 무영향 → PAGE_NO만 0이 된 현상과 일치. (정지 시마다 발생)
- **조치**: `PC_ERROR_CODE` 미사용 → 정지 시 0 쓰기 **줄 삭제**(WriteDWord 제거). 인접 PC_PAGE_NO 클로버 문제 해소 + 에코 워드는 그대로 보존.
- **증상②**: bit15 이후 Page Change bit가 와도 PageNo 안 바뀌고 시퀀스 미동작.
- 원인: bit15 후 [AutoRun Resume]가 `ResumeMode`로 **핸드셰이크를 스킵**하고 직전 `_CurrentPageNo`로 용접 → 새 Page 미반영.
- **조치(옵션A 채택)**: `CheckInitCondition`의 ResumeMode 스킵 분기 **제거** → 재개 시에도 `CheckPageNo`부터 정상 핸드셰이크 → PLC가 주는 새 Page Change 정상 처리. (ResumeMode는 Resume 버튼 게이트 + CheckCycleStop 정리 용도로만 잔존)
- 미커밋. 현장 검증(① PAGE_NO 보존, ② bit15→Resume→새 Page 정상 처리) 후 커밋 예정.
### 10-2. 다음 점검 항목 (TODO)
- [ ] **PLC 시퀀스 체크** — Recipe/Page 핸드셰이크 + 용접 트리거/완료(음극 0x10~12) PLC↔PC 신호 정합 전체 점검(에코·완료비트 타이밍, page2 음극 완료 수용 여부 포함).
- [ ] **신규 가변 용접 시나리오 체크** — bit15(가변 페이지)에서 정지·팝업 → Manual 티칭 → [AutoRun Resume] → 새 Recipe/Page 정상 핸드셰이크 → 용접까지 1사이클 end-to-end 검증(가접 레시피 21~24 포함).