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

2017년 5월 11일 목요일

라즈베리 파이에서 MQTT를 이용해 ESP8266 제어하기

여기서는 라즈베리 파이, ESP8266(또는 와이파이 쉴드를 붙인 아두이노), PC를 MQTT로 연결해 보도록 하겠다.

이번에 하고자 하는 것은 라즈베리파이가 python을 사용해 PC에 있는 MQTT 브로커에 메시지를 보내면 그 메시지가 ESP8266으로 전달되어 거기에 있는 LED를 제어하는 것이다.

MQTT for PC


MQTT server(브로커)로 사용할 수 있는 옵션이 몇가지 있다. Amazon의 AWS IoT나 AdafruitIO 같은 서비스들은 클라우드 기반의 브로커이다. 각 서비스는 여러가지 장점이 있다. 프로젝트의 필요성에 따라 클라우드 기반 서비스를 사용할 필요가 있을수도 있다.

Mosquitto


자신의 호스트에 브로커를 실행하고 싶으면 오픈소스인 moqsuitto가 훌륭한 옵션이다. 이 브로커는 MQTT를 완전히 지원할 뿐 아니라 pub/sub를 위한 커맨드라인 유틸리티까지 제공한다.

윈도우를 사용하면 mosquitto.org에서 바이너리 인스톨러를 받을 수 있다. 리눅스의 경우 패키지 매니져에서 'mosquitto' 또는 'mosquitto-mqtt'를 찾으면 된다. 맥에서는 homebrew를 사용해 mosquitto를 설치할 수 있다.

* 맥에서 설치한 경우 '/usr/local/sbin'을 PATH에 넣어줘야 한다.

Running Mosquitto


Mosquitto는 디폴트로 1883번 포트를 사용하고 보안기능은 다 꺼져 있다. 처음 시작할 때는 이것으로 충분하지만 결국에는 보안기능을 추가해 줄 필요가 있다.

Mosquitto를 verbose 모드로 실행하길 권장한다. 그러면 출력을 보고 어떤 일이 일어나는지에 대한 아이디어를 얻을 수 있을 것이다.

MacMan:~ james$ mosquitto -v 
1456272937: mosquitto version 1.4.5 (build date 2015-11-09 14:23:46-0800) starting 1456272937: Using default config. 
1456272937: Opening ipv4 listen socket on port 1883. 
1456272937: Opening ipv6 listen socket on port 1883.

Testing Mosquitto


서버 코드를 verbose 모드에서 실행시키고, 추가로 두개의 명령어 프롬프트를 열어준다. 각각의 명령어 프롬프트에서 메시지 전송 테스트를 위해 mosquitto_pub와 mosquitto_sub를 사용할 것이다.

Subscribing to MQTT Topic with Mosquitto


먼저 클라이언트가"debug"라는 토픽을 subscribe하게 해 준다. 첫번째 명령어 프롬프트에서 아래 명령을 입력해 주면 된다.

$ mosquitto_sub -h 127.0.0.1 -i testSub -t debug

* -h : host flag는 mosquitto가 실행되고 있는 서버를 지정. 여기서는 localhost
* -i : identity flag 는 옵션이다. Client ID가 지정되지 않으면 mosquitto_sub가 임의로 만듬
* -t : topic flag 는 subscribe 하려고 하는 topic을 지정. 여기서는 "debug"

서버에서는 topic을 만들지 않았다는걸 주목해라. Topic은 subscriber나 publisher가 처음 지정할 때 만들어진다.

Publish to MQTT Topic with Mosquitto


이제 topic을 기다리는 클라이언트를 가지고 있으므로, 다른 클라이언트가 그 topic을 publish하게 해 본다.

$ mosquitto_pub -h 127.0.0.1 -i testPublish -t debug -m 'Hello World'


이제 첫번째 명령어 프롬프트 화면을 보면 publish된 메시지가 와 있는것을 확인할 수 있다. mosquitto_pub와 mosquitto_sub 명렁 모두 --help 플래그로 확인 해 봐라. 매우 여러가지 유용한 옵션들을 찾아볼 수 있을 것이다.

이제 mosquitto 브로커가 정상 동작하고 있는것이 확인되었으므로 디바이스와 통신을 하게 해 보자.

MQTT for Raspberry Pi (Python)


라즈베리 파이에서 MQTT 메지시를 보내고 받을 수 있는 옵션으로는 mosquitto를 설치하는 것이다. 그러면 라즈베리 파이에서도 동일하게 mosquitto_pub와 mosquitto_sub 명령어를 사용할 수 있다.

다른 방법으로는 자신이 선호하는 언어용 MQTT 라이브러리를 사용하는 것이다. 여기서는 파이선을 사용한다.

Install MQTT for Python


여기서 사용할 MQTT library는 Paho Python Client이다. 오픈소스로 가장 최신의 MQTT를 지원한다.

