MQTT初入門

1.MQTT 入門介紹

MQTT(Message Queuing Telemetry Transport,消息隊列遙測傳輸協議),是一種基於發佈/訂閱(publish/subscribe)模式的"輕量級"通訊協議,該協議構建於TCP/IP協議上,由IBM在1999年發佈。MQTT最大優點在於,可以以極少的代碼和有限的帶寬,爲連接遠程設備提供實時可靠的消息服務。作爲一種低開銷、低帶寬佔用的即時通訊協議,使其在物聯網、小型設備、移動應用等方面有較廣泛的應用。

MQTT只是一個網絡協議,需要一個消息中間件,目前比較有名的有Mosquitto,Apollo,RabbitMQ,Emqx等,本篇使用Mosquitto,使用的是docker eclipse-mosquitto 鏡像

在這裏插入圖片描述

2.安裝MQTT

用Centos7 + docker部署 MQTT服務,使用下載和關注次數較多的 eclipse-mosquitto 鏡像,https://hub.docker.com/_/eclipse-mosquitto

在這裏插入圖片描述

1.創建目錄和文件
mkdir -p /mosquitto/config
mkdir -p /mosquitto/data
mkdir -p /mosquitto/log
touch /mosquitto/config/mosquitto.conf
touch /mosquitto/log/mosquitto.log

2.初始化配置文件
vi /mosquitto/config/mosquitto.conf,內容如下
  persistence true
  persistence_location /mosquitto/data
  log_dest file /mosquitto/log/mosquitto.log

3.目錄授權
chmod -R 755 /mosquitto

4.運行docker鏡像啓動mqtt
docker run -it --name=mosquitto -p 1883:1883 -p 9001:9001 -v /mosquitto/config/mosquitto.conf:/mosquitto/config/mosquitto.conf -v /mosquitto/data -v /mosquitto/log eclipse-mosquitto

5.添加配置
vi /mosquitto/config/mosquitto.conf
 # 關閉匿名模式
 allow_anonymous false
 # 指定密碼文件
 password_file /mosquitto/config/pwfile.conf

6.進入啓動的容器shell命令行:docker exec -it mosquitto sh

7.在容器shell命令行中,利用mosquitto命令設置密碼,才能訪問MQTT
  touch /mosquitto/config/pwfile.conf
  chmod -R 755 /mosquitto/config/pwfile.conf
  # 使用mosquitto_passwd命令創建用戶,第一個lxy是用戶名,第二個lxy是密碼
  mosquitto_passwd -b /mosquitto/config/pwfile.conf test test_123

8.重啓mqtt容器:docker restart mosquitto

9.利用MQTT.fx進行連接,下載地址:http://mqttfx.bceapp.com/
 安裝MQTT.fx後,設置好連接地址,端口(默認1883),訂閱一個主題,再向此主題Publish

10.mosquitto.conf完整內容如下:
  persistence true
  persistence_location /mosquitto/data
  log_dest file /mosquitto/log/mosquitto.log
  allow_anonymous false
  password_file /mosquitto/config/pwfile.conf
  #如果要讓 js 通過websocket連接,則需要設置protocol爲websockets
  #protocol websockets
3.使用MQTT.fx連接

對照上面的第9點,下載mqtt.fx 的windows64位版本,然後安裝,打開軟件,點擊Extras-Edit Connection…
在這裏插入圖片描述
輸入MQTT服務地址,端口,點擊Generate生成一個ClientID,在User Credentials中輸入用戶名和密碼
在這裏插入圖片描述
在Subscribe(訂閱)中輸入一個Topic名稱爲 test,在Publish(發佈)中選中test,輸入內容點擊publish,能在Subscribe的右下角看到發佈的內容
pis:訂閱一個主題,向此主題發佈內容,那麼訂閱者就能收到信息
在這裏插入圖片描述

4.JavaScript使用WebSocket連接 MQTT

