LGES-OC5-PtoP-Welder/docs/PLC_RecipeChange_구현_수정가이드.md
NohDoyeon241104 42c5565249 feat: PLC Recipe Change 핸드셰이크 구현 (SeqAutoRunPTOP) + 주소 정합
근거: 가이드 + Excel 260618(빨간셀 M70509/M70009/D70502/D70002). Page Change 미러링.
- 주소 enum: PLC_RECIPE_CHANGE_REQ(0x09)/PC_RECIPE_CHANGE_COMPLETE(0x09)/
  PLC_RECIPE_NO(idx2)/PC_RECIPE_NO(idx2). 공용 eCommonBitOutput 동기화.
  충돌: SeqStatusMonitor RMS_USED 읽기 주석, SeqAutoRunPrismatic 참조 이름만 교체.
- 시퀀스: CheckRecipeNo(논블로킹 Decision) + CheckRecipeNoComp(.Id 1:1 조회/활성화/
  반영폴링/에코·완료비트), Builder 흐름·엣지·루프백, 리셋 비트·워드, _RecipeManager Enter 확보.
- Page 검증 상한 하드코딩 제거 → 활성 Recipe Layers.Count() 가변.
- (별도) D:\ILSOSConfig\...\External\PLC CSV 디바이스맵 4종 라벨 정합(.bak260618 백업).

빌드는 VS Rebuild로 검증 필요(레거시 포함). STEP5 UI/PLC 사양 최종정합은 후속.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 15:31:43 +09:00

19 KiB
Raw Blame History

PLC Recipe Change 인터페이스 구현 — 수정 가이드

작성일: 2026-06-18 대상 시퀀스: ILSOS_PrismaticRD_PTOP / SeqAutoRunPTOP (현재 활성 AutoRun) 근거 문서: Doc/유니셀 PtoP 단동기 Laser Interface_260618.xlsx (시트 M70K, D70K, Recipe Number) 이 문서는 다른 agent가 읽고 직접 구현하기 위한 구현 명세서다. 분석은 끝났고, 아래 절차대로 코드를 추가하면 된다. 기존 Page Change 핸드셰이크를 그대로 본떠서 Recipe Change 핸드셰이크를 추가하는 것이 목표다.


1. 목표

PLC가 Recipe 변경을 요청하면, PC(Laser SW)가 해당 Recipe를 활성화하고 완료를 응답하는 비트/워드 핸드셰이크를 추가한다. 구조는 기존 Page Change와 동일하며, Recipe가 상위 개념, Page가 하위 개념이다 (Recipe 1개 = Page 여러 개).

핵심 원칙:

  • 신규 코드는 기존 Page Change 노드(CheckPageNo / CheckPageNoComp)를 미러링한다.
  • 런타임 실행 시퀀스는 SeqAutoRunPTOP 하나뿐이다 (시작 근거: UCMainAutoRunViewModel.cs:243, 등록 EquipmentSetup.cs:214).
  • ⚠️ 단, SeqAutoRunPrismatic는 빌드 대상이다: EquipmentSetup.cs:202에서 .Builder()가 호출되고 :207에서 SequenceIds.SeqAutoRun으로 등록되어 있다(다만 .Start()는 호출 안 됨 → 런타임 미실행). SeqAutoRunComponentWeld도 :203에서 빌드된다. 즉 "미사용=미실행"이지 "미컴파일"이 아니다. enum rename(충돌 ②) 시 이들이 깨질 수 있으니 STEP 1·3절을 반드시 확인.

2. 인터페이스 사양 (Excel 260618 기준)

출처/변경 표기: 엑셀에는 변경이력 시트·셀 코멘트가 없고, 이번 개정의 신규 주소는 빨간 글씨(font FFFF0000) 로만 표시돼 있다. 워크북 전체 빨간 셀은 5개: Recipe_CHGRequest(M70509), Recipe_CHGComplete(M70009), PLC_RecipeNo(D70502), PC_Recipe No(D70002) — 본 문서가 다루는 4개 — 과 별개 1개 Head_Theta_Position(D70510, Recipe 무관, 본 문서 범위 외). 즉 아래 표의 "신규" 항목은 모두 엑셀 빨간 글씨 근거.

2-1. 비트 핸드셰이크 — Page 대비 오프셋 +1