설치는 간단하다. 먼저 'pip'를 설치하고 나서 아래 명령을 실행한다.

$ pip install paho-mqtt

* 만일 python3를 사용한다면 'pip' 대신 'pip3'를 사용해야 하는걸 잊지 마라.

Example MQTT Python Code for Raspberry Pi


Paho는 MQTT 서버와 통신을 매우 쉽게 만들어 준다.

import paho.mqtt.publish as publish
import time
print ("Sending 0...")
publish.single("ledStatus", "0", hostname="macman")
time.sleep(1)
print ("Sending 1...")
publish.single("ledStatus", "1", hostname="macman")

진짜 간단하다. 스크립트에 서버가 실행되고 있는 호스트 이름(여기서는 'macman'), Topic (여기서는 'ledStatus'), 메시지(여기서는 '0' 또는 '1')만 알려주면 된다.

이 MQTT 튜토리얼 예제에서는 '0'을 보내고 1초 기다린 후에 '1'을 보낸다. 이 동작은 ESP8266에 있는 LED가 잠깐동안 꺼졌다 다시 켜지게 만든다.


이제 RPi가 MQTT 메시지를 보내게 만들었으니 그 메시지를 받도록 만들어 보자. 다음 섹션은 ESP8266이 topic "ledStatus"의 메시지를 받아 실제로 LED를 깜빡이게 만들 것이다.

MQTT for ESP8266


PubSubClient는 아두이노 기반의 MQTT 클라이언트이다. 단지 몇 줄의 코드만으로 매우 쉽게 topic을 subscribe하거나 새로운 topic을 publish할 수 있다.

여기서는 ESP8266을 프로그래밍 하기 위해 아두이노 IDE를 사용했다.

Installing MQTT for Arduino IDE


아두이노 IDE에 PubSubClient를 설치하는건 간단하다. Github에서 수동으로 설치하거나 또는 Arduino Package Installer를 사용할 수 있다.


Arduino ESP8266 and Uno Note


Ethernet 쉴드가 장착된 Uno와 ESP8266간에 스위칭에는 별도의 추가적인 노력이 필요 없다. 라이브러리는 양쪽 모두 잘 동작한다.

Code Example for Arduino MQTT


PubSubCilent에 포함되어 있는 예제는 매우 훌륭하다. 예제에는 특히 MQTT에 대한 ESP8266 코드도 들어있다. 처음 시작할 때 그것들도 꼭 확인해 보기 바란다.

아래는 WiFi에 연결하고 "ledStatus" topic을 subscribe하는 코드이다. ESP8266이 메시지를 받으면 그에 따라 ledPin을 on/off한다.

#include <EEPROM.h>
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <Wire.h>
#include <Adafruit_INA219.h>

// Connect to the WiFi
const char* ssid = "Dear John";
const char* password = "password123";
const char* mqtt_server = "macman";

WiFiClient espClient;
PubSubClient client(espClient);

const byte ledPin = 0; // Pin with LED on Adafruit Huzzah

void callback(char* topic, byte* payload, unsigned int length) {
 Serial.print("Message arrived [");
 Serial.print(topic);
 Serial.print("] ");
 for (int i=0;i<length;i++) {
  char receivedChar = (char)payload[i];
  Serial.print(receivedChar);
  if (receivedChar == '0')
  // ESP8266 Huzzah outputs are "reversed"
  digitalWrite(ledPin, HIGH);
  if (receivedChar == '1')
   digitalWrite(ledPin, LOW);
  }
  Serial.println();
}


void reconnect() {
 // Loop until we're reconnected
 while (!client.connected()) {
 Serial.print("Attempting MQTT connection...");
 // Attempt to connect
 if (client.connect("ESP8266 Client")) {
  Serial.println("connected");
  // ... and subscribe to topic
  client.subscribe("ledStatus");
 } else {
  Serial.print("failed, rc=");
  Serial.print(client.state());
  Serial.println(" try again in 5 seconds");
  // Wait 5 seconds before retrying
  delay(5000);
  }
 }
}

void setup()
{
 Serial.begin(115200);

 client.setServer(mqtt_server, 1883);
 client.setCallback(callback);

 pinMode(ledPin, OUTPUT);
}

void loop()
{
 if (!client.connected()) {
  reconnect();
 }
 client.loop();
}


모든 마법은 "callback" 함수 안에서 일어난다. 실제 코드에서는 받은 메시지를 처리하는 함수를 작성하고 싶을 것이다. 여기서는 topic에 대해 한글자 메시지만을 보내기 때문에 이 간단한 코드로 충분하다.

Conclusion


이 MQTT 튜토리얼은 매우 기초적이다. 하지만 라즈베리 파이, ESP8266을 MQTT 브로커가 실행되고 있는 PC에 연결하는데 필요한 최소한의 것을 보여준다.

다음에는 MQTT를 통해 어떻게 더 복잡한 메시지를 보낼 수 있는가를 설명하겠다.




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 …