想要使用websocket連接mqtt,需要mqtt服務支持websocket協議,
需要在配置文件中添加:protocol websockets
然後重啓docker服務:docker restart mosquitto

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8" />
    <title>websocket連接mqtt</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/paho-mqtt/1.0.1/mqttws31.min.js" type="text/javascript"></script>

    <script>
        var hostname = '192.168.68.134', //'192.168.1.2',
            port = 1883,
            clientId = 'client-test',
            timeout = 10,
            keepAlive = 100,
            cleanSession = false,
            ssl = false,
            userName = 'test',  
            password = 'test_123',  
            topic = '/test';
        client = new Paho.MQTT.Client(hostname, port, clientId);
        //建立客戶端實例  
        var options = {
            invocationContext: {
                host: hostname,
                port: port,
                path: client.path,
                clientId: clientId
            },
            timeout: timeout,
            keepAliveInterval: keepAlive,
            cleanSession: cleanSession,
            useSSL: ssl,
            userName : 'test',  
            password : 'test_123',
            onSuccess: onConnect,
            onFailure: function (e) {
                console.log(e);
                s = "{time:" + new Date().Format("yyyy-MM-dd hh:mm:ss") + ", onFailure()}";
                console.log(s);
            }
        };
        client.connect(options);
        //連接服務器並註冊連接成功處理事件  
        function onConnect() {
            console.log("onConnected");
            s = "{time:" + new Date().Format("yyyy-MM-dd hh:mm:ss") + ", onConnected()}";
            console.log(s);
            client.subscribe(topic);
        }

        client.onConnectionLost = onConnectionLost;

        //註冊連接斷開處理事件  
        client.onMessageArrived = onMessageArrived;

        //註冊消息接收處理事件  
        function onConnectionLost(responseObject) {
            console.log(responseObject);
            s = "{time:" + new Date().Format("yyyy-MM-dd hh:mm:ss") + ", onConnectionLost()}";
            console.log(s);
            if (responseObject.errorCode !== 0) {
                console.log("onConnectionLost:" + responseObject.errorMessage);
                console.log("連接已斷開");
            }
        }

        function onMessageArrived(message) {
            s = "{time:" + new Date().Format("yyyy-MM-dd hh:mm:ss") + ", onMessageArrived()}";
            console.log(s);
            console.log("收到消息:" + message.payloadString);
        }

        function send() {
            var s = document.getElementById("msg").value;
            if (s) {
                s = "{time:" + new Date().Format("yyyy-MM-dd hh:mm:ss") + ", content:" + (s) + ", from: web console}";
                message = new Paho.MQTT.Message(s);
                message.destinationName = topic;
                client.send(message);
                document.getElementById("msg").value = "";
            }
        }

        var count = 0;

        function start() {
            window.tester = window.setInterval(function () {
                if (client.isConnected) {
                    var s = "{time:" + new Date().Format("yyyy-MM-dd hh:mm:ss") + ", content:" + (count++) +
                        ", from: web console}";
                    message = new Paho.MQTT.Message(s);
                    message.destinationName = topic;
                    client.send(message);
                }
            }, 1000);
        }

        function stop() {
            window.clearInterval(window.tester);
        }

        Date.prototype.Format = function (fmt) { //author: meizz 
            var o = {
                "M+": this.getMonth() + 1, //月份 
                "d+": this.getDate(), //日 
                "h+": this.getHours(), //小時 
                "m+": this.getMinutes(), //分 
                "s+": this.getSeconds(), //秒 
                "q+": Math.floor((this.getMonth() + 3) / 3), //季度 
                "S": this.getMilliseconds() //毫秒 
            };
            if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
            for (var k in o)
                if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[
                    k]) : (("00" + o[k]).substr(("" + o[k]).length)));
            return fmt;
        }
    </script>
</head>

<body>
    <input type="text" id="msg" />
    <input type="button" value="Send" onclick="send()" />
    <input type="button" value="Start" onclick="start()" />
    <input type="button" value="Stop" onclick="stop()" />
</body>

</html>

效果如下,首先會提示連接成功,然後輸入 hello world ,點擊 send ,控制檯會監測輸出發送的信息
在這裏插入圖片描述

不過此版本的MQTT有點問題,要只能tcp連接,要麼只能websocket連接,而且測試發現 移動智能設備無法連接上,因此又找了一個開源 MQTT 服務器 EMQ X,請看下一節

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章