신호 방향 M-Device enum / 오프셋 비고
Page_CHGRequest (기존) PLC→PC (Input) M70508 eBitInput.PLC_PAGE_CHANGE_REQ = 0x08 참고용
Recipe_CHGRequest (신규) PLC→PC (Input) M70509 0x09 ⚠️ 충돌: 현재 PLC_RMS_USED = 0x09
Page_CHGComplete (기존) PC→PLC (Output) M70008 eBitOutput.PC_PAGE_CHANGE_COMPLETE = 0x08 참고용
Recipe_CHGComplete (신규) PC→PLC (Output) M70009 0x09 현재 PC_EMPTY01 = 0x09 (미사용, 안전)

2-2. 워드 — Page 대비 인덱스 +1

신호 방향 D-Device enum index 비고
PLC_PageNo (기존) PLC→PC (Input) D70501 eWordInput.PLC_PAGE_NO = 1 참고용
PLC_RecipeNo (신규) PLC→PC (Input) D70502 index 2 ⚠️ 충돌: 현재 PLC_STEP_NO(index 2)
PC_PageNo (기존) PC→PLC (Output) D70001 eWordOutput.PC_PAGE_NO = 1 참고용
PC_RecipeNo (신규) PC→PLC (Output) D70002 index 2 현재 EMPTY_02(index 2) (미사용, 안전)

주소 베이스: eBitInput=M70500, eBitOutput=M70000, eWordInput=D70500, eWordOutput=D70000. (⚠️ 베이스 절대주소 자체는 enum 코드가 아니라 외부 device-map/mmap 설정에서 온다 → 본 표의 오프셋 산술은 Excel·디바이스맵 기준이며 코드만으로는 베이스 검증 불가.) 정의 위치: Machines/ILSOS_PrismaticRD_PTOP/Device/PLC/PLCController.Address.cs (eBitInput L13–47, eBitOutput L49–78, eWordInput L80–146, eWordOutput L148–214)

2-3. Recipe Number ↔ Page 매핑 (Recipe Number 시트)

Recipe No Page 수 용접부
11 1, 2 양극 탭 비드 용접 / 음극 탭 비드 용접
21 1 ~ 5 전면 용접
22 1 ~ 5 후면 용접
31 1, 2 상면 용접
32 1, 2 하면 용접

중요: Recipe No는 11/21/22/31/32 로 불연속이며, Recipe마다 Page 수가 2~5개로 다르다(파일 갱신으로 21/22가 4→5페이지). 특정 상한을 절대 하드코딩하지 말 것. 따라서 기존 CheckPageNoComp의 하드코딩 검증 plcPageNo > 2 || plcPageNo < 1(SeqAutoRunPTOP.cs:370)은 Recipe별 Page 수에 따라 가변으로 바꿔야 한다. (STEP 6 참고)


3. ⚠️ 주소 충돌 — 구현 전 반드시 확인할 것

충돌 ① PLC_RMS_USED = 0x09 (eBitInput) — 현재 사용 중

  • 사용처: Sequences/Monitoring/SeqStatusMonitor.cs:106
    Status.RMSUse = _plc.ReadBit(PLCControllerPTOP.eBitInput.PLC_RMS_USED).data;
    
  • Excel 260618은 M70509(=0x09)를 Recipe_CHGRequest로 재정의함.
  • 즉 동일 비트(0x09)가 RMS_USED 상태와 Recipe 변경 요청으로 충돌한다.
  • 결정 필요(PLC 담당자 확인): RMS_USED 비트를 폐기/이설하고 0x09를 Recipe_CHGRequest로 넘길 것인지. → 4절 "미해결 질문" 참조.

충돌 ② PLC_STEP_NO (eWordInput index 2) — 레거시에서 컴파일됨

  • 사용처: Sequences/SeqAutoRunPrismatic.cs:414
  • 활성 SeqAutoRunPTOP는 PLC_STEP_NO를 쓰지 않으나, SeqAutoRunPrismatic는 등록·빌드 대상(EquipmentSetup.cs:202,207)이다.
  • ⚠️ 빌드 영향: PLC_STEP_NO → PLC_RECIPE_NO로 이름만 바꾸면 :414가 컴파일 에러가 난다.
  • 결정 필요(택1):
    • (a) :414도 같이 정리(레거시 수정 허용 시) — 6절 "레거시 미수정" 원칙과 충돌하므로 사용자 승인 필요, 또는
    • (b) PLC_STEP_NO(index 2)는 그대로 두고, Recipe용으로 별도 신규 멤버를 추가(단, eWordInput은 암묵 순번이라 index 2를 두 이름이 가질 수 없음 → 명시값 부여 PLC_RECIPE_NO = 2로 두되 PLC_STEP_NO도 = 2로 명시해 공존시키거나, PLC_STEP_NO를 의미상 PLC_RECIPE_NO로 rename + :414 동시 수정). → 결국 index 2 한 칸을 누가 쓰느냐의 문제이므로 (a) rename + :414 동시 수정이 가장 깔끔. STEP 1에서 확정.

