nodejs 實現MQTT協定的伺服器端和使用者端的雙向互動

2023-11-17 18:01:31

一、專案背景

  公司和第三方合作開發一個感測器專案,想要通過電腦或者手機去控制專案現場的感測器控制情況。現在的最大問題在於,現場的邊緣終端裝置接入的公網方式是無線接入,無法獲取固定IP,所以常規的HTTP協定通訊就沒法做,現在打算使用MQTT來實現雲平臺和邊緣終端(感測器)之間的雙向通訊。

二、術語定義

2.1雲平臺

  主要是針對資料、裝置等的管理。部署在雲端的軟體應用系統,通過與邊緣終端,實現資料獲取或者指令下發。

2.2邊緣終端

  位於網路邊緣的計算機裝置,通過網路與雲平臺連線,向下連線解析儀和各類感測器。

2.3解析儀

  資料接受裝置,通過有線/無線模式,連線邊緣終端或通過有線模式接收不同來源的感測器資料。

2.4感測器

  通過有線/無線模式,連線邊緣終端,傳輸相應的引數或通過有線模式連線解析儀,傳輸相應的引數。

三、網路結構

 四、程式碼實現

4.1 伺服器實現

首先安裝nodejs和aedes,具體的操作和截圖網上有很多現成的。

新建一個「server.js」

const aedes = require('aedes')();
const aedesServer = require('net').createServer(aedes.handle);
const port = 1883;

aedesServer.listen(port, function () {
    console.log('服務啟動並開始監聽埠:', port)
})

//監聽MQTT伺服器埠,當有使用者端連線上時,觸發該回撥
aedes.on("client", (client) => {
    console.log("使用者端連線成功:", client.id);
})

//監聽MQTT伺服器埠,當有使用者端主動斷開連線或者伺服器600s內沒收到某個使用者端的心跳包就會觸發
aedes.on("clientDisconnect", (client) => {
    console.log("使用者端斷開連線:", client.id);
})

//監聽使用者端釋出的主題
aedes.on("publish", function (packet, client) {
    //針對不同的使用者端寫不同的邏輯
    if (client) {
        //根據主題不同寫不同的邏輯,建議採用JSON格式傳輸
        console.log("監聽使用者端發過來的訊息",packet.topic, packet.payload.toString());
    }
})

//伺服器發出的訊息
setInterval(() => {
    aedes.publish({
        topic: "serverMsg",
        payload: "伺服器發訊息",
        qos: 1,
        retain: false,
        dup: false,
        cmd: "publish"
    }, (err) => {
        if (err) {
            console.log("釋出失敗");
        }
    });
}, 20000)

4.2使用者端實現

新建一個「client.js」

使用者端只需要使用「mqtt.connect」方法,就可以跟伺服器端建立長連線。

就目前實際使用的情況看,使用者端偶爾會自動與伺服器斷開,並且自動連上,穩定性方面有待驗證。

var mqtt = require('mqtt');

var client = mqtt.connect('mqtt://192.168.70.220:1883',{
    clientId:'nodejs-mqtt-client'
})

client.on('connect',function (){
    console.log('連線上MQTT伺服器')
    //需要訂閱伺服器主題,不然無法接受訊息
    client.subscribe('serverMsg',{
        qos:1
    })
})

//釋出使用者端訊息 setInterval(()
=>{ client.publish('topic1','hello mqtt client',{ qos:1 }) },20000) client.on('message',function (topic,message){ console.log('接受伺服器訊息:','主題:',topic,'訊息:',message.toString()) })

4.3 效果呈現

通過兩個定時器,實現了雙向通訊。

伺服器端

 使用者端