미들웨어는 서로 다른 애플리케이션이 서로 통신하는 데 사용되는 소프트웨어이다다.
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을 표시하는 기능을 추가했다.