레이블이 MQTT broker인 게시물을 표시합니다. 모든 게시물 표시
레이블이 MQTT broker인 게시물을 표시합니다. 모든 게시물 표시

2015년 4월 2일 목요일

파이선으로 만들어보는 간단한 MQTT 클라이언트

MQTT 브로커는 mosquitto나 rsmb같이 무료로 쉽게 구해 설치할 수 있다. 하지만 아직 설치하지 않았다면 테스트를 위해 공개되어 있는 브로커를 사용해도 된다.
공개 브로커 목록은 http://mqtt.org/wiki/doku.php/public_brokers 에서 확인할 수 있다.

MQTT 클라이언트는 publisher이건 subscriber이건 모두 다 브로커에 연결해야 한다. 브로커를 누구나 글을 붙이거나 읽을 수 있는 일종의 공개 게시판이라고 생각하면 된다.

여기서는 파이선 2.7을 사용해 간단한 MQTT 클라이언트를 만들어 MQTT 프로토콜을 직접 사용해 보도록 한다.



1. 인스톨

pip가 설치되어 있어야 한다. pip는 파이선 모듈을 설치하는데 귀찮은 문제들을 손쉽게 해결해주는 툴이다. 만일 설치되어 있지 않다면 아래 명령으로 pip를 설치한다.

$ sudo apt-get install python-pip

다음은 MQTT broker Mosquitto (지금은 Paho로 이름이 바뀌었음)

$ pip install paho-mqtt

2. Subscribe

아래는 로컬 머신에서 실행되고 있는 브로커에 토픽을 구독(subscribe)하기 위한 파이선 코드이다.

$ cat sub.py
import paho.mqtt.client as mqtt

# 클라이언트가 서버에게서 CONNACK 응답을 받을 때 호출되는 콜백
def on_connect(client, userdata, flags, rc):
  print ("Connected with result coe " + str(rc))
  client.subscribe("hello/world")

# 서버에게서 PUBLISH 메시지를 받을 때 호출되는 콜백
def on_message(client, userdata, msg):
  print "Topic: ", msg.topic + '\nMessage: ' + str(msg.payload)

client = mqtt.Client()        # MQTT Client 오브젝트 생성
client.on_connect = on_connect     # on_connect callback 설정
client.on_message = on_message   # on_message callback 설정

client.connect("test.mosquitto.org", 1883, 60)   # MQTT 서버에 연결

# 네트웍 트래픽을 처리, 콜백 디스패치, 재접속 등을 수행하는 블러킹 함수
# 멀티스레드 인터페이스나 수동 인터페이스를 위한 다른 loop*() 함수도 있음
client.loop_forever()
$


3. Publish

이제 /hello/world 토픽을 구독(subscribe)해서 해당 토픽의 메시지가 publish(발행)되기를 기다리는 노드를 만들었다. 아래 코드는 /hello/world 토픽으로 메시지를 발행하는 간단한 코드이다.

$ cat pub.py
import paho.mqtt.client as mqtt

mqttc = mqtt.Client("python_pub")      # MQTT Client 오브젝트 생성
mqttc.connect("test.mosquitto.org", 1883)    # MQTT 서버에 연결
mqttc.publish("hello/world", "Hello World!")  # 'hello/world' 토픽에 "Hello World!"라는 메시지 발행
mqttc.loop(2)        # timeout = 2초
$

4. 테스트

2번의 코드를 'sub.py'라는 이름으로 저장하고 3번의 코드를 'pub.py'라는 이름으로 저장했다면 터미널 창에서 'python sub.py'로 sub.py를 실행하고, 다른 터미널 창에서 'python pub.py'로 pub.py를 실행해 보면 sub.py를 실행한 창에 수신된 메시지가 표시되는걸 확인할 수 있을 것이다.

MQTT는 클라이언트/서버 모델처럼 publisher와 subscriber간에 1:1 연결이 아니기 때문에 여러 창에서 'sub.py'를 실행하고 난 후 'pub.py'를 실행하면 'sub.py'를 실행한 모든 창에 메시지가 수신되게 된다.

2015년 3월 23일 월요일

MQTT(Message Queue Telemetry Transport) 소개

Introduction

