NohDoyeon241104 3849d4d951 docs: ScoutField 페이지별 로드 버그 작업지시서 + 작업일지 2026-06-19
- FieldHelper.json 분석 및 selectedIndexNo stale 버그 원인 정리
- A안(SeqScoutNormal PageIndex 주입) 수정안 작업지시서 작성 (소스 미수정, null 가드 포함)
- 작업일지 16:30 항목 + 주말 출근(06.20~06.21) 기록

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 17:23:54 +09:00

226 lines
18 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-19
## 09:27
- External/Aurora/bin 을 git 커밋 대상에 포함시킴 (전역 `bin/` 무시는 유지, negation 예외 처리)
- `.gitignore`에 `!/External/Aurora/bin/`, `!/External/Aurora/bin/**` 두 줄 추가
- `.gitignore` 자체가 `/.gitignore`로 무시되어 `git add -f`로 강제 추가
- Aurora bin 산출물 14개 파일 + .gitignore 함께 커밋 (7f464ab)
- 위 커밋 규칙을 `docs/GIT_RULES.md`로 문서화
- bin 무시/예외, .gitignore 자체 커밋(-f) 규칙 정리
- `architecture.md`에 `@import ./GIT_RULES.md` 연결 (목차 7번 추가)
- 커밋 후 push (de0c1c2)
## 09:39
- WPF 빌드 자동 생성 임시 파일 `*_wpftmp.csproj`를 `.gitignore`에 추가
- `AuroraPLC_2pjacgrp_wpftmp.csproj`는 sln/csproj 어디에도 참조되지 않는 빌드 산출물 → 커밋 대상 아님
- 매번 git status에 안 뜨도록 `*_wpftmp.csproj` 무시 처리, push (3724007)
- 그 외 정리: rules.md 규칙 5번 .md 영문 작성 요건 제거(3293455), PtoP PLC 인터페이스 xlsx(260617) 삭제(7cb6525) 커밋·push
## 09:47
- 어제 필드가 좁았던 부분 Scan Field size 변경하던 곳 위치
- 프로그램상 Setting - SystemParameterILSOS - Scout 영역의 Scan field size (캔버스 영역 지정)
- 어제 그 레시피에서 캔버스 크기가 작았던 이슈 때문에 수정한 부분으로, 이 위치가 캔버스(Scan field) 크기를 수정하는 곳임
## 10:00
- Recipe > Laser Shot > Laser Control - Guide Beam Status 의 Guide Beam 버튼 동작 소스 분석
- **UI/바인딩**: `WeldingComponents/WeldingCommon/Views/Recipes/UCScannerObjectTeachingControlBox.xaml`
의 Guide Beam 버튼 → ViewModel `CMD_LaserGuideBeam`(DelegateCommand) → `PerformCmdLaserGuideBeam()` 호출
(ViewModel: 같은 폴더 `UCScannerObjectTeachingControlBoxViewModel.cs`)
- **버튼 핸들러(토글 동작)**: `PerformCmdLaserGuideBeam()` (456~463줄)
- `_Laser.GetPilotLaserSetBitStatus()` 가 false 면 `_Laser.PilotLaserOn()`, true 면 `_Laser.PilotLaserOff()`
- 즉 현재 파일럿(Guide) 레이저 set 비트 상태를 보고 ON/OFF 를 번갈아 보내는 토글 버튼
- **디바이스 추상화**: `_Laser` 는 `AuroraDevices/AuroraLaser/Laser.cs` 의 베이스 `Laser`
(`DeviceManager[CommonDeviceIds.Laser]`). 베이스는 IsSimul 이면 OK, 미활성/null 이면 GENERIC(GuideBeam 미동작),
아니면 내부 `ILaser` 구현체로 위임. 구체 타입은 `eLaserType` config 로 결정(ArmLaser/TruPulse/IPG_IO/Trumpf_IO 등)
- **실제 하드웨어 제어(예: IPG_IO `AuroraDevices/AuroraLaser/IPG/LaserIPG_IO.cs`)**:
- `PilotLaserOn()` → `SetLaserDOCommand(eADOAddress.GuideLaserEnable, true)` → IO보드 `WriteDoBit(GuideLaserEnable, true)`
- `PilotLaserOff()` → 같은 DO 비트를 false 로 Write → 가이드 빔 OFF
- **상태 표시(Guide Beam Status)**: ViewModel `OnMonitoring()` 타이머가 `_Laser.GetPilotLaserStatus()` 를
주기 폴링하여 `IsGuidBeam` 바인딩 갱신. IPG_IO 는 파일럿 DI 핀맵이 없어 `GuideLaserEnable` DO 상태를 그대로 읽어 표시
- **주의**: `OnMonitoring()` 의 TODO 주석대로 일부 Laser 디바이스는 `GetPilotLaserStatus()` 미구현 → 항상 false.
이 경우 버튼으로 DO 는 나가도 Status 표시는 갱신되지 않을 수 있음
## 10:21 — Guide Beam DO 주소 정합 (DO 3 → DO 17) 수정 및 현장 검증 대기
### 배경 / 문제
- 현장에서 **가이드빔(적색광)이 안 나옴** → 원인 분석 결과 모니터링/제어가 보던 DO 비트가 실제 제어선과 불일치
- 기존 소스: 버튼·모니터링 모두 `_Laser` 경로로 `eADOAddress.GuideLaserEnable`(Ajin enum = **raw 3**)을 사용
- 현장 확인(도연님): 실제 **가이드빔 제어선은 DO 17(EX_Red_Control)**. **DO 3 은 PLC 인터페이스3 용**으로 가이드빔과 무관
- DI 결선 없음 → 모니터링은 **DO(명령) 신호**를 그대로 표시하는 구조
### 분석 정리
- 동작 체인: Guide Beam 버튼 → `CMD_LaserGuideBeam` → `PerformCmdLaserGuideBeam()` → (기존)`_Laser.PilotLaserOn/Off`
→ IO Laser 는 `GuideLaserEnable`(raw 3) DO Write. 모니터링은 `OnMonitoring()` 타이머가 `GetPilotLaserStatus()`(raw 3 DO read) → `IsGuidBeam`
- `CommonDeviceIds.IODevice == "IO_Board"` (`EquipDefCommon.cs:115`) → ViewModel `_IODevice` 와 IO Laser 가 쓰는 보드 **동일**(PTOP=PAIX_PTOP)
- IO 기반 Laser(IPG_IO/TruPulse_IO/Trumpf_IO/Arm_IO)는 `GetPilotLaserStatus()` 구현되어 있음(미구현은 NL202/Rapid/YLPN/TrueDisk/TrumpfCore)
- 현장 Laser 타입 = **IO 기반**
### 수정 내용 (커밋 보류 — 현장 검증 후 결정)
- 파일: `WeldingComponents/WeldingCommon/Views/Recipes/UCScannerObjectTeachingControlBoxViewModel.cs`
- `OnMonitoring()` (174~181줄): `_Laser.GetPilotLaserStatus()` → `_IODevice.ReadDO(17)` + IO 미연결 가드(미연결 시 false)
- `PerformCmdLaserGuideBeam()` (457~464줄): `_Laser.PilotLaserOn/Off` → `_IODevice` **DO 17 토글**(현재값 읽어 반전)
- 효과: 버튼이 쓰는 비트와 모니터링이 읽는 비트가 **동일 DO 17** → 버튼/직접 SetBit 어느 쪽으로 켜도 Status 동기화
- 빌드 산출물: **WeldingCommon.dll** (현장 소스 덮어쓰기 시 재빌드 후 실행 폴더 반영 필요)
### 현장 검증 체크리스트
- [x] 현장 PC 에 수정 소스 덮어쓰기 후 WeldingCommon 재빌드
- [x] `WeldingCommon.dll` 실행 폴더 반영
- [x] Guide Beam 버튼 클릭 → 화면 Guide Beam Status 점등(ON) 확인 → **실패(변경 안 됨)**
- [ ] ~~Guide Beam 버튼 재클릭 → Status 소등(OFF) 확인~~
- [x] DO 17 직접 SetBit → Status 동기화 확인 → **실패(모니터링이 DO 17 을 보는 것도 아님)**
- [x] **실제 가이드빔(적색광) 점등** 여부 확인 → **점등 안 됨**
### 현장 검증 결과 (실패 → 원복)
- **결론: DO 17 은 가이드빔 제어선이 아님.** 버튼으로 변경도 안 되고, 모니터링이 DO 17 을 보는 것도 아니었음
- 수정분(`UCScannerObjectTeachingControlBoxViewModel.cs` OnMonitoring/PerformCmdLaserGuideBeam) **`git checkout` 으로 원복** (커밋 안 한 상태였음)
- DO 3 / DO 17 모두 실제 가이드빔 제어선이 아닌 것으로 확인 → **실제 제어선 DO 주소 재확인 필요**
### TODO / 후속
- 현장 IO 인터페이스(결선)에서 **실제 가이드빔 제어 DO 주소** 재확인 (DO 3·17 아님)
- 주소 확정 후 동일 방식(버튼 write + 모니터링 read 동일 비트)으로 재시도
- 추후 실제 점등 피드백 **DI 결선** 추가되면, 명령 DO 대신 피드백 DI 로 표시하도록 전환 검토
## 11:03 — TeachingRun 인터락 알람 분석 + 알람부 종합 분석
### TeachingRun 차단 원인 (현장 로그)
- `SeqComponentTeachingRun` 시작 시 `CheckCondition_Interlock()`의 `HasAlarmLevelHigh()`가 true → "Clear Heavy Alarms For Welding!" + 알람 202003 → FORCE_ERROR
- **원인 = 현장 PLC 미연결** → SeqAlarmMonitor가 PLC Deactivated/Disconnect(H) 알람 set → latch로 남아 인터락
- 임시조치: `SeqComponentTeachingRun.cs` CheckCondition_Interlock()의 H알람 블록 **주석 처리(테스트용, 원복 예정)** → 레이저 출사 확인 완료
### 알람부 종합 분석 문서 작성
- 문서: `docs/분석/2026/06/19/110333_alarm_subsystem_analysis.md`
- 내용: 클래스 구조, 핵심 메서드(set-once/시뮬우회/Unknown=H/Clear전체일괄), 생성·전파 흐름, 시퀀스별 알람 참조표, 알람 코드 표, 리스크 6종, SeqAlarmMonitor self-clearing 개선안
- 핵심 리스크: **알람 latch(조건 해소 시 자동 Clear 없음)** → PLC 재연결돼도 수동 ClearAll 전까지 인터락 지속
### TODO / 후속
- 현장 **MX Component 연결 설정** 후 PLC 연결 → 중알람 자연 해소 여부 확인 (별도 분석 진행 중)
- 알람 인터락 블록 **원복** (현장 PLC 정상화 후)
- `SeqAlarmMonitor` self-clearing 개선 검토 (AlarmManager 공통 수정 → 승인 필요)
## 11:13 — MX Component PLC 연결 설정 분석
- 문서: `docs/분석/2026/06/19/111326_mxcomponent_plc_connection_analysis.md`
- 핵심: 연결 = **논리국번(Logical Station Number)** 1개로 결정
- PC의 **MX Component Communication Setup Utility** 에 등록한 논리국번 ↔ 소스 `_config_device/PLC.json` 의 `ConnConfig.StationNumber`(기본 1, Gun 예시 22) **일치 필요**
- 드라이버: `AuroraMXComponent/MXComponent.cs` → `ActUtlType64Class.ActLogicalStationNumber` 설정 후 Open
- PLC측 요청: CPU 기종 / 접속방식(CPU내장이더넷·이더넷모듈·CC-Link IE 등) / **IP·포트** / MELSOFT 접속 허용
- 메모리맵 CSV 8종(`External/PLC/PLC_DeviceMap_*.csv`)은 연결과 별개지만 데이터 정합 필요 — PTOP는 repo에 없음(현장 전용)
- 연결되면 PLC 미연결 중알람 해소 → 단 latch라 **ClearAll 1회** 필요할 수 있음
## 12:22 — AjinIO.ReadDoBit(int) 미구현 분석 (스텁 유지 결정)
- 파일: `AuroraDevices/AuroraIO/Vendor/AJINEXTEK/AjinIO.cs` `ReadDoBit(int index)` (496줄~)
- 현황: bool 반환 `ReadDoBit(int)`만 미구현 스텁(`return true`). DO 읽기 API(`AxdoReadOutport`)는 같은 파일 469줄·GetDoArray에서 이미 검증됨
- 스텁 의존 호출처: `UCInformationPanelViewModel.cs` 5곳(ModeKeySolOn/SafetyDoorRelease 상태표시) — **전부 ePDOAddress(PAIX) → PAIX 보드 실행, PAIX는 정상 구현** → Ajin 스텁 실제 의존 코드 사실상 없음
- **결정: 스텁(`return true`) 유지 + 구현(ReadDiBit 패턴)은 주석으로 보존** → 동작 변화 없음(현장 안전), 추후 활성화 용이
- 빌드 산출물: **AuroraIO.dll**
- 분석 문서: `docs/분석/2026/06/19/122201_ajinio_readdobit_analysis.md`
## 12:47 — 가이드빔 제어 경로 추적 (IO → Laser/TruPulse) 및 미구현 확인
### 진행 경위
- 레시피 Guide Beam 을 `_IODevice` **DO 17(EX_Red_Control)** read/write 로 수정 → 상태표시(읽기)는 동작, **물리 빔은 안 나옴**
- 번들(DBW-MC) `RedLight Opened/Closed` 이벤트는 **번들 RedClosed 버튼 수동조작** 결과, DO 17과 무관 (Mod1_IO 비트만 일치)
- → **DO 17(IO) 경로는 가이드빔 제어가 아님.** 레이저 타입 = **TruPulse**
### 핵심 발견 (TruPulse 가이드빔 미구현)
- 경로: `_Laser.PilotLaserOn()` → (TruPulse)`PilotOnOffFunc` → `ExtPilotOnOff` (레이저 IO 보드 write 의도)
- 상태: `GetPilotLaserStatus()` → `PilotLaserEnable` ← TruPulse `Di2 bit9`
- **`ExtPilotOnOff`/`ExtLaserEnable`/`ExtLaserDisable` 가 선언만 되고 할당부 없음(미구현 TODO)**
- 시뮬(현재): 베이스 no-op → 빔 안 나옴(정상) / 실모드: null → NRE 위험
- 현재 Laser 디바이스 = **시뮬레이션**, 제어는 레이저 IO 보드로 한다고 함
### 처리 / 결정
- 레시피 DO 17 변경분 **원복 안 함** — 필요 시 도연님이 주석 토글로 운용 (기존 `_Laser` 코드 주석 보존됨)
- IO 미연결 가드(`IsConnected`)는 현장PC에서 동작 안 해 주석(개발PC에서 해제) — LaserReady 패턴과 동일
- 분석 문서: `docs/분석/2026/06/19/124752_guidebeam_trupulse_analysis.md`
### 금일 작업 정리 (커밋 대상)
- 코드(미커밋): `AjinIO.cs`(ReadDoBit 스텁 유지+구현 주석), `SeqComponentTeachingRun.cs`(중알람 인터락 임시 주석), `UCScannerObjectTeachingControlBoxViewModel.cs`(Guide Beam DO 17 + 가드 주석)
- 분석 문서 4종: 알람부 / MX Component / AjinIO ReadDoBit / 가이드빔 TruPulse
- → 커밋·push (3b8799a)
## 13:57 — Recipe View 진입 크래시 수정
- 증상: 빌드 후 Recipe View 진입 시 앱 종료(`0xe0434352`, 미처리 CLR 예외), 로그에 `System.Exception(AuroraIO.dll)`
- 원인: `OnMonitoring()`의 `IsGuidBeam = _IODevice.ReadDO(17);` 가 **try/catch 밖**에 있어, IO 보드 미연결(시뮬/개발PC)에서 `_iOUnit==null` → ReadDO 예외 → DispatcherTimer 틱에서 미처리 → 앱 종료
- LaserReady(`ReadDI`)는 try 안이라 안 터졌고, Guide Beam만 try 밖이라 터짐
- 수정: `IsGuidBeam = _IODevice.ReadDO(17);` 를 **try 블록 안으로 이동** + catch 에서 `IsGuidBeam=false`
- → 가드 토글 불필요, 현장/개발 PC 모두 안전
- 함께: `AjinIO.ReadDoBit(int)` 스텁(`return true`) → `AxdoReadOutport` 실제 구현 **활성화**(도연님)
- → 커밋·push (8bfeb73)
## 14:31 — ScoutNormal moveSleepTime 100 → 150 (현장 반영)
- 파일: `WeldingComponents/WeldingCommon/Sequences/Main/SeqScoutNormal.cs:241`
- 변경: `moveSleepTime = 100;//50` → `150;//100;//50` (msec)
- 이유: **Canvas(Scan field) 영역을 넓혀서** Scout Image 이동 시 sleep을 더 줘야 **제대로(안정적으로) 촬영**됨 (스캐너 Jump 후 정착 시간 확보)
- 흐름: Scanner JumpAbs → `Thread.Sleep(moveSleepTime)` → ChildImage Grab
- 빌드 산출물: **WeldingCommon.dll**
## 15:04 — Laser Head Theta 각도 인터락 추가
### 목적
- 레이저 발진 시 헤드 각도(Theta)가 **수평/수직이 아니면 발진 차단**(인터락)
- 절대값 하드코딩 대신 **세팅값 ±허용오차** 범위에서만 발진 허용 (수평/수직 둘 다 허용)
### 변경 내용 (PTOP 로컬, 7파일)
- `Machines/ILSOS_PrismaticRD_PTOP/Settings/LaserInterlockSetting.cs` (신규) — `ISettingItem`, 세팅 메뉴에 자동 UI
- `인터락 사용`(체크박스, 기본 false) / 수평·수직 각도(deg) / 허용오차(±2.5) / PLC 스케일(deg×10, 미확정→세팅화)
- `EquipDef.cs` — `SettingIds.LaserInterlock` 키
- `EquipmentSetup.cs` — `RegisterSettings`에 세팅 등록(메뉴 노출)
- `Alarm/AlarmCode_PTOP.cs` — `ALARM_LASER_HEAD_THETA_INTERLOCK = 210620`
- `Device/PLC/PLCController.Address.cs` — `eWordInput.HEAD_THETA_POSITION`(= D70510, index 10; 기존 EMPTY_10)
- `Sequences/SeqAutoRunPTOP.cs` — `ExecuteWelding`의 Laser Gate ON 직전 인터락
- 체크박스 ON 시에만 동작 / PLC 미연결·미활성·스케일0 시 **fail-closed(차단)** / 알람 호출 try-catch / `return null`(발진 차단)
### 검증
- WeldingCommon→PTOP 빌드 통과(Debug|x64, exit 0)
- 서브에이전트 리뷰로 fail-open 등 지적 → fail-closed·스케일0 가드·알람 방어 보강
- `raw`/`deg` 로그 남겨 실기에서 deg×10 스케일 확인 가능
### 런타임 설정(별도, 사용자 영역)
- CSV: `D:\ILSOSConfig\ILSOS_PrismaticRD_PTOP\External\PLC\PLC_DeviceMap_Word_Input_D_Device.csv` index10 = D70510
- 알람표: `...\_alarm\AlarmDescriptions.xlsm` 에 Code 210620 / Level H 행 추가
- 세팅 메뉴에서 "인터락 사용" 체크 + 수평/수직 값 설정
- → 커밋·push (0e73086)
## 15:25 — Scout Image Sleep Time 사용자 설정 추가
### 목적
- ScoutNormal 이미지 스캔 시 **같은 행 이동**과 **행 전환 이동(먼 거리)** 의 sleep을 분리
- 두 값을 **Recipe View > Scout Image 그룹에서 사용자 입력**, 시퀀스가 RowIdx 기준으로 적용
### 변경 내용 (WeldingCommon, 4파일)
- `Settings/SystemParameter.cs` — `[Category("Scout")]` `ScoutSameRowSleepMs`(150) / `ScoutRowChangeSleepMs`(300)
- `Views/Recipes/UCScannerObjectTeachingControlBoxViewModel.cs` — 바인딩 프로퍼티 2개(SetProperty) + `SaveScoutSleep()`(SettingEntry.Save) + ctor 초기화
- `Views/Recipes/UCScannerObjectTeachingControlBox.xaml` — Scout Image 그룹 4→6행, Selected Type↔Run 버튼 사이 입력 2줄, 버튼 그리드 재번호(Row 3/4)
- `Sequences/Main/SeqScoutNormal.cs` `CaptureNextPosition` — `prevRowIdx` 추적해 `isRowChange ? RowChange : SameRow` 분기 (기존 `moveSleepTime=150` 대체)
### 검증
- WeldingCommon.dll 빌드 통과(XAML 포함, exit 0)
- 서브에이전트 검증 통과(로직·XAML 그리드·VM·인코딩 PASS) → 작업지시서 삭제
- 공유(WeldingCommon)라 같은행은 150(기존 동일), **행 전환 기본 300ms**(기존 150) — 타 머신도 영향, Recipe View에서 조정 가능
- → 커밋·push (e263ab8)
## 16:30 — ScoutField 페이지별 로드 버그 분석 + 작업지시서 작성 (소스 미수정)
### 분석 (레시피 데이터 + 코드)
- `_config_recipe/<레시피>/` 분석: "Selected Scout Field" 팝업 값의 실제 저장처는 **`FieldHelper.json`** (페이지 배열, 각 페이지 `FieldScans` 80셀=10×8, `Enabled`=선택 셀)
- `ScannerObjectTeaching.json`/`LaserScannerTeaching.json`/`PLCRecipe.json`/`VisionInspectionRecipe.json` 은 **전부 빈 `{}`(미사용)**
- **버그**: 페이지 이동해도 그 페이지 필드를 다시 안 불러옴 → 항상 마지막 머문 페이지(보통 Page1) 필드로 ScoutNormal 동작
- 원인: `LoadScoutField()`(MainPage.cs:499/502)가 GUI 전역 `selectedIndexNo`만 키로 사용. 이 값은 WinForms 티칭 콤보박스 `toolStripComboBoxPage_SelectedIndexChanged`(1393)에서만 갱신 → 운전(WPF)/자동운전/시퀀스 경로에선 stale
- 비대칭: 저장 `UpdateScoutField`는 라이브 `SelectedIndex`(490) 사용해 페이지별 정상 저장되나, **로드만 stale**
- `SeqScoutNormal_InitParam`(SeqScoutNormal.cs:373)엔 페이지 인덱스 필드 없음 → 시퀀스가 처리 페이지를 모름
### 작업지시서 작성 (방식 A 채택, 소스는 미수정)
- 문서: `docs/작업지시서/2026-06-19_ScoutField_페이지인덱스_시퀀스주입.md`
- **A안**: InitParam에 `PageIndex` 추가 → `MainPage.LoadScoutField(int)` 오버로드 + `GetCurrentPageIndex()`(콤보박스 라이브값, fallback ActiveLayer.No) → `SeqScoutNormal.cs:151`에서 `_InitParam.PageIndex`로 로드 → 호출부 2곳(`UCScannerObjectTeachingControlBoxViewModel.cs:251`, `UCTestSequenceViewModel.cs:361`)에서 주입
- **null 가드 확정**: `LoadScoutField(PageIndex) ?? LoadScoutField() ?? new List<>()` (인덱스 초과 시 NRE 방지, 빈 리스트면 스캔 대상 없이 정상 종료)
- B안(GUI 콤보박스 동기화)은 위험성으로 제외
- 기존 소스는 주석 처리 / 신규·변경 라인은 의도 주석 표기 형식으로 작성 (Before/After 포함)
- **상태: 도연님이 더블체크 후 git 반영 예정 → 추후 pull 받아 적용** (이번엔 소스 변경/커밋 없음)
## 주말 출근 예정
- **06.20(토)~06.21(일) 주말 출근 예정**