미들웨어는 서로 다른 애플리케이션이 서로 통신하는 데 사용되는 소프트웨어이다다.
MQTT는 ISO 표준 발행-구독 기반의 메시징 프로토콜이다.
스마트 센서, 웨어러블 및 기타 사물 인터넷(IoT) 디바이스는 일반적으로 리소스 제약이 있는 네트워크를 통해 제한된 대역폭으로 데이터를 전송하고 수신해야 한다.
이러한 IoT 디바이스는 MQTT를 데이터 전송에 사용하는데, 구현이 쉽고 IoT 데이터를 효율적으로 전달할 수 있기 때문입니다. MQTT는 디바이스에서 클라우드로, 클라우드에서 디바이스로의 메시징을 지원한다.
확장성
신뢰성
보안
우수한 지원
공간 분리
시간 분리
동기화 분리

MQTT broker는 여러 클라이언트 간의 메시지를 조정하는 백엔드 시스템이다.
MQTT 클라이언트
MQTT 브로커
MQTT 연결
https://github.com/eclipse/paho.mqtt-spy/wiki/Downloads
Step 1: 시스템 업데이트
sudo apt-get update
sudo apt-get upgrade
Step 2: 모스키토 설치
sudo apt-get install mosquitto
sudo apt-get install mosquitto-clients
Step 3: 서버동작 시작
sudo /etc/init.d/mosquitto start
Step 4: 두개의 터미널로 통신 테스트
Terminal 1: Type the following:
mosquitto_sub -d -t /test
Terminal 2: Type the Following:
mosquitto_pub -d -t /test -m "Hello!"
https://www.rabbitmq.com/install-windows.html
와이파이 보안 문제로 개인 MQTT 구축이 어려워 https://www.hivemq.com/public-mqtt-broker/ 에서 hivemq를 통해 MQTT 통신을 구현했다.
hivemq을 통해 쉽게 topic을 만들 수 있다.
💡 메시지를 발행-구독하는 행위는 채널 단위로 일어난다. 이를 MQTT에서는 토픽이라고 부르고, 토픽은 슬래시(/)로 구분되는 계층 구조를 갖는다.
보드와 통신을 하기 전에 python을 통해 임의 값을 publish를 테스트 했다.
publish.py
import paho.mqtt.client as mqtt
import json
def on_connect(client, userdata, flags, rc):
if rc == 0:
print("connected OK")
else:
print("Bad connection Returned code=", rc)
def on_disconnect(client, userdata, flags, rc=0):
print(str(rc))
def on_publish(client, userdata, mid):
print("In on_pub callback mid=", mid)
# 새로운 클라이언트 생성
client = mqtt.Client()
# 콜백 함수 설정
client.on_connect = on_connect # 브로커에 접속
client.on_disconnect = on_disconnect # 브로커에 접속 종료
client.on_publish = on_publish # 메세지 발행``
# address 설정
client.connect('bssmheavn/1', 1883)
client.loop_start()
# common topic 으로 메세지 발행
client.publish('common', json.dumps({"sucess":"hi"}), 1)
client.loop_stop()
# 연결 종료
client.disconnect()
client.publish('common', json.dumps({"sucess":"hi"}), 1)을 json 형식으로 값을 보내게 된다.
client.connect('bssmheavn/1', 1883)을 통해 topic은 bssmheavn/1이 된다.
subscribe.py
import paho.mqtt.client as mqtt
def on_connect(client, userdata, flags, rc):
if rc == 0:
print("connected OK")
else:
print("Bad connection Returned code=", rc)
def on_disconnect(client, userdata, flags, rc=0):
print(str(rc))
def on_subscribe(client, userdata, mid, granted_qos):
print("subscribed: " + str(mid) + " " + str(granted_qos))
def on_message(client, userdata, msg):
print(str(msg.payload.decode("UTF-8")))
# 새로운 클라이언트 생성
client = mqtt.Client()
# 콜백 함수 설정 on_connect(브로커에 접속), on_disconnect(브로커에 접속종료), on_subscribe(topic 구독),
# on_message(발행된 메세지가 들아왔을 때)
client.on_connect = on_connect
client.on_disconnect = on_disconnect
client.on_subscribe = on_subscribe
client.on_message = on_message
# address : broker.hivemq.com, port: 1883에 연결
client.connect('broker.hivemq.com', 1883)
# common topic으로 메세지 발행
client.subscribe('bssmheavn/#', 1)
client.loop_forever()
client.subscribe('bssmheavn/#', 1)에서 #을 이용해 bssmheavn/에 들어오는 값과 topic을 전부 볼 수 있다.
wemos d1 mini