MQTT(Message Queue Telemetry Transport) 프로토콜은 기계간 통신(M2M)/IoT를 위한 프로토콜이다. HTTP의 request/response 방식 대신 브로커를 사용한 publish/subscribe 방식으로 메시지를 주고 받는다. 물론 MQTT 역시 HTTP와 마찬가지로 TCP/IP 프로토콜 위에서 동작한다. 이 프로토콜의 첫번째 버젼은 1999년 Andy Stanford-Clark와 Arlen Nipper에 의해 발표되었다. 2013년 IBM이 OASIS 표준화 기구에 MQTT v3.1을 제출하여 승인받았다. 또한 비 TCP/IP 네트웍 상에서 동작하는 MQTT의 변종도 존재한다. MQTT-SN은 ZigBee 기반 네트웍 상에서 사용된다.
MQTT는 최소한의 프로토콜 오버헤드만으로 동작할 수 있기 때문에 임베디드 시스템같이 한정된 자원을 가진 시스템이나 저대역폭(low bandwidth) 또는 불안정한 네트웍 환경에서도 사용할 수 있다. 또한 다양한 언어를 지원하는 라이브러리들이 공개되어 있다. mbed에서라면 mbed MQTT library, 아두이노에서는 arduino client for MQTT를 사용할 수 있다.
이 기술이 특히 흥미로운 것은 모든 데이터를 단일 transport 메커니즘으로 처리한다는 것이다. 즉 특정 서비스를 위해 각각 따로 방화벽을 설정할 필요 없이, 단일 TCP 포트만으로 모든 종류의 메시지를 전달하는데 충분하다.