안전 (그대로 rename 가능)

  • PC_EMPTY01 = 0x09 (eBitOutput): 참조 없음 → PC_RECIPE_CHANGE_COMPLETE로 교체 안전.
  • EMPTY_02 (eWordOutput index 2): 참조 없음 → PC_RECIPE_NO로 교체 안전.

⚠️ enum 이중 정의 (Recipe 완료 비트 구현에 직접 영향)

  • PC_PAGE_CHANGE_COMPLETE는 두 곳에 0x08로 중복 정의되어 있고 코드가 혼용한다:
    • PTOP: Device/PLC/PLCController.Address.cs eBitOutput.PC_PAGE_CHANGE_COMPLETE = 0x08
    • 공용: WeldingComponents/WeldingCommon/Devices/PLC/PLCController.Address.cs eCommonBitOutput.PC_PAGE_CHANGE_COMPLETE = 0x08
  • 사용처가 갈린다: RestoreDeviceStatus(SeqAutoRunPTOP.cs:803)는 eCommonBitOutput, OnSeqActionStop(:977)은 eBitOutput 사용.
  • 즉 신규 PC_RECIPE_CHANGE_COMPLETE를 PTOP eBitOutput에만 추가하면 RestoreDeviceStatus(common 경로)에서 못 쓴다. → STEP 1에서 양쪽 enum 동기화 또는 캐스팅 통일 필요(STEP 4 참조).

4. 확정된 설계 결정 (2026-06-18, 사용자 협의)

# 결정 사항 채택안 비고
1 시퀀스 흐름/배치 매 사이클 Page 앞에서 확인 CheckInitCondition → CheckRecipeNo → CheckRecipeNoComp → CheckPageNo …. 루프백(CheckCycleStop)은 CheckRecipeNo로 회귀.
2 CheckRecipeNo 동작 논블로킹 peek Page와 달리 REQ ON까지 무한대기 ❌. REQ OFF면 현 Recipe 유지하고 즉시 Page로 통과.
3 핸드셰이크 형태 기존 Page 미러형(B) CheckPageNoComp 방식 그대로. COMPLETE 비트만 처리, REQ-OFF 대기 없음(일관성 우선).
4 RecipeNo→레시피 매핑 .Id 직접 1:1 Recipes().FirstOrDefault(x => x.Id == plcRecipeNo) → 없으면 알람 → ActivateRecipe(recipe.Id, "PLC Recipe Change"). 선례: RMSHandlerForPTOP.cs:125-173.
5 비트 0x09 충돌(①) RMS_USED 폐기 → Recipe 전환 PLC_RMS_USED→PLC_RECIPE_CHANGE_REQ. SeqStatusMonitor.cs:106 RMSUse 읽기 제거/주석. RMS 핸들러 이미 비활성(EquipmentSetup.cs:92-94)이라 기능 영향 없음.
6 Page 수 가변(2~5) 런타임 동적 산출 상한 하드코딩 금지. Models.Layers.Count() 또는 활성 Recipe 메타 기준(STEP 6).
7 워드 idx 2 충돌(②) rename + 레거시 :414 동시 수정 PLC_STEP_NO→PLC_RECIPE_NO rename, SeqAutoRunPrismatic.cs:414의 참조도 이름만 교체(로직 불변). 사용자 승인 완료.

사양 전제 (PLC 담당자와 정합성 확인 권장, 코드 결정 아님)

  • PLC가 보내는 RecipeNo가 실제 등록 레시피의 .Id(11/21/22/31/32)와 일치한다는 전제. 불일치 시 결정 4를 매핑 테이블로 보강.

