317 lines
26 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-18
## 09:22
### 조명 컨트롤러 연결 완료 (아침)
- 조명 컨트롤러 연결을 완료했다.
**중요 사항 정리:**
- 조명 컨트롤러는 모델의 사양(스펙) 파라미터를 알고 있어야 한다.
- 사용 중인 모델은 EROOM E-MINI CONTROLLER 인데, AURORA에서 해당 모델 타입을 제공 중이라 그대로 활용했다.
- DEVICE에서 LIGHT1 과 Light 에 대한 파라미터 세팅을 동일하게 맞춰주고, 채널도 맞춰줘야 한다.
- 통신 파라미터: 정지 비트(stop bit), 패리티 비트(parity bit), 시작 비트(start bit), Baud 값, 그리고 어떤 COM 포트에 꽂혔는지만 정확히 알면 된다.
- **막혔던 부분 (해결):** 장치 관리자에서 COM1 포트 설정은 맞췄지만, 고급 설정에 들어가면 버퍼(buffer) 체크가 되어 있는 항목이 있다. 이걸 꼭 **해제**해줘야 리모트 모드로 조명 컨트롤러에 커맨드를 날릴 수 있다.
## 09:32
### 현장 update 파일 정리
- 어제(2026-06-17) 수정한 소스 파일들을 현장 소스에 옮기기 위해 `docs/현장update파일/` 폴더를 만들어 복사해두었다.
- 포함 파일:
- `SequenceSetting.cs` — Axis Position Interlock 파라미터 4개 추가 (수직/수평 기준값·허용오차, 커밋 `9543238`)
- `UCScannerObjectTeachingControlBoxViewModel.cs` — Laser Ready 판정을 `DI(9)` → `DI(12) && DI(24)` 동시 조건으로 변경 (커밋 `9aa1b2a`)
- `README.md` — 각 파일의 원본 위치 / 변경 부분(diff) / 적용 체크리스트 정리
### 현장 PC 원격 데스크톱 접속 가능하게 변경
- 금일 현장 PC가 방화벽 때문에 원격 데스크톱이 안 됐는데, **김남오 대리님**께서 세팅하신 뒤 PC를 재부팅해서 원격 접속이 가능하도록 변경해주셨다.
## 09:36
### 현장 소스 반영(옮기기) 완료
- `docs/현장update파일/`에 정리한 변경 내용을 현장 소스에 옮기기 완료했다.
- `SequenceSetting.cs` — Axis Position Interlock 파라미터 4개 추가 반영
- `UCScannerObjectTeachingControlBoxViewModel.cs` — Laser Ready 판정 `DI(12) && DI(24)` 변경 반영
## 10:02
### SeqScoutNormal moveSleepTime 50→100ms 변경
- `SeqScoutNormal.cs`의 Scanner Jump 후 `moveSleepTime`을 50 → 100ms로 변경했다.
- **이유:** 현장 PTOP의 경우 어제 Scout 이미지가 속도 때문에 제대로 안 됐는데, 현장 PTOP 상황에서 ScoutNormal의 FOV 거리가 멀어서 캡처가 흔들리는 부분 때문에 50에서 100으로 상향함.
- 커밋 `81fdf01`로 커밋·푸시 완료.
## 10:18
### [요청] 레이저 미발진 상태로 Analog만 살려 Power Cal 파일 생성 가능 여부
- **목적:** Laser Voltage를 1V 줬을 때 실제 몇 W가 나오는지 측정하는 **캘리브레이션(Cal) 파일**을 만들고 싶다.
- **핵심 요청:** 캘 파일을 만드는 동안 **레이저는 실제로 발진(발사)시키지 않고**, **아날로그 신호만 살려서** RTC5의 기록(로그/데이터)은 그대로 저장되도록 할 수 있는가?
- **상세:**
- 레시피(또는 메뉴얼) 화면 → **Manual Laser Power Control** 영역에서 레이저를 쏠지 안 쏠지 제어함.
- 보통은 **레이저 컨트롤러 IO를 살리지 않으면** 레이저가 실제로 나가지 않는다.
- 이때 **아날로그 신호만 활성화**해서, 레이저는 안 나가되 RTC5가 출력 기록은 정상적으로 남기도록(저장되도록) 만들 수 있는지 확인 필요.
- **정리:** Laser 발진 IO는 비활성(레이저 OFF) + Analog 출력은 활성 → RTC5 기록은 정상 저장. 이 구성이 가능한지 검토 요청.
## 11:27
### PTOP 네임스페이스/클래스 마이그레이션 적용 (Scanner → PTOP) + 머신 PTOP 단독화
- 프로젝트명만 PTOP로 바꾸고 Sequence만 손봤던 상태에서, `ILSOS_PrismaticScanner` 네임스페이스/using/클래스명/파일명이 남아있던 것을 참고본(`D:\Git\LGES-OC5-PtoP-Welder_정리후(빌드완)`)과 동일하게 정리.
- 분석 문서 기준으로 진행: `docs/분석/2026/06/18/111604_ptop_namespace_migration_guide.md`
- **적용 내역:**
- 파일 7개 git mv 리네임 (AlarmCode/AlarmManager/PAIX/EquipmentSpecificModel → _PTOP, RMSHandlerForScanner→ForPTOP, SettingUploadDataListForScanner→ForPTOP, SeqAutoRunPrismaticScanner→SeqAutoRunPrismatic)
- namespace `ILSOS_PrismaticScanner` → `ILSOS_PrismaticRD_PTOP` (전 .cs/.xaml)
- using 동일 변경, 클래스명 참조 전파 (PLCControllerPrismaticScanner→PLCControllerPTOP 등)
- ⚠ **PAIX_PrismaticScanner는 머신 참조만 PAIX_PTOP로 변경, WeldingCommon 공유 참조(SeqTestRun.cs)는 보존** — 빌드 깨짐 1순위 함정 회피
- XAML 3종(x:Class/clr-namespace/code-behind) 일치, csproj Compile Include 7줄 갱신
- csproj 빌드 경로 TDC→PTOP (`_out_prismatic_rd_ptop`)
- sln에서 Scanner/Gun/CleanLaser 제거, 해당 머신 소스 폴더 삭제, 비-PTOP `_out` 아티팩트 정리 → **Machines에 PTOP만 남김** (참고본과 동일 구조)
- **주의:** 이 환경에선 실제 MSBuild 검증 불가 → VS에서 Clean→Rebuild 권장(obj 비워둠).
## 11:34
### Manual Laser Power Control — Watt 입력 GroupBox 숨김(Collapsed)
- 마이그레이션 후 빌드 정상 확인 완료.
- `UCScannerLaserControl.xaml`(WeldingCommon)의 Manual Laser Power Control 2영역(%, W) 중 **W 입력 영역은 주로 안 쓰므로** Grid.Row="1"(Watt 기준) GroupBox에 `Visibility="Collapsed"` 추가로 숨김 처리.
- Percent(%) 영역만 노출, 공간도 미차지. ViewModel/바인딩(`CMD_LaserShotOnWatt` 등)은 변경 없음.
- 관련 분석: `docs/분석/2026/06/18/102847_manual_laser_power_control_groupbox_analysis.md`
- 커밋 `ad6cf68`로 커밋·푸시 완료.
## 12:12
### NoLaser 체크 — 레이저 컨트롤러(IO BIT9/13) 안 켜고 Laser On 가능
- 발진(lasing)을 막는 실제 지점은 `LaserSignalOn`(RTC5 게이트)이 아니라 **IO Control DO9(`CoreLaser_Control`)/DO13(`RingLaser_Control`)** 를 true로 주는 부분이었음.
- 위치: `UCScannerObjectTeachingControlBoxViewModel.PerformCmdLaserReadyCheck`(Laser Control GroupBox의 `Laser Ready` 버튼).
- 처음엔 `UCScannerLaserControl`에 Analog Only(IsAnalogOnly)로 `LaserSignalOn` 가드를 넣었으나, 실제 IO는 다른 소스(ObjectTeachingControlBox)라 **그 변경은 원복**하고(Watt 숨김은 유지), 정확한 지점에 다시 구현.
- 구현: ViewModel에 `IsNoLaser` 추가(기본 false). `Laser Ready` 버튼이 DO9/13을 켜는 분기에서 `ctrlOn = !IsNoLaser`로 적용 → **IsNoLaser=true면 DO9/13을 true로 안 켜고 false 유지** → 레이저 컨트롤러 OFF 상태로 Laser On 가능(Cal/전압 측정용).
- XAML: Laser Control GroupBox에 `No Laser (전압만, 발진 안 함)` 체크박스 추가.
- 디바이스 레이어(Scanner/RTC5) 무변경, IO 비트 9/13만 제어.
- 커밋·푸시 진행.
## 12:20
### Laser Ready 판정 DI 변경 — IO 결선 변경(12&24 → 11&15)
- IO 결선을 바꿔서, 레시피의 Laser Ready 판정 입력을 `ReadDI(12) && ReadDI(24)` → **`ReadDI(11) && ReadDI(15)`** 로 수정.
- 위치: `UCScannerObjectTeachingControlBoxViewModel`의 `OnMonitoring` Laser Ready 판정부.
- 변경된 결선에 맞춘 단순 입력 번호 교체(로직 동일).
## 13:55
### RTC5 AnalogOut 전압 Readback 표시 (Laser Shot Control)
- `docs/RTC5_AnalogOut_Readback_수정가이드.md`(외부 작성 구현 명세)에 맞춰 RTC5 보드의 AnalogOut(파워 지령 전압) readback 기능 구현. 가이드 파일은 적용 후 삭제.
- **Device 계층**: `ScannerObj`에 `abstract int GetAnalogOut(uint portNo)` 추가 → `ScannerRTC5`/`ScannerRTC6`(`n_get_value(signal=portNo+32)`, AnalogOut1=33/AnalogOut2=34)/`ScannerSimul`(더미 0) override + `Scanner` 파사드(미활성 시 -1).
- **ViewModel**(`UCScannerLaserControlViewModel`): `AnalogOut1Voltage`/`AnalogOut2Voltage` 속성 + `ReadbackAnalogOut()`(raw/4095×10 [V]) 추가, Laser On 직접 분기(No Use Spot Time)의 WriteDA 직후·출사 전 호출.
- **XAML**(`UCScannerLaserControl.xaml`): Control Setting(Percent 영역)에 `DA1 Voltage`/`DA2 Voltage` [V] 읽기전용 표시 추가.
- 표시 대상은 Power Calibration(dbVoltage)이 아니라 **ScannerLaserControl 화면**으로 확정(요청). LaserSignalOn 발사 동작은 변경 없음(readback만 추가).
- AuroraDevices 변경이라 VS Rebuild로 빌드 확인 예정(abstract 추가 → override 3개 모두 구현).
- 관련 분석: `docs/분석/2026/06/18/122432_laser_on_no_emission_analysis.md`
## 14:14
### NoLaser를 Manual(ScannerLaserControl)로 이동 + Recipe NoLaser 제거
- 어제/오늘 Recipe(UCScannerObjectTeachingControlBox)에 만들었던 NoLaser는 **원래 의도가 Manual 화면**이었음 → Recipe에서 **완전 제거**(속성/InitVariable/체크박스/RowDefinition/`PerformCmdLaserReadyCheck`의 `ctrlOn` 원복하여 `WriteDoBit(9/13,true)`로 환원). **DI 11&15 변경은 유지.**
- **Manual**(`UCScannerLaserControlViewModel`): `IsNoLaser` 추가, Laser On 직접 분기(Percent/Watt 두 곳)의 `LaserSignalOn()`을 `if(!IsNoLaser)`로 가드 → 체크 시 발진 없이 전압만 인가.
- **Manual XAML**(`UCScannerLaserControl.xaml`): Use Spot Time 토글과 **같은 ToggleSwitch 디자인**의 `No Laser (전압만)` 토글 추가. Timer Set 영역 배치 = Use Spot Time → Time(체크 시만) → No Laser → DA1/DA2 Voltage 순.
- 이 NoLaser는 RTC5 발진 게이트(`LaserSignalOn`)를 막는 방식이라 **이 화면만으로 자기완결**(DO9/13 별도 화면 불필요). No Use Spot Time + No Laser + Laser On → 전압 readback 표시 + 발진 없음.
## 14:19
### DA1/DA2 Voltage 표시를 No Laser 토글에 연동(조건부 표시)
- DA1/DA2 Voltage UniformGrid에 `Visibility="{Binding IsNoLaser, Converter={StaticResource convTrueVisible}}"` 추가.
- Time이 Use Spot Time 체크 시 표시되는 것과 동일하게, **No Laser 체크(전압만) 시에만 DA1/DA2 Voltage 표시**, Laser Fire(해제) 시 숨김.
## 14:33
### IOInterfaceView DI 경로 PTOP 전환 분석 (소스 무수정)
- Monitoring IOInterfaceView의 DI 표시가 Scanner DI를 보던 원인 분석. `IODevice.MappingDIO`가 `IO_Board.json`의 `IOInterfaceMapDI`(절대경로)를 그대로 읽음(path-agnostic) → 소스 수정 불필요.
- PTOP 전환 = `D:\ILSOSConfig\ILSOS_PrismaticRD_PTOP\_config_device\IO_Board.json`의 DI/DO 경로를 PTOP로 + DI/DO.csv 존재 + DataPath 확인. (Device 설정에서 파일 위치만 지정하면 됨)
- 분석일지: `docs/분석/2026/06/18/143345_io_interface_di_path_ptop_analysis.md`
## 15:30
### PLC Recipe Change 인터페이스 구현 (SeqAutoRunPTOP) + 주소/디바이스맵 정합
- 근거: `docs/PLC_RecipeChange_구현_수정가이드.md` + Excel `유니셀 PtoP 단동기 Laser Interface_260618.xlsx`(빨간셀 M70509/M70009/D70502/D70002). 기존 Page Change 핸드셰이크를 미러링해 Recipe Change(상위 개념) 추가.
- **STEP1 주소 enum** (`Device/PLC/PLCController.Address.cs`):
- eBitInput `PLC_RMS_USED`→`PLC_RECIPE_CHANGE_REQ`(0x09), eBitOutput `PC_EMPTY01`→`PC_RECIPE_CHANGE_COMPLETE`(0x09)
- eWordInput `PLC_STEP_NO`→`PLC_RECIPE_NO`(idx2), eWordOutput `EMPTY_02`→`PC_RECIPE_NO`(idx2)
- 공용 `eCommonBitOutput`에 `PC_RECIPE_CHANGE_COMPLETE=0x09` 동기화(RestoreDeviceStatus가 common enum 사용)
- 충돌: `SeqStatusMonitor`의 RMS_USED 읽기 주석(소비처 0), `SeqAutoRunPrismatic`의 PLC_STEP_NO 참조 이름만 교체(로직 불변)
- **STEP2~4,6 시퀀스** (`Sequences/SeqAutoRunPTOP.cs`):
- `CheckRecipeNo`(Decision, 논블로킹 peek: REQ OFF면 Page로, ON이면 Comp로) + `CheckRecipeNoComp`(3회 검증→`.Id` 1:1 조회→활성화+반영 폴링→에코/완료비트, Page 미러형) 추가
- Builder: `CheckInitCondition → CheckRecipeNo → CheckRecipeNoComp → CheckPageNo`, REQ-OFF 엣지 추가, 루프백(CheckCycleStop)을 RecipeNo로 회귀
- 리셋: `RestoreDeviceStatus`/`OnSeqActionStop`에 Recipe 비트·워드 초기화
- `_RecipeManager`는 **Enter 노드에서 미리 확보**해 사용
- STEP6: 페이지 상한 하드코딩(`>2`) 제거 → `_ScannerCanvasUserCtrl.Model.Layers.Count()` 가변 검증(Recipe별 2~5페이지)
- **CSV 디바이스맵 4종**(`D:\ILSOSConfig\…PTOP\External\PLC`): M70509/M70009/D70502/D70002 라벨을 enum과 정합(`.bak260618` 백업). enum 값/인덱스 ↔ CSV 주소 ↔ Excel 빨간셀 전부 1:1 일치 확인.
- STEP5(UI Recipe 표시)는 선택이라 생략. 핸드셰이크는 기존 Page 미러형(COMPLETE 비트만) — PLC 사양 최종 정합/base 절대주소는 PLC 담당자 확인 권장.
- ⚠️ 빌드는 VS Rebuild로 검증 필요(레거시 포함). 작업 중 Excel 워킹트리본(57249)을 커밋본(46119)으로 되돌린 이슈 있었음(도연님 확인 → 문제없음).
## 15:33
### 참고 자료
- 현재 PTOP 현장 레이저 참고 메뉴얼: `Doc/메뉴얼/공통/Laser/Trumpf/OPC UA for CPX.pdf` (Trumpf, OPC UA for CPX).
## 15:56
### Manual Laser Power Control 시작 파라미터 Power 기본값 0으로 변경
- 프로그램 시작 시 Manual - Laser Power Control의 Power 파라미터 초기값 변경: **Percent 10 → 0, Watt 300 → 0**.
- 위치: `UCScannerLaserControlViewModel.InitVariable()` (`LaserPower1Percent`, `LaserPower1Watt`).
- 커밋 `5eebe96`.
## 19:44
### SeqAutoRunPTOP.cs — PLCAddress 애매모호한 참조(CS0104) 분석 (퇴근 후 작업용 / 소스 무수정·diff 프리뷰만)
> 요청: `docs/260618_18_40_이후에_확인할_소스.txt`
> ① 애매모호한 참조 ② PLCAddress error 해결 ③ 시퀀스 타이밍차트 ④ 분석/정리. **바로 수정 X, diff 프리뷰만.**
**■ 근본 원인 (한 줄): `using static` 두 개가 같은 이름의 enum 4종을 동시에 끌어와 충돌.**
- `SeqAutoRunPTOP.cs` 상단:
- L22 `using static ILSOS_PrismaticRD_PTOP.Device.PLCControllerPTOP;`
- L23 `using static WeldingCommon.Devices.PLCController;`
- 그런데 `eBitInput / eBitOutput / eWordInput / eWordOutput` **4종이 두 클래스에 똑같은 이름으로 각각 정의**되어 있음:
- `WeldingCommon.Devices.PLCController` (base) — `PLCController.Address.cs`
- `ILSOS_PrismaticRD_PTOP.Device.PLCControllerPTOP : PLCController` (파생) — `Device/PLC/PLCController.Address.cs`
- 두 정의는 **값/멤버가 완전히 동일**(260617 "PLCController.Address 통일" 커밋으로 PTOP에 복제됨).
- 결과: 코드에서 `eBitOutput.PC_AUTO_STATUS`처럼 **수식어 없이** 쓰면 컴파일러가 둘 중 무엇인지 못 정함 → **CS0104 '모호한 참조'**. 파일 내 `eBitInput/eBitOutput/eWordInput/eWordOutput`을 쓰는 **모든 줄이 동일 에러**.
**■ 헷갈리면 안 되는 점 — 같이 쓰는 다른 enum들은 충돌 아님 (그대로 둘 것)**
- `eCommonBitInput/eCommonBitOutput/eCommonWordInput/eCommonWordOutput` → **프레임워크(AuroraPLC) 공용 enum**. `using AuroraPLC;`로 들어옴. base `PLCController.Logic.cs`의 `WriteBit(eCommonBitOutput …)` 등이 이걸 받음. **`using static`와 무관 → 충돌 없음.** (`RestoreDeviceStatus`가 이걸 사용. `PC_RECIPE_CHANGE_COMPLETE`는 15:30 작업에서 공용 enum에 동기화 완료.)
- `eADOAddress` → `AjinIO.IOModuleInfo` (L21 `using static …AjinIO.IOModuleInfo;`). 충돌 없음.
- `ePrismaticDOAddress` → 이 파일 안에서 로컬 정의. 충돌 없음.
**■ 왜 `(int)` 캐스트한 줄은 멀쩡해 보였나 (중요 포인트)**
- PTOP는 자기 enum용 타입드 오버로드를 따로 가짐 — `Device/PLC/PLCController.Logic.cs`:
- `ReadBit(eBitInput)`, `ReadOutBit(eBitOutput)`, `WriteBit(eBitOutput,…)`, `ReadWord(eWordInput)`, `WriteWord(eWordOutput,…)`, `WriteDWord(eWordOutput,…)`, `ReadWords(eWordInput,eWordInput)`.
- 즉 **타입 자체는 PTOP enum이 맞는데**, `using static` 중복 탓에 *이름 해석 단계*에서 먼저 막힌다. 그래서 `(int)eBitOutput.X`(캐스트)든 `eBitOutput.X`(논캐스트)든 **둘 다 CS0104**. (캐스트 유무가 원인이 아님 — 원인은 오로지 이름 모호성.)
**■ 해결안 (가장 단순·안전) — L23 한 줄 제거**
```diff
using static AuroraIO.AJINEXTEK.AjinIO.IOModuleInfo;
using static ILSOS_PrismaticRD_PTOP.Device.PLCControllerPTOP;
- using static WeldingCommon.Devices.PLCController;
using Application = System.Windows.Application;
```
- 근거: 이 파일의 `_PLC`는 `PLCControllerPTOP` 타입이고, 4종 enum은 PTOP 정의가 base와 **값까지 동일**하므로 PTOP 쪽만 남기면 전부 정상 해석됨. `eCommon*`는 `using AuroraPLC`로 유지되므로 `RestoreDeviceStatus`도 안전.
- **부작용 점검 필요(퇴근 후 확인)**: L23를 지웠을 때 base `PLCController`의 *static 멤버/상수*를 수식어 없이 쓰는 곳이 있는지. → 현재 파일에서 base에서만 오는 비수식 심볼은 안 보임(전부 PTOP/AuroraPLC/로컬). VS Rebuild로 최종 검증.
**■ 대안 (L23를 꼭 남겨야 한다면)**
- 파일 상단에 별칭으로 못박기: `using eBitOutput = ILSOS_PrismaticRD_PTOP.Device.PLCControllerPTOP.eBitOutput;` (4종 각각). → 장황함. 1안(L23 제거) 권장.
- 더 근본책: PTOP `PLCController.Address.cs`의 **중복 enum 정의 자체를 삭제**하고 base 것을 상속해 쓰기. 단 PTOP Logic의 `ReadBit(eBitInput)` 등 오버로드 시그니처가 base enum을 받도록 바꿔야 해서 변경 범위 큼. **지금은 1안으로 끊고, 통일은 별도 과제**( [[plc-devicemap-260617-pending]] 와 함께 ).
**■ 적용 전 확인 체크리스트 (퇴근 후)**
1. L23 제거 후 VS **Rebuild** (이 파일뿐 아니라 같은 패턴 쓰는 `SeqAutoRunPrismatic.cs`, `SeqTestRun.cs`, `SeqWaitWeldOrChangePage.cs` 동반 점검).
2. `eCommon*` 사용부(`RestoreDeviceStatus`)가 그대로 빌드되는지.
3. 런타임 동작 변화 없음(이름 해석만 바뀜) — 단 빌드 통과 자체가 목적.
---
### SeqAutoRunPTOP 시퀀스 타이밍 차트 (1 사이클)
플로우(Builder): `Enter → CheckInitCondition → CheckRecipeNo →(REQ ON) CheckRecipeNoComp / (REQ OFF) ─┐ → CheckPageNo → CheckPageNoComp → SetUploadWeldingList → [Sub]UploadWeldingList → GetResult → WeldingStartReadBit → WaitWeldingStart → ExecuteWelding → CheckCycleStop →(loop) CheckRecipeNo`
저장 경로: `… → SaveResultData → WriteCompletionPLCBit → Complete → (다시 Enter)`
```
PC(=우리) PLC 설명
│ ◀── RECIPE_CHANGE_REQ(0x09) ── [CheckRecipeNo] 논블로킹 1회 peek
│ OFF → 현 Recipe 유지하고 PageNo로 점프
│ (REQ ON 시에만 아래 Comp 진입)
│ read PLC_RECIPE_NO(D, idx2) ×3 [CheckRecipeNoComp] 200ms×3 검증
│ ActivateRecipe + 반영 폴링(10ms) .Id 1:1 조회 후 활성, 일치까지 대기
│ ── PC_RECIPE_NO 에코 ──▶
│ ── PC_RECIPE_CHANGE_COMPLETE=false ─▶ (Page 미러형: COMPLETE 비트만)
│
│ ◀── PAGE_CHANGE_REQ(0x08) ON 대기 ── [CheckPageNo] ON까지 무한대기(10ms 폴링, 60s마다 로그)
│ read PLC_PAGE_NO ×3 (200ms) [CheckPageNoComp] 3회 검증
│ 페이지 상한 = Layers.Count()로 가변검증 (1..N, 범위밖이면 return null)
│ CellId/LotId read, _CurrentPageNo=Page-1
│ ── PC_PAGE_NO 에코 ──▶
│ ── PC_PAGE_CHANGE_COMPLETE=false ─▶
│ EVENT_AUTO_RUN_UPDATE_PAGENUM 발행
│
│ [SetUploadWeldingList] _CurrentPageNo로 Layer 선택 → 용접리스트 파라미터
│ [Sub:UploadWeldingList] 스캐너 리스트 업로드
│ [GetResult] Success=false면 return null(중단)
│
│ ◀── WELD_READY_REQ(0x10) ON 대기 ── [WeldingStartReadBit] ON까지 무한대기
│ ── (page1) PC_WELD_READY_ACK=1, BUSY=1 ─▶ [WaitWeldingStart] 200ms 후 COMPLETE=0
│ ── (page2) PC_WELD_P_READY_REQ=1, P_BUSY=1 ─▶ 〃 P_COMP_ACK=0
│
│ ┌───────────── [ExecuteWelding] ─────────────
│ IO DO9(Core)=1, DO13(Ring)=1 (Laser Gate ON)
│ ── Gate ON Delay 15ms (매뉴얼 ≥10ms) ──
│ Scanner.ExecuteList(LIST1)
│ Scanner.WaitForListTaskCompleted(1000ms)
│ IO DO9=0, DO13=0 (Laser Gate OFF, 완료 즉시)
│ JumpAbs(0,0) + SelectCorrectionTable(1) 원복
│ ── (page1) READY_ACK=0 → BUSY=0 → COMPLETE=1 (각 5ms) ─▶
│ ── (page2) P_READY_REQ=0 → P_BUSY=0 → P_COMP_ACK=1 ─▶
│ └─ TactTime 로그(예: ~285ms)
│
│ [CheckCycleStop] → 항상 CheckRecipeNo로 루프백 (정지조건 미구현 TODO)
│ ※ 정상 종료 경로(Save→WriteCompletionPLCBit→Complete)는
│ 현재 CheckCycleStop이 무조건 루프백이라 도달 안 함 — 흐름 확인 필요.
```
**타이밍차트에서 같이 눈에 띈 것 (참고, 이번 에러와 별개):**
- `WaitWeldingStart`/`ExecuteWelding`의 page 분기 비트 네이밍이 음/양극에서 엇갈려 보임(`PC_WELD_P_READY_REQ`를 ACK 의미로 ON). PLC 사양과 1:1 재확인 권장.
- `CheckCycleStop`이 무조건 `SEQ_CHECK_RECIPENO` 반환 → `SaveResultData~Complete` 정상경로 미도달. 의도된 건지 확인 필요(카운트 업데이트/결과저장이 안 탈 수 있음).
- 위 2건은 **이번 PLCAddress 에러와 무관** — 별도 검토 항목으로만 메모.
### [적용] L23 제거 + 빌드 검증
- **적용함**: `SeqAutoRunPTOP.cs`에서 `using static WeldingCommon.Devices.PLCController;`(L23) 제거. (1안 그대로)
- 빌드 검증(MSBuild CLI, x64-Debug):
- **PTOP standalone 빌드 → CoreCompile 통과** (CS0104 사라짐, post-build `xcopy`만 `SolutionDir`=`*Undefined*`로 실패 — 산출물은 생성됨). ⇒ `SeqAutoRunPTOP.cs` 정상 컴파일 확인.
- SolutionDir 지정 2차 빌드에서 **WeldingCommon `_wpftmp`(WPF 임시컴파일) 패스가 `eCommonBitInput/Output/WordInput/WordOutput`을 CS0246**으로 못 찾음 → 이 enum들은 레포 소스에 정의 없음(External/Aurora 프레임워크 어셈블리 타입). **내 수정과 무관**(WeldingCommon은 PTOP 파일 미참조), CLI 환경/참조 이슈로 판단.
- **최종 검증은 VS Rebuild 권장**(Aurora 바이너리가 `_out\x64-Debug`에 정상 배치된 상태). 동일 패턴 파일(`SeqAutoRunPrismatic.cs` 등)은 이번에 미수정 — 추후 동반 점검.
### [정정·최종] 진짜 근본 원인 = HEAD 커밋 `89e9a02 "PLCController.Address 통일"`의 미완성 리네임
- 앞서 CS0246(`eCommon*` 없음)을 "CLI 환경 이슈"로 본 것은 **오판**. VS에서도 동일 에러. 추적 결과 **커밋 `89e9a02`가 base `WeldingCommon/…/PLCController.Address.cs`의 enum 선언만 리네임**한 게 원인:
- `eCommonBitInput→eBitInput`, `eCommonBitOutput→eBitOutput`, `eCommonWordInput→eWordInput`, `eCommonWordOutput→eWordOutput`
- **소비처(~10파일·60+곳)는 여전히 `eCommon*`** (base `PLCController.Logic.cs`의 타입드 API, `SeqExecutePlcBitInterface`, `RMSHandler`, `AlarmManager`, `AlarmMonitoring`, PTOP `SeqTestRun/SeqWaitWeldOrChangePage/SeqAutoRunPrismatic/SeqAutoRunPTOP`) → 전부 CS0246.
- 덤으로, base가 `eBitOutput`을 갖게 되며 PTOP `eBitOutput`과 `using static` 2개에서 충돌 → 처음 보고된 **CS0104**까지 이 커밋이 유발. (도연님 메모: PTOP와 통일하려 복붙하다 base 표기까지 덮인 것.)
- **해결(채택: 커밋 되돌리기)**:
- `git checkout 89e9a02^ -- WeldingComponents/WeldingCommon/Devices/PLC/PLCController.Address.cs` (base를 `eCommon*`로 원복, 워킹트리만)
- `SeqAutoRunPTOP.cs` **L23 `using static WeldingCommon.Devices.PLCController;` 복구**(=내 임시수정 원복). `RestoreDeviceStatus`의 `eCommonBitOutput`이 이걸 통해 해석됨.
- 구조 환원: **base=`eCommon*`, PTOP=`eBit*/eWord*`** (이름이 달라 `using static` 2개 공존해도 충돌 없음).
- **빌드 검증**: `ILSOS_PrismaticRD_PTOP.csproj` (Debug|x64, SolutionDir 지정) **MSBuild EXITCODE=0, error 0건**. WeldingCommon 포함 정상 컴파일 확인.
- 변경 파일: `PLCController.Address.cs`(원복) 1개뿐. `SeqAutoRunPTOP.cs`는 HEAD와 동일(diff 없음). **미커밋** — 도연님 커밋 권장.
- 후속: "Address 통일"을 정말 하려면 base 리네임 + 소비처 60+곳 일괄 교체 + PTOP 중복 enum 정리까지 **한 번에** 가야 함(별도 과제). 지금은 되돌려 빌드 정상화 우선.
## 20:33
### 오늘 작업 마무리
- 퇴근 후 작업으로 시작했던 SeqAutoRunPTOP.cs PLCAddress 에러건 + 현장 PC IO null 에러건 둘 다 정리하고 커밋/푸시까지 완료.
- **빌드 깨짐 근본 원인**: 직전 커밋 `89e9a02 "PLCController.Address 통일"`이 base(WeldingCommon)의 `eCommon*` enum 선언만 `eBit*/eWord*`로 리네임하면서, 소비처 60+곳이 CS0246으로 깨지고 PTOP enum과 충돌(CS0104)까지 났던 것. (PTOP랑 통일하려 복붙하다 base 표기까지 덮인 게 원인) → base를 `eCommon*`로 원복해 정상화.
- **현장 PC 런타임 꺼짐**: 시뮬 모드가 아니고 IO보드가 없으면 `IODevice._iOUnit`이 null → 레시피 메뉴 진입 시 `OnMonitoring`의 ReadDI(11/15)에서 NRE. `IsConnected()` 가드로 미연결이면 폴링 스킵하게 처리 → 안 꺼지는 것 확인 완료. (토스트 알림은 안 넣기로, 시뮬 체크는 직접 하기로)
- `field/ptop-1st`에 **3개 커밋 푸시 완료** (PR은 안 만듦):
- `95ef7b9` fix: PLCController.Address eCommon* enum 원복 (빌드 정상화)
- `a312e4e` fix: 레시피 화면 IO 미연결 시 null 가드 (OnMonitoring)
- `0ca485e` docs: 작업일지
- 워킹트리 잔여물(`AuroraPLC_*_wpftmp.csproj` 빌드 임시파일, `260618_18_40_이후에_확인할_소스.txt` 메모)은 커밋 제외, 필요 시 정리 예정.
- 빌드 검증: WeldingCommon 컴파일만(`/t:Compile`) EXITCODE=0, CS 에러 0건. (전체 빌드 시 뜨던 MSB3021/3027은 실행 중인 Aurora.exe의 DLL 복사 잠금일 뿐, 컴파일 에러 아님)