MQTT에서 publish/subscribe를 위한 메시지 큐를 '네트웍의 트위터'라고 생각할 수도 있다. 클라이언트는 특정 토픽에 대한 메시지를 수신하기 위해 토픽을 구독(subscribe)하고, 다른 클라이언트는 그 토픽에 대한 메시지를 발행(publish)한다. 메시지들은 토픽으로 분류된다. 예를들어 nagios/mta, nagios/disk, test/kr/private 같은 식의 토픽을 가질 수 있다. 클라이언트는 임의 갯수의 토픽을 구독할 수 있고, 구독할 토픽에 와일드카드를 포함할 수도 있다. (예: nagios/#) MQTT에서 메시지는 최대 256MB 크기의 UTF-8 BLOB이다.

Publish/Subscribe 모델


MQTT는 일반적으로 웹에서 사용되는 client/server 모델 대신 publish/subscribe(발행/구독) 모델을 사용한다. Client/server 모델에서는 클라이언트가 그 상대방이 되는 서버와 직접 통신을 하게 된다. 하지만 publish/subscribe 모델은 특정 메시지를 보내는 클라이언트(즉 publisher)와 그 메시지를 받는 다른 클라이언트들(즉 subscriber)를 분리시켜 서로는 상대방의 존재 여부를 모른다. 그러므로 통신을 하기 위해서는 publisher와 subscriber 양측이 모두 다 알고 있는 broker라 불리는 3번째 컴포넌트가 필요하게 된다. (publisher건 subscriber건) 모든 클라이언트는 브로커와 통신을 하고, 브로커는 자신이 받은 메시지들을 필터링 해 적절하게 분배하게 된다.



위의 그림에서 온도센서가 publisher, 랩탑과 스마트폰이 subscriber, HiveMQ가 MQTT 브로커가 된다. Subscriber들이 구독하길 원하는 토픽(여기서는 'temperature')이 있으면 그 토픽에 대해 브로커에게 구독신청(subscribe)을 한다. 그 후 온도센서가 측정한 온도값을 'temperature'라는 토픽으로 브로커에게 발행(publish)하게 된다. MQTT 브로커는 'temperature' 토픽에 대한 메시지를 받으면 해당 토픽을 구독하고 있는 subscriber들(여기서는 랩탑과 스마트폰)에게 이 메시지를 전달해준다. 토픽을 구독하는 클라이언트는 여러대가 될 수도 있다. 이 경우 publisher는 자신이 발행한 토픽을 구독한 subscriber가 몇개인지 신경 쓸 필요가 없다. (해당 토픽을 구독한 subscriber가 하나도 없을수도 있다.) 메시지는 브로커를 통해 전달되기 때문에 publisher와 subscriber는 서로의 IP주소와 포트를 알고 있을 필요도 없고, 서로 동시에 실행되고 있을 필요도 없다.

QoS (Quality of Service)


모든 메시지는 QoS값을 가지고 publish 된다. MQTT에는 3가지 QoS 타입이 있다.

  • QoS_0 - "At most once" TCP/IP 네트웍 상에서 최대의 노력을 기울여 메시지가 전달되도록 함. 하지만 메시지가 중복되거나 분실될 수도 있음. 센서값이 한번 분실되어도 금새 다음번 값을 publish하기 때문에 분실되는 것이 큰 문제가 되지 않는 경우에 사용
  • QoS_1 - "At least once" 메시지가 전달되는걸 보장. 하지만 이로 인해 중복이 발생할 수도 있음
  • QoS_2 - "Exactly once" 메시지가 한번만 전달되는걸 보장. 과금 정보처럼 메시지 분실이나 중복이 문제를 발생시킬 수 있는 경우에 사용


Scalability


그리고 publish/subscribe 모델은 기존의 client/server 모델에 비해 훨씬 더 큰 확장성을 가지고 있다. 브로커의 동작이 event-driven 방식이기 때문에 쉽게 병렬화가 가능하기 때문이다. 또한 메시지 캐슁과 지능적 라우팅이 확장성을 증가시키는데 결정적이다. 하지만 publish/subscribe를 동시에 수백~수천만개를 처리하도록 확장시키는건 역시 큰 문제이다. 하지만 이 경우도 클러스터 브로커 노드를 상요해 개별 서버의 로드를 로드밸런싱 하는 것으로 해결할 수 있다.

2015년 3월 5일 목요일

Raspberry Pi에 Mosquitto (MQTT broker) 설치하기

IoT에서 많이 이야기되고 있는 MQTT를 사용하려면 브로커가 있어야만 한다. 오픈소스로 쉽게 사용할 수 있는 브로커로 Mosquitto가 있다. (모기와는 스펠링이 아주 조끔 다름)



라즈베리 파이에 설치하는 경우 mosquitto의 개발자인 Roger Light이 Mosquitto Debian Repository를 만들어 놓았기 때문에 이를 이용하면 손쉽게 최신버젼을 설치할 수 있다. 먼저 repository를 추가해 줘야 한다.

$ curl -O http://repo.mosquitto.org/debian/mosquitto-repo.gpg.key
$ sudo apt-key add mosquitto-repo.gpg.key
$ rm mosquitto-repo.gpg.key
$ cd /etc/apt/sources.list.d
$ sudo curl -O http://repo.mosquitto.org/debian/mosquitto-repo.list

$ sudo apt-get update

이제 repository가 추가되었으니 mosquitto를 설치하면 된다. mosquitto, mosquitto-clients, python-mosquitto 3개의 패키지가 있고 전부 설치해도 약 665KB의 공간만을 차지하기 때문에 설치하는데 공간 부담은 별로 없다.

* mosquitto : MQTT 브로커
* mosquitto-clients : 커맨드라인 클라이언트
* python-mosquitto : python binding

apt-get으로 설치하면 된다.


$ sudo apt-get install mosquitto mosquitto-clients python-mosquitto

설치가 완료되면 mosquitto가 자동으로 실행된다.

설정을 변경하고 싶으면 먼저 mosquitto의 실행을 중단시킨다.

$ sudo /etc/init.d/mosquitto stop

이제 원하는대로 설정을 변경하면 된다. 설정파일은 디폴트로 /etc/mosquitto/mosquitto.conf 가 된다. 설정을 변경했으면 제대로 동작하는지 확인해 볼 수 있다.

$ sudo /usr/bin/mosquitto -c /etc/mosquitto/mosquitto.conf
1378042632: mosquitto version 1.2 (build date 2013-08-09 21:49:03+0100) starting
1378042632: Config loaded from /etc/mosquitto/mosquitto.conf.
1378042632: Opening ipv4 listen socket on port 1883.
1378042632: Opening ipv4 listen socket on port 8883.
1378042632: Opening ipv6 listen socket on port 8883.
1378042632: Warning: Address family not supported by protocol ...^C 1
378042634: mosquitto version 1.2 terminating

1378042634: Saving in-memory database to /tmp/mosquitto.db.

원하는대로 설정이 된것이 확인되었으면 다시 서비스를 시작시키면 된다.

sudo /etc/init.d/mosquitto restart

이제 MQTT publisher/subscriber가 브로커를 사용할 수 있다.

만일 TLS를 사용하도록 설정해 놓은 경우 mosquitto 클라이언트는 CA certificate(ca.cert)의 복사본을 가지고 있어야만 브로커에 억세스 할 수 있다. ca.cert는 public certificate이기 때문에 암호화 하지 않고 전달해도 상관없다.


$ mosquitto_pub —cafile ca.cert -h 127.0.0.1 -p 8883 …

새 버젼인 mosquitto 1.2 클라이언트는 디폴트로 TLS v1.2를 사용하기 때문에 TLS v1을 사용하도록 하려면 옵션을 추가해 줘야 한다.


$ mosquitto_pub —cafile ca.cert -h 127.0.0.1 -p 8883 —tls-version tlsv1 …