← 전체 글
SECS/GEM/약 18분 읽기/ 조회

SECS/GEM 알람이 set인지 clear인지는 ALCD 한 비트가 정한다

S5F1은 ALCD, ALID, ALTX 세 항목이다. ALCD 8번 비트가 set/clear를 정하고, 이걸 놓치면 MES 알람 목록이 영영 안 꺼진다. 재시작 후 S5F5/S5F6로 복구하는 방법까지.

SECS/GEM알람MESSCADA체크리스트문제 해결

MES 알람 배너에 세 건이 떠 있다. 장비 화면은 깨끗하다. 오퍼레이터는 한 시간 전에 다 처리했다고 한다.

로그를 열어 보면 S5F1이 여섯 번 들어왔다. set 세 번, clear 세 번. 호스트는 여섯 건을 전부 받았고, 전부 "알람 발생"으로 기록했다. ALID와 ALTX만 읽고 ALCD를 버렸기 때문이다.

S5F1은 항목이 세 개다

SEMI E5 Stream 5는 알람/예외 처리다. S5F1 Alarm Report Send의 body는 리스트 하나에 항목 세 개다.

L,3
  <B  ALCD>    1 byte   알람 코드 바이트
  <U4 ALID>             알람 ID (포맷은 고정이 아니다 — 아래 참고)
  <A  ALTX>             알람 텍스트, 최대 120자

순서가 저렇다. ALID가 아니라 ALCD가 먼저 온다. 파서를 손으로 쓰다가 첫 항목을 ID로 읽어 버리는 실수가 실제로 나온다.

디코더를 맞춰 볼 기준이 하나는 있어야 한다. 아래는 손으로 그린 예시가 아니다. HSMS passive listener(127.0.0.1:5501, session id 11)에 socket으로 붙어서 실제로 밀어 넣은 바이트고, 장비 쪽 로그에 RX로 찍힌 것을 그대로 옮겼다. 프레이밍은 SEMI E37, item header는 E5의 포맷 코드 표를 따른다.

TX Select.req    00 00 00 0A 00 0B 00 00 00 01 00 00 01 01
RX Select.rsp    00 00 00 0A 00 0B 00 00 00 02 00 00 01 01

TX S5F1 set      00 00 00 2C 00 0B 85 01 00 00 00 00 0B B9
                 01 03 21 01 82 B1 04 00 00 13 89
                 41 15 43 68 61 6D 62 65 72 20 70 72 65 73 73 75 72 65 20 68 69 67 68

Select.rsp의 byte 3이 00이라 링크는 SELECTED다. 그 다음 프레임을 잘라 놓으면 이렇다.

00 00 00 2C            length = 44 (header 10 + body 34)
00 0B                  session id 11
85                     W-bit(0x80) + stream 5
01                     function 1
00 00                  PType 0, SType 0 -> data message
00 00 0B B9            SystemBytes

01 03                  L,3
21 01 82               <B 0x82>   set + 분류 코드 2, equipment safety
B1 04 00 00 13 89      <U4 5001>  ALID
41 15 43 68 61 6D ...  <A "Chamber pressure high">  0x15 = 21자

장비 쪽 디코더가 이 프레임을 읽고 남긴 값은 len 44, sessionId 11, stream 5, function 1, wbit true, systemBytes 3001이다. 30010x00000BB9다. 내 인코더와 남의 디코더가 같은 값을 말하면 그 바이트는 맞다고 봐도 된다.

같은 알람의 clear를 같은 socket으로 이어서 보냈다.

TX S5F1 clear    00 00 00 2C 00 0B 85 01 00 00 00 00 0B BA
                 01 03 21 01 02 B1 04 00 00 13 89
                 41 15 43 68 61 6D 62 65 72 20 70 72 65 73 73 75 72 65 20 68 69 67 68

두 프레임을 나란히 놓으면 다른 바이트가 두 군데뿐이다. SystemBytes(0B B90B BA), 그리고 ALCD(8202). 길이도 44로 같고 ALID도 ALTX도 그대로다. 첫 항목을 건너뛴 호스트가 둘을 구분 못 하는 이유가 이거다.

