HMI의 탱크 레벨이 3.42 m로 보인다. 40분째 3.42 m다. Operator는 펌프가 꺼져 있다고 생각한다. 실제로는 펌프가 트립됐고 레벨은 올라가고 있는데, gateway 뒤의 OPC UA server가 40분 전 SourceTimestamp가 찍힌 마지막 캐시 DataValue를 Good status로 계속 내보내고 있다. HMI tag를 value 하나에만 매핑해 둔 탓에 아무도 그 timestamp를 못 본다.
이 주제가 존재하는 이유가 바로 이 장애다. OPC UA의 모든 read와 subscription notification은 DataValue다. value, StatusCode, SourceTimestamp, ServerTimestamp가 한 묶음으로 온다(IEC 62541-4). value만 tag에 매핑하면 값을 믿어도 되는지 알려 주는 나머지 세 필드를 버리는 셈이다.
StatusCode는 32비트, 먼저 볼 건 상위 2비트뿐
OPC UA StatusCode는 32비트 숫자다. 가장 먼저 봐야 할 건 최상위 2비트, 즉 severity다.
00— Good (0x00000000 대)01— Uncertain (0x40000000 대)10— Bad (0x80000000 대)
나머지 비트는 왜 그런지 알려 주는 sub-code다. 모든 걸 "bad quality" 하나로 뭉개는 driver는 이 정보를 버리고, 하필 제일 급할 때 그 대가를 치른다. Bad_NoCommunication(0x80310000)은 케이블, switch, 죽은 PLC다 — 현장으로 가야 한다. Bad_NodeIdUnknown(0x80340000)은 주소가 사라진 것이고, 거의 항상 PLC download 뒤 NodeId가 밀린 경우다. 공장을 아무리 돌아도 안 고쳐진다. HMI에서 똑같이 빨갛게 뜬 두 tag, 조치는 완전히 다르다.
시운전 중에 구분해서 남길 만한 것들:
| 심볼 이름 | Severity | 실제 의미 |
|---|---|---|
Good | Good | 값이 살아 있고 쓸 수 있음 |
UncertainLastUsableValue | Uncertain | Server가 stale 가능성을 경고 중 — Good으로 취급 금지 |
Bad_NoCommunication | Bad | PLC / remote I/O / gateway 통신 두절 |
Bad_NodeIdUnknown | Bad | 주소 매핑 깨짐, 보통 program download 뒤 |
Bad_OutOfService | Bad | 해당 item을 일부러 scan에서 제외 |
Bad_UserAccessDenied | Bad | 통신이 아니라 access level, role, security policy 문제 |
빠뜨리기 쉬운 게 UncertainLastUsableValue다. Server가 "지금 보여 주는 건 마지막으로 갖고 있던 값"이라고 정직하게 말하는 상태다. HMI가 Uncertain을 Good과 똑같이 그리면, server가 경고하려던 stale-value 버그를 그대로 다시 만든 것이다.
두 timestamp는 따로가 아니라 서로 비교해서 읽는다
SourceTimestamp는 source가 값을 샘플링하거나 변했다고 본 시각이다. ServerTimestamp는 OPC UA server가 처리한 시각이다. 둘 다 UTC이고(1601년부터 100 ns 틱, Windows FILETIME 인코딩), client가 local time으로 보여 준다면 그 변환이 "시간이 틀렸다"는 오해가 생기는 또 하나의 지점이다.
진단은 둘 사이의 간격에 있다.
- ServerTimestamp는 최신, SourceTimestamp는 오래됨 → server는 살아 있는데 원천 값이 안 움직인다. Frozen source이거나 캐시가 값을 붙들고 있다. 위의 탱크 레벨이 이 경우다.
- ServerTimestamp도 오래됨 → 문제는 server 쪽이다. Subscription이 굶고 있거나, session이 끊겼거나, publishing이 멈췄다.
- SourceTimestamp가 ServerTimestamp보다 앞섬 → 데이터 문제가 아니라 source와 server 사이 clock 불일치다.
오래된 SourceTimestamp를 장애로 부르기 전에 한 가지 단서를 봐야 한다. Tag 종류에 달렸다. Batch step number는 step이 안 바뀌면 6분 동안 같은 SourceTimestamp를 갖는 게 정상이다. 반대로 1초 analog가 안 움직이면 그건 죽은 거다. Tag가 어느 종류인지 알아야 하고, 이건 시운전 때 tag별로 적어 둔다.
- Analog process value: publish마다 또는 유의미한 변화마다 갱신(server 설정 의존)
- Discrete status: 전이할 때만 갱신
- Counter / totalizer: 증가 시점 또는 샘플링 시점에 갱신
- Recipe / batch state: step 내내 그대로일 수 있음 — 오래된 게 정상
- Heartbeat: 정해진 주기로 반드시 갱신 — 이게 stale 판단 기준
마지막 줄이 싼 보험이다. Server 쪽에서 1초마다 증가하는 heartbeat tag 하나면 "항상 움직여야 하는 값" 하나가 생긴다. 그게 멈추면 경로가 죽은 것이다 — tag마다 추측할 필요가 없다.
FAT에서 다들 건너뛰는 건 disconnect 시험이다
Critical tag마다 시운전 시험은 여섯 단계인데, 가치는 전부 마지막 두 단계에 있다.
- Source에서 안전한 값 변경을 만든다.
- 화면 값이 바뀌는지 확인한다.
SourceTimestamp가 기대한 시점에 갱신되는지 본다.ServerTimestamp와 client 수신 시각 차이가 공정 기준 안에 드는지 본다.- Source 경로를 끊고, quality가 Good으로 얼지 않고 Bad로 바뀌는지 확인한다.
- 다시 연결하고, HMI 재시작 없이 quality와 timestamp가 회복되는지 확인한다.
1~4단계는 어지간한 시스템에서 다 통과한다. 5, 6단계에서 마지막 값을 Good으로 계속 내보내는 gateway, 재구독을 안 하는 reconnect 로직, stale 값을 아무 표시 없이 보여 주는 HMI가 걸린다. 값이 바뀔 수 있다는 것만 시험했다면 쉬운 절반만 시험한 것이다.
로직을 디버그하기 전에 clock 계층부터 맞춘다
OPC UA 값, alarm, historian sample, MES event는 결국 downstream에서 timestamp로 줄 세워진다. PLC, OPC UA server, SCADA server, historian가 5분씩 어긋나면 그 비교가 전부 거짓말이 된다. 같은 5분 offset이 한 화면에선 historian backfill 오류로, 다른 화면에선 alarm 순서 뒤바뀜으로, MES에선 lot trace 깨짐으로 보인다 — clock 하나 틀려서 "버그" 세 개가 나온다.
Application 로직을 건드리기 전에 지루한 계층부터 확인한다.
- OPC UA server host의 NTP / 공장 time source — 정말 동기화 중인가, 아니면 설정만 되고 조용히 실패 중인가?
- Server time과 SCADA server time 차이 — alarm, historian 시험 시작 전에 실제로 재 본다.
- Clock 값뿐 아니라 time zone과 DST 설정.
- Client가 UTC를 local로 어떻게 렌더링하는지 — "시간 틀림" 신고 상당수는 순수 표시 문제다.
- 일반 OS time service가 없는 embedded gateway의 시간 기준 — 명시적으로 적어 둔다.
기준 값을 남겨 둔다
Critical interface마다 프로젝트 파일에 몇 줄 남긴다. Endpoint URL과 security policy, subscription과 sampling interval, quality/timestamp를 historize하는지, tag 종류별 stale timeout, controlled-change와 disconnect 시험에서 관찰한 SourceTimestamp/ServerTimestamp. 다음에 누가 HMI가 "느리다"고 하면, 논쟁 대신 known-good 기록과 비교하면 된다. 벤더가 자기네 status 처리가 "spec대로"라고 우기면, 이 code들이 무엇을 뜻해야 하는지 규정한 IEC 62541-8(Data Access)을 근거로 대면 된다.