uniapp 连接mqtt

1:下载插件

npm install mqtt

2:创建 mqtt.js

javascript 复制代码
/* main.js 项目主入口注入实例 */
// import mqttTool from './lib/mqttTool.js'
// Vue.prototype.$mqttTool = mqttTool

/* 使用范例见 /pages/index/index.vue */
// mqtt协议:H5使用ws/wss APP-PLUS使用wx/wxs

var mqtt = require('mqtt/dist/mqtt.js')

let mqttTool = {
	client: null
}

mqttTool.connect = function(params){
	let options = {
		clientId: params.clientId,
		username: params.username,
		password: params.password,
		clean: params.clean,
		connectTimeout: 600000, 
		cleanSession: false
	}
	let client = mqtt.connect(params.url, options);
	mqttTool.client = client
	return client;
}

mqttTool.end = function(){
	return new Promise((resolve, reject) => {
		if(mqttTool.client == null){
			resolve('未连接')
			console.log('App_text' + ":end 未连接")
			return;
		}
		mqttTool.client.end()
		mqttTool.client = null
		resolve('连接终止')
	})
}

mqttTool.reconnect = function(){
	return new Promise((resolve, reject) => {
		if(mqttTool.client == null){
			resolve('未连接')
			console.log('App_text' + ":reconnect 未连接")
			return;
		}
		mqttTool.client.reconnect()
	})
}

mqttTool.subscribe = function(params){
	return new Promise((resolve, reject) => {
		if(mqttTool.client == null){
			resolve('未连接')
			console.log('App_text' + ":unconnect 未连接")
			return;
		}
		mqttTool.client.subscribe(params.topic, {qos:params.qos}, function(err,res) {
			console.log(err,res)
			if (!err && res.length>0) {
				resolve('订阅成功')
				console.log('App_text' + ":subscribe success 订阅成功")
			}else{
				resolve('订阅失败')
				console.log('App_text' + ":subscribe failed 订阅失败")
				return;
			} 
		})  
	})
}

mqttTool.unsubscribe = function(params){
	return new Promise((resolve, reject) => {
		if(mqttTool.client == null){
			resolve('未连接')
			console.log('App_text' + ":unconnect 未连接")
			return;
		}
		mqttTool.client.unsubscribe(params.topic, function(err) {
			if (!err) {
				resolve('取消订阅成功')
				console.log('App_text' + ":unsubscribe success 取消订阅成功")
			}else{
				resolve('取消订阅失败')
				console.log('App_text' + ":unsubscribe failed 取消订阅失败")
				return;
			} 
		})  
	})
}

mqttTool.publish = function(params){
	return new Promise((resolve, reject) => {
		if(mqttTool.client == null){
			resolve('未连接')
			console.log('App_text' + ":unconnect 未连接")
			return;
		}
		mqttTool.client.publish(params.topic, params.message, function(err){
			if (!err) {
				resolve(params.topic + '-' + params.message + '-发送成功')
				console.log('App_text' + ":publish success 发送成功")
			}else{
				resolve(params.topic + '-' + params.message + '-发送失败')
				console.log('App_text' + ":publish failed 发送失败")
				return;
			} 
		})
	})
}

export default mqttTool

3:创建mqtt.vue 并引入mqtt.js