⚠️ 참고 — 기존 활성 Page Change 핸드셰이크는 미완결이다. CheckPageNoComp(SeqAutoRunPTOP.cs:408)는 PC_PAGE_CHANGE_COMPLETE를 false로만 쓴다. 결정 3(미러형)에 따라 Recipe도 이 방식을 그대로 본뜬다(향후 Page 핸드셰이크가 보정되면 Recipe도 동일하게 따라간다).


5. 수정 절차

STEP 1 — 주소 enum 추가

파일: Machines/ILSOS_PrismaticRD_PTOP/Device/PLC/PLCController.Address.cs

  • eBitInput: PLC_RMS_USED = 0x09 → PLC_RECIPE_CHANGE_REQ = 0x09 로 rename (결정 5). 동시에 SeqStatusMonitor.cs:106의 Status.RMSUse = _plc.ReadBit(...PLC_RMS_USED) 줄을 제거 또는 주석 처리(Status.RMSUse는 write-only·소비처 0건이라 안전).
    • ⚠️ 공용 WeldingCommon/Devices/PLC/PLCController.Address.cs의 eCommonBitInput.PLC_RMS_USED = 0x09는 별도 enum이며 참조 0건 → 빌드 영향 없음. 이름 일관성을 원하면 동반 rename(선택).
  • eBitOutput: PC_EMPTY01 = 0x09 → PC_RECIPE_CHANGE_COMPLETE = 0x09 로 교체.
  • eWordInput: index 2(충돌 ②, 결정 7) PLC_STEP_NO → PLC_RECIPE_NO rename + SeqAutoRunPrismatic.cs:414의 참조도 이름만 교체(로직 불변, 승인 완료).
  • eWordOutput: EMPTY_02 → PC_RECIPE_NO 로 교체.
  • 공용 enum 동기화(필수): 위 PTOP enum과 동일하게 WeldingCommon/Devices/PLC/PLCController.Address.cs의 eCommonBitOutput 0x09 자리에도 PC_RECIPE_CHANGE_COMPLETE = 0x09를 추가한다. (STEP 4의 RestoreDeviceStatus가 eCommonBitOutput을 쓰기 때문.) — §3 "enum 이중 정의" 참조.

enum은 암묵적 순번(eWordInput/eWordOutput)이라 멤버 이름만 바꾸면 인덱스는 유지된다. 새 값을 끼워 넣어 뒤 순번이 밀리지 않도록 이름 교체 방식으로 처리할 것. ⚠️ index 2는 한 칸뿐이라 PLC_STEP_NO와 PLC_RECIPE_NO가 공존할 수 없다 → rename 단일화가 원칙(충돌 ② 참조).

STEP 2 — Recipe Change 시퀀스 노드 추가

파일: Machines/ILSOS_PrismaticRD_PTOP/Sequences/SeqAutoRunPTOP.cs

기존 CheckPageNo(L277) / CheckPageNoComp(L331)를 본떠 CheckRecipeNo / CheckRecipeNoComp 추가. (결정 1~5 반영)

  • CheckRecipeNo (논블로킹 peek — 결정 2): _PLC.ReadBit(eBitInput.PLC_RECIPE_CHANGE_REQ)를 1회 확인.
    • REQ OFF → Recipe 변경 없음. 즉시 CheckPageNo로 통과(현 Recipe 유지). ⚠️ CheckPageNo처럼 ON까지 무한대기하지 말 것.
    • REQ ON → CheckRecipeNoComp로 진행.
    • 분기는 Decision 노드로 구현(결정 2 확정) — STEP 3 참고.
  • CheckRecipeNoComp:
    1. _PLC.ReadWord(eWordInput.PLC_RECIPE_NO) 읽기 (필요 시 CheckPageNoComp의 3회 적재 패턴 재사용).
    2. 레시피 조회/매핑 (결정 4 — .Id 직접 1:1):
      var recipe = AuroraEnv.RecipeManager /* 또는 _recipeEntry */
                   .Recipes().FirstOrDefault(x => x.Id == plcRecipeNo);
      if (recipe == null) { /* "{plcRecipeNo}번 레시피 없음" 알람 */ return null; }
      
      • 선례 그대로: RMSHandlerForPTOP.cs:125-130(조회/없음 알람), :173(활성화).
    3. Recipe 활성화: RecipeManager.ActivateRecipe(recipe.Id, "PLC Recipe Change")
      • 현재값 조회: RecipeManager.ActivatedRecipe().Id.
      • ⚠️ 반영 확인 필수(비동기 race 주의): ActivateRecipe는 EVENT_CHANGE_RECIPE_INFO 이벤트 체인으로 반영되며, RMS 선례(RMSHandlerForPTOP.cs:134,145)는 Dispatcher.Invoke로 UI스레드에서 Reload/Save한다. 본 시퀀스는 워커 스레드이므로, 활성화 직후 ActivatedRecipe().Id == recipe.Id 가 될 때까지 폴링/대기한 뒤 다음(PageNo)으로 진행할 것. 누락 시 직후 Page 검증이 이전 레시피 기준으로 돌 위험.
    4. _PLC.WriteWord(eWordOutput.PC_RECIPE_NO, plcRecipeNo) 에코.
    5. 핸드셰이크 응답 (결정 3 — 기존 Page 미러형): CheckPageNoComp(:401-409)의 COMPLETE 비트 처리 방식을 그대로 본떠 PC_RECIPE_CHANGE_COMPLETE 처리. REQ-OFF 대기 단계는 두지 않는다(현 Page와 동일).
    6. (선택) UI 알림: EVENT_AUTO_RUN_UPDATE_PAGENUM 패턴 본떠 Recipe 표시 이벤트 publish (STEP 5).

