UDP PubSub
- 한 프로세스에서 게시와 구독을 함께 실행해 UADP 메시지가 오가는 것을 확인합니다.
- 게시자와 구독자를 별도 프로세스로 나눠 UDP로 메시지를 주고받습니다.
- 게시할 필드를 직접 정하고, 받은 메시지의 식별자를 읽습니다.
준비물
섹션 제목: “준비물”- 실습 환경의
apps패키지와 환경 변수OPCUA_APPS - 터미널 두 개
PubSub에는 OPC UA 서버나 세션이 필요 없습니다. 이 튜토리얼에서는 server_start와 connect를 쓰지 않습니다.
1. 한 프로세스에서 게시하고 받기
섹션 제목: “1. 한 프로세스에서 게시하고 받기”헤드리스 시뮬레이터를 실행합니다.
"$OPCUA_APPS/bin/pdcomm-opcua-headless"기본 구성은 UDP 전송, 게시자와 구독자 역할을 함께 하는 both입니다. 구독자는 127.0.0.1의 빈 포트에서 듣고, 게시자는 그 주소로 보냅니다.
{"action":"pubsub_start"}{"ok":true,"result":{"acknowledged":0,"destination":"127.0.0.1:64578","dropped":0,"error":null,"listen":"127.0.0.1:64578","queued":0,"received":0,"rejected":0,"role":"both","running":true,"sent":0,"transport":"udp"}}기본 필드로 DataSet 하나를 게시합니다.
{"action":"pubsub_publish"}{"ok":true,"result":{"bytes":60,"fields":4,"sequence":1}}UADP NetworkMessage 하나가 60바이트로 전송되었습니다. 받은 메시지를 꺼냅니다.
{"action":"pubsub_received"}{"ok":true,"result":{"messages":[{"bytes":60,"datasets":[{"fields":[{"type":"Boolean","value":true},{"type":"Int32","value":42},{"type":"Double","value":3.5},{"type":"String","value":"pdcomm"}],"major":1,"minor":1,"sequence":1}],"publisher_id":77,"source":"127.0.0.1:54425","writer_group":1,"writer_ids":[17]}]}}| 필드 | 의미 |
|---|---|
publisher_id |
NetworkMessage 헤더의 PublisherId(UInt16 77) |
writer_group |
WriterGroupId(1) |
writer_ids |
메시지에 든 DataSetWriterId 목록([17]) |
datasets[].sequence |
DataSetMessage의 시퀀스 번호 |
datasets[].major, minor |
구성 버전(ConfigurationVersion) |
datasets[].fields |
키 프레임의 필드 값 |
source |
메시지를 보낸 UDP 주소 |
2. 필드 직접 정하기
섹션 제목: “2. 필드 직접 정하기”fields에 타입과 값을 가진 필드를 1~64개 넣습니다.
{"action":"pubsub_publish","fields":[{"type":"Double","value":21.5},{"type":"String","value":"line-1"}]}{"ok":true,"result":{"bytes":53,"fields":2,"sequence":2}}상태를 확인합니다.
{"action":"pubsub_status"}{"ok":true,"result":{"acknowledged":0,"destination":"127.0.0.1:64578","dropped":0,"error":null,"listen":"127.0.0.1:64578","queued":1,"received":2,"rejected":0,"role":"both","running":true,"sent":2,"transport":"udp"}}sent와 received는 누적 개수, queued는 아직 꺼내지 않은 메시지 수입니다. rejected는 해석하지 못한 메시지 수입니다.
{"action":"pubsub_received"}{"ok":true,"result":{"messages":[{"bytes":53,"datasets":[{"fields":[{"type":"Double","value":21.5},{"type":"String","value":"line-1"}],"major":1,"minor":1,"sequence":2}],"publisher_id":77,"source":"127.0.0.1:54425","writer_group":1,"writer_ids":[17]}]}}PubSub을 멈추고 프로그램을 끝냅니다.
{"action":"pubsub_stop"}{"action":"shutdown"}3. 구독자 프로세스 실행
섹션 제목: “3. 구독자 프로세스 실행”이제 게시자와 구독자를 나눕니다. 첫 번째 터미널에서 시뮬레이터를 다시 실행합니다.
"$OPCUA_APPS/bin/pdcomm-opcua-headless"역할을 subscriber로, 수신 주소를 127.0.0.1:4840으로 설정합니다. 4840은 Part 14가 정한 opc.udp의 기본 포트입니다. 구성 일부만 넘기면 나머지는 기본값을 씁니다.
{"action":"configure","config":{"pubsub":{"role":"subscriber","listen":"127.0.0.1:4840"}}}{"action":"pubsub_start"}{"ok":true,"result":{"acknowledged":0,"destination":null,"dropped":0,"error":null,"listen":"127.0.0.1:4840","queued":0,"received":0,"rejected":0,"role":"subscriber","running":true,"sent":0,"transport":"udp"}}4. 게시자 프로세스 실행
섹션 제목: “4. 게시자 프로세스 실행”두 번째 터미널에서 시뮬레이터를 하나 더 실행합니다.
"$OPCUA_APPS/bin/pdcomm-opcua-headless"역할을 publisher로, 목적지를 구독자의 주소로 설정합니다.
{"action":"configure","config":{"pubsub":{"role":"publisher","destination":"127.0.0.1:4840"}}}{"action":"pubsub_start"}{"ok":true,"result":{"acknowledged":0,"destination":"127.0.0.1:4840","dropped":0,"error":null,"listen":null,"queued":0,"received":0,"rejected":0,"role":"publisher","running":true,"sent":0,"transport":"udp"}}{"action":"pubsub_publish","fields":[{"type":"Int32","value":5},{"type":"Boolean","value":false}]}{"ok":true,"result":{"bytes":40,"fields":2,"sequence":1}}5. 구독자에서 확인
섹션 제목: “5. 구독자에서 확인”첫 번째 터미널에서 받은 메시지를 꺼냅니다.
{"action":"pubsub_received"}{"ok":true,"result":{"messages":[{"bytes":40,"datasets":[{"fields":[{"type":"Int32","value":5},{"type":"Boolean","value":false}],"major":1,"minor":1,"sequence":1}],"publisher_id":77,"source":"127.0.0.1:53076","writer_group":1,"writer_ids":[17]}]}}6. 정리
섹션 제목: “6. 정리”두 터미널에 각각 입력합니다.
{"action":"shutdown"}{"ok":true,"result":{"client_closed":null,"pubsub_stopped":true,"server_stopped":false}}자주 생기는 오류
섹션 제목: “자주 생기는 오류”응답의 error |
원인과 조치 |
|---|---|
PubSub is already running |
이미 시작했습니다. 구성을 바꾸려면 pubsub_stop 뒤에 configure를 보냅니다. |
PubSub is not running |
pubsub_start 전에 pubsub_publish나 pubsub_received를 보냈습니다. |
UDP transport I/O: address in use (os error 48) |
수신 주소를 다른 프로그램이 쓰고 있습니다. 다른 포트를 쓰거나 그 프로그램을 끝냅니다. 오류 번호는 운영 체제마다 다릅니다. |
This PubSub connection has no publisher |
subscriber 역할에서 pubsub_publish를 보냈습니다. |
fields must be an array of 1 to 64 typed values |
fields가 비었거나 64개를 넘습니다. |
시뮬레이터는 UADP 메시지를 서명하거나 암호화하지 않습니다. 신뢰할 수 있는 네트워크에서만 씁니다. GUI에서는 PubSub 탭에서 같은 작업을 합니다.