콘텐츠로 이동
무료 평가 시작

시뮬레이터로 발행·구독

이 튜토리얼을 마치면 다음을 할 수 있습니다.

  • 시뮬레이터가 발행한 UADP 페이로드를 파일로 받아 구조를 확인합니다.
  • mosquitto_pub로 같은 페이로드를 다시 보내 시뮬레이터 구독자가 받게 합니다.
  • Content Type과 UAMessageType 속성이 없거나 다를 때 시뮬레이터가 메시지를 거부하는 모습을 확인합니다.

다른 시스템이 시뮬레이터로 데이터를 보내야 할 때 이 조건을 알아야 합니다.

  • 로컬 Mosquitto 브로커 실행에서 만든 mqtt-lab 디렉터리와 local.conf
  • PDComm OPC UA 시뮬레이터 패키지의 bin/pdcomm-opcua-headless
  • 터미널 창 3개
  1. 첫 번째 터미널의 mqtt-lab 디렉터리에서 브로커를 시작합니다.

    터미널 창
    mosquitto -c local.conf
  2. 두 번째 터미널에서 시뮬레이터 패키지 디렉터리로 이동해 헤드리스 시뮬레이터를 실행하고, 다음 두 줄을 붙여 넣습니다.

    터미널 창
    bin/pdcomm-opcua-headless
    {"action":"configure","config":{"pubsub":{"transport":"mqtt","role":"both","broker":"127.0.0.1:1883","topic":"opcua/uadp/data/77/demo"}}}
    {"action":"pubsub_start"}

    두 번째 줄의 결과에 "running":true가 있으면 시뮬레이터가 브로커에 연결해 opcua/uadp/data/77/demo를 구독한 상태입니다.

  3. 세 번째 터미널의 mqtt-lab 디렉터리에서 다음 메시지 하나를 파일로 받도록 기다립니다.

    터미널 창
    mosquitto_sub -V 5 -t opcua/uadp/data/77/demo -C 1 -N > dataset.bin

    -N은 페이로드 뒤에 줄바꿈을 붙이지 않으므로 파일에 페이로드 바이트만 남습니다.

  4. 두 번째 터미널에서 DataSet 하나를 발행합니다.

    {"action":"pubsub_publish","fields":[{"type":"Int32","value":42},{"type":"String","value":"hello"}]}
    {"ok":true,"result":{"bytes":48,"fields":2,"sequence":1}}

    세 번째 터미널의 mosquitto_sub가 메시지를 받고 끝납니다. 파일 내용을 확인합니다.

    터미널 창
    xxd dataset.bin
    00000000: f101 4d00 0f01 0001 0000 0001 0001 0001 ..M.............
    00000010: 1100 7901 0000 0001 0000 0001 0000 0002 ..y.............
    00000020: 0006 2a00 0000 0c05 0000 0068 656c 6c6f ..*........hello

    UADP는 little-endian입니다. 4d 00은 PublisherId 77, 11 00은 DataSetWriterId 17입니다. 끝부분의 06 2a 00 00 00은 Int32 값 42, 0c 05 00 00 00 68 65 6c 6c 6f는 String 값 hello입니다.

  5. 두 번째 터미널에서 시뮬레이터가 받은 메시지를 꺼내 대기열을 비웁니다.

    {"action":"pubsub_received"}

    messages에 방금 발행한 메시지가 하나 있습니다. 비어 있으면 한 번 더 실행합니다.

  6. 세 번째 터미널에서 속성 없이 같은 페이로드를 발행합니다.

    터미널 창
    mosquitto_pub -V 5 -q 1 -t opcua/uadp/data/77/demo -f dataset.bin

    두 번째 터미널에서 상태를 확인합니다.

    {"action":"pubsub_status"}
    {"ok":true,"result":{"acknowledged":1,"broker":"127.0.0.1:1883","destination":null,"dropped":0,"error":"OPC UA PubSub Malformed","listen":null,"queued":0,"received":1,"rejected":1,"role":"both","running":true,"sent":1,"topic":"opcua/uadp/data/77/demo","transport":"mqtt"}}

    페이로드는 올바른 UADP지만 MQTT 5.0 메시지에 Content Type과 UAMessageType이 없으므로 rejected가 1이 되고 error가 OPC UA PubSub Malformed입니다.

  7. 이번에는 두 속성을 붙여 발행합니다.

    터미널 창
    mosquitto_pub -V 5 -q 1 -t opcua/uadp/data/77/demo \
    -D publish content-type application/opcua+uadp \
    -D publish user-property UAMessageType ua-data \
    -f dataset.bin

    -D publish <속성> <값>은 PUBLISH 패킷에 MQTT 5.0 속성을 붙입니다. 두 번째 터미널에서 확인합니다.

    {"action":"pubsub_received"}
    {"ok":true,"result":{"messages":[{"bytes":48,"datasets":[{"fields":[{"type":"Int32","value":42},{"type":"String","value":"hello"}],"major":1,"minor":1,"sequence":1}],"publisher_id":77,"source":"mqtt","writer_group":1,"writer_ids":[17]}]}}

    같은 바이트를 다시 보냈으므로 순번(sequence)도 1 그대로입니다. 받는 쪽은 순번으로 다시 보낸 메시지를 구별할 수 있습니다.

  8. 속성 값이 맞지 않는 두 경우를 확인합니다.

    터미널 창
    mosquitto_pub -V 5 -q 1 -t opcua/uadp/data/77/demo \
    -D publish content-type application/json \
    -D publish user-property UAMessageType ua-data \
    -m '{}'

    {"action":"pubsub_status"}의 error는 OPC UA PubSub Conflict입니다. Content Type이 이 구독의 인코딩(UADP)과 다릅니다.

    터미널 창
    mosquitto_pub -V 5 -q 1 -t opcua/uadp/data/77/demo \
    -D publish content-type application/opcua+uadp \
    -D publish user-property UAMessageType ua-data \
    -m hello

    이번에는 error가 OPC UA PubSub Unsupported이고 rejected가 3입니다. 속성은 맞지만 페이로드가 UADP NetworkMessage가 아닙니다.

  1. 두 번째 터미널에서 {"action":"shutdown"}을 보내 시뮬레이터를 끝냅니다.
  2. 첫 번째 터미널의 브로커를 Ctrl+C로 끝냅니다.
  3. dataset.bin은 필요 없으면 지웁니다.
error 뜻
OPC UA PubSub Malformed Content Type이나 UAMessageType이 없거나 형식이 틀렸습니다.
OPC UA PubSub Conflict 속성 값이 이 구독의 인코딩(UADP)이나 메시지 종류(ua-data)와 다릅니다.
OPC UA PubSub Unsupported 페이로드를 UADP NetworkMessage로 해석할 수 없습니다.

전체 목록은 전달 문제에 있습니다.