javascript 复制代码
<template>
	<view class="mqtt">
		<u-navbar title='MQTT调试' autoBack bgColor="#fff" placeholder>
		</u-navbar>
		<view class="options">
		
			<view class="info">
				<view class="bar">
					<text class="label">clientId:</text>
					<input v-model="connectInfo.clientId" class="value" style="width:70%" :adjust-position="false" placeholder=""/>
				</view>
				<view class="flex-between">
					<view class="bar">
						<text class="label">username:</text>
						<input v-model="connectInfo.username" class="value" :adjust-position="false" placeholder=""/>
					</view>
					<view class="bar" style="margin-left:4px;">
						<text class="label">password:</text>
						<input v-model="connectInfo.password" class="value" :adjust-position="false" placeholder=""/>
					</view>
				</view>
				<view class="flex-between">
					<view class="btn" @click="startConnect">连接</view>
					<view class="btn" @click="endConnect">终止</view>
					<view class="btn" @click="reConnect">重新连接</view>
				</view>
				<view class="flex-between">
					<view class="bar" style="width:40%;">
						<text class="label">topic</text>
						<input v-model="subscribeInfo.topic" class="value" :adjust-position="false" placeholder=""/>
					</view>
					<view class="bar" @click="changeQos">
						<text class="label">qos</text>
						<text class="value">{{subscribeInfo.qos}}</text>
					</view>
					<view class="bar" @click="connectInfo.clean = !connectInfo.clean">
						<text class="label">clean</text>
						<text class="value">{{connectInfo.clean}}</text>
					</view>
				</view>
				<view class="flex-row">
					<view class="btn" @click="startSubscribe">订阅</view>
					<view class="btn" style="margin-left:6px;" @click="endSubscribe">取消订阅</view>
				</view>
				<view class="tips">
					<text class="tips-lab">操作日志:</text>
					<text class="tips-reset" @click="clearConfig">清空配置</text>
					<text class="tips-buffer" :style="isBuffer?'':'opacity:0.5'" @click="isBuffer=!isBuffer">打印Buffer</text>
					<text class="tips-clear" @click="cealrLog">清空日志</text>
				</view>
			</view>
		</view>
		<scroll-view class="logs" scroll-y>
			<view class="logs-list" v-for="(item,index) in logs" :key="index">
				{{item.option + item.log}}
			</view>
		</scroll-view>
		<view class="feet" :style="'bottom:' + (isSending?sendInfo.keyboard:0) + 'px;'">
			<view class="inpbar">
				<input v-model="sendInfo.msg" @focus="focusSend(true)" @blur="focusSend(false)" :adjust-position="false" :cursor-spacing="12" class="inp" type="text" placeholder="请输入内容" placeholder-style="color:#cccccc;"/>
				<view v-if="sendInfo.msg==''" class="send send-dark">发送q</view>
				<view v-else @click="publish()" class="send">发送</view>
			</view>
		</view>
	</view>
</template>

