MQTT프로토콜을 nodejs를 이용해서 사용해보자 (mosquitto) mac os

MQTT란?

IOT에서 사용하는 프로토콜 중 하나로 구독자와 배포자, 브로커로 이루어져 있습니다. 배포자와 구독자는 client이며, client는 배포자가 될수도 있고, 구독자가 될 수도 있습니다. 배포자는 특정 topic을 통해 브로커에게 데이터를 전송해 데이터를 배포할 수 있고, 구독자는 브로커에게 특정 topic을 구독함으로써 데이터를 받을 수 있습니다. 브로커는 이런 topic을 중앙에서 관리하고, 구독/발행을 총괄합니다. MQTT에도 여러 가지 모델이 있지만, 자세하게 설명하면 복잡하므로 생략. 맥에서 구현을 해봅시다. 아래 사진같은 모양으로 구현 할 것입니다.

 

 

mosquitto 설치

mosquitto는 mqtt브로커 서버입니다. 맥의 경우 brew를 이용해 설치 할 수 있습니다.

brew install mosquitto

mosquitto를 설치 하였으니 제대로 실행이 되는지 테스트를 해봅시다.

 

mosquitto를 실행시켜줍니다.

brew service start mosquitto

 

mosquitto가 실행이 됬으면 구독자를 실행시켜 줍니다. 구독자가 브로커의 포트번호인 1883포트에 연결하고 tmp라는 topic을 구독하겠다는 뜻입니다.

 mosquitto_sub -t tmp -p 1883

위 명령을 실행했으면 cmd 창이 이런식으로 됬을겁니다.

새로운 cmd 창을 키고 아래 명령어를 입력해줍니다. 아래 명령어는 tmp라는 topic을 발행하며 {"tmp":20}이라는 데이터를 배포합니다.

mosquitto_pub -t tmp -m "{\"tmp\": 20}"

정상적으로 실행이 되었다면 구독자가 {"tmp":20} 이라는 데이터를 받은것을 볼 수 있을겁니다.

추가로 데이터를 몇개 더 보낸 결과. 중간에 이상한 기호는 신경쓰지 마세요. 잘못 누른거입니다.

 

mongo db 설치

db는 mongodb를 설치할겁입니다. 또한 mongo db compass도 이용할것입니다. mongodb 역시 brew를 이용해줍시다.

brew install mongodb-community

 mongodb를 설치 한 후 실행시켜줍시다.

brew services start mongodb-community

mongodb compass를 설치하면 이런 시작화면이 보입니다. Connect를 클릭하여 mongodb와 연결시켜줍시다. 만약 오류가 뜬다면 mongodb가 실행중인지 확인해보세요.

Resources라는 db를 생성해주고 Temperature라는 콜렉션을 생성해줍니다.

생성하면 이런식으로 db가 만들어집니다. 저는 먼저 해둔것 때문에 데이터가 들어있습니다.

 

nodejs로 mqtt 브로커 서버 연결

var mqtt = require('mqtt');
var mqtt_client = mqtt.connect("mqtt://127.0.0.1:1883");
console.log("test");
mqtt_client.on("connect",function(){
  mqtt_client.subscribe("tmp");
  console.log("Subscrbinf tmp");
});

mqtt_client.on("message", function(topic,message){
  console.log(topic+":"+message.toString());
  var obj = JSON.parse(message);
  obj.creat_at = new Date();
  console.log(obj);

  var coursor = db_obj.db("Resources").collection("Temperature");
  coursor.insertOne(obj, function(err, result){
    if(err)
      console.log(err);
    else
      console.log(JSON.stringify(result));
  });
});

mongodb 연결

var mongoDB = require("mongodb").MongoClient;
var url = "mongodb://localhost:27017";
var db_obj = null;
mongoDB.connect(url, function(err, db){
  db_obj = db;
  console.log("MongoDB Connect")
});

소켓을 이용해 html페이지와 연동

//Socket Commnucation with HTML pages
var io = require("socket.io")(server);
io.on("connection",function(socket){
  socket.on("evt_temp_c2s", function(data){
    var coursor = db_obj.db("Resources").collection("Temperature");
    const options = {
      sort : {"_id": -1},
      projection : {_id: 0, tmp : 1, creat_at : 1},
    };

  var data = coursor.find({},options).limit(1)
  data.toArray(function(err, results){
    if(!err){
      socket.emit("evt_temp_s2c", JSON.stringify(results[0]));
    }
  });
  });
});

html 페이지

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>MQTT Monitoring Service</title>
    <script src = "/socket.io/socket.io.js"></script>
    <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
    <script>
        var socket = io.connect();
        var timer = null;
        $(document).ready(function(){
            socket.on("evt_temp_s2c",function(data){
                data = JSON.parse(data);
                $(".mqttlist").html('<li>'+data.tmp+'C'+'<li>');
            });
            if(timer==null){
                timer = window.setInterval("timer1()",1000);
            }
        });
        function timer1(){
            socket.emit("evt_temp_c2s",JSON.stringify({}));
        }
    </script>
</head>
<body>
    MQTT 온도 모니터링
    <div id = "msg">
        <div id = "mqtt_logs">
            <ul class="mqttlist"></ul>
        </div>
    </div>
</body>
</html>

이런식으로 mqtt 배포자가 topic을 발행하면 html에서 업데이트가 됩니다. 그리고 mqtt가 배포한 정보를 바로 html로 전송하는것이 아닌 db에 저장을 한 후 최신순으로 정렬을 한 후에 가장 위에 있는 데이터 하나만 가져와서 표시하는식으로 작동합니다.