Aug 18, 2014

[IBM IoT Foundation Bootcamp @Korea] 3. MQTT Based Messaging

MQ Telemetry Transport (MQTT)
IoT Cloud가 제공하는 Device Connectivity는 MQTT 3.1.1을 표준 규격을 따르고 있다. MQTT는 기본적으로 아래 다이어그램에서 도식화한 Publish/Subscribe(PubSub) 방식의 메시징 규격이다.



Topic
  • Device로부터 data를 수신하기 위한 subscribe topic 형식은 다음과 같다.
    • iot-2/type/<type-id>/id/<device-id>/evt/<event-id>/fmt/<format-id>
  • IoT Cloud에 connect된 device로 command를 보내기 위한 publish topic 형식은 다음과 같다.
    • iot-2/type/<type-id>/id/<device-id>/cmd/<command-id>/fmt/<format-id>
  • Device가 IoT Cloud에 connect되었는지 disconnect되었는지 IoT Cloud의 system level에서 관리하고 이를 service application에서 알 수 있도록 publish하고 있다. 이에 subscribe하기 위한 topic 형식은 다음과 같다.
    • iot-2/type/<type-id>/id/<device-id>/mon
  • iot-2라는 topic의 root context 명 이후는 /key/value/ 형태의 key-value pair (KVP) 반복 구조로 정의한다.
  • KVP 구조에서 value에 해당하는 <type-id>, <device-id>, <event-id>, <command-id>, <format-id>는 최대 길이 제한 32의 문자열이어야 하며, 문자열 구성은 영문 대소문자, 숫자, '_', '-', '.'의 3개 기호 문자가 허용된다.
    • <type-id>: Device type을 정의하는 것으로 예를 들어 Galileo device는 'iotsample-galileo', Raspberry Pi는 'iotsample-raspberrypi'로 정의한다.
    • <device-id>: 각 device의 고유 MAC 주소값을 사용하며, ':'를 제외한 hex code값을 공백없이 붙이고 hex code값 중 영문 알파벳 해당값은 소문자로 맞추어 주어야 한다.
    • <event-id>: event code 명을 정의할 때 사용하며, 대표적인 것으로 'status'가 있다.
    • <command-id>: command code 명을 정의할 때 사용하며, 대표적인 것으로 'reboot', 'start', 'stop' 등이 있다.
    • <format-id>: IBM IoT Cloud는 송수신 데이터의 포맷으로 원칙적으로 다양한 형태를 지원하지만 JSON 사용을 권장하고 있다. 따라서, 대부분의 경우 'json'으로 정의하여 사용한다.
  • Value 문자열 대신 all을 의미하는 wildcard 문자로 대치할 수 있으며, '+'가 이를 위하여 reserve되어 있다.
  • /type/<type-id>/id/<device-id>를 생략한 축약형도 사용 가능하다. 예를 들어 모든 event를 subscribe하여 수신하고자 하는 경우에 'iot2/evt/+/fmt/json'로 topic을 설정할 수 있다.

Client ID
  • [Naming Convention] Broker에 연결하려는 client가 device인 경우는 'd:'를 Bluemix application인 경우는 'a:'를 사용한다.
  • Client ID는 MQTT connection 간에 중복 공유되지 않도록 신경써야 한다. 만일 두 MQTT connection이 동일한 Client ID를 사용한다면 시간 상으로 앞에 만들어진 connection이 그 뒤에 만들어지는 connection과 Client ID가 동일하다는 이유로 connection이 강제로 끊어지게 된다.

MQTT Transport Port Number
  • Internet Assigned Numbers Authority(IANA)에 의해 TCP 포트번호 1883이 MQTT 용도로 포트번호 8883이 MQTT over SSL/TLS 용도로 정의되어 있다. 

MQTT Client on the Galileo
  • Module dependency는 MQTT 프로토콜 처리를 위한 'mqtt', 로컬 파일 시스템 액세스를 위한 'fs'에 있다.
  • 설정 정보는 "device.cfg"의 디바이스 로컬 파일 형태로 관리한다.
  • Broker server의 URL은 디폴트 초기값으로 "quickstart.messaging.internetofthings.ibmcloud.com"를 사용하는데 이는 IoT Cloud에 등록하지 않은 디바이스에 대한 messaging test를 수행하는 Quickstart를 가정한 것이다.


  • Node.js의 'getmac' 모듈을 이용해서 디바이스의 MAC 주소를 읽은 후 ':'는 제거하고 hexa code 중 ABCDEF는 abcdef로 강제 변환한다.

  • Node.js의 'properties' 모듈을 이용해서 device.cfg에 정의되어 있는 "key:value" 형식의 설정값들을 읽어 들여 options 객체에 저장한다.
  • IoT Cloud에 디바이스 등록을 마치고 device.cfg에 "organization" property를 정의한 경우는 Broker server의 URL이 이에 맞게 변경된다.

  • Client ID는 device를 의미하는 'd'를 prefix로 사용하고 organization, device type, MAC address로 구성된 문자열을 사용함으로써 다른 ID와 겹치지 않게 유일성을 보장한다.
  • IoT Cloud로 publish하기 위한 topic은 "iot-2/evt/status/fmt/json"을 사용하고 1초 주기로 디바이스의 상태 정보를 수집하여 IoT Cloud로 송신한다.
  • 반대로 IOT Cloud에서 송신한 메시지를 수신하기 위하여 "iot-2/cmd/+/fmt/json"의 topic을 사용해서 subscribe한다.
  • IoT Cloud로부터 메시지를 수신할 때 디바이스의 MQTT Client Module에서는 "message" 이벤트가 발생한다. "message" 이벤트 처리 callback에서는 console에 log를 출력하고 수신한 메시지에 "send-status" property가 있는지 검사하여 그 값에 따라 주기적으로 상태 정보를 송신할 것인지 정보 송신을 중단할 것인지에 대한 action을 수행한다.


  • 앞에서 "iot-2/evt/status/fmt/json"을 이용해서 IoT Cloud로 주기적으로 메시지 송신하는 기능이 구현되어 있는데 메시지를 구성하는 것에 대한 것은 아래와 같이 "sys/class/thermal/thermal_zone0/temp" 파일을 읽어서 획득한 CPU 온도 값을 보내는 함수를 사용한다.


ibm-iot-quickstart.js를 실행하면 코드 내에 넣어 놓은 console.log()를 수행한 결과로 다음과 같은 정보를 확인할 수 있다.
  • protocolId: MQIsdp(MQ Integrator SCADA Device Protocol)
  • clean: true -- MQTT CleanSession flag


No comments:

Post a Comment