STEP 3 — 상태머신에 노드 연결

같은 파일 Builder() (L114–171). 현재 흐름(L142–163):

ENTER → CheckInitCondition → CheckPageNo → CheckPageNoComp → (UploadWeldingList) → ... → CheckCycleStop ─(loop)→ CheckPageNo

Recipe는 Page의 상위이므로 CheckPageNo 앞에 삽입 (결정 1):

... CheckInitCondition → CheckRecipeNo → CheckRecipeNoComp → CheckPageNo → CheckPageNoComp → ...
  • sb.AddAction(SEQ_CHECK_RECIPENO, CheckRecipeNo);
  • sb.AddAction(SEQ_CHECK_RECIPENO_COMPLETE, CheckRecipeNoComp);
  • 본 흐름(Builder() L142-161)에 두 노드를 CheckInitCondition과 CheckPageNo 사이에 끼움.
  • 분기(결정 2 논블로킹): CheckRecipeNo를 **Decision 노드(sb.AddDecision)**로 만들어 REQ ON → SEQ_CHECK_RECIPENO_COMPLETE, REQ OFF → SEQ_CHECK_PAGENO 문자열을 반환 분기(Decision은 다음 노드 id 문자열을 반환 — CheckInitCondition :259,269,273 패턴).
    • ⚠️ 엣지 선언 필수: Decision의 반환 타깃이 유효하려면 두 분기 엣지가 그래프에 모두 존재해야 한다. 메인 Flows에 ON 경로(CheckRecipeNo > CheckRecipeNoComp > CheckPageNo)를 넣고, OFF 경로는 별도로 sb.Flows(sb[SEQ_CHECK_RECIPENO] > sb[SEQ_CHECK_PAGENO]); 를 추가 선언할 것(선례: CheckCycleStop의 대체 분기 :163, CheckInitCondition의 :164).
  • 루프백 변경: 현재 sb.Flows(sb[SEQ_CHECK_CYCLE_STOP] > sb[SEQ_CHECK_PAGENO]);(L163)을 > sb[SEQ_CHECK_RECIPENO] 로 바꿔, 다음 사이클마다 Recipe부터 재확인.

STEP 4 — 리셋/정지 시 비트 초기화

같은 파일:

  • RestoreDeviceStatus() (L799~803): 이 메서드는 eCommonBitOutput 을 쓴다(:803). 따라서 eCommonBitOutput.PC_RECIPE_CHANGE_COMPLETE false 를 추가 — STEP 1에서 공용 enum에 멤버를 추가했어야 컴파일된다. (안 했으면 여기서 빌드 에러)
  • OnSeqActionStop 계열(L977 비트, L981-982 워드, PC_PAGE 초기화 지점): 이쪽은 eBitOutput/eWordOutput(PTOP) 사용. PC_RECIPE_CHANGE_COMPLETE false, PC_RECIPE_NO 0 추가.
  • ⚠️ 두 지점이 서로 다른 enum(common vs ptop)을 쓰므로, 사용하는 enum을 지점별로 맞출 것(혼동 시 컴파일 에러).

STEP 5 — (선택) UI 표시

