# ILSOS PTOP 알람부(AlarmManager) 종합 분석 — 2026-06-19 > 계기: 현장 PLC 미연결 상태에서 `SeqComponentTeachingRun` 시작 시 H(중)알람 인터락(202003)으로 차단됨. > 본 문서는 알람부 전체 구조·동작·시퀀스 참조·리스크·개선안을 정리한다. --- ## 1. 클래스 구조 | 클래스 | 위치 | 역할 | |--------|------|------| | `AlarmManager` (base) | `WeldingCommon/Alarm/AlarmManager.cs` | 정적 싱글톤(`_Instance`). 알람 set/조회/시퀀스 정지 | | `AlarmManager_PTOP` | `PTOP/Alarm/AlarmManager_PTOP.cs` | `StopSequenceByAlarm` — H알람 시 AutoRun 정지 | | `AlarmCode` / `AlarmCode_PTOP` | `.../Alarm/AlarmCode*.cs` | 알람 코드 상수. PTOP는 base 상속 후 21xxxx 추가 | | `IAlarmService` (Aurora 프레임워크) | External/Aurora | **활성 알람 목록·설명·레벨(H/L)** 보유 | - 알람 **레벨(H/L)** 은 소스 상수가 아니라 **Aurora 런타임 알람 테이블**에 정의됨(코드에 `AlarmLevel.H` 할당부 없음). ## 2. 핵심 메서드 동작 (주의점) - **`Alarm(code)`** (79줄): 이미 활성이면 재set 안 함 → **set-once(중복 없음)**. - **`HasAlarmLevelHigh()`** (172줄): 활성 알람 중 H 하나라도 있으면 true. **⚠️ Simulation이면 무조건 false**(시뮬은 인터락 우회). - **`IsAlarmLevelHigh(code)`** (194줄): 설명 모르는 코드(`desc==null`)는 **위험으로 보고 H 취급** → 미정의 코드도 인터락 유발. - **Clear**: 개별 `ClearAlarm()`은 **빈 함수**(주석만). 실제 해제는 **`ClearAllAlarm()`(전체 일괄)** 뿐. - 트리거: `SYS_ALARM_RESET_ALL_ALARM` / `EVENT_RESET_ALL_ALARMS_REQUEST` → `_AlarmService.ClearAllAlarm()`. - **PLC 알람워드 직접쓰기**(`WriteBit(HeavyAlarmStatusAddr..)`)는 AlarmManager 내에서 전부 **주석 처리**됨(대신 SeqStatusMonitor가 수행). ## 3. 알람 생성·소멸·전파 흐름 ``` [생성] SeqAlarmMonitor (상시 주기 감시) ├ PLC: EMO / Heavy / Door / 통신끊김 ├ Laser/Scanner/LBAD/OCT/Chiller: Deactivated/Disconnect/Error └ IO: Leak / null / deactivated → AlarmManager.Alarm(code) ← set-only, ❌조건 해소 시 Clear 안 함(LATCH) [전파] EquipmentSetup.OnSetAlarm(code, isHeavy) (EquipmentSetup.cs:82) → isHeavy 면 AlarmManager_PTOP.StopSequenceByAlarm(code) → H면 StopSequence(SeqAutoRun) 비상정지 [PLC보고] SeqStatusMonitor.UpdateStatus (SeqStatusMonitor.cs:86) → PC_HEAVY_ALARM_STATUS = HasAlarmLevelHigh(), PC_LIGHT_ALARM_STATUS = HasAlarmLevelLow() → PLC_ALARM_RESET 입력 시 EVENT_RESET_ALL_ALARMS_REQUEST 발행 → ClearAllAlarm() [차단] 각 시퀀스 시작 시 CheckCondition_Interlock() → HasAlarmLevelHigh() H면 시작 거부 ``` ## 4. 주요 시퀀스별 알람 참조 | 시퀀스 | 인터락 체크 | 비고 | |--------|------------|------| | **SeqComponentTeachingRun** | `HasAlarmLevelHigh()` → "Clear Heavy Alarms" + 202003 (Door/EMO 주석) | **이번에 막힌 시퀀스** | | SeqTeachingRun (Common) | `CheckCondition_Interlock()` = **빈 체크(true)** | 알람 체크 없음 | | **SeqAutoRunPTOP** | `CheckCondition_Interlock()` = **빈 체크(true)** | 차단은 시작이 아니라 OnSetAlarm→StopSequence | | SeqAutoRunPrismatic / ComponentWeld | 동일 패턴(빈 체크) | | | ScoutNormal/FlyingVision, UploadWeldingList, ReceiveCellInfo, ReportCellResult, MarkGrid, ScannerCalibration | 대부분 빈 체크 | 공통 시퀀스 | | **SeqStatusMonitor** | 알람을 **읽어 PLC 출력** + Reset 처리 | 차단 아님 | | **SeqAlarmMonitor** | 알람을 **생성(set-only)** | latch 원인 | > 실제 알람으로 "시작 차단"하는 곳은 `SeqComponentTeachingRun`이 거의 유일. AutoRun 계열은 "운전 중 H알람 발생 시 비상정지" 방식. ## 5. 알람 코드 표 (추정 레벨 — 권위값은 런타임 테이블) | 코드 | 이름 | 용도 | 추정 | |------|------|------|------| | 200xxx~203xxx | ALARM_SEQUENCE_* | 시퀀스 결과/초기조건 실패 | 혼합 | | 203004 | AutoRun_HeavyAlarmOccured | 자동운전 중 중알람 | H | | 210001/2/3 | PLC Deactivated/Disconnect/**EMO** | PLC 상태/비상정지 | H | | 210004/5/6 | PLC Light / **Heavy** / Door Interlock | PLC 경/중/도어 | 210005·6 H, 210004 L | | 210101/2/3 | Scanner Deactivated/Disconnect/Error | 스캐너 | H/혼합 | | 210201~205 | Laser Deactivated/Disconnect/Error/Warning/**EMO** | 레이저 | 205·201 H, 204 L | | 210206/7 | Laser Warning/Error MSG | 레이저 메시지(동적) | L/H | | 210301~303 | LBAD Deactivated/Disconnect/Error | LBAD | H/혼합 | | 210401~403 | OCT Deactivated/Disconnect/Error | OCT | H/혼합 | | 210501~503 | Chiller Deactivated/Disconnect/Error | 냉각기 | H/혼합 | | 210600~604 | IO Null/Deactivated/Disconnect/**Leak**(Scanner/Chiller) | IO보드/누액 | H | | 210605~614 | IO MC/BoxTemp/ChillerLeak/Fan1~6 | (현재 대부분 주석) | 혼합 | | 210700~705 | RMS_* 타임아웃/설정 | 레시피 관리 | L 추정 | ## 6. 리스크 / 개선 포인트 1. **알람 Latch (최우선)** — `SeqAlarmMonitor`가 set만 하고 조건 정상화 시 `ClearAlarm` 안 함. → **이번 PLC 미연결 사례**가 정확히 이것: 연결 복구돼도 알람이 남아 차단, 수동 ClearAll 필요. 2. **개별 Clear 부재** — `ClearAlarm()`이 빈 함수 → 전체 일괄 해제만 가능, 특정 알람만 해제 불가. 3. **Unknown=H 취급** — 미정의 코드 활성 시 무조건 H 차단 → 알람 테이블 누락 시 의도치 않은 인터락. 4. **시뮬 우회** — `HasAlarmLevelHigh()`가 Simulation이면 false → 시뮬/현장 동작 차이. 5. **인터락 일관성 부재** — TeachingRun만 알람 차단, 나머지 시작 시퀀스는 빈 체크. 안전 정책 제각각. 6. **Door/EMO 주석** — SeqComponentTeachingRun·UCMainAutoRunViewModel의 Door/EMO 인터락 주석 → 현재 중알람 1종만 차단. ## 7. 개선 제안 — SeqAlarmMonitor self-clearing 각 검사 항목을 "조건 나쁨 → Alarm, 조건 좋음 → Clear" 대칭 구조로. 예(개념): ```csharp // AS-IS if (!_Laser.IsActivated) AlarmManager.Alarm(ALARM_DEVICE_LASER_DEACTIVATED); else { /* clear 없음 → latch */ } // TO-BE (self-clearing) — AlarmManager에 개별 ClearAlarm(code) 구현 전제 if (!_Laser.IsActivated) AlarmManager.Alarm(ALARM_DEVICE_LASER_DEACTIVATED); else AlarmManager.ClearAlarm(ALARM_DEVICE_LASER_DEACTIVATED); ``` - 전제: `AlarmManager.ClearAlarm(int code)` 실구현 필요(현재 빈 함수). `_AlarmService`에 단건 해제 API 확인 후 연결. - 효과: PLC 재연결 등 조건 복구 시 알람 자동 해제 → 수동 ClearAll 불필요, 인터락 latch 해소. - 범위: AlarmManager(공통) 수정 → **승인 필요 영역**. 적용 전 별도 협의. ## 8. 부록 — 이번(PLC 미연결) 사례 요약 - PLC 미연결 → `SeqAlarmMonitor`가 PLC Deactivated/Disconnect(H) set → latch. - `SeqComponentTeachingRun` 시작 → `HasAlarmLevelHigh()` true → 202003, FORCE_ERROR. - 임시조치: `SeqComponentTeachingRun.CheckCondition_Interlock()`의 H알람 블록 주석(테스트용, **원복 예정**) → 레이저 출사 확인. - 관련: [[axis-position-interlock-todo]]