다양한 WiFI 통신 예제 중에서 Thingspeak의 MQTT방식에 의한 아두이노 통신 예제를 살펴본다. 우선 MQTT방식에 대해서 간단히 살펴보기로 한다. 지금까지 블로그에 주어진 예제들은 다 클라이언트와 서버와의 정확한 1:1 매칭관계를 기반으로 프로그래밍을 하였으나 그렇치 않은 사례들이 있다.
MQTT 방식을 설명할 수 있는 대표적인 사례로서 유튜브를 들 수 있다. 유튜브에 들어가 보면 많은 동영상들이 업로드 되어 있음을 볼 수 있다. 즉 많은 클라이언트들이 자신의 동영상을 준비하여 업로드 시켜 누구든지 선택해 볼 수 있도록 공개해 놓은 것이다.
유튜브 개인 사용자들은 유튜브 화면에서 입맛에 맞는 동영상을 클릭하여 다운로드하여 볼 수가 있는데 여기서 유튜브 동영상 제작자와 이를 보는 개인 사용자들은 서로 다른 주체들이다. 즉 동영상을 준비하여 올리는 사람들은 Publisher로서 출판하는 사람들이며 그리고 유튜브 사이트에서 동영상을 선택 다운해서 보는 사람들은 구독자로서 즉 Subscriber이다. 구독자는 임의로 한편 두편 만 보고 끝나는 구독자도 있으며 별도로 특정 Publisher의 동영상을 지속적으로 정기 구독하는 경우도 있을 수 있다.
결국 유튜브 처럼 업로드된 동영상들을 정리하여 많은 소비자들에게 보여주고 시청하도록 중계 작업을 수행 하는데 이러한 사이트를 단순 서버가 아니라 브로커 역할 즉 중계 역할을 하는 브로커 서버라고 한다.
사물인터넷을 지원하는 Thingspeak 사이트에도 mqtt.thingspeak.com이 전용 브로커로서 이러한 MQTT 방식을 지원하고 있다. 하지만 Thingspeak 사이트에 의하면 Publish 기능만 지원하고 Subscribe 는 지원하지 않는 다는 점을 밝히고 있으니 유의하기 바란다.
따라서 이번 예제를 통해 MQTT의 Publish 특성을 잘 이해하고 난 후에도 Subscribe 과정을 포함하는 보다 일반적인 MQTT 방식 프로그래밍에 대한 관심이 필요할 것이다.
하지만 인터넷에 유포된 많은 예제들이 아두이노 프로그래밍의 범위를 벗어나는 듯 하며 적어도 라즈베리 파이의 리눅스라든지, 자바 및 자바스크립트를 포함하는 등의 상당한 수준의 프로그래밍 능력이 필요해 보인다. 따라서 이 블로그에서는 아두이노 프로그램 능력으로 커버할 수 있는 범위까지에 집중하기로 한다.
참고로 MQTT 방식을 사용하여 자신의 아두이노 보드의 LED를 ON OFF 하는 예제들이 더러 있는데 이는 Webserver 예제로서는 적합하나 MQTT 예제로는 어울리지 않는다는 점을 지적한다.
MQTT 실험을 위한 장치는 앞서의 웹서버 예제와 동일하다. 사진의 NodeMCU 보드는 배선의 편의성을 위해 Baseboard 상에 설치하였다. 그렇지 않을 경우 보드 하방에 솓아 있는 핀에 암커넥터 핀으로 배선하면 그만이다.
한 가지 주의할 점은 이 블로그에서 제공하는 프로그램은 지난번 게시된
ESP8266WiFi NodeMCU 12E WiFi 모듈사용 ThingSpeak 전압데이터 전송 예제:III
NodeMCU_ThingSpeak_Resistor_01 와 유사한 점이 많으나 개념적으로 MQTT 방식으로 Publish하는 프로그램이라는 점이다.
다른 MQTT 프로그램서 예제들은 대체로 문자열 정보로서 Hello World! 와 같은 문장을 Publish하는 사례가 많으며 한편으로 클라이언트 자신이 아두이노에서 측정한 온도와 습도 또는 전압 값을 흔히 Publish 한다.
이 블로그에서는 클라이언트가 NodeMCU에서 측정한 전압 값을 Publish하도록 한다. Publish된 결과는 Thingspeak의 그래프로 작성해서 볼 수 있다.
아두이노 NodeMCU WiFi 보드에서 MQTT 방식으로 아날로그 데이터를 브로커에 중계헤 주기 위해서는 ESP8266WiFi.h 라이브러리 외에도 반드시 PubSubClient.h 라이브러리를 추가해야 할 필요가 있다. 스케치의 라이브러리 포함하기에서 라이브러리 관리를 클릭하고 창이 뜨면 검색 필터링하기에 PubSubClient를 입력하면 그림과 같이 Install 여부를 물어보게 된다. 예시된 창의 정보는 이미 PubSubClient.h가 인스톨되어 있음을 나타낸다. 탭에서 확인이 가능하다.
그밖에 Thingspeak에 이미 회원 가입이 되어 있다면 write용 API 키 값이 이미 부여되어 있을 것이다. 아울러 Channel Setting에서 적어도 하나의 개인 채널을 설정해 놓았다면 channel id 가 이미 부여되어 있으나 앞서의 예제에서는 필요가 없어 사용치 않았으나 MQTT 예제에서는 필요하다. 앞서 지적했던 것처럼 일단 Thingspeak 브로커에 전압데이터를 보내 그래프로 기록한 후에 Subscribe 대신 일반에게 공개할 경우 즉 Publish 내용을 Thinspeak에 로그인한 회원들에게 공개 즉 개인(Private)별 설정에서 공개(Public) 설정으로 바꿀 경우 이 channel id 값이 반드시 필요하게 된다.
트위터에 공개적으로 올리기 위해 설정된 Channel id를 사용하는 실례이다.
프로그램이 제대로 실행되기 위해서는 4가지 데이터를 정확히 입력해야 한다. 예제 프로그램에 입력된 값은 임의의 값이므로 반드시 본인이 확인하여 정확한 값을 입력하도록 하자.
MY_SSID 와 MY_PWD는 자신의 스마트 폰이나 또는 설치된 공유기의 값을 입력해도 무방하다.
NodeMCU_mqtt_thingspeak_01
#include <ESP8266WiFi.h> //WiFi 기본적인 라이브러리
#include <PubSubClient.h> //MQTT에 필요한 Publish, Subscribe 지원 라이브러리
//<YOUR-CHANNEL ID>
String channelid="195314"; // Channel Setting에 들어가면 id 번호를 볼 수 있음
//<YOUR CHANNEL Write API Key>
String apiwritekey="0FKR99L5Z0DXYFSP";//Thingspeak 회원에게 부여된 Write API 키
const char* MY_SSID = "AndroidHotspot1234"; //본인 스마트 폰 핫스팟 ID
const char* MY_PWD = "00000000"; // 본인 스마트 폰 핫스팟 비밀번호
// Initialize the Wifi client library
WiFiClient client;
// Initialize the PuBSubClient library
PubSubClient mqttClient(client);
// Define the ThingSpeak MQTT broker
const char* server = "mqtt.thingspeak.com"; //전용 mqtt 브로커 서버 사이트
// track the last connection time
unsigned long lastConnectionTime = 0;
// post data every 20 seconds
const unsigned long postingInterval = 20L * 1000L;
void setup() {
// Begin serial transfer
Serial.begin(115200);
Serial.print("Connecting to "+*MY_SSID);
WiFi.begin(MY_SSID, MY_PWD);
while (WiFi.status() != WL_CONNECTED) {
delay(10000);
Serial.print(".");
}
Serial.println("");
Serial.println("Connected");
Serial.println("");
// Set the MQTT broker details
mqttClient.setServer(server, 1883);// 포트 넘버는 다른 브로커들도 1883을 사용함
}//end connect
void loop() {
// Check if MQTT client has connected else reconnect
if (!mqttClient.connected())
{
reconnect();
}
// Call the loop continuously to establish connection to the server
mqttClient.loop();
// If interval time has passed since the last connection, Publish data to ThingSpeak
if (millis() - lastConnectionTime > postingInterval)
{
mqttpublish();
}
}
void reconnect()
{
// Loop until we're reconnected
while (!mqttClient.connected())
{
Serial.print("Attempting MQTT connection...");
// Connect to the MQTT broker
if (mqttClient.connect("ArduinoWiFi101Client"))
{
Serial.println("connected");
} else
{
Serial.print("failed, rc=");
// Print to know why the connection failed
// See http://pubsubclient.knolleary.net/api.html#state
Serial.print(mqttClient.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying to connect again
delay(5000);
}
}
}
void mqttpublish() {
// Read voltage from variable resistor: 0∼1023
float t = analogRead(0);
String data = String(t, DEC);
// Get the data string length
int length = data.length();
char msgBuffer[length];
// Convert data string to character buffer
data.toCharArray(msgBuffer,length+1);
Serial.println(msgBuffer);
// Publish data to ThingSpeak. Replace <YOUR-CHANNEL-ID>
//with your channel ID and <YOUR-CHANNEL-WRITEAPIKEY>
//with your write API key
// 여기서는 channel id와 Write API Key 값을 직접 입력했으나
// character들의 합으로 프로그램 변경도 가능
mqttClient.publish("channels/195314/publish/fields/field1/0FKR99L5Z0DXYFSP",msgBuffer);
// note the last connection time
lastConnectionTime = millis();
}
NodeMCU WiFi 모듈에서 MQTT 프로그램 실행을 시리얼 모니터에서 관찰해 보면 일정한 시간 간격을 가지고 지속적으로 연결을 시도함을 볼 수 있다.
따라서 데이터를 MQTT 방식으로 안전하게 전송하기 위해서는 프로그램 구조를 보다 잘 이해할 필요가 있을 것이다.
MQTT 방식에 의한 전압 측정 결과를 그래프에서 확인해 보면 다소 시간 간격이 불 균일함을 알 수 있다. 이는 프로그램 상에서 MQTT 브로커와 연결을 지속하는 과정에 기인하는 것으로 보인다.
'아두이노프로세싱 프로그래밍' 카테고리의 다른 글
NodeMCU WiFi 웹서버가 생성한 실시간가변저항 전압데이터를 스마트 폰에서 구글차트 그래프 작성 II: (0) | 2017.01.24 |
---|---|
아두이노 NodeMCU WiFi 웹서버 통신 프로그램을 이용 스마트 폰에서 구글차트 응용 그래프 작성:I (0) | 2017.01.23 |
ESP8266WiFi NodeMCU 12E WiFi 모듈사용 ThingSpeak 전압데이터 전송 예제:III (0) | 2017.01.14 |
아두이노 Cactus ESP8266WiFi 보드 Thingspeak 웹서버 예제: I 아날로그 입력 데이터 생성 및 Thingspeak 전송 및 그래프 작성 (0) | 2017.01.13 |
아두이노 NodeMCU ESP8266WiFi 웹서버 예제:아날로그 입력 데이터 생성 및 전송 (0) | 2017.01.12 |