๐ŸŽผ Project/๐ŸงŠ Monitoring System

[Monitoring System] 2. MQTT ํ†ต์‹ 

darly213 2023. 4. 6. 16:21
728x90

: Message Queuing Telemetry Transport

๊ฐ€์žฅ ๋จผ์ € ๋ฐ์ดํ„ฐ ์ˆ˜์ง‘์„ ์œ„ํ•ด MQTT ํ†ต์‹ ์ด ๋ฌด์—‡์ธ์ง€๋ถ€ํ„ฐ ์•Œ์•„๋ณด๋„๋ก ํ•˜๊ฒ ๋‹ค.

์›๋ฆฌ

  • Publish - Subscribe ๋ชจ๋ธ
    • ๋ฉ”์„ธ์ง€ ๋ฐœ์‹ ์ž์™€ ์ˆ˜์‹ ์ž๋ฅผ ๊ตฌ๋ถ„ํ•จ
    • ๋ธŒ๋กœ์ปค ๋ผ๋Š” ์ œ 3์˜ ๊ตฌ์„ฑ์š”์†Œ๊ฐ€ ๋‘˜ ์‚ฌ์ด์˜ ํ†ต์‹  ์ฒ˜๋ฆฌ
  • ๋ธŒ๋กœ์ปค์˜ publisher - subcriber ๋ถ„๋ฆฌ
    • ๊ณต๊ฐ„ ๋ถ„๋ฆฌ
      • ๋ฐœ์‹ ์ž / ์ˆ˜์‹ ์ž๊ฐ€ ์„œ๋กœ์˜ IP / ํฌํŠธ๋ฒˆํ˜ธ / ๋„คํŠธ์›Œํฌ ์œ„์น˜ ๋ชจ๋ฆ„
    • ์‹œ๊ฐ„ ๋ถ„๋ฆฌ
      • ๋™์‹œ์— ์ผ์ƒ๋˜๊ฑฐ๋‚˜ ๋„คํŠธ์›Œํฌ ํ†ตํ•ด ์—ฐ๊ฒฐ๋˜์ง€ ์•Š์Œ
    • ๋™๊ธฐํ™” ๋ถ„๋ฆฌ
      • ์„œ๋กœ๋ฅผ ์ค‘๋‹จ์‹œํ‚ค์ง€ ์•Š๊ณ  ๋ฉ”์„ธ์ง€ ์†ก์ˆ˜์‹  ๊ฐ€๋Šฅ. ๊ตฌ๋…์ž๊ฐ€ ๋ฐ์ดํ„ฐ ์˜ฌ ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆด ํ•„์š” ์—†๋‹ค.

์ถœ์ฒ˜ : Spiceworks

์š”์•ฝํ•˜๋ฉด, ๋ฉ”์„ธ์ง€ ๋ฐœ์‹ ์ž๊ฐ€ ์ฃผ์ œ + ๋ฐ์ดํ„ฐ๋ฅผ ๋ธŒ๋กœ์ปค์—๊ฒŒ ๋ณด๋‚ด๋ฉด, ๋ธŒ๋กœ์ปค๋Š” ๊ทธ ์ฃผ์ œ๋ฅผ ๊ตฌ๋…ํ•˜๊ณ  ์žˆ๋Š” ์ˆ˜์‹ ์ž๋ฅผ ์ฐพ์•„์„œ ๋ฐ›์€ ๋ฐ์ดํ„ฐ๋ฅผ ์ „์†กํ•ด์ค€๋‹ค. 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๋กœ ์‚ฌ์šฉํ•˜๊ณ  ์ƒ์œ„ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ๋ฐ์ดํ„ฐ ์†์‹ค์„ ์ปค๋ฒ„ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์ผ๋ฐ˜์ ์ด๋‹ค. 

728x90