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'를 실행한 모든 창에 메시지가 수신되게 된다.

댓글 2개:

  1. 안녕하세요.
    aws로 서버를 구축해서 docker로 mqtt를 해보려 하는 도중에 참고하여 잘 봤습니다.
    putty로 해서 서버에 접근을 하고 있는데요...
    pub.py와 sub.py를 둘 다 파일을 만들었습니다.
    그런데 python sub.py를 하고 다른 터미널 차에 python pub.py를 실행해 보면 된다고 하셨는데..
    같은 서버에서 터미널만 2개를 켜서 하면 되어야 하지 않나요??
    sub.py를 실행시키면 Connected with result code 0 와 같이 나오기만 하고 다른건 안되고
    다른 터미널에서 pub.py를 치면 아무런 변화가 없는데 어떻게 해야 통신이 되는건가요?? ㅜ

    답글삭제
    답글
    1. 어느 버젼에서 바뀌었는지 확인해 봐야겠지만 on_connect()의 함수 프로토타입이 바뀌었네요.

      def on_connect(client, userdata, rc): <- 이 줄을 다음과 같이 바꿔주시면 제대로 동작할겁니다.

      def on_connect(client, userdata, flags, rc):

      삭제