: Message Queuing Telemetry Transport
๊ฐ์ฅ ๋จผ์ ๋ฐ์ดํฐ ์์ง์ ์ํด MQTT ํต์ ์ด ๋ฌด์์ธ์ง๋ถํฐ ์์๋ณด๋๋ก ํ๊ฒ ๋ค.
์๋ฆฌ
- Publish - Subscribe ๋ชจ๋ธ
- ๋ฉ์ธ์ง ๋ฐ์ ์์ ์์ ์๋ฅผ ๊ตฌ๋ถํจ
- ๋ธ๋ก์ปค ๋ผ๋ ์ 3์ ๊ตฌ์ฑ์์๊ฐ ๋ ์ฌ์ด์ ํต์ ์ฒ๋ฆฌ
- ๋ธ๋ก์ปค์ publisher - subcriber ๋ถ๋ฆฌ
- ๊ณต๊ฐ ๋ถ๋ฆฌ
- ๋ฐ์ ์ / ์์ ์๊ฐ ์๋ก์ IP / ํฌํธ๋ฒํธ / ๋คํธ์ํฌ ์์น ๋ชจ๋ฆ
- ์๊ฐ ๋ถ๋ฆฌ
- ๋์์ ์ผ์๋๊ฑฐ๋ ๋คํธ์ํฌ ํตํด ์ฐ๊ฒฐ๋์ง ์์
- ๋๊ธฐํ ๋ถ๋ฆฌ
- ์๋ก๋ฅผ ์ค๋จ์ํค์ง ์๊ณ ๋ฉ์ธ์ง ์ก์์ ๊ฐ๋ฅ. ๊ตฌ๋ ์๊ฐ ๋ฐ์ดํฐ ์ฌ ๋๊น์ง ๊ธฐ๋ค๋ฆด ํ์ ์๋ค.
- ๊ณต๊ฐ ๋ถ๋ฆฌ
์์ฝํ๋ฉด, ๋ฉ์ธ์ง ๋ฐ์ ์๊ฐ ์ฃผ์ + ๋ฐ์ดํฐ๋ฅผ ๋ธ๋ก์ปค์๊ฒ ๋ณด๋ด๋ฉด, ๋ธ๋ก์ปค๋ ๊ทธ ์ฃผ์ ๋ฅผ ๊ตฌ๋ ํ๊ณ ์๋ ์์ ์๋ฅผ ์ฐพ์์ ๋ฐ์ ๋ฐ์ดํฐ๋ฅผ ์ ์กํด์ค๋ค. SNS ์๋ฆผ์ค์ ์ฒ๋ผ ์ผ๋จ ๋ฐ์ ์๊ฐ ํผ๋ธ๋ฆฌ์ฑ์ ํ๊ณ ๋๋ฉด, ๋ธ๋ก์ปค๊ฐ ๋ฐ์ ์(์ ํํ๋ ๋ฐ์ ์๊ฐ ํฌ์คํ ํ ์ฃผ์ )์ ๊ด์ฌ์ ๋ณด์ด๋ ๊ตฌ๋ ์๋ค์๊ฒ ๋ฐ์ดํฐ๋ฅผ ๋ณด๋ด์ฃผ๋ ํ์์ด๋ค. ๋ฐ์ ์๋ ๊ตฌ๋ ํ ์ชฝ์ ์ ํ์๊ฐ ์๊ณ , ๊ตฌ๋ ์๋ ๋ฐ์ ์๊ฐ ์๋๋ผ ๋ฐ์ ์์ ๋ฐ์ดํฐ์ ๊ด์ฌ์ด ์๊ธฐ ๋๋ฌธ์ ์๋ก ๋ชฐ๋ผ๋ ๋๋ค. ์ค๊ฐ ์ฒ๋ฆฌ๋ ๋ธ๋ก์ปค๊ฐ ๋ค ํด์ค๋ค!
๊ตฌ์ฑ์์
- MQTT ํด๋ผ์ด์ธํธ
- ๋ฉ์ธ์ง๋ฅผ ๋ณด๋ด๊ณ ๋ฐ๋ ๋ชจ๋ ๋๋ฐ์ด์ค. MQTT๋ฅผ ํตํด ํต์ ํ๋ฉด ๋ชจ๋ ํด๋ผ์ด์ธํธ
- MQTT ๋ธ๋ก์ปค
- ํด๋ผ์ด์ธํธ ๊ฐ ๋ฉ์ธ์ง ์กฐ์ ๋ฐฑ์๋ ์์คํ
- ๋ฉ์ธ์ง ์์ ๋ฐ ํํฐ๋ง / ํด๋ผ์ด์ธํธ ์๋ณ / ์ ์ก
- ํด๋ผ์ด์ธํธ ๊ถํ ๋ถ์ฌ ๋ฐ ์ธ์ฆ
- ์ถ๊ฐ ๋ถ์์ ์ํ ํ ์์คํ ์ผ๋ก ๋ฉ์ธ์ง ์ ๋ฌ
- ๋๋ฝ ๋ฉ์ธ์ง / ํด๋ผ์ด์ธํธ ์ธ์ ์ฒ๋ฆฌ
- MQTT ์ฐ๊ฒฐ
- ํด๋ผ์ด์ธํธ - ๋ธ๋ก์ปค์ ํต์ ๋ฐฉ์
- ํด๋ผ์ด์ธํธ = connect ๋ฅผ ๋ณด๋ด ์ฐ๊ฒฐ ์์, ๋ธ๋ก์ปค๋ connack ์ผ๋ก ์๋ตํด ์ฐ๊ฒฐ ํ์ธ
- TCP/IP ๊ธฐ๋ฐ
Mosquitto Broker ์ค์น
๋ฌด๋ฃ MQTT broker์ธ Mosquitto๋ฅผ ์ฌ์ฉํ๋ค.
https://mosquitto.org/download/
[Download
Source mosquitto-2.0.15.tar.gz (GPG signature) Git source code repository (github.com) Older downloads are available at https://mosquitto.org/files/ Binary Installation The binary packages listed be
mosquitto.org](https://mosquitto.org/download/)
์ ๋งํฌ์์ ์ด์์ฒด์ ์ ๋ง๋ ๋ฐฉ๋ฒ์ผ๋ก ์ค์นํด์ค๋ค. ๊ทธ๋ฆฌ๊ณ ํ์ด์ฌ์์๋
pip isntall paho-mqtt
๋ก ํจํค์ง๋ฅผ ์ค์นํด์ค๋ค. ์ ํจํค์ง๊ฐ python์์ mqtt๋ฅผ ๊ฐ๋ฅํ๋๋ก ๊ธฐ๋ฅ์ ์ ๊ณตํ๊ณ ์๋ค. ์ธ๋ถ์ ์์ ํ๊ณ ์ถ์ผ๋ฉด ๋ฐ๋ก ์ค์ ์ ๋ํด์ค์ผํ์ง๋ง, ์ฐ์ ์ง๊ธ์ ๋ก์ปฌ์์ ํ ์คํธ ํ ๊ฒ์ด๋ผ์ ์๋ตํ๋ค. ๊ถ๊ธํ์๋ค๋ฉด ์๊ธฐ https://iotmaker.kr/2021/08/23/mosquitto-remote-access-for-windows/
[์๋์ฐ์ฆ์ ์ค์นํ Mosquitto์ ์๊ฒฉ ์ ์ํ์ฉํ๊ธฐ | ์ฐ๊ตฌ๋ฃจ์ IoT ๊ณต๋ฐฉ ์๋์ฐ์ฆ์ ์ค์นํ Mosquitto
ESP32์ PWM์ถ๋ ฅ์ ์ํ ledcSetup,ledcAttachPin,ledcWriteํจ์์ ์ฌ์ฉ๋ฒ์ ์ค๋ช ํฉ๋๋ค.
iotmaker.kr](https://iotmaker.kr/2021/08/23/mosquitto-remote-access-for-windows/)
๊ทธ๋ฆฌ๊ณ mosquitto๊ฐ ์ค์น๋ ๊ณณ์ผ๋ก ์ด๋ํด์ ๋ช ๋ น์ด๋ฅผ ์ ๋ ฅํ๋ค.
C:\Program Files\mosquitto > mosquitto -v
ํ๋ ์ ์ํ ์ ์, ์ ๋ช ๋ น์ด๋ฅผ ์คํํ์ ๋ opening ipv6 listen socket on port 1883 ์ด ์ ๋์ค๊ณ ๋ญ๊ฐ ์๋ฌ๊ฐ ๋๋ค๋ฉด ์ง๊ธ 1883 ํฌํธ๋ฅผ ๋ค๋ฅธ ํ๋ก๊ทธ๋จ์์ ์ฌ์ฉ์ค์ธ ๊ฒ์ด๋ค. ์ด๋๋ ์ง์ 1883 ํฌํธ๋ฅผ ์ฌ์ฉํ๊ณ ์๋ ํ๋ก์ธ์ค๋ฅผ kill ํด์ ํฌํธ๋ฅผ ์ด์ด์ค์ผํ๋ค. mosquitto๋ ๊ธฐ๋ณธ์ ์ผ๋ก 1883๋ฒ ํฌํธ๋ฅผ ์ฌ์ฉํ๋ค.
netstat -ano
์ ๋ช ๋ น์ด๋ฅผ ์ฌ์ฉํด์ ๋ชจ๋ ํฌํธ์ pid๋ฅผ ํ์ธํ๊ณ , 0.0.0.0:1883์ ์ฐ๊ณ ์๋ ๋ ์์ ์์ ๊ด๋ฆฌ์-์ธ๋ถ์ ๋ณด์์ ์ค์งํด์ฃผ๊ณ ๋ค์ ์คํํด๋ณด๋ฉด ๋๋ค.
Python ์์
1. Publisher
import paho.mqtt.client as mqtt
import random
import time
mqttc = mqtt.Client("python_pub")
mqttc.connect("BROKER_IP_ADDRESS", 1883)
for i in range(5):
mqttc.publish("Temperature", "0 " + str(random.uniform(10, 18)))
print("published 0 ", i)
time.sleep(1)
mqttc.publish("Temperature2", "1 " + str(random.uniform(10, 18)))
print("published 1", i)
time.sleep(9)
์ ์์ ๋ ๊ฐ๋จํ๊ฒ 10์์ 18 ์ฌ์ด์ ๋๋คํ ์ค์๊ฐ์ Temperature๊ณผ Temeprature1์ด๋ผ๋ ์ฃผ์ ์ 10์ด์ ํ ๋ฒ, ์ด 5๋ฒ ํผ๋ธ๋ฆฌ์ฑํ๋ ๋ด์ฉ์ด๋ค.
mqttc = mqtt.Client("python_pub")
mqttc.connect("BROKER_IP_ADDRESS", 1883)
BROKER_IP_ADDRESS ์๋ ๋ก์ปฌ ์ปดํจํฐ์ IP ์ฃผ์๋ฅผ ๋ฃ์ด์ฃผ๋ฉด ๋๋ค. mqttc๋ผ๋ ์ด๋ฆ์ผ๋ก ํด๋ผ์ด์ธํธ๋ฅผ ์ ์ธํ๊ณ , connect๋ฅผ ํ์ฉํด ์ฐ๊ฒฐํ๋ค.
mqttc.publish("Temperature", "0 " + str(random.uniform(10, 18)))
publish ํจ์๋ 0๋ฒ ์ธ์๋ก Topic, 1๋ฒ ์ธ์๋ก ๋ฉ์ธ์ง๋ฅผ ์ ์กํ๋ค.
2. Subscriber
import paho.mqtt.client as mqtt
import time
from db import models
from db.base import SessionLocal
def add_data(db: any, sensor_id: int, datetime: str, value: float):
db_data = models.Degree(time=datetime, sensor_id=sensor_id, degree=value)
# database session์ db_data ์ ๋ณด ์ถ๊ฐ
db.add(db_data)
# db์ ๋ฐ์
db.commit()
# ์ต์ db ์ ๋ณด ๋ฐ์์ค๊ธฐ
db.refresh(db_data)
return db_data
# subscriber callback
def on_message(client, userdata, message):
print(message)
converted = str(message.payload.decode("utf-8")).split()
sensor_id = int(converted[0])
value = float(converted[1])
timestamp = time.strftime('%Y-%m-%d %H:%M:%S')
add_data(db=SessionLocal(), sensor_id=sensor_id, datetime=timestamp, value=value)
broker_address = "BROKER_IP_ADDRESS"
client1 = mqtt.Client("client1")
client1.connect(broker_address, 1883)
client1.subscribe("Temperature")
client1.on_message = on_message
client1.loop_forever()
publisher๋ณด๋ค ๊ธด ๊ฒ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ ๋ ฅ ๋๋ฌธ์ด๋ค. ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ด๋ ๋ถ๋ถ์ ์ ์ธํ๊ณ ๋ค์ฌ๋ค๋ณด์.
broker_address = "BROKER_IP_ADDRESS"
client1 = mqtt.Client("client1")
client1.connect(broker_address, 1883)
client1.subscribe("Temperature")
client1.on_message = on_message
client1.loop_forever()
๋๊ฐ์ด ํด๋ผ์ด์ธํธ๋ฅผ ์ ์ธํ๊ณ , ๋ธ๋ก์ปค์ ip ์ฃผ์์ ํฌํธ๋ก ์ฐ๊ฒฐํ๋ค. ๊ทธ๋ฆฌ๊ณ subscribe ํจ์๋ฅผ ํ์ฉํด์ ๊ด์ฌ์๋ Topic์ ๊ตฌ๋ ํ๋ค. ๋ฉ์ธ์ง๋ฅผ ๋ธ๋ก์ปค์๊ฒ์ ์ ๋ฌ๋ฐ์์ ๋์ ํจ์๋ฅผ ์ ์ํด์ฃผ๊ณ , loop_forever()๋ก ๋ฉ์ธ์ง๋ฅผ ๊ธฐ๋ค๋ฆฐ๋ค. ์ด ๋ถ๋ถ์ ๊ธฐ๋ค๋ฆฌ๊ฒ ๋์ง ์๊ณ ์ฃผ๊ธฐ์ ์ผ๋ก ํ์ธํด์ ๋ฐ์์๋ ๊ด์ฐฎ๋ค.
์ฃผ๊ธฐ์ ํ์ธ์ผ๋ก ๋ณ๊ฒฝํ๋ฉด ํด๋ผ์ด์ธํธ์์ ๋ค๋ฅธ ์ผ์ ๋์์ ์ฒ๋ฆฌํ๋ ๊ฒ๋ ๊ฐ๋ฅํ๋ฏ๋ก ๊ฒฝ์ ์ ์ผ๋ก ํ๋ก์ธ์ค๋ฅผ ์ฌ์ฉํ ์ ์๋ค. ์ง๊ธ์ ๊ทธ๋ฅ ์ฐ๋๋ก ํ๊ฒ ๋ค.
def on_message(client, userdata, message):
print(message)
converted = str(message.payload.decode("utf-8")).split()
sensor_id = int(converted[0])
value = float(converted[1])
timestamp = time.strftime('%Y-%m-%d %H:%M:%S')
add_data(db=SessionLocal(), sensor_id=sensor_id, datetime=timestamp, value=value)
message๋ฅผ ๋ธ๋ก์ปค๋ก๋ถํฐ ๋ฐ์ ๋ค์ ์ฒ๋ฆฌ๋ฅผ ํด์ db์ ๋ฐ์ดํฐ๋ฅผ ๋ฃ์ด์ค๋ค. ์ด ๊ฒฝ์ฐ ์จ๋์ผ์๋ผ๊ณ ๊ฐ์ ํ๊ธฐ์ ๋ฌธ์์ด์ ๊ฐ๊ณตํด์ sensor id, degree๋ก ๋๋์ด์ฃผ์๊ณ ํ์ฌ ์๊ฐ์ ํฌํจํด์ ๋ฐ์ดํฐ๋ฅผ db์ ๋ฃ์ด์ฃผ์๋ค.
db ์ ๋ฐ์ดํธ๋ sqlalchemy ๋ฅผ ์ฌ์ฉํ์ผ๋ฏ๋ก, ์ด๋ฒ ํฌ์คํธ์์๋ ์ฐ์ง ์๊ณ ! ๋ค์ ํฌ์คํ ์์ api๋ฅผ ์์ฑํ๋ฉด์ ์จ๋ณด๋๋ก ํ๊ฒ ๋ค.
์คํ์ ์ผ๋ฐ ํ์ด์ฌ ํ์ผ ์คํ๊ณผ ๋๊ฐ์ด ํฐ๋ฏธ๋์ python publisher.py / python subscriber.py ํด์ฃผ๋ฉด ๋๋ค.
์ด ์์ ์์ MQTT broker๋ ๋ฐ์ดํฐ ์ ๋ฌ์ ๋ณด์ฅํด์ฃผ์ง ์๋๋ค. ๊ทธ๋ฌ๋ฏ๋ก publisher๊ฐ ๋จผ์ ๋์ํด์ ๋ฐ์ดํฐ๋ฅผ ๋ณด๋ด๊ณ , subscriber๊ฐ ๋์ค์ ๋์ํ๊ฒ ๋๋ฉด publisher๊ฐ ์์ ๋ณด๋ธ ๋ฐ์ดํฐ๋ ๋ ์๊ฐ๊ฒ ๋๋ค. ์ด๊ฒ์ broker ์ธํ ์ ๋ณ๊ฒฝํด์ ํด๊ฒฐํ ์ ์๋ค. ์ด๋ฅผ QoS๋ผ๊ณ ํ๋ค. 0์ ๋ณด๋ด๊ณ ์์ด๋ฒ๋ฆฌ๋ ๊ฒ, 1์ ๋ฐ์๋์ง ๋ชจ๋ฅด๊ฒ ์ผ๋ฉด ์ ํด์ง๋งํผ ์ถ๊ฐ๋ก ์ ์ก, 2๋ ๋ฐ์๋ค๋ ๊ฒ์ด ํ์คํ๋๋ก ๋ณด์ฅํ๋ ๋ฐฉ์์ด๋ค.
๋ค๋ง 2๋ก ๊ฐ์๋ก ์ฑ๋ฅ์ด ๋จ์ด์ง๊ณ 0์ผ๋ก ๊ฐ์๋ก ๋ฐ์ดํฐ ์์ค์ด ๋ฐ์ํ๊ธฐ ๋๋ฌธ์ ์ฃผ๋ก 0~1๋ก ์ฌ์ฉํ๊ณ ์์ ์ดํ๋ฆฌ์ผ์ด์ ์์ ๋ฐ์ดํฐ ์์ค์ ์ปค๋ฒํ๋ ๋ฐฉ๋ฒ์ด ์ผ๋ฐ์ ์ด๋ค.