本文整理微信小程序整合MQTT開發所需要步驟和注意事項.
在本文的第一版時已經使用多終端測試過功能是OK的,沒想到上線時卻發現Android端不可用有點摸不着頭腦……多想無益只能繼續探索……好在微信社區論壇找到了一些相同的案例,借用各位的思路重新調整了一下文章。本文並沒有把原文刪除,而是在最后追加一章,為了記錄歷史過程。
參考:
https://blog.csdn.net/weixin_42306858/article/details/95307967
下載以下組件
MQTT Broker
杭州一家公司開發的EMQX,部署非常簡單,功能強大。目前評估了免費版本功能還夠用。
https://www.emqx.io/cn/downloads
JS客戶端庫
一個非常強大的千星+的MQTT js客戶端,
Github: https://github.com/mqttjs/MQTT.js
很貼心還提供了CDN:
https://unpkg.com/mqtt@3.0.0/dist/mqtt.min.js
https://unpkg.com/mqtt@3.0.0/dist/mqtt.js
Nginx
web服務器,本文用於反向代理。
http://nginx.org/en/download.html
微信小程序開發環境
微信開發工具設置
下載個VS Code吧...微信開發工具體驗實在是抱歉。微信開發工具只作為調試工具使用。
https://code.visualstudio.com/Download
使用Linux的朋友推薦wxdt,體驗非常不錯,記得裝wine,不然是沒法調試的。
https://github.com/cytle/wechat_web_devtools
開發環境把"不要驗證域名..."勾上,繞開雲服務器,域名,證書這些部署才需要的東西。
引入MQTT.js
從上面的CDN下載拷貝里面的代碼一個到小程序項目下/utils/mqtt.js
MQTT小樣
- 依賴
var mqtt = require('../../utils/mqtt.js'); //一個全局變量... var client = null;
- 創建連接
注意:實測以下配置僅在模擬器中或IOS真機中有效,對於Android真機並不起作用。
重點注意一下options里面的那個port,估計若是沒人告訴你得撲騰一會。mqtt.js默認會通過443端口建立Web Socket連接,如果你像我一樣用的是EMQX那么你需要指定端口。
協議用wx(ws)就好了,畢竟實在開發機調試用的先別搞那么復雜的。
connectMqtt: function() { const options = { connectTimeout: 4000, // 超時時間 clientId: 'wx_' + parseInt(Math.random() * 100 + 800, 10), port: 8083, //重點注意這個,坑了我很久 // username: 'xxx', // password: 'xxx', } client = mqtt.connect('wx://{你的IP地址}/mqtt', options) client.on('reconnect', (error) => { console.log('正在重連:', error) }) client.on('error', (error) => { console.log('連接失敗:', error) }) let that = this; client.on('connect', (e) => { console.log('成功連接服務器')
//訂閱一個主題 client.subscribe('message.queue', { qos: 0 }, function(err) { if (!err) { console.log("訂閱成功") } }) }) client.on('message', function (topic, message) { console.log('received msg:' + message.toString()); }) },
如果上一步你可以連接上,那么恭喜你雙向發送消息啦~
client.publish('message.queue', 'Hello MQTT')
微信部署
微信小程序上線比較嚴格,你的域名需要通過實名認證,還需要備案.所有的連接需要ssl加密,而且必須是認證的ca頒發的證書,如果用的是自己生成的會拒絕訪問。
所以你需要走完這個流程: 開通雲服務器->買域名->備案->買證書(阿里雲有個人免費的symantec,有效期一年)->部署
MQTT Broker要開通加密Web Socket
到這里假設上面提到的你都辦好了,下載證書。有很多個針對不同類型服務的證書,這里只需要下載apache那個就好了。
下載好解壓出來你會得到兩個文件,***.key和***_public.crt
- 設置wss
listener.wss.external.keyfile = etc/certs/{你的域名}.key
listener.wss.external.certfile = etc/certs/{你的域名}_public.crt
- 順便把tcp的ssl也設置了
listener.ssl.external.keyfile = etc/certs/{你的域名}.key
listener.ssl.external.certfile = etc/certs/{你的域名}_public.crt
- 重啟服務,你可以通過EMQX的工具測試連接
如果配置無誤那么點擊connect按鈕會顯示已連接。
修改一下連接MQTT的代碼
注意:實測以下配置僅在模擬器中或IOS真機中有效,對於Android真機並不起作用。
EMQX默認wss端口為8084,把之前的8083改為8084。
把IP地址換成域名,必須備案。
上線需要使用wss協議,所以這里把服務器協議改為wxs(wss,wxs的MQTT.js定的別問我)。
connectMqtt: function() { const options = { connectTimeout: 4000, // 超時時間 clientId: 'wx_' + parseInt(Math.random() * 100 + 800, 10), port: 8084, //重點注意這個,坑了我很久 // username: 'xxx', // password: 'xxx', } client = mqtt.connect('wxs://{你的域名}/mqtt', options) client.on('reconnect', (error) => { console.log('正在重連:', error) }) client.on('error', (error) => { console.log('連接失敗:', error) }) let that = this; client.on('connect', (e) => { console.log('成功連接服務器')
//訂閱一個主題 client.subscribe('message.queue', { qos: 0 }, function(err) { if (!err) { console.log("訂閱成功") } }) }) client.on('message', function (topic, message) { console.log('received msg:' + message.toString()); }) },
解決 Android真機無法連接MQTT Broker問題
下載一個Nginx版本的證書,給Nginx加一個新的Server,監聽端口443並代理轉發EMQX的8083端口。
需要你根據實際情況修改的地方:
- 設置域名
- 設置證書
server {
server_name www.{your domain}.cn;
listen 443 ssl;
ssl_certificate {path to cert}.pem;
ssl_certificate_key {path to cert key}.key;
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
ssl_prefer_server_ciphers on;
location /mqtt {
proxy_pass http://localhost:8083;
proxy_redirect off;
proxy_set_header Host localhost:8083;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
配套JS代碼:
connectMqtt: function() {
const options = {
connectTimeout: 4000, // 超時時間
clientId: 'wx_' + parseInt(Math.random() * 100 + 800, 10),
// username: 'xxx',
// password: 'xxx',
}
client = mqtt.connect('wxs://{你的域名}/mqtt', options)
client.on('reconnect', (error) => {
console.log('正在重連:', error)
})
client.on('error', (error) => {
console.log('連接失敗:', error)
})
let that = this;
client.on('connect', (e) => {
console.log('成功連接服務器')
//訂閱一個主題
client.subscribe('message.queue', {
qos: 0
}, function(err) {
if (!err) {
console.log("訂閱成功")
}
})
})
client.on('message', function (topic, message) {
console.log('received msg:' + message.toString());
})
},
OK,