赞
踩
uniapp项目中,需使用mqtt实现Andriod设备对接采集平台,记录过程中遇到的问题,便于后期查阅
npm install mqtt@3.0.0 (查阅多篇资料,前辈们说3.0.0版本最稳定,这里就直接用3.0.0了)。
1)将mqtt相关数据和接口函数封装在mqtt.js中。
import mqtt from 'mqtt/dist/mqtt.js' //引入mqtt依赖 var client let mqttConnected = false //mqtt连接状态,这个可以不要,直接查询client.connected即可 const publishTopic = '/test/123/456/set' //发布Topic const MQTT_IP = '192.168.9.128:8083/mqtt' //mqtt地址端口 const MQTT_OPTIONS = { connectTimeout: 5000, //连接超时时间 clientId: 'SiD0FMMAxrs', //clientId不能重复,这里可以随机生成 username: 'test', //用户名 password: 'test', //密码 clean: false } //创建客户端连接 export function mqttConnect() { // #ifdef H5 client = mqtt.connect('ws://' + MQTT_IP, MQTT_OPTIONS,function(err){ console.log(err) }) // #endif // #ifdef MP-WEIXIN||APP-PLUS client = mqtt.connect('wx://' + MQTT_IP, MQTT_OPTIONS,function(err){ console.log(err) }) // #endif client.on('connect', function() { console.log('连接成功') mqttConnected = true }).on('reconnect', function(error) { console.log('正在重连...', error) mqttConnected = false }).on('error', function(error) { console.log('连接失败...', error) mqttConnected = false }).on('end', function() { console.log('连接断开') mqttConnected = false }).on('close',function(){ console.log('连接关闭') mqttConnected = false }).on('offline',function(){ console.log('客户端下线') }) } //发布消息 export function mqttPublish(msg){ if(mqttConnected){ client.publish(publishTopic,msg,{qos:1,retain:false});//hello mqtt + console.log('发布了一条消息',msg) }else{ uni.showToast({ title: 'MQTT服务器未连接', icon: 'none' }); } } //断开连接 export function mqttDisconnect(){ console.log('mqttConnected',mqttConnected) console.log('client',client) if(mqttConnected){ client.end(true) mqttConnected = false } }
2)vue页面引用函数
项目中可能多个页面用到mqtt,尽量不要每个页面都创建client,否则会给服务器造成不必要的负担,根据项目逻辑,我需要在APP启动时创建客户端连接,在APP退出时断开连接。这里我将在APP生命周期onShow中调用mqttConnect函数,在onHide中调用mqttDisconnect函数,注意:应用生命周期一定是在App.vue中。
<script> import { mqttConnect, mqttDisconnect } from '@/api/mqtt.js' export default { onLaunch: function() { console.log('App Launch') }, onShow: function() { mqttConnect() console.log('App Show') }, onHide: function() { mqttDisconnect() console.log('App Hide') } } </script> <style lang="scss"> /*每个页面公共css */ @import '@/uni_modules/uni-scss/index.scss'; /* #ifndef APP-NVUE */ @import '@/static/customicons.css'; // 设置整个项目的背景色 page { background-color: #f5f5f5; } /* #endif */ .example-info { font-size: 14px; color: #333; padding: 10px; } </style>
3)如上整个APP运行过程中始终与MQTT服务器保持长连接,只需在需要发布消息的页面引用mqttPublish(msg)函数即可
<template> <view class="container"> <button @click="publishMessage">发布消息</button> </view> </template> <script> import { mqttPublish } from '@/api/mqtt.js' export default { data() { return { message:'' } }, methods: { publishMessage(){ this.message = 'hello world!' mqttPublish(this.message) } } } </script> <style> .container { padding: 20px; font-size: 14px; line-height: 24px; } </style>
1)mqtt依赖版本为3.0版,HBuilderX版本3.7.3以上,这条参考了其他博主的文章(如下),其他版本未实际测试
https://ask.dcloud.net.cn/article/id-38673__page-2
https://www.cnblogs.com/merryan-share/p/13578797.html
https://www.codetd.com/article/15357429
https://blog.csdn.net/lfqp_/article/details/131134830
2)所连接的mqtt地址需为ws开头,mqtt开头的一直重连
3)client.end()在H5端生效,但APP端不生效,关闭时未接收到“连接断开”的消息
这个问题可以在网上未找到答案,问题定位到./node_modules/mqtt/dist/mqtt.js文件,其MqttClient.prototype.end中有个finish函数,其中调用的that._cleanUp(force, setImmediate.bind(null, closeStores), opts)直接改成that._cleanUp(force, setImmediate.bind(null, closeStores)(), opts)即可解决,猜测原因为.bind方法返回的是一个函数,后面要加括号才能执行,详细可参考https://www.runoob.com/w3cnote/js-call-apply-bind.html
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。