Node.js 是一個基於 Chrome V8 引擎 的 JavaScript 運行時環境。在 Node.js 出現之前,JavaScript 通常作為客戶端程序設計語言使用,以 JavaScript 寫出的程序常在用戶的瀏覽器上運行。Node.js 的出現使 JavaScript 也能用於服務端編程。
MQTT 是一種基於發布/訂閱模式的輕量級物聯網消息傳輸協議,可以用極少的代碼和帶寬為聯網設備提供實時可靠的消息服務,它廣泛應用於物聯網、移動互聯網、智能硬件、車聯網、電力能源等行業。
本文主要介紹如何在 Node.js 項目中使用 MQTT 實現客戶端與 MQTT 服務器的連接、訂閱、取消訂閱、收發消息等功能。
MQTT 客戶端庫選擇
MQTT.js 是一個 MQTT 協議的客戶端庫,使用 JavaScript 編寫,用於 Node.js 和 瀏覽器環境中。是 JavaScript 生態中目前使用最為廣泛的 MQTT 客戶端庫。
項目初始化
確認 Node.js 版本
本項目使用 Node.js v14.14.0 進行開發和測試,讀者可用如下命令確認 Node.js 的版本
node --version
v14.14.0
使用 npm 安裝 MQTT.js 客戶端庫
# 新建項目
npm init -y
# 安裝依賴
npm install mqtt --save
完成后我們在當前目錄下新建一個 index.js 文件作為項目的入口文件,在該文件中來實現 MQTT 連接測試的完整邏輯。
Node.js MQTT 使用
連接 MQTT 服務器
本文將使用 EMQ X 提供的 免費公共 MQTT 服務器,該服務基於 EMQ X 的 MQTT 物聯網雲平台 創建。服務器接入信息如下:
- Broker: broker.emqx.io(國內可以使用 broker-cn.emqx.io)
- TCP Port: 1883
- SSL/TLS Port: 8883
引入 MQTT.js 客戶端庫
注意:在 Node.js 環境中,導入依賴模塊請使用 commonjs 規范
const mqtt = require('mqtt')
設置 MQTT Broker 的連接參數
設置 MQTT Broker 連接地址,端口以及 topic,這里我們使用 JavaScript 中的生成隨機數的函數來生成客戶端 ID。
const host = 'broker.emqx.io'
const port = '1883'
const clientId = `mqtt_${Math.random().toString(16).slice(3)}`
編寫 MQTT 連接函數
我們使用剛才設置的連接參數來進行連接,連接的 URL 通過上面定義的 host、port 端口來進行拼接。然后調用 mqtt 模塊內置的 connect 函數,連接成功后返回一個 Client 實例。
const connectUrl = `mqtt://${host}:${port}`
const client = mqtt.connect(connectUrl, {
clientId,
clean: true,
connectTimeout: 4000,
username: 'emqx',
password: 'public',
reconnectPeriod: 1000,
})
訂閱主題
使用返回的 Client 實例的 on 方法來監聽連接成功狀態,並在連接成功后的回調函數中訂閱 topic。此時我們連接成功后調用 Client 實例的 subscribe 方法訂閱 /nodejs/mqtt
主題。
const topic = '/nodejs/mqtt'
client.on('connect', () => {
console.log('Connected')
client.subscribe([topic], () => {
console.log(`Subscribe to topic '${topic}'`)
})
})
訂閱主題成功后,我們再使用 on 方法來監聽接收消息的方法,當接受到消息時,我們可以在該方法的回調函數中獲取到 topic 和 message 消息。
注意:回調函數中的 message 是 Buffer 類型,需要使用 toString 方法將其轉化為字符串
client.on('message', (topic, payload) => {
console.log('Received Message:', topic, payload.toString())
})
消息發布
完成上述的訂閱主題和消息監聽后,我們再來編寫一個發布消息的方法。
注意:消息發布需要在 MQTT 連接成功以后,因此這里我們寫到 Connect 成功的回調函數里
client.on('connect', () => {
client.publish(topic, 'nodejs mqtt test', { qos: 0, retain: false }, (error) => {
if (error) {
console.error(error)
}
})
})
完整代碼
服務器連接、主題訂閱、消息發布與接收的代碼。
const mqtt = require('mqtt')
const host = 'broker.emqx.io'
const port = '1883'
const clientId = `mqtt_${Math.random().toString(16).slice(3)}`
const connectUrl = `mqtt://${host}:${port}`
const client = mqtt.connect(connectUrl, {
clientId,
clean: true,
connectTimeout: 4000,
username: 'emqx',
password: 'public',
reconnectPeriod: 1000,
})
const topic = '/nodejs/mqtt'
client.on('connect', () => {
console.log('Connected')
client.subscribe([topic], () => {
console.log(`Subscribe to topic '${topic}'`)
})
client.publish(topic, 'nodejs mqtt test', { qos: 0, retain: false }, (error) => {
if (error) {
console.error(error)
}
})
})
client.on('message', (topic, payload) => {
console.log('Received Message:', topic, payload.toString())
})
項目完整代碼請見:https://github.com/emqx/MQTT-Client-Examples/tree/master/mqtt-client-Node.js
測試
我們在 package.json 文件中的腳本字段中添加一行啟動腳本。
"scripts": {
"start": "node index.js"
}
然后就可以簡單使用 npm start
來運行項目。
npm start
運行后我們可以看到控制的輸出信息如下:
我們看到了客戶端已經成功連接到 MQTT 服務器並且訂閱主題、接收和發布消息成功。此時我們再使用 MQTT 5.0 客戶端工具 - MQTT X 作為另一個客戶端進行消息收發測試。
可以看到控制台內打印出了 MQTT X 發送過來的消息。
至此,我們完成了使用 Node.js 來作為 MQTT 客戶端連接到公共 MQTT 服務器,並實現了測試客戶端與 MQTT 服務器的連接、消息發布和訂閱。
版權聲明: 本文為 EMQ 原創,轉載請注明出處。
原文鏈接:https://www.emqx.com/zh/blog/how-to-use-mqtt-in-nodejs
技術支持:如對本文或 EMQ 相關產品有疑問,可訪問 EMQ 問答社區 https://askemq.com 提問,我們將會及時回復支持。
更多技術干貨,歡迎關注我們公眾號【EMQ 中文社區】。