정보 모델
OPC UA 서버는 데이터를 주소 공간(address space)으로 공개합니다. 주소 공간은 노드(node)와 노드 사이의 참조(reference)로 이루어진 그래프입니다. 클라이언트는 이 그래프를 탐색(Browse)하고, 노드의 속성(attribute)을 읽고 쓰고, 메서드(method)를 호출합니다. 주소 공간 모델은 Part 3, 표준 노드와 타입은 Part 5에서 정의합니다.
노드와 NodeClass
섹션 제목: “노드와 NodeClass”모든 노드는 NodeClass 하나에 속합니다. NodeClass는 노드가 가지는 속성의 종류를 정합니다(Part 3, 5절 Standard NodeClasses).
| NodeClass | 값 | 용도 |
|---|---|---|
| Object | 1 | 장비, 폴더처럼 다른 노드를 묶는 객체 |
| Variable | 2 | 값을 가진 노드. 데이터 변수와 속성(property)이 있습니다. |
| Method | 4 | 호출할 수 있는 함수 |
| ObjectType | 8 | Object의 타입 정의 |
| VariableType | 16 | Variable의 타입 정의 |
| ReferenceType | 32 | 참조의 종류 |
| DataType | 64 | 값의 데이터 타입 |
| View | 128 | 주소 공간의 부분 집합 |
값은 Browse 결과의 NodeClass 필드에 그대로 나타납니다. 예를 들어 PDComm 예제의 Browse 출력에서 Variable은 2, Method는 4입니다.
노드의 정보는 속성으로 읽습니다. 속성마다 숫자 ID가 있습니다(AttributeId). 자주 쓰는 속성은 다음과 같습니다.
| AttributeId | 이름 | 설명 |
|---|---|---|
| 1 | NodeId | 노드 식별자 |
| 2 | NodeClass | 위 표의 값 |
| 3 | BrowseName | 탐색 경로에 쓰는 이름(QualifiedName). 2:Simulator.Double처럼 네임스페이스 인덱스가 붙습니다. |
| 4 | DisplayName | 사람이 읽는 이름(LocalizedText) |
| 12 | EventNotifier | 이벤트를 구독할 수 있는지 나타내는 비트 |
| 13 | Value | 변수의 값 |
| 14 | DataType | 값의 데이터 타입 NodeId |
| 15 | ValueRank | -1이면 스칼라, 1 이상이면 배열 차원 |
| 17 | AccessLevel | 읽기·쓰기·이력 접근 가능 여부 비트 |
| 20 | Historizing | 서버가 값의 이력을 저장하는지 여부 |
Read 서비스는 노드와 AttributeId의 쌍을 받습니다. AttributeId를 지정하지 않는 API는 대부분 Value(13)를 읽습니다. PDComm 시뮬레이터의 read 동작도 기본값이 13입니다.
NodeId와 네임스페이스
섹션 제목: “NodeId와 네임스페이스”NodeId는 네임스페이스 인덱스(namespace index)와 식별자(identifier)로 이루어집니다(Part 3, NodeId 데이터 타입). 식별자 형식은 네 가지입니다.
| 형식 | 텍스트 표기 | 예 |
|---|---|---|
| 숫자(Numeric) | i= |
i=85, ns=2;i=1001 |
| 문자열(String) | s= |
ns=2;s=Simulator.Double |
| GUID | g= |
ns=1;g=09087e75-8e5e-499b-954f-f2a9603db28a |
| 바이트 문자열(ByteString) | b= |
ns=1;b=M/RbKBsRVkePCePcx24oRA== |
네임스페이스 인덱스 0은 생략합니다. i=85는 ns=0;i=85와 같습니다.
네임스페이스 인덱스는 서버의 NamespaceArray 변수(i=2255)에 있는 URI 목록의 위치입니다. 인덱스 0은 항상 http://opcfoundation.org/UA/입니다. 인덱스 1은 서버 자신의 URI입니다. 그 뒤는 응용 프로그램 네임스페이스입니다. PDComm 시뮬레이터에서 i=2255를 읽으면 다음 값이 나옵니다.
["http://opcfoundation.org/UA/","urn:pdcomm:opcua:server","urn:pdcomm:opcua:nodes"]PDComm SDK의 메모리 서버와 시뮬레이터는 응용 노드를 인덱스 2(urn:pdcomm:opcua:nodes)에 둡니다. 인덱스는 서버마다 다를 수 있습니다. 다른 서버에 연결할 때는 NamespaceArray를 읽어 URI로 인덱스를 찾습니다.
참조는 방향이 있는 연결입니다. 원본 노드에서 대상 노드로 향하는 방향을 순방향(forward), 반대를 역방향(inverse)이라고 합니다. 참조의 종류는 ReferenceType 노드로 정의합니다(Part 3, 7절 Standard ReferenceTypes).
| ReferenceType | NodeId | 의미 |
|---|---|---|
| HierarchicalReferences | i=33 |
계층 참조 전체의 상위 타입. Browse의 기본 필터로 씁니다. |
| Organizes | i=35 |
폴더가 노드를 정리함 |
| HasComponent | i=47 |
객체가 구성 요소를 가짐 |
| HasProperty | i=46 |
노드가 속성 변수를 가짐 |
| HasTypeDefinition | i=40 |
인스턴스와 타입 정의를 연결 |
주소 공간의 출발점은 Objects 폴더(i=85)입니다. Objects 아래에는 서버 상태를 담는 Server 객체(i=2253)와 응용 프로그램 객체가 있습니다. PDComm 시뮬레이터의 주소 공간은 다음과 같습니다.
Objects (i=85)├── Server (i=2253) Organizes└── Simulator (ns=2;s=Simulator) Organizes ├── Simulator.Boolean Variable HasComponent ├── Simulator.Int32 Variable ├── Simulator.Double Variable Historizing ├── Simulator.String Variable ├── Simulator.Counter Variable read-only, historizing ├── Simulator.Protected Variable authenticated users only ├── Simulator.AlarmSource Variable drives Simulator.Alarm ├── Simulator.Add Method Double + Double └── Simulator.Delay Method holds the server for N msSDK 예제 서버(opcua_server)는 Objects 아래에 Value(ns=2;i=1001), Limit(ns=2;i=1002), Protected(ns=2;i=1003) 변수를 둡니다.
타입 체계
섹션 제목: “타입 체계”Object와 Variable은 타입 정의를 가집니다. 폴더는 FolderType(i=61), 일반 데이터 변수는 BaseDataVariableType(i=63)의 인스턴스입니다. 타입은 상속 계층을 이룹니다. 이벤트 타입과 알람 타입도 같은 방식으로 정의합니다(Part 5, Part 9).
변수 값의 타입은 DataType 속성으로 나타냅니다. 기본 데이터 타입(built-in type)은 UA Binary에서 Variant의 타입 번호로 인코딩됩니다(Part 6, 5.2절 OPC UA Binary).
| 타입 번호 | 데이터 타입 | DataType NodeId |
|---|---|---|
| 1 | Boolean | i=1 |
| 6 | Int32 | i=6 |
| 7 | UInt32 | i=7 |
| 10 | Float | i=10 |
| 11 | Double | i=11 |
| 12 | String | i=12 |
| 13 | DateTime | i=13 |
| 15 | ByteString | i=15 |
| 17 | NodeId | i=17 |
| 21 | LocalizedText | i=21 |
| 22 | ExtensionObject | i=22 |
ExtensionObject는 구조체 값을 담습니다. 구조체의 인코딩 NodeId가 앞에 붙고 그 뒤에 본문이 옵니다. 서비스 요청과 응답 메시지도 같은 원리로 인코딩 NodeId로 시작합니다.
변수와 접근 수준
섹션 제목: “변수와 접근 수준”변수의 Value 속성을 읽고 쓸 수 있는지는 AccessLevel 비트로 나타냅니다.
| 비트 | 이름 | 의미 |
|---|---|---|
0x01 |
CurrentRead | 현재 값을 읽을 수 있음 |
0x02 |
CurrentWrite | 현재 값을 쓸 수 있음 |
0x04 |
HistoryRead | 이력을 읽을 수 있음 |
0x08 |
HistoryWrite | 이력을 바꿀 수 있음 |
시뮬레이터의 Simulator.Double은 AccessLevel이 15(0x0F)입니다. UserAccessLevel은 세션의 사용자에 따라 달라질 수 있습니다. PDComm 서버는 공개하지 않은 변수에 익명 세션이 접근하면 BadUserAccessDenied를 돌려줍니다.
DataValue
섹션 제목: “DataValue”Read 응답과 구독 알림은 값을 DataValue로 전달합니다. DataValue는 다음 필드로 이루어집니다.
| 필드 | 설명 |
|---|---|
| Value | 값(Variant) |
| StatusCode | 값의 품질. 없으면 Good입니다. |
| SourceTimestamp | 값이 원천에서 바뀐 시각 |
| ServerTimestamp | 서버가 값을 받은 시각 |
각 필드는 있을 수도 없을 수도 있습니다. UA Binary에서는 첫 바이트의 마스크 비트가 어떤 필드가 있는지 알려 줍니다.
StatusCode
섹션 제목: “StatusCode”StatusCode는 32비트 값입니다. 상위 2비트가 심각도(severity)입니다.
| 상위 비트 | 심각도 | 예 |
|---|---|---|
00 |
Good | 0x00000000 Good, 0x00A50000 GoodNoData |
01 |
Uncertain | 0x40000000 Uncertain |
10 |
Bad | 0x803B0000 BadNotWritable, 0x801F0000 BadUserAccessDenied, 0x80340000 BadNodeIdUnknown |
최상위 비트(0x80000000)가 켜져 있으면 실패입니다. PDComm 예제는 이 비트로 실패를 판단합니다. 하위 16비트에는 추가 정보 비트가 있습니다. 예를 들어 이력 값의 0x00000408은 Good이면서 같은 시각에 값이 더 있음을 나타냅니다.
OPC UA 응답에는 StatusCode가 두 단계로 있습니다.
- 서비스 결과(serviceResult): 요청 전체의 결과입니다. 요청 자체가 거부되면 서버는 ServiceFault 응답을 보냅니다.
- 작업 결과(operation result): 요청 안의 항목마다 붙는 결과입니다.
예를 들어 읽기 전용 변수에 쓰면 서비스 결과는 Good이고 항목 결과만 BadNotWritable입니다. PDComm C 예제는 두 값을 service=0x00000000 status=0x803b0000처럼 함께 출력합니다. StatusCode 목록은 StatusCode 오류 목록에서 찾습니다.
다음 단계
섹션 제목: “다음 단계”서비스에서 클라이언트가 노드에 접근하는 순서를 살펴봅니다.