wemos d1 mini를 사용하였고 https://ieatt.tistory.com/47 을 참고하여 환경을 구축했다.
mqttesp.ino
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <sstream>
const char* ssid = "와이파이아디";
const char* password = "와이파이비번";
const char* mqttServer = "broker.hivemq.com";
const int mqttPort = 1883;
// const char* mqttUser = "yourMQTTuser";
// const char* mqttPassword = "yourMQTTpassword";
const char* topic_pub = "bssmheavn/1";
const char* topic_sub = "bssmheavn/#";
#define UPDATE_INTERVAL 5000L
unsigned long prevUpdateTime = 0L;
WiFiClient espClient;
PubSubClient mqttClient(espClient);
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived in topic: ");
Serial.println(topic);
Serial.print("Message: ");
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
}
Serial.println();
Serial.println("-----------------------");
}
void setup() {
Serial.begin(115200);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.println("Connecting to WiFi..");
}
Serial.println("Connected to the WiFi network");
mqttClient.setServer(mqttServer, mqttPort);
mqttClient.setCallback(callback);
while (!mqttClient.connected()) {
Serial.println("Connecting to MQTT...");
if (mqttClient.connect("minse")) {
Serial.println("connected");
} else {
Serial.print("failed with state ");
Serial.print(mqttClient.state());
delay(2000);
}
}
mqttClient.subscribe(topic_sub);
mqttClient.publish(topic_pub, "ESP32 logged in");
prevUpdateTime = millis();
}
void loop() {
//시분할 서브루틴
mqttClient.loop();
unsigned long currentTime = millis();
if(currentTime > prevUpdateTime + UPDATE_INTERVAL) {
int i = 3;
std::stringstream st;
st<<i;
mqttClient.publish(topic_pub, st.str().c_str());
prevUpdateTime = currentTime;
}
}
위 코드는 앞에 내용을 이해했다면 충분히 이해할 수 있다
subscribe.py
import paho.mqtt.client as mqtt
def on_connect(client, userdata, flags, rc):
if rc == 0:
print("connected OK")
else:
print("Bad connection Returned code=", rc)
def on_disconnect(client, userdata, flags, rc=0):
print(str(rc))
def on_subscribe(client, userdata, mid, granted_qos):
print("subscribed: " + str(mid) + " " + str(granted_qos))
def on_message(client, userdata, msg):
print("topic: "+msg.topic+" msg: " +str(msg.payload.decode("UTF-8")))
# 새로운 클라이언트 생성
client = mqtt.Client()
# 콜백 함수 설정 on_connect(브로커에 접속), on_disconnect(브로커에 접속종료), on_subscribe(topic 구독),
# on_message(발행된 메세지가 들아왔을 때)
client.on_connect = on_connect
client.on_disconnect = on_disconnect
client.on_subscribe = on_subscribe
client.on_message = on_message
# address : broker.hivemq.com, port: 1883에 연결
client.connect('broker.hivemq.com', 1883)
# common topic으로 메세지 발행
client.subscribe('bssmheavn/#', 1)
client.loop_forever()
print("topic: "+msg.topic+" msg: " +str(msg.payload.decode("UTF-8")))을 통해 topic을 표시하는 기능을 추가했다.