세 프레임 모두 1초를 기다렸지만 S5F2는 오지 않았다. 이 listener는 host 쪽 S5F2를 구현하지 않는다. 보내는 쪽에서 보면 답 없는 W-bit 메시지가 정확히 이렇게 보인다 — 아무 일도 일어나지 않는다. 실제 장비라면 지금 T3를 세고 있다.

HSMS header의 byte 2가 05가 아니라 85인 것이 W-bit다. 장비가 S5F2를 달라고 말하고 있는 것이다.

ALCD 한 바이트가 두 가지를 동시에 나른다.

비트
8번 비트 (0x80)1이면 알람 set, 0이면 알람 clear
7~1번 비트알람 분류 코드

그래서 위의 0x82는 "equipment safety 알람 발생", 0x02는 "같은 알람 해제"다. 두 메시지의 ALID와 ALTX는 완전히 같다. 구분은 최상위 비트 하나뿐이다.

분류 코드는 E5가 정해 둔 것이 있다.

분류
1Personal safety
2Equipment safety
3Parameter control warning
4Parameter control error
5Irrecoverable error
6Equipment status warning
7Attention flags
8Data integrity
9–63예약
64–127장비 제조사 정의

64 이상이 보이면 매뉴얼을 찾아야 한다. 표준에는 답이 없다.

키는 ALID다. ALTX가 아니다

ALTX는 E5에서 120자로 제한된 문자열이다. 오퍼레이터가 읽는 용도지 키로 쓸 물건이 아니다. 장비 소프트웨어를 올리면 오타 하나 고쳐지고 문자열이 바뀐다. 그러면 텍스트를 키로 쓴 통합은 그날부터 같은 알람을 새 알람으로 만든다.

ALID는 고정이다. GEM(SEMI E30)은 각 알람에 고유하고 변하지 않는 ALID를 요구한다. 매핑 테이블의 primary key는 여기다.

대신 ALID가 항상 U4인 건 아니다. E5는 ALID를 숫자 포맷으로 정의하고, 어느 포맷을 쓸지는 장비가 고른다. U1, U2, U4, U8은 물론 부호 있는 I1/I2/I4/I8도 허용된다. item header 바이트를 읽어라. 폭을 코드에 박지 마라. 실제로 마주치는 부호 없는 네 가지를 길이 바이트 1개짜리 item header로 적으면 이렇다.

포맷item header 바이트페이로드
U1A51 byte
U2A92 bytes
U4B14 bytes
U8A18 bytes

같은 알람을 ALID만 U2로 바꿔서 같은 socket으로 한 번 더 보냈다. 회선에서 뜬 바이트다.

TX S5F1 set (U2 ALID)  00 00 00 2A 00 0B 85 01 00 00 00 00 0B BB
                       01 03 21 01 82 A9 02 13 89
                       41 15 43 68 61 6D 62 65 72 20 70 72 65 73 73 75 72 65 20 68 69 67 68

바뀐 건 B1 04 00 00 13 89A9 02 13 89가 된 것뿐인데 프레임 길이가 44에서 42(0x2A)로 줄었다. 장비 디코더도 len 42로 읽었다.

여기서 B1을 가정하고 "header 2바이트 건너뛰고 4바이트를 ID로" 읽는 호스트는 13 89 41 15를 ALID로 집어 든다. 5001이 아니라 327762197(0x13894115)이다. 그 다음부터 파싱은 전부 밀리고, 로그에는 알람 매핑 실패만 남는다. 버그는 표가 아니라 디코더에 있다.

ALTX는 그래도 원문 그대로 보관해라. 장애 조사 때 장비 화면, 벤더 매뉴얼, 필드 서비스 리포트가 전부 원문으로 말한다. 정규화한 이름만 남기면 대조가 안 된다.

매핑 테이블에 들어갈 것

코드 쓰기 전에 표부터 채운다.