<script>
	export default{
		data(){
			return{
				/* 连接信息 */
				connectInfo: {
					clientId: '随机客户id',
					username: '你的用户名',
					password: '用户密码',
					clean: false
				},
				/* 订阅信息 */
				subscribeInfo: {
					topic: '你订阅的topic',
					qos: 1
				},
				/* 日志信息 */
				isBuffer: false,
				logs: [
					{option:'环境配置:', log:'配置成功'},
				],
				/* 发送信息 */
				isSending: false,
				sendInfo: {
					msg: '',
					keyboard: 0
				}
			}
		},
		computed:{
			/* system */
			systemInfo(){
				return uni.getSystemInfoSync()
			},
		},
		onLoad(){
			/* 即时通讯类键盘元素高度处理 */
			uni.onKeyboardHeightChange(res => {
				this.sendInfo.keyboard = res.height
			})
		},
		onUnload(){
			uni.offKeyboardHeightChange();
		},
		methods:{
			/* 连接 */
			 startConnect(){
				var _this = this
				let opts = {
					url: 'wx://你的服务器域名:8083/mqtt',
					clientId: this.connectInfo.clientId,
					username: this.connectInfo.username,
					password: this.connectInfo.password,
					clean: this.connectInfo.clean
				}
				var client =  this.$mqttTool.connect(opts);
				client.on('connect', function(res) {
					_this.logs.unshift({option:'mqtt:', log:'连接成功'})
				})
				client.on('reconnect', function(res) {
					_this.logs.unshift({option:'mqtt:', log:'重新连接'})
				})
				client.on('error', function(res) {
					_this.logs.unshift({option:'mqtt:', log:'连接失败'})
				})
				client.on('close', function(res) {
					_this.logs.unshift({option:'mqtt:', log:'关闭成功'})
				})
				client.on('message', function(topic, message, buffer) {
					if(_this.isBuffer){
						_this.logs.unshift({option:topic+' buffer:', log: JSON.stringify(buffer)})
					}
					_this.logs.unshift({option:topic+' message:', log: message.toString()})
				})
			},
			/* 终止连接 */
			endConnect(){
				var _this = this
				this.$mqttTool.end().then(res =>{
					_this.logs.unshift({option:'终止:', log:res})
				})
			},
			/* 重新连接 */
			reConnect(){
				var _this = this
				this.$mqttTool.reconnect().then(res =>{
					_this.logs.unshift({option:'重连:', log:res})
				})
			},
			/* 更改Qos */
			changeQos(){
				var _this = this
				if(this.subscribeInfo.qos >= 2){
					this.subscribeInfo.qos = 0
					this.logs.unshift({option:'Qos:', log:this.subscribeInfo.qos + ' Qos变更,订阅已取消,请重新发起订阅'})
					this.endSubscribe();
				}else{
					this.subscribeInfo.qos += 1
					this.logs.unshift({option:'Qos:', log:this.subscribeInfo.qos + ' Qos变更,订阅已取消,请重新发起订阅'})
					this.endSubscribe();
				}
			},
			/* 订阅 */
			startSubscribe(){
				if(this.subscribeInfo.topic == ''){
					uni.showToast({
						icon: 'none',
						title: '输入topic'
					})
					return;
				}
				var _this = this
				let opts = {
					topic: this.subscribeInfo.topic,
					qos: this.subscribeInfo.qos,
				}
				this.$mqttTool.subscribe(opts).then(res =>{
					_this.logs.unshift({option:'订阅' + opts.topic + ':', log:res})
				})
			},
			/* 取消订阅 */
			endSubscribe(){
				var _this = this
				let opts = {
					topic: this.subscribeInfo.topic
				}
				this.$mqttTool.unsubscribe(opts).then(res =>{
					_this.logs.unshift({option:'取消订阅:', log:res})
				})
			},
			/* 发送消息 */
			publish(){
				var _this = this
				let opts = {
					topic: this.subscribeInfo.topic,
					message: this.sendInfo.msg,
				}
				this.$mqttTool.publish(opts).then(res =>{
					_this.sendInfo.msg = ''
					_this.logs.unshift({option:'发送:', log:res})
				}).catch(err=>{
					_this.logs.unshift({option:'发送失败:', log:err})
				})
			},
			/* 清空配置 */
			clearConfig(){
				this.endConnect();
				this.connectInfo = {
					clientId: '',
					username: '',
					password: ''
				}
				this.subscribeInfo = {
					topic: '',
					qos: 1,
					sendMsg: ''
				}
				this.isBuffer = false
			},
			/* 清空日志 */
			cealrLog(){
				this.logs = [{option:'环境配置:', log:'配置成功'}]
			},
		
			/* 聚焦 */
			focusSend(val){
				this.isSending = val
			},
		}
	}
</script>