Recipe 번호를 UI에 노출하려면 Views/Main/UCMainAutoRunViewModel.cs의 CurrentPageNum(L71-72) 패턴을 본떠 CurrentRecipeNo 속성 + 이벤트 구독 추가.

STEP 6 — Page 검증 Recipe-aware 화

CheckPageNoComp의 페이지 범위 검증 plcPageNo > 2 || plcPageNo < 1(SeqAutoRunPTOP.cs:370)을 활성 Recipe의 Page 수(질문 5)에 따른 상한으로 교체.

  • ⚠️ 이 검증은 3회 폴링 게이트 if (checknum > 2)(:368) 안에 있다. 상한만 바꾸고 checknum > 2 누적 폴링 구조(plcPageNoList 3회 적재)는 그대로 유지할 것.
  • Page 수 출처 후보: 활성 Recipe 메타, 또는 Models.Layers.Count()(레이어 수). Recipe 21/22는 5페이지, 11/31/32는 2페이지(2-3절 표) — 상한 하드코딩 금지, 런타임 동적 산출.

6. 변경 대상 파일 요약

파일 변경
ILSOS_PrismaticRD_PTOP/Device/PLC/PLCController.Address.cs PTOP enum 4종에 Recipe 신호 추가/교체 (STEP 1)
WeldingCommon/Devices/PLC/PLCController.Address.cs eCommonBitOutput에 PC_RECIPE_CHANGE_COMPLETE=0x09 동기화 (STEP 1·4)
Sequences/SeqAutoRunPTOP.cs 노드 2개 추가, Builder 흐름, 리셋, Page 검증 (STEP 2·3·4·6)
Views/Main/UCMainAutoRunViewModel.cs (선택) Recipe 표시 (STEP 5)
Sequences/Monitoring/SeqStatusMonitor.cs 충돌 ① 처리 시 RMS_USED 참조 정리
Sequences/SeqAutoRunPrismatic.cs 충돌 ②(결정 7): :414 PLC_STEP_NO → PLC_RECIPE_NO 이름만 교체 (로직 불변, 승인 완료)

런타임 미실행이지만 빌드 대상인 레거시(SeqAutoRunPrismatic.cs, SeqAutoRunComponentWeld.cs)는 enum rename 영향이 미친다 — 컴파일 통과를 위해 필요한 최소 수정만 하되, 로직 변경은 하지 말 것. 완전 미참여 파일(SeqWaitWeldOrChangePage.cs, SeqTestRun.cs)은 참고만 하고 수정하지 않는다.


7. 검증 체크리스트

  • STEP 1 enum 인덱스가 밀리지 않았는가 (이름 교체 방식 확인).
  • 충돌 ①(RMS_USED) / 충돌 ②(STEP_NO) 처리 방침이 확정·반영되었는가.
  • recipeNo 유효값 {11,21,22,31,32} 외 입력 시 알람/중단 처리.
  • ActivateRecipe 호출 후 실제 레시피가 바뀌고 ActivatedRecipe().Id가 일치하는가.
  • 핸드셰이크: REQ ON → (work) → COMPLETE 응답 → REQ OFF → COMPLETE 해제 순서가 PLC 사양과 맞는가.
  • 정지/리셋 시 PC_RECIPE_CHANGE_COMPLETE, PC_RECIPE_NO 초기화.
  • Recipe별 Page 수 가변 검증(STEP 6)이 11/21/22/31/32 모두에서 동작.
  • 솔루션 빌드 통과(레거시 포함). 빌드 실패를 경고로 넘기지 말 것.

8. 핵심 참고 코드 위치 (active path)

  • 상태머신: SeqAutoRunPTOP.Builder() — SeqAutoRunPTOP.cs:114-171 (흐름 L142-163)
  • Page REQ 대기: CheckPageNo — SeqAutoRunPTOP.cs:277-328
  • Page 확정/에코: CheckPageNoComp — SeqAutoRunPTOP.cs:331-422
  • 리셋: RestoreDeviceStatus — SeqAutoRunPTOP.cs:799+ / OnSeqActionStop 인근 L976-981
  • 주소맵: Device/PLC/PLCController.Address.cs
  • Recipe 활성화 API: Recipes/RMSHandlerForPTOP.cs:173 (RecipeManager.ActivateRecipe), 조회 :125-130
  • 레거시 완전형 핸드셰이크(참고): Sequences/SeqWaitWeldOrChangePage.cs:251-318