컬럼이유
ALID고정 키. set/clear/이력/필터가 전부 여기에 걸린다.
ALCD 분류1~8은 E5 정의, 64 이상은 벤더 정의. 어느 쪽인지 적어 둔다.
ALTX 원문벤더 문구 그대로. 손대지 않는다.
정규화 이름MES 화면과 리포트용.
심각도사이트 우선순위. 벤더 심각도를 그대로 쓰지 않는다.
위치chamber, module, station.
연동 CEID알람 set/clear에 걸린 collection event.
스냅샷 변수알람 순간에 같이 잡을 SVID/DVID.
조치 문구오퍼레이터가 먼저 볼 것.
시험 증거실제로 발생시켜 본 기록.

연동 CEID 컬럼을 비워 두지 마라. GEM은 알람을 collection event 보고와도 엮어 두기 때문에, 같은 전이가 S5F1과 S6F11 두 경로로 올 수 있다. 두 경로를 다 활성화해 놓고 중복 처리를 안 하면 알람 하나가 목록에 두 번 뜬다.

호스트가 재시작하면 상태를 다시 물어라

세션이 끊긴 동안 발생한 S5F1은 사라진다. 재접속했다고 상태가 따라오지 않는다. 다시 물어야 한다.

  • S5F5 List Alarms Request — ALID 리스트를 보내면 그 알람들의 현재 상태가 온다. 리스트를 길이 0으로 보내면 전체다. 답은 S5F6이고, 안에 든 ALCD의 8번 비트가 지금 set인지 clear인지를 말한다. 재시작 후 활성 알람 복구는 이 한 번의 왕복으로 끝난다.
  • S5F7 List Enabled Alarm Request — body 없이 header만 보낸다. S5F8로 현재 enable된 알람 목록이 온다. 내가 활성화했다고 믿는 것과 장비가 실제로 켜 둔 것이 다른 경우를 여기서 잡는다.
  • S5F3 Enable/Disable Alarm Send — ALED가 0x80이면 enable, 0x00이면 disable이다. S5F4가 ACKC5로 답한다.

S5F3을 쓸 거면 누가 쓰는지부터 정해라. 호스트 통합과 벤더 툴이 같은 알람의 enable 상태를 서로 모르고 뒤집는 상황이 제일 찾기 어렵다.

상태 모델은 네 개로는 부족하다

이벤트만 쌓는 알람 목록은 목록이 아니다. 현재 상태를 들고 있어야 한다.

상태언제
Activeset을 받았고 대응하는 clear가 아직 없다.
Clearedactive 이후 clear를 받았다.
Unknown통합이 재시작했고 S5F5로 아직 재조회를 못 했다.
StaleHSMS 링크가 끊겼거나 마지막 갱신이 너무 오래됐다.
Disabled장비가 그 알람을 enable하지 않았다(S5F8 기준).

UnknownStale을 빼먹는 구현이 대부분이다. 링크가 죽은 동안 화면은 마지막으로 본 상태를 그대로 보여 주고, 그건 깨끗해 보인다. 아무것도 안 오는 것과 알람이 없는 것은 다르다. 화면에서 그 둘이 같아 보이면 그 화면은 틀렸다.

S5F1은 GEM에서 W-bit를 세워 보내므로 호스트는 ACKC5를 담은 S5F2로 답해야 한다. 기한은 T3 reply timeout이고 E37의 권장 기본값은 45초다. ACKC5는 0이 accept, 0이 아니면 error다. 답장 전체는 13바이트다.

00 00 00 0D 00 0B 05 02 00 00 00 00 0B B9 21 01 00
                  ^^  stream 5, W-bit 없음
                     ^^  function 2
                              ^^^^^^^^^^^  S5F1의 SystemBytes를 그대로 돌려준다
                                          ^^^^^^^^  <B 0> — ACKC5 = accept

SystemBytes는 반드시 그대로 echo해라. 새 SystemBytes로 보낸 것은 답장이 아니고, 장비는 T3가 터질 때까지 기다린다. 여기서 주의할 것 하나 — S5F2를 안 보냈다고 알람이 취소되지 않는다. 장비 쪽에서는 T3가 터지고 로그가 남을 뿐, 알람은 그대로 set이다.