<style lang="less" scoped>
	.flex-row{
		display: flex;
		flex-direction: row;
		align-items: center;
		justify-content: flex-start;
	}
	.flex-between{
		display: flex;
		flex-direction: row;
		align-items: center;
		justify-content: space-between;
	}
	.mqtt{
		width: 100vw;
		height: 100vh;
		background-color: #f8f8f8;
		.options{
			width: 100%;
			height: 316px;
			background-color: #ffffff;
			box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.1);
			font-size: 13px;
			color: #666666;
			.title{
				width: 710upx;
				margin: 0 auto;
				font-size: 15px;
				font-weight: 500;
				color: #333333;
				text-align: center;
				padding-bottom: 8px;
				display: flex;
				flex-direction: row;
				align-items: center;
				justify-content: space-between;
				.title-btn{
					font-size: 14px;
					font-weight: 400;
					color: #3F536E;
				}
			}
			.info{
				width: 710upx;
				margin: 0 auto;
				.bar{
					min-width: 160upx;
					margin-bottom: 8px;
					height: 30px;
					border-radius: 8px;
					box-shadow: inset 0px 0px 6px rgba(0, 0, 0, 0.1);
					border: 1px solid #cccccc;
					display: flex;
					flex-direction: row;
					align-items: center;
					justify-content: flex-start;
					font-size: 14px;
					.label{
						height: 30px;
						background-color: #f8f8f8;
						padding: 0px 10px;
						line-height: 30px;
						border-right: 1px solid #eeeeee;
						border-radius: 15px 0px 0px 15px;
					}
					.value{
						height: 30px;
						padding: 0px 12px;
						line-height: 30px;
						font-size: 14px;
						color: #3F536E;
					}
				}
				.btn{
					width: 30%;
					height: 32px;
					background-color: #3F536E;
					color: #ffffff;
					border-radius: 8px;
					margin-bottom: 8px;
					text-align: center;
					line-height: 32px;
				}
				.tips{
					width: 100%;
					height: 30px;
					margin-top: 6px;
					display: flex;
					flex-direction: row;
					align-items: center;
					position: relative;
					.tips-lab{
						font-size: 14px;
						color: #333333;
					}
					.tips-reset{
						font-size: 14px;
						font-weight: 500;
						color: #3F536E;
						position: absolute;
						right: 150px;
					}
					.tips-buffer{
						font-size: 14px;
						font-weight: 500;
						color: #3F536E;
						position: absolute;
						right: 70px;
					}
					.tips-clear{
						font-size: 14px;
						font-weight: 500;
						color: #3F536E;
						position: absolute;
						right: 0px;
					}
				}
			}
		}
		.logs{
			width: 100%;
			height: calc(100% - 396px);
			.logs-list{
				padding: 14upx 20upx;
				border-bottom: 1px solid #eeeeee;
				font-size: 13px;
				color: #3e3d3e;
				word-break: break-all;
			}
		}
		.feet{
			width: 100%;
			height: 80px;
			background-color: #ffffff;
			position: absolute;
			bottom: 0px;
			transition: all 0.35s;
			-webkit-transition: all 0.35s;
			&::before{
				position: absolute;
				content: '';
				top: 0px;
				background: rgba(0,0,0,0.2);
				width: 100%;
				height: 1px;
				transform: scaleY(0.5);
				transform-origin: 0 0;
				-webkit-transform: scaleY(0.5);
				-webkit-transform-origin: 0 0;
			}
			.inpbar{
				width: 710upx;
				height: 44px;
				background-color: #eeeeee;
				border-radius: 10px;
				position: absolute;
				left: 20upx;
				top: 10px;
				display: flex;
				flex-direction: row;
				align-items: center;
				justify-content: space-between;
				.img{
					width: 30px;
					height: 30px;
					margin-left: 12px;
				}
				.inp{
					width: calc(100% - 138px);
					height: 40px;
					margin: 0px 12px;
					font-size: 14px;
					color: #000000;
				}
				.send-dark{
					opacity: 0.7;
				}
				.send{
					width: 60px;
					height: 32px;
					background-color: #3F536E;
					border-radius: 6px;
					font-size: 14px;
					color: #ffffff;
					display: flex;
					align-items: center;
					justify-content: center;
					margin-right: 12px;
				}
			}
		}
	}
</style>
相关推荐
快乐的二进制鸭4 小时前
uniapp实现app的pdf预览
pdf·uni-app
qq_316837755 小时前
uniapp 打包安卓 集成高德地图
uni-app
阿福的工作室5 小时前
uniapp录制语音
uni-app
貂蝉空大8 小时前
uni-app开发app时 使用uni.chooseLocation遇到的问题
uni-app
林同学++8 小时前
uniapp多端适配
uni-app
kidding7238 小时前
uniapp引入uview组件库(可以引用多个组件)
前端·前端框架·uni-app·uview
qq_316837758 小时前
uniapp 安卓10+ 选择并上传文件
uni-app
合法的咸鱼8 小时前
uniapp 使用unplugin-auto-import 后, vue文件报红问题
前端·vue.js·uni-app
阳%12 小时前
uni-app小程序开发 基础知识2
前端·uni-app
花伤情犹在17 小时前
uView UI 在 UniApp 中的集成与配置
uni-app·view design