심각도는 벤더가 아니라 운영이 정한다

벤더 심각도를 1:1로 옮기면 MES 알람 화면이 장비 화면의 시끄러운 복사본이 된다.

ISA-18.2가 말하는 rationalization을 알람마다 한 번씩 돌리는 게 맞다. 질문은 짧다.

  • 오퍼레이터가 지금 움직여야 하는가?
  • 생산이 멈추는가, 가동률만 떨어지는가?
  • 제품이나 장비가 상하는가?
  • 제어실에서 조치가 되는가, 아니면 장비 앞에 가야 하는가?
  • 장비 HMI에서 이미 처리되고 있는가?

EEMUA 191은 정상 운전 중 오퍼레이터 한 명이 받는 알람을 10분에 1건 이하로 본다. 툴 한 대의 알람을 전부 올려 놓으면 그 예산은 장비 한 대로 다 쓴다.

시운전에서 실제로 해 볼 것

  • 매핑한 ALID가 설치된 장비 소프트웨어 버전에 실제로 있는지 확인한다.
  • 대표 알람을 발생시키고 S5F1 원본 바이트를 잡는다. ALCD가 0x80 이상인지 본다.
  • 같은 알람을 해제하고 ALCD의 8번 비트가 0으로 오는지 본다.
  • 통합을 재시작하고 S5F5/S5F6로 활성 알람이 복구되는지 확인한다.
  • HSMS 링크를 끊고 화면이 Stale로 바뀌는지 확인한다. 안 바뀌면 그게 버그다.
  • 같은 set을 두 번 받았을 때 목록에 두 번 뜨지 않는지 확인한다.
  • active가 아닌 알람의 clear를 받았을 때 상태가 깨지지 않는지 확인한다.
  • ALTX 인코딩을 확인한다. 한글과 특수문자가 들어간 알람을 골라서 본다.
  • 타임스탬프 출처를 정한다. 장비 시각인지 호스트 수신 시각인지 문서에 적는다.
  • S5F1과 S6F11 양쪽으로 오는 알람이 있는지, 있다면 중복 제거가 되는지 확인한다.

자주 나오는 실수

  • ALTX를 키로 쓴다. 장비 업그레이드 날 전부 새 알람이 된다.
  • ALCD를 버리고 S5F1을 전부 "발생"으로 처리한다. 이 글의 첫 문단이 그 결과다.
  • 모든 벤더 경고를 같은 우선순위로 올린다.
  • 통신 두절을 화면에서 숨긴다.
  • ALID만 저장하고 chamber, recipe, lot 문맥을 안 잡는다. 나중에 재구성이 안 된다.
  • 시뮬레이터로만 시험하고 실제 장비 동작을 한 번도 안 본다.

SECS/GEM 시뮬레이터에서 알람을 raise하고 clear해 보면 한 쌍이 지나가는 걸 볼 수 있다. 기본 S5F1은 ALCD 128, ALID 5001로 나간다. 1280x80이다 — set 비트만 켜져 있고 분류 코드는 0인, 실제 장비에서 흔히 보는 모양이다.

그 데모에 대해 솔직하게 두 가지. raise는 E5에 없는 네 번째 항목(severity 문자열)을 덧붙이고, clear는 세 개만 보낸다. 모양을 따라하지 말고 교훈만 가져가라. S5F1은 위치로 읽고 항목 3에서 멈춰라. 리스트 개수로 검증하지 마라. 실제 장비도 벤더 항목을 뒤에 붙인다. 그리고 화면에 뜨는 그 S5F1은 표시용으로 합성한 것이지 socket으로 나간 바이트가 아니다. 이 글에 실은 바이트는 그쪽이 아니라 listener에 직접 붙어서 뜬 것이다.

다음에 알람 목록이 안 꺼진다는 말을 들으면 화면부터 보지 말고 S5F1 원본 바이트의 첫 항목을 봐라. 대개 거기서 끝난다.